One customer organization per instance. No Core client-organization implementation. Controlled local human and registered-machine auth is implemented in #2–7 (5e455d7). #8 reviewed merged-source local acceptance completed; SSO is future, unimplemented and unverified.
DC-IAM-01 — Identity and access
Direction: one customer organization has its own forward-deployed Core instance. We do not build a multi-customer organization directory, tenant selection, organization onboarding or client membership-management system in Core.
As-built source baseline: 5e455d7 (#2–7 merged). The first slice is controlled local human password login and registered machine client credentials—not SSO-first. Integrated delivery merged as 3f20aec182715f114e3506414b55e62387e6203e. Clean merged-source operator execution passed all four existing-k3d journeys and verified cleanup. Runtime source/build inputs are unchanged from installed 5e455d7; no unnecessary rebuild, rollout or credential change was performed. Maintained acceptance runbook · #8 integration / evidence target.
Ownership and trust flow
Authorizer is a separate service, pinned to docker.io/lakhansamani/authorizer:2.4.4@sha256:d1ce7574a75d409f83ef611d7fab4846da64f3d30595f7d5a2bd0e083a97e28d in deploy/authorizer values. Core uses supported HTTP GraphQL validate_jwt_token and bearer-authenticated profile; no SDK runtime dependency, signing key or mirrored user directory. Published Go SDK v2.2.0 (proto v0.2.0) is used in disposable compatibility fixtures only.
Trust is explicit: exact issuer http://127.0.0.1:18080, separately configured endpoint http://authorizer:8080, and deployment ClientID audience—not an individual machine ClientID. Token metadata cannot choose the endpoint. HS256 access-token preflight is fixed; the provider verifies signatures and current stored sessions. ID and refresh tokens do not authorize Core APIs. Wrong issuer, audience, type, signature or expiry must fail closed.
Every protected request validates the session online. Humans additionally require matching current profile, explicit null revocation state and intersection of current and signed roles; machines additionally require a primary/majority current registry eligibility read. Required provider/storage failure returns 503; invalid credentials 401; authenticated permission/eligibility denial 403. There is no offline success fallback.
Identity records and responsibilities
- Authorizer owns controlled local human accounts, password authentication, current roles, sessions, machine clients and token issuance. Public signup stays disabled. A human admin role is not the provider super-admin credential.
- Core owns RegisteredAgent lifecycle, immutable verified issuer/subject association, permissions and business records. No HumanPrincipal, client-tenancy or membership-directory model is introduced.
- The ordinary authentication adapter receives only deployment ClientID and trusted origins. A separate privileged provisioning adapter uses supported client-management APIs and mounts the existing authorizer-runtime ADMIN_SECRET by reference. The provider has no narrower management credential; this is a broad local trust boundary.
- Business authority remains separate. An administrator, registered agent or machine token does not gain permission to move money or act for another business.
Issue #5 removed RegisteredAgent.authority_organization_id from the model and registration requirement. Legacy persisted authority keys are ignored on reads and unset by registry mutations; no authority or client-organization identifier is invented to register an agent. Financial authority remains separate.
Agent registry
Open the dedicated Agent Registry page →
Agreed product boundary: Core owns the registry for agents that consume Core. Building, hosting or operating those agents is a separate product capability—not part of the registry MVI.
One contract for every agent
An agent we build or operate for a downstream client, such as an orthodontic practice on a payment provider's infrastructure, is a client of Core. An agent the practice brings from elsewhere is also a client of Core. Both follow exactly the same registration, authentication, lifecycle, permission and separate authority checks.
There is no implicit trust, automatic activation or privileged internal route because we wrote the agent, host it, or run it on the same infrastructure. Do not add different registry types or access semantics for “internal” versus “external” without an actual behavioral requirement.
What the registry owns
- The agent's durable registration and stable identity association.
- Registration lifecycle: pending, active, suspended and revoked, with expiry and soft-deletion checks.
- The platform-access configuration and restrictions Core must enforce for that agent.
- A consistent lookup/enforcement contract for every registered agent consuming protected Core operations.
An authorized administrator or provisioner registers the agent and establishes its machine identity. The new agent does not need pre-existing access to create its own registration; registration is not an unauthenticated self-enrollment loophole. It may consume protected operations only after the required registration, authentication and access checks succeed.
Authorizer supplies the selected machine-authentication and credential mechanisms. Core owns the registration and enforces access. No credential or token alone bypasses the registry.
What the registry does not own
- Agent creation, hosting, deployment, scheduling or runtime supervision.
- A managed-agent or bring-your-own-agent deployment platform.
- An agent's reasoning, prompts, tools, task execution or runtime memory.
- Permission to represent a practice, access its business records or perform a financial action merely because the agent is registered.
If we later offer agent custody—building, provisioning, hosting and operating agents for customers—that feature integrates with this same registry as a client. It does not receive a trusted bypass and does not change the external-agent contract.
Core's own service workers are implementation components, not the separately running agents that consume Core. Do not conflate the daemon's internal modules with registered platform clients.
Registration, authentication and authority stay separate
- Registration identifies a known agent and its permitted platform-access state.
- Authentication proves which registered machine identity is calling.
- Core enforces current lifecycle, permission, expiry and applicable source restrictions.
- Separate business authority determines whether the requested action is permitted for the represented business and resource, including limits and approvals where applicable.
Who operates an agent and whom it may act for are different questions. Neither custody nor registration grants authority. Serving downstream practices does not reintroduce a client-organization directory or membership-management feature into Core.
MVI boundary
The registry and common client-access contract are implemented in #4/#6 without depending on an internally hosted agent product. The maintained registry contract defines exact APIs and recovery. Issue #5 removed the former authority_organization_id requirement/model field with legacy-key cleanup; registry membership grants no financial authority.
The current authentication MVI is minimal local human auth and machine client credentials. SSO is future, unimplemented and unverified, not an acceptance requirement. Agent custody/hosting remains outside the registry MVI.
Initial access roles — fixed local mapping
- Human admin, present in both signed token and current profile: core.read, core.admin and agent.manage; not agent.read.
- Human user or readonly, present in both signed token and current profile: core.read only. Unknown roles grant nothing.
- Verified machine service_account with exact agent.read scope: own eligible registration through GET /api/agent/me only; no human diagnostic or administrator permission.
- No mapping grants financial authority. GET /api/runtime is the configured service catalog, not worker health or business records; GET /api/admin/runtime is a restricted safe diagnostic projection.
Installation setup and agent registration
- Use the existing Terraform-owned local k3d installation and controlled account operator. Ordinary password enrollment occurs only during isolated maintenance, with public signup disabled before normal service returns. Bootstrap creates an ordinary user, not an admin; role assignment uses supported admin APIs plus readback and fresh login.
- Only authenticated human admin with agent.manage may register a pending agent. A durable operation identity, owner/input fingerprint and atomic CAS claim precede provider creation; do not treat registration alone as credential provisioning.
- Provision exactly agent.read through the separate adapter; read back subject, individual ClientID, scope and active state, then atomically establish unique immutable issuer/subject binding before activation. No caller can supply/rebind identity.
- The successful administrator provision/replacement response delivers the client secret once. Core never persists it, logs it, returns it from retrieval or rediscloses it on retry. The administrator installs it securely; no durable secret escrow or delivery service is implemented.
- Lost or malformed replies and uncertain completion remain ineligible. Never blindly retry creation. Reconcile the exact original operation after a durable access fence; confirm provider disable before retirement. Zero/multiple matches or unknown disable stay closed; an empty scan is not proof an outstanding create cannot finish.
- Replacement permanently reserves one successor operation, confirms original disable and creates a distinct registration/provider client. Original binding remains retained and cannot be reused; competing successor IDs cannot fork credentials. Lost delivery requires explicit recovery/replacement, not secret retrieval.
- Each machine request enforces active, complete, bound, nonexpired, non-soft-deleted registration plus source policy. Suspension and irreversible retained soft deletion deny Core access but do not themselves confirm provider revocation; explicit revoke does. Source allowlists use transport RemoteAddr, not forwarded headers; k3d/SNAT peers do not prove original external IP.
Customer SSO and AWS — future only
SSO federation, IAM Identity Center/SAML/OIDC, EKS workload identity, MFA and SMTP recovery are future, unimplemented and unverified here. None is an acceptance gate for the local human/machine slice. Upstream capability claims do not establish installed integration, mappings or sign-out behavior. IAM roles, IRSA or EKS Pod Identity do not automatically authorize Core calls. No customer federation or automatic email-based identity linking is introduced.
Resolved local contract and remaining decisions
- DC-IAM-D01 — One customer organization per dedicated instance; no client-organization directory or membership management.
- DC-IAM-D02 — Issue #5 removed authority_organization_id from registration/model; legacy keys are ignored on reads and unset on mutations, never replaced by invented authority.
- DC-IAM-D03 — Authorizer 2.4.4 pinned separate service; supported HTTP APIs in Core, published SDK only in fixtures. Future SSO requires its own qualification.
- DC-IAM-D04 — Local mappings are fixed: admin/user/readonly; machine agent.read. Financial mandates and agent custody are separate.
- DC-IAM-D05 — Access/ID issuance 1800 seconds, human refresh 2592000 seconds; machine access 1800 seconds with no refresh/ID token. Core rejects access exp−iat above 1800 seconds. Zero positive authorization cache; ten-second aggregate authorization deadline shortened by caller cancellation.
- DC-IAM-D06 — Completed mutation means supported success plus current-state readback. Enforce on the next fresh decision, within the ten-second deadline; assert the first response, never poll past an unexpected success. Previously authorized concurrent/in-flight work is not retroactively canceled. No delayed financial executor/queue is implemented.
Acceptance evidence — reviewed local delivery
The maintained authentication acceptance runbook maps executable checks to epic #1 / #8 evidence. Reviewed source tree d3b713d8f1886183ffe4c6b9db24380e781bc723 equals the complete merged tree. The clean merged-source runner and all four child operators returned zero after cleanup; exact revision, installed image, measured bounds and row-by-row U/F/K results are attached to #8. Disposable key/storage faults remain F, not installed key-rotation or restore evidence.
- U: unit/contract checks with controlled responses. F: disposable real Authorizer/MongoDB with actual Core adapters/routes. K: existing k3d installation. Missing-binary skips are not provider acceptance; a printed inner PASS is provisional until verified cleanup and outer operator success.
- Cover controlled creation/password login/wrong-password denial, fixed permissions, missing/tampered/expired/type/issuer/audience rejection, unbound and missing-scope machines, authorized registration and eligible own-registration read. Token lifetime issuance bounds are not an elapsed 30-minute/30-day expiry claim.
- Cover suspension, revocation, registration expiry, source restriction and retained soft deletion; one-time delivery, concurrent/idempotent registration, response-loss uncertainty, reconciliation and nonforking replacement. Distinguish issuance denial from Core permission denial.
- Measure the first fresh decision after completed human logout/disable/role removal and machine revocation/replacement. Test provider/storage outages, readiness recovery, retained active success and continued revoked denial. Cached discovery readiness (five-second interval, two-second deadline) is not an authorization cache or business readiness.
- Before localhost:8080 acceptance, verify the exact intended k3d Core port-forward; no parallel host Core or silent port change. The integrated runner owns its temporary forward and refuses an occupied port. Keep private raw evidence outside Git and attach only sanitized revision/environment-bound outcomes to #8.
- Verify generated account absence, owned provider clients inactive, retained registrations revoked/soft-deleted and normal signup-disabled policy. Unknown cleanup stops normal Authorizer and retains the exact operator lock; no blind rerun/unlock or unrelated resource cleanup.
Local custody and recovery limits: local HTTP and MongoDB are cleartext. Kubernetes Secret custody, trusted-container process argv/environment/tmpfs exposure and plaintext local Terraform state remain deliberate local limitations—not production security; no-store is not TLS. Provider ADMIN_SECRET is broad. Never read/publish credentials, raw traces, state or plans as evidence. Preserve signing/encryption keys, provider session state and Core registry state together. Same-state restart persistence is not backup/restore, disaster recovery, replica failover or key-custody proof. Do not regenerate Secrets, initialize fresh Terraform state or wipe persistent data to repair an outage.
Sources and scope
Grounded in reviewed merge 3f20aec182715f114e3506414b55e62387e6203e and source-equivalent installed runtime 5e455d7: authentication.md · authentication-lifecycle.md · agent-registry.md · authorizer-operations.md · authentication-acceptance.md · pinned deployment values. Main-branch links are maintained sources, not immutable execution receipts.
Only this existing identity/access topic, its two diagrams and portable Markdown export are updated. Navigation, styling, dialog JavaScript, stable IDs and unrelated registry principles/links are preserved. Repository delivery and local execution results are recorded separately on #8; production qualification remains pending.