From b83d52860432126a5fd4a4edbf67e2bfe2925ba1 Mon Sep 17 00:00:00 2001 From: bordumb Date: Mon, 8 Jun 2026 23:37:46 +0100 Subject: [PATCH 1/7] feat(resolvers): add P-256 key extraction to did:key and CESR decoders Dispatch curve on the in-band tag (multicodec varint for did:key, derivation code for CESR), never on byte length. Ed25519 (0xED01 / D,B) stays 32 bytes; P-256 (0x8024 / 1AAJ,1AAI) returns 33-byte compressed SEC1. Adds base64url + multicodec helpers and explicit unsupported-tag errors. Mirrors Rust KeriPublicKey::parse. --- .flow/config.json | 5 ++ .flow/epics/fn-1.json | 13 ++++ .flow/meta.json | 4 ++ .flow/specs/fn-1.md | 95 ++++++++++++++++++++++++++ .flow/tasks/fn-1.1.json | 16 +++++ .flow/tasks/fn-1.1.md | 57 ++++++++++++++++ .flow/tasks/fn-1.2.json | 16 +++++ .flow/tasks/fn-1.2.md | 51 ++++++++++++++ .flow/tasks/fn-1.3.json | 16 +++++ .flow/tasks/fn-1.3.md | 52 ++++++++++++++ .flow/tasks/fn-1.4.json | 17 +++++ .flow/tasks/fn-1.4.md | 47 +++++++++++++ .flow/tasks/fn-1.5.json | 16 +++++ .flow/tasks/fn-1.5.md | 39 +++++++++++ .flow/tasks/fn-1.6.json | 24 +++++++ .flow/tasks/fn-1.6.md | 34 ++++++++++ src/resolvers/did-utils.ts | 109 ++++++++++++++++++++++-------- tests/resolvers/did-utils.test.ts | 35 +++++++++- 18 files changed, 613 insertions(+), 33 deletions(-) create mode 100644 .flow/config.json create mode 100644 .flow/epics/fn-1.json create mode 100644 .flow/meta.json create mode 100644 .flow/specs/fn-1.md create mode 100644 .flow/tasks/fn-1.1.json create mode 100644 .flow/tasks/fn-1.1.md create mode 100644 .flow/tasks/fn-1.2.json create mode 100644 .flow/tasks/fn-1.2.md create mode 100644 .flow/tasks/fn-1.3.json create mode 100644 .flow/tasks/fn-1.3.md create mode 100644 .flow/tasks/fn-1.4.json create mode 100644 .flow/tasks/fn-1.4.md create mode 100644 .flow/tasks/fn-1.5.json create mode 100644 .flow/tasks/fn-1.5.md create mode 100644 .flow/tasks/fn-1.6.json create mode 100644 .flow/tasks/fn-1.6.md diff --git a/.flow/config.json b/.flow/config.json new file mode 100644 index 0000000..3b584a9 --- /dev/null +++ b/.flow/config.json @@ -0,0 +1,5 @@ +{ + "memory": { + "enabled": false + } +} diff --git a/.flow/epics/fn-1.json b/.flow/epics/fn-1.json new file mode 100644 index 0000000..9e1e01d --- /dev/null +++ b/.flow/epics/fn-1.json @@ -0,0 +1,13 @@ +{ + "branch_name": "fn-152-c1", + "created_at": "2026-06-08T22:04:26.033805Z", + "depends_on_epics": [], + "id": "fn-1", + "next_task": 1, + "plan_review_status": "unknown", + "plan_reviewed_at": null, + "spec_path": ".flow/specs/fn-1.md", + "status": "open", + "title": "Stream C \u2014 auths-verify-widget GTM: resolver-doc truth + embed/SRI/playground", + "updated_at": "2026-06-08T22:36:13.268099Z" +} diff --git a/.flow/meta.json b/.flow/meta.json new file mode 100644 index 0000000..3c4f647 --- /dev/null +++ b/.flow/meta.json @@ -0,0 +1,4 @@ +{ + "next_epic": 1, + "schema_version": 2 +} diff --git a/.flow/specs/fn-1.md b/.flow/specs/fn-1.md new file mode 100644 index 0000000..88b742f --- /dev/null +++ b/.flow/specs/fn-1.md @@ -0,0 +1,95 @@ +# Stream C — `auths-verify-widget` GTM + +> Source: `roadmap/go_to_market/go_to_market.md` → "Stream C — `auths-verify-widget` (the most launch-ready artifact)". +> Roadmap task IDs preserved for traceability: **G0.5 / G4.1 (D-5)**, **G4.4**, **G4.5**. + +## Overview + +`@auths-dev/verify@0.3.0` is the most launch-ready artifact in the GTM plan: live on unpkg *and* jsDelivr, WASM base64-inlined into a single file so the one-line ` +``` +No version pin (implicit `@latest`), no `integrity=`, no `crossorigin`. The full build base64-inlines WASM into the single `dist/auths-verify.mjs` (671 KB) — so **one sha384 covers the entire runtime**, the SRI-friendly path. The slim build (`dist/slim/`) is ambiguous: no separate `.wasm` is emitted and it's the same size as full (see Investigation). + +## Changes + +1. **Investigation (do first):** determine what the slim build actually ships for WASM (`package.json:25` `build:slim` runs `vite build --mode slim` *without* `INLINE_WASM`; `vite.config.ts:7-32` inline plugin; `verifier-bridge.ts:11,22-44` sentinel + `wasm-url` override). Confirm whether slim fetches a separate `.wasm` at runtime. Record the finding in the task notes. +2. **README CDN guidance** — replace the bare snippet with a **pinned + SRI** one: + ```html + + ``` + - Add a short subsection explaining: pin an exact version (SRI + `@latest` breaks on every release); `crossorigin="anonymous"` is **required** or the browser blocks the cross-origin script; jsDelivr equivalent + that it can show the SRI hash for you. + - State the **full-vs-slim** SRI truth from the investigation: recommend the **full** inlined bundle for SRI users (one hash = everything); document slim honestly (if it fetches a sibling `.wasm`, the ` + +``` + +> **Pin a version with SRI — never `@latest`.** The `integrity` hash is +> byte-exact, so it only validates against an immutable, version-pinned URL +> (`@0.3.0`). A moving `@latest` URL changes bytes on every release and would +> break the hash — and the badge — without warning. `crossorigin="anonymous"` +> is required: without it the browser fetches the cross-origin script opaquely, +> can't read it to verify, and the load fails. The hash above is for `@0.3.0`; +> regenerate it for any other version with `npm run sri`, or copy it from the +> file's page on [jsDelivr](https://www.jsdelivr.com/), which displays the SRI +> hash for you. The WASM verifier is base64-inlined into this single `.mjs`, so +> one `integrity` hash covers the entire runtime — there is no separate `.wasm` +> fetch to protect. + +[jsDelivr](https://www.jsdelivr.com/) serves the same published file, so the same pin + `integrity` works there too: + +```html + ``` **npm (for bundlers):** @@ -223,8 +253,10 @@ npm run build ``` Outputs: -- `dist/auths-verify.mjs` — single file with WASM base64-inlined -- `dist/slim/auths-verify.mjs` — smaller JS, loads `.wasm` separately +- `dist/auths-verify.mjs` — single self-contained file with the WASM base64-inlined. Recommended for CDN + SRI: one file, one `integrity` hash covers the whole runtime. +- `dist/slim/auths-verify.mjs` — the `./slim` export. Note: it currently also inlines the WASM (via `vite-plugin-wasm`), so it is the same size as the full bundle and shares the same single-hash SRI story; there is no separate `.wasm` to fetch today. + +Generate the SRI hash for the built bundle(s) with `npm run sri`. ## License diff --git a/package.json b/package.json index a681b65..e0199f9 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "build:slim": "vite build --mode slim", "build:wasm": "cd ../auths/crates/auths-verifier && wasm-pack build --target bundler --no-default-features --features wasm && rm -rf ../../../auths-verify-widget/wasm && mv pkg ../../../auths-verify-widget/wasm", "typecheck": "tsc --noEmit", + "sri": "node scripts/sri.mjs", "test": "vitest run", "test:e2e": "playwright test", "test:watch": "vitest", diff --git a/scripts/sri.mjs b/scripts/sri.mjs new file mode 100644 index 0000000..821f4e8 --- /dev/null +++ b/scripts/sri.mjs @@ -0,0 +1,39 @@ +#!/usr/bin/env node +/** + * Compute the Subresource Integrity (SRI) hash for the built CDN bundle(s). + * + * SRI is byte-exact: the hash below is valid ONLY for the precise bytes of the + * file it was computed from. Re-run this after every `npm run build` / release + * and paste the value into the pinned ` + + diff --git a/examples/embed-snippet.ts b/examples/embed-snippet.ts new file mode 100644 index 0000000..4c4cb34 --- /dev/null +++ b/examples/embed-snippet.ts @@ -0,0 +1,65 @@ +/** + * Pure embed-snippet builder for the Embed Builder page. + * + * Reuses `detectForge` (the single source of truth for repo-URL normalization) + * so the generated snippet round-trips through the exact same parser the widget + * uses at runtime. No URL parsing is re-implemented here. + */ +import { detectForge } from '../src/resolvers/detect'; +import type { ForgeConfig } from '../src/resolvers/types'; + +// Keep VERSION + SRI in sync with the README CDN snippet and `npm run sri`. +export const VERSION = '0.3.0'; +export const SRI = 'sha384-M1UJQ02k36YqkLbXIPrV98mCZKA7pm3J2TX5PNGwi+ZJwjcJC2CoKN8dCJZpe0+l'; + +export const cdnUrl = (version = VERSION): string => + `https://unpkg.com/@auths-dev/verify@${version}/dist/auths-verify.mjs`; + +/** Reconstruct the canonical web URL (full form) from a ForgeConfig. */ +export function canonicalRepoUrl(cfg: ForgeConfig): string { + // GitHub's baseUrl is api.github.com; its web origin is github.com. + const origin = cfg.type === 'github' ? 'https://github.com' : cfg.baseUrl; + return `${origin}/${cfg.owner}/${cfg.repo}`; +} + +export type BuildResult = + | { ok: true; snippet: string; repo: string; forge: ForgeConfig['type'] } + | { ok: false; error: string }; + +/** + * Build the copy-paste embed (pinned + SRI `\n\n` + + ``; + + return { ok: true, snippet, repo, forge: cfg.type }; +} diff --git a/examples/index.html b/examples/index.html index f0e41d0..b1552d0 100644 --- a/examples/index.html +++ b/examples/index.html @@ -16,6 +16,8 @@

auths-verify Examples