Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BvMSXH8VH2tMWXanb8SJdf
3.2 KiB
HUX client foundation integration contract
The WebUI image packages these files. Its server derives a matching
hux.webui_context.v1 only from the authenticated, persisted WebUI session,
the bounded server HUX_PROJECT_SOURCE, the trusted tenant slot, and the
router-asserted HUX subject. The browser bridge remains inert unless that
context is present and the same-origin capability endpoint advertises a
complete route set. It is versioned as hux.v1, contains no tenant-global
browser storage, and defaults to a hidden shell.
The router negotiation endpoint is GET /hux/v1/capabilities. A disabled
foundation returns 404. An enabled response is:
{
"schema": "hux.capabilities.v1",
"contract_version": "1.1.0",
"identity": {
"tenant_slot": "slot-3",
"subject": "usr_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"surface": "chat",
"trust": "relay"
},
"cards": [
{
"card": "HUX-11",
"flag": "hux.foundation",
"enabled": true,
"routes": ["/hux/v1/capabilities", "/hux/v1/context/bootstrap"]
}
],
"server": {}
}
The boot bridge reads opaque identity and scope only from S.session.hux_context.
That record must bind its webui_session_id to the loaded WebUI session. The
bridge compares it to the authenticated BFF capability identity before it
mounts anything. It must never pass a raw Keycloak subject, email, Telegram
identifier, or tenant ordinal. The client rejects an identity or surface
mismatch, unknown versions, cross-user objects, and cross-conversation
records. It does not use local/session storage.
Opaque IDs use a server-owned 32-byte key at HUX_CONTEXT_KEY_FILE, or
$HERMES_WEBUI_STATE_DIR/.hux-context-key by default. The file is created
before context is emitted and must remain an owner-only regular file. Chat and
Worker derive the same IDs with hux.context.id.v1; no browser value can
select the subject, slot, key, or default project source. The project source
defaults to profile:default when its server environment override is absent.
After capability negotiation, the bridge sends the exact server-derived scope
to POST /hux/v1/context/bootstrap with CSRF and an idempotency key. The HUX
service recomputes every ID from the shared key and creates or verifies the
project/conversation binding. The drawer is not created unless that response
matches the authenticated context exactly.
Feature extensions register an id, label, HUX flag, display order, and render
callback with HermesHuxShell.createShell(). The shell is hidden for a 404,
for an off foundation, or when no registered extension is enabled. Loading and
errors are accessible status regions; errors disclose no backend body. Event
adapters omit detail, evidence URIs, hashes, and tool payloads. Object
adapters return display metadata only. Feature code must fetch sensitive
details from its owning tenant-scoped endpoint after an explicit user action.
Scripts load in dependency order and the image service worker caches the same reviewed assets. No manifest or live HUX flag is changed by this browser bundle. A 404, missing server context, incomplete route advertisement, or session change destroys or suppresses the workspace.