Files
inter-hub/contracts/core/widget-envelope-v1.md
Bernd Worsch b5d73aa18b
Some checks failed
Test / test (push) Has been cancelled
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

89 lines
3.2 KiB
Markdown

# 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
1. `data-widget-id` must be a valid UUID. Non-UUID values cause the envelope to
be treated as malformed.
2. `data-hub-id` must match the `slug` of a registered hub in the `hubs` table.
Unknown hub slugs are logged but do not block event capture.
3. `data-widget-type` must exist in `widget_type_registry` with `status = 'active'`
at the time of capture. Events from deprecated types are accepted but flagged.
4. `data-view-context` has no format enforcement in v1.0 beyond non-empty.
---
## Failure Mode
- **Missing required attribute**: the capture pipeline logs a
`malformed_envelope` event with the missing attribute names in `metadata`.
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_type` validated against `widget_type_registry`
on create/update in `WidgetsController`
- Client-side: `static/ihf-annotation-launcher.js` reads `data-widget-id` and
`data-hub-id` from the nearest ancestor with these attributes
- Server-side envelope rendering: `widgetEnvelope` HSX helper in
`Application/Helper/View.hs`