Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions src/contracts/layer4-integrity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/**
* Layer 4 (Audit Trail) integrity validators. Implements TC-L4-01..05 per
* RFC-0005: the audit trail is lifecycle-complete and append-only, not
* merely present.
*
* See: https://github.com/Source-Engineering/source-engineering-specifications/blob/main/compatibility-test-suite.md
*/

import type { Cots, AuditEntry } from "../types.js";
import { type Result, combine, fail, warn } from "../result.js";

const URN_RE = /^[a-z][a-z0-9+\-.]*:/i;

/** TC-L4-01: every decision's audit trail starts with "created" and every entry is complete. */
export const validateAuditTrailComplete = (cots: Cots): Result => {
const errors: Result[] = [];

for (let i = 0; i < cots.decisions.length; i++) {
const history = cots.decisions[i].audit_history;
if (history.length === 0) {
errors.push(fail("TC-L4-01", `decisions[${i}].audit_history is empty (must start with "created")`));
continue;
}
if (history[0].action !== "created") {
errors.push(fail("TC-L4-01", `decisions[${i}].audit_history[0] is not "created" (got "${history[0].action}")`));
}
for (let j = 0; j < history.length; j++) {
const e: AuditEntry = history[j];
if (!e.id || !URN_RE.test(e.id)) {
errors.push(fail("TC-L4-01", `decisions[${i}].audit_history[${j}].id is missing or not a valid URI ('${e.id}')`));
}
if (!e.action) {
errors.push(fail("TC-L4-01", `decisions[${i}].audit_history[${j}].action is empty`));
}
if (!e.performed_by) {
errors.push(fail("TC-L4-01", `decisions[${i}].audit_history[${j}].performed_by is empty`));
}
if (Number.isNaN(Date.parse(e.performed_at))) {
errors.push(fail("TC-L4-01", `decisions[${i}].audit_history[${j}].performed_at is not a valid ISO-8601 timestamp ('${e.performed_at}')`));
}
}
}

return combine(...errors);
};

/** TC-L4-02: append-only verifiable: unique entry ids and monotonic time order. */
export const validateAuditTrailAppendOnly = (cots: Cots): Result => {
const errors: Result[] = [];

for (let i = 0; i < cots.decisions.length; i++) {
const history = cots.decisions[i].audit_history;
const seen = new Set<string>();
for (let j = 0; j < history.length; j++) {
const e = history[j];
if (seen.has(e.id)) {
errors.push(fail("TC-L4-02", `decisions[${i}].audit_history contains duplicate entry id '${e.id}' (append-only violated)`));
}
seen.add(e.id);
if (j > 0) {
const prev = Date.parse(history[j - 1].performed_at);
const curr = Date.parse(e.performed_at);
if (!Number.isNaN(prev) && !Number.isNaN(curr) && curr < prev) {
errors.push(fail("TC-L4-02", `decisions[${i}].audit_history[${j}] is earlier than its predecessor (append-only violated: ${e.performed_at} < ${history[j - 1].performed_at})`));
}
}
}
}

return combine(...errors);
};

/** TC-L4-03: every non-"created" entry names a decision that exists in the COTS. */
export const validateLifecycleEventsResolve = (cots: Cots): Result => {
const errors: Result[] = [];
const decisionIds = new Set(cots.decisions.map((d) => d.id));

for (let i = 0; i < cots.decisions.length; i++) {
for (let j = 0; j < cots.decisions[i].audit_history.length; j++) {
const e = cots.decisions[i].audit_history[j];
if (e.action === "created") continue;
const m = e.notes.match(/decision_id=(\S+)/);
if (!m) {
errors.push(fail("TC-L4-03", `decisions[${i}].audit_history[${j}] (${e.action}) does not name a decision_id; the lifecycle event dangles`));
} else if (!decisionIds.has(m[1])) {
errors.push(fail("TC-L4-03", `decisions[${i}].audit_history[${j}] references unknown decision '${m[1]}'`));
}
}
}

return combine(...errors);
};

