/** * manage.html entry (v0.10) — CLIENT-SIDE preview grid. Server previews die under E2E; the * key-holding browser decrypts a ciphertext replay and renders read-only xterms. No inline script. * * The §4.4 replay crypto is imported from relay-e2e (P4) and injected into the grid — cited * verbatim, never re-implemented. * * INTEGRATION POINT: `loadReplay` must fetch the host's ciphertext ring-buffer replay + the §4.5 * `hostContentSecret` (delivered via P5 after auth/step-up). Those endpoints are owned by P5/P1/P3; * this glue wires the shape and throws until they land, so a card shows "unavailable" rather than a * fabricated screen. */ import { deriveContentKey, openReplayCiphertext } from 'relay-e2e' import { readConfig } from '../config' import { createApiClient } from '../api-client' import { mountPreviewGrid } from '../preview-grid' import type { ReplaySource } from '../preview-client' /** * FIX 3b / F6 placeholder epoch. The real per-generation `epoch` MUST be served by P1/P2 alongside * the ciphertext ring buffer (the agent stamps a fresh epoch each time it reconstructs the sealer and * resets seq to 0). This constant only keeps the `ReplaySource` shape explicit until those endpoints * land; the stub still throws, so no frame is ever decrypted under it. */ const PLACEHOLDER_EPOCH = 'PENDING_P1_P2_EPOCH' async function loadReplay( _hostId: string, ): Promise<{ replay: ReplaySource; hostContentSecret: Uint8Array }> { // TODO(P5/P1/P2): fetch ciphertext replay + hostContentSecret (post auth/step-up) AND the real // per-generation `epoch` (FIX 3b / F6) that the frames were sealed under. Until then the shape is: // { replay: { sessionId, alg, epoch: PLACEHOLDER_EPOCH, frames }, hostContentSecret } // Not yet available → throw so a card shows "unavailable" rather than a fabricated screen. void PLACEHOLDER_EPOCH throw new Error('replay source not yet wired (pending P5/P1/P2 endpoints)') } function boot(): void { const cfg = readConfig(window.location) const root = document.getElementById('manage') if (!root) return const api = createApiClient(cfg) mountPreviewGrid(root, api, loadReplay, { deriveContentKey, openReplayCiphertext }) } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot) } else { boot() }