Skip to content

Commit 1713eaf

Browse files
Mayumi Haraclaude
authored andcommitted
docs(examples): worked example — sign & verify an OKF bundle (VOKF-9 / M1)
Completes M1. examples/okf-bundle/ is a small multi-concept OKF bundle (a GA4 analytics mapping: purchase / add_to_cart / consent-mode). - examples/sign-and-verify.sh: signs every concept, verifies each, and renders an offline HTML report via the built CLIs (< 5 min, copy-paste). - README: a "Worked example" section. - A visualizer test guards it in CI: every concept signs → verifies as `verified`, and the rendered report is offline (no external refs). Full suite green (canon 28 + signer 7 + verifier 22 + visualizer 7 + attest 5 = 69). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 2973f3b commit 1713eaf

6 files changed

Lines changed: 117 additions & 0 deletions

File tree

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ The signed output is byte-identical to `fixtures/signed/ga4-event.md`, and tampe
4141
signature, schema, or issuer yields the corresponding `failed` reason code (see `fixtures/tampered/`).
4242
Verification is fully offline for `did:key`; `did:web` resolves the issuer over HTTPS.
4343

44+
## Worked example (a real OKF bundle)
45+
46+
`examples/okf-bundle/` is a small multi-concept OKF bundle (a GA4 analytics mapping). Sign every
47+
concept, verify each, and render an offline report:
48+
49+
```bash
50+
pnpm install && pnpm build
51+
examples/sign-and-verify.sh
52+
# add-to-cart-event.md {"status":"verified", ...}
53+
# consent-mode.md {"status":"verified", ...}
54+
# purchase-event.md {"status":"verified", ...}
55+
# report → /tmp/.../report.html (3 concepts, 0 failed)
56+
```
57+
4458
## Development
4559
```bash
4660
pnpm install
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
title: GA4 — add_to_cart event
3+
resource: https://example.com/okf/ga4/add-to-cart
4+
type: event
5+
tags: [analytics, ga4, ecommerce]
6+
---
7+
# add_to_cart
8+
9+
Emit `add_to_cart` when an item is added to the cart.
10+
11+
| parameter | source |
12+
|---|---|
13+
| value | item.price * item.qty |
14+
| currency | catalog.currency |
15+
| items | [item] |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
title: GA4 — consent mode defaults
3+
resource: https://example.com/okf/ga4/consent
4+
type: config
5+
tags: [analytics, ga4, consent]
6+
---
7+
# consent mode
8+
9+
Default consent state before the user interacts with the banner.
10+
11+
- `ad_storage`: denied
12+
- `analytics_storage`: denied
13+
- `ad_user_data`: denied
14+
- `ad_personalization`: denied
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: GA4 — purchase event
3+
resource: https://example.com/okf/ga4/purchase
4+
type: event
5+
tags: [analytics, ga4, ecommerce]
6+
---
7+
# purchase
8+
9+
Emit a GA4 `purchase` event when an order is confirmed server-side.
10+
11+
| parameter | source |
12+
|---|---|
13+
| transaction_id | order.id |
14+
| value | order.total |
15+
| currency | order.currency |
16+
| items | order.line_items[] |

examples/sign-and-verify.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
# Worked example: sign every concept in examples/okf-bundle/, verify each, and
3+
# render an offline HTML report. Run `pnpm install && pnpm build` first.
4+
set -e
5+
cd "$(dirname "$0")/.." # repo root
6+
7+
# Test-only Ed25519 seed (32 bytes hex). NEVER use a real key on the CLI.
8+
SEED=0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
9+
OUT="$(mktemp -d)"
10+
11+
echo "→ signing examples/okf-bundle/ → $OUT"
12+
for f in examples/okf-bundle/*.md; do
13+
node packages/signer/dist/cli.js "$f" --key "$SEED" \
14+
--valid-from 2026-01-01T00:00:00Z --valid-until 2027-01-01T00:00:00Z \
15+
-o "$OUT/$(basename "$f")"
16+
done
17+
18+
echo "→ verifying"
19+
for f in "$OUT"/*.md; do
20+
printf ' %-22s %s\n' "$(basename "$f")" "$(node packages/verifier/dist/cli.js "$f")"
21+
done
22+
23+
node packages/visualizer/dist/cli.js "$OUT" -o "$OUT/report.html"
24+
echo "→ report: $OUT/report.html"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { describe, it, expect } from "vitest";
2+
import { readFileSync, readdirSync } from "node:fs";
3+
import { fileURLToPath } from "node:url";
4+
import { signConcept } from "@verifiable-okf/signer";
5+
import { verifyConcept } from "@verifiable-okf/verifier";
6+
import { renderReport, type ReportItem } from "../src/index.js";
7+
8+
// VOKF-9 worked example: the OKF bundle under examples/ must sign → verify cleanly.
9+
const bundleDir = fileURLToPath(new URL("../../../examples/okf-bundle", import.meta.url));
10+
const SEED = Uint8Array.from(Array.from({ length: 32 }, (_, i) => i + 1));
11+
const SIGN = { privateKey: SEED, validFrom: "2026-01-01T00:00:00Z", validUntil: "2027-01-01T00:00:00Z" };
12+
const NOW = new Date("2026-06-15T00:00:00Z");
13+
14+
describe("worked example (examples/okf-bundle)", () => {
15+
const files = readdirSync(bundleDir).filter((f) => f.endsWith(".md")).sort();
16+
17+
it("contains a multi-concept bundle", () => {
18+
expect(files.length).toBeGreaterThanOrEqual(3);
19+
});
20+
21+
it("every concept signs then verifies as `verified`", async () => {
22+
const items: ReportItem[] = [];
23+
for (const f of files) {
24+
const signed = signConcept(readFileSync(`${bundleDir}/${f}`), SIGN);
25+
const result = await verifyConcept(signed, { now: NOW });
26+
expect(result.status, f).toBe("verified");
27+
items.push({ id: f, result });
28+
}
29+
// and the report renders all of them as verified, offline
30+
const html = renderReport(items);
31+
expect((html.match(/>verified</g) ?? []).length).toBe(files.length);
32+
expect(html).not.toMatch(/(?:src|href)\s*=\s*["']https?:\/\//i);
33+
});
34+
});

0 commit comments

Comments
 (0)