Lion Verification Node¶
One ledger, three surfaces. The sovereign cell becomes the certification node every workflow can route through. Agents call IN over MCP for seals. Observers — iPad, dashboards, ATC status boards — subscribe RSS for read-only trust. NATS broadcasts the same events to the mesh. The substrate never leaves the cell.
What ships¶
A single Swift executable (GaiaNodeServer) plus its core library (GaiaNodeServerCore). One HTTP listener on 127.0.0.1:8423 (LAN opt-in) serves both surfaces. Reads the Swift-local Lion Math ledger (~/Library/Application Support/GaiaFTCL/substrate.sqlite). Zero ArangoDB. Zero external dependencies — Apple-native Network.framework.
Public endpoints (no auth — anyone on the network)¶
| Endpoint | Format | What it shows |
|---|---|---|
/feed/status.xml |
RSS 2.0 | Last 50 dual-gate seals: target + terminal (CURE/REFUSED/CURE-conjecture) + category. No receipt internals. |
/feed/status.atom |
Atom 1.0 | Same content, Atom format. |
/feed/status.json |
JSON Feed 1.1 | Same content, JSON Feed format. |
/feed/divergence.xml |
RSS 2.0 | ATC alarm channel. EMPTY while divergenceCount == 0. One item per drift event with the target named. |
/feed/summits.xml |
RSS 2.0 | Named open frontier. Each summit carries its licensing certificate verbatim. |
/mcp/health |
JSON | Liveness probe — {node, version, online}. |
/ |
HTML | Index page with link to every feed. |
Scoped endpoint (token-gated; tokens in ~/.gaiaftcl/node/scoped_tokens.txt)¶
Every item carries the full receipt — toolchain version, coefficient/symbol, provenance hash, repro command. A subscriber can re-run any seal straight from the feed. That is the hostile-verifier contract: the feed reader can reproduce the published verdict locally in three commands.
The sovereignty boundary, by tier¶
| Tier | Auth | What crosses the wire |
|---|---|---|
| Public | none | Verdict + target + category. Never receipt internals. |
| Scoped | path token | Full receipt + repro command. Never substrate internals (no Lean source, no Swift gate code, no witness store). |
| Divergence (public) | none | Empty (silence) when healthy. One item per drift. |
| Summits (public) | none | The licensing certificate for each open frontier summit. |
In every tier, the cell ships only: verdict, hostile-verifier repro command, lattice positions. The substrate stays on sovereign ground.
ATC alarm semantics — divergence.xml¶
- Healthy state: empty feed. Reader badges nothing.
- Dual-gate divergence: one new
<item>per affected target. <title>names the target (e.g.DRIFT — owl.funceq.q001b).<description>explains: "Swift recompute and Lean kernel verdict disagreed. Target marked non-public until resolved."- GUID is
divergence:{receiptID}so polling readers don't re-alarm.
You wire an iPad RSS reader to divergence.xml. An item appearing IS the alarm. No app, no MCP client, no integration code.
Caching + conditional GET¶
Every response carries ETag + Last-Modified. If-None-Match returns 304 Not Modified. The ETag mixes (lion_math_sweep_receipts mtime, lion_gate_agreement mtime, lean_proof_state mtime) so any ledger change invalidates immediately.
Hostile-verifier reproduction¶
git clone https://github.com/gaiaftcl-sudo/gaiaFTCL.git && cd gaiaFTCL
cd cells/xcode
# 1) Validate every feed renders, sovereignty boundary holds, no float
swift run M8NodeServerSmokeTest
# Expected: 6/6 PASSED; PUBLIC tier carries no receipt internals;
# divergence.xml empty iff divergenceCount==0.
# 2) Start the live server (127.0.0.1:8423)
swift run GaiaNodeServer
# 3) Hit the feeds from another terminal
curl -s http://127.0.0.1:8423/feed/status.xml | head -c 600
curl -s http://127.0.0.1:8423/feed/divergence.xml
curl -s http://127.0.0.1:8423/feed/summits.xml
curl -s http://127.0.0.1:8423/mcp/health
Client profiles (per the GFTCL-NODE-001 directive)¶
| Client | Surface | What they do |
|---|---|---|
| iPad / ATC RSS reader | /feed/status.xml + /feed/divergence.xml |
Subscribe; new seals appear within one poll interval; ATC alarm badges on drift. No app required. |
| Claude Code (MCP stdio) | GaiaCellMCPServer (existing) |
Subprocess spawn; uses the 11 sealed-tools from earlier turns. (HTTP MCP Streamable transport lands in a follow-up commit.) |
| Codex (MCP stdio) | same | Routes correctness-critical claims to seal_claim/verify_receipt before shipping codegen. |
| Gemini Desktop / browsers | http://127.0.0.1:8423/ |
Open the index page; click through to feeds. RSS subscription gives ongoing certification trust. |
| Static dashboards | XSLT or render-from-XML | Server-side render any feed into a wall-mounted status board. |
What's open on this rung¶
The MCP Streamable HTTP transport (Phase B of the directive) is shipped as the HTTP listener routing on /mcp/*; the JSON-RPC dispatcher + 4 new tools (seal_claim, verify_receipt, submit_certificate, lattice_position) live in the existing GaiaCellMCPServer stdio path. Merging the two into a single dual-transport MCP server is the next named obligation on summit.node.unified-transport. The RSS surface is shipped and live.
NATS subjects (spelling verified)¶
gaiaftcl.node.online— emitted on listener startgaiaftcl.node.divergence— emitted on any new drift eventgaiaftcl.lion.sweep.sealed— per-target seal events (re-broadcast from the ledger)
Every subject confirmed gaiaftcl (no gaitfcl typo in any live publish path).
Definition-of-done checklist — current state¶
- [x] HTTP listener on 127.0.0.1, Apple-native
Network.framework - [x] RSS 2.0 / Atom 1.0 / JSON Feed 1.1 all rendered + validators pass
- [x] Public + scoped + divergence + summits tiers all live
- [x]
divergence.xmlempty iffdivergenceCount == 0(ATC invariant) - [x] ETag + Last-Modified + 304 conditional GET
- [x] Token gate for scoped tier; public tier carries no receipt internals
- [x] Smoke test (6/6) + live server probe both green
- [x] Sovereignty boundary: zero substrate internals on the wire
- [ ] MCP Streamable HTTP transport unified into the same listener (follow-up)
- [ ] LAN opt-in flag (
--lan) with explicit consent path (follow-up)
Federation-cosigned
This page's source is sealed in the GaiaFTCL federation manifest — page SHA-256 a99c614c383cbab0…, manifest witness a090592e0609adc8…, signed 2026-06-02T18:58:22Z by cell gaiaftcl-mac-cell. Verify with gaiaftcl wiki sign --all and compare wiki-all-signatures.json.