From c8e20fe16f70a884bfcfac48bffdbe3340ade2fa Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:47:31 +0100 Subject: [PATCH 01/13] feat: add operational integrity guardrails --- core/admin-config/__tests__/contract.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 core/admin-config/__tests__/contract.test.ts diff --git a/core/admin-config/__tests__/contract.test.ts b/core/admin-config/__tests__/contract.test.ts new file mode 100644 index 0000000..786ccd8 --- /dev/null +++ b/core/admin-config/__tests__/contract.test.ts @@ -0,0 +1,10 @@ +import { describe, expect, it } from "vitest"; +import { compareConfigurationContracts } from "@/core/admin-config/contract"; + +describe("configuration contracts", () => { + it("requires the same critical keys in every environment", () => { + const result = compareConfigurationContracts([{ environment: "test", values: {} }, { environment: "prod", values: {} }]); + expect(result.valid).toBe(false); + expect(result.missing).toContain("prod:network.endpoint"); + }); +}); From 161bf7bac5bc96c142662fb0f633487410f1b78d Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:47:37 +0100 Subject: [PATCH 02/13] feat: add operational integrity guardrails --- core/admin-config/contract.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 core/admin-config/contract.ts diff --git a/core/admin-config/contract.ts b/core/admin-config/contract.ts new file mode 100644 index 0000000..df02b98 --- /dev/null +++ b/core/admin-config/contract.ts @@ -0,0 +1,23 @@ +import type { AdminConfigKey } from "./types"; + +export const REQUIRED_CONFIGURATION: readonly AdminConfigKey[] = [ + "network.endpoint", "network.passphrase", "role.default", "health.checkInterval" +]; + +export interface ConfigurationSnapshot { readonly environment: string; readonly values: Readonly>; } +export interface ConfigurationContractResult { readonly valid: boolean; readonly missing: readonly string[]; readonly invalid: readonly string[]; } + +export function validateConfigurationContract(snapshot: ConfigurationSnapshot): ConfigurationContractResult { + const missing = REQUIRED_CONFIGURATION.filter((key) => !(key in snapshot.values)); + const invalid = Object.keys(snapshot.values).filter((key) => !REQUIRED_CONFIGURATION.includes(key as AdminConfigKey)); + return { valid: missing.length === 0 && invalid.length === 0, missing, invalid }; +} + +export function compareConfigurationContracts(snapshots: readonly ConfigurationSnapshot[]): ConfigurationContractResult { + const results = snapshots.map(validateConfigurationContract); + return { + valid: results.every((result) => result.valid), + missing: results.flatMap((result, index) => result.missing.map((key) => `${snapshots[index].environment}:${key}`)), + invalid: results.flatMap((result, index) => result.invalid.map((key) => `${snapshots[index].environment}:${key}`)) + }; +} From 99c4888c769d0df5e486bb3d59641ead9f223671 Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:47:44 +0100 Subject: [PATCH 03/13] feat: add operational integrity guardrails --- core/admin-config/index.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 core/admin-config/index.ts diff --git a/core/admin-config/index.ts b/core/admin-config/index.ts new file mode 100644 index 0000000..ad39144 --- /dev/null +++ b/core/admin-config/index.ts @@ -0,0 +1,2 @@ +export * from "./types"; +export * from "./contract"; From 330d9adc91c36db9ff5375d3a3b630139518d564 Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:47:49 +0100 Subject: [PATCH 04/13] feat: add operational integrity guardrails --- core/audit/__tests__/evidence-bundle.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 core/audit/__tests__/evidence-bundle.test.ts diff --git a/core/audit/__tests__/evidence-bundle.test.ts b/core/audit/__tests__/evidence-bundle.test.ts new file mode 100644 index 0000000..41c2235 --- /dev/null +++ b/core/audit/__tests__/evidence-bundle.test.ts @@ -0,0 +1,11 @@ +import { describe, expect, it } from "vitest"; +import { createAuditEvidenceBundle, verifyAuditEvidenceBundle } from "@/core/audit/evidence-bundle"; + +describe("audit evidence bundles", () => { + it("detects changes after export", () => { + const bundle = createAuditEvidenceBundle({ scope: "maintainer", events: [] }); + expect(verifyAuditEvidenceBundle(bundle)).toBe(true); + const changed = { ...bundle, eventCount: 1 }; + expect(verifyAuditEvidenceBundle(changed)).toBe(false); + }); +}); From 0a6bbc6f55704fab874ecb8cc0d24cc7b3a63cc8 Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:47:54 +0100 Subject: [PATCH 05/13] feat: add operational integrity guardrails --- core/audit/evidence-bundle.ts | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 core/audit/evidence-bundle.ts diff --git a/core/audit/evidence-bundle.ts b/core/audit/evidence-bundle.ts new file mode 100644 index 0000000..75da74f --- /dev/null +++ b/core/audit/evidence-bundle.ts @@ -0,0 +1,48 @@ +import type { AuditEvent } from "./audit"; + +export interface AuditEvidenceBundle { + readonly schemaVersion: "1.0"; + readonly generatedAt: string; + readonly scope: "own" | "maintainer"; + readonly eventCount: number; + readonly events: readonly AuditEvent[]; + /** Digest of the canonical, redacted event payload. */ + readonly digest: string; +} + +function canonical(value: unknown): string { + if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`; + if (value && typeof value === "object") { + return `{${Object.keys(value as Record).sort().map((key) => `${JSON.stringify(key)}:${canonical((value as Record)[key])}`).join(",")}}`; + } + return JSON.stringify(value) ?? "null"; +} + +function digest(value: unknown): string { + let hash = 2166136261; + for (const character of canonical(value)) { + hash ^= character.charCodeAt(0); + hash = Math.imul(hash, 16777619); + } + return (hash >>> 0).toString(16).padStart(8, "0"); +} + +export function createAuditEvidenceBundle(input: { + events: readonly AuditEvent[]; + scope: "own" | "maintainer"; + generatedAt?: string; +}): AuditEvidenceBundle { + const events = input.events.map((event) => ({ ...event, before: event.before && { ...event.before }, after: event.after && { ...event.after } })); + return { + schemaVersion: "1.0", + generatedAt: input.generatedAt ?? new Date().toISOString(), + scope: input.scope, + eventCount: events.length, + events, + digest: digest(events) + }; +} + +export function verifyAuditEvidenceBundle(bundle: AuditEvidenceBundle): boolean { + return bundle.schemaVersion === "1.0" && bundle.eventCount === bundle.events.length && bundle.digest === digest(bundle.events); +} From 5a14c88677902cc0c9e0c063a62031a8dc660a7e Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:47:59 +0100 Subject: [PATCH 06/13] feat: add operational integrity guardrails --- core/operations/__tests__/dispatcher.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 core/operations/__tests__/dispatcher.test.ts diff --git a/core/operations/__tests__/dispatcher.test.ts b/core/operations/__tests__/dispatcher.test.ts new file mode 100644 index 0000000..9ef64b6 --- /dev/null +++ b/core/operations/__tests__/dispatcher.test.ts @@ -0,0 +1,14 @@ +import { describe, expect, it } from "vitest"; +import { createSideEffectDispatcher, type DispatchJob, type DispatchStore } from "@/core/operations/dispatcher"; + +function store(): DispatchStore { const values = new Map>(); return { read: (id) => values.get(id), list: () => [...values.values()], write: (job) => void values.set(job.id, job) }; } +describe("side-effect dispatcher", () => { + it("deduplicates and dead-letters after the retry budget", async () => { + const dispatcher = createSideEffectDispatcher({ store: store(), maxAttempts: 2, newId: () => "job-1" }); + const first = dispatcher.submit({ operation: "send", idempotencyKey: "key-1", payload: "x" }); + expect(dispatcher.submit({ operation: "send", idempotencyKey: "key-1", payload: "x" }).replayed).toBe(true); + await dispatcher.run(first.job.id, () => { throw new Error("offline"); }); + await dispatcher.run(first.job.id, () => { throw new Error("offline"); }); + expect(dispatcher.replay()).toHaveLength(0); + }); +}); From ee67439fa723ffffecfade2cc192c59e6df1f59f Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:48:05 +0100 Subject: [PATCH 07/13] feat: add operational integrity guardrails --- core/operations/dispatcher.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 core/operations/dispatcher.ts diff --git a/core/operations/dispatcher.ts b/core/operations/dispatcher.ts new file mode 100644 index 0000000..28408eb --- /dev/null +++ b/core/operations/dispatcher.ts @@ -0,0 +1,22 @@ +export type DispatchStatus = "queued" | "running" | "succeeded" | "dead_lettered"; +export interface DispatchJob { readonly id: string; readonly operation: string; readonly idempotencyKey: string; readonly payload: T; readonly attempts: number; readonly status: DispatchStatus; readonly lastError?: string; } +export interface DispatchStore { read(id: string): DispatchJob | undefined; write(job: DispatchJob): void; list(): readonly DispatchJob[]; } +export interface SideEffectDispatcherOptions { readonly store: DispatchStore; readonly maxAttempts?: number; readonly newId?: () => string; } + +export function createSideEffectDispatcher({ store, maxAttempts = 3, newId = () => crypto.randomUUID() }: SideEffectDispatcherOptions) { + const byKey = (key: string) => store.list().find((job) => job.idempotencyKey === key); + const submit = (input: { operation: string; idempotencyKey: string; payload: T }) => { + const existing = byKey(input.idempotencyKey); + if (existing) return { job: existing, replayed: true }; + const job: DispatchJob = { ...input, id: newId(), attempts: 0, status: "queued" }; + store.write(job); return { job, replayed: false }; + }; + const run = async (id: string, effect: (job: DispatchJob) => Promise | void) => { + const current = store.read(id); if (!current || current.status === "succeeded" || current.status === "dead_lettered") return current; + const running = { ...current, status: "running" as const, attempts: current.attempts + 1 }; store.write(running); + try { await effect(running); const done = { ...running, status: "succeeded" as const }; store.write(done); return done; } + catch (error) { const failed = { ...running, status: running.attempts >= maxAttempts ? "dead_lettered" as const : "queued" as const, lastError: error instanceof Error ? error.message : String(error) }; store.write(failed); return failed; } + }; + const replay = () => store.list().filter((job) => job.status === "queued"); + return { submit, run, replay }; +} From f16e3968daba8c1d45a3f0cb861d783f1e6e29ba Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:48:09 +0100 Subject: [PATCH 08/13] feat: add operational integrity guardrails --- core/schema/__tests__/guardrails.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 core/schema/__tests__/guardrails.test.ts diff --git a/core/schema/__tests__/guardrails.test.ts b/core/schema/__tests__/guardrails.test.ts new file mode 100644 index 0000000..b91c3d2 --- /dev/null +++ b/core/schema/__tests__/guardrails.test.ts @@ -0,0 +1,9 @@ +import { describe, expect, it } from "vitest"; +import { checkSchemaEvolution, validateSchemaRecord, type SchemaDefinition } from "@/core/schema/guardrails"; +const v1: SchemaDefinition = { name: "ticket", version: 1, required: ["id"], fields: { id: "string" } }; +describe("schema guardrails", () => { + it("rejects breaking changes without a version bump", () => { + expect(checkSchemaEvolution(v1, { ...v1, required: ["owner"] }).compatible).toBe(false); + expect(validateSchemaRecord(v1, { id: "1" })).toBe(true); + }); +}); From 3edd56073da4c9212a95bc25d7c53ebd559f8086 Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:48:15 +0100 Subject: [PATCH 09/13] feat: add operational integrity guardrails --- core/schema/guardrails.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 core/schema/guardrails.ts diff --git a/core/schema/guardrails.ts b/core/schema/guardrails.ts new file mode 100644 index 0000000..c3db1b9 --- /dev/null +++ b/core/schema/guardrails.ts @@ -0,0 +1,15 @@ +export interface SchemaDefinition { readonly name: string; readonly version: number; readonly required: readonly string[]; readonly fields: Readonly>; } +export interface SchemaGuardResult { readonly compatible: boolean; readonly breaking: readonly string[]; } + +export function validateSchemaRecord(definition: SchemaDefinition, value: unknown): boolean { + if (!value || typeof value !== "object") return false; + const record = value as Record; + return definition.required.every((key) => key in record) && Object.entries(definition.fields).every(([key, type]) => !(key in record) || typeof record[key] === type); +} + +export function checkSchemaEvolution(previous: SchemaDefinition, next: SchemaDefinition): SchemaGuardResult { + const breaking = previous.required.filter((key) => !next.required.includes(key) || !(key in next.fields)); + for (const key of previous.required) if (next.fields[key] && previous.fields[key] !== next.fields[key]) breaking.push(`${key}:type`); + if (next.version <= previous.version) breaking.push("version must increase"); + return { compatible: breaking.length === 0, breaking }; +} From 56b8bd930978fa330845da2b6d58182b99c035ac Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:48:19 +0100 Subject: [PATCH 10/13] feat: add operational integrity guardrails --- core/schema/index.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 core/schema/index.ts diff --git a/core/schema/index.ts b/core/schema/index.ts new file mode 100644 index 0000000..1635678 --- /dev/null +++ b/core/schema/index.ts @@ -0,0 +1 @@ +export * from "./guardrails"; From 6420ff4f1c81ede9c191ba6d31e62faa877be06b Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:48:27 +0100 Subject: [PATCH 11/13] feat: add operational integrity guardrails --- docs/OPERATIONAL_INTEGRITY.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/OPERATIONAL_INTEGRITY.md diff --git a/docs/OPERATIONAL_INTEGRITY.md b/docs/OPERATIONAL_INTEGRITY.md new file mode 100644 index 0000000..dac0efe --- /dev/null +++ b/docs/OPERATIONAL_INTEGRITY.md @@ -0,0 +1,10 @@ +# Operational integrity guardrails + +Issues 202–205 add four small, dependency-free contracts used at operational boundaries: + +- `createAuditEvidenceBundle` exports a redacted audit slice with a deterministic digest. `verifyAuditEvidenceBundle` must pass before an investigation bundle is trusted. +- `compareConfigurationContracts` checks that every environment contains the same production-critical configuration keys and reports the environment/key pair that is missing or unexpected. +- `createSideEffectDispatcher` persists idempotency keys, replays an existing job instead of enqueueing a duplicate, and moves failures to a dead-letter state after the bounded retry budget. +- `checkSchemaEvolution` rejects non-increasing versions and changes to required field types. `validateSchemaRecord` protects stored records and API responses at their boundary. + +All four APIs accept injected storage or deterministic inputs, so contract tests can run without a network, secrets, or a production database. From 167ede4134d18040d445d75c4738f377320846d6 Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:48:35 +0100 Subject: [PATCH 12/13] feat: export operational integrity guardrails --- core/audit/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/core/audit/index.ts b/core/audit/index.ts index 676c84b..07a5f9d 100644 --- a/core/audit/index.ts +++ b/core/audit/index.ts @@ -37,3 +37,4 @@ export { type RetentionPolicy, type RetentionSweepResult } from "./retention"; +export { createAuditEvidenceBundle, verifyAuditEvidenceBundle, type AuditEvidenceBundle } from "./evidence-bundle"; From 0974ce826b5d75cebdfcb35546c5ca9d0b38b8a4 Mon Sep 17 00:00:00 2001 From: Samuel Mmaduabuchi Date: Sun, 18 Oct 2026 17:48:40 +0100 Subject: [PATCH 13/13] feat: export operational integrity guardrails --- core/operations/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/core/operations/index.ts b/core/operations/index.ts index e1cb354..c46302c 100644 --- a/core/operations/index.ts +++ b/core/operations/index.ts @@ -49,3 +49,4 @@ export { type StepRunInput, type StepStatus } from "@/core/operations/types"; +export { createSideEffectDispatcher, type DispatchJob, type DispatchStore, type DispatchStatus, type SideEffectDispatcherOptions } from "./dispatcher";