| User Engine `web.py`, `service.py::me` | `/api/v1/me` resolves `(iss, sub)` but creates User/Account/ExternalIdentity records if absent | A side-effect-free authority lookup; Hub must not bootstrap identities to check access |
| User Engine `service.py` | `PLATFORM_TENANT = "platform:root"`; `platform-operator` is an actor role | Explicit mapping to IAM `tenant:platform` and the one immutable root principal; a role or string substitution is insufficient |
| User Engine tenant administration APIs | Human/edge-oriented routes; no reviewed Hub workload lookup for current root entitlement | Independently authenticated Hub workload, exact lookup scope and current entitlement provenance |
| Tenant Engine `/tenants/{tenant_id}` | Current lifecycle and record version, authorized `tenant.read` | Resolve immutable tenant ID versus canonical identifier; preserve owner version and lifecycle |
| Tenant Engine `/tenants/{tenant_id}/roles/live` | Live role state with `tenant.role.read.live`, caller supplies an `actor` query | Admit/authenticate the actual Hub workload and its actor assertion; do not mistake query text or a network path for caller authentication |
The accepted integration must return identity references, account status,
explicit current root entitlement, actor/target tenant status, observation times
and owner evidence/version references. Unknown identity is denied without
creating anything. Revocation must be visible on the next privileged read as
well as write; no cached token role supplies current entitlement.
`LiveFacts` is the Hub-side normalized result, not a wire endpoint invented for
an owner. Each source lookup must complete inside its timeout. The observation
age is measured from the actual source observation and cannot be reset after
slow downstream calls. All joined facts must still be at most five seconds old
when policy/audit finish. Missing, ambiguous, inactive or stale facts deny.
Producer aliases must come from an explicit owner binding to that identity.
T01/T02 require owner review of the lookup and root/tenant mapping before a
production `FactSource` is configured. The runtime will not load fixture facts,
query owner databases directly, forward Hub bearer tokens to other audiences,
or use `/me` as an account-provisioning side effect.
## Audit Core adapter and sender admission
`AuditCoreSink` implements the actual `docs/event-envelope.md` contract:
`POST /v1/events` with eight fields, a distinct rotating sender bearer, and an
`Idempotency-Key` matching the event ID. Source is exactly `hub-core`, tenant
exactly `tenant:platform`. Only a matching `202 accepted` or `200 duplicate`
with a nonempty archive reference counts as custody. Before each append,
`/readyz` must report `status=ok`, `durable=true`, and custody class
`operational` or its rollout alias `archive`. The entire append is bounded
at three seconds, uses TLS, and never follows redirects.
Allow is blocked until the archive accepts the authorization record. A lost
receipt blocks the business operation even if the attempt reached storage. This
is a pre-execution authorization journal, not proof that an operation committed.
There is no local success buffer or silent redaction. Domain transaction/outcome
atomicity and failure detection remain separate T03/T04 acceptance gates.
The exact verified signed decision is retained under `data.signed_decision` as
serialized JSON so another serialization of the archive cannot reorder its Go
struct fields. The verifier refuses secret-shaped field names before retention.
No end-user bearer, message body or command body is emitted. Independent tests
reverify the signed artifact after retrieval from the owner's receiver.
Proposed receiver registration (no credential values):
- Name/source: `hub-core`; allowed tenants: only `tenant:platform`.