Federation Cosignature Verification¶
Every substrate row Franklin emits carries a 5-context federation cosignature quintet sealing the row's canonical witness. The Python client surfaces verification through gaiaftcl.federation.verify_signature_quintet.
The five contexts¶
| Context | Substrate meaning |
|---|---|
1. cellID |
The substrate cell's identifier (e.g. gaiaftcl-mac-cell) |
2. domainID |
The substrate operation's domain (e.g. qc020-substrate-research-telemetry) |
3. leanArtifactPath |
The Lean 4 artifact path the substrate witnesses against |
4. payloadCanonical |
The row's canonical witness string |
5. tauBlock |
The substrate's Tau (block-time) marker |
The substrate writes signature_quintet as a JSON-array string. Each entry is either a bare signature string (substrate's self-signed default) or a full {cell_id, domain_id, lean_artifact_path, payload_canonical, tau_block, signature} object.
Witness hash invariant¶
For any substrate row:
Bit-exact. The verify_signature_quintet function recomputes this hash and compares against the substrate-written value as the verification anchor.
Self-signed verification (default)¶
from gaiaftcl import FranklinClient
from gaiaftcl.federation.cosignature import verify_signature_quintet
with FranklinClient.connect() as franklin:
hb = franklin.heartbeat_history(limit=1)[0]
ok = verify_signature_quintet(
canonical_witness=hb.canonical_witness,
witness_hash_sha256=hb.witness_hash_sha256,
signature_quintet_json=hb.signature_quintet,
)
assert ok
True means the witness hash is bit-exact equivalent to the canonical-witness SHA-256, and the signature quintet contains at least one context.
Full federation verification¶
Provide the federation public-key set:
ok = verify_signature_quintet(
canonical_witness=hb.canonical_witness,
witness_hash_sha256=hb.witness_hash_sha256,
signature_quintet_json=hb.signature_quintet,
federation_public_keys=[
"ed25519:...", "ed25519:...", "ed25519:...",
"ed25519:...", "ed25519:...",
],
)
Full path requires:
- Exactly 5 quintet contexts
- Exactly 5 federation public keys
- Each context's signature verifies against the corresponding key
The signing scheme is operator-configured via ~/.gaiaftcl/federation_keys.toml.
Parse the quintet into a typed object¶
from gaiaftcl.federation.cosignature import FederationCosignature
quintet = FederationCosignature.parse(
signature_quintet_json=hb.signature_quintet,
canonical_witness=hb.canonical_witness,
)
for ctx in quintet.contexts:
print(ctx.cell_id, ctx.domain_id, ctx.signature[:16], "...")
Verification failure modes¶
| Failure | Meaning | Action |
|---|---|---|
| witness hash mismatch | Substrate-written hash differs from SHA-256(canonical_witness) |
Substrate divergence or row corruption — surface to operator |
| empty quintet | signature_quintet empty array |
Substrate writer skipped federation seal — operator bug; surface |
| quintet length ≠ 5 with full federation mode | Substrate wrote partial quintet | Federation configuration drift; operator must reconcile |
| signature verification fails | Public key mismatch | Federation public keys out of sync; operator reconciles federation_keys.toml |
Verification in a loop¶
from gaiaftcl import FranklinClient
from gaiaftcl.federation.cosignature import verify_signature_quintet
with FranklinClient.connect() as franklin:
hbs = franklin.heartbeat_history(limit=1000)
failed = [h for h in hbs
if not verify_signature_quintet(
h.canonical_witness,
h.witness_hash_sha256,
h.signature_quintet)]
print(f"verified: {len(hbs) - len(failed)} / {len(hbs)}")
if failed:
print("first failure:", failed[0].heartbeat_id, failed[0].tick_at_iso)
A healthy substrate produces 100% verification rate. Any failure is operationally significant.
Federation cosignature is the substrate's verifiable seal. The Python client surfaces verification as a primitive operation.
Federation-cosigned
This page's source is sealed in the GaiaFTCL federation manifest — page SHA-256 b5028ea48a8a5a19…, 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.