/** TC-L4-04: rerun entries link to the original decision; superseded entries name the superseding decision. */
export const validateLifecycleLinkage = (cots: Cots): Result => {
const errors: Result[] = [];
const decisionIds = new Set(cots.decisions.map((d) => d.id));

for (let i = 0; i < cots.decisions.length; i++) {
for (let j = 0; j < cots.decisions[i].audit_history.length; j++) {
const e = cots.decisions[i].audit_history[j];
if (e.action === "rerun") {
const m = e.notes.match(/rerun_of=(\S+)/);
if (!m) {
errors.push(fail("TC-L4-04", `decisions[${i}].audit_history[${j}] is a rerun without rerun_of linkage`));
} else if (!decisionIds.has(m[1])) {
errors.push(fail("TC-L4-04", `decisions[${i}].audit_history[${j}] rerun_of '${m[1]}' does not resolve to a decision in the COTS`));
}
}
if (e.action === "superseded") {
const m = e.notes.match(/superseded_by=(\S+)/);
if (!m) {
errors.push(fail("TC-L4-04", `decisions[${i}].audit_history[${j}] is superseded without superseded_by linkage`));
} else if (!decisionIds.has(m[1])) {
errors.push(fail("TC-L4-04", `decisions[${i}].audit_history[${j}] superseded_by '${m[1]}' does not resolve to a decision in the COTS`));
}
}
}
}

return combine(...errors);
};

