From 0597f4832d2e88db49da376ccbf77f868990739e Mon Sep 17 00:00:00 2001 From: Midia Kiasat Date: Sun, 19 Apr 2026 17:01:10 +0200 Subject: [PATCH] Publish REGRESSORIUM recourse boundary objects and audit schemas --- OBLIGATION_MODEL.md | 7 + README.md | 6 +- claims/current/index.json | 3 +- claims/history/README.md | 2 + contracts/boundary-policy.json | 67 +++++++++ fixtures/recourse-audit-record.valid.json | 25 +++ fixtures/recourse-output.valid.json | 26 ++++ .../recourse-audit-record.example.json | 25 +++ outputs/examples/recourse-output.example.json | 25 +++ schemas/boundary-policy.schema.json | 142 ++++++++++++++++++ schemas/recourse-audit-record.schema.json | 112 ++++++++++++++ schemas/recourse-object.schema.json | 119 +++++++++------ schemas/recourse-output.schema.json | 87 +++++++++++ tests/test_boundary_policy_schema_smoke.py | 10 ++ tests/test_recourse_audit_schema_smoke.py | 10 ++ ...t_recourse_boundary_negative_assertions.py | 37 +++++ tests/test_recourse_output_schema_smoke.py | 10 ++ tests/verify_boundary_object_minimum.py | 95 ++++++++++++ 18 files changed, 758 insertions(+), 50 deletions(-) create mode 100644 contracts/boundary-policy.json create mode 100644 fixtures/recourse-audit-record.valid.json create mode 100644 fixtures/recourse-output.valid.json create mode 100644 outputs/examples/recourse-audit-record.example.json create mode 100644 outputs/examples/recourse-output.example.json create mode 100644 schemas/boundary-policy.schema.json create mode 100644 schemas/recourse-audit-record.schema.json create mode 100644 schemas/recourse-output.schema.json create mode 100644 tests/test_boundary_policy_schema_smoke.py create mode 100644 tests/test_recourse_audit_schema_smoke.py create mode 100644 tests/test_recourse_boundary_negative_assertions.py create mode 100644 tests/test_recourse_output_schema_smoke.py create mode 100755 tests/verify_boundary_object_minimum.py diff --git a/OBLIGATION_MODEL.md b/OBLIGATION_MODEL.md index ec4347c..0b52493 100644 --- a/OBLIGATION_MODEL.md +++ b/OBLIGATION_MODEL.md @@ -10,3 +10,10 @@ Required fields for any obligation model: - remedy path - escalation path - closure rule + +## Machine-readable boundary surfaces + +- `contracts/boundary-policy.json` +- `schemas/boundary-policy.schema.json` +- `schemas/recourse-output.schema.json` +- `schemas/recourse-audit-record.schema.json` diff --git a/README.md b/README.md index 5885b65..3da18ea 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ It determines burden, remedy, escalation, and closure of bounded claims without ## Status -Active public sovereign boundary with an explicit terminal recourse role inside the Verifrax stack. +Active public sovereign boundary with an explicit terminal recourse role, machine-readable boundary policy, typed recourse schemas, and audit surfaces. ## Boundary @@ -26,6 +26,8 @@ It does not replace adjacent sovereign boundaries. - defines terminal-recourse doctrine - defines counterparty, burden, remedy, escalation, and closure rules - publishes recourse-object structure +- publishes machine-readable boundary policy through `contracts/boundary-policy.json` +- publishes typed recourse output and audit schemas through `schemas/` - publishes current and historical recourse indexes - publishes the current recourse-object entry surface - preserves recourse as a distinct sovereign function @@ -43,7 +45,7 @@ It does not replace adjacent sovereign boundaries. ## Public surface -The public surface of this repository is its repository identity, README boundary, recourse doctrine, recourse-object schema, the current recourse-object entry surface, and explicit current/historical recourse indexes. +The public surface of this repository is its repository identity, README boundary, recourse doctrine, `contracts/boundary-policy.json`, typed schemas, the current recourse-object entry surface, and explicit current/historical recourse indexes. Recourse here is not recognition. Recourse here is not verification. diff --git a/claims/current/index.json b/claims/current/index.json index 0280a09..dc29fa4 100644 --- a/claims/current/index.json +++ b/claims/current/index.json @@ -9,5 +9,6 @@ "subject_ref": "https://github.com/Verifrax/VERIFRAX/blob/main/evidence/artifact-0005/artifact-0005.json", "recourse_status": "OPEN_FOR_RECOURSE" } - ] + ], + "historical": false } diff --git a/claims/history/README.md b/claims/history/README.md index a4945db..53a8ca1 100644 --- a/claims/history/README.md +++ b/claims/history/README.md @@ -5,3 +5,5 @@ This directory stores superseded or closed historical recourse objects. Historical recourse objects remain auditable and reconstructable. They must not outrank the current recourse object published under `claims/current/`. + +Historical recourse objects remain subordinate to the current active recourse index and may not replace recognition, law, state, authority, execution, or verification. diff --git a/contracts/boundary-policy.json b/contracts/boundary-policy.json new file mode 100644 index 0000000..ca40b6f --- /dev/null +++ b/contracts/boundary-policy.json @@ -0,0 +1,67 @@ +{ + "object_type": "BOUNDARY_POLICY", + "surface": "REGRESSORIUM", + "schema_version": "0.1.0", + "state_type": "ACTIVE_TRUTH", + "role": "terminal-recourse", + "allowed_inputs": [ + "recognition-object-reference", + "claim-class-reference", + "law-version-reference", + "accepted-epoch-reference", + "authority-object-reference", + "execution-receipt-reference", + "verification-result-reference", + "operator-request" + ], + "allowed_output_classes": [ + "recourse-object", + "recourse-output-record", + "recourse-audit-record", + "recourse-index-update" + ], + "forbidden_output_classes": [ + "law-object", + "accepted-state-object", + "authority-object", + "execution-receipt", + "verification-verdict", + "recognition-object", + "proof-publication-object", + "intake-decision-object" + ], + "required_boundary_assertions": [ + "not-law", + "not-state", + "not-authority", + "not-execution", + "not-verification", + "not-recognition", + "not-proof", + "not-intake", + "recourse-downstream-of-recognition" + ], + "rejection_reasons": [ + "input-class-unsupported", + "output-class-unsupported", + "would-author-law", + "would-mutate-accepted-state", + "would-issue-authority", + "would-execute-governed-action", + "would-emit-verification-verdict", + "would-recognize-terminal-truth", + "would-publish-proof-authority", + "would-operate-intake-authority" + ], + "adjacent_sovereign_surfaces": { + "law": "SYNTAGMARIUM", + "state": "ORBISTIUM", + "reconciliation": "CONSONORIUM", + "cognition": "TACHYRIUM", + "authority": "AUCTORISEAL", + "execution": "CORPIFORM", + "verification": "VERIFRAX", + "recognition": "ANAGNORIUM" + }, + "review_rule": "recourse-object-requires-explicit-recognition-basis-and-non-recognition-boundary" +} diff --git a/fixtures/recourse-audit-record.valid.json b/fixtures/recourse-audit-record.valid.json new file mode 100644 index 0000000..e4e13a5 --- /dev/null +++ b/fixtures/recourse-audit-record.valid.json @@ -0,0 +1,25 @@ +{ + "object_type": "RECOURSE_AUDIT_RECORD", + "schema_version": "0.1.0", + "audit_id": "regressorium-audit-0001", + "timestamp": "2026-04-19T16:55:36Z", + "input_class": "operator-request", + "requested_output_class": "recognition-object", + "decision": "rejected", + "rejection_reason": "would-recognize-terminal-truth", + "boundary_zone": "outside-regressorium-boundary", + "sovereign_collision_flags": { + "law": false, + "state": false, + "authority": false, + "execution": false, + "verification": false, + "recognition": true, + "proof": false, + "intake": false + }, + "notes": [ + "Terminal recognition belongs upstream of terminal recourse.", + "Request must leave REGRESSORIUM and move to ANAGNORIUM." + ] +} diff --git a/fixtures/recourse-output.valid.json b/fixtures/recourse-output.valid.json new file mode 100644 index 0000000..b7bb978 --- /dev/null +++ b/fixtures/recourse-output.valid.json @@ -0,0 +1,26 @@ +{ + "object_type": "RECOURSE_OUTPUT", + "schema_version": "0.1.0", + "output_id": "regressorium-output-0001", + "generated_at": "2026-04-19T16:55:36Z", + "input_class": "recognition-object-reference", + "output_class": "recourse-object", + "status": "ACTIVE_TRUTH", + "summary": "Terminal recourse emitted with explicit downstream-of-recognition boundary.", + "recourse_scope": "terminal recourse only", + "boundary_assertions": { + "not-law": true, + "not-state": true, + "not-authority": true, + "not-execution": true, + "not-verification": true, + "not-recognition": true, + "not-proof": true, + "not-intake": true, + "recourse-downstream-of-recognition": true + }, + "basis_refs": [ + "claims/current/recourse-object-0001.json", + "claims/current/index.json" + ] +} diff --git a/outputs/examples/recourse-audit-record.example.json b/outputs/examples/recourse-audit-record.example.json new file mode 100644 index 0000000..844cbe4 --- /dev/null +++ b/outputs/examples/recourse-audit-record.example.json @@ -0,0 +1,25 @@ +{ + "object_type": "RECOURSE_AUDIT_RECORD", + "schema_version": "0.1.0", + "audit_id": "regressorium-audit-example-0001", + "timestamp": "2026-04-19T16:55:36Z", + "input_class": "operator-request", + "requested_output_class": "verification-verdict", + "decision": "rejected", + "rejection_reason": "would-emit-verification-verdict", + "boundary_zone": "outside-regressorium-boundary", + "sovereign_collision_flags": { + "law": false, + "state": false, + "authority": false, + "execution": false, + "verification": true, + "recognition": false, + "proof": false, + "intake": false + }, + "notes": [ + "Verification remains upstream of terminal recourse.", + "REGRESSORIUM may not emit verification verdicts." + ] +} diff --git a/outputs/examples/recourse-output.example.json b/outputs/examples/recourse-output.example.json new file mode 100644 index 0000000..4ce40cc --- /dev/null +++ b/outputs/examples/recourse-output.example.json @@ -0,0 +1,25 @@ +{ + "object_type": "RECOURSE_OUTPUT", + "schema_version": "0.1.0", + "output_id": "regressorium-output-example-0001", + "generated_at": "2026-04-19T16:55:36Z", + "input_class": "recognition-object-reference", + "output_class": "recourse-index-update", + "status": "DERIVED_PROJECTION", + "summary": "Recourse index update derived from the active recourse object.", + "recourse_scope": "current recourse publication only", + "boundary_assertions": { + "not-law": true, + "not-state": true, + "not-authority": true, + "not-execution": true, + "not-verification": true, + "not-recognition": true, + "not-proof": true, + "not-intake": true, + "recourse-downstream-of-recognition": true + }, + "basis_refs": [ + "claims/current/index.json" + ] +} diff --git a/schemas/boundary-policy.schema.json b/schemas/boundary-policy.schema.json new file mode 100644 index 0000000..730cf1b --- /dev/null +++ b/schemas/boundary-policy.schema.json @@ -0,0 +1,142 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://verifrax.net/regressorium/schemas/boundary-policy.schema.json", + "title": "REGRESSORIUM Boundary Policy", + "type": "object", + "additionalProperties": false, + "required": [ + "object_type", + "surface", + "schema_version", + "state_type", + "role", + "allowed_inputs", + "allowed_output_classes", + "forbidden_output_classes", + "required_boundary_assertions", + "rejection_reasons", + "adjacent_sovereign_surfaces", + "review_rule" + ], + "properties": { + "object_type": { "const": "BOUNDARY_POLICY" }, + "surface": { "const": "REGRESSORIUM" }, + "schema_version": { + "type": "string", + "pattern": "^\\d+\\.\\d+\\.\\d+$" + }, + "state_type": { "const": "ACTIVE_TRUTH" }, + "role": { "const": "terminal-recourse" }, + "allowed_inputs": { + "type": "array", + "uniqueItems": true, + "minItems": 1, + "items": { + "enum": [ + "recognition-object-reference", + "claim-class-reference", + "law-version-reference", + "accepted-epoch-reference", + "authority-object-reference", + "execution-receipt-reference", + "verification-result-reference", + "operator-request" + ] + } + }, + "allowed_output_classes": { + "type": "array", + "uniqueItems": true, + "minItems": 1, + "items": { + "enum": [ + "recourse-object", + "recourse-output-record", + "recourse-audit-record", + "recourse-index-update" + ] + } + }, + "forbidden_output_classes": { + "type": "array", + "uniqueItems": true, + "minItems": 1, + "items": { + "enum": [ + "law-object", + "accepted-state-object", + "authority-object", + "execution-receipt", + "verification-verdict", + "recognition-object", + "proof-publication-object", + "intake-decision-object" + ] + } + }, + "required_boundary_assertions": { + "type": "array", + "uniqueItems": true, + "minItems": 1, + "items": { + "enum": [ + "not-law", + "not-state", + "not-authority", + "not-execution", + "not-verification", + "not-recognition", + "not-proof", + "not-intake", + "recourse-downstream-of-recognition" + ] + } + }, + "rejection_reasons": { + "type": "array", + "uniqueItems": true, + "minItems": 1, + "items": { + "enum": [ + "input-class-unsupported", + "output-class-unsupported", + "would-author-law", + "would-mutate-accepted-state", + "would-issue-authority", + "would-execute-governed-action", + "would-emit-verification-verdict", + "would-recognize-terminal-truth", + "would-publish-proof-authority", + "would-operate-intake-authority" + ] + } + }, + "adjacent_sovereign_surfaces": { + "type": "object", + "additionalProperties": false, + "required": [ + "law", + "state", + "reconciliation", + "cognition", + "authority", + "execution", + "verification", + "recognition" + ], + "properties": { + "law": { "const": "SYNTAGMARIUM" }, + "state": { "const": "ORBISTIUM" }, + "reconciliation": { "const": "CONSONORIUM" }, + "cognition": { "const": "TACHYRIUM" }, + "authority": { "const": "AUCTORISEAL" }, + "execution": { "const": "CORPIFORM" }, + "verification": { "const": "VERIFRAX" }, + "recognition": { "const": "ANAGNORIUM" } + } + }, + "review_rule": { + "const": "recourse-object-requires-explicit-recognition-basis-and-non-recognition-boundary" + } + } +} diff --git a/schemas/recourse-audit-record.schema.json b/schemas/recourse-audit-record.schema.json new file mode 100644 index 0000000..f1fdf94 --- /dev/null +++ b/schemas/recourse-audit-record.schema.json @@ -0,0 +1,112 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://verifrax.net/regressorium/schemas/recourse-audit-record.schema.json", + "title": "REGRESSORIUM Recourse Audit Record", + "type": "object", + "additionalProperties": false, + "required": [ + "object_type", + "schema_version", + "audit_id", + "timestamp", + "input_class", + "requested_output_class", + "decision", + "rejection_reason", + "boundary_zone", + "sovereign_collision_flags", + "notes" + ], + "properties": { + "object_type": { "const": "RECOURSE_AUDIT_RECORD" }, + "schema_version": { + "type": "string", + "pattern": "^\\d+\\.\\d+\\.\\d+$" + }, + "audit_id": { "type": "string", "minLength": 1 }, + "timestamp": { "type": "string", "format": "date-time" }, + "input_class": { + "enum": [ + "recognition-object-reference", + "claim-class-reference", + "law-version-reference", + "accepted-epoch-reference", + "authority-object-reference", + "execution-receipt-reference", + "verification-result-reference", + "operator-request" + ] + }, + "requested_output_class": { + "enum": [ + "recourse-object", + "recourse-index-update", + "law-object", + "accepted-state-object", + "authority-object", + "execution-receipt", + "verification-verdict", + "recognition-object", + "proof-publication-object", + "intake-decision-object" + ] + }, + "decision": { + "enum": [ + "emitted", + "rejected", + "redirected" + ] + }, + "rejection_reason": { + "enum": [ + "not-applicable", + "input-class-unsupported", + "output-class-unsupported", + "would-author-law", + "would-mutate-accepted-state", + "would-issue-authority", + "would-execute-governed-action", + "would-emit-verification-verdict", + "would-recognize-terminal-truth", + "would-publish-proof-authority", + "would-operate-intake-authority" + ] + }, + "boundary_zone": { + "enum": [ + "regressorium-recourse", + "outside-regressorium-boundary" + ] + }, + "sovereign_collision_flags": { + "type": "object", + "additionalProperties": false, + "required": [ + "law", + "state", + "authority", + "execution", + "verification", + "recognition", + "proof", + "intake" + ], + "properties": { + "law": { "type": "boolean" }, + "state": { "type": "boolean" }, + "authority": { "type": "boolean" }, + "execution": { "type": "boolean" }, + "verification": { "type": "boolean" }, + "recognition": { "type": "boolean" }, + "proof": { "type": "boolean" }, + "intake": { "type": "boolean" } + } + }, + "notes": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 } + } + } +} diff --git a/schemas/recourse-object.schema.json b/schemas/recourse-object.schema.json index 8aef7c8..13de5b0 100644 --- a/schemas/recourse-object.schema.json +++ b/schemas/recourse-object.schema.json @@ -1,66 +1,91 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://verifrax.net/regressorium/schemas/recourse-object.schema.json", - "title": "REGRESSORIUM recourse object", + "title": "REGRESSORIUM Recourse Object", "type": "object", + "additionalProperties": false, "required": [ - "recourse_id", - "recognition_ref", - "counterparty", - "burden", - "remedy", - "escalation", + "object_type", + "recourse_object_id", + "status", + "claim_class_ref", + "recourse_index_ref", + "historical_archive_ref", + "governing_law_version_ref", + "accepted_epoch_ref", + "authority_object_ref", + "execution_receipt_ref", + "verification_result_ref", + "recognition_object_ref", + "subject_ref", + "counterparty_rule_ref", + "burden_assignment_ref", + "remedy_matrix_ref", + "escalation_flow_ref", + "closure_states_ref", + "recourse_status", + "burden_assignment", + "remedy_path", + "escalation_path", "closure_state", - "status" + "limits", + "notes" ], "properties": { - "recourse_id": { - "type": "string", - "minLength": 1 - }, - "recognition_ref": { - "type": "string", - "minLength": 1 - }, - "counterparty": { - "type": "string", - "minLength": 1 - }, - "burden": { - "type": "string", - "minLength": 1 - }, - "remedy": { - "type": "string", - "minLength": 1 - }, - "escalation": { - "type": "string", - "minLength": 1 + "object_type": { "const": "RecourseObject" }, + "recourse_object_id": { "type": "string", "minLength": 1 }, + "status": { + "enum": [ + "ACTIVE_TRUTH", + "HISTORICAL_SNAPSHOT" + ] }, - "closure_state": { - "type": "string", + "claim_class_ref": { "type": "string", "minLength": 1 }, + "recourse_index_ref": { "type": "string", "minLength": 1 }, + "historical_archive_ref": { "type": "string", "minLength": 1 }, + "governing_law_version_ref": { "type": "string", "minLength": 1 }, + "accepted_epoch_ref": { "type": "string", "minLength": 1 }, + "authority_object_ref": { "type": "string", "minLength": 1 }, + "execution_receipt_ref": { "type": "string", "minLength": 1 }, + "verification_result_ref": { "type": "string", "minLength": 1 }, + "recognition_object_ref": { "type": "string", "minLength": 1 }, + "subject_ref": { "type": "string", "minLength": 1 }, + "counterparty_rule_ref": { "type": "string", "minLength": 1 }, + "burden_assignment_ref": { "type": "string", "minLength": 1 }, + "remedy_matrix_ref": { "type": "string", "minLength": 1 }, + "escalation_flow_ref": { "type": "string", "minLength": 1 }, + "closure_states_ref": { "type": "string", "minLength": 1 }, + "recourse_status": { "enum": [ - "open", - "burdened", - "remediating", - "escalated", - "closed" + "OPEN_FOR_RECOURSE", + "BURDEN_ASSIGNED", + "REMEDIATING", + "ESCALATED", + "CLOSED" ] }, - "status": { - "type": "string", + "burden_assignment": { "type": "string", "minLength": 1 }, + "remedy_path": { "type": "string", "minLength": 1 }, + "escalation_path": { "type": "string", "minLength": 1 }, + "closure_state": { "enum": [ - "current", - "historical" + "OPEN", + "BURDENED", + "REMEDIATING", + "ESCALATED", + "CLOSED" ] }, + "limits": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 }, + "uniqueItems": true + }, "notes": { "type": "array", - "items": { - "type": "string" - } + "minItems": 1, + "items": { "type": "string", "minLength": 1 } } - }, - "additionalProperties": false + } } diff --git a/schemas/recourse-output.schema.json b/schemas/recourse-output.schema.json new file mode 100644 index 0000000..a2d689e --- /dev/null +++ b/schemas/recourse-output.schema.json @@ -0,0 +1,87 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://verifrax.net/regressorium/schemas/recourse-output.schema.json", + "title": "REGRESSORIUM Recourse Output", + "type": "object", + "additionalProperties": false, + "required": [ + "object_type", + "schema_version", + "output_id", + "generated_at", + "input_class", + "output_class", + "status", + "summary", + "recourse_scope", + "boundary_assertions", + "basis_refs" + ], + "properties": { + "object_type": { "const": "RECOURSE_OUTPUT" }, + "schema_version": { + "type": "string", + "pattern": "^\\d+\\.\\d+\\.\\d+$" + }, + "output_id": { "type": "string", "minLength": 1 }, + "generated_at": { "type": "string", "format": "date-time" }, + "input_class": { + "enum": [ + "recognition-object-reference", + "claim-class-reference", + "law-version-reference", + "accepted-epoch-reference", + "authority-object-reference", + "execution-receipt-reference", + "verification-result-reference", + "operator-request" + ] + }, + "output_class": { + "enum": [ + "recourse-object", + "recourse-index-update" + ] + }, + "status": { + "enum": [ + "ACTIVE_TRUTH", + "HISTORICAL_SNAPSHOT", + "DERIVED_PROJECTION" + ] + }, + "summary": { "type": "string", "minLength": 1 }, + "recourse_scope": { "type": "string", "minLength": 1 }, + "boundary_assertions": { + "type": "object", + "additionalProperties": false, + "required": [ + "not-law", + "not-state", + "not-authority", + "not-execution", + "not-verification", + "not-recognition", + "not-proof", + "not-intake", + "recourse-downstream-of-recognition" + ], + "properties": { + "not-law": { "const": true }, + "not-state": { "const": true }, + "not-authority": { "const": true }, + "not-execution": { "const": true }, + "not-verification": { "const": true }, + "not-recognition": { "const": true }, + "not-proof": { "const": true }, + "not-intake": { "const": true }, + "recourse-downstream-of-recognition": { "const": true } + } + }, + "basis_refs": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 } + } + } +} diff --git a/tests/test_boundary_policy_schema_smoke.py b/tests/test_boundary_policy_schema_smoke.py new file mode 100644 index 0000000..faee898 --- /dev/null +++ b/tests/test_boundary_policy_schema_smoke.py @@ -0,0 +1,10 @@ +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + +def test_boundary_policy_core(): + obj = json.loads((ROOT / "contracts/boundary-policy.json").read_text()) + assert obj["object_type"] == "BOUNDARY_POLICY" + assert obj["surface"] == "REGRESSORIUM" + assert obj["role"] == "terminal-recourse" diff --git a/tests/test_recourse_audit_schema_smoke.py b/tests/test_recourse_audit_schema_smoke.py new file mode 100644 index 0000000..dc185a5 --- /dev/null +++ b/tests/test_recourse_audit_schema_smoke.py @@ -0,0 +1,10 @@ +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + +def test_recourse_audit_fixture(): + obj = json.loads((ROOT / "fixtures/recourse-audit-record.valid.json").read_text()) + assert obj["object_type"] == "RECOURSE_AUDIT_RECORD" + assert obj["decision"] == "rejected" + assert obj["rejection_reason"] == "would-recognize-terminal-truth" diff --git a/tests/test_recourse_boundary_negative_assertions.py b/tests/test_recourse_boundary_negative_assertions.py new file mode 100644 index 0000000..b05e975 --- /dev/null +++ b/tests/test_recourse_boundary_negative_assertions.py @@ -0,0 +1,37 @@ +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + +def load(rel): + return json.loads((ROOT / rel).read_text()) + +def test_forbidden_output_classes_do_not_overlap_allowed_output_classes(): + policy = load("contracts/boundary-policy.json") + assert set(policy["allowed_output_classes"]).isdisjoint(set(policy["forbidden_output_classes"])) + +def test_recourse_object_carries_non_recognition_boundary(): + obj = load("claims/current/recourse-object-0001.json") + limits = set(obj["limits"]) + assert "recourse does not redefine law" in limits + assert "recourse does not redefine accepted epoch" in limits + assert "recourse does not replace authority issuance" in limits + assert "recourse does not replace execution" in limits + assert "recourse does not replace verification" in limits + assert "recourse does not replace recognition" in limits + +def test_current_index_shape_uses_active_truth(): + idx = load("claims/current/index.json") + assert idx["object_type"] == "RecourseIndex" + assert idx["status"] == "ACTIVE_TRUTH" + assert idx["historical"] is False + +def test_boundary_policy_rejection_reasons_cover_upstream_collisions(): + policy = load("contracts/boundary-policy.json") + reasons = set(policy["rejection_reasons"]) + assert "would-author-law" in reasons + assert "would-mutate-accepted-state" in reasons + assert "would-issue-authority" in reasons + assert "would-execute-governed-action" in reasons + assert "would-emit-verification-verdict" in reasons + assert "would-recognize-terminal-truth" in reasons diff --git a/tests/test_recourse_output_schema_smoke.py b/tests/test_recourse_output_schema_smoke.py new file mode 100644 index 0000000..9a8d98a --- /dev/null +++ b/tests/test_recourse_output_schema_smoke.py @@ -0,0 +1,10 @@ +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + +def test_recourse_output_fixture(): + obj = json.loads((ROOT / "fixtures/recourse-output.valid.json").read_text()) + assert obj["object_type"] == "RECOURSE_OUTPUT" + assert obj["output_class"] == "recourse-object" + assert obj["boundary_assertions"]["not-recognition"] is True diff --git a/tests/verify_boundary_object_minimum.py b/tests/verify_boundary_object_minimum.py new file mode 100755 index 0000000..f23b12a --- /dev/null +++ b/tests/verify_boundary_object_minimum.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + +def load(rel): + p = ROOT / rel + if not p.exists(): + raise SystemExit(f"FAIL missing-file {rel}") + try: + return json.loads(p.read_text()) + except Exception as e: + raise SystemExit(f"FAIL invalid-json {rel}: {e}") + +def need(cond, msg): + if not cond: + raise SystemExit(f"FAIL {msg}") + +policy = load("contracts/boundary-policy.json") +recourse_schema = load("schemas/recourse-object.schema.json") +output_schema = load("schemas/recourse-output.schema.json") +audit_schema = load("schemas/recourse-audit-record.schema.json") +current_obj = load("claims/current/recourse-object-0001.json") +current_idx = load("claims/current/index.json") +output_fixture = load("fixtures/recourse-output.valid.json") +audit_fixture = load("fixtures/recourse-audit-record.valid.json") + +print("[VERIFY] files-present") + +need(policy["object_type"] == "BOUNDARY_POLICY", "boundary policy object_type") +need(policy["surface"] == "REGRESSORIUM", "boundary policy surface") +need(policy["role"] == "terminal-recourse", "boundary policy role") + +allowed = set(policy["allowed_output_classes"]) +forbidden = set(policy["forbidden_output_classes"]) +need(allowed.isdisjoint(forbidden), "allowed/forbidden overlap") + +required_reasons = { + "would-author-law", + "would-mutate-accepted-state", + "would-issue-authority", + "would-execute-governed-action", + "would-emit-verification-verdict", + "would-recognize-terminal-truth" +} +need(required_reasons.issubset(set(policy["rejection_reasons"])), "missing rejection reasons") + +print("[VERIFY] boundary-policy-core") + +need(current_obj["object_type"] == "RecourseObject", "current recourse object type") +need(current_obj["status"] == "ACTIVE_TRUTH", "current recourse object status") +need(current_obj["recourse_index_ref"] == "claims/current/index.json", "recourse index ref") +need(current_obj["historical_archive_ref"] == "claims/history/", "historical archive ref") +need(current_obj["recognition_object_ref"].endswith("/recognitions/current/recognition-object-0001.json"), "recognition object ref") +need(current_obj["recourse_status"] == "OPEN_FOR_RECOURSE", "recourse status") +need(current_obj["closure_state"] == "OPEN", "closure state") + +limits = set(current_obj["limits"]) +need("recourse does not redefine law" in limits, "missing non-law limit") +need("recourse does not replace verification" in limits, "missing non-verification limit") +need("recourse does not replace recognition" in limits, "missing non-recognition limit") + +print("[VERIFY] recourse-object-core") + +need(current_idx["object_type"] == "RecourseIndex", "current index type") +need(current_idx["status"] == "ACTIVE_TRUTH", "current index status") +need(current_idx["historical"] is False, "current index historical false") +need(current_idx["current_recourse_object_ref"] == "claims/current/recourse-object-0001.json", "current object ref") +need(current_idx["entries"][0]["path"] == "claims/current/recourse-object-0001.json", "index entry path") + +print("[VERIFY] recourse-index-core") + +need(output_fixture["object_type"] == "RECOURSE_OUTPUT", "output fixture type") +need(output_fixture["boundary_assertions"]["not-recognition"] is True, "output fixture non-recognition") +need(audit_fixture["object_type"] == "RECOURSE_AUDIT_RECORD", "audit fixture type") +need(audit_fixture["decision"] == "rejected", "audit fixture decision") +need(audit_fixture["rejection_reason"] == "would-recognize-terminal-truth", "audit fixture reason") +need(audit_fixture["sovereign_collision_flags"]["recognition"] is True, "audit fixture recognition flag") + +print("[VERIFY] output-and-audit-core") + +try: + import jsonschema # type: ignore +except Exception: + print("[VERIFY] jsonschema-module absent -> structural verification only") +else: + from jsonschema import Draft202012Validator, FormatChecker # type: ignore + Draft202012Validator(recourse_schema, format_checker=FormatChecker()).validate(current_obj) + Draft202012Validator(output_schema, format_checker=FormatChecker()).validate(output_fixture) + Draft202012Validator(audit_schema, format_checker=FormatChecker()).validate(audit_fixture) + Draft202012Validator(load("schemas/boundary-policy.schema.json"), format_checker=FormatChecker()).validate(policy) + print("[VERIFY] full-jsonschema-validation") + +print("[PASS] PHASE 2 / STEP 12 boundary-object minimum verified")