ADR-0033: Employee/HR management is a Product on ABOS, dogfooded on Octopodia's own tenant¶
- Status: Proposed
- Date: 2026-07-18
- Deciders: El (Lachlan — pending review)
- Related: ADR-0001 (orchestration-first), ADR-0002 (engines vs products), ADR-0006 (control plane holds the map, not content), ADR-0011 (Console vs Client App)
Draft proposed via Cowork, moved into this repo on 26 Aug 2026.
🚨 NUMBERED TWICE BEFORE THIS ONE, AND BOTH TIMES THE NUMBER WAS GONE BY THE TIME ANYBODY LOOKED AGAIN. Written as 0013 on 18 July while it lived in the Claude project;
ADR-0013-tenant-modes.mdlanded here on 31 July. Renumbered to 0021 on 13 Aug after checking it free across every branch and the whole history;ADR-0021-host-baseline-and-hardening.mdlanded here on 17 Aug. Now 0033.✨ THE LESSON IS NOT 'CHECK HARDER'. A draft outside the repo reserves nothing. Both checks were correct when they were made and both were overtaken, because allocation happens here and the draft was invisible to it. That is why this file is in the repo now rather than being renumbered a third time: committing it IS the reservation.
Context¶
We want a way to manage employees — human staff, HR — as distinct from the client-management work the Internal Portal already does. The open question was whether to build this into ABOS as a single front end that both Octopodia and (optionally) clients log into, or to build a separate internal portal that ABOS feeds.
The framing is a false binary. Octopodia is not "the operator standing outside the platform" for this purpose — for staff/HR we are tenant #0: we consume the capability the same way a client would. Our own decisions already resolve how to build something that both we and clients use: separate the engine/product (built once, shared) from the surface (per-tenant, isolated). ADR-0011 already commits us to Console and Client App being separate services over shared engines; ADR-0006 already forbids putting business content in the control plane; ADR-0001 already forbids becoming a system-of-record where the client already runs a tool.
Decision¶
Employee/HR management is built once as a Product over the shared ABOS engines (Capture / Progress / Bill / Remember), config-driven and multi-tenant from day one (ADR-0002, ADR-0003). It is not a control-plane feature and not a module bolted into the Internal Portal.
Three consequences of that framing are load-bearing:
-
Data lives in a tenant spine, never the control plane. Employee records are business content, so they live in the per-tenant Postgres spine. Octopodia's own HR data lives in Octopodia's tenant stack, exactly as a client's lives in theirs. The control plane holds only the map — that the tenant exists and what config it runs (ADR-0006). "Build it into the control plane" is explicitly rejected.
-
Surfaces stay isolated per tenant (ADR-0011). The capability is one product; the surfaces are many and never shared. Each tenant — Octopodia included — sees only its own spine, through its own Client-App-style surface. The founders' view of our staff may be embedded inside the Internal Portal for convenience, but only as a read/write surface that reaches our own tenant through the same tenant API a Client App uses — never as new HR logic in the Portal, and never via the BOS Console (which edits config across tenants). A single front end that Octopodia and clients both authenticate into is explicitly rejected: it collapses tenant isolation and drags multi-tenant RBAC into the control plane.
-
Orchestrate, don't replace (ADR-0001). SMB clients already run payroll/HRIS tools. The product is workflow over what they already run — onboarding automation, leave/approval flows, staff comms, task assignment — not a new system-of-record. We fall back to owning an HR primitive only where a client genuinely lacks one.
Consequences¶
We build employee/HR once and get both internal use and a sellable product from it, consistent with the recurring "unify internally, separate commercially" pattern (AI Employee, feedback survey, newsletter). Tenant isolation, exit, and data-residency guarantees (ADR-0007/0008/0012) apply to HR data automatically because it is ordinary tenant-spine content.
The main caution: Octopodia is a strong proof but a weak spec. A two-founder company has near-zero real HR need, so building to our own requirements would over- or mis-build the product. Requirements should be pulled from a real client BOR, not from our internal need. Until such a client exists, keep the internal build lean — enough to dogfood the tenant-#0 path, not a full HR suite.
Deciding, per ADR-0001, when a client "genuinely lacks" an HR primitive (and we should own it) versus when we orchestrate their existing tool remains a case-by-case judgement.
Alternatives considered¶
- Single ABOS front end that Octopodia and clients share — rejected: violates Console/Client-App separation (ADR-0011), collapses tenant isolation, and forces multi-tenant RBAC into what is otherwise an internal control surface.
- Employee data/feature in the control plane — rejected: the control plane holds the map, not content (ADR-0006). HR records are tenant content.
- A standalone internal HR portal with no ABOS underneath — rejected: builds the capability twice (once to run ourselves, once to sell) and forfeits the dogfood proof and the commercial product.
- A full HRIS system-of-record sold to clients — rejected: rip-and-replace competition against entrenched payroll/HR tools, against orchestration-first (ADR-0001).