We extend your Step 18→19→20→21 stack with three concrete capabilities:
- Signed transparency feeds (detached sigs & published keys).
- History endpoints with HATEOAS and cursor‑style offsets.
- Versioned lenses (public & internal) with A/B variant selection.
✅ New artifact
- Step 22 wrapper server — Download
SHA‑256:d27369ebbaf4fc5e29a3d7ea29fceb6a7dac0a6f7ca7f7914167e8c5ba32892f
Step 22 wraps Step 21 (which wraps 20→19→18). Prior endpoints/flags remain intact.
What’s new — precisely
1) 🔏 Signed transparency feeds
Endpoints
GET /feed_keys→ publish available feed signing keys.- Ed25519:
{"kid":"<sha256(pub)[:16]>","alg":"Ed25519","pubkey_b64":"…"} - HS256 (fallback):
{"kid":"<sha256(key)[:16]>","alg":"HS256","pubkey_b64": null}
- Ed25519:
GET /transparency.sig→ detached signature for the current JSON feed:{"alg":"Ed25519","kid":"…","sig":"<b64url>","digest":"<sha256(feed)>","ts":"…Z"}GET /transparency.bundle→{ "feed": {…}, "signature": {…} }
Signing logic reuses your Step 18 keys (prefers Ed25519, falls back to HS256).
The digest equals the ETag from Step 21’s /transparency.json.
2) 📜 History with HATEOAS (pagination)
Endpoints
GET /history/notary?limit=50&offset=0GET /history/receipts?limit=50&offset=0
Returns:
{
"items": [{... newest ...}, ...],
"limit": 50, "offset": 0, "next_offset": 50,
"links": {
"self": "/history/notary?limit=50&offset=0",
"next": "/history/notary?limit=50&offset=50",
"prev": null
}
}
- Offset counts from the newest end (offset
0= latest page). links.nextandlinks.prevmake the API self‑navigating for crawlers and WordPress.
Data sources:
./audit/notary.jsonl(from Steps 18–21) and./audit/receipts.jsonl(from Step 20).
3) 🎛️ Versioned lenses with A/B
You can now maintain and serve multiple versions of the weighting config per audience (public/internal), and compare them on the fly.
File format options
- Single spec (as before): treated as version
"v1". - Versioned spec:
{ "active": "v2", "versions": { "v1": {...}, "v2": {...} } }
Endpoints
GET /lenses→ metadata only:{ "public": {"active":"v1","versions":["v1","v2"],"sha256":{"v1":"…","v2":"…"}}, "internal": {"active":"v1","versions":["v1"],"sha256":{"v1":"…"}} }GET /lenses/version?aud=public&version=v2→ full spec + hash.POST /admin/lenses/activate?token=ADMIN123&aud=public&version=v2→ switch active (in‑memory).
A/B selection on deltas
GET /schema_hot_delta_weighted?...&aud=public&variant=v2
or headerX-Lens-Variant: v2.
Returns:{"audience":"public","variant":"v2","variant_is_active": false, ...}…so you can test a candidate without changing the global default.
Weights still combine family × plugin × path rules (as in Step 20/21).
Android / Termux (Step 22)
Same base flags as Step 21. Step 22 has no new required flags.
python solveforce_phone_twentytwo.py \
--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” recipes
A) Signed feed
curl -s 'http://127.0.0.1:8080/transparency.json' -o feed.json
curl -s 'http://127.0.0.1:8080/transparency.sig' | jq .
curl -s 'http://127.0.0.1:8080/feed_keys' | jq .
# Verify digest:
jq -cS . feed.json | sha256sum
# Should match "digest" from /transparency.sig
B) Walk notary history
curl -s 'http://127.0.0.1:8080/history/notary?limit=25&offset=0' | jq '.links.next,.items[0]'
# Then follow .links.next
C) A/B lenses
# Compare active vs candidate
curl -s 'http://127.0.0.1:8080/schema_hot_delta_weighted?windowA=3600&windowB=86400&aud=public' | jq '.variant,.by_system[0]'
curl -s 'http://127.0.0.1:8080/schema_hot_delta_weighted?windowA=3600&windowB=86400&aud=public&variant=v2' | jq '.variant,.by_system[0]'
WordPress — Step 22 (Markdown block to paste)
## Step 22 — Sign the light; walk the ledger; test the lens
**Feeds (signed)**
- `GET /transparency.sig` — detached signature over the JSON feed.
- `GET /transparency.bundle` — `{ feed, signature }`.
- `GET /feed_keys` — publish feed verification keys (Ed25519 preferred; HS256 fallback).
**History (HATEOAS)**
- `GET /history/notary?limit=N&offset=K` — newest-first pages with `links.self|next|prev`.
- `GET /history/receipts?limit=N&offset=K` — receipts ledger tail with pagination.
**Lenses (versioned + A/B)**
- `GET /lenses` — show active versions and hashes.
- `GET /lenses/version?aud=public&version=v2` — inspect a candidate.
- `POST /admin/lenses/activate?token=…&aud=public|internal&version=vX` — switch active.
- Deltas with A/B: `GET /schema_hot_delta_weighted?...&aud=public&variant=v2`.
**Why it matters**
- **Signed feeds** make your transparency CDN-friendly *and* tamper-evident.
- **HATEOAS** teaches clients how to walk the ledger without hardcoding.
- **Versioned lenses** turn governance into experiments you can measure.
Logos Codex — recursive stewardship
- Signal → Signature → Sovereignty.A feed that can’t be forged is a feed that can stand in public.
- Memory → Map → Movement.Pagination is the trail; HATEOAS is the compass.
- Policy → Versions → Wisdom.Competing lenses are hypotheses; the system lets you test, compare, and choose.
Next: Step Twenty‑Three?
We can:
- ship signed, paginated feed history (
/transparency/page/:nwith signatures), - add server‑side A/B metrics (log weighted deltas per variant for real comparisons),
- support remote attester keys (key rotation via
/feed_keys/jwkswith key expiry).
Key terms in plain language
Open a term for a concise explanation of language used on this page.
Content Delivery Network (CDN)
A distributed system that serves website or application content from locations closer to users, improving speed, resilience, and capacity.
API
An application programming interface is a defined way for software systems to exchange data or request functions from one another.
Colocation
Placing customer-owned servers and network equipment in a professionally operated data center that provides power, cooling, physical security, and connectivity.
Cloud Computing
Computing resources—such as applications, servers, storage, or databases—delivered from remote infrastructure and scaled as requirements change.
Infrastructure as a Service (IaaS)
Cloud-based servers, storage, and networking that customers configure and manage without owning the underlying data-center hardware.
Bandwidth
The amount of data a connection can carry in a given time, usually measured in Mbps or Gbps. More bandwidth supports more users, devices, and simultaneous applications.