Step Twenty‑Eight — Convene the quorum; agree the directory; prove you were there.(Auto‑attest policies • Cross‑directory consensus • Privacy‑preserving witness tickets)

We harden governance and privacy atop your Step‑18→27 stack:

  1. Quorum policy engine — automatically issues M‑of‑N quorum attestations when thresholds are met.
  2. Cross‑directory consensus — compute peers included by at least M signed directories and sign the consensus view.
  3. Witness tickets (zk‑lite) — let devices prove “I saw this root” without revealing who they are.

✅ Fresh artifacts

  • Step 28 wrapper serverDownload
    SHA‑256: 0d15d8b1e3641212ea0cfb78202dc679f709b902a604be8a5d3b74c9078d16cc
  • Sample quorum policiesDownload
  • WordPress block (paste‑ready)Download

Step 28 wraps Step 27 (which wraps 26→25→24→22→21→20→19→18). Earlier endpoints continue to work.


What’s new — in detail

1) 🗳️ Quorum policy engine (auto‑attest)

A background worker scans recent federation anchors (Step 25) and, per policy, emits a signed quorum attestation when observed >= m.

Policy file shape (quorum.policies.json)

{
  "interval_sec": 300,
  "policies": [
    {"subject":"page","m":2,"n":3,"window_sec":86400,
     "autopush": false,
     "push_url": "",
     "header": ["Authorization: Bearer ..."],
     "basic": ""}
  ]
}

Endpoints

  • GET /quorum/policies — engine enabled?, interval, and current config.
  • POST /admin/quorum/refresh?token=… — reload policy file.
  • GET /quorum/autotail?n=50 — tail of auto‑attest events (and any push errors).

Flags

--quorum-auto-enable
--quorum-policy-file /sdcard/solveforce/quorum.policies.json
--quorum-interval-sec 300

2) 🌐 Cross‑directory consensus (from DoD)

Compute peers that appear in ≥ m of your signed directories (Step 27 DoD) and sign the consensus object with your feed key.

Endpoints

  • GET /discovery/consensus?m=2 → returns {policy:"atleast_m_of_directories", m, peers, explain}
  • GET /discovery/consensus.sig?m=2 → detached signature plus digest over that object

Use this to publish a defensible peer list (who’s in by multi‑directory agreement).


3) 🎟️ Witness tickets (privacy‑preserving)

Devices mint a short‑lived ticket proving they observed a root in the recent window—no device identity disclosed.
Workflow:

  1. Device makes a fresh Ed25519 ephemeral key; send its raw 32‑byte public key as wpk (base64url).
  2. POST /observer/ticket/request with {root,wpk,nonce?,window_sec?}.
    • Server verifies the root exists in recent anchors, then signs:
    { "ticket": {"type":"witness_ticket","root":"...","wpk":"<b64url>","nonce":"...","ts":"...Z"}, "proof": {"alg":"Ed25519","kid":"<sha16>","x":"<pub_b64>","sig":"<b64url>"} }
  3. Anyone can POST /observer/ticket/verify with {ticket,proof} to check validity against your JWKS (/feed_keys/jwks).

Endpoints

  • POST /observer/ticket/request — issue ticket (auth required).
  • POST /observer/ticket/verify — verify a ticket.
  • GET /observer/tickets/tail?n=50 — recent ticket issues.

Tickets are signed using your active Ed25519 feed key (Step 24 keyring) when present; otherwise HS256 falls back.


Android / Termux run‑book (Step 28)

# Optional: set policies
cp ~/downloads/quorum.policies.sample.json /sdcard/solveforce/quorum.policies.json

python solveforce_phone_twentyeight.py \
  --quorum-auto-enable \
  --quorum-policy-file /sdcard/solveforce/quorum.policies.json \
  --quorum-interval-sec 300 \
  --discovery-dod-enable \
  --discovery-dod-source https://directory1.example.com/solveforce/peers.json \
  --discovery-dod-source https://directory2.example.org/solveforce/peers.json \
  --discovery-dod-jwks   https://directory1.example.com/jwks.json \
  --discovery-dod-policy union \
  --attest-enable \
  --attest-url https://your-site.tld/wp-json/solveforce/v1/attest \
  --attest-header "Authorization: Bearer <WP_TOKEN>" \
  --alarm-enable \
  --alarm-config-file /sdcard/solveforce/alarms.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 \
  --mirror-enable \
  --mirror-target-url https://your-site.tld/wp-json/solveforce/v1/notary \
  --mirror-header "Authorization: Bearer <WP_TOKEN>" \
  --allow-query-token --open-ui

“Show me” commands

A) Consensus now

curl -s 'http://127.0.0.1:8080/discovery/consensus?m=2' | jq .
curl -s 'http://127.0.0.1:8080/discovery/consensus.sig?m=2' | jq .

B) Auto‑attest trail

curl -s 'http://127.0.0.1:8080/quorum/policies' | jq .
curl -s 'http://127.0.0.1:8080/quorum/autotail?n=20' | jq .

C) Witness tickets

# Get a ticket (device supplies fresh 32-byte pubkey base64url as WPK)
WPK="kS0j...<your-ephemeral-b64url>..."
curl -s -X POST 'http://127.0.0.1:8080/observer/ticket/request' \
  -H 'Content-Type: application/json' \
  -d "{\"root\":\"<ROOT>\",\"wpk\":\"$WPK\",\"nonce\":\"demo\"}" | jq .

# Verify (use the output ticket+proof)
curl -s -X POST 'http://127.0.0.1:8080/observer/ticket/verify' \
  -H 'Content-Type: application/json' \
  -d '{"ticket":{...},"proof":{...}}' | jq .

WordPress — Step 28 (public page block)

Paste from step28_wordpress.md.
It explains Auto‑Attest Policies, Directory Consensus, and Witness Tickets succinctly for your readers.


Logos Codex — recursive legitimacy, continued

  • Threshold → Act → Archive. Policies turn agreement into attestations right on time.
  • Lists → Agreement → Law. Many directories speaking together make a commons.
  • Presence → Privacy → Proof. Tickets let a witness be counted without being named.

If you want Step Twenty‑Nine, we can introduce:

  • Quorum issuance windows with grace and revocation,
  • Consensus deltas (who joined/left since last signed view), and
  • Ticket spend/nonce registries to prevent double‑use without deanonymization.

We extend the Step‑18→25 line with three pragmatic upgrades:

  1. Peer discovery so federation isn’t hand‑managed.
  2. Signed public attestations of the state you care about (feed digest, page‑chain root, federated root).
  3. Alarms with hysteresis and multi‑channel delivery (webhooks + SMTP + Twilio HTTP).

✅ New artifacts (ready to run & publish)

  • Step 26 wrapper serverDownload
    SHA‑256: 977adf5c9f1e53241137794e1903f194cc4f913e5b6562af0137f555d6b80b41
  • WordPress block (paste‑ready)Download
  • Sample discovery directory (signed format)Download
  • Sample attestation payloadDownload

Step 26 wraps Step 25 (which wraps 24→22→21→20→19→18). All prior endpoints and flags continue to work.


What’s new — precisely

1) 🌐 Peer discovery (HTTP / DNS / static)

  • HTTP Directory (signed)
    Point the phone at a directory JSON like: { "issuer":"solveforce-directory", "ts":"2025-08-19T00:00:00Z", "peers":["https://phone-a.example.net:8080", "https://phone-b.example.net:8080"], "sig":{"alg":"Ed25519","kid":"<kid>","sig":"<b64url>"} } The server optionally verifies the signature with a JWKS URL or a known public key.
  • DNS discovery (best‑effort)
    Attempts _solveforce._tcp.<domain> SRV and TXT lookups (uses dnspython if present; otherwise makes a minimal fallback). TXT can carry a small JSON blob with {"peers":[...]}.
  • Filtering
    --discovery-allow <substr> and --discovery-deny <substr> to constrain the set.
  • Endpoints
    • GET /discovery/status — current peers, method, and settings.
    • POST /admin/discovery/refresh?token=… — snap refresh (also updates the Step‑25 federation peer list).

2) 🪶 Public attestations

A compact, signed statement you can push to WordPress (or any endpoint) at a regular cadence:

{
  "alg":"Ed25519","kid":"<sha16>","x":"<pub_b64url>","sig":"<b64url>",
  "page_root":"<page_chain_root>", "page_latest": 12,
  "feed_digest":"<sha256-of-transparency.json>",
  "fed_root":"<federation_chain_root>", "fed_n": 24,
  "ts":"2025-08-19T00:00:00Z"
}
  • Signed by the active Ed25519 feed key (Step 24 keyring) when available; otherwise falls back to your Step‑22 signer.
  • Endpoints
    • GET /attestation — preview the current attestation (no network).
    • GET /attest/history?n=50 — tail of attempts (ok/failed).
    • POST /admin/attest/now?token=… — build & push now.
  • Flags --attest-enable --attest-url https://your-site.tld/wp-json/solveforce/v1/attest --attest-header "Authorization: Bearer <TOKEN>" --attest-basic "user:pass" --attest-interval-sec 1800

