Step Twenty‑Six — Find the peers; attest the truth; calm the sirens.(Peer discovery • Public attestations • Hysteresis + multi‑channel alerts)

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.