feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
---
|
|
|
|
|
|
id: IHUB-WP-0009
|
|
|
|
|
|
type: workplan
|
|
|
|
|
|
title: "IHF GAAF Compliance Foundation — Type Registries, Extension Manifests, and Architectural Contracts"
|
|
|
|
|
|
domain: inter_hub
|
|
|
|
|
|
repo: inter-hub
|
|
|
|
|
|
status: done
|
|
|
|
|
|
owner: custodian
|
|
|
|
|
|
topic_slug: inter_hub
|
|
|
|
|
|
created: "2026-03-31"
|
|
|
|
|
|
updated: "2026-03-31"
|
|
|
|
|
|
completed: "2026-03-31"
|
|
|
|
|
|
token_cost:
|
2026-03-31 21:32:37 +00:00
|
|
|
|
pricing_model: "claude-sonnet-4-6 — assumed $3/MTok input, $15/MTok output (same tier as 3.5 Sonnet; verify against current Anthropic pricing)"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
session_1_context_exhausted: true
|
|
|
|
|
|
session_1_model: claude-sonnet-4-6
|
2026-03-31 21:32:37 +00:00
|
|
|
|
session_1_input_tokens_est: ~125000
|
|
|
|
|
|
session_1_output_tokens_est: ~75000
|
|
|
|
|
|
session_1_cost_usd_est: "~$1.50"
|
|
|
|
|
|
session_1_notes: "Context exhausted (~200k total). High output: GAAF spec, Operational Architecture spec, IHF v0.2 spec annotations, workplan (857 lines), 6 contract files, ARCHITECTURE-LAYERS.md, migration SQL, TypeRegistry helper, TypeRegistries controller+4 views, hub_kind schema+controller+views, CLAUDE.md/Schema.sql/Types/Routes changes."
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
session_2_model: claude-sonnet-4-6
|
2026-03-31 21:32:37 +00:00
|
|
|
|
session_2_input_tokens_est: ~65000
|
|
|
|
|
|
session_2_output_tokens_est: ~35000
|
|
|
|
|
|
session_2_cost_usd_est: "~$0.72"
|
|
|
|
|
|
session_2_notes: "Continuation via summary injection. T04 (registry validation wired into 4 controllers, 3 maturity badges), T05 (HubCapabilityManifests controller+4 views, FrontController nav), T06 (functional-modules.md + domain-hub-extension-guide.md), T07 (LayerBoundarySpec + Test/Main), T08 (CLAUDE.md, SCOPE.md, workplan close-out)."
|
|
|
|
|
|
total_input_tokens_est: ~190000
|
|
|
|
|
|
total_output_tokens_est: ~110000
|
|
|
|
|
|
total_cost_usd_est: "~$2.22"
|
|
|
|
|
|
calibration_note: "Commit b5d73aa shows 4855 insertions/104 deletions across 47 files. Output estimate derived from line counts (~4 chars/token). Input estimate from file reads + tool results + prior context accumulation."
|
|
|
|
|
|
state_hub_sync: done
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_workstream_id: "24ad18c7-f2a9-4cfd-88f0-4cbc78064bb0"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# IHF GAAF Compliance Foundation
|
|
|
|
|
|
|
|
|
|
|
|
## Goal
|
|
|
|
|
|
|
|
|
|
|
|
Establish inter-hub as a GAAF-2026 compliant framework foundation before any
|
|
|
|
|
|
domain hub (dev-hub, ops-hub, fin-hub, sec-hub) begins implementation. Close
|
|
|
|
|
|
the architectural gaps identified in the GAAF review of 2026-03-31 so that
|
|
|
|
|
|
Phase 9 and beyond are built on a framework with a formal extension layer,
|
|
|
|
|
|
typed vocabularies, explicit contracts, and CI-enforced architectural boundaries.
|
|
|
|
|
|
|
|
|
|
|
|
## Background
|
|
|
|
|
|
|
|
|
|
|
|
Phases 1–8 are complete. The core traceability chain, federated governance
|
|
|
|
|
|
machinery, and cross-framework adapter protocol are all production-grade. The
|
|
|
|
|
|
GAAF-2026 review confirmed the Core layer is strong (3.4/5.0) but revealed
|
|
|
|
|
|
four critical gaps that must be closed before domain hubs can safely extend
|
|
|
|
|
|
the framework:
|
|
|
|
|
|
|
|
|
|
|
|
1. **No Extension Layer** — no mechanism for domain hubs to register their
|
|
|
|
|
|
widget types, event types, annotation categories, or policy vocabulary
|
|
|
|
|
|
with the framework. All type discriminators are unvalidated TEXT, creating
|
|
|
|
|
|
vocabulary divergence risk the moment two hubs independently name things.
|
|
|
|
|
|
|
|
|
|
|
|
2. **No `/contracts/` directory or `ARCHITECTURE-LAYERS.md`** — GAAF requires
|
|
|
|
|
|
these as living governance artifacts. Their absence means architectural
|
|
|
|
|
|
intent is implicit in spec documents and tribal knowledge rather than
|
|
|
|
|
|
machine-readable contracts in the repository.
|
|
|
|
|
|
|
|
|
|
|
|
3. **No hub kind classification** — the `hubs` table treats the framework host
|
|
|
|
|
|
(inter-hub itself) and domain consumer hubs (dev, ops, fin, sec) as
|
|
|
|
|
|
structurally identical. The Phase 10 Hub Registry cannot distinguish
|
|
|
|
|
|
providers from consumers without this.
|
|
|
|
|
|
|
|
|
|
|
|
4. **No architectural fitness functions** — architectural constraints exist
|
|
|
|
|
|
in the spec but are not automatically verified in CI. Layer boundary
|
|
|
|
|
|
violations can accumulate silently.
|
|
|
|
|
|
|
|
|
|
|
|
Reference: `specs/GoodSoftwareArchitectureFramework_2026.md`,
|
|
|
|
|
|
`specs/InteractionHubFrameworkSpecification_v0.2.md`,
|
|
|
|
|
|
GAAF review document (2026-03-31 analysis).
|
|
|
|
|
|
|
|
|
|
|
|
## Why This Workplan Precedes Phase 9
|
|
|
|
|
|
|
|
|
|
|
|
Phase 9 exposes the IHF as a versioned external API and generates an OpenAPI
|
|
|
|
|
|
3.1 specification. That specification must enumerate type discriminators
|
|
|
|
|
|
(widget_type, event_type, annotation category, policy_scope) as finite enum
|
|
|
|
|
|
arrays — not arbitrary strings. If the type registries do not exist before
|
|
|
|
|
|
Phase 9 begins, the OpenAPI spec will document TEXT fields and the API will
|
|
|
|
|
|
be incorrect by design. The type registries must be stable before the API
|
|
|
|
|
|
contract is written.
|
|
|
|
|
|
|
|
|
|
|
|
Phase 10 (Hub Registry and Marketplace) is the extension layer in IHF terms.
|
|
|
|
|
|
Its hub registry IS the `HubCapabilityManifest` table introduced here, scaled
|
|
|
|
|
|
to a public-facing UI. Building Phase 10 without first establishing the
|
|
|
|
|
|
manifest schema would require a breaking re-architecture mid-phase.
|
|
|
|
|
|
|
|
|
|
|
|
## GAAF Compliance Targets
|
|
|
|
|
|
|
|
|
|
|
|
After this workplan, inter-hub should score:
|
|
|
|
|
|
|
|
|
|
|
|
| Layer | Before | Target |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| Core | 3.4 | 3.8 |
|
|
|
|
|
|
| Functional | 2.2 | 3.2 |
|
|
|
|
|
|
| Customization | 1.5 | 2.5 |
|
|
|
|
|
|
| Configuration | 1.6 | 3.0 |
|
|
|
|
|
|
| Extensions | 0.3 | 3.5 |
|
|
|
|
|
|
| Cross-layer | 2.3 | 3.5 |
|
|
|
|
|
|
| **Weighted total** | **2.23** | **~3.3** |
|
|
|
|
|
|
|
|
|
|
|
|
The target moves the framework from "Needs restructuring" (≤2.4) to "Usable
|
|
|
|
|
|
but vulnerable" (2.5–3.4), clearing the floor for Phase 9+ work. A score of
|
|
|
|
|
|
≥3.5 (Strong) is the Phase 10 exit target.
|
|
|
|
|
|
|
|
|
|
|
|
## Data Artifacts Introduced
|
|
|
|
|
|
|
|
|
|
|
|
`WidgetTypeRegistry`, `EventTypeRegistry`, `AnnotationCategoryRegistry`,
|
|
|
|
|
|
`PolicyScopeRegistry`, `HubCapabilityManifest`
|
|
|
|
|
|
|
|
|
|
|
|
Schema additions: `hubs.hub_kind`, maturity columns on existing contract
|
|
|
|
|
|
tables.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Tasks
|
|
|
|
|
|
|
|
|
|
|
|
### T01 — Governance scaffolding: `/contracts/` and `ARCHITECTURE-LAYERS.md`
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: IHUB-WP-0009-T01
|
|
|
|
|
|
status: done
|
|
|
|
|
|
priority: high
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_task_id: "dbeaa00d-a5c1-47bf-9621-58ece75dcd42"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Pure documentation. No schema or code changes. Establishes the governance
|
|
|
|
|
|
artifacts required by GAAF §4, §9, and §12.
|
|
|
|
|
|
|
|
|
|
|
|
1. Create `/contracts/README.md` — contract catalog listing all contracts by
|
|
|
|
|
|
layer, with one-line descriptions and file links. Template:
|
|
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
|
# IHF Contract Catalog
|
|
|
|
|
|
**Framework:** GAAF-2026 | **Last reviewed:** YYYY-MM-DD
|
|
|
|
|
|
|
|
|
|
|
|
## Core Contracts
|
|
|
|
|
|
- [widget-envelope-v1](core/widget-envelope-v1.md) — Required widget envelope
|
|
|
|
|
|
attributes and format rules
|
|
|
|
|
|
- [append-only-events-v1](core/append-only-events-v1.md) — Immutability
|
|
|
|
|
|
invariant for interaction_events and outcome_signals
|
|
|
|
|
|
|
|
|
|
|
|
## Functional Contracts
|
|
|
|
|
|
- [interaction-reporting-v1](functional/interaction-reporting-v1.md) — REST
|
|
|
|
|
|
API contract for external event and annotation submission
|
|
|
|
|
|
- [module-maturity-labels](functional/module-maturity-labels.md) — Definition
|
|
|
|
|
|
of Experimental / Beta / Stable / Deprecated for IHF modules
|
|
|
|
|
|
|
|
|
|
|
|
## Extensions Contracts
|
|
|
|
|
|
- [hub-capability-manifest-v1](extensions/hub-capability-manifest-v1.md) —
|
|
|
|
|
|
Domain hub extension registration protocol
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. Create `/contracts/core/widget-envelope-v1.md`:
|
|
|
|
|
|
- Required `data-*` attributes: `data-widget-id`, `data-hub-id`,
|
|
|
|
|
|
`data-view-context`, `data-widget-type`
|
|
|
|
|
|
- Optional: `data-capability-ref`, `data-policy-scope`,
|
|
|
|
|
|
`data-widget-version`, `data-experiment-variant`
|
|
|
|
|
|
- Format rules: `data-widget-id` must be a valid UUID; `data-hub-id` must
|
|
|
|
|
|
match a registered hub slug; `data-widget-type` must exist in the
|
|
|
|
|
|
`widget_type_registry`
|
|
|
|
|
|
- Version: 1.0. Immutable after activation. New requirements → v1.1 with
|
|
|
|
|
|
backwards-compatible additions only.
|
|
|
|
|
|
- Failure mode: widgets missing required attributes are logged as
|
|
|
|
|
|
`malformed_envelope` events; they do not crash the capture pipeline.
|
|
|
|
|
|
|
|
|
|
|
|
3. Create `/contracts/core/append-only-events-v1.md`:
|
|
|
|
|
|
- Invariant: `interaction_events` and `outcome_signals` rows are never
|
|
|
|
|
|
updated or deleted after insertion.
|
|
|
|
|
|
- Enforcement: PostgreSQL triggers `interaction_events_no_update`,
|
|
|
|
|
|
`interaction_events_no_delete`, `outcome_signals_no_update`,
|
|
|
|
|
|
`outcome_signals_no_delete`.
|
|
|
|
|
|
- Correction policy: erroneous events are retracted by inserting a new
|
|
|
|
|
|
event of type `retracted` with `metadata.retracted_event_id` pointing
|
|
|
|
|
|
to the original. The original row is never modified.
|
|
|
|
|
|
- Failure mode: any attempt to UPDATE or DELETE raises a PostgreSQL
|
|
|
|
|
|
exception with message "is append-only".
|
|
|
|
|
|
|
|
|
|
|
|
4. Create `/contracts/functional/interaction-reporting-v1.md`:
|
|
|
|
|
|
- Summarise the `InteractionReportingContract` DB record as a human and
|
|
|
|
|
|
machine-readable contract file. Include endpoint path, accepted event
|
|
|
|
|
|
types, required payload fields, auth scheme.
|
|
|
|
|
|
- Note: the canonical source of truth is the active
|
|
|
|
|
|
`interaction_reporting_contracts` row; this file is the discoverable
|
|
|
|
|
|
declaration.
|
|
|
|
|
|
|
|
|
|
|
|
5. Create `/contracts/functional/module-maturity-labels.md`:
|
|
|
|
|
|
- **Stable**: public interface will not change within a major version.
|
|
|
|
|
|
Removing a Stable field is a breaking change requiring a major version bump.
|
|
|
|
|
|
- **Beta**: interface is finalised for typical use but edge-case fields may
|
|
|
|
|
|
change with a minor-version notice. Suitable for production with awareness.
|
|
|
|
|
|
- **Experimental**: interface may change without notice between patches.
|
|
|
|
|
|
Use only for internal prototyping or explicit opt-in.
|
|
|
|
|
|
- **Deprecated**: will be removed in the next major version. A replacement
|
|
|
|
|
|
is documented in the contract.
|
|
|
|
|
|
|
|
|
|
|
|
6. Create `/contracts/extensions/hub-capability-manifest-v1.md`:
|
|
|
|
|
|
- Describes the `HubCapabilityManifest` schema (introduced in T05).
|
|
|
|
|
|
- Registration workflow: create manifest in draft → declare types → activate
|
|
|
|
|
|
(auto-registers declared types into their registries).
|
|
|
|
|
|
- Invariant: once a type name is added to a registry, it cannot be deleted
|
|
|
|
|
|
(only deprecated). Names are permanent — hubs may depend on them.
|
|
|
|
|
|
- Versioning: manifest_version tracks the protocol version, not the content
|
|
|
|
|
|
version. Content changes in draft do not require a version bump; a new
|
|
|
|
|
|
active manifest supersedes its predecessor.
|
|
|
|
|
|
|
|
|
|
|
|
7. Create `ARCHITECTURE-LAYERS.md` at the repository root using the GAAF §12.1
|
|
|
|
|
|
template. Include:
|
|
|
|
|
|
- Layer map: Core (Hub, Widget, WidgetVersion, InteractionEvent, Annotation,
|
|
|
|
|
|
traceability chain, append-only invariants, widget envelope) | Functional
|
|
|
|
|
|
(RequirementCandidate lifecycle through to FederatedGovernance) |
|
|
|
|
|
|
Customization (HubRoutingRule, FederatedPolicyOverlay — hub-specific
|
|
|
|
|
|
routing and policy) | Configuration (hub_kind, policy_scope, hub api_key,
|
|
|
|
|
|
HubCapabilityManifest) | Extensions (HubCapabilityManifest + type
|
|
|
|
|
|
registries — domain hub vocabulary registration)
|
|
|
|
|
|
- Dependency rule diagram
|
|
|
|
|
|
- GAAF weighted scorecard (initial values from 2026-03-31 review)
|
|
|
|
|
|
- Next review date: 2026-09-30
|
|
|
|
|
|
|
|
|
|
|
|
**Exit criteria:** `/contracts/` exists with six contract files; `README.md`
|
|
|
|
|
|
catalogs all of them; `ARCHITECTURE-LAYERS.md` exists at root with layer map
|
|
|
|
|
|
and scorecard filled in.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### T02 — Hub kind: classify hubs as `framework | domain | shared`
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: IHUB-WP-0009-T02
|
|
|
|
|
|
status: done
|
|
|
|
|
|
priority: high
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_task_id: "139cad01-24fb-4586-bd64-b5e1f72d657c"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Adds the structural distinction between inter-hub (the framework host) and
|
|
|
|
|
|
domain consumer hubs. Required by Phase 10 Hub Registry and by any fitness
|
|
|
|
|
|
function that checks "all domain hubs have an active capability manifest".
|
|
|
|
|
|
|
|
|
|
|
|
1. Schema addition:
|
|
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
|
-- hub_kind: structural role of the hub within the framework
|
|
|
|
|
|
-- 'framework' = inter-hub itself; there is exactly one framework hub
|
|
|
|
|
|
-- 'domain' = a bounded domain consumer (dev-hub, ops-hub, fin-hub, sec-hub)
|
|
|
|
|
|
-- 'shared' = a cross-domain service hub (state-hub, governance-hub)
|
|
|
|
|
|
ALTER TABLE hubs
|
|
|
|
|
|
ADD COLUMN hub_kind TEXT NOT NULL DEFAULT 'domain';
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX hubs_hub_kind_idx ON hubs (hub_kind);
|
|
|
|
|
|
|
|
|
|
|
|
-- Constraint: only one framework hub at a time
|
|
|
|
|
|
CREATE UNIQUE INDEX hubs_one_framework_idx ON hubs (hub_kind)
|
|
|
|
|
|
WHERE hub_kind = 'framework';
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. Write and run migration.
|
|
|
|
|
|
|
|
|
|
|
|
3. If a hub row representing inter-hub itself exists (slug = 'inter-hub' or
|
|
|
|
|
|
equivalent), update it: `UPDATE hubs SET hub_kind = 'framework' WHERE
|
|
|
|
|
|
slug = 'inter-hub'`. If no such row exists, this is a documentation-only
|
|
|
|
|
|
concern — add a note in `ARCHITECTURE-LAYERS.md`.
|
|
|
|
|
|
|
|
|
|
|
|
4. Validation in `HubsController`:
|
|
|
|
|
|
- `hub_kind` must be one of `framework | domain | shared`
|
|
|
|
|
|
- `framework` kind cannot be set via the web UI (read-only in forms;
|
|
|
|
|
|
only settable via migration or seeding)
|
|
|
|
|
|
- Default for new hubs created through the UI: `domain`
|
|
|
|
|
|
|
|
|
|
|
|
5. Hub list view: add a kind badge column (framework=purple, domain=blue,
|
|
|
|
|
|
shared=teal). Hub show page: kind badge in the header.
|
|
|
|
|
|
|
|
|
|
|
|
6. Hub index: add a tab filter for kind (All / Framework / Domain / Shared).
|
|
|
|
|
|
|
|
|
|
|
|
**Exit criteria:** migration runs; hub kind badge renders correctly;
|
|
|
|
|
|
constraint prevents a second `framework` hub; new hubs default to `domain`.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### T03 — Type registries: registered vocabularies for widget type, event type, annotation category, and policy scope
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: IHUB-WP-0009-T03
|
|
|
|
|
|
status: done
|
|
|
|
|
|
priority: high
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_task_id: "237e56e6-ee27-4947-a16b-098722b5ed42"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
This is the most consequential task in the workplan. These four registries
|
|
|
|
|
|
replace the implicit, unvalidated TEXT vocabularies that all type
|
|
|
|
|
|
discriminators currently rely on. They are the foundation for both the
|
|
|
|
|
|
Phase 9 OpenAPI enumerations and the Phase 10 marketplace's type-safe
|
|
|
|
|
|
widget patterns.
|
|
|
|
|
|
|
|
|
|
|
|
1. Schema — four registry tables:
|
|
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
|
-- widget_type_registry: registered widget types
|
|
|
|
|
|
CREATE TABLE widget_type_registry (
|
|
|
|
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
|
|
|
|
name TEXT NOT NULL UNIQUE,
|
|
|
|
|
|
-- canonical identifier: lowercase-hyphenated, e.g. 'pipeline-status'
|
|
|
|
|
|
label TEXT NOT NULL,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
owner_hub_id UUID REFERENCES hubs(id),
|
|
|
|
|
|
-- null = framework-level type (cross-domain); non-null = domain-owned
|
|
|
|
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
|
|
|
|
-- 'active' | 'deprecated'
|
|
|
|
|
|
deprecated_in_favour_of TEXT,
|
|
|
|
|
|
-- name of the replacement type, if deprecated
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX widget_type_registry_status_idx
|
|
|
|
|
|
ON widget_type_registry (status);
|
|
|
|
|
|
CREATE INDEX widget_type_registry_owner_hub_idx
|
|
|
|
|
|
ON widget_type_registry (owner_hub_id);
|
|
|
|
|
|
|
|
|
|
|
|
-- event_type_registry: registered interaction event types
|
|
|
|
|
|
CREATE TABLE event_type_registry (
|
|
|
|
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
|
|
|
|
name TEXT NOT NULL UNIQUE,
|
|
|
|
|
|
label TEXT NOT NULL,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
owner_hub_id UUID REFERENCES hubs(id),
|
|
|
|
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
|
|
|
|
deprecated_in_favour_of TEXT,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX event_type_registry_status_idx
|
|
|
|
|
|
ON event_type_registry (status);
|
|
|
|
|
|
|
|
|
|
|
|
-- annotation_category_registry: registered annotation categories
|
|
|
|
|
|
CREATE TABLE annotation_category_registry (
|
|
|
|
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
|
|
|
|
name TEXT NOT NULL UNIQUE,
|
|
|
|
|
|
label TEXT NOT NULL,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
owner_hub_id UUID REFERENCES hubs(id),
|
|
|
|
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
|
|
|
|
deprecated_in_favour_of TEXT,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX annotation_category_registry_status_idx
|
|
|
|
|
|
ON annotation_category_registry (status);
|
|
|
|
|
|
|
|
|
|
|
|
-- policy_scope_registry: registered policy scope names
|
|
|
|
|
|
CREATE TABLE policy_scope_registry (
|
|
|
|
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
|
|
|
|
name TEXT NOT NULL UNIQUE,
|
|
|
|
|
|
label TEXT NOT NULL,
|
|
|
|
|
|
description TEXT,
|
|
|
|
|
|
owner_hub_id UUID REFERENCES hubs(id),
|
|
|
|
|
|
status TEXT NOT NULL DEFAULT 'active',
|
|
|
|
|
|
deprecated_in_favour_of TEXT,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX policy_scope_registry_status_idx
|
|
|
|
|
|
ON policy_scope_registry (status);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. Seed the framework-level vocabulary (owner_hub_id = NULL):
|
|
|
|
|
|
|
|
|
|
|
|
**Widget types** (from IHF spec §6.2 and existing usage):
|
|
|
|
|
|
`chart`, `form`, `table`, `action`, `panel`, `workflow-step`,
|
|
|
|
|
|
`recommendation`, `chat`, `diff`
|
|
|
|
|
|
|
|
|
|
|
|
**Event types** (from IHF spec §6.4):
|
|
|
|
|
|
`viewed`, `focused`, `clicked`, `submitted`, `abandoned`, `retried`,
|
|
|
|
|
|
`failed`, `commented`, `flagged_confusing`, `flagged_helpful`,
|
|
|
|
|
|
`blocked_by_policy`, `escalated`, `accepted_recommendation`,
|
|
|
|
|
|
`rejected_recommendation`
|
|
|
|
|
|
|
|
|
|
|
|
**Annotation categories** (from schema defaults and IHF spec §6.6):
|
|
|
|
|
|
`friction`, `missing_capability`, `policy_conflict`, `trust_deficit`,
|
|
|
|
|
|
`accessibility`, `workflow_bottleneck`, `documentation_gap`,
|
|
|
|
|
|
`product_opportunity`, `governance_concern`
|
|
|
|
|
|
|
|
|
|
|
|
**Policy scopes** (from existing usage):
|
|
|
|
|
|
`internal`, `org-wide`, `external`, `regulatory`, `security`
|
|
|
|
|
|
|
|
|
|
|
|
3. Scaffold `TypeRegistriesController` (single controller for all four
|
|
|
|
|
|
registries, scoped by `registry` parameter):
|
|
|
|
|
|
- `index { registry }`: table of all entries for the given registry —
|
|
|
|
|
|
name, label, owner hub (or "Framework"), status badge, created at
|
|
|
|
|
|
- `show { registry, id }`: full detail including deprecated_in_favour_of
|
|
|
|
|
|
- `new { registry }` / `create`: add a new type. `owner_hub_id` defaults
|
|
|
|
|
|
to the current user's hub (if applicable). Framework-level entries
|
|
|
|
|
|
(owner_hub_id = NULL) are restricted to admin users.
|
|
|
|
|
|
- `DeprecateTypeAction { registry, id }`: sets `status = 'deprecated'`,
|
|
|
|
|
|
requires `deprecated_in_favour_of` to be set. No delete — names are
|
|
|
|
|
|
permanent.
|
|
|
|
|
|
- No edit of `name` after creation (names are permanent identifiers).
|
|
|
|
|
|
Label and description are editable.
|
|
|
|
|
|
|
|
|
|
|
|
4. Link "Type Registries" from global nav (admin section).
|
|
|
|
|
|
|
|
|
|
|
|
5. Framework-level type entries are pre-seeded by the migration and not
|
|
|
|
|
|
creatable via the UI without admin privileges. Hub-owned types are
|
|
|
|
|
|
created by any authenticated user.
|
|
|
|
|
|
|
|
|
|
|
|
**Exit criteria:** all four registry tables exist; framework vocabulary is
|
|
|
|
|
|
seeded; CRUD UI works; deprecation works; name edits are blocked; registry
|
|
|
|
|
|
index is accessible from nav.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### T04 — Registry-backed validation: type discriminators checked against registries in controllers
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: IHUB-WP-0009-T04
|
|
|
|
|
|
status: done
|
|
|
|
|
|
priority: high
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_task_id: "85882f5c-e52f-44b3-b68e-3f35e7baa9e7"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Wire the four type registries (T03) into the controllers that create records
|
|
|
|
|
|
using type discriminator fields. This transforms the registries from
|
|
|
|
|
|
documentation artifacts into enforced contracts.
|
|
|
|
|
|
|
|
|
|
|
|
Also adds `maturity` to the three existing contract tables so that
|
|
|
|
|
|
functional module stability is machine-readable.
|
|
|
|
|
|
|
|
|
|
|
|
**Controller validations to add:**
|
|
|
|
|
|
|
|
|
|
|
|
1. `WidgetsController` — `CreateWidgetAction` and `UpdateWidgetAction`:
|
|
|
|
|
|
- Validate `widget_type` exists in `widget_type_registry` with
|
|
|
|
|
|
`status = 'active'`
|
|
|
|
|
|
- Validate `policy_scope` exists in `policy_scope_registry` with
|
|
|
|
|
|
`status = 'active'`
|
|
|
|
|
|
- Error message format: "Widget type 'X' is not registered. Register it
|
|
|
|
|
|
in the Type Registry or choose an existing type."
|
|
|
|
|
|
- Widget `new` and `edit` forms: replace `widget_type` free-text input
|
|
|
|
|
|
with a `<select>` populated from `widget_type_registry` (active entries
|
|
|
|
|
|
first; framework-level types at top, hub-owned below a divider).
|
|
|
|
|
|
Same for `policy_scope`.
|
|
|
|
|
|
|
|
|
|
|
|
2. `InteractionEventsController` and `ApiInteractionEventsController` —
|
|
|
|
|
|
`CreateInteractionEventAction`:
|
|
|
|
|
|
- Validate `event_type` exists in `event_type_registry` with
|
|
|
|
|
|
`status = 'active'`
|
|
|
|
|
|
- The API controller returns HTTP 422 with
|
|
|
|
|
|
`{"error": "event_type 'X' not registered"}` if validation fails.
|
|
|
|
|
|
- New/create form and API docs: enumerate active event types.
|
|
|
|
|
|
|
|
|
|
|
|
3. `AnnotationsController` — `CreateAnnotationAction`:
|
|
|
|
|
|
- Validate `category` exists in `annotation_category_registry` with
|
|
|
|
|
|
`status = 'active'`
|
|
|
|
|
|
- Annotation `new` form: replace `category` text input with `<select>`.
|
|
|
|
|
|
|
|
|
|
|
|
4. `HubRoutingRulesController` — `CreateHubRoutingRuleAction` and
|
|
|
|
|
|
`UpdateHubRoutingRuleAction`:
|
|
|
|
|
|
- If `match_widget_type` is set, validate it exists in
|
|
|
|
|
|
`widget_type_registry`
|
|
|
|
|
|
- If `match_category` is set, validate it exists in
|
|
|
|
|
|
`annotation_category_registry`
|
|
|
|
|
|
|
|
|
|
|
|
5. Add a shared validation helper in `Application/Helper/TypeRegistry.hs`:
|
|
|
|
|
|
|
|
|
|
|
|
```haskell
|
|
|
|
|
|
-- Returns Right () if the name is registered and active; Left error otherwise.
|
|
|
|
|
|
validateRegisteredType ::
|
|
|
|
|
|
(?modelContext :: ModelContext) =>
|
|
|
|
|
|
Text -> Text -> IO (Either Text ())
|
|
|
|
|
|
validateRegisteredType registryTable name = ...
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Use this helper from all four controllers above.
|
|
|
|
|
|
|
|
|
|
|
|
**Maturity on existing contract tables:**
|
|
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
|
-- Add maturity tracking to existing contract tables (T04)
|
|
|
|
|
|
ALTER TABLE envelope_emission_contracts
|
|
|
|
|
|
ADD COLUMN maturity TEXT NOT NULL DEFAULT 'stable';
|
|
|
|
|
|
|
|
|
|
|
|
ALTER TABLE interaction_reporting_contracts
|
|
|
|
|
|
ADD COLUMN maturity TEXT NOT NULL DEFAULT 'stable';
|
|
|
|
|
|
|
|
|
|
|
|
ALTER TABLE widget_adapter_specs
|
|
|
|
|
|
ADD COLUMN maturity TEXT NOT NULL DEFAULT 'beta';
|
|
|
|
|
|
-- existing adapter specs are beta until explicitly promoted
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Valid values: `experimental | beta | stable | deprecated`
|
|
|
|
|
|
(consistent with `/contracts/functional/module-maturity-labels.md`).
|
|
|
|
|
|
|
|
|
|
|
|
Show maturity badge on the show views for each contract table.
|
|
|
|
|
|
|
|
|
|
|
|
**Exit criteria:** creating a widget with an unregistered `widget_type`
|
|
|
|
|
|
returns a validation error; creating an interaction event with an
|
|
|
|
|
|
unregistered `event_type` returns a validation error (web and API);
|
|
|
|
|
|
creating an annotation with an unregistered `category` returns a validation
|
|
|
|
|
|
error; widget and annotation forms render as select dropdowns; maturity
|
|
|
|
|
|
columns exist and render badges on contract show pages.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### T05 — HubCapabilityManifest: domain hub extension registration
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: IHUB-WP-0009-T05
|
|
|
|
|
|
status: done
|
|
|
|
|
|
priority: high
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_task_id: "1e5ad5db-e01f-41c5-9a81-759ab4dc88dd"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Introduces the GAAF Extensions layer: a formal mechanism for domain hubs to
|
|
|
|
|
|
declare the vocabulary they contribute to the framework. This is the central
|
|
|
|
|
|
artifact for the extension registration goal. Phase 10's Hub Registry will
|
|
|
|
|
|
build its public-facing UI directly on top of this table.
|
|
|
|
|
|
|
|
|
|
|
|
1. Schema:
|
|
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
|
-- HubCapabilityManifest: a domain hub's declaration of the types it
|
|
|
|
|
|
-- introduces and the capabilities it governs.
|
|
|
|
|
|
CREATE TABLE hub_capability_manifests (
|
|
|
|
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
|
|
|
|
hub_id UUID NOT NULL UNIQUE REFERENCES hubs(id),
|
|
|
|
|
|
manifest_version TEXT NOT NULL DEFAULT '1.0',
|
|
|
|
|
|
-- protocol version of the manifest format, not the hub's content version
|
|
|
|
|
|
declared_widget_types JSONB NOT NULL DEFAULT '[]',
|
|
|
|
|
|
-- array of type names referencing widget_type_registry
|
|
|
|
|
|
declared_event_types JSONB NOT NULL DEFAULT '[]',
|
|
|
|
|
|
declared_annotation_categories JSONB NOT NULL DEFAULT '[]',
|
|
|
|
|
|
declared_policy_scopes JSONB NOT NULL DEFAULT '[]',
|
|
|
|
|
|
capability_description TEXT,
|
|
|
|
|
|
-- human-readable summary of what this hub governs
|
|
|
|
|
|
contact TEXT,
|
|
|
|
|
|
-- team / person responsible for this hub's vocabulary
|
|
|
|
|
|
status TEXT NOT NULL DEFAULT 'draft',
|
|
|
|
|
|
-- 'draft' | 'active' | 'retired'
|
|
|
|
|
|
activated_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
|
|
|
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX hub_capability_manifests_hub_id_idx
|
|
|
|
|
|
ON hub_capability_manifests (hub_id);
|
|
|
|
|
|
CREATE INDEX hub_capability_manifests_status_idx
|
|
|
|
|
|
ON hub_capability_manifests (status);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
2. Activation semantics (the critical business logic):
|
|
|
|
|
|
On `ActivateManifestAction { hubCapabilityManifestId }`:
|
|
|
|
|
|
- For each name in `declared_widget_types`: insert into
|
|
|
|
|
|
`widget_type_registry (name, owner_hub_id)` if not already present.
|
|
|
|
|
|
If the name exists with a different `owner_hub_id`, return a validation
|
|
|
|
|
|
error: "Type 'X' is already owned by hub Y. Coordinate with that hub
|
|
|
|
|
|
to share or rename."
|
|
|
|
|
|
- Same for `declared_event_types`, `declared_annotation_categories`,
|
|
|
|
|
|
`declared_policy_scopes`.
|
|
|
|
|
|
- Set `status = 'active'`, `activated_at = now()`.
|
|
|
|
|
|
- Once active, `declared_*` arrays are read-only. To add new types, the
|
|
|
|
|
|
hub operator amends the manifest: creates a new `draft` record
|
|
|
|
|
|
(the unique constraint is per `hub_id`, so the active record must be
|
|
|
|
|
|
retired first) or the update goes via a `DraftAmendmentAction` that
|
|
|
|
|
|
merges new types into the active manifest with a review step.
|
|
|
|
|
|
- A hub with `hub_kind = 'domain'` should have an active manifest before
|
|
|
|
|
|
it creates any hub-owned type registry entries. This is enforced as a
|
|
|
|
|
|
warning (not a hard block) in the activation flow.
|
|
|
|
|
|
|
|
|
|
|
|
3. Scaffold `HubCapabilityManifestsController`:
|
|
|
|
|
|
- `index`: table of all manifests — hub name, kind badge, status badge,
|
|
|
|
|
|
declared type counts (widget / event / category / policy), activated at
|
|
|
|
|
|
- `show { id }`: full detail — hub info, all declared type arrays with
|
|
|
|
|
|
links to their registry entries, activation history, contact
|
|
|
|
|
|
- `new { hubId }` / `create`: creates a draft manifest for a hub.
|
|
|
|
|
|
One manifest per hub (unique constraint); if a draft exists, redirect
|
|
|
|
|
|
to `edit`.
|
|
|
|
|
|
- `edit` / `update`: edit draft manifest fields. Active manifests are
|
|
|
|
|
|
read-only except via `DraftAmendmentAction`.
|
|
|
|
|
|
- `ActivateManifestAction { id }`: runs the activation workflow above.
|
|
|
|
|
|
- `RetireManifestAction { id }`: sets `status = 'retired'`. The hub's
|
|
|
|
|
|
types remain in the registry but the manifest is no longer current.
|
|
|
|
|
|
|
|
|
|
|
|
4. Hub show page: add "Capability Manifest" section — status badge (No
|
|
|
|
|
|
manifest / Draft / Active / Retired), declared type summary, link to
|
|
|
|
|
|
manifest show page, "Register Capabilities" button if no active manifest.
|
|
|
|
|
|
|
|
|
|
|
|
5. Link "Extensions" from global nav (lists all active manifests).
|
|
|
|
|
|
|
|
|
|
|
|
**Exit criteria:** manifest can be created in draft; activation registers all
|
|
|
|
|
|
declared types into registries; name conflict during activation returns an
|
|
|
|
|
|
error; activated manifest is read-only on declared types; hub show page
|
|
|
|
|
|
displays manifest status; extensions nav entry renders all active manifests.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### T06 — Functional module maturity documentation and domain hub extension guide
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: IHUB-WP-0009-T06
|
|
|
|
|
|
status: done
|
|
|
|
|
|
priority: medium
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_task_id: "dbe749b0-0ac2-437f-9ef7-d119b5b120dd"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Documentation tasks that complete the GAAF Functional and Extensions layer
|
|
|
|
|
|
requirements. No schema changes.
|
|
|
|
|
|
|
|
|
|
|
|
1. Create `docs/functional-modules.md` — the authoritative maturity register
|
|
|
|
|
|
for all IHF functional modules:
|
|
|
|
|
|
|
|
|
|
|
|
| Module | Phase introduced | Maturity | Stability guarantee | Deprecation policy |
|
|
|
|
|
|
|--------|-----------------|----------|--------------------|--------------------|
|
|
|
|
|
|
| RequirementCandidate lifecycle | Phase 2 | Stable | Schema and controller API frozen | Major version only |
|
|
|
|
|
|
| DecisionRecord + governance ledger | Phase 3 | Stable | Schema and controller API frozen | Major version only |
|
|
|
|
|
|
| DeploymentRecord + OutcomeSignal | Phase 4 | Stable | Append-only invariant permanent | Major version only |
|
|
|
|
|
|
| AgentProposal + review workflow | Phase 5 | Beta | Core fields stable; confidence model may extend | Minor version notice |
|
|
|
|
|
|
| Cross-framework adapter contracts | Phase 6 | Stable | EnvelopeEmissionContract v1.0 immutable | Superseding contract only |
|
|
|
|
|
|
| FrictionScore + BottleneckRecord | Phase 7 | Beta | Computation algorithm may improve | Minor version notice |
|
|
|
|
|
|
| HubHealthSnapshot | Phase 7 | Beta | Snapshot schema stable; score formula may change | Minor version notice |
|
|
|
|
|
|
| CrossHubPropagation | Phase 7 | Experimental | Pattern detection logic evolving | No notice |
|
|
|
|
|
|
| WidgetOwnership + routing | Phase 8 | Stable | Ownership audit pattern permanent | Major version only |
|
|
|
|
|
|
| FederatedPolicyOverlay | Phase 8 | Beta | Activation immutability permanent; scope model may extend | Minor version notice |
|
|
|
|
|
|
| StewardshipRole | Phase 8 | Stable | Point-in-time audit pattern permanent | Major version only |
|
|
|
|
|
|
| ArchiveRecord + lineage inspector | Phase 8 | Beta | Soft-delete pattern stable; lineage query may deepen | Minor version notice |
|
|
|
|
|
|
| Type registries (this workplan) | GAAF | Beta | Schema stable; seed vocabulary may expand | Additive only |
|
|
|
|
|
|
| HubCapabilityManifest (this workplan) | GAAF | Beta | Activation semantics stable; manifest protocol may version | Minor version notice |
|
|
|
|
|
|
|
|
|
|
|
|
For each module: also document known limitations and what is NOT
|
|
|
|
|
|
guaranteed.
|
|
|
|
|
|
|
|
|
|
|
|
2. Create `docs/domain-hub-extension-guide.md` — the integration guide for
|
|
|
|
|
|
developers building a new domain hub (dev-hub, ops-hub, etc.):
|
|
|
|
|
|
|
|
|
|
|
|
Sections:
|
|
|
|
|
|
- **What inter-hub provides** — the framework services a domain hub
|
|
|
|
|
|
inherits without any setup (event capture, annotation, requirements,
|
|
|
|
|
|
governance, AI assistance, observability, federation)
|
|
|
|
|
|
- **Extension registration in three steps**:
|
|
|
|
|
|
1. Create a hub row with `hub_kind = 'domain'`
|
|
|
|
|
|
2. Create a `HubCapabilityManifest` in draft — declare widget types,
|
|
|
|
|
|
event types, annotation categories, policy scopes your domain
|
|
|
|
|
|
introduces
|
|
|
|
|
|
3. Activate the manifest — your types are now registered and validated
|
|
|
|
|
|
by the framework
|
|
|
|
|
|
- **Naming your types** — conventions: lowercase-hyphenated, prefixed
|
|
|
|
|
|
with domain shortcode where collision-prone (e.g. `dev-pipeline-run`,
|
|
|
|
|
|
`fin-budget-alert`, `sec-vuln-widget`). Framework-level types have no
|
|
|
|
|
|
prefix.
|
|
|
|
|
|
- **Using framework-level types** — no registration needed; any active
|
|
|
|
|
|
framework type is available to all hubs
|
|
|
|
|
|
- **Cross-hub routing** — how to configure `HubRoutingRule` entries so
|
|
|
|
|
|
cross-domain candidates route correctly to your hub
|
|
|
|
|
|
- **What changes between upgrades** — how to interpret the maturity
|
|
|
|
|
|
labels; Stable = safe to depend on; Beta = upgrade-aware; Experimental
|
|
|
|
|
|
= internal use only
|
|
|
|
|
|
- **FAQ**: Can two hubs declare the same type name? (No — activate order
|
|
|
|
|
|
determines ownership; coordinate with the owning hub to share.) Can a
|
|
|
|
|
|
type be renamed? (No — deprecated and replaced by a new name.) Can a
|
|
|
|
|
|
hub retire its manifest? (Yes — its types remain in registries but are
|
|
|
|
|
|
orphaned; reassign ownership or deprecate them.)
|
|
|
|
|
|
|
|
|
|
|
|
**Exit criteria:** `docs/functional-modules.md` exists with all modules
|
|
|
|
|
|
listed; `docs/domain-hub-extension-guide.md` exists with all three
|
|
|
|
|
|
registration steps and naming conventions covered.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### T07 — Architectural fitness functions in CI
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: IHUB-WP-0009-T07
|
|
|
|
|
|
status: done
|
|
|
|
|
|
priority: medium
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_task_id: "09109092-c1ca-48ba-b9b6-f4bc3d747910"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Implements the GAAF §8 requirement for automated architectural verification.
|
|
|
|
|
|
Adds a `Test/Architecture/` test module that runs as part of the standard
|
|
|
|
|
|
`test` command.
|
|
|
|
|
|
|
|
|
|
|
|
1. Create `Test/Architecture/LayerBoundarySpec.hs`:
|
|
|
|
|
|
|
|
|
|
|
|
**Test 1 — Core immutability contract presence**:
|
|
|
|
|
|
Assert that `Application/Schema.sql` contains the four trigger names that
|
|
|
|
|
|
enforce append-only semantics:
|
|
|
|
|
|
- `interaction_events_no_update`
|
|
|
|
|
|
- `interaction_events_no_delete`
|
|
|
|
|
|
- `outcome_signals_no_update`
|
|
|
|
|
|
- `outcome_signals_no_delete`
|
|
|
|
|
|
Failure message: "Core append-only invariant trigger missing from schema."
|
|
|
|
|
|
|
|
|
|
|
|
**Test 2 — Contract artifact presence**:
|
|
|
|
|
|
Assert that the following files exist (filesystem check):
|
|
|
|
|
|
- `/contracts/README.md`
|
|
|
|
|
|
- `/contracts/core/widget-envelope-v1.md`
|
|
|
|
|
|
- `/contracts/core/append-only-events-v1.md`
|
|
|
|
|
|
- `ARCHITECTURE-LAYERS.md`
|
|
|
|
|
|
Failure message: "GAAF contract artifact missing: {path}. See
|
|
|
|
|
|
ARCHITECTURE-LAYERS.md §Compliance."
|
|
|
|
|
|
|
|
|
|
|
|
**Test 3 — Type registry non-empty**:
|
|
|
|
|
|
Query `widget_type_registry`, `event_type_registry`,
|
|
|
|
|
|
`annotation_category_registry`, `policy_scope_registry`. Assert each
|
|
|
|
|
|
table has ≥1 active entry.
|
|
|
|
|
|
Failure message: "Type registry {table} has no active entries. Seed the
|
|
|
|
|
|
framework vocabulary before running tests."
|
|
|
|
|
|
|
|
|
|
|
|
**Test 4 — No bare TEXT type discriminators in new migrations**:
|
|
|
|
|
|
Read `Application/Schema.sql`. For any column named `widget_type`,
|
|
|
|
|
|
`event_type`, `category`, or `policy_scope` added after a specific marker
|
|
|
|
|
|
comment `-- GAAF: type registries enforced from here`, assert the column
|
|
|
|
|
|
definition includes a `REFERENCES` or `CHECK` constraint.
|
|
|
|
|
|
Failure message: "Column {col} in {table} uses bare TEXT for a type
|
|
|
|
|
|
discriminator. Reference a registry table or add a CHECK constraint."
|
|
|
|
|
|
|
|
|
|
|
|
**Test 5 — Domain hub manifest coverage** (warning, not failure):
|
|
|
|
|
|
Query all `hubs` rows with `hub_kind = 'domain'`. For each, check that a
|
|
|
|
|
|
`hub_capability_manifests` record exists with `status = 'active'`.
|
|
|
|
|
|
Log a warning (not a test failure): "Domain hub '{slug}' has no active
|
|
|
|
|
|
capability manifest. Register its types via the Extension Registry before
|
|
|
|
|
|
adding hub-owned type discriminators."
|
|
|
|
|
|
|
|
|
|
|
|
2. Register `Test/Architecture/LayerBoundarySpec.hs` in the test suite
|
|
|
|
|
|
(`Test/Main.hs`).
|
|
|
|
|
|
|
|
|
|
|
|
3. Add marker comment to `Application/Schema.sql` after the last Phase 8
|
|
|
|
|
|
migration block:
|
|
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
|
-- GAAF: type registries enforced from here (IHUB-WP-0009)
|
|
|
|
|
|
-- All new type discriminator columns (widget_type, event_type, category,
|
|
|
|
|
|
-- policy_scope) must reference a registry table or carry a CHECK constraint.
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Exit criteria:** `test` includes the architecture spec; Tests 1–3 pass
|
|
|
|
|
|
against a fresh database with seed data; Test 4 passes against the current
|
|
|
|
|
|
schema; Test 5 produces no warnings for a DB with a seeded framework hub and
|
|
|
|
|
|
no domain hubs yet.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### T08 — GAAF gate: scorecard, consistency, documentation updates
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: IHUB-WP-0009-T08
|
|
|
|
|
|
status: done
|
|
|
|
|
|
priority: high
|
2026-03-31 23:19:31 +02:00
|
|
|
|
state_hub_task_id: "7a7dfc5b-77da-4658-b1ce-971518fb8cc8"
|
feat(WP-0009): IHF GAAF Compliance Foundation — type registries, extension manifests, architectural contracts
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins.
- TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest)
- HubCapabilityManifest entity with validation and registry linkage
- ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts
- Alembic migration 1743724800, fitness tests (Test/Architecture/)
- GAAF spec, Operational Architecture spec, domain hub extension guide
- Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types
state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 21:17:39 +00:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Closes the workplan, validates GAAF compliance targets, and prepares the
|
|
|
|
|
|
repository for Phase 9.
|
|
|
|
|
|
|
|
|
|
|
|
1. **Update `ARCHITECTURE-LAYERS.md` scorecard** with post-workplan scores.
|
|
|
|
|
|
Fill in the actual weighted total and compare against targets from this
|
|
|
|
|
|
workplan's Background section. Document any criteria that remain below
|
|
|
|
|
|
target and why.
|
|
|
|
|
|
|
|
|
|
|
|
2. **Update `SCOPE.md`**:
|
|
|
|
|
|
- Current state: add "GAAF compliance foundation complete (IHUB-WP-0009);
|
|
|
|
|
|
type registries, extension manifests, architectural contracts, and
|
|
|
|
|
|
fitness functions in place"
|
|
|
|
|
|
- Upstream dependencies: update hub-core reference to note that
|
|
|
|
|
|
`HubCapabilityManifest` in inter-hub now provides the DB-side of
|
|
|
|
|
|
capability registration; hub-core (when implemented) will provide the
|
|
|
|
|
|
shared Haskell library that domain hubs compile against.
|
|
|
|
|
|
|
|
|
|
|
|
3. **Update `CLAUDE.md`**:
|
|
|
|
|
|
- Active workplan: change from IHUB-WP-0005 to IHUB-WP-0010 (Phase 9)
|
|
|
|
|
|
- Add "GAAF compliance" context block noting that type registries must be
|
|
|
|
|
|
kept seeded and all new type discriminator columns must reference a
|
|
|
|
|
|
registry
|
|
|
|
|
|
- Add reference to `docs/domain-hub-extension-guide.md` as the entry
|
|
|
|
|
|
point for new domain hub developers
|
|
|
|
|
|
|
|
|
|
|
|
4. **State Hub consistency sync**:
|
|
|
|
|
|
`check_repo_consistency(repo_slug="inter-hub", fix=True)`
|
|
|
|
|
|
|
|
|
|
|
|
5. **Integration tests** (`Test/`):
|
|
|
|
|
|
- `HubCapabilityManifest` create in draft + activate + verify type
|
|
|
|
|
|
auto-registration in registries
|
|
|
|
|
|
- Activation conflict: two hubs declaring the same type name → second
|
|
|
|
|
|
activation returns a conflict error
|
|
|
|
|
|
- Widget create with unregistered type → validation error
|
|
|
|
|
|
- Widget create with registered type → success
|
|
|
|
|
|
- InteractionEvent create via API with unregistered event_type → 422
|
|
|
|
|
|
- Annotation create with unregistered category → validation error
|
|
|
|
|
|
- Architecture spec tests pass (T07)
|
|
|
|
|
|
|
|
|
|
|
|
6. **Smoke test checklist**:
|
|
|
|
|
|
- Create a hub with `hub_kind = 'domain'`; verify kind badge
|
|
|
|
|
|
- Open Type Registries nav; verify all four registries have seeded entries
|
|
|
|
|
|
- Create a widget with an unregistered `widget_type`; verify error
|
|
|
|
|
|
- Register a new widget type via the Type Registry admin UI; retry widget
|
|
|
|
|
|
creation → success
|
|
|
|
|
|
- Create a `HubCapabilityManifest` for the domain hub in draft; add two
|
|
|
|
|
|
custom widget types; activate → verify types appear in registry with
|
|
|
|
|
|
correct `owner_hub_id`
|
|
|
|
|
|
- Attempt to activate a second hub's manifest using the same type name →
|
|
|
|
|
|
verify conflict error
|
|
|
|
|
|
- Open Extensions nav; verify active manifest is listed
|
|
|
|
|
|
- Hub show page: verify "Capability Manifest" section shows active status
|
|
|
|
|
|
- Run `test`; verify architecture spec tests pass with no warnings
|
|
|
|
|
|
|
|
|
|
|
|
**Exit criteria:** all integration tests pass; smoke test completed without
|
|
|
|
|
|
errors; `ARCHITECTURE-LAYERS.md` scorecard shows weighted total ≥3.1;
|
|
|
|
|
|
`SCOPE.md` and `CLAUDE.md` updated; State Hub consistency sync reports no
|
|
|
|
|
|
errors.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Task Dependencies
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
T01 (contracts scaffold) ──→ T08 (gate reads scorecard)
|
|
|
|
|
|
T02 (hub_kind) ──→ T05 (manifest references hub_kind)
|
|
|
|
|
|
──→ T07 (fitness test 5 queries hub_kind)
|
|
|
|
|
|
T03 (type registries) ──→ T04 (validation reads registries)
|
|
|
|
|
|
──→ T05 (manifest declares types into registries)
|
|
|
|
|
|
──→ T07 (fitness tests 3 and 4 check registries)
|
|
|
|
|
|
T04 (validation) ──→ T08 (gate integration tests validate creation paths)
|
|
|
|
|
|
T05 (manifest) ──→ T06 (extension guide documents manifest workflow)
|
|
|
|
|
|
──→ T08 (gate integration tests activate manifests)
|
|
|
|
|
|
T06 (maturity docs) ──→ T08 (gate checks docs exist)
|
|
|
|
|
|
T07 (fitness functions) ──→ T08 (gate runs architecture spec)
|
|
|
|
|
|
All T01–T07 ──→ T08 (gate)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Parallelisable: T01 (documentation only) can proceed in parallel with T02–T07.
|
|
|
|
|
|
T02 and T03 are independent of each other and can proceed in parallel.
|
|
|
|
|
|
T04 requires T03 complete. T05 requires T02 and T03 complete. T06 requires
|
|
|
|
|
|
T05 complete. T07 requires T03 complete.
|
|
|
|
|
|
|
|
|
|
|
|
## Phase 9 Readiness Checklist
|
|
|
|
|
|
|
|
|
|
|
|
The following must be true before IHUB-WP-0010 (Phase 9) begins:
|
|
|
|
|
|
|
|
|
|
|
|
- [ ] All four type registries are seeded with framework vocabulary
|
|
|
|
|
|
- [ ] All type discriminator TEXT columns are validated against registries in controllers
|
|
|
|
|
|
- [ ] `HubCapabilityManifest` table exists and the activation workflow is operational
|
|
|
|
|
|
- [ ] `/contracts/` contains at minimum `core/widget-envelope-v1.md`,
|
|
|
|
|
|
`core/append-only-events-v1.md`, `functional/interaction-reporting-v1.md`,
|
|
|
|
|
|
and `extensions/hub-capability-manifest-v1.md`
|
|
|
|
|
|
- [ ] `ARCHITECTURE-LAYERS.md` exists and is current
|
|
|
|
|
|
- [ ] Architecture fitness functions pass in CI
|
|
|
|
|
|
- [ ] `ARCHITECTURE-LAYERS.md` weighted scorecard is ≥3.1
|
|
|
|
|
|
|
|
|
|
|
|
## Notes
|
|
|
|
|
|
|
|
|
|
|
|
- **Type names are permanent.** Once a name enters a registry (whether via
|
|
|
|
|
|
seed or manifest activation), it cannot be deleted — only deprecated. Build
|
|
|
|
|
|
the seeded vocabulary carefully. Domain hub names should use a
|
|
|
|
|
|
domain-shortcode prefix where collision is likely (see extension guide).
|
|
|
|
|
|
|
|
|
|
|
|
- **Manifests are the domain hub's identity contract.** A domain hub that has
|
|
|
|
|
|
not activated a manifest is an unregistered participant. It can still create
|
|
|
|
|
|
hubs and widgets (the framework permits it) but its types are not validated,
|
|
|
|
|
|
not namespaced, and not discoverable in Phase 10's marketplace.
|
|
|
|
|
|
|
|
|
|
|
|
- **This workplan does not split the shared PostgreSQL schema.** Domain
|
|
|
|
|
|
isolation at the database level (separate schemas or RLS) is a Phase 9+
|
|
|
|
|
|
concern. This workplan establishes the vocabulary-level isolation needed
|
|
|
|
|
|
before physical isolation decisions are made.
|
|
|
|
|
|
|
|
|
|
|
|
- **hub-core remains a future concern.** The Haskell shared library for domain
|
|
|
|
|
|
hub bootstrapping is planned but not blocked on this workplan.
|
|
|
|
|
|
`HubCapabilityManifest` provides the DB-side registration contract.
|
|
|
|
|
|
hub-core, when implemented, will provide the compile-time Haskell types
|
|
|
|
|
|
that correspond to a hub's declared vocabulary. The two are complementary,
|
|
|
|
|
|
not redundant.
|