# Hub access profile 1.0.0 — implementation candidate HUB-WP-0012 source implementation, 2026-09-28. Owner review and live acceptance remain open. This profile does not grant platform access or enable public exposure. ## Runtime behavior `HUB_CORE_ACCESS_MODE=auto` enables enforcement whenever `HUB_CORE_ENV` is not `development` or `test`. `enforce` also enables it locally. `development` is rejected in other environments. **Do not deploy this candidate as a routine upgrade:** the default production factory has no admitted owner adapters yet and returns 401 for missing credentials and 503 for credential-bearing requests. The current deployed image and its release configuration have not been changed. Without explicit browser composition, only exact `GET /healthz` is public, returning `{"status":"ok"}`. The shared ASGI boundary protects docs, readiness, native ports, projections, compatibility aliases and subsequently attached routes. Unknown method/route/handler combinations, WebSockets, mounts without admission, and slash redirects without catalog entries fail closed. Clients must use exact paths. Catalog admission does not override compatibility feature flags or single-writer/read-only gates. Legacy bearer checks remain in the development lane; production enforcement never falls back to them. `hub_core/security/routes.json` is the candidate action catalog. It names each runtime method, path template and handler, with a stable action per handler/method. It is packaged in the wheel and tested against actual route construction. Source inventory generation does **not** auto-admit a new route. Duplicate docs handlers remain separately inventoried; the boundary selects the first effective route. These technical action names require flex-auth/owner review before policy delivery. Optional browser composition adds four exact `/auth/*` protocol routes and the `hub.browser.session` action; login initiation is public, callback state is browser-bound, and session access requires current root authority. See the [browser integration contract](owner-access-integration.md#browser-composition-source-candidate). ## Composition and trust A host composes `create_app(access_controller=AccessController(...))` with: - `OIDCVerifier`: an explicitly trusted HTTPS issuer and Hub audience, an owned `httpx.AsyncClient`, RS256 discovery/JWKS, token and assurance lifetime at most 300 seconds, a 60-second key cache, and unknown-key rotation refresh (rate limited to once per second). Access tokens require `at+jwt` or the KeyCape `typ: Bearer` payload marker. ID tokens, local issuers/profiles, weak keys, AAL0 and delegated agents are refused. Strict integer NumericDates and assurance time are required. - `FactSource.resolve`: an **owner implementation still owed** that queries authoritative account, root entitlement, actor tenant and target tenant state. Its result binds issuer, subject, actor tenant, evidence reference and permitted producer addresses; its age may not exceed five seconds, including after policy and audit finish. No token role or incoming tenant/identity header supplies facts. - `FlexPolicy`: a dedicated HTTPS Hub PDP, exact admitted ServiceAccount principal, a rotating projected caller-token file and an owner-delivered trusted public-key set. The token is reread on every call and is separate from the end-user token. Remote `/v1/keys` responses never establish their own trust. Current/previous keys can coexist in the mounted trust file; removing a key takes effect next call. - `AuditCoreSink`: implemented against the owner [eight-field ingestion contract](../../audit-core/docs/event-envelope.md), returning only after an operational-custody probe and explicit durable acceptance. Every allow must reach this sink before handler execution; a failed sink blocks reads as well as writes. Authorization receipts say `authorized`, not “operation completed.” Domain commit/outcome audit remains a separate requirement; this source seam does not claim transactional audit. - The root's existing immutable issuer and subject, supplied after owner resolution. No username, email, first-login promotion or generic role establishes root. Do not implement these missing adapters as a constant allow, in-memory audit sink, or an assertion copied from token claims. Tests use synthetic owners explicitly. The current CLI deliberately provides no fixture adapter or production bypass. An explicit `SecuritySettings`/owner-facts composition now owns the HTTP client and closes it with the runtime. Audit custody is probed per append. Real owner-facts admission and additional owner dependency probes remain T02–T04 work; see the [owner integration review](owner-access-integration.md). For this candidate all Hub resources are explicitly **platform-owned**. Other target tenants are refused. Root requires AAL2/3, active account and tenants, current root entitlement, and a fresh policy allow for every action. Workloads receive no root shortcut: a policy grant and current authoritative facts are always required. Real workload admission remains unproven. Cross-tenant owner administration and Phase 2 storage/query isolation are not implemented by this classification. ## Policy interoperability and failure handling The PDP request carries actor, target tenant, action, concrete resource path, assurance, root entitlement, authoritative evidence reference, and a digest of HTTP method/path/query/body. Client bodies and bearer tokens are not sent to the PDP or audit sink. Body size is bounded at 1 MiB with a ten-second receive deadline. The controller's identity/facts/ policy/audit chain has a ten-second timeout; individual HTTP calls have three seconds. A separate refusal-audit attempt is bounded at three seconds. The verifier requires Ed25519 signing, the submitted request digest, matching request ID and structured actor/action/resource/tenant/context, enforced caller provenance, policy version/digest, a decision age at most 30 seconds and a valid allow lifetime. It never caches decisions. Every unimplemented obligation and non-allow/non-deny effect fails closed; approval requirements cannot be waived. A malformed/untrusted/unavailable decision returns 503, a verified denial 403, and invalid authentication 401. Responses are `no-store` and do not expose backend exceptions. There is no local allow fallback. Interoperability tests retain flex-auth's real Go-signed fixture, tampered pair, public test key and original submitted request. Go `encoding/json` emits struct fields in declaration order and map keys in sorted order. The verifier retains wire order and HTML escaping for signatures and reproduces the request structs for `submitted_request_digest`. This is **not** RFC 8785. Duplicate JSON keys and non-integer decision numbers are outside this candidate profile and fail closed; a reordered envelope also fails signature verification. Agree broader canonical encoding with flex-auth before expanding this profile. ## Producers, MCP and embedded hosts `from_address`, `from_agent` and `author`, when present in a top-level JSON command, must match the live owner's producer-address set. Native events get a reserved `payload._hub_access` record containing verified actor/tenant/correlation identity; client assertions under that key are overwritten. Domain `subject_refs` remain business data, never proof of origin. Compatibility event implementations and external publishers still need owner acceptance of equivalent attribution. Embedded hosts can install `AccessBoundary` and an explicit host route catalog. Tests prove the common seam on an embedded host; each real host's mounted paths, features and routers still require inventory and admission. Do not treat the standalone runtime catalog as admission for every embedded API. MCP hosts may supply `token_provider`, a callable resolving a **Hub-audience** credential from the current invocation, with `require_credentials=True`. Credentials are never retained on the server; requests do not follow redirects when carrying one. `trailing_slash=False` targets the standalone runtime's native paths. The standalone production MCP has no human flow/provider yet and fails closed. Many legacy tools target APIs the standalone Hub does not implement. They remain unsupported, not silently translated or authorized. Cross-audience delegation, browser PKCE sessions/logout and real MCP root login remain open. ## Remaining release gates 1. T01: cross-owner contract review, concrete policy vocabulary, effective host and service-route expansion; the 250-object snapshot is not full route discovery. 2. T02: immutable root binding, registered audience/redirects, PKCE/MFA/recovery, admitted live facts adapters, attended login/logout and revocation receipts. 3. T03: dedicated Hub policy and fact provenance review; authenticated deployment, credential/key custody, real Audit Core sender admission and native rotation probes. 4. T04–T05: deploy the admitted composition, complete dependency health probes and all client/extension migrations, domain outcome audit, legacy lane rollback and full root journeys. 5. T06–T08: every platform/Railiance receipt, separate public-enable approval and later role/delegation/tenant isolation. No milestone is closed by local fixtures.