/** TC-L4-05: a pre-RFC-0005 COTS with a created-only history passes with a legacy warning. */
export const validateLegacyAuditTrail = (cots: Cots): Result => {
const warnings: Result[] = [];

for (let i = 0; i < cots.decisions.length; i++) {
const history = cots.decisions[i].audit_history;
if (history.length === 1 && history[0].action === "created") {
warnings.push(
warn("TC-L4-05", `decisions[${i}] has a created-only audit history (pre-RFC-0005 producer; no lifecycle events recorded)`)
);
}
}

return combine(...warnings);
};
171 changes: 171 additions & 0 deletions src/fixtures/l4-conformant.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
{
"cots_version": "0.1.0",
"cots_id": "urn:source-engineering:cots:00000000-0000-0000-0000-000000000001",
"produced_at": "2026-10-11T12:00:00Z",
"produced_by": {
"system_name": "test-fixture",
"system_version": "0.1.0"
},
"inputs": {
"source_artifacts": [
{
"id": "urn:source-engineering:source:contract-2026-001",
"origin": {
"system_name": "Acme Contracts",
"system_version": "1.0.0",
"configuration_hash": "0000000000000000000000000000000000000000000000000000000000000001"
},
"version": {
"content_hash": "1111111111111111111111111111111111111111111111111111111111111111",
"issued_at": "2026-10-10T08:00:00Z"
},
"authority": {
"asserted_by": "acme-contracts",
"trust_score": 0.95
},
"temporal_validity": {
"valid_from": "2026-10-10T08:00:00Z",
"valid_until": null
},
"content_reference": {
"uri": "https://example.com/contracts/2026-001.pdf",
"media_type": "application/pdf"
}
}
]
},
"context": {
"model": {
"model_name": "claude-sonnet-4-5",
"model_version": "2026-09-15"
},
"parameters": {
"temperature": 0.3,
"top_p": 0.95,
"prompt_cache_id": null,
"tool_budget": 8,
"retrieval_depth": 5
},
"constraints": [
{
"id": "urn:source-engineering:constraint:jurisdiction-001",
"type": "jurisdiction",
"scope": "all_decisions",
"value": "US-NY"
}
]
},
"decisions": [
{
"id": "urn:source-engineering:decision:00000000-0000-0000-0000-000000000001",
"decision_text": "The contract is a standard commercial services agreement with mutual indemnification, a 30-day termination notice, and a New York governing-law clause.",
"basis_id": "urn:source-engineering:basis:00000000-0000-0000-0000-000000000001",
"evidence_chain_ref": "urn:source-engineering:evidence-chain:00000000-0000-0000-0000-000000000001",
"validation_status": {
"status": "pending",
"last_changed_at": "2026-10-11T12:00:00Z",
"last_changed_by": "test-fixture"
},
"responsible_authority": {
"authority_id": "claude-sonnet-4-5",
"authority_type": "automated"
},
"audit_history": [
{
"id": "urn:source-engineering:audit:00000000-0000-0000-0000-000000000001",
"action": "created",
"performed_by": "test-fixture",
"performed_at": "2026-10-11T12:00:00Z",
"notes": "Initial creation."
},
{
"id": "urn:source-engineering:audit:l4-002",
"action": "appealed",
"performed_by": "reviewer-1",
"performed_at": "2026-10-12T09:00:00Z",
"notes": "User appealed. decision_id=urn:source-engineering:decision:00000000-0000-0000-0000-000000000001"
},
{
"id": "urn:source-engineering:audit:l4-003",
"action": "rerun",
"performed_by": "reviewer-1",
"performed_at": "2026-10-12T10:00:00Z",
"notes": "Re-run on model v2. rerun_of=urn:source-engineering:decision:00000000-0000-0000-0000-000000000001 decision_id=urn:source-engineering:decision:00000000-0000-0000-0000-000000000001"
}
],
"created_at": "2026-10-11T12:00:00Z"
}
],
"evidence": {
"evidence_chain": [
{
"decision_id": "urn:source-engineering:decision:00000000-0000-0000-0000-000000000001",
"supporting_evidence": [
{
"id": "urn:source-engineering:evidence:00000000-0000-0000-0000-000000000001",
"claim_id": "urn:source-engineering:claim:00000000-0000-0000-0000-000000000001",
"source_id": "urn:source-engineering:source:contract-2026-001",
"transformation": {
"operation": "extract_clause",
"inputs": [
"https://example.com/contracts/2026-001.pdf#section-7"
],
"output": "Section 7.1: Each party shall indemnify and hold harmless...",
"recorded_at": "2026-10-11T12:00:00Z"
},
"uncertainty": {
"calibrated_score": 0.92,
"basis": "Direct extraction from the section 7.1 text."
},
"polarity": "supports"
}
],
"contradicting_evidence": [
{
"id": "urn:source-engineering:evidence:00000000-0000-0000-0000-000000000002",
"claim_id": "urn:source-engineering:claim:00000000-0000-0000-0000-000000000001",
"source_id": "urn:source-engineering:source:contract-2026-001",
"transformation": {
"operation": "search_clause",
"inputs": [
"https://example.com/contracts/2026-001.pdf#section-12"
],
"output": "Section 12.4: This agreement shall be governed by the laws of the State of Delaware.",
"recorded_at": "2026-10-11T12:00:00Z"
},
"uncertainty": {
"calibrated_score": 0.78,
"basis": "Contradictory governing-law clause in section 12.4 (the model rejected it because section 14.1 is the prevailing clause)."
},
"polarity": "contradicts"
}
],
"claims": [
{
"id": "urn:source-engineering:claim:00000000-0000-0000-0000-000000000001",
"decision_record_id": "urn:source-engineering:decision:00000000-0000-0000-0000-000000000001",
"claim_text": "The contract contains a mutual indemnification clause in section 7.1.",
"claim_type": "factual",
"supporting_evidence": [
"urn:source-engineering:evidence:00000000-0000-0000-0000-000000000001"
],
"contradicting_evidence": [
"urn:source-engineering:evidence:00000000-0000-0000-0000-000000000002"
]
}
]
}
]
},
"validation": {
"feedback_surfaces": [
{
"id": "urn:source-engineering:surface:00000000-0000-0000-0000-000000000001",
"type": "appeal",
"target": "urn:source-engineering:decision:00000000-0000-0000-0000-000000000001",
"endpoint": "https://example.com/appeal/00000000-0000-0000-0000-000000000001",
"description": "File an appeal against this decision."
}
]
}
}
Loading
Loading