Skip to content

feat(quickstart): end on the person's own Seal, in an offline viewer - #1566

Open
abrichr wants to merge 1 commit into
mainfrom
feat/quickstart-own-seal-offline
Open

abrichr wants to merge 1 commit into
mainfrom
feat/quickstart-own-seal-offline

Conversation

@abrichr

@abrichr abrichr commented Oct 25, 2026

Copy link
Copy Markdown
Member

openadapt quickstart now ends by opening the Seal of the run the person just did. It's one offline page built from the same code as openadapt.ai's Seal pages, and it uploads nothing.

This replaces #1437, where the code was reviewed and approved. It is the same code squashed into one commit on main. The one change is that the verifier test now derives its signing key at run time from sha256("openadapt-test-seal"), so no private key is committed and .gitleaksignore is unchanged from main.

What changes

  • packages/seal-view (@openadapt/seal-view, MIT) holds openadapt.ai's Seal page, extracted from OpenAdaptAI/openadapt-web#587 through 4da61c59:
    • What it draws: the step ring, the read-back table, the iris drawn from the digests, the replay synced with the step table, and the full program workbench, with a Seal card in its inspector and "Back to the Seal".
    • The tamper demo, and every check: offline Seals, run authorizations, Sigstore Rekor anchors, and RFC 3161 timestamps with their .tsr token file.
    • Host props: the site-specific parts (links, footer, live checks, how files load, workbench title and media) come in as props.
    • Any program: the rings read any program graph. When a run has no governed requirements, as in the quickstart, they use each step's own record checks.
    • Ed25519 everywhere: a pure-JS check covers browsers whose WebCrypto lacks Ed25519.
  • Offline viewer (dist/seal-viewer.html): one file built with Preact, with the program map and styles inlined. It is 212,474 bytes (68,660 gzipped) against a 262,144-byte budget. Its CSP allows no requests, so it works from file://. The launcher wheel ships it as openadapt/seal_view/viewer.html, which grows the wheel by about 70 KB compressed. openadapt.seal_view embeds a run's exact files in it.
  • Quickstart finale:
    • The stopped run is sealed too.
    • It writes run-1/seal.html and run-broken/seal.html and opens the first one when a display is available. It no longer opens the side-by-side page, which stays on the Details line.
    • It prints Your Seal: <path>, then See real Seals from OpenEMR runs: https://openadapt.ai/seals.
    • The page says it was "checked against your computer's Seal key", so a forwarded seal.html doesn't read as third-party proof. The receipt counts the stopped run's Seal once that Seal is written.
  • openadapt seal view RUN_DIR [--keys FILE] [--bundle DIR] [--no-open] writes and opens the page for any sealed run, or for each run in a folder of runs.

Tests

  • tests/test_seal_view.py uses a real quickstart run as its fixture and opens its pages from file:// in Chromium. It checks:

    • the real Seal is valid;
    • a tampered report fails (subject_mismatch), and so does a changed Seal (bad_signature);
    • a report changed on disk fails on open;
    • the stopped run replays to its stop, with the map following;
    • the Seal card works;
    • a Playwright request listener sees no requests.

    It also snapshots the viewer's size against its budget.

  • Package (vitest):

    • the checks and rings on the same run;
    • RFC 8032 section 7.1 TESTs 1-3 and the 7.3 Ed25519ph vector (public keys, messages and signatures only);
    • a Seal signed with a key derived at run time from a public label, through verifyLocalSeal with WebCrypto Ed25519 and with it switched off;
    • a published OpenEMR Seal's real Rekor entry and Sigstore timestamp, checked offline.
  • CI: a new seal-view job in packages.yml runs the unit tests, then build.mjs --check (the rebuilt viewer must equal the shipped copy and fit its budget), then the browser tests with the browser required.

Not in this PR

  • Recording: the real quickstart was recorded once in VHS and ends on the Seal lines. That take predates the fix that picks run 1's page (it showed run 3's), and the re-record and the browser half weren't made, so no recording is attached.
  • openadapt.ai: the website doesn't import the package yet; that's OpenAdaptAI/openadapt-web#591.

🤖 Generated with Claude Code

`openadapt quickstart` now ends by opening the Seal of the run the person
just did: one offline page built from the same code as openadapt.ai's Seal
pages, with nothing uploaded. The same code as #1437 (reviewed there),
squashed onto main, with the verifier's test key derived at run time instead
of committed.

- packages/seal-view (@openadapt/seal-view, MIT): openadapt.ai's Seal page
  (openadapt-web#587 through 4da61c59): the step ring, the read-back table,
  the iris drawn from the digests, the replay synced with the step table and
  the full program workbench (with a Seal card in its inspector), the tamper
  demo, and every check (offline Seals, run authorizations, Rekor anchors,
  RFC 3161 timestamps with their .tsr file). The site's parts come in as
  props; the rings read any program graph and fall back to each step's own
  record checks; a pure-JS Ed25519 check covers browsers without WebCrypto
  Ed25519.
- The offline viewer: one HTML file (Preact, the program map and styles
  inlined), 212,474 bytes (68,660 gzipped), budget 262,144, CSP allowing no
  requests. The launcher ships it as openadapt/seal_view/viewer.html;
  openadapt.seal_view embeds a run's exact files in it.
- Quickstart finale: seals the stopped run too, writes run-1/seal.html and
  run-broken/seal.html, opens the first when a display is available, and
  prints "Your Seal: <path>" then the openadapt.ai/seals line. The page says
  it was checked against your computer's Seal key.
- `openadapt seal view RUN_DIR [--keys FILE] [--bundle DIR] [--no-open]`.
- Tests: a real quickstart run's pages from file:// in Chromium (valid,
  tampered, no requests), the viewer's size snapshot, RFC 8032 vectors
  (public keys and signatures only), a Seal signed with a key derived from
  sha256("openadapt-test-seal"), and a published OpenEMR Seal's Rekor entry
  and timestamp; a seal-view job in packages.yml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant