Skip to content

Commit 59d4339

Browse files
authored
SAN-665: bump spec submodule to SAN-647 HEAD + mirror receipt schema (#72)
Bump the spec submodule pin to sanna-protocol SAN-647 branch HEAD (35950af9b3d7052e61a2f9965ffd8c5e5be046bc) and update the src/sanna/spec/receipt.schema.json mirror to match byte-exact. constitution.schema.json mirror unchanged (SAN-647 did not touch the constitution schema). This is the second stage of a two-stage release. SAN-647 adds optional enforcement.halt_reason + enforcement.constitution_status_evidence fields to the receipt schema, plus spec Section 2.23, Appendix H, and Section 4.6 cross-field consistency rules. SAN-647's cross-sdk-smoke-python CI gate diffs the protocol schema against this mirror; an additive protocol change creates transient drift the gate flags as failure. Landing this PR on sanna main first clears the drift so SAN-647 can re-run the gate green and merge. Additive schema changes; existing receipts and goldens validate unchanged. CFC conditionals only fire when the new optional fields are present.
1 parent 489c5de commit 59d4339

4 files changed

Lines changed: 129 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
## [Unreleased] -- 2026-05-18 (SAN-665)
2+
3+
### Changed
4+
5+
- **`spec` submodule**: bumped to `35950af9b3d7052e61a2f9965ffd8c5e5be046bc` (sanna-protocol SAN-647 branch HEAD). Pulls in optional `enforcement.halt_reason` enum + `enforcement.constitution_status_evidence` object fields on the receipt schema, the corresponding spec Section 2.23 + Appendix H additions, and four new Section 4.6 cross-field consistency rules (CFC-A, CFC-B, CFC-C verifier-side, CFC-D).
6+
- **`src/sanna/spec/receipt.schema.json`**: byte-exact mirror update to match the new submodule HEAD. Satisfies the operational-schema governance gate at `.github/workflows/ci.yml`. `src/sanna/spec/constitution.schema.json` mirror is unchanged (SAN-647 did not touch the constitution schema).
7+
8+
### Why this matters
9+
10+
Sanna-protocol PR #46 (SAN-647) adds the receipt-schema vocabulary the Cloud receipt-ingestion RC blocker (SAN-568) consumes. The protocol PR's cross-sdk-smoke-python CI gate diffs the protocol schema against sanna-repo's SDK mirror at main; an additive protocol schema change creates transient drift the gate flags as failure. Landing this submodule bump + mirror update on sanna main FIRST clears the drift; the protocol PR then re-runs the gate against the updated mirror and passes.
11+
12+
The schema additions are optional/nullable; existing receipts validate unchanged. The new cross-field consistency conditionals (CFC-A, CFC-B, CFC-D) in receipt.schema.json only fire when the new optional fields are present, so the full golden-receipt fixture set and the SDK test suite remain green without modification.
13+
14+
### Notes
15+
16+
- Staged release sequence: SAN-665 (this PR) merges first; sanna-protocol PR #46 re-runs cross-sdk-smoke-python green; PR #46 merges.
17+
- The pinned SHA (`35950af9b3d7052e61a2f9965ffd8c5e5be046bc`) is the SAN-647 PR branch HEAD; after SAN-647 squash-merges and its branch auto-deletes per `delete_branch_on_merge=true` (SAN-543), the SHA remains reachable via the sanna-protocol PR ref (`refs/pull/46/head`). A follow-up cleanup PR will re-pin the spec submodule to the resulting merged-to-main commit so the pin references a commit reachable on sanna-protocol main without going through the PR ref.
18+
- SDK-side fail-closed implementation of the new halt_reason + constitution_status_evidence emission is post-beta scope (separate ticket family); this PR only updates the schema vocabulary.
19+
20+
### Tickets
21+
22+
- SAN-665 (this PR)
23+
- SAN-647 (sanna-protocol protocol/spec change consumed by this submodule bump)
24+
- SAN-568 (Cloud RC blocker consumer of the SAN-647 vocabulary)
25+
26+
---
27+
128
## [Unreleased] -- 2026-05-15 (SAN-540)
229

330
### Changed

docs/state.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!-- auto-generated by tools/generate_state_doc.py — do not edit manually -->
2-
<!-- generated: 2026-05-16T02:27:51Z -->
2+
<!-- generated: 2026-05-18T21:34:06Z -->
33

44
# Sanna Python SDK — State
55

@@ -64,11 +64,15 @@ Count: 132 (`tests/test_*.py` + `tests/reasoning/test_*.py`)
6464

6565
## Latest CHANGELOG Entry
6666

67-
## [Unreleased] -- 2026-05-15 (SAN-540)
67+
## [Unreleased] -- 2026-05-18 (SAN-665)
6868

6969
### Changed
7070

71-
- Refactor golden receipt generators: merge generate_golden.py + generate_legacy_goldens.py into a single cv-parameterized generate_goldens.py using sanna.fingerprint.compute_fingerprints (centralized cv-aware formula from SAN-524). All 13 existing cv=9 fixtures remain byte-identical (verified via git diff --exit-code); cv=5/6/7/8/10 fixtures unchanged. Removes the inline 20-field add_extensions formula. (SAN-540)
71+
- **`spec` submodule**: bumped to `35950af9b3d7052e61a2f9965ffd8c5e5be046bc` (sanna-protocol SAN-647 branch HEAD). Pulls in optional `enforcement.halt_reason` enum + `enforcement.constitution_status_evidence` object fields on the receipt schema, the corresponding spec Section 2.23 + Appendix H additions, and four new Section 4.6 cross-field consistency rules (CFC-A, CFC-B, CFC-C verifier-side, CFC-D).
72+
- **`src/sanna/spec/receipt.schema.json`**: byte-exact mirror update to match the new submodule HEAD. Satisfies the operational-schema governance gate at `.github/workflows/ci.yml`. `src/sanna/spec/constitution.schema.json` mirror is unchanged (SAN-647 did not touch the constitution schema).
7273

73-
---
74+
### Why this matters
7475

76+
Sanna-protocol PR #46 (SAN-647) adds the receipt-schema vocabulary the Cloud receipt-ingestion RC blocker (SAN-568) consumes. The protocol PR's cross-sdk-smoke-python CI gate diffs the protocol schema against sanna-repo's SDK mirror at main; an additive protocol schema change creates transient drift the gate flags as failure. Landing this submodule bump + mirror update on sanna main FIRST clears the drift; the protocol PR then re-runs the gate against the updated mirror and passes.
77+
78+
The schema additions are optional/nullable; existing receipts validate unchanged. The new cross-field consistency conditionals (CFC-A, CFC-B, CFC-D) in receipt.schema.json only fire when the new optional fields are present, so the full golden-receipt fixture set and the SDK test suite remain green without modification.

src/sanna/spec/receipt.schema.json

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,33 @@
354354
"type": "string",
355355
"description": "ISO 8601 timestamp",
356356
"format": "date-time"
357+
},
358+
"halt_reason": {
359+
"type": ["string", "null"],
360+
"description": "Machine-readable categorization of the halt cause when enforcement.action=halted. Stable enum; verifier MUST accept unknown values with informational warning. Spec Section 2.23.",
361+
"enum": ["constitution_revoked", "constitution_status_unavailable", null]
362+
},
363+
"constitution_status_evidence": {
364+
"type": ["object", "null"],
365+
"description": "Audit-quality binding fields tying the halt action to the observed constitution status. Required when halt_reason is in {constitution_revoked, constitution_status_unavailable}. Spec Section 2.23.",
366+
"required": ["constitution_policy_hash", "version", "status_observed", "status_checked_at", "status_etag"],
367+
"properties": {
368+
"constitution_policy_hash": {
369+
"type": "string",
370+
"pattern": "^[a-f0-9]{64}$",
371+
"description": "SHA-256 hex of the observed constitution's policy_hash. MUST equal the receipt's constitution_ref.policy_hash. Spec Section 2.23.4."
372+
},
373+
"version": {"type": "string"},
374+
"status_observed": {
375+
"type": "string",
376+
"enum": ["active", "superseded", "revoked", "draft", "archived", "rejected"]
377+
},
378+
"status_checked_at": {"type": "string", "format": "date-time"},
379+
"status_etag": {"type": "string"},
380+
"activated_at": {"type": ["string", "null"], "format": "date-time"},
381+
"revoked_at": {"type": ["string", "null"], "format": "date-time"}
382+
},
383+
"additionalProperties": false
357384
}
358385
},
359386
"additionalProperties": false
@@ -865,6 +892,72 @@
865892
}
866893
}
867894
}
895+
},
896+
{
897+
"$comment": "CFC-A: enforcement.halt_reason present requires enforcement.action=halted. Spec Section 4.6.",
898+
"if": {
899+
"properties": {
900+
"enforcement": {
901+
"type": "object",
902+
"required": ["halt_reason"],
903+
"properties": {"halt_reason": {"type": "string"}}
904+
}
905+
},
906+
"required": ["enforcement"]
907+
},
908+
"then": {
909+
"properties": {
910+
"enforcement": {
911+
"properties": {"action": {"const": "halted"}}
912+
}
913+
}
914+
}
915+
},
916+
{
917+
"$comment": "CFC-B: enforcement.halt_reason in constitution-status set requires enforcement.constitution_status_evidence present and non-null. Spec Section 4.6.",
918+
"if": {
919+
"properties": {
920+
"enforcement": {
921+
"type": "object",
922+
"required": ["halt_reason"],
923+
"properties": {
924+
"halt_reason": {"enum": ["constitution_revoked", "constitution_status_unavailable"]}
925+
}
926+
}
927+
},
928+
"required": ["enforcement"]
929+
},
930+
"then": {
931+
"properties": {
932+
"enforcement": {
933+
"required": ["constitution_status_evidence"],
934+
"properties": {
935+
"constitution_status_evidence": {"type": "object"}
936+
}
937+
}
938+
}
939+
}
940+
},
941+
{
942+
"$comment": "CFC-D: enforcement.constitution_status_evidence present requires enforcement.halt_reason present (evidence-without-claim prevention). Spec Section 4.6.",
943+
"if": {
944+
"properties": {
945+
"enforcement": {
946+
"type": "object",
947+
"required": ["constitution_status_evidence"],
948+
"properties": {"constitution_status_evidence": {"type": "object"}}
949+
}
950+
},
951+
"required": ["enforcement"]
952+
},
953+
"then": {
954+
"properties": {
955+
"enforcement": {
956+
"required": ["halt_reason"],
957+
"properties": {"halt_reason": {"type": "string"}}
958+
}
959+
}
960+
}
868961
}
869962
],
870963
"$defs": {

0 commit comments

Comments
 (0)