betterwithage commited on
Commit
25487ac
·
verified ·
1 Parent(s): 3fb5a36

forge-family wall: /api/forge/family — server-side ed25519 receipt verification (ReceiptAgent + Khipu)

Browse files

Additive module a11oy_forge_family.py (front-moved route, per-request verification, fail-closed pin mismatch) + registration block in serve.py tail + Dockerfile COPY. Moves the family wall onto a-11-oy.com so a11oy.net can retire. Receipts fetched from the public HF model repos.

Files changed (3) hide show
  1. Dockerfile +6 -0
  2. a11oy_forge_family.py +250 -0
  3. serve.py +20 -0
Dockerfile CHANGED
@@ -1620,6 +1620,12 @@ COPY szl_spend_cap.py ./szl_spend_cap.py
1620
  COPY a11oy_model_intel.py a11oy_experimental_tier.py a11oy_markets.py szl_agent_tts.py szl_gated_delta.py szl_blocksparse.py szl_retrieval_attn.py szl_model_harness.py szl_agent_loop_governed.py szl_crypto_pipeline.py szl_confattest.py szl_agent_operate.py szl_agentloop_brain.py szl_governed_rag.py szl_sovereign_flywheel.py szl_brain_corpus.py szl_verify_transcript.py szl_frontier_index.py szl_whatsnew.py szl_honestywall.py szl_brainmemory.py szl_agentos.py szl_brainground.py szl_brainuncertainty.py szl_brainhealth.py szl_brainwatch.py szl_boot_preflight.py szl_guarded_surface.py szl_status_aggregate.py szl_brainconstitution.py szl_brainagent.py szl_surface_manifests.py szl_source_attestation.py ./
1621
  COPY static/3d/surfaces/gateddelta.js static/3d/surfaces/blocksparse.js static/3d/surfaces/retrievalattn.js static/3d/surfaces/governedagent.js static/3d/surfaces/cryptopipeline.js static/3d/surfaces/confattest.js static/3d/surfaces/agentops.js static/3d/surfaces/frontierindex.js static/3d/surfaces/whatsnew.js static/3d/surfaces/opsdash.js ./static/3d/surfaces/
1622
 
 
 
 
 
 
 
1623
  # git_sha wireup (FORGE-INSTRUCTION-gitsha-quiet-window): surface the deployed commit
1624
  # at the /honest endpoint so a stale box or Space is self-detecting. Provided at build
1625
  # time (box rebuild passes --build-arg SZL_GIT_SHA=$(git rev-parse HEAD); HF Space sets
 
1620
  COPY a11oy_model_intel.py a11oy_experimental_tier.py a11oy_markets.py szl_agent_tts.py szl_gated_delta.py szl_blocksparse.py szl_retrieval_attn.py szl_model_harness.py szl_agent_loop_governed.py szl_crypto_pipeline.py szl_confattest.py szl_agent_operate.py szl_agentloop_brain.py szl_governed_rag.py szl_sovereign_flywheel.py szl_brain_corpus.py szl_verify_transcript.py szl_frontier_index.py szl_whatsnew.py szl_honestywall.py szl_brainmemory.py szl_agentos.py szl_brainground.py szl_brainuncertainty.py szl_brainhealth.py szl_brainwatch.py szl_boot_preflight.py szl_guarded_surface.py szl_status_aggregate.py szl_brainconstitution.py szl_brainagent.py szl_surface_manifests.py szl_source_attestation.py ./
1621
  COPY static/3d/surfaces/gateddelta.js static/3d/surfaces/blocksparse.js static/3d/surfaces/retrievalattn.js static/3d/surfaces/governedagent.js static/3d/surfaces/cryptopipeline.js static/3d/surfaces/confattest.js static/3d/surfaces/agentops.js static/3d/surfaces/frontierindex.js static/3d/surfaces/whatsnew.js static/3d/surfaces/opsdash.js ./static/3d/surfaces/
1622
 
1623
+ # FORGE-FAMILY WALL (2026-07-14): /api/forge/family — server-side ed25519
1624
+ # re-verification of the owner-signed model receipts (ReceiptAgent + Khipu),
1625
+ # fetched from the public HF model repos. Moves the family wall onto
1626
+ # a-11-oy.com so a11oy.net can retire. Additive module, front-moved route.
1627
+ COPY a11oy_forge_family.py ./a11oy_forge_family.py
1628
+
1629
  # git_sha wireup (FORGE-INSTRUCTION-gitsha-quiet-window): surface the deployed commit
1630
  # at the /honest endpoint so a stale box or Space is self-detecting. Provided at build
1631
  # time (box rebuild passes --build-arg SZL_GIT_SHA=$(git rev-parse HEAD); HF Space sets
