Step Twenty‑Three — Freeze the witness; measure the experiment; publish the keys.(Signed historical feed pages • Server‑side A/B metrics • JWKS for public keys)

We’re continuing the cadence. Building on Steps 18–22, Step 23 adds:

  1. Signed, paginated transparency history
    Create immutable page snapshots of your transparency feed, each with a detached signature. This makes your ledger crawlable, cacheable, and citable—down to the page.
  2. Server‑side A/B metrics
    Every call to schema_hot_delta_weighted is recorded with audience/variant and summary stats so you can compare lens variants empirically.
  3. JWKS for attester keys
    Expose your Ed25519 public keys via a JSON Web Key Set for standards‑based verification and rotation, with an admin refresh.

✅ New artifact

  • Step 23 wrapper serverDownload
    SHA‑256: ff109dcd4511b713d156f414ae63a47f2f5453f32a4a6a150b78fbd81e6aec5a

Step 23 wraps Step 22 (which wraps 21→20→19→18). All previous endpoints & flags continue to work.


What’s new — in detail

1) 📚 Signed historical transparency pages

Endpoints

  • GET /transparency/pages
    → shows the latest page number + quick links to the most recent ~10 pages.
  • GET /transparency/page/<n>.json — the frozen feed snapshot for page n.
  • GET /transparency/page/<n>.sig — detached signature for page n.
  • GET /transparency/page/<n>.bundle{ feed, signature }.

Admin roll

  • POST /admin/feed/roll?token=ADMIN123 → creates the next page only if the current feed changed (compares SHA‑256 digest).
    • Force a page even if unchanged: &force=1.

On‑disk layout

./audit/feed_history/
  index.json            # {"latest": N, "last_digest": "...", "ts": "...Z"}
  page-1.json, page-1.sig
  page-2.json, page-2.sig
  ...

Optional auto‑roll
Enable a background roller that snapshots whenever the feed changes:

--feed-roll-enable
--feed-roll-interval-sec 600    # default 10 minutes

2) 📈 A/B metrics for weighted deltas

Every response from:

GET /schema_hot_delta_weighted?...&aud=public|internal[&variant=vX]

is summarized to ./audit/ab_metrics.jsonl:

{
  "_ts": "2025-08-19T…Z",
  "audience": "public",
  "variant": "v2",
  "active": false,
  "A": [sinceA, untilA],
  "B": [sinceB, untilB],
  "weighted_total": -13.2,
  "weighted_abs_sum": 47.9,
  "top_system": {"system": "power", "weighted_delta": -21.0},
  "paths_reported": 50
}

Use this to compare candidate lenses (variant=v2) against the active version over time. It’s append‑only and friendly to your transparency story.


3) 🔑 JWKS for feed verification keys

Endpoints

  • GET /feed_keys/jwks{"keys":[ {"kid":"<sha16>","kty":"OKP","crv":"Ed25519","x":"<b64url>","use":"sig","alg":"EdDSA"}, ... ]}
    • Includes the current server Ed25519 public key (from Step 18 config).
    • Optionally merges extra public keys loaded from a directory.

Admin

  • POST /admin/feed_keys/refresh?token=ADMIN123 — re-scan extra keys directory.

Flags

--feed-pubkeys-dir /sdcard/solveforce/pubkeys   # files ending with .ed25519.pub (raw 32 bytes)

HS256 keys are not published (they’re shared secrets). JWKS exposes only public Ed25519 keys.


Android / Termux run‑book (Step 23)

python solveforce_phone_twentythree.py \
  --feed-history-dir ./audit/feed_history \
  --feed-tail-per-page 50 \
  --feed-roll-enable \
  --feed-roll-interval-sec 600 \
  --feed-pubkeys-dir /sdcard/solveforce/pubkeys \
  --lenses-public-file /sdcard/solveforce/lenses.public.json \
  --lenses-internal-file /sdcard/solveforce/lenses.internal.json \
  --transparency-tail-limit 50 \
  --receipt-challenge-enable --receipt-challenge-bits 14 --receipt-challenge-ttl-sec 300 \
  --families-file /sdcard/solveforce/families.json \
  --lenses-file /sdcard/solveforce/lenses.public.json \
  --host 0.0.0.0 --port 8080 \
  --plugins-dir ~/solveforce/plugins \
  --auth-mode protected \
  --auth-token READER1:reader \
  --allow-admin --admin-token ADMIN123 \
  --schema-ed25519-secret-file /sdcard/solveforce/schema.ed25519.seed \
  --schema-signing-secret-file /sdcard/solveforce/schema.hmac.key \
  --audit-dir ./audit \
  --lease-bundle-dir ./audit/bundles \
  --mirror-enable \
  --mirror-target-url https://your-site.tld/wp-json/solveforce/v1/notary \
  --mirror-header "Authorization: Bearer <YOUR_WP_TOKEN>" \
  --allow-query-token --open-ui

