--- id: HUB-WP-0009 type: workplan title: "Complete the hub-extension conformance profile" domain: infotech repo: hub-core status: finished flavor: residual owner: codex topic_slug: custodian created: "2026-08-31" updated: "2026-09-27" origin: residual origin_ref: OPS-WP-0003 related: - HUB-WP-0004 - HUB-WP-0005 - OPS-WP-0003 state_hub_workstream_id: "0d6e94f3-fd15-5f57-af41-60f0b862da5e" --- # Complete the hub-extension conformance profile ## Goal Turn the deliberately open Tier-2 checks in `helixforge.hub-extension/0.1.0` into executable framework evidence without making an extension repository implement hub-core policy. OPS-WP-0003 passed the current C1/C3/C4/C5/C6/C8 profile; this residual owns C2, C7, C9, and C10. ## Add registry resolution evidence ```task id: HUB-WP-0009-T01 status: done flavor: residual priority: medium state_hub_task_id: "0702bd43-146e-5f5d-9bf3-81ae4a367afb" ``` Implement C2 against the public registry/discovery contract, including missing, ambiguous, and stale registrations. Keep repository and capability authority in their owner systems and make registry audit history queryable. Completed 2026-09-27. `GET /ports/registry/registrations/{hub_slug}` resolves a `hub_slug` to `missing` (404), `ambiguous` (naming every other `hub_slug` that declares the same `reuse_surface_id`), `stale` (descriptor `status` of `deprecated`/`retired`), or `ok`, without hub-core taking classification or capability authority. `GET .../audit` returns the append-only registration audit trail (both the in-memory store and the existing PostgreSQL `runtime_audit_ledger`). Harness check C2 and `tests/test_runtime.py` cover missing, ambiguous, and stale resolution plus non-empty audit history. ## Enforce raw-port configuration policy ```task id: HUB-WP-0009-T02 status: done flavor: residual priority: medium state_hub_task_id: "427a663c-fbd5-55c8-9889-6946a5072932" ``` Implement C7 so production configuration cannot bypass named ports or silently enable overlapping authorities. Cover policy allow, deny, and unavailable behavior without embedding credentials in fixtures. Completed 2026-09-27. `RuntimeSettings.__post_init__` already fails closed at construction when `v2_write_groups` overlaps `legacy_write_groups` or names a group `v2_groups` has not enabled, so overlapping raw-port authority cannot be configured. Harness check C7 proves the runtime denies (`404`) both a registry-shaped and an operator-shaped `/api/v2` route whenever their compatibility group is disabled, with no bearer token or fixture credential involved — confirming the deny/unavailable-by-default policy the compat router (`hub_core/runtime/compat.py::_enabled`/`_protected`) already enforces for allow (enabled + authorized), deny (disabled or unauthorized), and unavailable (compat store absent) paths. ## Prove dependency-aware readiness ```task id: HUB-WP-0009-T03 status: done flavor: residual priority: high state_hub_task_id: "41476950-bb3f-5fc3-8d44-bea3d851e5f9" ``` Implement C9 for every enabled port and compatibility group. Readiness must fail when its required database, policy, registry, or owner projection is unavailable while unrelated disabled groups remain non-blocking. Completed 2026-09-27. `/readyz` already aggregated per-dependency checks (database, `port.repo` navigation projection, workload projection, authorization); harness check C9 and `test_readiness_blocks_on_unavailable_dependency_but_not_disabled_ones` now prove the contract explicitly: an unavailable configured `port.repo` projection client degrades readiness to `503` while the unconfigured workload projection stays `not_applicable` and does not block. ## Add contract-version negotiation ```task id: HUB-WP-0009-T04 status: done flavor: residual priority: medium state_hub_task_id: "90849a2d-c3ac-5fca-b86f-88cef2803957" ``` Implement C10 using descriptor min/max versions and explicit incompatibility responses. Include the 0.1 compatibility adapter and ensure future versions do not silently accept a contract they cannot interpret. Record tenant-isolation coverage separately if it still exceeds this profile. Completed 2026-09-27. `ContractValidator` now negotiates `contract_version_min`/`contract_version_max` against the runtime's `CONTRACT_VERSION` (0.1.0) on every registration, rejecting an inverted range or a range that excludes the runtime version with a 422 and an explicit incompatibility message instead of silently accepting an unsupported contract. Harness check C10 and two `tests/test_runtime.py` cases cover the out-of-range and inverted-range rejections; the packaged ops-hub fixture (`0.1.0`-`0.1.0`) continues to register, proving the 0.1 compatibility adapter still passes. Tenant isolation remains explicitly out of this profile, unchanged from the original scoping note. ## Acceptance - [x] C2, C7, C9, and C10 are automated and fail closed - [x] The conformance report distinguishes unsupported from pass/fail - [x] Ops Hub's canonical owner package passes the expanded profile - [ ] Any tenant-isolation residual has its own live owner record — out of scope: the 0.1 runtime still has no tenant identity/authorization context, as noted in `docs/conformance.md`; no owner record exists to link because there is no implementation to attribute one to.