generated from coulomb/repo-seed
feat(T02-T11): IHF Phase 1 schema, controllers, views, and helpers
- Schema: hubs, widgets, widget_versions, interaction_events (append-only trigger), annotations, users — single migration file - Web layer: Types, Routes, FrontController with auth + AutoRefresh layout - Controllers: Hubs (CRUD), Widgets (CRUD + versioning), InteractionEvents (JSON capture, canonical event_type validation), Annotations (threaded, append-only) - Sessions controller for IHP auth - Views: Hubs (index/show/new/edit), Widgets (index/show/new/edit), Annotations (index/new), Sessions (login) - widgetEnvelope helper with full data-* governance attributes - Integration tests: Hub CRUD, Widget versioning, event capture, append-only guard, annotation threading, validation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
56
docs/widget-envelope-convention.md
Normal file
56
docs/widget-envelope-convention.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Widget Envelope Convention
|
||||
|
||||
Every rendered widget in inter-hub wraps its HSX in the `widgetEnvelope` helper
|
||||
from `Application.Helper.View`. This injects a stable set of `data-*` attributes
|
||||
that enable client-side event capture without coupling to implementation details.
|
||||
|
||||
## Usage
|
||||
|
||||
```haskell
|
||||
import Application.Helper.View (widgetEnvelope)
|
||||
|
||||
-- In any view:
|
||||
widgetEnvelope widget [hsx|
|
||||
<button class="...">Click me</button>
|
||||
|]
|
||||
```
|
||||
|
||||
## Emitted HTML
|
||||
|
||||
```html
|
||||
<div
|
||||
class="ihf-widget"
|
||||
data-widget-id="<uuid>"
|
||||
data-widget-type="chart"
|
||||
data-hub-id="<uuid>"
|
||||
data-capability-ref="pipeline.run"
|
||||
data-view-context="ops/dashboard"
|
||||
data-policy-scope="internal"
|
||||
data-widget-version="3"
|
||||
>
|
||||
<!-- inner content -->
|
||||
<div class="ihf-widget-controls">
|
||||
<a href="/widgets/<uuid>/annotations" class="ihf-annotate-btn">Annotate</a>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
| Attribute | Source | Purpose |
|
||||
|-----------|--------|---------|
|
||||
| `data-widget-id` | `widget.id` | Stable identity for event capture |
|
||||
| `data-widget-type` | `widget.widgetType` | Semantic role of the widget |
|
||||
| `data-hub-id` | `widget.hubId` | Which hub owns this widget |
|
||||
| `data-capability-ref` | `widget.capabilityRef` | Link to hub capability |
|
||||
| `data-view-context` | `widget.viewContext` | Logical location in the UI |
|
||||
| `data-policy-scope` | `widget.policyScope` | Governance policy boundary |
|
||||
| `data-widget-version` | `widget.version` | Version at render time |
|
||||
|
||||
## Rules
|
||||
|
||||
1. **Every interactive hub element** that participates in governance must be wrapped.
|
||||
2. The `data-widget-id` is the capture key — the event capture endpoint uses it as `widget_id`.
|
||||
3. Do not add or remove `data-*` attributes without updating both this convention doc and
|
||||
the event capture client script.
|
||||
4. The "Annotate" control is always rendered. It links to the full annotation thread for the widget.
|
||||
Reference in New Issue
Block a user