Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e747-8f27-7242-8df8-8bc44f88c929
6.6 KiB
HUB-WP-0012 owner integration review — 2026-09-28
The Hub foundation is committed as 3e38614. This follow-up delivers an Audit
Core sender and runtime composition, and identifies the remaining source
contracts. These are owner review inputs, not evidence of deployed grants.
Account, root entitlement and tenant facts
| Owner surface reviewed | Observed behavior | Required integration |
|---|---|---|
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: onlytenant:platform. - Write enabled, read disabled; distinct sender tokens with rotation overlap.
secret_policy=reject; authorization record classeshub.access.authorized,hub.access.denied,hub.access.refused.- Load-bearing authorization evidence: execution requires receipt. Owner review must settle exact emission-cadence/failure detection; no claim that this journal provides complete domain mutation evidence or archive tamper evidence.
Credential routing: warden route show audit-core-senders --json identifies
ops-mason, subsystem OpenBao + audit-core, warden_executes=false, and currently
resolvable=false. This route points to registry custody; it does not prove an
admitted Hub sender or mint a credential. No secret was requested or retrieved.
Runtime assembly
SecuritySettings uses these HUB_CORE_SECURITY_ environment suffixes:
| Suffix | Value |
|---|---|
ISSUER, AUDIENCE, ROOT_SUBJECT |
Admitted HTTPS issuer, Hub audience, immutable root subject |
POLICY_URL, POLICY_CALLER |
Dedicated HTTPS PDP and exact admitted ServiceAccount principal |
POLICY_TOKEN_FILE, POLICY_KEYS_FILE |
Absolute projected caller-token and trusted public-key paths |
AUDIT_URL, AUDIT_TOKEN_FILE |
HTTPS receiver and separate absolute sender-token path |
A host calls create_app(access_facts=reviewed_owner_adapter) in enforcement
mode. It can alternatively supply an explicit SecuritySettings instance.
The runtime owns and closes the shared HTTP client; proxy environment variables
are not inherited. Partial/invalid composition is rejected. Without an explicit
facts adapter, the standalone app stays closed even if security variables exist.
No file-backed allowlist or dynamic arbitrary-module loader supplies authority.
Evidence boundary
The opt-in tests/test_audit_core_owner_contract.py exercises the actual Audit
Core WSGI receiver and durable SQLite storage, including reopen, wrong-credential
and lost-receipt cases. A test-only readiness fixture reports operational
custody to exercise the production client's receipt checks; this is not native
operational custody. Unmodified development custody is independently refused.
A composed fixture journey verifies a real RSA JWT, fresh facts, an Ed25519
policy decision, receiver custody and native Hub write, followed by entitlement
withdrawal denial. Real root enrollment/login, service deployment, live key and
sender custody, and operational acceptance remain open.