generated from coulomb/repo-seed
- 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>
1.9 KiB
1.9 KiB
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
import Application.Helper.View (widgetEnvelope)
-- In any view:
widgetEnvelope widget [hsx|
<button class="...">Click me</button>
|]
Emitted 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
- Every interactive hub element that participates in governance must be wrapped.
- The
data-widget-idis the capture key — the event capture endpoint uses it aswidget_id. - Do not add or remove
data-*attributes without updating both this convention doc and the event capture client script. - The "Annotate" control is always rendered. It links to the full annotation thread for the widget.