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>
3.2 KiB
Widget Envelope Contract
Name: widget-envelope Version: 1.0 Date: 2026-03-31 Status: Active Layer: Core Immutable: Yes — changes require v1.1 with backwards-compatible additions only
Purpose
The Widget Envelope is the metadata boundary attached to every rendered widget. It enables the IHF capture pipeline to attribute any DOM event to a governed widget without coupling to the widget's implementation.
Any UI technology that emits the required data-* attributes on a DOM element
is a first-class IHF participant.
Required Attributes
Every widget root element MUST carry all of the following:
| Attribute | Format | Example |
|---|---|---|
data-widget-id |
UUID (RFC 4122) | data-widget-id="550e8400-e29b-41d4-a716-446655440000" |
data-hub-id |
Registered hub slug (TEXT) | data-hub-id="ops-hub" |
data-view-context |
Dot-separated path (TEXT) | data-view-context="ops.incidents.list" |
data-widget-type |
Registered name from widget_type_registry |
data-widget-type="chart" |
Optional Attributes
| Attribute | Format | Notes |
|---|---|---|
data-capability-ref |
TEXT | Links widget to a hub capability |
data-policy-scope |
Registered name from policy_scope_registry |
Defaults to internal if absent |
data-widget-version |
Integer as string | Current widget version number |
data-experiment-variant |
TEXT | A/B experiment identifier |
data-requirements-thread-ref |
UUID | Links to an open AnnotationThread |
Validation Rules
data-widget-idmust be a valid UUID. Non-UUID values cause the envelope to be treated as malformed.data-hub-idmust match theslugof a registered hub in thehubstable. Unknown hub slugs are logged but do not block event capture.data-widget-typemust exist inwidget_type_registrywithstatus = 'active'at the time of capture. Events from deprecated types are accepted but flagged.data-view-contexthas no format enforcement in v1.0 beyond non-empty.
Failure Mode
- Missing required attribute: the capture pipeline logs a
malformed_envelopeevent with the missing attribute names inmetadata. The original interaction event is not stored. This is fail-safe, not fail-loud — the UI does not crash. - Unknown hub slug: event is stored with
metadata.hub_warning = "unknown_hub_slug". - Unregistered widget_type: event is stored with
metadata.type_warning = "unregistered_widget_type". No 422 is returned to the frontend (retroactive registration is possible).
Backwards Compatibility Rule
v1.0 is frozen. New optional attributes may be added in v1.1 without breaking existing implementations. Removing any attribute, or making an optional attribute required, requires a new major version (v2.0) with a migration window.
Implementation Reference
- Schema enforcement:
widgets.widget_typevalidated againstwidget_type_registryon create/update inWidgetsController - Client-side:
static/ihf-annotation-launcher.jsreadsdata-widget-idanddata-hub-idfrom the nearest ancestor with these attributes - Server-side envelope rendering:
widgetEnvelopeHSX helper inApplication/Helper/View.hs