a11oy_forge_family.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # © 2026 Lutar, Stephen P. — SZL Holdings
3
+ """
4
+ a11oy forge-family wall — GET /api/forge/family
5
+
6
+ The public evidence wall for the owner-forged model family:
7
+ * SZL-Forge-1.5B-ReceiptAgent (owner keyId e7f01810aaa97394)
8
+ * SZL-Khipu-1.5B-BrainNavigator (owner keyId 89540347a69b789e)
9
+
10
+ Doctrine: provenance, not vibes. Every band is re-verified SERVER-SIDE on every
11
+ request from the owner-signed receipt files fetched from the public HF model
12
+ repos (receipt BYTES are cached briefly to spare the Hub; the cryptographic
13
+ verification itself runs on every request and is never cached or skipped).
14
+ Nothing is asserted that an ed25519 signature does not prove:
15
+
16
+ per receipt (training + eval):
17
+ - the canonical string must reproduce BYTE-EXACTLY from the payload
18
+ (sorted keys, compact separators — the forge kit signer's rules)
19
+ - the ed25519 signature must verify over the canonical bytes
20
+ - the embedded SPKI and keyId must equal owner_pubkey.json's, and the
21
+ keyId must equal sha256(SPKI DER)[:16]
22
+ per model:
23
+ - eval payload.trainingReceiptSha256 must equal sha256(training canonical)
24
+ - keyTrust: "PINNED" when the A11OY_*_OWNER_KEYID env pin matches the
25
+ verified keyId; a set-but-different pin is "PIN_MISMATCH" and FAILS THE
26
+ BAND CLOSED; no pin set is "REPO_DECLARED".
27
+
28
+ Counts (planValid / grounding / abstain / hallucinatedCitations) are DERIVED
29
+ from the verified eval payload — never hand-typed. Failures are loud: a band
30
+ that cannot be verified says so explicitly; nothing silently degrades.
31
+
32
+ Additive module per Space convention: register(app) adds the route and
33
+ front-moves it so the exact JSON path wins over the SPA history fallback and
34
+ the /api proxy. No new dependencies (httpx + cryptography are pinned in the
35
+ image).
36
+ """
37
+
38
+ import base64
39
+ import hashlib
40
+ import json
41
+ import os
42
+ import time
43
+ from datetime import datetime, timezone
44
+
45
+ import httpx
46
+ from cryptography.hazmat.primitives.serialization import load_der_public_key
47
+ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
48
+
49
+ _ROUTE = "/api/forge/family"
50
+ _HF = "https://huggingface.co"
51
+ _RECEIPT_FILES = ("owner_pubkey.json", "training_receipt.signed.json", "eval_receipt.signed.json")
52
+ _CACHE_TTL_SECONDS = 300 # receipt BYTES only; verification always re-runs
53
+
54
+ _MODELS = (
55
+ {
56
+ "model": "receiptagent",
57
+ "displayName": "SZL-Forge-1.5B-ReceiptAgent",
58
+ "hfRepo": "SZLHOLDINGS/SZL-Forge-1.5B-ReceiptAgent",
59
+ "pinEnv": "A11OY_OWNER_KEYID",
60
+ },
61
+ {
62
+ "model": "khipu",
63
+ "displayName": "SZL-Khipu-1.5B-BrainNavigator",
64
+ "hfRepo": "SZLHOLDINGS/SZL-Khipu-1.5B-BrainNavigator",
65
+ "pinEnv": "A11OY_KHIPU_OWNER_KEYID",
66
+ },
67
+ )
68
+
69
+ # repo -> {"at": epoch, "files": {name: bytes}}
70
+ _byte_cache: dict = {}
71
+
72
+
73
+ def _now_iso() -> str:
74
+ return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
75
+
76
+
77
+ def _sha256_hex(data: bytes) -> str:
78
+ return hashlib.sha256(data).hexdigest()
79
+
80
+
81
+ def _canonical(payload: dict) -> str:
82
+ """The forge kit's canonical form: sorted keys, compact separators, raw UTF-8."""
83
+ return json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
84
+
85
+
86
+ async def _fetch_receipt_bytes(client: httpx.AsyncClient, repo: str) -> dict:
87
+ cached = _byte_cache.get(repo)
88
+ if cached and (time.time() - cached["at"]) < _CACHE_TTL_SECONDS:
89
+ return cached
90
+ files = {}
91
+ for name in _RECEIPT_FILES:
92
+ resp = await client.get(f"{_HF}/{repo}/resolve/main/{name}")
93
+ resp.raise_for_status()
94
+ files[name] = resp.content
95
+ entry = {"at": time.time(), "files": files}
96
+ _byte_cache[repo] = entry
97
+ return entry
98
+
99
+
100
+ def _verify_one_receipt(receipt: dict, owner_spki_b64: str, owner_key_id: str, expected_kind_word: str) -> dict:
101
+ """Run every check for one signed receipt. Returns {check_name: bool} + meta."""
102
+ checks = {}
103
+ payload = receipt.get("payload") or {}
104
+ canonical = receipt.get("canonical") or ""
105
+ checks["canonicalReproducesFromPayload"] = _canonical(payload) == canonical
106
+ checks["embeddedSpkiMatchesOwner"] = receipt.get("publicKeySpkiBase64") == owner_spki_b64
107
+ checks["embeddedKeyIdMatchesOwner"] = receipt.get("keyId") == owner_key_id
108
+ checks["payloadKeyIdMatchesOwner"] = payload.get("keyId") == owner_key_id
109
+ kind = str(payload.get("kind", ""))
110
+ checks["kindLooksRight"] = expected_kind_word in kind.lower()
111
+ sig_ok = False
112
+ try:
113
+ spki_der = base64.b64decode(owner_spki_b64, validate=True)
114
+ public_key = load_der_public_key(spki_der)
115
+ if isinstance(public_key, Ed25519PublicKey):
116
+ public_key.verify(
117
+ base64.b64decode(receipt.get("signatureBase64", ""), validate=True),
118
+ canonical.encode("utf-8"),
119
+ )
120
+ sig_ok = True
121
+ except Exception:
122
+ sig_ok = False
123
+ checks["ed25519SignatureVerifies"] = sig_ok
124
+ return {
125
+ "checks": checks,
126
+ "allPassed": all(checks.values()),
127
+ "kind": kind,
128
+ "canonicalSha256": _sha256_hex(canonical.encode("utf-8")),
129
+ "payload": payload,
130
+ }
131
+
132
+
133
+ def _band_for_model(cfg: dict, raw_files: dict, fetched_at_epoch: float) -> dict:
134
+ """Build one fully-verified wall band. Verification runs on every call."""
135
+ owner = json.loads(raw_files["owner_pubkey.json"])
136
+ training = json.loads(raw_files["training_receipt.signed.json"])
137
+ evaluation = json.loads(raw_files["eval_receipt.signed.json"])
138
+
139
+ owner_spki_b64 = owner.get("publicKeySpkiBase64", "")
140
+ owner_key_id = owner.get("keyId", "")
141
+ owner_checks = {
142
+ "ownerAlgoIsEd25519": owner.get("algo") == "ed25519",
143
+ "ownerKeyIdDerivesFromSpki": (
144
+ _sha256_hex(base64.b64decode(owner_spki_b64)) [:16] == owner_key_id
145
+ if owner_spki_b64 else False
146
+ ),
147
+ }
148
+
149
+ training_result = _verify_one_receipt(training, owner_spki_b64, owner_key_id, "train")
150
+ eval_result = _verify_one_receipt(evaluation, owner_spki_b64, owner_key_id, "eval")
151
+
152
+ chain_ok = (
153
+ eval_result["payload"].get("trainingReceiptSha256")
154
+ == _sha256_hex((training.get("canonical") or "").encode("utf-8"))
155
+ )
156
+
157
+ pin_env = cfg["pinEnv"]
158
+ pinned_value = os.environ.get(pin_env, "").strip()
159
+ if not pinned_value:
160
+ key_trust = "REPO_DECLARED"
161
+ pin_ok = True
162
+ elif pinned_value == owner_key_id:
163
+ key_trust = "PINNED"
164
+ pin_ok = True
165
+ else:
166
+ key_trust = "PIN_MISMATCH" # fail CLOSED
167
+ pin_ok = False
168
+
169
+ training_verified = owner_checks["ownerAlgoIsEd25519"] and owner_checks["ownerKeyIdDerivesFromSpki"] and training_result["allPassed"] and pin_ok
170
+ eval_verified = owner_checks["ownerAlgoIsEd25519"] and owner_checks["ownerKeyIdDerivesFromSpki"] and eval_result["allPassed"] and chain_ok and pin_ok
171
+ ep = eval_result["payload"]
172
+ tp = training_result["payload"]
173
+
174
+ return {
175
+ "model": cfg["model"],
176
+ "displayName": cfg["displayName"],
177
+ "hfRepo": cfg["hfRepo"],
178
+ "keyId": owner_key_id,
179
+ "keyTrust": key_trust,
180
+ "pinEnv": pin_env,
181
+ "verified": training_verified and eval_verified,
182
+ "status": (
183
+ (["TRAINED_RECEIPT_VERIFIED"] if training_verified else ["TRAINING_RECEIPT_FAILED"])
184
+ + (["EVAL_RECEIPT_VERIFIED"] if eval_verified else ["EVAL_RECEIPT_FAILED"])
185
+ ),
186
+ "checks": {
187
+ "owner": owner_checks,
188
+ "training": training_result["checks"],
189
+ "eval": eval_result["checks"],
190
+ "evalChainsToTraining": chain_ok,
191
+ },
192
+ "derived": {
193
+ "baseModel": tp.get("baseModel"),
194
+ "trainedAt": tp.get("trainedAt"),
195
+ "finalTrainLoss": tp.get("finalTrainLoss"),
196
+ "evaluatedAt": ep.get("evaluatedAt"),
197
+ "planValid": ep.get("planValid"),
198
+ "planTotal": ep.get("planTotal"),
199
+ "groundingCorrect": ep.get("groundingCorrect"),
200
+ "groundingTotal": ep.get("groundingTotal"),
201
+ "abstainCorrect": ep.get("abstainCorrect"),
202
+ "abstainTotal": ep.get("abstainTotal"),
203
+ "hallucinatedCitationCount": ep.get("hallucinatedCitationCount"),
204
+ },
205
+ "receiptFiles": {
206
+ name: {"sha256": _sha256_hex(raw_files[name]), "bytes": len(raw_files[name])}
207
+ for name in _RECEIPT_FILES
208
+ },
209
+ "receiptBytesCacheAgeSeconds": round(time.time() - fetched_at_epoch, 1),
210
+ }
211
+
212
+
213
+ async def _forge_family_handler():
214
+ bands = []
215
+ async with httpx.AsyncClient(timeout=10.0, follow_redirects=True) as client:
216
+ for cfg in _MODELS:
217
+ try:
218
+ entry = await _fetch_receipt_bytes(client, cfg["hfRepo"])
219
+ bands.append(_band_for_model(cfg, entry["files"], entry["at"]))
220
+ except Exception as band_error: # loud, honest, isolated per band
221
+ bands.append({
222
+ "model": cfg["model"],
223
+ "displayName": cfg["displayName"],
224
+ "hfRepo": cfg["hfRepo"],
225
+ "verified": False,
226
+ "status": ["UNAVAILABLE"],
227
+ "error": f"{type(band_error).__name__}: {band_error}",
228
+ })
229
+ return {
230
+ "ok": all(b.get("verified") is True for b in bands),
231
+ "wall": "forge-family",
232
+ "servedFrom": "a-11-oy.com (a11oy flagship Space)",
233
+ "verifier": {
234
+ "mode": "ed25519 via cryptography, server-side",
235
+ "perRequest": True,
236
+ "note": "receipt bytes cached briefly; verification never cached",
237
+ },
238
+ "generatedAt": _now_iso(),
239
+ "models": bands,
240
+ }
241
+
242
+
243
+ def register(app) -> str:
244
+ """Additive registration + front-move (exact route must beat SPA fallback)."""
245
+ app.add_api_route(_ROUTE, _forge_family_handler, methods=["GET"], include_in_schema=False)
246
+ for index, route in enumerate(app.router.routes):
247
+ if getattr(route, "path", None) == _ROUTE:
248
+ app.router.routes.insert(0, app.router.routes.pop(index))
249
+ break
250
+ return f"{_ROUTE} (bands: {', '.join(m['model'] for m in _MODELS)})"
serve.py CHANGED
@@ -13430,6 +13430,26 @@ except Exception as _szl_source_error: # additive: never take down the SPA
13430
  )