“Show me” commands

A) Roll a new signed history page

# roll if changed
curl -s -X POST 'http://127.0.0.1:8080/admin/feed/roll?token=ADMIN123' | jq .
# list pages
curl -s 'http://127.0.0.1:8080/transparency/pages' | jq .
# fetch page JSON + signature
curl -s 'http://127.0.0.1:8080/transparency/page/3.bundle' | jq .

B) Fetch JWKS & verify an Ed25519 signature

curl -s 'http://127.0.0.1:8080/feed_keys/jwks' | jq .
# Compare 'kid' and 'x' to the pubkey on your verifier station

C) Drive A/B traffic and review metrics

# Public (active)
curl -s 'http://127.0.0.1:8080/schema_hot_delta_weighted?windowA=3600&windowB=86400&aud=public' >/dev/null
# Candidate variant v2
curl -s 'http://127.0.0.1:8080/schema_hot_delta_weighted?windowA=3600&windowB=86400&aud=public&variant=v2' >/dev/null
# Inspect metrics
tail -n 20 ./audit/ab_metrics.jsonl | jq .

WordPress — Step 23 (Markdown block to paste)

## Step 23 — Freeze the witness; measure the experiment; publish the keys

**Historical transparency (signed)**
- `GET /transparency/pages` — latest page & links.
- `GET /transparency/page/<n>.json` — immutable snapshot.
- `GET /transparency/page/<n>.sig` — detached signature.
- `GET /transparency/page/<n>.bundle` — `{ feed, signature }`.
- Admin roll: `POST /admin/feed/roll?token=…[&force=1]`.

**A/B metrics (server‑side)**
- Every `GET /schema_hot_delta_weighted?...` logs to `audit/ab_metrics.jsonl` with:
  `audience, variant, weighted_total, weighted_abs_sum, top_system, A/B windows`.
- Use it to compare **candidate lens variants** over time.

**JWKS (public keys)**
- `GET /feed_keys/jwks` — JSON Web Key Set (Ed25519 keys, `kty=OKP`, `crv=Ed25519`, `alg=EdDSA`).
- Admin: `POST /admin/feed_keys/refresh?token=…`.
- Extra keys directory: `--feed-pubkeys-dir /path/to/*.ed25519.pub`.

**Why it matters**
- **History** graduates from “latest view” to **citable pages** with **signatures**.
- **A/B** grows from hunch to **evidence**, logged on the server.
- **Keys** step into **JWKS**, meeting the world where it verifies.

Logos Codex — recursive publication

  • Moment → Page → Permanence.A feed without pages is weather; with signatures, it becomes almanac.
  • Hypothesis → Metric → Choice.Lenses aren’t beliefs—they’re experiments. The ledger remembers what wins.
  • Key → JWKS → Commons.Private truth, public proof—now in a dialect the web speaks.

Forward to Step Twenty‑Four?

Proposals:

  • Signed page indexand rolling Merkle chain of pages (page‑to‑page linkability),
  • AB reports endpointthat aggregates metrics over time windows,
  • Auto‑rotationof feed signing keys with grace periods and JWKS kid rollouts.

Say the word and we’ll keep walking the ledger.

Key terms in plain language

Open a term for a concise explanation of language used on this page.

Broadband

A general term for always-on, high-speed Internet access. Broadband can be delivered over fiber, cable, DSL, fixed wireless, cellular, or satellite networks.

Cloud Computing

Computing resources—such as applications, servers, storage, or databases—delivered from remote infrastructure and scaled as requirements change.

Cybersecurity

The practices and controls used to protect identities, devices, networks, applications, and data from unauthorized access, disruption, or manipulation.

Identity and Access Management (IAM)

The systems and policies that determine who a user is, what resources they may access, and how that access is authenticated and reviewed.

API

An application programming interface is a defined way for software systems to exchange data or request functions from one another.

Artificial Intelligence (AI)

Software designed to perform tasks involving prediction, classification, generation, reasoning, or decision support. Business use still requires clear data, governance, security, and human accountability.