3) 🔔 Alarms: hysteresis + multi‑channel delivery

  • Hysteresis (anti‑flap)
    In addition to Step‑25’s op/value, you can specify rise/fall thresholds: {"metric":"weighted_total","rise":100,"fall":80,"window_sec":3600,"debounce_sec":900} The alarm arms when >= rise and disarms when <= fall. If rise/fall are absent, we keep using Step‑25’s comparison logic.
  • Channels
    • Webhooks: multiple URLs, JSON POST.
    • SMTP: simple mailer (TLS optional).
    • Twilio (HTTP): SMS via REST (Basic auth; no extra libs required).
    Example alarms.json (adds to your Step‑25 config): { "webhooks": ["https://example.com/wp-json/solveforce/v1/alerts"], "headers": ["Authorization: Bearer YOUR_TOKEN"], "smtp": {"server":"smtp.example.com","port":587,"tls":true,"user":"bot","pass":"***","from":"bot@example.com","to":["ops@example.com"]}, "twilio": {"account_sid":"AC...","token":"...","from":"+15555550001","to":"+15555550002"}, "rules": [ {"audience":"public","metric":"weighted_total","rise":60,"fall":40,"window_sec":3600,"debounce_sec":900}, {"audience":"public","variant":"v2","metric":"weighted_abs_sum","op":"abs>","value":100,"window_sec":7200,"debounce_sec":1200}, {"audience":"internal","variant":"v1","metric":"top_system_abs","op":">=","value":25,"window_sec":1800,"debounce_sec":900} ] }
  • Endpoints (same as Step‑25)
    • GET /alarms/status — engine state & last triggers
    • POST /admin/alarms/refresh?token=… — reload config
    • POST /admin/alarms/test?token=… — send a test payload

Android / Termux run‑book (Step 26)

# Discovery config (HTTP-signed directory example)
# (See discovery.sample.json for shape; host it behind your WordPress or CDN.)
# Attestations go to your WP REST route or any webhook.

python solveforce_phone_twentysix.py \
  --discovery-enable \
  --discovery-source http \
  --discovery-http-url https://directory.example.com/solveforce/peers.json \
  --discovery-http-header "Authorization: Bearer <DIR_TOKEN>" \
  --discovery-jwks-url https://directory.example.com/jwks.json \
  --discovery-allow example.com \
  --discovery-interval-sec 600 \
  --attest-enable \
  --attest-url https://your-site.tld/wp-json/solveforce/v1/attest \
  --attest-header "Authorization: Bearer <WP_TOKEN>" \
  --attest-interval-sec 1800 \
  --alarm-enable \
  --alarm-config-file /sdcard/solveforce/alarms.json \
  --alarm-interval-sec 300 \
  --lenses-public-file /sdcard/solveforce/lenses.public.json \
  --lenses-internal-file /sdcard/solveforce/lenses.internal.json \
  --families-file /sdcard/solveforce/families.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 <WP_TOKEN>" \
  --allow-query-token --open-ui

“Show me” commands

A) Discovery now

curl -s 'http://127.0.0.1:8080/discovery/status' | jq .
curl -s -X POST 'http://127.0.0.1:8080/admin/discovery/refresh?token=ADMIN123' | jq .
curl -s 'http://127.0.0.1:8080/federation/peers' | jq .

B) Attest now

curl -s 'http://127.0.0.1:8080/attestation' | jq .
curl -s -X POST 'http://127.0.0.1:8080/admin/attest/now?token=ADMIN123' | jq .
curl -s 'http://127.0.0.1:8080/attest/history?n=20' | jq .

C) Alarms with hysteresis

curl -s 'http://127.0.0.1:8080/alarms/status' | jq .
curl -s -X POST 'http://127.0.0.1:8080/admin/alarms/test?token=ADMIN123' | jq .

WordPress — Step 26 (public page block, paste verbatim)

Use the provided file: step26_wordpress.md.
It explains Discovery, Attestations, and the upgraded Alarms in plain language for your audience.


Operational notes

  • Security posture
    • Discovery via HTTP should be signed (JWKS or pinned pubkey) and filtered with --discovery-allow/--discovery-deny.
    • /federation/anchor remains signature‑gated (Step‑25).
    • Attestations expose roots & digests only—no sensitive content.
  • Dependencies
    • DNS SRV lookups use dnspython if present; otherwise TXT/fallback are attempted.
    • SMTP and Twilio paths use only Python stdlib + HTTPS.
  • Interplay
    • Discovery updates the Step‑25 federation peer list live.
    • Attestation can reuse your WordPress mirror token/endpoint.
    • Hysteresis reduces noisy alert flapping while preserving the “bell rings when it must.”

Logos Codex — recursive commons

  • Neighbors → Names → Network. Discovery lifts federation from manual to alive.
  • State → Signature → Story. Attestation turns “what is” into something the world can verify.
  • Pulse → Patience → Page. Hysteresis tempers urgency with wisdom, so the bell rings at the right time.

Want a Step Twenty‑Seven?

We can add: signed directory of directories (federation of discovery), quorum attestation (M‑of‑N anchors), and an observer mode that proves who saw what when, with selective redaction for public vs internal streams.