13431
 
13432
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13433
  if __name__ == "__main__":
13434
  import uvicorn
13435
  port = int(os.environ.get("PORT", "7860"))
 
13430
  )
13431
 
13432
 
13433
+ # ============================================================================
13434
+ # FORGE FAMILY WALL (2026-07-14): /api/forge/family — the public evidence wall
13435
+ # for the owner-forged model family (ReceiptAgent + Khipu). Server-side ed25519
13436
+ # re-verification on every request; receipts fetched from the public HF model
13437
+ # repos (bytes cached briefly, verification never skipped). Front-moved inside
13438
+ # the module so the exact JSON route wins over the SPA history fallback and the
13439
+ # /api proxy. Moves the wall onto a-11-oy.com so a11oy.net can retire.
13440
+ # ============================================================================
13441
+ try:
13442
+ import a11oy_forge_family as _a11oy_forge_family
13443
+
13444
+ _forge_family_result = _a11oy_forge_family.register(app)
13445
+ print(f"[a11oy] forge-family wall registered (front-moved): {_forge_family_result}", file=sys.stderr)
13446
+ except Exception as _forge_family_error: # additive: never take down the SPA
13447
+ print(
13448
+ f"[a11oy] forge-family wall NOT registered (non-fatal): {_forge_family_error!r}",
13449
+ file=sys.stderr,
13450
+ )
13451
+
13452
+
13453
  if __name__ == "__main__":
13454
  import uvicorn
13455
  port = int(os.environ.get("PORT", "7860"))