| Side-effect-free lookup by exact issuer and subject | User Engine: existing identity only; unknown identity denies without provisioning |
| Current account state and explicit root grant | User Engine + NetKingdom: identity link, global and scoped account state, grant source/revocation/version, independent of JWT roles and Hub root-subject configuration |
| Platform naming | Both owners: explicit reviewed mapping of User Engine scope to canonical `tenant:platform`; no string substitution inferred by Hub |
| Current tenant lifecycle | Tenant Engine: canonical identifier bound to immutable record and version |
| Caller authentication | Each owner: dedicated Hub workload audience/identity and narrowly scoped read authorization; no end-user bearer forwarding |
| Freshness and evidence | Each owner: source observation timestamp and durable evidence/version reference; no stale cache on failure |
| Producer aliases | Account/identity owner: explicit current bindings, or an empty set; no aliases derived from display names |
Owners must specify the actual route, request/response schema, authentication
mechanism and scoped grants before HTTP reader implementations can be written.
The Python types below are an internal normalization seam, **not a proposed
HTTP endpoint that already exists**. Missing/unknown/ambiguous results must raise
and deny; they must never synthesize an active account.
## Implemented composition
`hub_core.security.facts.PlatformFacts` implements `FactSource` with injected
`AccountReader` and `TenantReader`. The account reader returns a typed
`AccountObservation`; the tenant reader returns a `TenantObservation`. Readers
own authentication and wire verification. `account_active` must include the
current identity link, global account and required scoped-account validity; a
globally active account alone is insufficient. They receive identity references only,
not the end-user token. No concrete network reader or automatic environment
activation is provided.
The host supplies the reviewed account-tenant identifier and mapping evidence
reference explicitly. That mapping is not an entitlement grant. This candidate
admits only human actors in `tenant:platform`; workload and cross-tenant lookups
remain separately scoped work. The shared controller still verifies the exact
root issuer/subject before consulting this source.
Every request rereads both owners within one three-second budget. Results must
match exact identity/tenant bindings, contain strict booleans and nonempty evidence,
and be no older than five seconds or in the future. The result retains the oldest
source timestamp, so slow joining/policy/audit cannot refresh authority. Inactive
or withdrawn state remains a valid observation and is denied by the controller.
Failures expose only a sanitized 503 and never fall back to an earlier allow.
Cancellation propagates to the pending lookup.
The evidence join is SHA-256 over canonical JSON containing the account, tenant
and mapping references. Readers/owners must retain the referenced evidence for
reconstruction; this hash is a join identifier, not a signature or independent
proof of owner authenticity. No account payload or credential enters the join.
## Acceptance cases and remaining work
Local tests cover exact bindings, malformed state, stale/future observations,
oldest-timestamp preservation, bounded outages, repeated lookup, entitlement and
account suspension, tenant inactivity, and refusal before policy after withdrawal.
Fixtures implement the internal readers; they do not prove owner API acceptance.
T01/T02 remain open for owner disposition of the table above, implementation of
real authenticated readers, and isolated owner-source integration tests proving
unknown lookups create nothing. Private acceptance must then demonstrate root
allow, ordinary/forged identity denial, next-request revocation and owner outages
with real admitted callers. No public exposure follows from this contract.