Step Twenty‑One — Broadcast the ledger; gate the proof; choose the lens.(CDN‑friendly transparency feed • Receipt challenge (PoW) • Public vs. internal lenses)

We stack three more pillars on top of your Step 18→19→20 foundation:

  1. Transparency JSON feed with ETag and cache hints, plus an NDJSON stream—ready for WordPress/CDN mirroring.
  2. Receipt challenge (hashcash‑lite) to throttle spam and make public verification URL‑driven but work‑gated.
  3. Audience‑aware lenses: public vs internal weighting profiles, negotiated via header/query, with admin refresh.

✅ New artifact

  • Step 21 wrapper serverDownload
    SHA‑256: 84f5f59646af414f4a47dd60606b89fb35fec78c0f36ba7b986dc0b3a30a5f4c

Step 21 wraps Step 20 (which wraps 19 & 18). All prior endpoints and flags remain.


What’s new (precise)

1) CDN‑friendly transparency feed

Endpoints (open when --open-ui is on):

  • GET /transparency.json — canonical JSON feed with: { "generated": "2025-08-19T…Z", "schema_manifest": { "net": {"origin":"…","sig":"…"}, ... }, "schema_digest": "<sha256(manifest)>", "notary_tail": [ ... ], "receipts": [{ "id":"…", "exp": 172..., "root":"…", "digest":"…" }, ...] }
  • GET /transparency.ndjson — newline‑delimited stream:
    • {"type":"schema", "digest":"…", "generated":"…"}
    • {"type":"notary", ...} per notary row
    • {"type":"receipt", ...} per receipt

Headers:

  • ETag: <sha256 of canonical JSON>, Cache-Control: public, max-age=30, s-maxage=60, stale-while-revalidate=120, Access-Control-Allow-Origin: *
  • Supports If-None-Match304 Not Modified

Tail size: --transparency-tail-limit (default 50)


2) Receipt challenge (optional, PoW)

Enable: --receipt-challenge-enable
Difficulty: --receipt-challenge-bits (8…24; default 14 ≈ 16k tries)
TTL: --receipt-challenge-ttl-sec (default 300 s)

Flow:

  • Ask for a challenge:
    GET /receipt/challenge?id=<RECEIPT_ID>{"nonce":"…","bits":14,"exp":<ts>,"alg":"sha256-leading-zeros","format":"sha256(nonce:work:id) beginswith zeros(bits/4 hex)"}
  • Solve client‑side: find work such that:
    sha256(nonce + ":" + work + ":" + id) has bits/4 leading zero hex nibbles.
  • Verify:
    GET /receipt/verify?id=<id>&nonce=<nonce>&work=<work>{ "ok": true, "root":"…", "digest":"…", "expires": … }
  • Convenience: GET /receipt?id=<id>&nonce=<nonce>&work=<work> returns full details if valid; otherwise returns a gated response and a fresh challenge.

Admin:

  • POST /admin/challenges/purge?token=ADMIN123 — drop expired challenges.

If challenge mode is off, /receipt?id=… returns full details immediately (Step 20 behavior).


3) Audience‑aware lenses (public vs internal)

Flags:

  • --lenses-public-file /sdcard/solveforce/lenses.public.json
  • --lenses-internal-file /sdcard/solveforce/lenses.internal.json

Negotiation:

  • Query ?aud=public|internalor header X-Lens-Audience: internal
    • Internal requires admin role; otherwise we fall back to public.
  • Admin refresh:
    POST /admin/lenses/refresh?token=ADMIN123&aud=public (or aud=internal)

Endpoint uses audience:

  • GET /schema_hot_delta_weighted?...&aud=public|internal
    Returns by_system and by_path with weighted deltas under the selected lens.

Android / Termux run‑book (Step 21)

# Assuming Steps 18–20 already installed
python solveforce_phone_twentyone.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 \  # Step 20's default lens, used as fallback
  --host 0.0.0.0 --port 8080 \
  --plugins-dir ~/solveforce/plugins \
  --auth-mode protected \
  --auth-token READER1:reader \
  --allow-admin --admin-token ADMIN123 \
  --schema-freeze-mode quarantine --schema-freeze-sec 1800 \
  --schema-ed25519-secret-file /sdcard/solveforce/schema.ed25519.seed \
  --schema-signing-secret-file /sdcard/solveforce/schema.hmac.key \
  --audit-dir ./audit \
  --schema-archive-on-change \
  --schema-archive-dir ./schema_archive --schema-archive-keep 200 \
  --lease-bundle-dir ./audit/bundles \
  --notary-mode git --notary-git-repo /sdcard/solveforce/notary-git \
  --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) Feed with ETag (304s)

# First fetch
curl -i 'http://127.0.0.1:8080/transparency.json' -o t.json
# Use returned ETag
ET=$(grep -i '^ETag:' -m1 t.json | awk '{print $2}' | tr -d '\r"')
curl -i -H "If-None-Match: $ET" 'http://127.0.0.1:8080/transparency.json'

