02 — Identity Model

The principals BitVault must authenticate, authorize, and isolate: tenants, organizations, teams, users, service accounts, and API keys — plus the anonymous public-link holder. Getting this hierarchy right is the prerequisite for everything in 0306.


1. The hierarchy

flowchart TB
    classDef b fill:#fecaca,stroke:#b91c1c,color:#111827;
    classDef o fill:#fde68a,stroke:#b45309,color:#111827;
    classDef u fill:#bbf7d0,stroke:#15803d,color:#111827;
    classDef c fill:#c7d2fe,stroke:#3730a3,color:#111827;
    T["TENANT — the hard isolation boundary ([05])"]:::b
    T --> O["Organization — top admin/billing entity (often 1:1 with tenant)"]:::o
    O --> Tm["Teams / Groups — membership units"]:::o
    Tm --> U["Users — human principals"]:::u
    Tm --> SA["Service Accounts — machine principals"]:::u
    U --> K1["API key (scoped, hashed)"]:::c
    SA --> K2["API key (scoped, hashed)"]:::c
    SA --> W["workload OIDC (mTLS/JWT)"]:::c
    ext["Anonymous public-link holder — capability bearer ([06])"]:::c
Concept Definition Security role
Tenant one customer’s isolated universe the hard isolation boundary (05); every owned row carries tenant_id
Organization the top administrative/billing entity within a tenant (usually 1:1; a reseller tenant may host several) admin scope; the unit SSO/SCIM bind to
Team / Group a collection of members the subject of ReBAC role grants (04)
User a human member interactive principal; MFA-capable (03)
Service account a non-human member owned by an org/team automation principal; no interactive login
API key a credential, not a principal authenticates a user or service account with a scope
Anonymous holder of a share/presigned token a capability, scoped to one resource (06)

Tenant ≠ Organization (on purpose). The tenant is the security/isolation boundary; the organization is an administrative construct inside it. Keeping them distinct lets us support reseller/holding structures later without weakening the isolation boundary, which always stays at the tenant.


2. Service accounts (machine principals)


3. API keys (credentials)

Design (decision: ADR-0035):

Property Design
Format bv_<env>_<keyid>_<secret> — a public prefix/keyid (for lookup + display) + a high-entropy secret (≥256-bit)
Storage hashed at rest (the keyid indexes the row; the secret is verified by hash + constant-time compare) — never stored or logged in plaintext
Display shown once at creation; unrecoverable afterward
Scope bound to a principal (user/SA) + scoped to actions and resource prefixes (least privilege)
Lifetime optional expiry; rotatable (overlap window) and revocable instantly
Audit creation/use/rotation/revocation logged; last-used tracked for stale-key cleanup

Key risks & defenses: leakage to Git/logs → secret scanning in CI (platform/07) + short scope + rotation; an API key is not a session → it grants only API scope, no MFA-gated or admin-destructive actions without step-up (03). Prefer workload OIDC over long-lived keys wherever the runtime supports it.


4. External / guest principals

Sharing creates limited principals: guest users (external collaborators with a constrained role on specific resources) and anonymous public-link holders (a pure capability, no account). Both are sandboxed to exactly what’s shared — never the tenant (06).


5. Identity lifecycle (Joiner / Mover / Leaver)

flowchart LR
    classDef a fill:#fde68a,stroke:#b45309,color:#111827;
    classDef d fill:#fecaca,stroke:#b91c1c,color:#111827;
    j["Joiner: SCIM provision → roles by group ([03])"]:::a --> m["Mover: group change → roles auto-update"]:::a
    m --> l["Leaver: SCIM deprovision → revoke sessions, keys, grants"]:::d
    l --> orphan["sweep orphaned API keys / service accounts"]:::d

Deprovisioning is the most-skipped, highest-risk step: a leaver’s lingering session, API key, or service-account ownership is a breach waiting to happen. SCIM automates JML; sessions + keys are revoked on deactivation; orphaned service accounts are reassigned or disabled (03 §SSO/SCIM, 11 compliance).


6. Trust relationships (who may act on whom)

This model is the substrate the rest of the review enforces.