2026-08-24 04:12:42 -03:00

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.