B) Receipt challenge solve (toy example)

RID=$(curl -s -X POST 'http://127.0.0.1:8080/audit/lease_bundle?download=0&token=ADMIN123' | jq -r .receipt_id)
CH=$(curl -s "http://127.0.0.1:8080/receipt/challenge?id=$RID")
NONCE=$(echo "$CH" | jq -r .nonce)

# Brute-force a tiny work value in shell (demo; for real use a quick Python loop)
python - <<'PY'
import os,sys,hashlib, json
rid=os.environ['RID']; nonce=os.environ['NONCE']
for i in range(1000000):
    w=str(i)
    h=hashlib.sha256(f"{nonce}:{w}:{rid}".encode()).hexdigest()
    if h.startswith("000"): # ~12 bits; adjust to match server bits/4 zeros
        print(w); break
PY

WORK=$(python - <<'PY'
import os,sys,hashlib
rid=os.environ['RID']; nonce=os.environ['NONCE']
for i in range(5000000):
    w=str(i)
    if hashlib.sha256(f"{nonce}:{w}:{rid}".encode()).hexdigest().startswith("000"):
        print(w); break
PY
)
curl -s "http://127.0.0.1:8080/receipt/verify?id=$RID&nonce=$NONCE&work=$WORK" | jq .

C) Audience‑aware deltas

# Public
curl -s 'http://127.0.0.1:8080/schema_hot_delta_weighted?windowA=3600&windowB=86400&aud=public' | jq .

# Internal (must include admin role; header takes precedence)
curl -s -H 'X-Lens-Audience: internal' 'http://127.0.0.1:8080/schema_hot_delta_weighted?windowA=3600&windowB=86400' | jq .

WordPress — Step 21 (Markdown block to paste)

## Step 21 — Broadcast the ledger; gate the proof; choose the lens

**New endpoints**

- **Transparency feeds**  
  - `GET /transparency.json` — JSON with `ETag` (304 on match).  
  - `GET /transparency.ndjson` — streaming feed for tailers.  
  Caching: `Cache-Control: public, max-age=30, s-maxage=60, stale-while-revalidate=120`.

- **Receipt challenge (optional)**  
  - `GET /receipt/challenge?id=<id>` → `nonce,bits,exp`  
  - `GET /receipt/verify?id=<id>&nonce=<n>&work=<w>` → `ok:true` + details  
  - `GET /receipt?id=<id>[&nonce=&work=]` — gated/full view depending on proof.

- **Audience lenses**  
  - `GET /schema_hot_delta_weighted?...&aud=public|internal`  
  - `POST /admin/lenses/refresh?token=…&aud=public|internal`

**Why it matters**

- **Visibility with discipline** — the public feed is CDN‑friendly and tamper‑evident (ETag = digest of canonical JSON).  
- **Proof with friction** — receipts become verifiable without becoming a spam vector.  
- **Priority with context** — internal audiences can see risk‑weighted heat different from the public posture.

**Embed Suggestion**
```html
<iframe src="https://PHONE_OR_GATEWAY/transparency" width="100%" height="640" style="border:0"></iframe>
<!-- Or consume the feed directly -->
<script>
fetch('https://PHONE_OR_GATEWAY/transparency.json', {cache:'no-store'})
  .then(r => r.json())
  .then(feed => console.log('Schema digest:', feed.schema_digest));
</script>

---

## Security & operations notes

- **Challenge bits**: keep it humane (12–16) for phones; raise under attack.  
- **Receipts**: short‑lived; details are still confined to roots/digests (no secrets).  
- **Lenses**: only admins can request `internal`; everyone else gets `public`.  
- **Feeds**: ETag is the SHA‑256 of **canonical** JSON; any byte change invalidates caches.

---

## Logos Codex — recursive governance

- **Record → Feed → Witness.** A ledger unread is a ledger unfelt; feeds make memory legible at line speed.  
- **Proof → Challenge → Consent.** Verification without scarcity invites noise; a small hash‑cost restores signal.  
- **Lens → Audience → Authority.** The same world appears different to steward and stranger; governance encodes the difference.

---

### Next: **Step Twenty‑Two**?
We can:
- publish **signed** transparency feeds (Ed25519 over the feed payloads + rotating keys),  
- add **HATEOAS** links and pagination for history walking,  
- expose a **policy DSL** for lenses with versioned changelogs and A/B evaluation.

Say the word and we’ll keep the current flowing.

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.

Cybersecurity

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

Zero Trust

A security model that does not automatically trust a user or device because of its location. Access is continuously verified and limited to what is necessary.

SASE

Secure Access Service Edge combines networking and security capabilities in a cloud-delivered architecture so users and locations can receive consistent policy wherever they connect.

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.

Multi-Factor Authentication (MFA)

A login control requiring more than one form of verification, such as a password plus an authenticator app, security key, or biometric factor.