From cd8240934565df3b647be6c8f821e5afa18f927f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:06:05 +0900 Subject: [PATCH 001/269] test(perf): define separation fixture contract --- ...employment_separation_fixture_contract.mjs | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 tests/performance/employment_separation_fixture_contract.mjs diff --git a/tests/performance/employment_separation_fixture_contract.mjs b/tests/performance/employment_separation_fixture_contract.mjs new file mode 100644 index 000000000..67af77ed1 --- /dev/null +++ b/tests/performance/employment_separation_fixture_contract.mjs @@ -0,0 +1,191 @@ +const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +const ACTOR_PATTERN = /^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$/; +const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/; +const SHA_PATTERN = /^[0-9a-f]{40}$/; +const BODY_KEYS = Object.freeze([ + "confirmation_reference", + "employment_record_id", + "evidence_reference", + "evidence_version_code", + "expected_employment_record_version_id", + "person_record_id", + "separation_effective_on", + "separation_reason_code", +]); +const REASON_CODES = new Set([ + "voluntary_resignation", + "retirement_transition", + "fixed_term_completion", + "position_elimination", + "employer_initiated_separation", +]); +const PROFILE_NAMES = Object.freeze(["first_commit", "replay", "rejection", "contention"]); + +function fail(message) { + throw new Error(message); +} + +function isPlainObject(value) { + return value !== null && typeof value === "object" && !Array.isArray(value); +} + +function requirePlainObject(value, label) { + if (!isPlainObject(value)) fail(`${label} must be an object`); + return value; +} + +function requireExactKeys(value, expected, label) { + const actual = Object.keys(value).sort(); + const wanted = [...expected].sort(); + if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) { + fail(`${label} must contain exactly: ${wanted.join(", ")}`); + } +} + +function requireString(value, label) { + if (typeof value !== "string" || value.trim() === "") fail(`${label} must be a non-empty string`); + return value; +} + +function requireUuid(value, label) { + const text = requireString(value, label); + if (!UUID_PATTERN.test(text)) fail(`${label} must be a canonical UUID string`); + const compact = text.split("-").join("").toLowerCase(); + if (compact === "0".repeat(32) || compact === "f".repeat(32)) fail(`${label} must be an operational UUID`); + return text.toLowerCase(); +} + +function requireCommand(command, label) { + const value = requirePlainObject(command, label); + requireExactKeys(value, ["actor_reference", "idempotency_key", "payload", "tenant_record_id"], label); + requireUuid(value.tenant_record_id, `${label}.tenant_record_id`); + const actor = requireString(value.actor_reference, `${label}.actor_reference`); + if (!ACTOR_PATTERN.test(actor)) fail(`${label}.actor_reference must be a namespaced opaque reference`); + const key = requireString(value.idempotency_key, `${label}.idempotency_key`); + if (key.length > 200) fail(`${label}.idempotency_key must not exceed 200 characters`); + + const payload = requirePlainObject(value.payload, `${label}.payload`); + requireExactKeys(payload, BODY_KEYS, `${label}.payload`); + requireUuid(payload.person_record_id, `${label}.payload.person_record_id`); + requireUuid(payload.employment_record_id, `${label}.payload.employment_record_id`); + requireUuid(payload.expected_employment_record_version_id, `${label}.payload.expected_employment_record_version_id`); + if (typeof payload.separation_effective_on !== "string" || !DATE_PATTERN.test(payload.separation_effective_on)) { + fail(`${label}.payload.separation_effective_on must be an RFC 3339 full-date`); + } + if (!REASON_CODES.has(payload.separation_reason_code)) { + fail(`${label}.payload.separation_reason_code must use the governed vocabulary`); + } + requireString(payload.evidence_reference, `${label}.payload.evidence_reference`); + requireString(payload.evidence_version_code, `${label}.payload.evidence_version_code`); + requireString(payload.confirmation_reference, `${label}.payload.confirmation_reference`); + return value; +} + +function semanticCommand(command) { + return JSON.stringify({ + actor_reference: command.actor_reference, + payload: command.payload, + tenant_record_id: command.tenant_record_id, + }); +} + +function recordIdentity(command) { + return command.payload.employment_record_id.toLowerCase(); +} + +function reserveIdentity(seen, command, label) { + const identity = recordIdentity(command); + if (seen.has(identity)) fail(`${label} reuses an Employment assigned to another performance profile`); + seen.add(identity); +} + +export const PERFORMANCE_FIXTURE_SCHEMA = "orgmetra.employment_separation.performance_fixture.v1"; + +export function validatePerformanceFixture( + document, + { minimumNonContendingRecords = 1000, minimumContentionPairs = 100 } = {}, +) { + const fixture = requirePlainObject(document, "fixture"); + requireExactKeys( + fixture, + [ + "candidate_sha", + "clearance_reference", + "dataset_id", + "prepared_at", + "profiles", + "resource_evidence_reference", + "right_cleared", + "schema_version", + "synthetic", + ], + "fixture", + ); + if (fixture.schema_version !== PERFORMANCE_FIXTURE_SCHEMA) fail("fixture.schema_version is unsupported"); + if (fixture.right_cleared !== true) fail("fixture.right_cleared must be true for commercial acceptance"); + if (fixture.synthetic !== false) fail("fixture.synthetic must be false for commercial acceptance"); + requireString(fixture.clearance_reference, "fixture.clearance_reference"); + requireString(fixture.dataset_id, "fixture.dataset_id"); + requireString(fixture.prepared_at, "fixture.prepared_at"); + requireString(fixture.resource_evidence_reference, "fixture.resource_evidence_reference"); + const candidateSha = requireString(fixture.candidate_sha, "fixture.candidate_sha").toLowerCase(); + if (!SHA_PATTERN.test(candidateSha)) fail("fixture.candidate_sha must be a full Git commit SHA"); + + const profiles = requirePlainObject(fixture.profiles, "fixture.profiles"); + requireExactKeys(profiles, PROFILE_NAMES, "fixture.profiles"); + for (const profile of ["first_commit", "replay", "rejection"]) { + if (!Array.isArray(profiles[profile]) || profiles[profile].length < minimumNonContendingRecords) { + fail(`fixture.profiles.${profile} must contain at least ${minimumNonContendingRecords} records`); + } + } + if (!Array.isArray(profiles.contention) || profiles.contention.length < minimumContentionPairs) { + fail(`fixture.profiles.contention must contain at least ${minimumContentionPairs} pairs`); + } + + const seenEmployment = new Set(); + const seenKeys = new Set(); + for (const profile of ["first_commit", "replay", "rejection"]) { + profiles[profile].forEach((raw, index) => { + const label = `fixture.profiles.${profile}[${index}]`; + const command = requireCommand(raw, label); + reserveIdentity(seenEmployment, command, label); + if (seenKeys.has(command.idempotency_key)) fail(`${label}.idempotency_key must be unique across fixture records`); + seenKeys.add(command.idempotency_key); + }); + } + + profiles.contention.forEach((raw, index) => { + const label = `fixture.profiles.contention[${index}]`; + const pair = requirePlainObject(raw, label); + requireExactKeys(pair, ["left", "right"], label); + const left = requireCommand(pair.left, `${label}.left`); + const right = requireCommand(pair.right, `${label}.right`); + if (left.idempotency_key === right.idempotency_key) fail(`${label} must use distinct idempotency keys`); + if (semanticCommand(left) !== semanticCommand(right)) fail(`${label} commands must differ only by idempotency key`); + reserveIdentity(seenEmployment, left, label); + for (const command of [left, right]) { + if (seenKeys.has(command.idempotency_key)) fail(`${label} idempotency keys must be unique across fixture records`); + seenKeys.add(command.idempotency_key); + } + }); + + return fixture; +} + +export function requestHeaders(command, bearerToken) { + requireCommand(command, "command"); + const token = requireString(bearerToken, "bearer token"); + return { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + "Idempotency-Key": command.idempotency_key, + "X-Actor-Reference": command.actor_reference, + "X-Purpose-Code": "workforce_admin", + "X-Tenant-Reference": command.tenant_record_id, + }; +} + +export function requestBody(command) { + requireCommand(command, "command"); + return JSON.stringify(command.payload); +} From 0af8eea726de12504bb8fff573a55bfb46a454d5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:06:17 +0900 Subject: [PATCH 002/269] test(perf): verify separation fixture guardrails --- ...yment_separation_fixture_contract.test.mjs | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 tests/performance/employment_separation_fixture_contract.test.mjs diff --git a/tests/performance/employment_separation_fixture_contract.test.mjs b/tests/performance/employment_separation_fixture_contract.test.mjs new file mode 100644 index 000000000..f971ab45e --- /dev/null +++ b/tests/performance/employment_separation_fixture_contract.test.mjs @@ -0,0 +1,106 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + PERFORMANCE_FIXTURE_SCHEMA, + requestBody, + requestHeaders, + validatePerformanceFixture, +} from "./employment_separation_fixture_contract.mjs"; + +const ZERO = "00000000-0000-0000-0000-000000000000"; + +function command(seed, key = `separation-${seed}`) { + const suffix = seed.toString(16).padStart(12, "0"); + return { + tenant_record_id: `10000000-0000-4000-8000-${suffix}`, + actor_reference: `worker_admin:perf_${seed}`, + idempotency_key: key, + payload: { + person_record_id: `20000000-0000-4000-8000-${suffix}`, + employment_record_id: `30000000-0000-4000-8000-${suffix}`, + expected_employment_record_version_id: `40000000-0000-4000-8000-${suffix}`, + separation_effective_on: "2026-09-13", + separation_reason_code: "voluntary_resignation", + evidence_reference: `evidence:perf_${seed}`, + evidence_version_code: "v1", + confirmation_reference: `confirmation:perf_${seed}`, + }, + }; +} + +function fixture() { + const left = command(4, "contention-left"); + const right = structuredClone(left); + right.idempotency_key = "contention-right"; + return { + schema_version: PERFORMANCE_FIXTURE_SCHEMA, + candidate_sha: "a".repeat(40), + right_cleared: true, + synthetic: false, + clearance_reference: "data-clearance:perf-2026-09", + dataset_id: "dataset:employment-separation-perf-1", + prepared_at: "2026-09-13T02:00:00Z", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profiles: { + first_commit: [command(1)], + replay: [command(2)], + rejection: [command(3)], + contention: [{ left, right }], + }, + }; +} + +const smallAcceptance = { minimumNonContendingRecords: 1, minimumContentionPairs: 1 }; + +test("accepts a right-cleared fixture with isolated performance profiles", () => { + const value = fixture(); + assert.equal(validatePerformanceFixture(value, smallAcceptance), value); +}); + +test("rejects synthetic or uncleared commercial fixtures", () => { + const synthetic = fixture(); + synthetic.synthetic = true; + assert.throws(() => validatePerformanceFixture(synthetic, smallAcceptance), /synthetic must be false/); + + const uncleared = fixture(); + uncleared.right_cleared = false; + assert.throws(() => validatePerformanceFixture(uncleared, smallAcceptance), /right_cleared must be true/); +}); + +test("rejects sentinel identities and profile cross-contamination", () => { + const sentinel = fixture(); + sentinel.profiles.first_commit[0].payload.person_record_id = ZERO; + assert.throws(() => validatePerformanceFixture(sentinel, smallAcceptance), /operational UUID/); + + const overlap = fixture(); + overlap.profiles.replay[0].payload.employment_record_id = overlap.profiles.first_commit[0].payload.employment_record_id; + assert.throws(() => validatePerformanceFixture(overlap, smallAcceptance), /reuses an Employment/); +}); + +test("requires contention commands to differ only by idempotency key", () => { + const value = fixture(); + value.profiles.contention[0].right.payload.separation_reason_code = "retirement_transition"; + assert.throws(() => validatePerformanceFixture(value, smallAcceptance), /differ only by idempotency key/); +}); + +test("enforces minimum sample cardinality rather than silently shrinking the run", () => { + assert.throws( + () => validatePerformanceFixture(fixture(), { minimumNonContendingRecords: 2, minimumContentionPairs: 1 }), + /at least 2 records/, + ); +}); + +test("builds the exact published separation request without storing bearer credentials in fixtures", () => { + const value = command(9, "exact-key"); + const headers = requestHeaders(value, "opaque-token"); + assert.deepEqual(headers, { + Authorization: "Bearer opaque-token", + "Content-Type": "application/json", + "Idempotency-Key": "exact-key", + "X-Actor-Reference": "worker_admin:perf_9", + "X-Purpose-Code": "workforce_admin", + "X-Tenant-Reference": "10000000-0000-4000-8000-000000000009", + }); + assert.deepEqual(JSON.parse(requestBody(value)), value.payload); +}); From 2046bc4bea97cf8e0a11694fe3b707c23d5273df Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:06:34 +0900 Subject: [PATCH 003/269] test(perf): add separation buyer-path k6 workload --- .../employment_separation_buyer_path.js | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 tests/performance/employment_separation_buyer_path.js diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js new file mode 100644 index 000000000..4608e01b4 --- /dev/null +++ b/tests/performance/employment_separation_buyer_path.js @@ -0,0 +1,179 @@ +import http from "k6/http"; +import { check, fail } from "k6"; +import exec from "k6/execution"; +import { Rate, Trend } from "k6/metrics"; + +import { + requestBody, + requestHeaders, + validatePerformanceFixture, +} from "./employment_separation_fixture_contract.mjs"; + +const ROUTE = "/v1/employment-separations"; +const MINIMUM_NON_CONTENDING_RECORDS = 1000; +const MINIMUM_CONTENTION_PAIRS = 100; +const fixturePath = __ENV.ORGMETRA_PERFORMANCE_DATA_FILE; +const baseUrl = (__ENV.ORGMETRA_PERFORMANCE_BASE_URL || "").replace(/\/$/, ""); +const bearerToken = __ENV.ORGMETRA_PERFORMANCE_BEARER_TOKEN || ""; +const targetSha = (__ENV.ORGMETRA_PERFORMANCE_TARGET_SHA || "").toLowerCase(); + +if (!fixturePath) fail("ORGMETRA_PERFORMANCE_DATA_FILE is required"); +if (!baseUrl) fail("ORGMETRA_PERFORMANCE_BASE_URL is required"); +if (!bearerToken) fail("ORGMETRA_PERFORMANCE_BEARER_TOKEN is required and must not be stored in the fixture"); +if (!/^[0-9a-f]{40}$/.test(targetSha)) fail("ORGMETRA_PERFORMANCE_TARGET_SHA must be a full Git commit SHA"); + +const fixture = validatePerformanceFixture(JSON.parse(open(fixturePath)), { + minimumNonContendingRecords: MINIMUM_NON_CONTENDING_RECORDS, + minimumContentionPairs: MINIMUM_CONTENTION_PAIRS, +}); +if (fixture.candidate_sha.toLowerCase() !== targetSha) { + fail("performance fixture candidate_sha does not match ORGMETRA_PERFORMANCE_TARGET_SHA"); +} + +function integerSetting(name, fallback, maximum) { + const raw = __ENV[name]; + if (raw === undefined || raw === "") return Math.min(fallback, maximum); + if (!/^\d+$/.test(raw)) fail(`${name} must be a positive integer`); + const value = Number(raw); + if (!Number.isSafeInteger(value) || value < 1 || value > maximum) { + fail(`${name} must be between 1 and ${maximum}`); + } + return value; +} + +const nonContendingVus = integerSetting("ORGMETRA_PERFORMANCE_VUS", 20, fixture.profiles.first_commit.length); +const contentionVus = integerSetting("ORGMETRA_PERFORMANCE_CONTENTION_VUS", 10, fixture.profiles.contention.length); + +const firstCommitDuration = new Trend("employment_separation_first_commit_duration_ms", true); +const replayDuration = new Trend("employment_separation_replay_duration_ms", true); +const rejectionDuration = new Trend("employment_separation_rejection_duration_ms", true); +const contentionDuration = new Trend("employment_separation_contention_duration_ms", true); +const unexpectedResponse = new Rate("employment_separation_unexpected_response"); + +export const options = { + discardResponseBodies: false, + scenarios: { + first_commit: { + executor: "shared-iterations", + exec: "firstCommit", + iterations: fixture.profiles.first_commit.length, + vus: nonContendingVus, + maxDuration: "30m", + gracefulStop: "0s", + }, + replay: { + executor: "shared-iterations", + exec: "replay", + iterations: fixture.profiles.replay.length, + vus: nonContendingVus, + maxDuration: "30m", + gracefulStop: "0s", + }, + rejection: { + executor: "shared-iterations", + exec: "rejection", + iterations: fixture.profiles.rejection.length, + vus: nonContendingVus, + maxDuration: "30m", + gracefulStop: "0s", + }, + contention: { + executor: "shared-iterations", + exec: "contention", + iterations: fixture.profiles.contention.length, + vus: contentionVus, + maxDuration: "30m", + gracefulStop: "0s", + }, + }, + thresholds: { + employment_separation_first_commit_duration_ms: ["p(95)<=20"], + employment_separation_unexpected_response: ["rate==0"], + checks: ["rate==1"], + }, +}; + +function recordAt(profile) { + const records = fixture.profiles[profile]; + const index = exec.scenario.iterationInTest; + if (index < 0 || index >= records.length) fail(`${profile} iteration ${index} is outside the fixture`); + return records[index]; +} + +function parseJson(response) { + try { + return response.json(); + } catch (_) { + return null; + } +} + +function post(command, profile) { + return http.post(`${baseUrl}${ROUTE}`, requestBody(command), { + headers: requestHeaders(command, bearerToken), + tags: { profile }, + }); +} + +function observe(response, trend, profile, predicate) { + trend.add(response.timings.duration, { profile }); + const passed = check(response, { + [`${profile} returned the governed result`]: predicate, + }); + unexpectedResponse.add(!passed, { profile }); +} + +export function firstCommit() { + const response = post(recordAt("first_commit"), "first_commit"); + observe(response, firstCommitDuration, "first_commit", (result) => { + const body = parseJson(result); + return result.status === 200 && body !== null && body.replayed === false; + }); +} + +export function replay() { + const response = post(recordAt("replay"), "replay"); + observe(response, replayDuration, "replay", (result) => { + const body = parseJson(result); + return result.status === 200 && body !== null && body.replayed === true; + }); +} + +export function rejection() { + const response = post(recordAt("rejection"), "rejection"); + observe(response, rejectionDuration, "rejection", (result) => { + const body = parseJson(result); + return result.status === 409 && body !== null && body.error_code === "separation_conflict"; + }); +} + +export function contention() { + const pair = recordAt("contention"); + const responses = http.batch([ + ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.left), { headers: requestHeaders(pair.left, bearerToken), tags: { profile: "contention" } }], + ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.right), { headers: requestHeaders(pair.right, bearerToken), tags: { profile: "contention" } }], + ]); + for (const response of responses) contentionDuration.add(response.timings.duration, { profile: "contention" }); + const statuses = responses.map((response) => response.status).sort((left, right) => left - right); + const passed = check(statuses, { + "contention serializes one commit and one conflict": (values) => values.length === 2 && values[0] === 200 && values[1] === 409, + }); + unexpectedResponse.add(!passed, { profile: "contention" }); +} + +export function handleSummary(data) { + const payload = { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: targetSha, + dataset_id: fixture.dataset_id, + clearance_reference: fixture.clearance_reference, + resource_evidence_reference: fixture.resource_evidence_reference, + base_url: baseUrl, + minimum_non_contending_records: MINIMUM_NON_CONTENDING_RECORDS, + minimum_contention_pairs: MINIMUM_CONTENTION_PAIRS, + k6: data, + }; + const rendered = `${JSON.stringify(payload, null, 2)}\n`; + const path = __ENV.ORGMETRA_PERFORMANCE_SUMMARY_FILE || "employment-separation-performance-result.json"; + return { [path]: rendered, stdout: rendered }; +} From b5c25443713b769f6945dec62a300b97593a290e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:09:08 +0900 Subject: [PATCH 004/269] fix(perf): match production idempotency contract --- .../performance/employment_separation_fixture_contract.mjs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_fixture_contract.mjs b/tests/performance/employment_separation_fixture_contract.mjs index 67af77ed1..0ae4b7513 100644 --- a/tests/performance/employment_separation_fixture_contract.mjs +++ b/tests/performance/employment_separation_fixture_contract.mjs @@ -62,7 +62,12 @@ function requireCommand(command, label) { const actor = requireString(value.actor_reference, `${label}.actor_reference`); if (!ACTOR_PATTERN.test(actor)) fail(`${label}.actor_reference must be a namespaced opaque reference`); const key = requireString(value.idempotency_key, `${label}.idempotency_key`); - if (key.length > 200) fail(`${label}.idempotency_key must not exceed 200 characters`); + if (key.length < 16 || key.length > 200 || [...key].some((character) => { + const code = character.charCodeAt(0); + return code < 0x21 || code > 0x7e; + })) { + fail(`${label}.idempotency_key must be 16 to 200 visible ASCII characters`); + } const payload = requirePlainObject(value.payload, `${label}.payload`); requireExactKeys(payload, BODY_KEYS, `${label}.payload`); From a7918a90e880fda01c59990f36bd8927e96cce98 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:09:26 +0900 Subject: [PATCH 005/269] test(perf): cover exact idempotency boundary --- ...yment_separation_fixture_contract.test.mjs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/performance/employment_separation_fixture_contract.test.mjs b/tests/performance/employment_separation_fixture_contract.test.mjs index f971ab45e..6eb2fb9ee 100644 --- a/tests/performance/employment_separation_fixture_contract.test.mjs +++ b/tests/performance/employment_separation_fixture_contract.test.mjs @@ -10,7 +10,7 @@ import { const ZERO = "00000000-0000-0000-0000-000000000000"; -function command(seed, key = `separation-${seed}`) { +function command(seed, key = `separation-key-${seed.toString().padStart(4, "0")}`) { const suffix = seed.toString(16).padStart(12, "0"); return { tenant_record_id: `10000000-0000-4000-8000-${suffix}`, @@ -30,9 +30,9 @@ function command(seed, key = `separation-${seed}`) { } function fixture() { - const left = command(4, "contention-left"); + const left = command(4, "contention-key-left-0001"); const right = structuredClone(left); - right.idempotency_key = "contention-right"; + right.idempotency_key = "contention-key-right-0001"; return { schema_version: PERFORMANCE_FIXTURE_SCHEMA, candidate_sha: "a".repeat(40), @@ -91,13 +91,23 @@ test("enforces minimum sample cardinality rather than silently shrinking the run ); }); +test("matches the production Idempotency-Key length and visible-ASCII contract", () => { + const shortKey = fixture(); + shortKey.profiles.first_commit[0].idempotency_key = "too-short"; + assert.throws(() => validatePerformanceFixture(shortKey, smallAcceptance), /16 to 200 visible ASCII/); + + const hiddenByte = fixture(); + hiddenByte.profiles.first_commit[0].idempotency_key = "valid-prefix-0001\n"; + assert.throws(() => validatePerformanceFixture(hiddenByte, smallAcceptance), /16 to 200 visible ASCII/); +}); + test("builds the exact published separation request without storing bearer credentials in fixtures", () => { - const value = command(9, "exact-key"); + const value = command(9, "exact-key-00000001"); const headers = requestHeaders(value, "opaque-token"); assert.deepEqual(headers, { Authorization: "Bearer opaque-token", "Content-Type": "application/json", - "Idempotency-Key": "exact-key", + "Idempotency-Key": "exact-key-00000001", "X-Actor-Reference": "worker_admin:perf_9", "X-Purpose-Code": "workforce_admin", "X-Tenant-Reference": "10000000-0000-4000-8000-000000000009", From 2d11255b2867e86ad587a74674133167c8652f6a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:11:15 +0900 Subject: [PATCH 006/269] fix(perf): mirror separation request validation --- ...employment_separation_fixture_contract.mjs | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/tests/performance/employment_separation_fixture_contract.mjs b/tests/performance/employment_separation_fixture_contract.mjs index 0ae4b7513..8f0d5a2fd 100644 --- a/tests/performance/employment_separation_fixture_contract.mjs +++ b/tests/performance/employment_separation_fixture_contract.mjs @@ -1,6 +1,7 @@ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const ACTOR_PATTERN = /^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$/; const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/; +const VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/; const SHA_PATTERN = /^[0-9a-f]{40}$/; const BODY_KEYS = Object.freeze([ "confirmation_reference", @@ -47,6 +48,19 @@ function requireString(value, label) { return value; } +function requireFullDate(value, label) { + const text = requireString(value, label); + if (!DATE_PATTERN.test(text)) fail(`${label} must be an RFC 3339 full-date`); + const [year, month, day] = text.split("-").map(Number); + const parsed = new Date(Date.UTC(year, month - 1, day)); + if ( + parsed.getUTCFullYear() !== year + || parsed.getUTCMonth() !== month - 1 + || parsed.getUTCDate() !== day + ) fail(`${label} must be an RFC 3339 full-date`); + return text; +} + function requireUuid(value, label) { const text = requireString(value, label); if (!UUID_PATTERN.test(text)) fail(`${label} must be a canonical UUID string`); @@ -60,7 +74,7 @@ function requireCommand(command, label) { requireExactKeys(value, ["actor_reference", "idempotency_key", "payload", "tenant_record_id"], label); requireUuid(value.tenant_record_id, `${label}.tenant_record_id`); const actor = requireString(value.actor_reference, `${label}.actor_reference`); - if (!ACTOR_PATTERN.test(actor)) fail(`${label}.actor_reference must be a namespaced opaque reference`); + if (actor.length > 200 || !ACTOR_PATTERN.test(actor)) fail(`${label}.actor_reference must be a namespaced opaque reference`); const key = requireString(value.idempotency_key, `${label}.idempotency_key`); if (key.length < 16 || key.length > 200 || [...key].some((character) => { const code = character.charCodeAt(0); @@ -74,15 +88,16 @@ function requireCommand(command, label) { requireUuid(payload.person_record_id, `${label}.payload.person_record_id`); requireUuid(payload.employment_record_id, `${label}.payload.employment_record_id`); requireUuid(payload.expected_employment_record_version_id, `${label}.payload.expected_employment_record_version_id`); - if (typeof payload.separation_effective_on !== "string" || !DATE_PATTERN.test(payload.separation_effective_on)) { - fail(`${label}.payload.separation_effective_on must be an RFC 3339 full-date`); - } + requireFullDate(payload.separation_effective_on, `${label}.payload.separation_effective_on`); if (!REASON_CODES.has(payload.separation_reason_code)) { fail(`${label}.payload.separation_reason_code must use the governed vocabulary`); } - requireString(payload.evidence_reference, `${label}.payload.evidence_reference`); - requireString(payload.evidence_version_code, `${label}.payload.evidence_version_code`); - requireString(payload.confirmation_reference, `${label}.payload.confirmation_reference`); + const evidenceReference = requireString(payload.evidence_reference, `${label}.payload.evidence_reference`); + if (!ACTOR_PATTERN.test(evidenceReference)) fail(`${label}.payload.evidence_reference must be a namespaced opaque reference`); + const evidenceVersion = requireString(payload.evidence_version_code, `${label}.payload.evidence_version_code`); + if (!VERSION_PATTERN.test(evidenceVersion)) fail(`${label}.payload.evidence_version_code must be a whitespace-free version token`); + const confirmationReference = requireString(payload.confirmation_reference, `${label}.payload.confirmation_reference`); + if (!ACTOR_PATTERN.test(confirmationReference)) fail(`${label}.payload.confirmation_reference must be a namespaced opaque reference`); return value; } @@ -131,7 +146,10 @@ export function validatePerformanceFixture( if (fixture.synthetic !== false) fail("fixture.synthetic must be false for commercial acceptance"); requireString(fixture.clearance_reference, "fixture.clearance_reference"); requireString(fixture.dataset_id, "fixture.dataset_id"); - requireString(fixture.prepared_at, "fixture.prepared_at"); + const preparedAt = requireString(fixture.prepared_at, "fixture.prepared_at"); + if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/.test(preparedAt) || Number.isNaN(Date.parse(preparedAt))) { + fail("fixture.prepared_at must be an RFC 3339 UTC timestamp"); + } requireString(fixture.resource_evidence_reference, "fixture.resource_evidence_reference"); const candidateSha = requireString(fixture.candidate_sha, "fixture.candidate_sha").toLowerCase(); if (!SHA_PATTERN.test(candidateSha)) fail("fixture.candidate_sha must be a full Git commit SHA"); @@ -180,6 +198,10 @@ export function validatePerformanceFixture( export function requestHeaders(command, bearerToken) { requireCommand(command, "command"); const token = requireString(bearerToken, "bearer token"); + if (token.length > 8192 || [...token].some((character) => { + const code = character.charCodeAt(0); + return code < 0x21 || code > 0x7e; + })) fail("bearer token must be 1 to 8192 visible ASCII characters"); return { Authorization: `Bearer ${token}`, "Content-Type": "application/json", From 093e8b200bff732a3dd67e9b76bfed10bb0add40 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:11:30 +0900 Subject: [PATCH 007/269] test(perf): cover separation request parity --- ...yment_separation_fixture_contract.test.mjs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/performance/employment_separation_fixture_contract.test.mjs b/tests/performance/employment_separation_fixture_contract.test.mjs index 6eb2fb9ee..20f73a4bb 100644 --- a/tests/performance/employment_separation_fixture_contract.test.mjs +++ b/tests/performance/employment_separation_fixture_contract.test.mjs @@ -101,6 +101,26 @@ test("matches the production Idempotency-Key length and visible-ASCII contract", assert.throws(() => validatePerformanceFixture(hiddenByte, smallAcceptance), /16 to 200 visible ASCII/); }); +test("rejects fixture values the HTTP and application boundaries would reject", () => { + const badDate = fixture(); + badDate.profiles.first_commit[0].payload.separation_effective_on = "2026-02-30"; + assert.throws(() => validatePerformanceFixture(badDate, smallAcceptance), /RFC 3339 full-date/); + + const badEvidence = fixture(); + badEvidence.profiles.first_commit[0].payload.evidence_reference = "not namespaced"; + assert.throws(() => validatePerformanceFixture(badEvidence, smallAcceptance), /namespaced opaque reference/); + + const badVersion = fixture(); + badVersion.profiles.first_commit[0].payload.evidence_version_code = "version with spaces"; + assert.throws(() => validatePerformanceFixture(badVersion, smallAcceptance), /whitespace-free version token/); +}); + +test("rejects bearer values that the production authentication boundary would reject", () => { + const value = command(10); + assert.throws(() => requestHeaders(value, "has space"), /visible ASCII/); + assert.throws(() => requestHeaders(value, `token${"x".repeat(8192)}`), /visible ASCII/); +}); + test("builds the exact published separation request without storing bearer credentials in fixtures", () => { const value = command(9, "exact-key-00000001"); const headers = requestHeaders(value, "opaque-token"); From 6dc5e2806b566ca8952eaf2d5bd65de6fa41d836 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:12:12 +0900 Subject: [PATCH 008/269] fix(perf): keep target endpoint out of result evidence --- tests/performance/employment_separation_buyer_path.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 4608e01b4..fcf27e430 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -168,7 +168,6 @@ export function handleSummary(data) { dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, resource_evidence_reference: fixture.resource_evidence_reference, - base_url: baseUrl, minimum_non_contending_records: MINIMUM_NON_CONTENDING_RECORDS, minimum_contention_pairs: MINIMUM_CONTENTION_PAIRS, k6: data, From 8f30a0e081dde789fa0583164aad1c5cffab8455 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:15:48 +0900 Subject: [PATCH 009/269] fix(perf): bind prepared-state provenance --- ...employment_separation_fixture_contract.mjs | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/tests/performance/employment_separation_fixture_contract.mjs b/tests/performance/employment_separation_fixture_contract.mjs index 8f0d5a2fd..7e1cd3727 100644 --- a/tests/performance/employment_separation_fixture_contract.mjs +++ b/tests/performance/employment_separation_fixture_contract.mjs @@ -21,6 +21,12 @@ const REASON_CODES = new Set([ "employer_initiated_separation", ]); const PROFILE_NAMES = Object.freeze(["first_commit", "replay", "rejection", "contention"]); +const PROFILE_PRECONDITIONS = Object.freeze({ + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", +}); function fail(message) { throw new Error(message); @@ -48,6 +54,12 @@ function requireString(value, label) { return value; } +function requireNamespacedReference(value, label) { + const text = requireString(value, label); + if (text.length > 200 || !ACTOR_PATTERN.test(text)) fail(`${label} must be a namespaced opaque reference`); + return text; +} + function requireFullDate(value, label) { const text = requireString(value, label); if (!DATE_PATTERN.test(text)) fail(`${label} must be an RFC 3339 full-date`); @@ -73,8 +85,7 @@ function requireCommand(command, label) { const value = requirePlainObject(command, label); requireExactKeys(value, ["actor_reference", "idempotency_key", "payload", "tenant_record_id"], label); requireUuid(value.tenant_record_id, `${label}.tenant_record_id`); - const actor = requireString(value.actor_reference, `${label}.actor_reference`); - if (actor.length > 200 || !ACTOR_PATTERN.test(actor)) fail(`${label}.actor_reference must be a namespaced opaque reference`); + requireNamespacedReference(value.actor_reference, `${label}.actor_reference`); const key = requireString(value.idempotency_key, `${label}.idempotency_key`); if (key.length < 16 || key.length > 200 || [...key].some((character) => { const code = character.charCodeAt(0); @@ -92,12 +103,10 @@ function requireCommand(command, label) { if (!REASON_CODES.has(payload.separation_reason_code)) { fail(`${label}.payload.separation_reason_code must use the governed vocabulary`); } - const evidenceReference = requireString(payload.evidence_reference, `${label}.payload.evidence_reference`); - if (!ACTOR_PATTERN.test(evidenceReference)) fail(`${label}.payload.evidence_reference must be a namespaced opaque reference`); + requireNamespacedReference(payload.evidence_reference, `${label}.payload.evidence_reference`); const evidenceVersion = requireString(payload.evidence_version_code, `${label}.payload.evidence_version_code`); if (!VERSION_PATTERN.test(evidenceVersion)) fail(`${label}.payload.evidence_version_code must be a whitespace-free version token`); - const confirmationReference = requireString(payload.confirmation_reference, `${label}.payload.confirmation_reference`); - if (!ACTOR_PATTERN.test(confirmationReference)) fail(`${label}.payload.confirmation_reference must be a namespaced opaque reference`); + requireNamespacedReference(payload.confirmation_reference, `${label}.payload.confirmation_reference`); return value; } @@ -133,6 +142,9 @@ export function validatePerformanceFixture( "clearance_reference", "dataset_id", "prepared_at", + "prepared_state_evidence_reference", + "preparation_protocol_reference", + "profile_preconditions", "profiles", "resource_evidence_reference", "right_cleared", @@ -144,16 +156,26 @@ export function validatePerformanceFixture( if (fixture.schema_version !== PERFORMANCE_FIXTURE_SCHEMA) fail("fixture.schema_version is unsupported"); if (fixture.right_cleared !== true) fail("fixture.right_cleared must be true for commercial acceptance"); if (fixture.synthetic !== false) fail("fixture.synthetic must be false for commercial acceptance"); - requireString(fixture.clearance_reference, "fixture.clearance_reference"); - requireString(fixture.dataset_id, "fixture.dataset_id"); + requireNamespacedReference(fixture.clearance_reference, "fixture.clearance_reference"); + requireNamespacedReference(fixture.dataset_id, "fixture.dataset_id"); + requireNamespacedReference(fixture.preparation_protocol_reference, "fixture.preparation_protocol_reference"); + requireNamespacedReference(fixture.prepared_state_evidence_reference, "fixture.prepared_state_evidence_reference"); + requireNamespacedReference(fixture.resource_evidence_reference, "fixture.resource_evidence_reference"); const preparedAt = requireString(fixture.prepared_at, "fixture.prepared_at"); if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/.test(preparedAt) || Number.isNaN(Date.parse(preparedAt))) { fail("fixture.prepared_at must be an RFC 3339 UTC timestamp"); } - requireString(fixture.resource_evidence_reference, "fixture.resource_evidence_reference"); const candidateSha = requireString(fixture.candidate_sha, "fixture.candidate_sha").toLowerCase(); if (!SHA_PATTERN.test(candidateSha)) fail("fixture.candidate_sha must be a full Git commit SHA"); + const preconditions = requirePlainObject(fixture.profile_preconditions, "fixture.profile_preconditions"); + requireExactKeys(preconditions, PROFILE_NAMES, "fixture.profile_preconditions"); + for (const profile of PROFILE_NAMES) { + if (preconditions[profile] !== PROFILE_PRECONDITIONS[profile]) { + fail(`fixture.profile_preconditions.${profile} must be ${PROFILE_PRECONDITIONS[profile]}`); + } + } + const profiles = requirePlainObject(fixture.profiles, "fixture.profiles"); requireExactKeys(profiles, PROFILE_NAMES, "fixture.profiles"); for (const profile of ["first_commit", "replay", "rejection"]) { From 5191f2fb68f5ccea893f21bfdb2de2e070dee5e6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:16:12 +0900 Subject: [PATCH 010/269] test(perf): require prepared-state evidence --- ...yment_separation_fixture_contract.test.mjs | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_fixture_contract.test.mjs b/tests/performance/employment_separation_fixture_contract.test.mjs index 20f73a4bb..34c379469 100644 --- a/tests/performance/employment_separation_fixture_contract.test.mjs +++ b/tests/performance/employment_separation_fixture_contract.test.mjs @@ -38,10 +38,18 @@ function fixture() { candidate_sha: "a".repeat(40), right_cleared: true, synthetic: false, - clearance_reference: "data-clearance:perf-2026-09", + clearance_reference: "data_clearance:perf-2026-09", dataset_id: "dataset:employment-separation-perf-1", prepared_at: "2026-09-13T02:00:00Z", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", + }, profiles: { first_commit: [command(1)], replay: [command(2)], @@ -53,7 +61,7 @@ function fixture() { const smallAcceptance = { minimumNonContendingRecords: 1, minimumContentionPairs: 1 }; -test("accepts a right-cleared fixture with isolated performance profiles", () => { +test("accepts a right-cleared fixture with explicit prepared-state provenance", () => { const value = fixture(); assert.equal(validatePerformanceFixture(value, smallAcceptance), value); }); @@ -68,6 +76,22 @@ test("rejects synthetic or uncleared commercial fixtures", () => { assert.throws(() => validatePerformanceFixture(uncleared, smallAcceptance), /right_cleared must be true/); }); +test("requires explicit preparation protocol and prepared-state evidence", () => { + const badProtocol = fixture(); + badProtocol.preparation_protocol_reference = "not namespaced"; + assert.throws(() => validatePerformanceFixture(badProtocol, smallAcceptance), /preparation_protocol_reference must be a namespaced opaque reference/); + + const badEvidence = fixture(); + badEvidence.prepared_state_evidence_reference = "not namespaced"; + assert.throws(() => validatePerformanceFixture(badEvidence, smallAcceptance), /prepared_state_evidence_reference must be a namespaced opaque reference/); +}); + +test("pins the pre-state semantics of every measured profile", () => { + const value = fixture(); + value.profile_preconditions.replay = "active_current_expected_version"; + assert.throws(() => validatePerformanceFixture(value, smallAcceptance), /profile_preconditions.replay/); +}); + test("rejects sentinel identities and profile cross-contamination", () => { const sentinel = fixture(); sentinel.profiles.first_commit[0].payload.person_record_id = ZERO; From beff0210c24f5d179f8a6717fbfeb5881f7c5365 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 11:16:31 +0900 Subject: [PATCH 011/269] fix(perf): emit prepared-state provenance --- tests/performance/employment_separation_buyer_path.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index fcf27e430..c1906333b 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -167,7 +167,10 @@ export function handleSummary(data) { candidate_sha: targetSha, dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, + preparation_protocol_reference: fixture.preparation_protocol_reference, + prepared_state_evidence_reference: fixture.prepared_state_evidence_reference, resource_evidence_reference: fixture.resource_evidence_reference, + profile_preconditions: fixture.profile_preconditions, minimum_non_contending_records: MINIMUM_NON_CONTENDING_RECORDS, minimum_contention_pairs: MINIMUM_CONTENTION_PAIRS, k6: data, From 8a844bb769e05b9188310299e881daf471c738d3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:00:39 +0900 Subject: [PATCH 012/269] test(perf): codify separation response contract --- ...mployment_separation_response_contract.mjs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/performance/employment_separation_response_contract.mjs diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs new file mode 100644 index 000000000..31e8a4cd2 --- /dev/null +++ b/tests/performance/employment_separation_response_contract.mjs @@ -0,0 +1,26 @@ +const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; + +function isPlainObject(value) { + return value !== null && typeof value === "object" && !Array.isArray(value); +} + +export function isGovernedSeparationSuccess(status, body, { employmentRecordId, replayed }) { + if (status !== 200 || !isPlainObject(body)) return false; + if (typeof employmentRecordId !== "string" || !UUID_PATTERN.test(employmentRecordId)) return false; + if (typeof replayed !== "boolean") return false; + if (typeof body.employment_record_id !== "string" || body.employment_record_id.toLowerCase() !== employmentRecordId.toLowerCase()) { + return false; + } + if (typeof body.separated_employment_record_version_id !== "string" || !UUID_PATTERN.test(body.separated_employment_record_version_id)) { + return false; + } + if (typeof body.recorded_at !== "string" || !UTC_TIMESTAMP_PATTERN.test(body.recorded_at) || Number.isNaN(Date.parse(body.recorded_at))) { + return false; + } + return body.replayed === replayed; +} + +export function isGovernedSeparationConflict(status, body) { + return status === 409 && isPlainObject(body) && body.error === "separation_conflict"; +} From bee688e369e39214b59e2bb0f2308939a22eef45 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:00:47 +0900 Subject: [PATCH 013/269] test(perf): regress published separation responses --- ...ment_separation_response_contract.test.mjs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/performance/employment_separation_response_contract.test.mjs diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs new file mode 100644 index 000000000..e73ffea95 --- /dev/null +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -0,0 +1,50 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + isGovernedSeparationConflict, + isGovernedSeparationSuccess, +} from "./employment_separation_response_contract.mjs"; + +const EMPLOYMENT = "30000000-0000-4000-8000-000000000001"; +const VERSION = "50000000-0000-4000-8000-000000000001"; + +function successBody(replayed = false) { + return { + employment_record_id: EMPLOYMENT, + separated_employment_record_version_id: VERSION, + recorded_at: "2026-09-13T02:00:00Z", + replayed, + }; +} + +test("accepts the published first-commit and replay response shape", () => { + assert.equal( + isGovernedSeparationSuccess(200, successBody(false), { employmentRecordId: EMPLOYMENT, replayed: false }), + true, + ); + assert.equal( + isGovernedSeparationSuccess(200, successBody(true), { employmentRecordId: EMPLOYMENT, replayed: true }), + true, + ); +}); + +test("rejects success responses that are replay- or target-inconsistent", () => { + assert.equal( + isGovernedSeparationSuccess(200, successBody(true), { employmentRecordId: EMPLOYMENT, replayed: false }), + false, + ); + assert.equal( + isGovernedSeparationSuccess(200, successBody(false), { + employmentRecordId: "30000000-0000-4000-8000-000000000002", + replayed: false, + }), + false, + ); +}); + +test("uses the published conflict error field rather than an invented error_code field", () => { + assert.equal(isGovernedSeparationConflict(409, { error: "separation_conflict" }), true); + assert.equal(isGovernedSeparationConflict(409, { error_code: "separation_conflict" }), false); + assert.equal(isGovernedSeparationConflict(404, { error: "separation_conflict" }), false); +}); From 6d20671794325facbd285bcae793d9b2b9cb241c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:01:05 +0900 Subject: [PATCH 014/269] fix(perf): match published separation responses --- .../employment_separation_buyer_path.js | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index c1906333b..a49c09169 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -8,6 +8,10 @@ import { requestHeaders, validatePerformanceFixture, } from "./employment_separation_fixture_contract.mjs"; +import { + isGovernedSeparationConflict, + isGovernedSeparationSuccess, +} from "./employment_separation_response_contract.mjs"; const ROUTE = "/v1/employment-separations"; const MINIMUM_NON_CONTENDING_RECORDS = 1000; @@ -124,27 +128,32 @@ function observe(response, trend, profile, predicate) { } export function firstCommit() { - const response = post(recordAt("first_commit"), "first_commit"); - observe(response, firstCommitDuration, "first_commit", (result) => { - const body = parseJson(result); - return result.status === 200 && body !== null && body.replayed === false; - }); + const command = recordAt("first_commit"); + const response = post(command, "first_commit"); + observe(response, firstCommitDuration, "first_commit", (result) => ( + isGovernedSeparationSuccess(result.status, parseJson(result), { + employmentRecordId: command.payload.employment_record_id, + replayed: false, + }) + )); } export function replay() { - const response = post(recordAt("replay"), "replay"); - observe(response, replayDuration, "replay", (result) => { - const body = parseJson(result); - return result.status === 200 && body !== null && body.replayed === true; - }); + const command = recordAt("replay"); + const response = post(command, "replay"); + observe(response, replayDuration, "replay", (result) => ( + isGovernedSeparationSuccess(result.status, parseJson(result), { + employmentRecordId: command.payload.employment_record_id, + replayed: true, + }) + )); } export function rejection() { const response = post(recordAt("rejection"), "rejection"); - observe(response, rejectionDuration, "rejection", (result) => { - const body = parseJson(result); - return result.status === 409 && body !== null && body.error_code === "separation_conflict"; - }); + observe(response, rejectionDuration, "rejection", (result) => ( + isGovernedSeparationConflict(result.status, parseJson(result)) + )); } export function contention() { @@ -154,9 +163,16 @@ export function contention() { ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.right), { headers: requestHeaders(pair.right, bearerToken), tags: { profile: "contention" } }], ]); for (const response of responses) contentionDuration.add(response.timings.duration, { profile: "contention" }); - const statuses = responses.map((response) => response.status).sort((left, right) => left - right); - const passed = check(statuses, { - "contention serializes one commit and one conflict": (values) => values.length === 2 && values[0] === 200 && values[1] === 409, + const parsed = responses.map((response) => ({ status: response.status, body: parseJson(response) })); + const successes = parsed.filter(({ status, body }) => ( + isGovernedSeparationSuccess(status, body, { + employmentRecordId: pair.left.payload.employment_record_id, + replayed: false, + }) + )); + const conflicts = parsed.filter(({ status, body }) => isGovernedSeparationConflict(status, body)); + const passed = check(parsed, { + "contention serializes one governed commit and one governed conflict": () => successes.length === 1 && conflicts.length === 1, }); unexpectedResponse.add(!passed, { profile: "contention" }); } From 57e4728f790b51e79889984aea6428e0b68f94d8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:01:37 +0900 Subject: [PATCH 015/269] test(perf): codify isolated profile runs --- .../employment_separation_run_contract.mjs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/performance/employment_separation_run_contract.mjs diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs new file mode 100644 index 000000000..6d3eff976 --- /dev/null +++ b/tests/performance/employment_separation_run_contract.mjs @@ -0,0 +1,25 @@ +export const PERFORMANCE_PROFILES = Object.freeze([ + "first_commit", + "replay", + "rejection", + "contention", +]); + +export function requirePerformanceProfile(value) { + if (typeof value !== "string" || !PERFORMANCE_PROFILES.includes(value)) { + throw new Error(`ORGMETRA_PERFORMANCE_PROFILE must be exactly one of: ${PERFORMANCE_PROFILES.join(", ")}`); + } + return value; +} + +export function thresholdsForPerformanceProfile(profile) { + requirePerformanceProfile(profile); + const thresholds = { + employment_separation_unexpected_response: ["rate==0"], + checks: ["rate==1"], + }; + if (profile === "first_commit") { + thresholds.employment_separation_first_commit_duration_ms = ["p(95)<=20"]; + } + return thresholds; +} From 059d9f447681baa60a93233944aef67dd2f2bcf4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:01:44 +0900 Subject: [PATCH 016/269] test(perf): regress profile isolation --- ...mployment_separation_run_contract.test.mjs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/performance/employment_separation_run_contract.test.mjs diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs new file mode 100644 index 000000000..af7fd60b6 --- /dev/null +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -0,0 +1,27 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + requirePerformanceProfile, + thresholdsForPerformanceProfile, +} from "./employment_separation_run_contract.mjs"; + +test("requires one explicit performance profile per run", () => { + for (const profile of ["first_commit", "replay", "rejection", "contention"]) { + assert.equal(requirePerformanceProfile(profile), profile); + } + assert.throws(() => requirePerformanceProfile(""), /must be exactly one of/); + assert.throws(() => requirePerformanceProfile("all"), /must be exactly one of/); +}); + +test("applies the commercial p95 threshold only to the ordinary first-commit profile", () => { + assert.deepEqual(thresholdsForPerformanceProfile("first_commit"), { + employment_separation_unexpected_response: ["rate==0"], + checks: ["rate==1"], + employment_separation_first_commit_duration_ms: ["p(95)<=20"], + }); + assert.deepEqual(thresholdsForPerformanceProfile("contention"), { + employment_separation_unexpected_response: ["rate==0"], + checks: ["rate==1"], + }); +}); From 2ef2f39449bcaa0ce8a077f43649af4a70a8e0e3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:02:05 +0900 Subject: [PATCH 017/269] fix(perf): isolate buyer-path profiles --- .../employment_separation_buyer_path.js | 92 ++++++++++--------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index a49c09169..df40888ba 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -12,6 +12,10 @@ import { isGovernedSeparationConflict, isGovernedSeparationSuccess, } from "./employment_separation_response_contract.mjs"; +import { + requirePerformanceProfile, + thresholdsForPerformanceProfile, +} from "./employment_separation_run_contract.mjs"; const ROUTE = "/v1/employment-separations"; const MINIMUM_NON_CONTENDING_RECORDS = 1000; @@ -20,6 +24,7 @@ const fixturePath = __ENV.ORGMETRA_PERFORMANCE_DATA_FILE; const baseUrl = (__ENV.ORGMETRA_PERFORMANCE_BASE_URL || "").replace(/\/$/, ""); const bearerToken = __ENV.ORGMETRA_PERFORMANCE_BEARER_TOKEN || ""; const targetSha = (__ENV.ORGMETRA_PERFORMANCE_TARGET_SHA || "").toLowerCase(); +const selectedProfile = requirePerformanceProfile(__ENV.ORGMETRA_PERFORMANCE_PROFILE || ""); if (!fixturePath) fail("ORGMETRA_PERFORMANCE_DATA_FILE is required"); if (!baseUrl) fail("ORGMETRA_PERFORMANCE_BASE_URL is required"); @@ -45,8 +50,12 @@ function integerSetting(name, fallback, maximum) { return value; } -const nonContendingVus = integerSetting("ORGMETRA_PERFORMANCE_VUS", 20, fixture.profiles.first_commit.length); -const contentionVus = integerSetting("ORGMETRA_PERFORMANCE_CONTENTION_VUS", 10, fixture.profiles.contention.length); +const selectedRecords = fixture.profiles[selectedProfile]; +const selectedVus = integerSetting( + selectedProfile === "contention" ? "ORGMETRA_PERFORMANCE_CONTENTION_VUS" : "ORGMETRA_PERFORMANCE_VUS", + selectedProfile === "contention" ? 10 : 20, + selectedRecords.length, +); const firstCommitDuration = new Trend("employment_separation_first_commit_duration_ms", true); const replayDuration = new Trend("employment_separation_replay_duration_ms", true); @@ -54,49 +63,47 @@ const rejectionDuration = new Trend("employment_separation_rejection_duration_ms const contentionDuration = new Trend("employment_separation_contention_duration_ms", true); const unexpectedResponse = new Rate("employment_separation_unexpected_response"); -export const options = { - discardResponseBodies: false, - scenarios: { - first_commit: { - executor: "shared-iterations", - exec: "firstCommit", - iterations: fixture.profiles.first_commit.length, - vus: nonContendingVus, - maxDuration: "30m", - gracefulStop: "0s", - }, - replay: { - executor: "shared-iterations", - exec: "replay", - iterations: fixture.profiles.replay.length, - vus: nonContendingVus, - maxDuration: "30m", - gracefulStop: "0s", - }, - rejection: { - executor: "shared-iterations", - exec: "rejection", - iterations: fixture.profiles.rejection.length, - vus: nonContendingVus, - maxDuration: "30m", - gracefulStop: "0s", - }, - contention: { - executor: "shared-iterations", - exec: "contention", - iterations: fixture.profiles.contention.length, - vus: contentionVus, - maxDuration: "30m", - gracefulStop: "0s", - }, +const scenarioByProfile = { + first_commit: { + executor: "shared-iterations", + exec: "firstCommit", + iterations: fixture.profiles.first_commit.length, + vus: selectedVus, + maxDuration: "30m", + gracefulStop: "0s", + }, + replay: { + executor: "shared-iterations", + exec: "replay", + iterations: fixture.profiles.replay.length, + vus: selectedVus, + maxDuration: "30m", + gracefulStop: "0s", + }, + rejection: { + executor: "shared-iterations", + exec: "rejection", + iterations: fixture.profiles.rejection.length, + vus: selectedVus, + maxDuration: "30m", + gracefulStop: "0s", }, - thresholds: { - employment_separation_first_commit_duration_ms: ["p(95)<=20"], - employment_separation_unexpected_response: ["rate==0"], - checks: ["rate==1"], + contention: { + executor: "shared-iterations", + exec: "contention", + iterations: fixture.profiles.contention.length, + vus: selectedVus, + maxDuration: "30m", + gracefulStop: "0s", }, }; +export const options = { + discardResponseBodies: false, + scenarios: { [selectedProfile]: scenarioByProfile[selectedProfile] }, + thresholds: thresholdsForPerformanceProfile(selectedProfile), +}; + function recordAt(profile) { const records = fixture.profiles[profile]; const index = exec.scenario.iterationInTest; @@ -181,6 +188,7 @@ export function handleSummary(data) { const payload = { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: targetSha, + selected_profile: selectedProfile, dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, preparation_protocol_reference: fixture.preparation_protocol_reference, @@ -192,6 +200,6 @@ export function handleSummary(data) { k6: data, }; const rendered = `${JSON.stringify(payload, null, 2)}\n`; - const path = __ENV.ORGMETRA_PERFORMANCE_SUMMARY_FILE || "employment-separation-performance-result.json"; + const path = __ENV.ORGMETRA_PERFORMANCE_SUMMARY_FILE || `employment-separation-performance-${selectedProfile}.json`; return { [path]: rendered, stdout: rendered }; } From 350acaa04f4781f5ec7611bd7015bc5c1e4491cb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:03:43 +0900 Subject: [PATCH 018/269] fix(perf): require p99 summary evidence --- tests/performance/employment_separation_run_contract.mjs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index 6d3eff976..b42a13980 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -5,6 +5,13 @@ export const PERFORMANCE_PROFILES = Object.freeze([ "contention", ]); +export const PERFORMANCE_SUMMARY_TREND_STATS = Object.freeze([ + "p(50)", + "p(95)", + "p(99)", + "max", +]); + export function requirePerformanceProfile(value) { if (typeof value !== "string" || !PERFORMANCE_PROFILES.includes(value)) { throw new Error(`ORGMETRA_PERFORMANCE_PROFILE must be exactly one of: ${PERFORMANCE_PROFILES.join(", ")}`); From 5c8037e6b35daf40beda96e014081949c7d0b8c4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:03:50 +0900 Subject: [PATCH 019/269] test(perf): regress required percentile evidence --- .../performance/employment_separation_run_contract.test.mjs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index af7fd60b6..70a091165 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -2,6 +2,7 @@ import assert from "node:assert/strict"; import test from "node:test"; import { + PERFORMANCE_SUMMARY_TREND_STATS, requirePerformanceProfile, thresholdsForPerformanceProfile, } from "./employment_separation_run_contract.mjs"; @@ -25,3 +26,7 @@ test("applies the commercial p95 threshold only to the ordinary first-commit pro checks: ["rate==1"], }); }); + +test("requires the buyer evidence percentiles named by issue 316", () => { + assert.deepEqual(PERFORMANCE_SUMMARY_TREND_STATS, ["p(50)", "p(95)", "p(99)", "max"]); +}); From 2dff0b072417332683a1d814b5fac1c80b07c9cc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:04:10 +0900 Subject: [PATCH 020/269] fix(perf): emit required percentile stats --- tests/performance/employment_separation_buyer_path.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index df40888ba..c8aa803c2 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -13,6 +13,7 @@ import { isGovernedSeparationSuccess, } from "./employment_separation_response_contract.mjs"; import { + PERFORMANCE_SUMMARY_TREND_STATS, requirePerformanceProfile, thresholdsForPerformanceProfile, } from "./employment_separation_run_contract.mjs"; @@ -102,6 +103,7 @@ export const options = { discardResponseBodies: false, scenarios: { [selectedProfile]: scenarioByProfile[selectedProfile] }, thresholds: thresholdsForPerformanceProfile(selectedProfile), + summaryTrendStats: PERFORMANCE_SUMMARY_TREND_STATS, }; function recordAt(profile) { From 0de53f08855ce11e18b67a5d0b1e307e994c70e1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:05:24 +0900 Subject: [PATCH 021/269] fix(perf): fail truncated acceptance runs --- tests/performance/employment_separation_run_contract.mjs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index b42a13980..e152c7d52 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -19,11 +19,15 @@ export function requirePerformanceProfile(value) { return value; } -export function thresholdsForPerformanceProfile(profile) { +export function thresholdsForPerformanceProfile(profile, expectedIterations) { requirePerformanceProfile(profile); + if (!Number.isSafeInteger(expectedIterations) || expectedIterations < 1) { + throw new Error("expectedIterations must be a positive safe integer"); + } const thresholds = { employment_separation_unexpected_response: ["rate==0"], checks: ["rate==1"], + iterations: [`count>=${expectedIterations}`], }; if (profile === "first_commit") { thresholds.employment_separation_first_commit_duration_ms = ["p(95)<=20"]; From a960937a8d1c25874557eb72561de80a762141f4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:05:31 +0900 Subject: [PATCH 022/269] test(perf): regress complete sample requirement --- .../employment_separation_run_contract.test.mjs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 70a091165..8077bd0e4 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -16,17 +16,24 @@ test("requires one explicit performance profile per run", () => { }); test("applies the commercial p95 threshold only to the ordinary first-commit profile", () => { - assert.deepEqual(thresholdsForPerformanceProfile("first_commit"), { + assert.deepEqual(thresholdsForPerformanceProfile("first_commit", 1000), { employment_separation_unexpected_response: ["rate==0"], checks: ["rate==1"], + iterations: ["count>=1000"], employment_separation_first_commit_duration_ms: ["p(95)<=20"], }); - assert.deepEqual(thresholdsForPerformanceProfile("contention"), { + assert.deepEqual(thresholdsForPerformanceProfile("contention", 100), { employment_separation_unexpected_response: ["rate==0"], checks: ["rate==1"], + iterations: ["count>=100"], }); }); +test("refuses acceptance thresholds without an exact positive iteration requirement", () => { + assert.throws(() => thresholdsForPerformanceProfile("first_commit", 0), /positive safe integer/); + assert.throws(() => thresholdsForPerformanceProfile("first_commit", 1.5), /positive safe integer/); +}); + test("requires the buyer evidence percentiles named by issue 316", () => { assert.deepEqual(PERFORMANCE_SUMMARY_TREND_STATS, ["p(50)", "p(95)", "p(99)", "max"]); }); From abc0fadc8641b5be34010885c87b9bd6d152e63c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 12:05:56 +0900 Subject: [PATCH 023/269] fix(perf): expose sample completion evidence --- tests/performance/employment_separation_buyer_path.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index c8aa803c2..0f69abd2c 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -102,7 +102,7 @@ const scenarioByProfile = { export const options = { discardResponseBodies: false, scenarios: { [selectedProfile]: scenarioByProfile[selectedProfile] }, - thresholds: thresholdsForPerformanceProfile(selectedProfile), + thresholds: thresholdsForPerformanceProfile(selectedProfile, selectedRecords.length), summaryTrendStats: PERFORMANCE_SUMMARY_TREND_STATS, }; @@ -187,10 +187,14 @@ export function contention() { } export function handleSummary(data) { + const completedIterations = data.metrics?.iterations?.values?.count ?? null; const payload = { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: targetSha, selected_profile: selectedProfile, + expected_iterations: selectedRecords.length, + completed_iterations: completedIterations, + sample_complete: completedIterations === selectedRecords.length, dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, preparation_protocol_reference: fixture.preparation_protocol_reference, From a02fd5277be6e6711669026e8a5fab6eb1764240 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:05:20 +0900 Subject: [PATCH 024/269] test(perf): reject unbound separation acceptance evidence --- ...nt_separation_acceptance_contract.test.mjs | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_contract.test.mjs diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs new file mode 100644 index 000000000..67d678722 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -0,0 +1,125 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; + +function result() { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: "a".repeat(40), + selected_profile: "first_commit", + expected_iterations: 1000, + completed_iterations: 1000, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", + }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: 1000, rate: 40 } }, + checks: { values: { rate: 1, passes: 1000, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3 }, + }, + }, + }, + }; +} + +function runtimeEvidence(resultText) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: "a".repeat(40), + observed_service_sha: "a".repeat(40), + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42.5, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1.2, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +function evidencePair() { + const performance = result(); + const text = `${JSON.stringify(performance, null, 2)}\n`; + return { performance, text, runtime: runtimeEvidence(text) }; +} + +test("accepts an exact candidate result only with bound deployment, resource, and cleanup evidence", () => { + const { text, runtime } = evidencePair(); + assert.deepEqual(validateEmploymentSeparationAcceptance(text, runtime), { + accepted: true, + candidate_sha: "a".repeat(40), + selected_profile: "first_commit", + performance_result_sha256: runtime.performance_result_sha256, + p95_ms: 18.4, + }); +}); + +test("rejects a self-declared target when the observed service revision differs", () => { + const { text, runtime } = evidencePair(); + runtime.observed_service_sha = "b".repeat(40); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime), /observed_service_sha must match candidate_sha/); +}); + +test("rejects a result artifact that is not the one observed by the runtime evidence", () => { + const { text, runtime } = evidencePair(); + runtime.performance_result_sha256 = "0".repeat(64); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime), /performance_result_sha256/); +}); + +test("rejects first-commit evidence above the commercial p95 target", () => { + const { performance } = evidencePair(); + performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(95)"] = 20.001; + const text = `${JSON.stringify(performance, null, 2)}\n`; + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text)), /p95 must be <= 20 ms/); +}); + +test("rejects incomplete samples even when the completed subset is fast", () => { + const { performance } = evidencePair(); + performance.completed_iterations = 999; + performance.sample_complete = false; + performance.k6.metrics.iterations.values.count = 999; + const text = `${JSON.stringify(performance, null, 2)}\n`; + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text)), /sample must be complete/); +}); + +test("rejects acceptance when post-run cleanup finds a run-scoped leak", () => { + const { text, runtime } = evidencePair(); + runtime.residual_open_transactions = 1; + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime), /residual_open_transactions must be 0/); +}); + +test("rejects missing CPU, memory, or pool observations instead of accepting latency alone", () => { + const { text, runtime } = evidencePair(); + runtime.db_pool_acquire_p95_ms = null; + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime), /db_pool_acquire_p95_ms/); +}); From 53656cb2de4ee8be7ee0632000595e6c5dfa0a54 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:06:37 +0900 Subject: [PATCH 025/269] fix(perf): bind separation acceptance to runtime evidence --- ...loyment_separation_acceptance_contract.mjs | 192 ++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_contract.mjs diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs new file mode 100644 index 000000000..31d00e315 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -0,0 +1,192 @@ +import { createHash } from "node:crypto"; + +const RESULT_SCHEMA = "orgmetra.employment_separation.performance_result.v1"; +const RUNTIME_SCHEMA = "orgmetra.employment_separation.runtime_evidence.v1"; +const SHA_PATTERN = /^[0-9a-f]{40}$/; +const SHA256_PATTERN = /^[0-9a-f]{64}$/; +const REFERENCE_PATTERN = /^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$/; +const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; +const PROFILE_TRENDS = Object.freeze({ + first_commit: "employment_separation_first_commit_duration_ms", + replay: "employment_separation_replay_duration_ms", + rejection: "employment_separation_rejection_duration_ms", + contention: "employment_separation_contention_duration_ms", +}); +const RESIDUAL_FIELDS = Object.freeze([ + "residual_http_tasks", + "residual_db_sessions", + "residual_open_transactions", + "residual_sockets", + "residual_background_workers", + "residual_pool_checkouts", + "residual_pool_waiters", +]); + +function fail(message) { + throw new Error(message); +} + +function plainObject(value, label) { + if (value === null || typeof value !== "object" || Array.isArray(value)) { + fail(`${label} must be an object`); + } + return value; +} + +function stringValue(value, label) { + if (typeof value !== "string" || value.trim() === "") fail(`${label} must be a non-empty string`); + return value; +} + +function sha(value, label) { + const text = stringValue(value, label).toLowerCase(); + if (!SHA_PATTERN.test(text)) fail(`${label} must be a full Git commit SHA`); + return text; +} + +function reference(value, label) { + const text = stringValue(value, label); + if (text.length > 200 || !REFERENCE_PATTERN.test(text)) fail(`${label} must be a namespaced opaque reference`); + return text; +} + +function utcTimestamp(value, label) { + const text = stringValue(value, label); + if (!UTC_TIMESTAMP_PATTERN.test(text) || Number.isNaN(Date.parse(text))) { + fail(`${label} must be an RFC 3339 UTC timestamp`); + } + return text; +} + +function positiveInteger(value, label) { + if (!Number.isSafeInteger(value) || value < 1) fail(`${label} must be a positive safe integer`); + return value; +} + +function nonNegativeInteger(value, label) { + if (!Number.isSafeInteger(value) || value < 0) fail(`${label} must be a non-negative safe integer`); + return value; +} + +function finiteNumber(value, label, { minimum = 0, maximum = Number.POSITIVE_INFINITY } = {}) { + if (typeof value !== "number" || !Number.isFinite(value) || value < minimum || value > maximum) { + fail(`${label} must be a finite number between ${minimum} and ${maximum}`); + } + return value; +} + +function metric(data, name) { + const metrics = plainObject(data.k6, "result.k6").metrics; + const table = plainObject(metrics, "result.k6.metrics"); + return plainObject(table[name], `result.k6.metrics.${name}`); +} + +function metricValues(data, name) { + return plainObject(metric(data, name).values, `result.k6.metrics.${name}.values`); +} + +function validateResult(result) { + if (result.schema_version !== RESULT_SCHEMA) fail("result.schema_version is unsupported"); + const candidateSha = sha(result.candidate_sha, "result.candidate_sha"); + const profile = stringValue(result.selected_profile, "result.selected_profile"); + const trendName = PROFILE_TRENDS[profile]; + if (!trendName) fail("result.selected_profile is unsupported"); + + const expectedIterations = positiveInteger(result.expected_iterations, "result.expected_iterations"); + const completedIterations = nonNegativeInteger(result.completed_iterations, "result.completed_iterations"); + if (result.sample_complete !== true || completedIterations !== expectedIterations) { + fail("result sample must be complete"); + } + const completedAt = utcTimestamp(result.completed_at, "result.completed_at"); + reference(result.resource_evidence_reference, "result.resource_evidence_reference"); + + const iterationValues = metricValues(result, "iterations"); + const metricIterations = nonNegativeInteger(iterationValues.count, "result.k6.metrics.iterations.values.count"); + if (metricIterations !== expectedIterations) fail("k6 iteration count must equal expected_iterations"); + + const checkValues = metricValues(result, "checks"); + if (finiteNumber(checkValues.rate, "result.k6.metrics.checks.values.rate", { maximum: 1 }) !== 1) { + fail("k6 checks rate must equal 1"); + } + const unexpectedValues = metricValues(result, "employment_separation_unexpected_response"); + if (finiteNumber(unexpectedValues.rate, "result.k6.metrics.employment_separation_unexpected_response.values.rate", { maximum: 1 }) !== 0) { + fail("unexpected response rate must equal 0"); + } + + const trendValues = metricValues(result, trendName); + const p50 = finiteNumber(trendValues["p(50)"], `${trendName}.p50`); + const p95 = finiteNumber(trendValues["p(95)"], `${trendName}.p95`); + const p99 = finiteNumber(trendValues["p(99)"], `${trendName}.p99`); + const maximum = finiteNumber(trendValues.max, `${trendName}.max`); + if (!(p50 <= p95 && p95 <= p99 && p99 <= maximum)) { + fail(`${trendName} percentile evidence must be monotonic`); + } + if (profile === "first_commit" && p95 > 20) fail("first_commit p95 must be <= 20 ms"); + + return { candidateSha, profile, p95, completedAt }; +} + +function validateRuntimeEvidence(runtime, resultText, result, validatedResult) { + if (runtime.schema_version !== RUNTIME_SCHEMA) fail("runtime.schema_version is unsupported"); + const candidateSha = sha(runtime.candidate_sha, "runtime.candidate_sha"); + const observedServiceSha = sha(runtime.observed_service_sha, "runtime.observed_service_sha"); + if (candidateSha !== validatedResult.candidateSha) fail("runtime.candidate_sha must match result.candidate_sha"); + if (observedServiceSha !== validatedResult.candidateSha) fail("runtime.observed_service_sha must match candidate_sha"); + if (runtime.selected_profile !== validatedResult.profile) fail("runtime.selected_profile must match result.selected_profile"); + + const suppliedDigest = stringValue(runtime.performance_result_sha256, "runtime.performance_result_sha256").toLowerCase(); + if (!SHA256_PATTERN.test(suppliedDigest)) fail("runtime.performance_result_sha256 must be a SHA-256 digest"); + const observedDigest = createHash("sha256").update(resultText, "utf8").digest("hex"); + if (suppliedDigest !== observedDigest) fail("runtime.performance_result_sha256 does not bind the supplied result artifact"); + + reference(runtime.environment_reference, "runtime.environment_reference"); + reference(runtime.deployment_reference, "runtime.deployment_reference"); + reference(runtime.observer_reference, "runtime.observer_reference"); + const resourceReference = reference(runtime.resource_evidence_reference, "runtime.resource_evidence_reference"); + if (resourceReference !== result.resource_evidence_reference) { + fail("runtime.resource_evidence_reference must match result.resource_evidence_reference"); + } + const observedAt = utcTimestamp(runtime.observed_at, "runtime.observed_at"); + if (Date.parse(observedAt) < Date.parse(validatedResult.completedAt)) { + fail("runtime.observed_at must not precede result.completed_at"); + } + + finiteNumber(runtime.host_cpu_percent_p95, "runtime.host_cpu_percent_p95", { maximum: 100 }); + positiveInteger(runtime.host_rss_bytes_max, "runtime.host_rss_bytes_max"); + finiteNumber(runtime.db_pool_acquire_p95_ms, "runtime.db_pool_acquire_p95_ms"); + nonNegativeInteger(runtime.db_pool_in_use_max, "runtime.db_pool_in_use_max"); + nonNegativeInteger(runtime.db_pool_waiters_max, "runtime.db_pool_waiters_max"); + positiveInteger(runtime.db_connections_max, "runtime.db_connections_max"); + if (runtime.db_pool_in_use_max > runtime.db_connections_max) { + fail("runtime.db_pool_in_use_max cannot exceed runtime.db_connections_max"); + } + + for (const field of RESIDUAL_FIELDS) { + if (nonNegativeInteger(runtime[field], `runtime.${field}`) !== 0) { + fail(`runtime.${field} must be 0`); + } + } + + return suppliedDigest; +} + +export function validateEmploymentSeparationAcceptance(resultText, runtimeEvidence) { + if (typeof resultText !== "string" || resultText.trim() === "") fail("performance result must be non-empty JSON text"); + let parsed; + try { + parsed = JSON.parse(resultText); + } catch (error) { + throw new Error("performance result must be valid JSON", { cause: error }); + } + const result = plainObject(parsed, "result"); + const runtime = plainObject(runtimeEvidence, "runtime"); + const validatedResult = validateResult(result); + const resultDigest = validateRuntimeEvidence(runtime, resultText, result, validatedResult); + return { + accepted: true, + candidate_sha: validatedResult.candidateSha, + selected_profile: validatedResult.profile, + performance_result_sha256: resultDigest, + p95_ms: validatedResult.p95, + }; +} From ca6151c43e1d6ade1c3926f811d6e16a6951ac39 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:07:12 +0900 Subject: [PATCH 026/269] fix(perf): timestamp terminal separation results --- tests/performance/employment_separation_buyer_path.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 0f69abd2c..4080ec7f5 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -195,6 +195,7 @@ export function handleSummary(data) { expected_iterations: selectedRecords.length, completed_iterations: completedIterations, sample_complete: completedIterations === selectedRecords.length, + completed_at: new Date().toISOString(), dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, preparation_protocol_reference: fixture.preparation_protocol_reference, From 87b4039c50448689edc70cc37a331022432febff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:07:43 +0900 Subject: [PATCH 027/269] test(perf): make separation acceptance evidence executable --- ...employment_separation_acceptance_check.mjs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_check.mjs diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs new file mode 100644 index 000000000..a6dd2ac59 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -0,0 +1,27 @@ +import { readFile } from "node:fs/promises"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; + +async function main() { + const [resultPath, runtimeEvidencePath] = process.argv.slice(2); + if (!resultPath || !runtimeEvidencePath || process.argv.length !== 4) { + throw new Error("usage: node employment_separation_acceptance_check.mjs "); + } + const [resultText, runtimeText] = await Promise.all([ + readFile(resultPath, "utf8"), + readFile(runtimeEvidencePath, "utf8"), + ]); + let runtimeEvidence; + try { + runtimeEvidence = JSON.parse(runtimeText); + } catch (error) { + throw new Error("runtime evidence must be valid JSON", { cause: error }); + } + const acceptance = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence); + process.stdout.write(`${JSON.stringify(acceptance, null, 2)}\n`); +} + +main().catch((error) => { + process.stderr.write(`${error.message}\n`); + process.exitCode = 1; +}); From 8d3b56c7592257a1b32dbbfdb2dcb0eb64697651 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:09:01 +0900 Subject: [PATCH 028/269] test(perf): keep p95 target regression percentile-valid --- .../employment_separation_acceptance_contract.test.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 67d678722..e77cf1914 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -99,6 +99,7 @@ test("rejects a result artifact that is not the one observed by the runtime evid test("rejects first-commit evidence above the commercial p95 target", () => { const { performance } = evidencePair(); performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(95)"] = 20.001; + performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(99)"] = 21; const text = `${JSON.stringify(performance, null, 2)}\n`; assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text)), /p95 must be <= 20 ms/); }); From ef35dd54c12ab17a0e424c127bd714d3c2eed109 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:11:00 +0900 Subject: [PATCH 029/269] test(perf): enforce separation acceptance sample floors --- ...separation_acceptance_cardinality.test.mjs | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_cardinality.test.mjs diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs new file mode 100644 index 000000000..38957cf6c --- /dev/null +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -0,0 +1,86 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; + +function performanceResult(profile, iterations) { + const trendName = profile === "contention" + ? "employment_separation_contention_duration_ms" + : "employment_separation_first_commit_duration_ms"; + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: "a".repeat(40), + selected_profile: profile, + expected_iterations: iterations, + completed_iterations: iterations, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + resource_evidence_reference: "metrics:employment-separation-perf-1", + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: iterations } }, + checks: { values: { rate: 1 } }, + employment_separation_unexpected_response: { values: { rate: 0 } }, + [trendName]: { + values: profile === "contention" + ? { "p(50)": 12, "p(95)": 80, "p(99)": 120, max: 200 } + : { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3 }, + }, + }, + }, + }; +} + +function runtimeEvidence(resultText, profile) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: "a".repeat(40), + observed_service_sha: "a".repeat(40), + selected_profile: profile, + performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42.5, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1.2, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +function assertRejected(result, pattern) { + const text = `${JSON.stringify(result, null, 2)}\n`; + assert.throws( + () => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text, result.selected_profile)), + pattern, + ); +} + +test("requires at least 1000 ordinary buyer-path iterations", () => { + assertRejected(performanceResult("first_commit", 1), /at least 1000 iterations/); +}); + +test("requires at least 100 contention pairs", () => { + assertRejected(performanceResult("contention", 99), /at least 100 iterations/); +}); + +test("requires fixed cardinality declarations in the result artifact", () => { + const result = performanceResult("first_commit", 1000); + result.minimum_non_contending_records = 1; + result.minimum_contention_pairs = 1; + assertRejected(result, /minimum_non_contending_records must equal 1000/); +}); From cdc500cf7760272ffdf09dfd422a3258f613825b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:11:33 +0900 Subject: [PATCH 030/269] fix(perf): enforce separation acceptance sample floors --- .../employment_separation_acceptance_contract.mjs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 31d00e315..8a3e1a3b1 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -6,6 +6,8 @@ const SHA_PATTERN = /^[0-9a-f]{40}$/; const SHA256_PATTERN = /^[0-9a-f]{64}$/; const REFERENCE_PATTERN = /^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$/; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; +const MINIMUM_NON_CONTENDING_RECORDS = 1000; +const MINIMUM_CONTENTION_PAIRS = 100; const PROFILE_TRENDS = Object.freeze({ first_commit: "employment_separation_first_commit_duration_ms", replay: "employment_separation_replay_duration_ms", @@ -92,7 +94,18 @@ function validateResult(result) { const trendName = PROFILE_TRENDS[profile]; if (!trendName) fail("result.selected_profile is unsupported"); + if (result.minimum_non_contending_records !== MINIMUM_NON_CONTENDING_RECORDS) { + fail(`result.minimum_non_contending_records must equal ${MINIMUM_NON_CONTENDING_RECORDS}`); + } + if (result.minimum_contention_pairs !== MINIMUM_CONTENTION_PAIRS) { + fail(`result.minimum_contention_pairs must equal ${MINIMUM_CONTENTION_PAIRS}`); + } + const expectedIterations = positiveInteger(result.expected_iterations, "result.expected_iterations"); + const minimumIterations = profile === "contention" ? MINIMUM_CONTENTION_PAIRS : MINIMUM_NON_CONTENDING_RECORDS; + if (expectedIterations < minimumIterations) { + fail(`${profile} requires at least ${minimumIterations} iterations`); + } const completedIterations = nonNegativeInteger(result.completed_iterations, "result.completed_iterations"); if (result.sample_complete !== true || completedIterations !== expectedIterations) { fail("result sample must be complete"); From 301053f0f504484dfa65ee36058933997df26143 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:13:16 +0900 Subject: [PATCH 031/269] test(perf): cover separation acceptance edge cases --- ...oyment_separation_acceptance_edge.test.mjs | 208 ++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_edge.test.mjs diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs new file mode 100644 index 000000000..ecefb3bad --- /dev/null +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -0,0 +1,208 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; + +const TREND_BY_PROFILE = { + first_commit: "employment_separation_first_commit_duration_ms", + replay: "employment_separation_replay_duration_ms", + rejection: "employment_separation_rejection_duration_ms", + contention: "employment_separation_contention_duration_ms", +}; + +function result(profile = "first_commit") { + const iterations = profile === "contention" ? 100 : 1000; + const trend = profile === "first_commit" + ? { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22 } + : { "p(50)": 30, "p(95)": 80, "p(99)": 100, max: 120 }; + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: "a".repeat(40), + selected_profile: profile, + expected_iterations: iterations, + completed_iterations: iterations, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + resource_evidence_reference: "metrics:employment-separation-perf-1", + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: iterations } }, + checks: { values: { rate: 1 } }, + employment_separation_unexpected_response: { values: { rate: 0 } }, + [TREND_BY_PROFILE[profile]]: { values: trend }, + }, + }, + }; +} + +function runtime(resultText, profile = "first_commit") { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: "a".repeat(40), + observed_service_sha: "a".repeat(40), + selected_profile: profile, + performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +function render(value) { + return `${JSON.stringify(value, null, 2)}\n`; +} + +function rejectResult(mutate, pattern = /./, profile = "first_commit") { + const value = result(profile); + mutate(value); + const text = render(value); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text, profile)), pattern); +} + +function rejectRuntime(mutate, pattern = /./, profile = "first_commit") { + const value = result(profile); + const text = render(value); + const evidence = runtime(text, profile); + mutate(evidence); + assert.throws(() => validateEmploymentSeparationAcceptance(text, evidence), pattern); +} + +test("rejects malformed result and runtime containers", () => { + assert.throws(() => validateEmploymentSeparationAcceptance("", {}), /non-empty JSON text/); + assert.throws(() => validateEmploymentSeparationAcceptance(4, {}), /non-empty JSON text/); + assert.throws(() => validateEmploymentSeparationAcceptance("not json", {}), /valid JSON/); + assert.throws(() => validateEmploymentSeparationAcceptance("[]", {}), /result must be an object/); + const text = render(result()); + assert.throws(() => validateEmploymentSeparationAcceptance(text, []), /runtime must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, null), /runtime must be an object/); +}); + +test("rejects invalid result authority and cardinality metadata", () => { + rejectResult((value) => { value.schema_version = "v0"; }, /schema_version/); + rejectResult((value) => { value.candidate_sha = ""; }, /non-empty string/); + rejectResult((value) => { value.candidate_sha = "z".repeat(40); }, /full Git commit SHA/); + rejectResult((value) => { value.selected_profile = null; }, /non-empty string/); + rejectResult((value) => { value.selected_profile = "unknown"; }, /unsupported/); + rejectResult((value) => { value.minimum_non_contending_records = 999; }, /must equal 1000/); + rejectResult((value) => { value.minimum_contention_pairs = 99; }, /must equal 100/); + rejectResult((value) => { value.expected_iterations = 1.5; }, /positive safe integer/); + rejectResult((value) => { value.expected_iterations = 0; }, /positive safe integer/); + rejectResult((value) => { value.completed_iterations = 1.5; }, /non-negative safe integer/); + rejectResult((value) => { value.completed_iterations = -1; }, /non-negative safe integer/); + rejectResult((value) => { value.sample_complete = false; }, /sample must be complete/); + rejectResult((value) => { value.completed_iterations = 999; }, /sample must be complete/); +}); + +test("rejects invalid timestamps and result evidence references", () => { + rejectResult((value) => { value.completed_at = "nope"; }, /UTC timestamp/); + rejectResult((value) => { value.completed_at = "2026-13-40T04:10:00Z"; }, /UTC timestamp/); + rejectResult((value) => { value.resource_evidence_reference = ""; }, /non-empty string/); + rejectResult((value) => { value.resource_evidence_reference = "not namespaced"; }, /namespaced opaque reference/); + rejectResult((value) => { value.resource_evidence_reference = `metrics:${"x".repeat(201)}`; }, /namespaced opaque reference/); +}); + +test("rejects malformed k6 metric containers and iteration evidence", () => { + rejectResult((value) => { value.k6 = null; }, /result.k6 must be an object/); + rejectResult((value) => { value.k6.metrics = []; }, /result.k6.metrics must be an object/); + rejectResult((value) => { delete value.k6.metrics.iterations; }, /iterations must be an object/); + rejectResult((value) => { value.k6.metrics.iterations.values = []; }, /iterations.values must be an object/); + rejectResult((value) => { value.k6.metrics.iterations.values.count = 999; }, /iteration count/); +}); + +test("rejects invalid success and unexpected-response rates", () => { + rejectResult((value) => { value.k6.metrics.checks.values.rate = 0.5; }, /checks rate must equal 1/); + rejectResult((value) => { value.k6.metrics.checks.values.rate = "1"; }, /finite number/); + rejectResult((value) => { value.k6.metrics.checks.values.rate = -0.1; }, /finite number/); + rejectResult((value) => { value.k6.metrics.checks.values.rate = 1.1; }, /finite number/); + rejectResult((value) => { value.k6.metrics.employment_separation_unexpected_response.values.rate = 0.1; }, /unexpected response rate/); +}); + +test("rejects invalid or non-monotonic latency distributions", () => { + const metric = (value) => value.k6.metrics.employment_separation_first_commit_duration_ms.values; + rejectResult((value) => { metric(value)["p(50)"] = null; }, /finite number/); + rejectResult((value) => { metric(value)["p(50)"] = -1; }, /finite number/); + rejectResult((value) => { metric(value)["p(50)"] = 19; metric(value)["p(95)"] = 18; }, /monotonic/); + rejectResult((value) => { metric(value)["p(95)"] = 20; metric(value)["p(99)"] = 19; }, /monotonic/); + rejectResult((value) => { metric(value)["p(99)"] = 23; metric(value).max = 22; }, /monotonic/); +}); + +test("accepts non-first profiles without applying the first-commit latency target", () => { + for (const profile of ["replay", "rejection", "contention"]) { + const value = result(profile); + const text = render(value); + const accepted = validateEmploymentSeparationAcceptance(text, runtime(text, profile)); + assert.equal(accepted.selected_profile, profile); + assert.equal(accepted.p95_ms, 80); + } +}); + +test("rejects malformed runtime authority and artifact binding", () => { + rejectRuntime((value) => { value.schema_version = "v0"; }, /schema_version/); + rejectRuntime((value) => { value.candidate_sha = "b".repeat(40); }, /candidate_sha must match/); + rejectRuntime((value) => { value.candidate_sha = "bad"; }, /full Git commit SHA/); + rejectRuntime((value) => { value.observed_service_sha = "b".repeat(40); }, /observed_service_sha/); + rejectRuntime((value) => { value.observed_service_sha = "bad"; }, /full Git commit SHA/); + rejectRuntime((value) => { value.selected_profile = "replay"; }, /selected_profile/); + rejectRuntime((value) => { value.performance_result_sha256 = "bad"; }, /SHA-256 digest/); + rejectRuntime((value) => { value.performance_result_sha256 = "0".repeat(64); }, /does not bind/); +}); + +test("rejects invalid runtime references and observation time", () => { + rejectRuntime((value) => { value.environment_reference = ""; }, /non-empty string/); + rejectRuntime((value) => { value.environment_reference = "no namespace"; }, /namespaced opaque reference/); + rejectRuntime((value) => { value.deployment_reference = "bad"; }, /namespaced opaque reference/); + rejectRuntime((value) => { value.observer_reference = "bad"; }, /namespaced opaque reference/); + rejectRuntime((value) => { value.resource_evidence_reference = "metrics:different"; }, /must match result.resource_evidence_reference/); + rejectRuntime((value) => { value.observed_at = "nope"; }, /UTC timestamp/); + rejectRuntime((value) => { value.observed_at = "2026-13-40T04:10:01Z"; }, /UTC timestamp/); + rejectRuntime((value) => { value.observed_at = "2026-09-13T04:09:59Z"; }, /must not precede/); +}); + +test("rejects invalid host and pool measurements", () => { + rejectRuntime((value) => { value.host_cpu_percent_p95 = "42"; }, /finite number/); + rejectRuntime((value) => { value.host_cpu_percent_p95 = -1; }, /finite number/); + rejectRuntime((value) => { value.host_cpu_percent_p95 = 101; }, /finite number/); + rejectRuntime((value) => { value.host_rss_bytes_max = 0; }, /positive safe integer/); + rejectRuntime((value) => { value.host_rss_bytes_max = 1.5; }, /positive safe integer/); + rejectRuntime((value) => { value.db_pool_acquire_p95_ms = -1; }, /finite number/); + rejectRuntime((value) => { value.db_pool_in_use_max = -1; }, /non-negative safe integer/); + rejectRuntime((value) => { value.db_pool_in_use_max = 1.5; }, /non-negative safe integer/); + rejectRuntime((value) => { value.db_pool_waiters_max = -1; }, /non-negative safe integer/); + rejectRuntime((value) => { value.db_connections_max = 0; }, /positive safe integer/); + rejectRuntime((value) => { value.db_pool_in_use_max = 21; }, /cannot exceed/); +}); + +test("rejects every residual resource and invalid residual counters", () => { + const fields = [ + "residual_http_tasks", + "residual_db_sessions", + "residual_open_transactions", + "residual_sockets", + "residual_background_workers", + "residual_pool_checkouts", + "residual_pool_waiters", + ]; + for (const field of fields) { + rejectRuntime((value) => { value[field] = 1; }, new RegExp(`${field} must be 0`)); + } + rejectRuntime((value) => { value.residual_http_tasks = -1; }, /non-negative safe integer/); + rejectRuntime((value) => { value.residual_http_tasks = 1.5; }, /non-negative safe integer/); +}); From 999a825f4e99941485daab0b61538554650b2a39 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:22:00 +0900 Subject: [PATCH 032/269] test(perf): reject unproven separation fixture lineage --- ..._separation_acceptance_provenance.test.mjs | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_provenance.test.mjs diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs new file mode 100644 index 000000000..34c54b8a3 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -0,0 +1,97 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; + +const PROFILE_PRECONDITIONS = Object.freeze({ + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", +}); + +function result() { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: "a".repeat(40), + selected_profile: "first_commit", + expected_iterations: 1000, + completed_iterations: 1000, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { ...PROFILE_PRECONDITIONS }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: 1000 } }, + checks: { values: { rate: 1 } }, + employment_separation_unexpected_response: { values: { rate: 0 } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22 }, + }, + }, + }, + }; +} + +function runtime(resultText) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: "a".repeat(40), + observed_service_sha: "a".repeat(40), + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +function reject(mutate, pattern) { + const value = result(); + mutate(value); + const text = `${JSON.stringify(value, null, 2)}\n`; + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text)), pattern); +} + +test("requires right-cleared dataset and preparation provenance references", () => { + for (const field of [ + "dataset_id", + "clearance_reference", + "preparation_protocol_reference", + "prepared_state_evidence_reference", + ]) { + reject((value) => { delete value[field]; }, new RegExp(`result\\.${field}`)); + reject((value) => { value[field] = "not namespaced"; }, new RegExp(`result\\.${field}`)); + } +}); + +test("requires exact profile-precondition vocabulary", () => { + reject((value) => { delete value.profile_preconditions; }, /result\.profile_preconditions/); + reject((value) => { value.profile_preconditions = []; }, /result\.profile_preconditions/); + reject((value) => { delete value.profile_preconditions.replay; }, /exactly first_commit, replay, rejection, contention/); + reject((value) => { value.profile_preconditions.replay = "already_committed_maybe"; }, /profile_preconditions\.replay/); + reject((value) => { value.profile_preconditions.extra = "unexpected"; }, /exactly first_commit, replay, rejection, contention/); +}); From 5b13e3fcc881923938ad51c9aee5a0fc8dcd8d6c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:22:59 +0900 Subject: [PATCH 033/269] fix(perf): require separation fixture provenance at acceptance --- ...loyment_separation_acceptance_contract.mjs | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 8a3e1a3b1..875f4e631 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -8,6 +8,13 @@ const REFERENCE_PATTERN = /^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$/; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; const MINIMUM_NON_CONTENDING_RECORDS = 1000; const MINIMUM_CONTENTION_PAIRS = 100; +const PROFILE_NAMES = Object.freeze(["first_commit", "replay", "rejection", "contention"]); +const PROFILE_PRECONDITIONS = Object.freeze({ + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", +}); const PROFILE_TRENDS = Object.freeze({ first_commit: "employment_separation_first_commit_duration_ms", replay: "employment_separation_replay_duration_ms", @@ -35,6 +42,14 @@ function plainObject(value, label) { return value; } +function exactKeys(value, expected, label) { + const actual = Object.keys(value).sort(); + const wanted = [...expected].sort(); + if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) { + fail(`${label} must contain exactly ${expected.join(", ")}`); + } +} + function stringValue(value, label) { if (typeof value !== "string" || value.trim() === "") fail(`${label} must be a non-empty string`); return value; @@ -94,6 +109,19 @@ function validateResult(result) { const trendName = PROFILE_TRENDS[profile]; if (!trendName) fail("result.selected_profile is unsupported"); + reference(result.dataset_id, "result.dataset_id"); + reference(result.clearance_reference, "result.clearance_reference"); + reference(result.preparation_protocol_reference, "result.preparation_protocol_reference"); + reference(result.prepared_state_evidence_reference, "result.prepared_state_evidence_reference"); + reference(result.resource_evidence_reference, "result.resource_evidence_reference"); + const preconditions = plainObject(result.profile_preconditions, "result.profile_preconditions"); + exactKeys(preconditions, PROFILE_NAMES, "result.profile_preconditions"); + for (const profileName of PROFILE_NAMES) { + if (preconditions[profileName] !== PROFILE_PRECONDITIONS[profileName]) { + fail(`result.profile_preconditions.${profileName} must be ${PROFILE_PRECONDITIONS[profileName]}`); + } + } + if (result.minimum_non_contending_records !== MINIMUM_NON_CONTENDING_RECORDS) { fail(`result.minimum_non_contending_records must equal ${MINIMUM_NON_CONTENDING_RECORDS}`); } @@ -111,7 +139,6 @@ function validateResult(result) { fail("result sample must be complete"); } const completedAt = utcTimestamp(result.completed_at, "result.completed_at"); - reference(result.resource_evidence_reference, "result.resource_evidence_reference"); const iterationValues = metricValues(result, "iterations"); const metricIterations = nonNegativeInteger(iterationValues.count, "result.k6.metrics.iterations.values.count"); From 58feed9f7c656f3fc8bb5fb9bf7e8bac237393c7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:23:18 +0900 Subject: [PATCH 034/269] test(perf): preserve provenance in cardinality fixtures --- ...oyment_separation_acceptance_cardinality.test.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index 38957cf6c..ac868751b 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -4,6 +4,13 @@ import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +const PROFILE_PRECONDITIONS = Object.freeze({ + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", +}); + function performanceResult(profile, iterations) { const trendName = profile === "contention" ? "employment_separation_contention_duration_ms" @@ -16,7 +23,12 @@ function performanceResult(profile, iterations) { completed_iterations: iterations, sample_complete: true, completed_at: "2026-09-13T04:10:00Z", + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { ...PROFILE_PRECONDITIONS }, minimum_non_contending_records: 1000, minimum_contention_pairs: 100, k6: { From 964de4e20ec67319b46a095fb82f6cf80e86f9f3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:23:50 +0900 Subject: [PATCH 035/269] test(perf): preserve provenance in acceptance edge fixtures --- .../employment_separation_acceptance_edge.test.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index ecefb3bad..ccc8931f5 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -10,6 +10,12 @@ const TREND_BY_PROFILE = { rejection: "employment_separation_rejection_duration_ms", contention: "employment_separation_contention_duration_ms", }; +const PROFILE_PRECONDITIONS = Object.freeze({ + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", +}); function result(profile = "first_commit") { const iterations = profile === "contention" ? 100 : 1000; @@ -24,7 +30,12 @@ function result(profile = "first_commit") { completed_iterations: iterations, sample_complete: true, completed_at: "2026-09-13T04:10:00Z", + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { ...PROFILE_PRECONDITIONS }, minimum_non_contending_records: 1000, minimum_contention_pairs: 100, k6: { From dbd7408fa7a7be11cb881db3202f0902fbb984e7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:32:57 +0900 Subject: [PATCH 036/269] test(perf): require complete latency sample evidence --- tests/performance/employment_separation_run_contract.test.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 8077bd0e4..43245d5ac 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -18,12 +18,14 @@ test("requires one explicit performance profile per run", () => { test("applies the commercial p95 threshold only to the ordinary first-commit profile", () => { assert.deepEqual(thresholdsForPerformanceProfile("first_commit", 1000), { employment_separation_unexpected_response: ["rate==0"], + employment_separation_latency_samples: ["count>=1000"], checks: ["rate==1"], iterations: ["count>=1000"], employment_separation_first_commit_duration_ms: ["p(95)<=20"], }); assert.deepEqual(thresholdsForPerformanceProfile("contention", 100), { employment_separation_unexpected_response: ["rate==0"], + employment_separation_latency_samples: ["count>=200"], checks: ["rate==1"], iterations: ["count>=100"], }); From d6b6994df1daf28e3dd998100c7bcf819520cdad Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:33:10 +0900 Subject: [PATCH 037/269] test(perf): reject incomplete latency samples --- ...ration_acceptance_latency_samples.test.mjs | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_latency_samples.test.mjs diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs new file mode 100644 index 000000000..7dfde2e5d --- /dev/null +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -0,0 +1,88 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; + +const candidateSha = "a".repeat(40); + +function performanceResult(latencySamples = 999) { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: candidateSha, + selected_profile: "first_commit", + expected_iterations: 1000, + completed_iterations: 1000, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", + }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: 1000 } }, + checks: { values: { rate: 1 } }, + employment_separation_unexpected_response: { values: { rate: 0 } }, + employment_separation_latency_samples: { values: { count: latencySamples } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22 }, + }, + }, + }, + }; +} + +function runtimeEvidence(resultText) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: candidateSha, + observed_service_sha: candidateSha, + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +test("rejects a complete iteration count with an incomplete latency sample", () => { + const value = performanceResult(); + const resultText = `${JSON.stringify(value, null, 2)}\n`; + assert.throws( + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText)), + /latency sample count/, + ); +}); + +test("accepts latency evidence only when every expected request contributed a sample", () => { + const value = performanceResult(1000); + const resultText = `${JSON.stringify(value, null, 2)}\n`; + const accepted = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText)); + assert.equal(accepted.accepted, true); + assert.equal(accepted.p95_ms, 18); +}); From 759fd7fc8cbd7fa1cc0f354f20c9b80086439414 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:33:48 +0900 Subject: [PATCH 038/269] fix(perf): gate complete latency samples --- tests/performance/employment_separation_run_contract.mjs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index e152c7d52..df7cd5f13 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -24,8 +24,13 @@ export function thresholdsForPerformanceProfile(profile, expectedIterations) { if (!Number.isSafeInteger(expectedIterations) || expectedIterations < 1) { throw new Error("expectedIterations must be a positive safe integer"); } + const expectedLatencySamples = profile === "contention" ? expectedIterations * 2 : expectedIterations; + if (!Number.isSafeInteger(expectedLatencySamples)) { + throw new Error("expected latency sample count must be a positive safe integer"); + } const thresholds = { employment_separation_unexpected_response: ["rate==0"], + employment_separation_latency_samples: [`count>=${expectedLatencySamples}`], checks: ["rate==1"], iterations: [`count>=${expectedIterations}`], }; From 38bf8d3e8461ede9b5da1504687e816ecb8a540e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:34:11 +0900 Subject: [PATCH 039/269] fix(perf): count every latency sample --- tests/performance/employment_separation_buyer_path.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 4080ec7f5..10bd25c27 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -1,7 +1,7 @@ import http from "k6/http"; import { check, fail } from "k6"; import exec from "k6/execution"; -import { Rate, Trend } from "k6/metrics"; +import { Counter, Rate, Trend } from "k6/metrics"; import { requestBody, @@ -62,6 +62,7 @@ const firstCommitDuration = new Trend("employment_separation_first_commit_durati const replayDuration = new Trend("employment_separation_replay_duration_ms", true); const rejectionDuration = new Trend("employment_separation_rejection_duration_ms", true); const contentionDuration = new Trend("employment_separation_contention_duration_ms", true); +const latencySamples = new Counter("employment_separation_latency_samples"); const unexpectedResponse = new Rate("employment_separation_unexpected_response"); const scenarioByProfile = { @@ -130,6 +131,7 @@ function post(command, profile) { function observe(response, trend, profile, predicate) { trend.add(response.timings.duration, { profile }); + latencySamples.add(1, { profile }); const passed = check(response, { [`${profile} returned the governed result`]: predicate, }); @@ -171,7 +173,10 @@ export function contention() { ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.left), { headers: requestHeaders(pair.left, bearerToken), tags: { profile: "contention" } }], ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.right), { headers: requestHeaders(pair.right, bearerToken), tags: { profile: "contention" } }], ]); - for (const response of responses) contentionDuration.add(response.timings.duration, { profile: "contention" }); + for (const response of responses) { + contentionDuration.add(response.timings.duration, { profile: "contention" }); + latencySamples.add(1, { profile: "contention" }); + } const parsed = responses.map((response) => ({ status: response.status, body: parseJson(response) })); const successes = parsed.filter(({ status, body }) => ( isGovernedSeparationSuccess(status, body, { From 982ad9a155a7153c32355ed5848bcdf091c549b0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:34:42 +0900 Subject: [PATCH 040/269] fix(perf): bind latency cardinality to acceptance --- .../employment_separation_acceptance_contract.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 875f4e631..3a390fa8e 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -144,6 +144,17 @@ function validateResult(result) { const metricIterations = nonNegativeInteger(iterationValues.count, "result.k6.metrics.iterations.values.count"); if (metricIterations !== expectedIterations) fail("k6 iteration count must equal expected_iterations"); + const expectedLatencySamples = profile === "contention" ? expectedIterations * 2 : expectedIterations; + if (!Number.isSafeInteger(expectedLatencySamples)) fail("expected latency sample count must be a safe integer"); + const latencySampleValues = metricValues(result, "employment_separation_latency_samples"); + const latencySampleCount = nonNegativeInteger( + latencySampleValues.count, + "result.k6.metrics.employment_separation_latency_samples.values.count", + ); + if (latencySampleCount !== expectedLatencySamples) { + fail(`latency sample count must equal ${expectedLatencySamples}`); + } + const checkValues = metricValues(result, "checks"); if (finiteNumber(checkValues.rate, "result.k6.metrics.checks.values.rate", { maximum: 1 }) !== 1) { fail("k6 checks rate must equal 1"); From 0d9abd815639ce0450e9f6c367f081226afa06a5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:34:57 +0900 Subject: [PATCH 041/269] test(perf): carry latency sample evidence --- .../employment_separation_acceptance_contract.test.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index e77cf1914..d5be884c4 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -31,6 +31,7 @@ function result() { iterations: { values: { count: 1000, rate: 40 } }, checks: { values: { rate: 1, passes: 1000, fails: 0 } }, employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, + employment_separation_latency_samples: { values: { count: 1000, rate: 40 } }, employment_separation_first_commit_duration_ms: { values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3 }, }, @@ -109,6 +110,7 @@ test("rejects incomplete samples even when the completed subset is fast", () => performance.completed_iterations = 999; performance.sample_complete = false; performance.k6.metrics.iterations.values.count = 999; + performance.k6.metrics.employment_separation_latency_samples.values.count = 999; const text = `${JSON.stringify(performance, null, 2)}\n`; assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text)), /sample must be complete/); }); From 3ee9e628327ce7533654bb97884abb4a4d089e49 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:35:11 +0900 Subject: [PATCH 042/269] test(perf): bind cardinality to latency samples --- .../employment_separation_acceptance_cardinality.test.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index ac868751b..42a70db70 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -15,6 +15,7 @@ function performanceResult(profile, iterations) { const trendName = profile === "contention" ? "employment_separation_contention_duration_ms" : "employment_separation_first_commit_duration_ms"; + const latencySamples = profile === "contention" ? iterations * 2 : iterations; return { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: "a".repeat(40), @@ -36,6 +37,7 @@ function performanceResult(profile, iterations) { iterations: { values: { count: iterations } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, + employment_separation_latency_samples: { values: { count: latencySamples } }, [trendName]: { values: profile === "contention" ? { "p(50)": 12, "p(95)": 80, "p(99)": 120, max: 200 } From 14691ad9233ebc793e5d87af3fbdb13d45efc006 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:35:23 +0900 Subject: [PATCH 043/269] test(perf): preserve latency samples in provenance fixtures --- .../employment_separation_acceptance_provenance.test.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index 34c54b8a3..021be50ba 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -33,6 +33,7 @@ function result() { iterations: { values: { count: 1000 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, + employment_separation_latency_samples: { values: { count: 1000 } }, employment_separation_first_commit_duration_ms: { values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22 }, }, From e6e2511d09f56facf494eb8ee2969b3de61eac40 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:35:51 +0900 Subject: [PATCH 044/269] test(perf): cover latency sample evidence edges --- .../employment_separation_acceptance_edge.test.mjs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index ccc8931f5..9d85b9e41 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -19,6 +19,7 @@ const PROFILE_PRECONDITIONS = Object.freeze({ function result(profile = "first_commit") { const iterations = profile === "contention" ? 100 : 1000; + const latencySamples = profile === "contention" ? iterations * 2 : iterations; const trend = profile === "first_commit" ? { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22 } : { "p(50)": 30, "p(95)": 80, "p(99)": 100, max: 120 }; @@ -43,6 +44,7 @@ function result(profile = "first_commit") { iterations: { values: { count: iterations } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, + employment_separation_latency_samples: { values: { count: latencySamples } }, [TREND_BY_PROFILE[profile]]: { values: trend }, }, }, @@ -136,6 +138,13 @@ test("rejects malformed k6 metric containers and iteration evidence", () => { rejectResult((value) => { delete value.k6.metrics.iterations; }, /iterations must be an object/); rejectResult((value) => { value.k6.metrics.iterations.values = []; }, /iterations.values must be an object/); rejectResult((value) => { value.k6.metrics.iterations.values.count = 999; }, /iteration count/); + rejectResult((value) => { delete value.k6.metrics.employment_separation_latency_samples; }, /latency_samples must be an object/); + rejectResult((value) => { value.k6.metrics.employment_separation_latency_samples.values.count = 999; }, /latency sample count/); + rejectResult( + (value) => { value.k6.metrics.employment_separation_latency_samples.values.count = 199; }, + /latency sample count/, + "contention", + ); }); test("rejects invalid success and unexpected-response rates", () => { From 19bfd0e5d5276d904efecead6de8b0bc716cd75c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:38:41 +0900 Subject: [PATCH 045/269] test(perf): require trend sample cardinality --- tests/performance/employment_separation_run_contract.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 43245d5ac..1bf1b6e4d 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -36,6 +36,6 @@ test("refuses acceptance thresholds without an exact positive iteration requirem assert.throws(() => thresholdsForPerformanceProfile("first_commit", 1.5), /positive safe integer/); }); -test("requires the buyer evidence percentiles named by issue 316", () => { - assert.deepEqual(PERFORMANCE_SUMMARY_TREND_STATS, ["p(50)", "p(95)", "p(99)", "max"]); +test("requires buyer percentiles plus the exact Trend sample count", () => { + assert.deepEqual(PERFORMANCE_SUMMARY_TREND_STATS, ["p(50)", "p(95)", "p(99)", "max", "count"]); }); From 8ed66f49ebc609c5945beb36a010612fca95231d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:39:01 +0900 Subject: [PATCH 046/269] test(perf): reject truncated Trend samples --- ...ration_acceptance_latency_samples.test.mjs | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs index 7dfde2e5d..3e7653952 100644 --- a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -6,7 +6,7 @@ import { validateEmploymentSeparationAcceptance } from "./employment_separation_ const candidateSha = "a".repeat(40); -function performanceResult(latencySamples = 999) { +function performanceResult(latencySamples = 1000, trendSamples = latencySamples) { return { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: candidateSha, @@ -35,7 +35,7 @@ function performanceResult(latencySamples = 999) { employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: latencySamples } }, employment_separation_first_commit_duration_ms: { - values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22 }, + values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: trendSamples }, }, }, }, @@ -70,8 +70,8 @@ function runtimeEvidence(resultText) { }; } -test("rejects a complete iteration count with an incomplete latency sample", () => { - const value = performanceResult(); +test("rejects a complete iteration count with an incomplete latency counter", () => { + const value = performanceResult(999, 1000); const resultText = `${JSON.stringify(value, null, 2)}\n`; assert.throws( () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText)), @@ -79,8 +79,17 @@ test("rejects a complete iteration count with an incomplete latency sample", () ); }); -test("accepts latency evidence only when every expected request contributed a sample", () => { - const value = performanceResult(1000); +test("rejects a complete counter when the measured Trend itself is truncated", () => { + const value = performanceResult(1000, 999); + const resultText = `${JSON.stringify(value, null, 2)}\n`; + assert.throws( + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText)), + /Trend sample count/, + ); +}); + +test("accepts latency evidence only when every expected request contributed to the measured Trend", () => { + const value = performanceResult(1000, 1000); const resultText = `${JSON.stringify(value, null, 2)}\n`; const accepted = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText)); assert.equal(accepted.accepted, true); From 0a671b3791e3ea0fcc0fd235e310d5d7105e7d24 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:39:26 +0900 Subject: [PATCH 047/269] fix(perf): expose Trend sample count --- tests/performance/employment_separation_run_contract.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index df7cd5f13..095006642 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -10,6 +10,7 @@ export const PERFORMANCE_SUMMARY_TREND_STATS = Object.freeze([ "p(95)", "p(99)", "max", + "count", ]); export function requirePerformanceProfile(value) { From 5a08490fd49efc72faa7fcb0f5e2eae733f852fb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:39:58 +0900 Subject: [PATCH 048/269] fix(perf): bind percentile Trend count --- .../performance/employment_separation_acceptance_contract.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 3a390fa8e..24f5307f5 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -165,6 +165,10 @@ function validateResult(result) { } const trendValues = metricValues(result, trendName); + const trendSampleCount = nonNegativeInteger(trendValues.count, `${trendName}.count`); + if (trendSampleCount !== expectedLatencySamples) { + fail(`Trend sample count must equal ${expectedLatencySamples}`); + } const p50 = finiteNumber(trendValues["p(50)"], `${trendName}.p50`); const p95 = finiteNumber(trendValues["p(95)"], `${trendName}.p95`); const p99 = finiteNumber(trendValues["p(99)"], `${trendName}.p99`); From f118dda0884f92fcf6675de367f59f63662030fc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:41:10 +0900 Subject: [PATCH 049/269] test(perf): bind contract fixture to Trend count --- .../employment_separation_acceptance_contract.test.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index d5be884c4..2e8f8ce36 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -33,7 +33,7 @@ function result() { employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, employment_separation_latency_samples: { values: { count: 1000, rate: 40 } }, employment_separation_first_commit_duration_ms: { - values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3 }, + values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count: 1000 }, }, }, }, @@ -111,6 +111,7 @@ test("rejects incomplete samples even when the completed subset is fast", () => performance.sample_complete = false; performance.k6.metrics.iterations.values.count = 999; performance.k6.metrics.employment_separation_latency_samples.values.count = 999; + performance.k6.metrics.employment_separation_first_commit_duration_ms.values.count = 999; const text = `${JSON.stringify(performance, null, 2)}\n`; assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text)), /sample must be complete/); }); From aa315aa3a3fd0dcb8eab757634e6e5487e3a7fe0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:41:29 +0900 Subject: [PATCH 050/269] test(perf): bind cardinality fixture Trend count --- .../employment_separation_acceptance_cardinality.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index 42a70db70..176fe8758 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -40,8 +40,8 @@ function performanceResult(profile, iterations) { employment_separation_latency_samples: { values: { count: latencySamples } }, [trendName]: { values: profile === "contention" - ? { "p(50)": 12, "p(95)": 80, "p(99)": 120, max: 200 } - : { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3 }, + ? { "p(50)": 12, "p(95)": 80, "p(99)": 120, max: 200, count: latencySamples } + : { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count: latencySamples }, }, }, }, From aedfc3b079ed787cd221c4746bbe40cd5f4df2c5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:41:49 +0900 Subject: [PATCH 051/269] test(perf): bind provenance fixture Trend count --- .../employment_separation_acceptance_provenance.test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index 021be50ba..f33784e34 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -35,7 +35,7 @@ function result() { employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: 1000 } }, employment_separation_first_commit_duration_ms: { - values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22 }, + values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: 1000 }, }, }, }, From 5807ce42aa88805c66287bd81d9e241f149d6ac8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:42:24 +0900 Subject: [PATCH 052/269] test(perf): bind edge fixture Trend count --- .../employment_separation_acceptance_edge.test.mjs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index 9d85b9e41..85cbcba6a 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -21,8 +21,8 @@ function result(profile = "first_commit") { const iterations = profile === "contention" ? 100 : 1000; const latencySamples = profile === "contention" ? iterations * 2 : iterations; const trend = profile === "first_commit" - ? { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22 } - : { "p(50)": 30, "p(95)": 80, "p(99)": 100, max: 120 }; + ? { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: latencySamples } + : { "p(50)": 30, "p(95)": 80, "p(99)": 100, max: 120, count: latencySamples }; return { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: "a".repeat(40), @@ -145,6 +145,12 @@ test("rejects malformed k6 metric containers and iteration evidence", () => { /latency sample count/, "contention", ); + rejectResult((value) => { value.k6.metrics.employment_separation_first_commit_duration_ms.values.count = 999; }, /Trend sample count/); + rejectResult( + (value) => { value.k6.metrics.employment_separation_contention_duration_ms.values.count = 199; }, + /Trend sample count/, + "contention", + ); }); test("rejects invalid success and unexpected-response rates", () => { From 85919ec395e80a914f27bec902e469c8c8701dcf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:45:54 +0900 Subject: [PATCH 053/269] test(perf): add right-cleared fixture evidence helper --- ...ration_acceptance_fixture_test_support.mjs | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_fixture_test_support.mjs diff --git a/tests/performance/employment_separation_acceptance_fixture_test_support.mjs b/tests/performance/employment_separation_acceptance_fixture_test_support.mjs new file mode 100644 index 000000000..164560872 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_fixture_test_support.mjs @@ -0,0 +1,73 @@ +import { createHash } from "node:crypto"; + +export const ACCEPTANCE_CANDIDATE_SHA = "a".repeat(40); +export const ACCEPTANCE_PROFILE_PRECONDITIONS = Object.freeze({ + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", +}); + +function uuid(value) { + const tail = value.toString(16).padStart(12, "0"); + return `00000000-0000-4000-8000-${tail}`; +} + +function command(index, keySuffix = "only") { + return { + actor_reference: `actor:perf${index}`, + idempotency_key: `employment-separation-perf-${index}-${keySuffix}`, + tenant_record_id: uuid(900000), + payload: { + confirmation_reference: `confirmation:perf${index}`, + employment_record_id: uuid(100000 + index), + evidence_reference: `evidence:perf${index}`, + evidence_version_code: "v1", + expected_employment_record_version_id: uuid(500000 + index), + person_record_id: uuid(300000 + index), + separation_effective_on: "2026-09-01", + separation_reason_code: "voluntary_resignation", + }, + }; +} + +function records(start, count) { + return Array.from({ length: count }, (_, offset) => command(start + offset)); +} + +export function acceptanceFixture({ rightCleared = true, synthetic = false } = {}) { + const contentionStart = 4000; + return { + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + clearance_reference: "data_clearance:perf-2026-09", + dataset_id: "dataset:employment-separation-perf-1", + prepared_at: "2026-09-13T04:00:00Z", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + profile_preconditions: { ...ACCEPTANCE_PROFILE_PRECONDITIONS }, + profiles: { + first_commit: records(1, 1000), + replay: records(1001, 1000), + rejection: records(2001, 1000), + contention: Array.from({ length: 100 }, (_, offset) => { + const index = contentionStart + offset; + return { + left: command(index, "left"), + right: command(index, "right"), + }; + }), + }, + resource_evidence_reference: "metrics:employment-separation-perf-1", + right_cleared: rightCleared, + schema_version: "orgmetra.employment_separation.performance_fixture.v1", + synthetic, + }; +} + +export function acceptanceFixtureText(options) { + return `${JSON.stringify(acceptanceFixture(options), null, 2)}\n`; +} + +export function acceptanceFixtureSha256(text) { + return createHash("sha256").update(text, "utf8").digest("hex"); +} From 6912de4fed9a2ba41e3af0adeb56fa21caa1c132 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:46:15 +0900 Subject: [PATCH 054/269] test(perf): require immutable fixture binding --- ...ration_acceptance_fixture_binding.test.mjs | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_fixture_binding.test.mjs diff --git a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs new file mode 100644 index 000000000..a8b398402 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs @@ -0,0 +1,117 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + ACCEPTANCE_CANDIDATE_SHA, + ACCEPTANCE_PROFILE_PRECONDITIONS, + acceptanceFixtureSha256, + acceptanceFixtureText, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; + +function performanceResult(fixtureSha256, { includeFixtureDigest = true } = {}) { + const value = { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + selected_profile: "first_commit", + expected_iterations: 1000, + completed_iterations: 1000, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { ...ACCEPTANCE_PROFILE_PRECONDITIONS }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: 1000 } }, + checks: { values: { rate: 1 } }, + employment_separation_unexpected_response: { values: { rate: 0 } }, + employment_separation_latency_samples: { values: { count: 1000 } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: 1000 }, + }, + }, + }, + }; + if (includeFixtureDigest) value.fixture_sha256 = fixtureSha256; + return value; +} + +function runtimeEvidence(resultText, fixtureSha256) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + observed_service_sha: ACCEPTANCE_CANDIDATE_SHA, + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + fixture_sha256: fixtureSha256, + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +function render(value) { + return `${JSON.stringify(value, null, 2)}\n`; +} + +test("rejects acceptance without an exact fixture digest", () => { + const fixtureText = acceptanceFixtureText(); + const fixtureSha256 = acceptanceFixtureSha256(fixtureText); + const resultText = render(performanceResult(fixtureSha256, { includeFixtureDigest: false })); + assert.throws( + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureText), + /fixture_sha256/, + ); +}); + +test("rejects runtime evidence bound to a different fixture digest", () => { + const fixtureText = acceptanceFixtureText(); + const fixtureSha256 = acceptanceFixtureSha256(fixtureText); + const resultText = render(performanceResult(fixtureSha256)); + assert.throws( + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, "0".repeat(64)), fixtureText), + /fixture_sha256/, + ); +}); + +test("rejects a fixture whose exact bytes are not right-cleared", () => { + const fixtureText = acceptanceFixtureText({ rightCleared: false }); + const fixtureSha256 = acceptanceFixtureSha256(fixtureText); + const resultText = render(performanceResult(fixtureSha256)); + assert.throws( + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureText), + /right_cleared/, + ); +}); + +test("rejects a fixture whose exact bytes are synthetic", () => { + const fixtureText = acceptanceFixtureText({ synthetic: true }); + const fixtureSha256 = acceptanceFixtureSha256(fixtureText); + const resultText = render(performanceResult(fixtureSha256)); + assert.throws( + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureText), + /synthetic/, + ); +}); From 43ae9f687c4ceb5ce62693ee5196a0d42e90902e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:47:21 +0900 Subject: [PATCH 055/269] fix(perf): bind result to exact fixture bytes --- tests/performance/employment_separation_buyer_path.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 10bd25c27..13ff76306 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -1,4 +1,5 @@ import http from "k6/http"; +import crypto from "k6/crypto"; import { check, fail } from "k6"; import exec from "k6/execution"; import { Counter, Rate, Trend } from "k6/metrics"; @@ -32,7 +33,9 @@ if (!baseUrl) fail("ORGMETRA_PERFORMANCE_BASE_URL is required"); if (!bearerToken) fail("ORGMETRA_PERFORMANCE_BEARER_TOKEN is required and must not be stored in the fixture"); if (!/^[0-9a-f]{40}$/.test(targetSha)) fail("ORGMETRA_PERFORMANCE_TARGET_SHA must be a full Git commit SHA"); -const fixture = validatePerformanceFixture(JSON.parse(open(fixturePath)), { +const fixtureText = open(fixturePath); +const fixtureSha256 = crypto.sha256(fixtureText, "hex"); +const fixture = validatePerformanceFixture(JSON.parse(fixtureText), { minimumNonContendingRecords: MINIMUM_NON_CONTENDING_RECORDS, minimumContentionPairs: MINIMUM_CONTENTION_PAIRS, }); @@ -196,6 +199,7 @@ export function handleSummary(data) { const payload = { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: targetSha, + fixture_sha256: fixtureSha256, selected_profile: selectedProfile, expected_iterations: selectedRecords.length, completed_iterations: completedIterations, From f1145983c0c5e7f7a487b261019bae7c355453e3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:47:59 +0900 Subject: [PATCH 056/269] fix(perf): verify exact right-cleared fixture bytes --- ...loyment_separation_acceptance_contract.mjs | 66 +++++++++++++++++-- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 24f5307f5..8aeabfe1d 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -1,5 +1,7 @@ import { createHash } from "node:crypto"; +import { validatePerformanceFixture } from "./employment_separation_fixture_contract.mjs"; + const RESULT_SCHEMA = "orgmetra.employment_separation.performance_result.v1"; const RUNTIME_SCHEMA = "orgmetra.employment_separation.runtime_evidence.v1"; const SHA_PATTERN = /^[0-9a-f]{40}$/; @@ -61,6 +63,12 @@ function sha(value, label) { return text; } +function sha256(value, label) { + const text = stringValue(value, label).toLowerCase(); + if (!SHA256_PATTERN.test(text)) fail(`${label} must be a SHA-256 digest`); + return text; +} + function reference(value, label) { const text = stringValue(value, label); if (text.length > 200 || !REFERENCE_PATTERN.test(text)) fail(`${label} must be a namespaced opaque reference`); @@ -105,6 +113,7 @@ function metricValues(data, name) { function validateResult(result) { if (result.schema_version !== RESULT_SCHEMA) fail("result.schema_version is unsupported"); const candidateSha = sha(result.candidate_sha, "result.candidate_sha"); + const fixtureSha256 = sha256(result.fixture_sha256, "result.fixture_sha256"); const profile = stringValue(result.selected_profile, "result.selected_profile"); const trendName = PROFILE_TRENDS[profile]; if (!trendName) fail("result.selected_profile is unsupported"); @@ -178,10 +187,50 @@ function validateResult(result) { } if (profile === "first_commit" && p95 > 20) fail("first_commit p95 must be <= 20 ms"); - return { candidateSha, profile, p95, completedAt }; + return { candidateSha, fixtureSha256, profile, p95, completedAt }; } -function validateRuntimeEvidence(runtime, resultText, result, validatedResult) { +function parseAndValidateFixture(fixtureText, result, validatedResult) { + if (typeof fixtureText !== "string" || fixtureText.trim() === "") fail("performance fixture must be non-empty JSON text"); + let parsed; + try { + parsed = JSON.parse(fixtureText); + } catch (error) { + throw new Error("performance fixture must be valid JSON", { cause: error }); + } + const fixture = validatePerformanceFixture(parsed, { + minimumNonContendingRecords: MINIMUM_NON_CONTENDING_RECORDS, + minimumContentionPairs: MINIMUM_CONTENTION_PAIRS, + }); + const observedDigest = createHash("sha256").update(fixtureText, "utf8").digest("hex"); + if (observedDigest !== validatedResult.fixtureSha256) { + fail("result.fixture_sha256 does not bind the supplied performance fixture"); + } + if (fixture.candidate_sha.toLowerCase() !== validatedResult.candidateSha) { + fail("fixture.candidate_sha must match result.candidate_sha"); + } + for (const field of [ + "dataset_id", + "clearance_reference", + "preparation_protocol_reference", + "prepared_state_evidence_reference", + "resource_evidence_reference", + ]) { + if (fixture[field] !== result[field]) fail(`fixture.${field} must match result.${field}`); + } + for (const profileName of PROFILE_NAMES) { + if (fixture.profile_preconditions[profileName] !== result.profile_preconditions[profileName]) { + fail(`fixture.profile_preconditions.${profileName} must match result.profile_preconditions.${profileName}`); + } + } + const expectedIterations = fixture.profiles[validatedResult.profile].length; + if (expectedIterations !== result.expected_iterations) { + fail("result.expected_iterations must equal the selected fixture profile cardinality"); + } + return observedDigest; +} + +function validateRuntimeEvidence(runtime, resultText, result, validatedResult, fixtureDigest) { if (runtime.schema_version !== RUNTIME_SCHEMA) fail("runtime.schema_version is unsupported"); const candidateSha = sha(runtime.candidate_sha, "runtime.candidate_sha"); const observedServiceSha = sha(runtime.observed_service_sha, "runtime.observed_service_sha"); @@ -189,10 +238,13 @@ function validateRuntimeEvidence(runtime, resultText, result, validatedResult) { if (observedServiceSha !== validatedResult.candidateSha) fail("runtime.observed_service_sha must match candidate_sha"); if (runtime.selected_profile !== validatedResult.profile) fail("runtime.selected_profile must match result.selected_profile"); - const suppliedDigest = stringValue(runtime.performance_result_sha256, "runtime.performance_result_sha256").toLowerCase(); - if (!SHA256_PATTERN.test(suppliedDigest)) fail("runtime.performance_result_sha256 must be a SHA-256 digest"); + const suppliedDigest = sha256(runtime.performance_result_sha256, "runtime.performance_result_sha256"); const observedDigest = createHash("sha256").update(resultText, "utf8").digest("hex"); if (suppliedDigest !== observedDigest) fail("runtime.performance_result_sha256 does not bind the supplied result artifact"); + const runtimeFixtureDigest = sha256(runtime.fixture_sha256, "runtime.fixture_sha256"); + if (runtimeFixtureDigest !== fixtureDigest || runtimeFixtureDigest !== validatedResult.fixtureSha256) { + fail("runtime.fixture_sha256 must match the exact validated performance fixture"); + } reference(runtime.environment_reference, "runtime.environment_reference"); reference(runtime.deployment_reference, "runtime.deployment_reference"); @@ -225,7 +277,7 @@ function validateRuntimeEvidence(runtime, resultText, result, validatedResult) { return suppliedDigest; } -export function validateEmploymentSeparationAcceptance(resultText, runtimeEvidence) { +export function validateEmploymentSeparationAcceptance(resultText, runtimeEvidence, fixtureText) { if (typeof resultText !== "string" || resultText.trim() === "") fail("performance result must be non-empty JSON text"); let parsed; try { @@ -236,11 +288,13 @@ export function validateEmploymentSeparationAcceptance(resultText, runtimeEviden const result = plainObject(parsed, "result"); const runtime = plainObject(runtimeEvidence, "runtime"); const validatedResult = validateResult(result); - const resultDigest = validateRuntimeEvidence(runtime, resultText, result, validatedResult); + const fixtureDigest = parseAndValidateFixture(fixtureText, result, validatedResult); + const resultDigest = validateRuntimeEvidence(runtime, resultText, result, validatedResult, fixtureDigest); return { accepted: true, candidate_sha: validatedResult.candidateSha, selected_profile: validatedResult.profile, + fixture_sha256: fixtureDigest, performance_result_sha256: resultDigest, p95_ms: validatedResult.p95, }; From 5225ff345119d2e233102cd05c4ca27f13d932b0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:48:09 +0900 Subject: [PATCH 057/269] fix(perf): require fixture artifact at acceptance --- .../employment_separation_acceptance_check.mjs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index a6dd2ac59..f2650f5d1 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -3,13 +3,14 @@ import { readFile } from "node:fs/promises"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; async function main() { - const [resultPath, runtimeEvidencePath] = process.argv.slice(2); - if (!resultPath || !runtimeEvidencePath || process.argv.length !== 4) { - throw new Error("usage: node employment_separation_acceptance_check.mjs "); + const [resultPath, runtimeEvidencePath, fixturePath] = process.argv.slice(2); + if (!resultPath || !runtimeEvidencePath || !fixturePath || process.argv.length !== 5) { + throw new Error("usage: node employment_separation_acceptance_check.mjs "); } - const [resultText, runtimeText] = await Promise.all([ + const [resultText, runtimeText, fixtureText] = await Promise.all([ readFile(resultPath, "utf8"), readFile(runtimeEvidencePath, "utf8"), + readFile(fixturePath, "utf8"), ]); let runtimeEvidence; try { @@ -17,7 +18,7 @@ async function main() { } catch (error) { throw new Error("runtime evidence must be valid JSON", { cause: error }); } - const acceptance = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence); + const acceptance = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence, fixtureText); process.stdout.write(`${JSON.stringify(acceptance, null, 2)}\n`); } From 99a31e2a67e100cb8227f458854e7c2dfa2a899a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:48:43 +0900 Subject: [PATCH 058/269] test(perf): bind acceptance contract to fixture bytes --- ...nt_separation_acceptance_contract.test.mjs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 2e8f8ce36..2fc363da2 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -3,11 +3,19 @@ import { createHash } from "node:crypto"; import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + acceptanceFixtureSha256, + acceptanceFixtureText, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; + +const FIXTURE_TEXT = acceptanceFixtureText(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); function result() { return { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: "a".repeat(40), + fixture_sha256: FIXTURE_SHA256, selected_profile: "first_commit", expected_iterations: 1000, completed_iterations: 1000, @@ -47,6 +55,7 @@ function runtimeEvidence(resultText) { observed_service_sha: "a".repeat(40), selected_profile: "first_commit", performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", @@ -74,12 +83,13 @@ function evidencePair() { return { performance, text, runtime: runtimeEvidence(text) }; } -test("accepts an exact candidate result only with bound deployment, resource, and cleanup evidence", () => { +test("accepts an exact candidate result only with bound fixture, deployment, resource, and cleanup evidence", () => { const { text, runtime } = evidencePair(); - assert.deepEqual(validateEmploymentSeparationAcceptance(text, runtime), { + assert.deepEqual(validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), { accepted: true, candidate_sha: "a".repeat(40), selected_profile: "first_commit", + fixture_sha256: FIXTURE_SHA256, performance_result_sha256: runtime.performance_result_sha256, p95_ms: 18.4, }); @@ -88,13 +98,13 @@ test("accepts an exact candidate result only with bound deployment, resource, an test("rejects a self-declared target when the observed service revision differs", () => { const { text, runtime } = evidencePair(); runtime.observed_service_sha = "b".repeat(40); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime), /observed_service_sha must match candidate_sha/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), /observed_service_sha must match candidate_sha/); }); test("rejects a result artifact that is not the one observed by the runtime evidence", () => { const { text, runtime } = evidencePair(); runtime.performance_result_sha256 = "0".repeat(64); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime), /performance_result_sha256/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), /performance_result_sha256/); }); test("rejects first-commit evidence above the commercial p95 target", () => { @@ -102,7 +112,7 @@ test("rejects first-commit evidence above the commercial p95 target", () => { performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(95)"] = 20.001; performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(99)"] = 21; const text = `${JSON.stringify(performance, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text)), /p95 must be <= 20 ms/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text), FIXTURE_TEXT), /p95 must be <= 20 ms/); }); test("rejects incomplete samples even when the completed subset is fast", () => { @@ -113,17 +123,17 @@ test("rejects incomplete samples even when the completed subset is fast", () => performance.k6.metrics.employment_separation_latency_samples.values.count = 999; performance.k6.metrics.employment_separation_first_commit_duration_ms.values.count = 999; const text = `${JSON.stringify(performance, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text)), /sample must be complete/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text), FIXTURE_TEXT), /sample must be complete/); }); test("rejects acceptance when post-run cleanup finds a run-scoped leak", () => { const { text, runtime } = evidencePair(); runtime.residual_open_transactions = 1; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime), /residual_open_transactions must be 0/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), /residual_open_transactions must be 0/); }); test("rejects missing CPU, memory, or pool observations instead of accepting latency alone", () => { const { text, runtime } = evidencePair(); runtime.db_pool_acquire_p95_ms = null; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime), /db_pool_acquire_p95_ms/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), /db_pool_acquire_p95_ms/); }); From cbfdb9f60ecd185b0e3ebcd1a8f59e853a59c725 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:49:05 +0900 Subject: [PATCH 059/269] test(perf): bind latency evidence to fixture bytes --- ..._separation_acceptance_latency_samples.test.mjs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs index 3e7653952..4537ce3d2 100644 --- a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -3,13 +3,20 @@ import { createHash } from "node:crypto"; import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + acceptanceFixtureSha256, + acceptanceFixtureText, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; const candidateSha = "a".repeat(40); +const FIXTURE_TEXT = acceptanceFixtureText(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); function performanceResult(latencySamples = 1000, trendSamples = latencySamples) { return { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: candidateSha, + fixture_sha256: FIXTURE_SHA256, selected_profile: "first_commit", expected_iterations: 1000, completed_iterations: 1000, @@ -49,6 +56,7 @@ function runtimeEvidence(resultText) { observed_service_sha: candidateSha, selected_profile: "first_commit", performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", @@ -74,7 +82,7 @@ test("rejects a complete iteration count with an incomplete latency counter", () const value = performanceResult(999, 1000); const resultText = `${JSON.stringify(value, null, 2)}\n`; assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText)), + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_TEXT), /latency sample count/, ); }); @@ -83,7 +91,7 @@ test("rejects a complete counter when the measured Trend itself is truncated", ( const value = performanceResult(1000, 999); const resultText = `${JSON.stringify(value, null, 2)}\n`; assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText)), + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_TEXT), /Trend sample count/, ); }); @@ -91,7 +99,7 @@ test("rejects a complete counter when the measured Trend itself is truncated", ( test("accepts latency evidence only when every expected request contributed to the measured Trend", () => { const value = performanceResult(1000, 1000); const resultText = `${JSON.stringify(value, null, 2)}\n`; - const accepted = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText)); + const accepted = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_TEXT); assert.equal(accepted.accepted, true); assert.equal(accepted.p95_ms, 18); }); From 924d1617198066c3d88701a161c630fb1db605e0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:49:30 +0900 Subject: [PATCH 060/269] test(perf): bind cardinality evidence to fixture bytes --- ...ployment_separation_acceptance_cardinality.test.mjs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index 176fe8758..69c5e2738 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -3,6 +3,10 @@ import { createHash } from "node:crypto"; import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + acceptanceFixtureSha256, + acceptanceFixtureText, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; const PROFILE_PRECONDITIONS = Object.freeze({ first_commit: "active_current_expected_version", @@ -10,6 +14,8 @@ const PROFILE_PRECONDITIONS = Object.freeze({ rejection: "expected_version_stale_or_semantic_conflict", contention: "active_current_expected_version", }); +const FIXTURE_TEXT = acceptanceFixtureText(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); function performanceResult(profile, iterations) { const trendName = profile === "contention" @@ -19,6 +25,7 @@ function performanceResult(profile, iterations) { return { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: "a".repeat(40), + fixture_sha256: FIXTURE_SHA256, selected_profile: profile, expected_iterations: iterations, completed_iterations: iterations, @@ -55,6 +62,7 @@ function runtimeEvidence(resultText, profile) { observed_service_sha: "a".repeat(40), selected_profile: profile, performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", @@ -79,7 +87,7 @@ function runtimeEvidence(resultText, profile) { function assertRejected(result, pattern) { const text = `${JSON.stringify(result, null, 2)}\n`; assert.throws( - () => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text, result.selected_profile)), + () => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text, result.selected_profile), FIXTURE_TEXT), pattern, ); } From 0964c49a91f689120fb56ffd04e22c693ce24734 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:50:43 +0900 Subject: [PATCH 061/269] test(perf): bind provenance evidence to fixture bytes --- ...mployment_separation_acceptance_provenance.test.mjs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index f33784e34..c97f56a1f 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -3,6 +3,10 @@ import { createHash } from "node:crypto"; import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + acceptanceFixtureSha256, + acceptanceFixtureText, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; const PROFILE_PRECONDITIONS = Object.freeze({ first_commit: "active_current_expected_version", @@ -10,11 +14,14 @@ const PROFILE_PRECONDITIONS = Object.freeze({ rejection: "expected_version_stale_or_semantic_conflict", contention: "active_current_expected_version", }); +const FIXTURE_TEXT = acceptanceFixtureText(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); function result() { return { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: "a".repeat(40), + fixture_sha256: FIXTURE_SHA256, selected_profile: "first_commit", expected_iterations: 1000, completed_iterations: 1000, @@ -49,6 +56,7 @@ function runtime(resultText) { observed_service_sha: "a".repeat(40), selected_profile: "first_commit", performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", @@ -74,7 +82,7 @@ function reject(mutate, pattern) { const value = result(); mutate(value); const text = `${JSON.stringify(value, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text)), pattern); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text), FIXTURE_TEXT), pattern); } test("requires right-cleared dataset and preparation provenance references", () => { From 32dbdc9f4381e9099dac95b9b52852375df2b918 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 13:51:27 +0900 Subject: [PATCH 062/269] test(perf): bind edge evidence to fixture bytes --- ...oyment_separation_acceptance_edge.test.mjs | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index 85cbcba6a..009105c07 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -3,6 +3,10 @@ import { createHash } from "node:crypto"; import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + acceptanceFixtureSha256, + acceptanceFixtureText, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; const TREND_BY_PROFILE = { first_commit: "employment_separation_first_commit_duration_ms", @@ -16,6 +20,8 @@ const PROFILE_PRECONDITIONS = Object.freeze({ rejection: "expected_version_stale_or_semantic_conflict", contention: "active_current_expected_version", }); +const FIXTURE_TEXT = acceptanceFixtureText(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); function result(profile = "first_commit") { const iterations = profile === "contention" ? 100 : 1000; @@ -26,6 +32,7 @@ function result(profile = "first_commit") { return { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: "a".repeat(40), + fixture_sha256: FIXTURE_SHA256, selected_profile: profile, expected_iterations: iterations, completed_iterations: iterations, @@ -58,6 +65,7 @@ function runtime(resultText, profile = "first_commit") { observed_service_sha: "a".repeat(40), selected_profile: profile, performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", @@ -87,7 +95,7 @@ function rejectResult(mutate, pattern = /./, profile = "first_commit") { const value = result(profile); mutate(value); const text = render(value); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text, profile)), pattern); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text, profile), FIXTURE_TEXT), pattern); } function rejectRuntime(mutate, pattern = /./, profile = "first_commit") { @@ -95,23 +103,24 @@ function rejectRuntime(mutate, pattern = /./, profile = "first_commit") { const text = render(value); const evidence = runtime(text, profile); mutate(evidence); - assert.throws(() => validateEmploymentSeparationAcceptance(text, evidence), pattern); + assert.throws(() => validateEmploymentSeparationAcceptance(text, evidence, FIXTURE_TEXT), pattern); } test("rejects malformed result and runtime containers", () => { - assert.throws(() => validateEmploymentSeparationAcceptance("", {}), /non-empty JSON text/); - assert.throws(() => validateEmploymentSeparationAcceptance(4, {}), /non-empty JSON text/); - assert.throws(() => validateEmploymentSeparationAcceptance("not json", {}), /valid JSON/); - assert.throws(() => validateEmploymentSeparationAcceptance("[]", {}), /result must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance("", {}, FIXTURE_TEXT), /non-empty JSON text/); + assert.throws(() => validateEmploymentSeparationAcceptance(4, {}, FIXTURE_TEXT), /non-empty JSON text/); + assert.throws(() => validateEmploymentSeparationAcceptance("not json", {}, FIXTURE_TEXT), /valid JSON/); + assert.throws(() => validateEmploymentSeparationAcceptance("[]", {}, FIXTURE_TEXT), /result must be an object/); const text = render(result()); - assert.throws(() => validateEmploymentSeparationAcceptance(text, []), /runtime must be an object/); - assert.throws(() => validateEmploymentSeparationAcceptance(text, null), /runtime must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, [], FIXTURE_TEXT), /runtime must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, null, FIXTURE_TEXT), /runtime must be an object/); }); test("rejects invalid result authority and cardinality metadata", () => { rejectResult((value) => { value.schema_version = "v0"; }, /schema_version/); rejectResult((value) => { value.candidate_sha = ""; }, /non-empty string/); rejectResult((value) => { value.candidate_sha = "z".repeat(40); }, /full Git commit SHA/); + rejectResult((value) => { value.fixture_sha256 = "bad"; }, /SHA-256 digest/); rejectResult((value) => { value.selected_profile = null; }, /non-empty string/); rejectResult((value) => { value.selected_profile = "unknown"; }, /unsupported/); rejectResult((value) => { value.minimum_non_contending_records = 999; }, /must equal 1000/); @@ -174,7 +183,7 @@ test("accepts non-first profiles without applying the first-commit latency targe for (const profile of ["replay", "rejection", "contention"]) { const value = result(profile); const text = render(value); - const accepted = validateEmploymentSeparationAcceptance(text, runtime(text, profile)); + const accepted = validateEmploymentSeparationAcceptance(text, runtime(text, profile), FIXTURE_TEXT); assert.equal(accepted.selected_profile, profile); assert.equal(accepted.p95_ms, 80); } @@ -189,6 +198,8 @@ test("rejects malformed runtime authority and artifact binding", () => { rejectRuntime((value) => { value.selected_profile = "replay"; }, /selected_profile/); rejectRuntime((value) => { value.performance_result_sha256 = "bad"; }, /SHA-256 digest/); rejectRuntime((value) => { value.performance_result_sha256 = "0".repeat(64); }, /does not bind/); + rejectRuntime((value) => { value.fixture_sha256 = "bad"; }, /SHA-256 digest/); + rejectRuntime((value) => { value.fixture_sha256 = "0".repeat(64); }, /exact validated performance fixture/); }); test("rejects invalid runtime references and observation time", () => { From 9b1b9bc7637a946c3646b26703f27dea295bc7dd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:02:08 +0900 Subject: [PATCH 063/269] test(perf): reject lossy fixture decoding --- ...ration_acceptance_fixture_binding.test.mjs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs index a8b398402..f61bf0029 100644 --- a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs @@ -115,3 +115,23 @@ test("rejects a fixture whose exact bytes are synthetic", () => { /synthetic/, ); }); + +test("rejects byte-distinct fixture artifacts that collide after lossy UTF-8 decoding", () => { + const fixtureBytes = Buffer.from(acceptanceFixtureText(), "utf8"); + const malformedA = Buffer.concat([Buffer.from([0x80]), fixtureBytes]); + const malformedB = Buffer.concat([Buffer.from([0x81]), fixtureBytes]); + assert.equal(malformedA.toString("utf8"), malformedB.toString("utf8")); + assert.notEqual( + createHash("sha256").update(malformedA).digest("hex"), + createHash("sha256").update(malformedB).digest("hex"), + ); + + for (const malformed of [malformedA, malformedB]) { + const fixtureSha256 = createHash("sha256").update(malformed).digest("hex"); + const resultText = render(performanceResult(fixtureSha256)); + assert.throws( + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), malformed), + /valid UTF-8/, + ); + } +}); From ebcc1b405ee09325eeacb158e902d07d90f57783 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:03:06 +0900 Subject: [PATCH 064/269] fix(perf): bind acceptance to raw fixture bytes --- ...loyment_separation_acceptance_contract.mjs | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 8aeabfe1d..1e67163af 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -1,4 +1,5 @@ import { createHash } from "node:crypto"; +import { TextDecoder } from "node:util"; import { validatePerformanceFixture } from "./employment_separation_fixture_contract.mjs"; @@ -100,6 +101,24 @@ function finiteNumber(value, label, { minimum = 0, maximum = Number.POSITIVE_INF return value; } +function rawBytes(value, label) { + if (value instanceof Uint8Array) return value; + if (value instanceof ArrayBuffer) return new Uint8Array(value); + fail(`${label} must be supplied as raw bytes`); +} + +function decodeStrictUtf8(value, label) { + const bytes = rawBytes(value, label); + let text; + try { + text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); + } catch (error) { + throw new Error(`${label} must be valid UTF-8`, { cause: error }); + } + if (text.trim() === "") fail(`${label} must be non-empty JSON text`); + return { bytes, text }; +} + function metric(data, name) { const metrics = plainObject(data.k6, "result.k6").metrics; const table = plainObject(metrics, "result.k6.metrics"); @@ -190,8 +209,13 @@ function validateResult(result) { return { candidateSha, fixtureSha256, profile, p95, completedAt }; } -function parseAndValidateFixture(fixtureText, result, validatedResult) { - if (typeof fixtureText !== "string" || fixtureText.trim() === "") fail("performance fixture must be non-empty JSON text"); +function parseAndValidateFixture(fixtureArtifact, result, validatedResult) { + const { bytes, text: fixtureText } = decodeStrictUtf8(fixtureArtifact, "performance fixture"); + const observedDigest = createHash("sha256").update(bytes).digest("hex"); + if (observedDigest !== validatedResult.fixtureSha256) { + fail("result.fixture_sha256 does not bind the supplied performance fixture"); + } + let parsed; try { parsed = JSON.parse(fixtureText); @@ -202,10 +226,6 @@ function parseAndValidateFixture(fixtureText, result, validatedResult) { minimumNonContendingRecords: MINIMUM_NON_CONTENDING_RECORDS, minimumContentionPairs: MINIMUM_CONTENTION_PAIRS, }); - const observedDigest = createHash("sha256").update(fixtureText, "utf8").digest("hex"); - if (observedDigest !== validatedResult.fixtureSha256) { - fail("result.fixture_sha256 does not bind the supplied performance fixture"); - } if (fixture.candidate_sha.toLowerCase() !== validatedResult.candidateSha) { fail("fixture.candidate_sha must match result.candidate_sha"); } @@ -277,7 +297,7 @@ function validateRuntimeEvidence(runtime, resultText, result, validatedResult, f return suppliedDigest; } -export function validateEmploymentSeparationAcceptance(resultText, runtimeEvidence, fixtureText) { +export function validateEmploymentSeparationAcceptance(resultText, runtimeEvidence, fixtureArtifact) { if (typeof resultText !== "string" || resultText.trim() === "") fail("performance result must be non-empty JSON text"); let parsed; try { @@ -288,7 +308,7 @@ export function validateEmploymentSeparationAcceptance(resultText, runtimeEviden const result = plainObject(parsed, "result"); const runtime = plainObject(runtimeEvidence, "runtime"); const validatedResult = validateResult(result); - const fixtureDigest = parseAndValidateFixture(fixtureText, result, validatedResult); + const fixtureDigest = parseAndValidateFixture(fixtureArtifact, result, validatedResult); const resultDigest = validateRuntimeEvidence(runtime, resultText, result, validatedResult, fixtureDigest); return { accepted: true, From 986e0c5712ebae40043d2d77395e9f4ab0d349a3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:03:16 +0900 Subject: [PATCH 065/269] fix(perf): preserve fixture bytes in acceptance CLI --- .../performance/employment_separation_acceptance_check.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index f2650f5d1..d45191a2e 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -7,10 +7,10 @@ async function main() { if (!resultPath || !runtimeEvidencePath || !fixturePath || process.argv.length !== 5) { throw new Error("usage: node employment_separation_acceptance_check.mjs "); } - const [resultText, runtimeText, fixtureText] = await Promise.all([ + const [resultText, runtimeText, fixtureBytes] = await Promise.all([ readFile(resultPath, "utf8"), readFile(runtimeEvidencePath, "utf8"), - readFile(fixturePath, "utf8"), + readFile(fixturePath), ]); let runtimeEvidence; try { @@ -18,7 +18,7 @@ async function main() { } catch (error) { throw new Error("runtime evidence must be valid JSON", { cause: error }); } - const acceptance = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence, fixtureText); + const acceptance = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence, fixtureBytes); process.stdout.write(`${JSON.stringify(acceptance, null, 2)}\n`); } From 8691d8ed87649d5c4fe426cda18e61b7fcf5479a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:03:42 +0900 Subject: [PATCH 066/269] fix(perf): hash raw fixture bytes in k6 --- .../employment_separation_buyer_path.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 13ff76306..3148ec106 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -33,9 +33,21 @@ if (!baseUrl) fail("ORGMETRA_PERFORMANCE_BASE_URL is required"); if (!bearerToken) fail("ORGMETRA_PERFORMANCE_BEARER_TOKEN is required and must not be stored in the fixture"); if (!/^[0-9a-f]{40}$/.test(targetSha)) fail("ORGMETRA_PERFORMANCE_TARGET_SHA must be a full Git commit SHA"); -const fixtureText = open(fixturePath); -const fixtureSha256 = crypto.sha256(fixtureText, "hex"); -const fixture = validatePerformanceFixture(JSON.parse(fixtureText), { +const fixtureBytes = open(fixturePath, "b"); +const fixtureSha256 = crypto.sha256(fixtureBytes, "hex"); +let fixtureText; +try { + fixtureText = new TextDecoder("utf-8", { fatal: true }).decode(fixtureBytes); +} catch (_) { + fail("performance fixture must be valid UTF-8"); +} +let fixtureDocument; +try { + fixtureDocument = JSON.parse(fixtureText); +} catch (_) { + fail("performance fixture must be valid JSON"); +} +const fixture = validatePerformanceFixture(fixtureDocument, { minimumNonContendingRecords: MINIMUM_NON_CONTENDING_RECORDS, minimumContentionPairs: MINIMUM_CONTENTION_PAIRS, }); From b1af05297bc0ca29ad401bd46bf618c9e25c38be Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:04:02 +0900 Subject: [PATCH 067/269] test(perf): expose raw fixture artifact bytes --- ...loyment_separation_acceptance_fixture_test_support.mjs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_fixture_test_support.mjs b/tests/performance/employment_separation_acceptance_fixture_test_support.mjs index 164560872..df4d1904b 100644 --- a/tests/performance/employment_separation_acceptance_fixture_test_support.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_test_support.mjs @@ -68,6 +68,10 @@ export function acceptanceFixtureText(options) { return `${JSON.stringify(acceptanceFixture(options), null, 2)}\n`; } -export function acceptanceFixtureSha256(text) { - return createHash("sha256").update(text, "utf8").digest("hex"); +export function acceptanceFixtureBytes(options) { + return Buffer.from(acceptanceFixtureText(options), "utf8"); +} + +export function acceptanceFixtureSha256(value) { + return createHash("sha256").update(value).digest("hex"); } From 1396f8e3eaadf541e1ba56abd7152aff16265acc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:04:22 +0900 Subject: [PATCH 068/269] test(perf): validate cardinality against raw fixture bytes --- .../employment_separation_acceptance_cardinality.test.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index 69c5e2738..21a244f1a 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -4,8 +4,8 @@ import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; import { + acceptanceFixtureBytes, acceptanceFixtureSha256, - acceptanceFixtureText, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const PROFILE_PRECONDITIONS = Object.freeze({ @@ -14,8 +14,8 @@ const PROFILE_PRECONDITIONS = Object.freeze({ rejection: "expected_version_stale_or_semantic_conflict", contention: "active_current_expected_version", }); -const FIXTURE_TEXT = acceptanceFixtureText(); -const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); function performanceResult(profile, iterations) { const trendName = profile === "contention" @@ -87,7 +87,7 @@ function runtimeEvidence(resultText, profile) { function assertRejected(result, pattern) { const text = `${JSON.stringify(result, null, 2)}\n`; assert.throws( - () => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text, result.selected_profile), FIXTURE_TEXT), + () => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text, result.selected_profile), FIXTURE_BYTES), pattern, ); } From 6b66effd4d63fbdfd7198b637e90cb4fc0129b51 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:04:45 +0900 Subject: [PATCH 069/269] test(perf): bind acceptance tests to raw fixture bytes --- ...nt_separation_acceptance_contract.test.mjs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 2fc363da2..ee501813c 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -4,12 +4,12 @@ import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; import { + acceptanceFixtureBytes, acceptanceFixtureSha256, - acceptanceFixtureText, } from "./employment_separation_acceptance_fixture_test_support.mjs"; -const FIXTURE_TEXT = acceptanceFixtureText(); -const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); function result() { return { @@ -85,7 +85,7 @@ function evidencePair() { test("accepts an exact candidate result only with bound fixture, deployment, resource, and cleanup evidence", () => { const { text, runtime } = evidencePair(); - assert.deepEqual(validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), { + assert.deepEqual(validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), { accepted: true, candidate_sha: "a".repeat(40), selected_profile: "first_commit", @@ -98,13 +98,13 @@ test("accepts an exact candidate result only with bound fixture, deployment, res test("rejects a self-declared target when the observed service revision differs", () => { const { text, runtime } = evidencePair(); runtime.observed_service_sha = "b".repeat(40); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), /observed_service_sha must match candidate_sha/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /observed_service_sha must match candidate_sha/); }); test("rejects a result artifact that is not the one observed by the runtime evidence", () => { const { text, runtime } = evidencePair(); runtime.performance_result_sha256 = "0".repeat(64); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), /performance_result_sha256/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /performance_result_sha256/); }); test("rejects first-commit evidence above the commercial p95 target", () => { @@ -112,7 +112,7 @@ test("rejects first-commit evidence above the commercial p95 target", () => { performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(95)"] = 20.001; performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(99)"] = 21; const text = `${JSON.stringify(performance, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text), FIXTURE_TEXT), /p95 must be <= 20 ms/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text), FIXTURE_BYTES), /p95 must be <= 20 ms/); }); test("rejects incomplete samples even when the completed subset is fast", () => { @@ -123,17 +123,17 @@ test("rejects incomplete samples even when the completed subset is fast", () => performance.k6.metrics.employment_separation_latency_samples.values.count = 999; performance.k6.metrics.employment_separation_first_commit_duration_ms.values.count = 999; const text = `${JSON.stringify(performance, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text), FIXTURE_TEXT), /sample must be complete/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text), FIXTURE_BYTES), /sample must be complete/); }); test("rejects acceptance when post-run cleanup finds a run-scoped leak", () => { const { text, runtime } = evidencePair(); runtime.residual_open_transactions = 1; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), /residual_open_transactions must be 0/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /residual_open_transactions must be 0/); }); test("rejects missing CPU, memory, or pool observations instead of accepting latency alone", () => { const { text, runtime } = evidencePair(); runtime.db_pool_acquire_p95_ms = null; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_TEXT), /db_pool_acquire_p95_ms/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /db_pool_acquire_p95_ms/); }); From 5a27e85f03bab2e7c51b0cdf8c35d73570be2217 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:05:16 +0900 Subject: [PATCH 070/269] test(perf): prove raw-byte fixture binding --- ...ration_acceptance_fixture_binding.test.mjs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs index f61bf0029..1f9ef09ca 100644 --- a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs @@ -6,8 +6,8 @@ import { validateEmploymentSeparationAcceptance } from "./employment_separation_ import { ACCEPTANCE_CANDIDATE_SHA, ACCEPTANCE_PROFILE_PRECONDITIONS, + acceptanceFixtureBytes, acceptanceFixtureSha256, - acceptanceFixtureText, } from "./employment_separation_acceptance_fixture_test_support.mjs"; function performanceResult(fixtureSha256, { includeFixtureDigest = true } = {}) { @@ -77,47 +77,47 @@ function render(value) { } test("rejects acceptance without an exact fixture digest", () => { - const fixtureText = acceptanceFixtureText(); - const fixtureSha256 = acceptanceFixtureSha256(fixtureText); + const fixtureBytes = acceptanceFixtureBytes(); + const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); const resultText = render(performanceResult(fixtureSha256, { includeFixtureDigest: false })); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureText), + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureBytes), /fixture_sha256/, ); }); test("rejects runtime evidence bound to a different fixture digest", () => { - const fixtureText = acceptanceFixtureText(); - const fixtureSha256 = acceptanceFixtureSha256(fixtureText); + const fixtureBytes = acceptanceFixtureBytes(); + const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); const resultText = render(performanceResult(fixtureSha256)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, "0".repeat(64)), fixtureText), + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, "0".repeat(64)), fixtureBytes), /fixture_sha256/, ); }); test("rejects a fixture whose exact bytes are not right-cleared", () => { - const fixtureText = acceptanceFixtureText({ rightCleared: false }); - const fixtureSha256 = acceptanceFixtureSha256(fixtureText); + const fixtureBytes = acceptanceFixtureBytes({ rightCleared: false }); + const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); const resultText = render(performanceResult(fixtureSha256)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureText), + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureBytes), /right_cleared/, ); }); test("rejects a fixture whose exact bytes are synthetic", () => { - const fixtureText = acceptanceFixtureText({ synthetic: true }); - const fixtureSha256 = acceptanceFixtureSha256(fixtureText); + const fixtureBytes = acceptanceFixtureBytes({ synthetic: true }); + const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); const resultText = render(performanceResult(fixtureSha256)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureText), + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureBytes), /synthetic/, ); }); test("rejects byte-distinct fixture artifacts that collide after lossy UTF-8 decoding", () => { - const fixtureBytes = Buffer.from(acceptanceFixtureText(), "utf8"); + const fixtureBytes = acceptanceFixtureBytes(); const malformedA = Buffer.concat([Buffer.from([0x80]), fixtureBytes]); const malformedB = Buffer.concat([Buffer.from([0x81]), fixtureBytes]); assert.equal(malformedA.toString("utf8"), malformedB.toString("utf8")); From 0d2e1f07a75d46b6e4a80158a7b75796012da575 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:05:57 +0900 Subject: [PATCH 071/269] test(perf): exercise edge acceptance with raw fixture bytes --- ...oyment_separation_acceptance_edge.test.mjs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index 009105c07..cdd66fe46 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -4,8 +4,8 @@ import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; import { + acceptanceFixtureBytes, acceptanceFixtureSha256, - acceptanceFixtureText, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const TREND_BY_PROFILE = { @@ -20,8 +20,8 @@ const PROFILE_PRECONDITIONS = Object.freeze({ rejection: "expected_version_stale_or_semantic_conflict", contention: "active_current_expected_version", }); -const FIXTURE_TEXT = acceptanceFixtureText(); -const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); function result(profile = "first_commit") { const iterations = profile === "contention" ? 100 : 1000; @@ -95,7 +95,7 @@ function rejectResult(mutate, pattern = /./, profile = "first_commit") { const value = result(profile); mutate(value); const text = render(value); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text, profile), FIXTURE_TEXT), pattern); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text, profile), FIXTURE_BYTES), pattern); } function rejectRuntime(mutate, pattern = /./, profile = "first_commit") { @@ -103,17 +103,17 @@ function rejectRuntime(mutate, pattern = /./, profile = "first_commit") { const text = render(value); const evidence = runtime(text, profile); mutate(evidence); - assert.throws(() => validateEmploymentSeparationAcceptance(text, evidence, FIXTURE_TEXT), pattern); + assert.throws(() => validateEmploymentSeparationAcceptance(text, evidence, FIXTURE_BYTES), pattern); } test("rejects malformed result and runtime containers", () => { - assert.throws(() => validateEmploymentSeparationAcceptance("", {}, FIXTURE_TEXT), /non-empty JSON text/); - assert.throws(() => validateEmploymentSeparationAcceptance(4, {}, FIXTURE_TEXT), /non-empty JSON text/); - assert.throws(() => validateEmploymentSeparationAcceptance("not json", {}, FIXTURE_TEXT), /valid JSON/); - assert.throws(() => validateEmploymentSeparationAcceptance("[]", {}, FIXTURE_TEXT), /result must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance("", {}, FIXTURE_BYTES), /non-empty JSON text/); + assert.throws(() => validateEmploymentSeparationAcceptance(4, {}, FIXTURE_BYTES), /non-empty JSON text/); + assert.throws(() => validateEmploymentSeparationAcceptance("not json", {}, FIXTURE_BYTES), /valid JSON/); + assert.throws(() => validateEmploymentSeparationAcceptance("[]", {}, FIXTURE_BYTES), /result must be an object/); const text = render(result()); - assert.throws(() => validateEmploymentSeparationAcceptance(text, [], FIXTURE_TEXT), /runtime must be an object/); - assert.throws(() => validateEmploymentSeparationAcceptance(text, null, FIXTURE_TEXT), /runtime must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, [], FIXTURE_BYTES), /runtime must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance(text, null, FIXTURE_BYTES), /runtime must be an object/); }); test("rejects invalid result authority and cardinality metadata", () => { @@ -183,7 +183,7 @@ test("accepts non-first profiles without applying the first-commit latency targe for (const profile of ["replay", "rejection", "contention"]) { const value = result(profile); const text = render(value); - const accepted = validateEmploymentSeparationAcceptance(text, runtime(text, profile), FIXTURE_TEXT); + const accepted = validateEmploymentSeparationAcceptance(text, runtime(text, profile), FIXTURE_BYTES); assert.equal(accepted.selected_profile, profile); assert.equal(accepted.p95_ms, 80); } From f6c81e87d2720ff9106cb6817f538439e7cd8a04 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:06:14 +0900 Subject: [PATCH 072/269] test(perf): verify latency samples with raw fixture bytes --- ...nt_separation_acceptance_latency_samples.test.mjs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs index 4537ce3d2..6423cfeb8 100644 --- a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -4,13 +4,13 @@ import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; import { + acceptanceFixtureBytes, acceptanceFixtureSha256, - acceptanceFixtureText, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const candidateSha = "a".repeat(40); -const FIXTURE_TEXT = acceptanceFixtureText(); -const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); function performanceResult(latencySamples = 1000, trendSamples = latencySamples) { return { @@ -82,7 +82,7 @@ test("rejects a complete iteration count with an incomplete latency counter", () const value = performanceResult(999, 1000); const resultText = `${JSON.stringify(value, null, 2)}\n`; assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_TEXT), + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_BYTES), /latency sample count/, ); }); @@ -91,7 +91,7 @@ test("rejects a complete counter when the measured Trend itself is truncated", ( const value = performanceResult(1000, 999); const resultText = `${JSON.stringify(value, null, 2)}\n`; assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_TEXT), + () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_BYTES), /Trend sample count/, ); }); @@ -99,7 +99,7 @@ test("rejects a complete counter when the measured Trend itself is truncated", ( test("accepts latency evidence only when every expected request contributed to the measured Trend", () => { const value = performanceResult(1000, 1000); const resultText = `${JSON.stringify(value, null, 2)}\n`; - const accepted = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_TEXT); + const accepted = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_BYTES); assert.equal(accepted.accepted, true); assert.equal(accepted.p95_ms, 18); }); From f4aa8d2e43dce8073a2efd58f9f2ee0e6cba6b62 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:06:29 +0900 Subject: [PATCH 073/269] test(perf): bind provenance checks to raw fixture bytes --- .../employment_separation_acceptance_provenance.test.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index c97f56a1f..a6df8dd45 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -4,8 +4,8 @@ import test from "node:test"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; import { + acceptanceFixtureBytes, acceptanceFixtureSha256, - acceptanceFixtureText, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const PROFILE_PRECONDITIONS = Object.freeze({ @@ -14,8 +14,8 @@ const PROFILE_PRECONDITIONS = Object.freeze({ rejection: "expected_version_stale_or_semantic_conflict", contention: "active_current_expected_version", }); -const FIXTURE_TEXT = acceptanceFixtureText(); -const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_TEXT); +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); function result() { return { @@ -82,7 +82,7 @@ function reject(mutate, pattern) { const value = result(); mutate(value); const text = `${JSON.stringify(value, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text), FIXTURE_TEXT), pattern); + assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text), FIXTURE_BYTES), pattern); } test("requires right-cleared dataset and preparation provenance references", () => { From e8abd50a75dd3cf340670a2337c80ed1bb9036c6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:08:17 +0900 Subject: [PATCH 074/269] test(perf): reject lossy result decoding --- ...nt_separation_acceptance_contract.test.mjs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index ee501813c..4c7a2c9bc 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -137,3 +137,24 @@ test("rejects missing CPU, memory, or pool observations instead of accepting lat runtime.db_pool_acquire_p95_ms = null; assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /db_pool_acquire_p95_ms/); }); + +test("rejects byte-distinct result artifacts that collide after lossy UTF-8 decoding", () => { + const text = `${JSON.stringify(result(), null, 2)}\n`; + const resultBytes = Buffer.from(text, "utf8"); + const malformedA = Buffer.concat([Buffer.from([0x80]), resultBytes]); + const malformedB = Buffer.concat([Buffer.from([0x81]), resultBytes]); + assert.equal(malformedA.toString("utf8"), malformedB.toString("utf8")); + assert.notEqual( + createHash("sha256").update(malformedA).digest("hex"), + createHash("sha256").update(malformedB).digest("hex"), + ); + + for (const malformed of [malformedA, malformedB]) { + const runtime = runtimeEvidence(text); + runtime.performance_result_sha256 = createHash("sha256").update(malformed).digest("hex"); + assert.throws( + () => validateEmploymentSeparationAcceptance(malformed, runtime, FIXTURE_BYTES), + /valid UTF-8/, + ); + } +}); From f4fcb68405a5098a2bae742d70de062f52f36642 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:09:00 +0900 Subject: [PATCH 075/269] fix(perf): bind acceptance to raw result bytes --- ...loyment_separation_acceptance_contract.mjs | 55 +++++++++++-------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 1e67163af..31987338a 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -119,6 +119,21 @@ function decodeStrictUtf8(value, label) { return { bytes, text }; } +function parseJsonArtifact(value, label) { + const { bytes, text } = decodeStrictUtf8(value, label); + let parsed; + try { + parsed = JSON.parse(text); + } catch (error) { + throw new Error(`${label} must be valid JSON`, { cause: error }); + } + return { + bytes, + digest: createHash("sha256").update(bytes).digest("hex"), + parsed, + }; +} + function metric(data, name) { const metrics = plainObject(data.k6, "result.k6").metrics; const table = plainObject(metrics, "result.k6.metrics"); @@ -210,19 +225,12 @@ function validateResult(result) { } function parseAndValidateFixture(fixtureArtifact, result, validatedResult) { - const { bytes, text: fixtureText } = decodeStrictUtf8(fixtureArtifact, "performance fixture"); - const observedDigest = createHash("sha256").update(bytes).digest("hex"); - if (observedDigest !== validatedResult.fixtureSha256) { + const fixtureDocument = parseJsonArtifact(fixtureArtifact, "performance fixture"); + if (fixtureDocument.digest !== validatedResult.fixtureSha256) { fail("result.fixture_sha256 does not bind the supplied performance fixture"); } - let parsed; - try { - parsed = JSON.parse(fixtureText); - } catch (error) { - throw new Error("performance fixture must be valid JSON", { cause: error }); - } - const fixture = validatePerformanceFixture(parsed, { + const fixture = validatePerformanceFixture(fixtureDocument.parsed, { minimumNonContendingRecords: MINIMUM_NON_CONTENDING_RECORDS, minimumContentionPairs: MINIMUM_CONTENTION_PAIRS, }); @@ -247,10 +255,10 @@ function parseAndValidateFixture(fixtureArtifact, result, validatedResult) { if (expectedIterations !== result.expected_iterations) { fail("result.expected_iterations must equal the selected fixture profile cardinality"); } - return observedDigest; + return fixtureDocument.digest; } -function validateRuntimeEvidence(runtime, resultText, result, validatedResult, fixtureDigest) { +function validateRuntimeEvidence(runtime, resultDigest, result, validatedResult, fixtureDigest) { if (runtime.schema_version !== RUNTIME_SCHEMA) fail("runtime.schema_version is unsupported"); const candidateSha = sha(runtime.candidate_sha, "runtime.candidate_sha"); const observedServiceSha = sha(runtime.observed_service_sha, "runtime.observed_service_sha"); @@ -259,8 +267,7 @@ function validateRuntimeEvidence(runtime, resultText, result, validatedResult, f if (runtime.selected_profile !== validatedResult.profile) fail("runtime.selected_profile must match result.selected_profile"); const suppliedDigest = sha256(runtime.performance_result_sha256, "runtime.performance_result_sha256"); - const observedDigest = createHash("sha256").update(resultText, "utf8").digest("hex"); - if (suppliedDigest !== observedDigest) fail("runtime.performance_result_sha256 does not bind the supplied result artifact"); + if (suppliedDigest !== resultDigest) fail("runtime.performance_result_sha256 does not bind the supplied result artifact"); const runtimeFixtureDigest = sha256(runtime.fixture_sha256, "runtime.fixture_sha256"); if (runtimeFixtureDigest !== fixtureDigest || runtimeFixtureDigest !== validatedResult.fixtureSha256) { fail("runtime.fixture_sha256 must match the exact validated performance fixture"); @@ -297,19 +304,19 @@ function validateRuntimeEvidence(runtime, resultText, result, validatedResult, f return suppliedDigest; } -export function validateEmploymentSeparationAcceptance(resultText, runtimeEvidence, fixtureArtifact) { - if (typeof resultText !== "string" || resultText.trim() === "") fail("performance result must be non-empty JSON text"); - let parsed; - try { - parsed = JSON.parse(resultText); - } catch (error) { - throw new Error("performance result must be valid JSON", { cause: error }); - } - const result = plainObject(parsed, "result"); +export function validateEmploymentSeparationAcceptance(resultArtifact, runtimeEvidence, fixtureArtifact) { + const resultDocument = parseJsonArtifact(resultArtifact, "performance result"); + const result = plainObject(resultDocument.parsed, "result"); const runtime = plainObject(runtimeEvidence, "runtime"); const validatedResult = validateResult(result); const fixtureDigest = parseAndValidateFixture(fixtureArtifact, result, validatedResult); - const resultDigest = validateRuntimeEvidence(runtime, resultText, result, validatedResult, fixtureDigest); + const resultDigest = validateRuntimeEvidence( + runtime, + resultDocument.digest, + result, + validatedResult, + fixtureDigest, + ); return { accepted: true, candidate_sha: validatedResult.candidateSha, From 9187caa9e226c4e200072699c631f51eb582e2a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:09:19 +0900 Subject: [PATCH 076/269] fix(perf): preserve result bytes in acceptance CLI --- .../performance/employment_separation_acceptance_check.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index d45191a2e..23d2afcb4 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -7,8 +7,8 @@ async function main() { if (!resultPath || !runtimeEvidencePath || !fixturePath || process.argv.length !== 5) { throw new Error("usage: node employment_separation_acceptance_check.mjs "); } - const [resultText, runtimeText, fixtureBytes] = await Promise.all([ - readFile(resultPath, "utf8"), + const [resultBytes, runtimeText, fixtureBytes] = await Promise.all([ + readFile(resultPath), readFile(runtimeEvidencePath, "utf8"), readFile(fixturePath), ]); @@ -18,7 +18,7 @@ async function main() { } catch (error) { throw new Error("runtime evidence must be valid JSON", { cause: error }); } - const acceptance = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence, fixtureBytes); + const acceptance = validateEmploymentSeparationAcceptance(resultBytes, runtimeEvidence, fixtureBytes); process.stdout.write(`${JSON.stringify(acceptance, null, 2)}\n`); } From 8d7f40b30fa98ad8c34b32fae36201587ced1afa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:09:55 +0900 Subject: [PATCH 077/269] test(perf): validate raw result artifacts --- .../employment_separation_acceptance_cardinality.test.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index 21a244f1a..16fa54f29 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -55,13 +55,13 @@ function performanceResult(profile, iterations) { }; } -function runtimeEvidence(resultText, profile) { +function runtimeEvidence(resultArtifact, profile) { return { schema_version: "orgmetra.employment_separation.runtime_evidence.v1", candidate_sha: "a".repeat(40), observed_service_sha: "a".repeat(40), selected_profile: profile, - performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", @@ -85,9 +85,9 @@ function runtimeEvidence(resultText, profile) { } function assertRejected(result, pattern) { - const text = `${JSON.stringify(result, null, 2)}\n`; + const artifact = Buffer.from(`${JSON.stringify(result, null, 2)}\n`, "utf8"); assert.throws( - () => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text, result.selected_profile), FIXTURE_BYTES), + () => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact, result.selected_profile), FIXTURE_BYTES), pattern, ); } From 7cdd95fc4b4aa6d7a9b4aedd9153f346988334bf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:10:16 +0900 Subject: [PATCH 078/269] test(perf): bind result acceptance to raw artifacts --- ...nt_separation_acceptance_contract.test.mjs | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 4c7a2c9bc..1f461f31d 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -48,13 +48,17 @@ function result() { }; } -function runtimeEvidence(resultText) { +function render(value) { + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + +function runtimeEvidence(resultArtifact) { return { schema_version: "orgmetra.employment_separation.runtime_evidence.v1", candidate_sha: "a".repeat(40), observed_service_sha: "a".repeat(40), selected_profile: "first_commit", - performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", @@ -79,13 +83,13 @@ function runtimeEvidence(resultText) { function evidencePair() { const performance = result(); - const text = `${JSON.stringify(performance, null, 2)}\n`; - return { performance, text, runtime: runtimeEvidence(text) }; + const artifact = render(performance); + return { performance, artifact, runtime: runtimeEvidence(artifact) }; } test("accepts an exact candidate result only with bound fixture, deployment, resource, and cleanup evidence", () => { - const { text, runtime } = evidencePair(); - assert.deepEqual(validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), { + const { artifact, runtime } = evidencePair(); + assert.deepEqual(validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), { accepted: true, candidate_sha: "a".repeat(40), selected_profile: "first_commit", @@ -96,23 +100,23 @@ test("accepts an exact candidate result only with bound fixture, deployment, res }); test("rejects a self-declared target when the observed service revision differs", () => { - const { text, runtime } = evidencePair(); + const { artifact, runtime } = evidencePair(); runtime.observed_service_sha = "b".repeat(40); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /observed_service_sha must match candidate_sha/); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), /observed_service_sha must match candidate_sha/); }); test("rejects a result artifact that is not the one observed by the runtime evidence", () => { - const { text, runtime } = evidencePair(); + const { artifact, runtime } = evidencePair(); runtime.performance_result_sha256 = "0".repeat(64); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /performance_result_sha256/); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), /performance_result_sha256/); }); test("rejects first-commit evidence above the commercial p95 target", () => { const { performance } = evidencePair(); performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(95)"] = 20.001; performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(99)"] = 21; - const text = `${JSON.stringify(performance, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text), FIXTURE_BYTES), /p95 must be <= 20 ms/); + const artifact = render(performance); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /p95 must be <= 20 ms/); }); test("rejects incomplete samples even when the completed subset is fast", () => { @@ -122,25 +126,24 @@ test("rejects incomplete samples even when the completed subset is fast", () => performance.k6.metrics.iterations.values.count = 999; performance.k6.metrics.employment_separation_latency_samples.values.count = 999; performance.k6.metrics.employment_separation_first_commit_duration_ms.values.count = 999; - const text = `${JSON.stringify(performance, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtimeEvidence(text), FIXTURE_BYTES), /sample must be complete/); + const artifact = render(performance); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /sample must be complete/); }); test("rejects acceptance when post-run cleanup finds a run-scoped leak", () => { - const { text, runtime } = evidencePair(); + const { artifact, runtime } = evidencePair(); runtime.residual_open_transactions = 1; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /residual_open_transactions must be 0/); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), /residual_open_transactions must be 0/); }); test("rejects missing CPU, memory, or pool observations instead of accepting latency alone", () => { - const { text, runtime } = evidencePair(); + const { artifact, runtime } = evidencePair(); runtime.db_pool_acquire_p95_ms = null; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime, FIXTURE_BYTES), /db_pool_acquire_p95_ms/); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), /db_pool_acquire_p95_ms/); }); test("rejects byte-distinct result artifacts that collide after lossy UTF-8 decoding", () => { - const text = `${JSON.stringify(result(), null, 2)}\n`; - const resultBytes = Buffer.from(text, "utf8"); + const resultBytes = render(result()); const malformedA = Buffer.concat([Buffer.from([0x80]), resultBytes]); const malformedB = Buffer.concat([Buffer.from([0x81]), resultBytes]); assert.equal(malformedA.toString("utf8"), malformedB.toString("utf8")); @@ -150,8 +153,7 @@ test("rejects byte-distinct result artifacts that collide after lossy UTF-8 deco ); for (const malformed of [malformedA, malformedB]) { - const runtime = runtimeEvidence(text); - runtime.performance_result_sha256 = createHash("sha256").update(malformed).digest("hex"); + const runtime = runtimeEvidence(malformed); assert.throws( () => validateEmploymentSeparationAcceptance(malformed, runtime, FIXTURE_BYTES), /valid UTF-8/, From 00bfeb4e76515d576a7b009c1ce1464e9d8f332c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:10:36 +0900 Subject: [PATCH 079/269] test(perf): preserve raw result bytes in fixture tests --- ...ration_acceptance_fixture_binding.test.mjs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs index 1f9ef09ca..66976abee 100644 --- a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs @@ -43,13 +43,13 @@ function performanceResult(fixtureSha256, { includeFixtureDigest = true } = {}) return value; } -function runtimeEvidence(resultText, fixtureSha256) { +function runtimeEvidence(resultArtifact, fixtureSha256) { return { schema_version: "orgmetra.employment_separation.runtime_evidence.v1", candidate_sha: ACCEPTANCE_CANDIDATE_SHA, observed_service_sha: ACCEPTANCE_CANDIDATE_SHA, selected_profile: "first_commit", - performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), fixture_sha256: fixtureSha256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", @@ -73,15 +73,15 @@ function runtimeEvidence(resultText, fixtureSha256) { } function render(value) { - return `${JSON.stringify(value, null, 2)}\n`; + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); } test("rejects acceptance without an exact fixture digest", () => { const fixtureBytes = acceptanceFixtureBytes(); const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); - const resultText = render(performanceResult(fixtureSha256, { includeFixtureDigest: false })); + const resultArtifact = render(performanceResult(fixtureSha256, { includeFixtureDigest: false })); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureBytes), + () => validateEmploymentSeparationAcceptance(resultArtifact, runtimeEvidence(resultArtifact, fixtureSha256), fixtureBytes), /fixture_sha256/, ); }); @@ -89,9 +89,9 @@ test("rejects acceptance without an exact fixture digest", () => { test("rejects runtime evidence bound to a different fixture digest", () => { const fixtureBytes = acceptanceFixtureBytes(); const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); - const resultText = render(performanceResult(fixtureSha256)); + const resultArtifact = render(performanceResult(fixtureSha256)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, "0".repeat(64)), fixtureBytes), + () => validateEmploymentSeparationAcceptance(resultArtifact, runtimeEvidence(resultArtifact, "0".repeat(64)), fixtureBytes), /fixture_sha256/, ); }); @@ -99,9 +99,9 @@ test("rejects runtime evidence bound to a different fixture digest", () => { test("rejects a fixture whose exact bytes are not right-cleared", () => { const fixtureBytes = acceptanceFixtureBytes({ rightCleared: false }); const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); - const resultText = render(performanceResult(fixtureSha256)); + const resultArtifact = render(performanceResult(fixtureSha256)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureBytes), + () => validateEmploymentSeparationAcceptance(resultArtifact, runtimeEvidence(resultArtifact, fixtureSha256), fixtureBytes), /right_cleared/, ); }); @@ -109,9 +109,9 @@ test("rejects a fixture whose exact bytes are not right-cleared", () => { test("rejects a fixture whose exact bytes are synthetic", () => { const fixtureBytes = acceptanceFixtureBytes({ synthetic: true }); const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); - const resultText = render(performanceResult(fixtureSha256)); + const resultArtifact = render(performanceResult(fixtureSha256)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), fixtureBytes), + () => validateEmploymentSeparationAcceptance(resultArtifact, runtimeEvidence(resultArtifact, fixtureSha256), fixtureBytes), /synthetic/, ); }); @@ -128,9 +128,9 @@ test("rejects byte-distinct fixture artifacts that collide after lossy UTF-8 dec for (const malformed of [malformedA, malformedB]) { const fixtureSha256 = createHash("sha256").update(malformed).digest("hex"); - const resultText = render(performanceResult(fixtureSha256)); + const resultArtifact = render(performanceResult(fixtureSha256)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText, fixtureSha256), malformed), + () => validateEmploymentSeparationAcceptance(resultArtifact, runtimeEvidence(resultArtifact, fixtureSha256), malformed), /valid UTF-8/, ); } From d5b1079a0d0544aab79726dde13d67a54150631d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:11:13 +0900 Subject: [PATCH 080/269] test(perf): enforce raw result artifact boundary --- ...oyment_separation_acceptance_edge.test.mjs | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index cdd66fe46..5ba1019b9 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -58,13 +58,13 @@ function result(profile = "first_commit") { }; } -function runtime(resultText, profile = "first_commit") { +function runtime(resultArtifact, profile = "first_commit") { return { schema_version: "orgmetra.employment_separation.runtime_evidence.v1", candidate_sha: "a".repeat(40), observed_service_sha: "a".repeat(40), selected_profile: profile, - performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", @@ -88,32 +88,33 @@ function runtime(resultText, profile = "first_commit") { } function render(value) { - return `${JSON.stringify(value, null, 2)}\n`; + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); } function rejectResult(mutate, pattern = /./, profile = "first_commit") { const value = result(profile); mutate(value); - const text = render(value); - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text, profile), FIXTURE_BYTES), pattern); + const artifact = render(value); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtime(artifact, profile), FIXTURE_BYTES), pattern); } function rejectRuntime(mutate, pattern = /./, profile = "first_commit") { const value = result(profile); - const text = render(value); - const evidence = runtime(text, profile); + const artifact = render(value); + const evidence = runtime(artifact, profile); mutate(evidence); - assert.throws(() => validateEmploymentSeparationAcceptance(text, evidence, FIXTURE_BYTES), pattern); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, evidence, FIXTURE_BYTES), pattern); } test("rejects malformed result and runtime containers", () => { - assert.throws(() => validateEmploymentSeparationAcceptance("", {}, FIXTURE_BYTES), /non-empty JSON text/); - assert.throws(() => validateEmploymentSeparationAcceptance(4, {}, FIXTURE_BYTES), /non-empty JSON text/); - assert.throws(() => validateEmploymentSeparationAcceptance("not json", {}, FIXTURE_BYTES), /valid JSON/); - assert.throws(() => validateEmploymentSeparationAcceptance("[]", {}, FIXTURE_BYTES), /result must be an object/); - const text = render(result()); - assert.throws(() => validateEmploymentSeparationAcceptance(text, [], FIXTURE_BYTES), /runtime must be an object/); - assert.throws(() => validateEmploymentSeparationAcceptance(text, null, FIXTURE_BYTES), /runtime must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance("", {}, FIXTURE_BYTES), /raw bytes/); + assert.throws(() => validateEmploymentSeparationAcceptance(4, {}, FIXTURE_BYTES), /raw bytes/); + assert.throws(() => validateEmploymentSeparationAcceptance(Buffer.alloc(0), {}, FIXTURE_BYTES), /non-empty JSON text/); + assert.throws(() => validateEmploymentSeparationAcceptance(Buffer.from("not json", "utf8"), {}, FIXTURE_BYTES), /valid JSON/); + assert.throws(() => validateEmploymentSeparationAcceptance(Buffer.from("[]", "utf8"), {}, FIXTURE_BYTES), /result must be an object/); + const artifact = render(result()); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, [], FIXTURE_BYTES), /runtime must be an object/); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, null, FIXTURE_BYTES), /runtime must be an object/); }); test("rejects invalid result authority and cardinality metadata", () => { @@ -182,8 +183,8 @@ test("rejects invalid or non-monotonic latency distributions", () => { test("accepts non-first profiles without applying the first-commit latency target", () => { for (const profile of ["replay", "rejection", "contention"]) { const value = result(profile); - const text = render(value); - const accepted = validateEmploymentSeparationAcceptance(text, runtime(text, profile), FIXTURE_BYTES); + const artifact = render(value); + const accepted = validateEmploymentSeparationAcceptance(artifact, runtime(artifact, profile), FIXTURE_BYTES); assert.equal(accepted.selected_profile, profile); assert.equal(accepted.p95_ms, 80); } From a0bb35fc737f4fd84ec08ffe5d30ec8d3d226b41 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:12:14 +0900 Subject: [PATCH 081/269] test(perf): preserve result bytes in latency acceptance --- ...ration_acceptance_latency_samples.test.mjs | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs index 6423cfeb8..0c0969015 100644 --- a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -49,13 +49,17 @@ function performanceResult(latencySamples = 1000, trendSamples = latencySamples) }; } -function runtimeEvidence(resultText) { +function render(value) { + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + +function runtimeEvidence(resultArtifact) { return { schema_version: "orgmetra.employment_separation.runtime_evidence.v1", candidate_sha: candidateSha, observed_service_sha: candidateSha, selected_profile: "first_commit", - performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", @@ -79,27 +83,24 @@ function runtimeEvidence(resultText) { } test("rejects a complete iteration count with an incomplete latency counter", () => { - const value = performanceResult(999, 1000); - const resultText = `${JSON.stringify(value, null, 2)}\n`; + const artifact = render(performanceResult(999, 1000)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_BYTES), + () => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /latency sample count/, ); }); test("rejects a complete counter when the measured Trend itself is truncated", () => { - const value = performanceResult(1000, 999); - const resultText = `${JSON.stringify(value, null, 2)}\n`; + const artifact = render(performanceResult(1000, 999)); assert.throws( - () => validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_BYTES), + () => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /Trend sample count/, ); }); test("accepts latency evidence only when every expected request contributed to the measured Trend", () => { - const value = performanceResult(1000, 1000); - const resultText = `${JSON.stringify(value, null, 2)}\n`; - const accepted = validateEmploymentSeparationAcceptance(resultText, runtimeEvidence(resultText), FIXTURE_BYTES); + const artifact = render(performanceResult(1000, 1000)); + const accepted = validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES); assert.equal(accepted.accepted, true); assert.equal(accepted.p95_ms, 18); }); From d9b85d14056bfcbbb5d5cb6732fb31b4bec6d03f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 14:12:27 +0900 Subject: [PATCH 082/269] test(perf): preserve result bytes in provenance acceptance --- ...loyment_separation_acceptance_provenance.test.mjs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index a6df8dd45..534717d8d 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -49,13 +49,17 @@ function result() { }; } -function runtime(resultText) { +function render(value) { + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + +function runtime(resultArtifact) { return { schema_version: "orgmetra.employment_separation.runtime_evidence.v1", candidate_sha: "a".repeat(40), observed_service_sha: "a".repeat(40), selected_profile: "first_commit", - performance_result_sha256: createHash("sha256").update(resultText, "utf8").digest("hex"), + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), fixture_sha256: FIXTURE_SHA256, environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", @@ -81,8 +85,8 @@ function runtime(resultText) { function reject(mutate, pattern) { const value = result(); mutate(value); - const text = `${JSON.stringify(value, null, 2)}\n`; - assert.throws(() => validateEmploymentSeparationAcceptance(text, runtime(text), FIXTURE_BYTES), pattern); + const artifact = render(value); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtime(artifact), FIXTURE_BYTES), pattern); } test("requires right-cleared dataset and preparation provenance references", () => { From c71a52f12d17cc2db5d8c8a0a1c43b691f981387 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 15:03:18 +0900 Subject: [PATCH 083/269] test(perf): define buyer-path elapsed timing contract --- .../employment_separation_timing_contract.mjs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/performance/employment_separation_timing_contract.mjs diff --git a/tests/performance/employment_separation_timing_contract.mjs b/tests/performance/employment_separation_timing_contract.mjs new file mode 100644 index 000000000..b799e9025 --- /dev/null +++ b/tests/performance/employment_separation_timing_contract.mjs @@ -0,0 +1,24 @@ +function fail(message) { + throw new Error(message); +} + +function finiteNonNegative(value, label) { + if (typeof value !== "number" || !Number.isFinite(value) || value < 0) { + fail(`${label} must be a finite non-negative number`); + } + return value; +} + +export function buyerPathElapsedMs(timings) { + if (timings === null || typeof timings !== "object" || Array.isArray(timings)) { + fail("response.timings must be an object"); + } + + const blocked = finiteNonNegative(timings.blocked, "response.timings.blocked"); + const duration = finiteNonNegative(timings.duration, "response.timings.duration"); + + // k6 http_req_duration excludes connection acquisition. `blocked + duration` + // preserves the observed client-side request elapsed time without separately + // adding connecting/TLS phases that can already be contained in `blocked`. + return blocked + duration; +} From a3099f6c8d9678d9dcc887350e93ed8e944af86c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 15:03:28 +0900 Subject: [PATCH 084/269] test(perf): cover transport-inclusive buyer latency --- ...oyment_separation_timing_contract.test.mjs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/performance/employment_separation_timing_contract.test.mjs diff --git a/tests/performance/employment_separation_timing_contract.test.mjs b/tests/performance/employment_separation_timing_contract.test.mjs new file mode 100644 index 000000000..e1f1b2a86 --- /dev/null +++ b/tests/performance/employment_separation_timing_contract.test.mjs @@ -0,0 +1,35 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { buyerPathElapsedMs } from "./employment_separation_timing_contract.mjs"; + +test("includes connection acquisition in the buyer-path elapsed time", () => { + assert.equal(buyerPathElapsedMs({ blocked: 6.5, duration: 14.5 }), 21); +}); + +test("does not double count connecting or TLS fields already represented by blocked", () => { + assert.equal(buyerPathElapsedMs({ + blocked: 6, + connecting: 2, + tls_handshaking: 3, + duration: 10, + }), 16); +}); + +test("preserves keep-alive requests whose blocked phase is effectively zero", () => { + assert.equal(buyerPathElapsedMs({ blocked: 0.4, duration: 9.6 }), 10); +}); + +test("rejects missing, negative, or non-finite timing evidence", () => { + for (const timings of [ + null, + [], + {}, + { blocked: -1, duration: 10 }, + { blocked: 1, duration: -1 }, + { blocked: Number.NaN, duration: 10 }, + { blocked: 1, duration: Number.POSITIVE_INFINITY }, + ]) { + assert.throws(() => buyerPathElapsedMs(timings), /timings|finite non-negative/); + } +}); From d03c8f4ad2d8697f362713ba8819c8ae9217aef8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 15:03:55 +0900 Subject: [PATCH 085/269] fix(perf): include connection acquisition in buyer latency --- tests/performance/employment_separation_buyer_path.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 3148ec106..422f09735 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -18,6 +18,7 @@ import { requirePerformanceProfile, thresholdsForPerformanceProfile, } from "./employment_separation_run_contract.mjs"; +import { buyerPathElapsedMs } from "./employment_separation_timing_contract.mjs"; const ROUTE = "/v1/employment-separations"; const MINIMUM_NON_CONTENDING_RECORDS = 1000; @@ -145,7 +146,7 @@ function post(command, profile) { } function observe(response, trend, profile, predicate) { - trend.add(response.timings.duration, { profile }); + trend.add(buyerPathElapsedMs(response.timings), { profile }); latencySamples.add(1, { profile }); const passed = check(response, { [`${profile} returned the governed result`]: predicate, @@ -189,7 +190,7 @@ export function contention() { ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.right), { headers: requestHeaders(pair.right, bearerToken), tags: { profile: "contention" } }], ]); for (const response of responses) { - contentionDuration.add(response.timings.duration, { profile: "contention" }); + contentionDuration.add(buyerPathElapsedMs(response.timings), { profile: "contention" }); latencySamples.add(1, { profile: "contention" }); } const parsed = responses.map((response) => ({ status: response.status, body: parseJson(response) })); From d3b7ba75fe8e7e55bf8790c0e102c87a3464ff9d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:02:47 +0900 Subject: [PATCH 086/269] test(perf): require open-model arrival schedule --- .../employment_separation_run_contract.mjs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index 095006642..4835a5579 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -13,6 +13,13 @@ export const PERFORMANCE_SUMMARY_TREND_STATS = Object.freeze([ "count", ]); +const EXEC_BY_PROFILE = Object.freeze({ + first_commit: "firstCommit", + replay: "replay", + rejection: "rejection", + contention: "contention", +}); + export function requirePerformanceProfile(value) { if (typeof value !== "string" || !PERFORMANCE_PROFILES.includes(value)) { throw new Error(`ORGMETRA_PERFORMANCE_PROFILE must be exactly one of: ${PERFORMANCE_PROFILES.join(", ")}`); @@ -20,6 +27,45 @@ export function requirePerformanceProfile(value) { return value; } +function positiveInteger(value, label) { + if (!Number.isSafeInteger(value) || value < 1) { + throw new Error(`${label} must be a positive safe integer`); + } + return value; +} + +export function arrivalRateScenarioForPerformanceProfile(profile, { + expectedIterations, + targetRps, + durationSeconds, + preAllocatedVUs, + maxVUs, +}) { + requirePerformanceProfile(profile); + const iterations = positiveInteger(expectedIterations, "expectedIterations"); + const rate = positiveInteger(targetRps, "targetRps"); + const duration = positiveInteger(durationSeconds, "durationSeconds"); + const preAllocated = positiveInteger(preAllocatedVUs, "preAllocatedVUs"); + const maximum = positiveInteger(maxVUs, "maxVUs"); + if (maximum < preAllocated) { + throw new Error("maxVUs must be greater than or equal to preAllocatedVUs"); + } + const scheduledIterations = rate * duration; + if (!Number.isSafeInteger(scheduledIterations) || scheduledIterations !== iterations) { + throw new Error("targetRps * durationSeconds must equal the selected fixture iteration count exactly"); + } + return { + executor: "constant-arrival-rate", + exec: EXEC_BY_PROFILE[profile], + rate, + timeUnit: "1s", + duration: `${duration}s`, + preAllocatedVUs: preAllocated, + maxVUs: maximum, + gracefulStop: "30s", + }; +} + export function thresholdsForPerformanceProfile(profile, expectedIterations) { requirePerformanceProfile(profile); if (!Number.isSafeInteger(expectedIterations) || expectedIterations < 1) { @@ -33,6 +79,7 @@ export function thresholdsForPerformanceProfile(profile, expectedIterations) { employment_separation_unexpected_response: ["rate==0"], employment_separation_latency_samples: [`count>=${expectedLatencySamples}`], checks: ["rate==1"], + dropped_iterations: ["count==0"], iterations: [`count>=${expectedIterations}`], }; if (profile === "first_commit") { From 583921f0a4563cbf0ff6ce4a32af653c35c1872f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:02:57 +0900 Subject: [PATCH 087/269] test(perf): cover open arrival-rate contract --- ...mployment_separation_run_contract.test.mjs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 1bf1b6e4d..0e56b3162 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -3,6 +3,7 @@ import test from "node:test"; import { PERFORMANCE_SUMMARY_TREND_STATS, + arrivalRateScenarioForPerformanceProfile, requirePerformanceProfile, thresholdsForPerformanceProfile, } from "./employment_separation_run_contract.mjs"; @@ -15,11 +16,48 @@ test("requires one explicit performance profile per run", () => { assert.throws(() => requirePerformanceProfile("all"), /must be exactly one of/); }); +test("uses an open arrival-rate model whose schedule is independent of response time", () => { + assert.deepEqual(arrivalRateScenarioForPerformanceProfile("first_commit", { + expectedIterations: 1000, + targetRps: 20, + durationSeconds: 50, + preAllocatedVUs: 20, + maxVUs: 80, + }), { + executor: "constant-arrival-rate", + exec: "firstCommit", + rate: 20, + timeUnit: "1s", + duration: "50s", + preAllocatedVUs: 20, + maxVUs: 80, + gracefulStop: "30s", + }); +}); + +test("refuses arrival schedules that can hide load or outrun fixture cardinality", () => { + assert.throws(() => arrivalRateScenarioForPerformanceProfile("first_commit", { + expectedIterations: 1000, + targetRps: 20, + durationSeconds: 49, + preAllocatedVUs: 20, + maxVUs: 80, + }), /must equal the selected fixture iteration count exactly/); + assert.throws(() => arrivalRateScenarioForPerformanceProfile("contention", { + expectedIterations: 100, + targetRps: 10, + durationSeconds: 10, + preAllocatedVUs: 20, + maxVUs: 10, + }), /greater than or equal/); +}); + test("applies the commercial p95 threshold only to the ordinary first-commit profile", () => { assert.deepEqual(thresholdsForPerformanceProfile("first_commit", 1000), { employment_separation_unexpected_response: ["rate==0"], employment_separation_latency_samples: ["count>=1000"], checks: ["rate==1"], + dropped_iterations: ["count==0"], iterations: ["count>=1000"], employment_separation_first_commit_duration_ms: ["p(95)<=20"], }); @@ -27,6 +65,7 @@ test("applies the commercial p95 threshold only to the ordinary first-commit pro employment_separation_unexpected_response: ["rate==0"], employment_separation_latency_samples: ["count>=200"], checks: ["rate==1"], + dropped_iterations: ["count==0"], iterations: ["count>=100"], }); }); From 57c7b4ae4a4c166e33d0b7bd6942091cebdf0847 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:03:35 +0900 Subject: [PATCH 088/269] fix(perf): eliminate closed-model coordinated omission --- .../employment_separation_buyer_path.js | 72 +++++++------------ 1 file changed, 26 insertions(+), 46 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 422f09735..de02fb888 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -15,6 +15,7 @@ import { } from "./employment_separation_response_contract.mjs"; import { PERFORMANCE_SUMMARY_TREND_STATS, + arrivalRateScenarioForPerformanceProfile, requirePerformanceProfile, thresholdsForPerformanceProfile, } from "./employment_separation_run_contract.mjs"; @@ -56,23 +57,30 @@ if (fixture.candidate_sha.toLowerCase() !== targetSha) { fail("performance fixture candidate_sha does not match ORGMETRA_PERFORMANCE_TARGET_SHA"); } -function integerSetting(name, fallback, maximum) { +function requiredPositiveIntegerSetting(name) { const raw = __ENV[name]; - if (raw === undefined || raw === "") return Math.min(fallback, maximum); - if (!/^\d+$/.test(raw)) fail(`${name} must be a positive integer`); + if (raw === undefined || raw === "" || !/^\d+$/.test(raw)) { + fail(`${name} must be an explicit positive integer`); + } const value = Number(raw); - if (!Number.isSafeInteger(value) || value < 1 || value > maximum) { - fail(`${name} must be between 1 and ${maximum}`); + if (!Number.isSafeInteger(value) || value < 1) { + fail(`${name} must be an explicit positive safe integer`); } return value; } const selectedRecords = fixture.profiles[selectedProfile]; -const selectedVus = integerSetting( - selectedProfile === "contention" ? "ORGMETRA_PERFORMANCE_CONTENTION_VUS" : "ORGMETRA_PERFORMANCE_VUS", - selectedProfile === "contention" ? 10 : 20, - selectedRecords.length, -); +const targetRps = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_TARGET_RPS"); +const durationSeconds = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_DURATION_SECONDS"); +const preAllocatedVUs = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_PREALLOCATED_VUS"); +const maxVUs = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_MAX_VUS"); +const selectedScenario = arrivalRateScenarioForPerformanceProfile(selectedProfile, { + expectedIterations: selectedRecords.length, + targetRps, + durationSeconds, + preAllocatedVUs, + maxVUs, +}); const firstCommitDuration = new Trend("employment_separation_first_commit_duration_ms", true); const replayDuration = new Trend("employment_separation_replay_duration_ms", true); @@ -81,44 +89,9 @@ const contentionDuration = new Trend("employment_separation_contention_duration_ const latencySamples = new Counter("employment_separation_latency_samples"); const unexpectedResponse = new Rate("employment_separation_unexpected_response"); -const scenarioByProfile = { - first_commit: { - executor: "shared-iterations", - exec: "firstCommit", - iterations: fixture.profiles.first_commit.length, - vus: selectedVus, - maxDuration: "30m", - gracefulStop: "0s", - }, - replay: { - executor: "shared-iterations", - exec: "replay", - iterations: fixture.profiles.replay.length, - vus: selectedVus, - maxDuration: "30m", - gracefulStop: "0s", - }, - rejection: { - executor: "shared-iterations", - exec: "rejection", - iterations: fixture.profiles.rejection.length, - vus: selectedVus, - maxDuration: "30m", - gracefulStop: "0s", - }, - contention: { - executor: "shared-iterations", - exec: "contention", - iterations: fixture.profiles.contention.length, - vus: selectedVus, - maxDuration: "30m", - gracefulStop: "0s", - }, -}; - export const options = { discardResponseBodies: false, - scenarios: { [selectedProfile]: scenarioByProfile[selectedProfile] }, + scenarios: { [selectedProfile]: selectedScenario }, thresholds: thresholdsForPerformanceProfile(selectedProfile, selectedRecords.length), summaryTrendStats: PERFORMANCE_SUMMARY_TREND_STATS, }; @@ -218,6 +191,13 @@ export function handleSummary(data) { completed_iterations: completedIterations, sample_complete: completedIterations === selectedRecords.length, completed_at: new Date().toISOString(), + load_model: { + executor: selectedScenario.executor, + target_rps: targetRps, + duration_seconds: durationSeconds, + preallocated_vus: preAllocatedVUs, + max_vus: maxVUs, + }, dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, preparation_protocol_reference: fixture.preparation_protocol_reference, From 9c2c60f319be021d63a9b3552d089a1905b06685 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:07:40 +0900 Subject: [PATCH 089/269] fix(perf): include connection phases in buyer latency --- .../employment_separation_timing_contract.mjs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_timing_contract.mjs b/tests/performance/employment_separation_timing_contract.mjs index b799e9025..f276e6297 100644 --- a/tests/performance/employment_separation_timing_contract.mjs +++ b/tests/performance/employment_separation_timing_contract.mjs @@ -15,10 +15,14 @@ export function buyerPathElapsedMs(timings) { } const blocked = finiteNonNegative(timings.blocked, "response.timings.blocked"); + const connecting = finiteNonNegative(timings.connecting, "response.timings.connecting"); + const tlsHandshaking = finiteNonNegative(timings.tls_handshaking, "response.timings.tls_handshaking"); const duration = finiteNonNegative(timings.duration, "response.timings.duration"); - // k6 http_req_duration excludes connection acquisition. `blocked + duration` - // preserves the observed client-side request elapsed time without separately - // adding connecting/TLS phases that can already be contained in `blocked`. - return blocked + duration; + // k6 documents duration as sending + waiting + receiving. TCP setup and TLS + // negotiation are separate phases, while blocked also carries pre-request wait + // such as connection-slot/DNS work. Final commercial acceptance disallows a + // client-side HTTPS MITM proxy because k6 can overlap these phases in the + // unusual double-TLS topology documented upstream. + return blocked + connecting + tlsHandshaking + duration; } From 137f04ff69152fb5354afe3d883ddcec68b324b7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:07:47 +0900 Subject: [PATCH 090/269] test(perf): cover full HTTP phase timing --- ...oyment_separation_timing_contract.test.mjs | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/tests/performance/employment_separation_timing_contract.test.mjs b/tests/performance/employment_separation_timing_contract.test.mjs index e1f1b2a86..2f655c18b 100644 --- a/tests/performance/employment_separation_timing_contract.test.mjs +++ b/tests/performance/employment_separation_timing_contract.test.mjs @@ -3,21 +3,31 @@ import test from "node:test"; import { buyerPathElapsedMs } from "./employment_separation_timing_contract.mjs"; -test("includes connection acquisition in the buyer-path elapsed time", () => { - assert.equal(buyerPathElapsedMs({ blocked: 6.5, duration: 14.5 }), 21); +test("includes blocked, TCP, TLS, and request phases in buyer-path elapsed time", () => { + assert.equal(buyerPathElapsedMs({ + blocked: 1.5, + connecting: 2.5, + tls_handshaking: 3, + duration: 14, + }), 21); }); -test("does not double count connecting or TLS fields already represented by blocked", () => { +test("preserves keep-alive requests when connection phases are zero", () => { assert.equal(buyerPathElapsedMs({ - blocked: 6, - connecting: 2, - tls_handshaking: 3, - duration: 10, - }), 16); + blocked: 0.4, + connecting: 0, + tls_handshaking: 0, + duration: 9.6, + }), 10); }); -test("preserves keep-alive requests whose blocked phase is effectively zero", () => { - assert.equal(buyerPathElapsedMs({ blocked: 0.4, duration: 9.6 }), 10); +test("does not drop TCP or TLS latency from a cold request", () => { + assert.equal(buyerPathElapsedMs({ + blocked: 1, + connecting: 4, + tls_handshaking: 5, + duration: 10, + }), 20); }); test("rejects missing, negative, or non-finite timing evidence", () => { @@ -25,10 +35,13 @@ test("rejects missing, negative, or non-finite timing evidence", () => { null, [], {}, - { blocked: -1, duration: 10 }, - { blocked: 1, duration: -1 }, - { blocked: Number.NaN, duration: 10 }, - { blocked: 1, duration: Number.POSITIVE_INFINITY }, + { blocked: 1, connecting: 2, tls_handshaking: 3 }, + { blocked: -1, connecting: 2, tls_handshaking: 3, duration: 10 }, + { blocked: 1, connecting: -1, tls_handshaking: 3, duration: 10 }, + { blocked: 1, connecting: 2, tls_handshaking: -1, duration: 10 }, + { blocked: 1, connecting: 2, tls_handshaking: 3, duration: -1 }, + { blocked: Number.NaN, connecting: 2, tls_handshaking: 3, duration: 10 }, + { blocked: 1, connecting: 2, tls_handshaking: 3, duration: Number.POSITIVE_INFINITY }, ]) { assert.throws(() => buyerPathElapsedMs(timings), /timings|finite non-negative/); } From d31b96f9c88b84648d652e2d82f93c4307f3bb60 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:08:17 +0900 Subject: [PATCH 091/269] fix(perf): bind open-load and direct-network evidence --- .../employment_separation_run_contract.mjs | 97 +++++++++++++++---- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index 4835a5579..bf7b78b8c 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -13,12 +13,22 @@ export const PERFORMANCE_SUMMARY_TREND_STATS = Object.freeze([ "count", ]); +export const PERFORMANCE_CLIENT_NETWORK_TOPOLOGY = "direct_no_client_mitm_proxy"; + const EXEC_BY_PROFILE = Object.freeze({ first_commit: "firstCommit", replay: "replay", rejection: "rejection", contention: "contention", }); +const PROXY_ENVIRONMENT_KEYS = Object.freeze([ + "HTTP_PROXY", + "HTTPS_PROXY", + "ALL_PROXY", + "http_proxy", + "https_proxy", + "all_proxy", +]); export function requirePerformanceProfile(value) { if (typeof value !== "string" || !PERFORMANCE_PROFILES.includes(value)) { @@ -34,6 +44,63 @@ function positiveInteger(value, label) { return value; } +export function requireDirectPerformanceClientNetwork(environment) { + if (environment === null || typeof environment !== "object" || Array.isArray(environment)) { + throw new Error("performance client environment must be an object"); + } + const configuredProxy = PROXY_ENVIRONMENT_KEYS.find((key) => ( + typeof environment[key] === "string" && environment[key].trim() !== "" + )); + if (configuredProxy) { + throw new Error(`${configuredProxy} must be unset for commercial timing acceptance`); + } + return PERFORMANCE_CLIENT_NETWORK_TOPOLOGY; +} + +export function validatePerformanceLoadModel(value, expectedIterations) { + if (value === null || typeof value !== "object" || Array.isArray(value)) { + throw new Error("load_model must be an object"); + } + const expectedKeys = [ + "executor", + "target_rps", + "duration_seconds", + "preallocated_vus", + "max_vus", + "client_network_topology", + ].sort(); + const actualKeys = Object.keys(value).sort(); + if (actualKeys.length !== expectedKeys.length || actualKeys.some((key, index) => key !== expectedKeys[index])) { + throw new Error(`load_model must contain exactly ${expectedKeys.join(", ")}`); + } + if (value.executor !== "constant-arrival-rate") { + throw new Error("load_model.executor must be constant-arrival-rate"); + } + if (value.client_network_topology !== PERFORMANCE_CLIENT_NETWORK_TOPOLOGY) { + throw new Error(`load_model.client_network_topology must be ${PERFORMANCE_CLIENT_NETWORK_TOPOLOGY}`); + } + const iterations = positiveInteger(expectedIterations, "expectedIterations"); + const rate = positiveInteger(value.target_rps, "load_model.target_rps"); + const duration = positiveInteger(value.duration_seconds, "load_model.duration_seconds"); + const preAllocated = positiveInteger(value.preallocated_vus, "load_model.preallocated_vus"); + const maximum = positiveInteger(value.max_vus, "load_model.max_vus"); + if (maximum < preAllocated) { + throw new Error("load_model.max_vus must be greater than or equal to load_model.preallocated_vus"); + } + const scheduledIterations = rate * duration; + if (!Number.isSafeInteger(scheduledIterations) || scheduledIterations !== iterations) { + throw new Error("load_model target_rps * duration_seconds must equal expectedIterations exactly"); + } + return Object.freeze({ + executor: value.executor, + target_rps: rate, + duration_seconds: duration, + preallocated_vus: preAllocated, + max_vus: maximum, + client_network_topology: value.client_network_topology, + }); +} + export function arrivalRateScenarioForPerformanceProfile(profile, { expectedIterations, targetRps, @@ -42,26 +109,22 @@ export function arrivalRateScenarioForPerformanceProfile(profile, { maxVUs, }) { requirePerformanceProfile(profile); - const iterations = positiveInteger(expectedIterations, "expectedIterations"); - const rate = positiveInteger(targetRps, "targetRps"); - const duration = positiveInteger(durationSeconds, "durationSeconds"); - const preAllocated = positiveInteger(preAllocatedVUs, "preAllocatedVUs"); - const maximum = positiveInteger(maxVUs, "maxVUs"); - if (maximum < preAllocated) { - throw new Error("maxVUs must be greater than or equal to preAllocatedVUs"); - } - const scheduledIterations = rate * duration; - if (!Number.isSafeInteger(scheduledIterations) || scheduledIterations !== iterations) { - throw new Error("targetRps * durationSeconds must equal the selected fixture iteration count exactly"); - } - return { + const loadModel = validatePerformanceLoadModel({ executor: "constant-arrival-rate", + target_rps: targetRps, + duration_seconds: durationSeconds, + preallocated_vus: preAllocatedVUs, + max_vus: maxVUs, + client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + }, expectedIterations); + return { + executor: loadModel.executor, exec: EXEC_BY_PROFILE[profile], - rate, + rate: loadModel.target_rps, timeUnit: "1s", - duration: `${duration}s`, - preAllocatedVUs: preAllocated, - maxVUs: maximum, + duration: `${loadModel.duration_seconds}s`, + preAllocatedVUs: loadModel.preallocated_vus, + maxVUs: loadModel.max_vus, gracefulStop: "30s", }; } From 6bc5490da009faf81bd8811886cf6078f33b24f8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:08:35 +0900 Subject: [PATCH 092/269] test(perf): cover load and network evidence binding --- ...mployment_separation_run_contract.test.mjs | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 0e56b3162..9862cfc52 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -2,10 +2,13 @@ import assert from "node:assert/strict"; import test from "node:test"; import { + PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, PERFORMANCE_SUMMARY_TREND_STATS, arrivalRateScenarioForPerformanceProfile, + requireDirectPerformanceClientNetwork, requirePerformanceProfile, thresholdsForPerformanceProfile, + validatePerformanceLoadModel, } from "./employment_separation_run_contract.mjs"; test("requires one explicit performance profile per run", () => { @@ -42,7 +45,7 @@ test("refuses arrival schedules that can hide load or outrun fixture cardinality durationSeconds: 49, preAllocatedVUs: 20, maxVUs: 80, - }), /must equal the selected fixture iteration count exactly/); + }), /must equal expectedIterations exactly/); assert.throws(() => arrivalRateScenarioForPerformanceProfile("contention", { expectedIterations: 100, targetRps: 10, @@ -52,6 +55,44 @@ test("refuses arrival schedules that can hide load or outrun fixture cardinality }), /greater than or equal/); }); +test("binds result evidence to the exact open load model", () => { + assert.deepEqual(validatePerformanceLoadModel({ + executor: "constant-arrival-rate", + target_rps: 20, + duration_seconds: 50, + preallocated_vus: 20, + max_vus: 80, + client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + }, 1000), { + executor: "constant-arrival-rate", + target_rps: 20, + duration_seconds: 50, + preallocated_vus: 20, + max_vus: 80, + client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + }); + assert.throws(() => validatePerformanceLoadModel({ + executor: "shared-iterations", + target_rps: 20, + duration_seconds: 50, + preallocated_vus: 20, + max_vus: 80, + client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + }, 1000), /constant-arrival-rate/); +}); + +test("fails closed when the k6 client is routed through an ambient proxy", () => { + assert.equal(requireDirectPerformanceClientNetwork({}), PERFORMANCE_CLIENT_NETWORK_TOPOLOGY); + assert.throws( + () => requireDirectPerformanceClientNetwork({ HTTPS_PROXY: "https://proxy.example" }), + /HTTPS_PROXY must be unset/, + ); + assert.throws( + () => requireDirectPerformanceClientNetwork({ all_proxy: "socks5://proxy.example" }), + /all_proxy must be unset/, + ); +}); + test("applies the commercial p95 threshold only to the ordinary first-commit profile", () => { assert.deepEqual(thresholdsForPerformanceProfile("first_commit", 1000), { employment_separation_unexpected_response: ["rate==0"], From ed42459f480de194b073e25a2df4cd51a5e53121 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:08:56 +0900 Subject: [PATCH 093/269] fix(perf): reject proxy timing ambiguity --- tests/performance/employment_separation_buyer_path.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index de02fb888..b41a750cc 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -16,6 +16,7 @@ import { import { PERFORMANCE_SUMMARY_TREND_STATS, arrivalRateScenarioForPerformanceProfile, + requireDirectPerformanceClientNetwork, requirePerformanceProfile, thresholdsForPerformanceProfile, } from "./employment_separation_run_contract.mjs"; @@ -29,6 +30,7 @@ const baseUrl = (__ENV.ORGMETRA_PERFORMANCE_BASE_URL || "").replace(/\/$/, ""); const bearerToken = __ENV.ORGMETRA_PERFORMANCE_BEARER_TOKEN || ""; const targetSha = (__ENV.ORGMETRA_PERFORMANCE_TARGET_SHA || "").toLowerCase(); const selectedProfile = requirePerformanceProfile(__ENV.ORGMETRA_PERFORMANCE_PROFILE || ""); +const clientNetworkTopology = requireDirectPerformanceClientNetwork(__ENV); if (!fixturePath) fail("ORGMETRA_PERFORMANCE_DATA_FILE is required"); if (!baseUrl) fail("ORGMETRA_PERFORMANCE_BASE_URL is required"); @@ -197,6 +199,7 @@ export function handleSummary(data) { duration_seconds: durationSeconds, preallocated_vus: preAllocatedVUs, max_vus: maxVUs, + client_network_topology: clientNetworkTopology, }, dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, From e8f527229b0dc378995af4263ace85913497e567 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:09:37 +0900 Subject: [PATCH 094/269] fix(perf): verify open-load result evidence --- .../employment_separation_acceptance_contract.mjs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 31987338a..41aaaea36 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -2,6 +2,7 @@ import { createHash } from "node:crypto"; import { TextDecoder } from "node:util"; import { validatePerformanceFixture } from "./employment_separation_fixture_contract.mjs"; +import { validatePerformanceLoadModel } from "./employment_separation_run_contract.mjs"; const RESULT_SCHEMA = "orgmetra.employment_separation.performance_result.v1"; const RUNTIME_SCHEMA = "orgmetra.employment_separation.runtime_evidence.v1"; @@ -177,6 +178,7 @@ function validateResult(result) { if (expectedIterations < minimumIterations) { fail(`${profile} requires at least ${minimumIterations} iterations`); } + validatePerformanceLoadModel(result.load_model, expectedIterations); const completedIterations = nonNegativeInteger(result.completed_iterations, "result.completed_iterations"); if (result.sample_complete !== true || completedIterations !== expectedIterations) { fail("result sample must be complete"); @@ -186,6 +188,12 @@ function validateResult(result) { const iterationValues = metricValues(result, "iterations"); const metricIterations = nonNegativeInteger(iterationValues.count, "result.k6.metrics.iterations.values.count"); if (metricIterations !== expectedIterations) fail("k6 iteration count must equal expected_iterations"); + const droppedValues = metricValues(result, "dropped_iterations"); + const droppedIterations = nonNegativeInteger( + droppedValues.count, + "result.k6.metrics.dropped_iterations.values.count", + ); + if (droppedIterations !== 0) fail("k6 dropped_iterations count must equal 0"); const expectedLatencySamples = profile === "contention" ? expectedIterations * 2 : expectedIterations; if (!Number.isSafeInteger(expectedLatencySamples)) fail("expected latency sample count must be a safe integer"); From dff7b3eeec30eddbe2d0464eeaf4ab554d3e67c8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:10:28 +0900 Subject: [PATCH 095/269] test(perf): centralize acceptance load evidence --- ...t_separation_acceptance_fixture_test_support.mjs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_fixture_test_support.mjs b/tests/performance/employment_separation_acceptance_fixture_test_support.mjs index df4d1904b..288b829fe 100644 --- a/tests/performance/employment_separation_acceptance_fixture_test_support.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_test_support.mjs @@ -1,5 +1,7 @@ import { createHash } from "node:crypto"; +import { PERFORMANCE_CLIENT_NETWORK_TOPOLOGY } from "./employment_separation_run_contract.mjs"; + export const ACCEPTANCE_CANDIDATE_SHA = "a".repeat(40); export const ACCEPTANCE_PROFILE_PRECONDITIONS = Object.freeze({ first_commit: "active_current_expected_version", @@ -35,6 +37,17 @@ function records(start, count) { return Array.from({ length: count }, (_, offset) => command(start + offset)); } +export function acceptanceLoadModel(expectedIterations) { + return { + executor: "constant-arrival-rate", + target_rps: 1, + duration_seconds: expectedIterations, + preallocated_vus: 1, + max_vus: 1, + client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + }; +} + export function acceptanceFixture({ rightCleared = true, synthetic = false } = {}) { const contentionStart = 4000; return { From d92d1df76281abdd94cdfa907e1425974ab8c468 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:10:51 +0900 Subject: [PATCH 096/269] test(perf): reject closed or dropped load evidence --- ...ment_separation_acceptance_contract.test.mjs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 1f461f31d..82f6313d3 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -6,6 +6,7 @@ import { validateEmploymentSeparationAcceptance } from "./employment_separation_ import { acceptanceFixtureBytes, acceptanceFixtureSha256, + acceptanceLoadModel, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const FIXTURE_BYTES = acceptanceFixtureBytes(); @@ -21,6 +22,7 @@ function result() { completed_iterations: 1000, sample_complete: true, completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(1000), dataset_id: "dataset:employment-separation-perf-1", clearance_reference: "data_clearance:perf-2026-09", preparation_protocol_reference: "protocol:employment-separation-perf-v1", @@ -37,6 +39,7 @@ function result() { k6: { metrics: { iterations: { values: { count: 1000, rate: 40 } }, + dropped_iterations: { values: { count: 0, rate: 0 } }, checks: { values: { rate: 1, passes: 1000, fails: 0 } }, employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, employment_separation_latency_samples: { values: { count: 1000, rate: 40 } }, @@ -87,7 +90,7 @@ function evidencePair() { return { performance, artifact, runtime: runtimeEvidence(artifact) }; } -test("accepts an exact candidate result only with bound fixture, deployment, resource, and cleanup evidence", () => { +test("accepts an exact candidate result only with bound fixture, deployment, resource, load, and cleanup evidence", () => { const { artifact, runtime } = evidencePair(); assert.deepEqual(validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), { accepted: true, @@ -119,6 +122,18 @@ test("rejects first-commit evidence above the commercial p95 target", () => { assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /p95 must be <= 20 ms/); }); +test("rejects closed or incomplete offered-load evidence", () => { + const { performance } = evidencePair(); + performance.load_model.executor = "shared-iterations"; + let artifact = render(performance); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /constant-arrival-rate/); + + const dropped = result(); + dropped.k6.metrics.dropped_iterations.values.count = 1; + artifact = render(dropped); + assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /dropped_iterations count must equal 0/); +}); + test("rejects incomplete samples even when the completed subset is fast", () => { const { performance } = evidencePair(); performance.completed_iterations = 999; From fc7de361fc6c412907f5035732354af291086f02 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:11:06 +0900 Subject: [PATCH 097/269] test(perf): bind cardinality cases to open load model --- .../employment_separation_acceptance_cardinality.test.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index 16fa54f29..16aa84a9e 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -6,6 +6,7 @@ import { validateEmploymentSeparationAcceptance } from "./employment_separation_ import { acceptanceFixtureBytes, acceptanceFixtureSha256, + acceptanceLoadModel, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const PROFILE_PRECONDITIONS = Object.freeze({ @@ -31,6 +32,7 @@ function performanceResult(profile, iterations) { completed_iterations: iterations, sample_complete: true, completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(iterations), dataset_id: "dataset:employment-separation-perf-1", clearance_reference: "data_clearance:perf-2026-09", preparation_protocol_reference: "protocol:employment-separation-perf-v1", @@ -42,6 +44,7 @@ function performanceResult(profile, iterations) { k6: { metrics: { iterations: { values: { count: iterations } }, + dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: latencySamples } }, From e92dee9be0e78035580510c8b1b933daec016ad7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:11:21 +0900 Subject: [PATCH 098/269] test(perf): bind latency samples to open load evidence --- .../employment_separation_acceptance_latency_samples.test.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs index 0c0969015..f6fb5043f 100644 --- a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -6,6 +6,7 @@ import { validateEmploymentSeparationAcceptance } from "./employment_separation_ import { acceptanceFixtureBytes, acceptanceFixtureSha256, + acceptanceLoadModel, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const candidateSha = "a".repeat(40); @@ -22,6 +23,7 @@ function performanceResult(latencySamples = 1000, trendSamples = latencySamples) completed_iterations: 1000, sample_complete: true, completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(1000), dataset_id: "dataset:employment-separation-perf-1", clearance_reference: "data_clearance:perf-2026-09", preparation_protocol_reference: "protocol:employment-separation-perf-v1", @@ -38,6 +40,7 @@ function performanceResult(latencySamples = 1000, trendSamples = latencySamples) k6: { metrics: { iterations: { values: { count: 1000 } }, + dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: latencySamples } }, From 21e5762b517142b73f57f285e82b1635a975ec37 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:11:41 +0900 Subject: [PATCH 099/269] test(perf): require load-model provenance --- .../employment_separation_acceptance_provenance.test.mjs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index 534717d8d..09823cd29 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -6,6 +6,7 @@ import { validateEmploymentSeparationAcceptance } from "./employment_separation_ import { acceptanceFixtureBytes, acceptanceFixtureSha256, + acceptanceLoadModel, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const PROFILE_PRECONDITIONS = Object.freeze({ @@ -27,6 +28,7 @@ function result() { completed_iterations: 1000, sample_complete: true, completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(1000), dataset_id: "dataset:employment-separation-perf-1", clearance_reference: "data_clearance:perf-2026-09", preparation_protocol_reference: "protocol:employment-separation-perf-v1", @@ -38,6 +40,7 @@ function result() { k6: { metrics: { iterations: { values: { count: 1000 } }, + dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: 1000 } }, @@ -108,3 +111,9 @@ test("requires exact profile-precondition vocabulary", () => { reject((value) => { value.profile_preconditions.replay = "already_committed_maybe"; }, /profile_preconditions\.replay/); reject((value) => { value.profile_preconditions.extra = "unexpected"; }, /exactly first_commit, replay, rejection, contention/); }); + +test("requires exact open-load and direct-network provenance", () => { + reject((value) => { delete value.load_model; }, /load_model must be an object/); + reject((value) => { value.load_model.executor = "shared-iterations"; }, /constant-arrival-rate/); + reject((value) => { value.load_model.client_network_topology = "https_mitm_proxy"; }, /client_network_topology/); +}); From a96fa66a45816a80d50943b7e7efb0d351bc49aa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:11:56 +0900 Subject: [PATCH 100/269] test(perf): bind fixture acceptance to load evidence --- .../employment_separation_acceptance_fixture_binding.test.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs index 66976abee..be95b896d 100644 --- a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs @@ -8,6 +8,7 @@ import { ACCEPTANCE_PROFILE_PRECONDITIONS, acceptanceFixtureBytes, acceptanceFixtureSha256, + acceptanceLoadModel, } from "./employment_separation_acceptance_fixture_test_support.mjs"; function performanceResult(fixtureSha256, { includeFixtureDigest = true } = {}) { @@ -19,6 +20,7 @@ function performanceResult(fixtureSha256, { includeFixtureDigest = true } = {}) completed_iterations: 1000, sample_complete: true, completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(1000), dataset_id: "dataset:employment-separation-perf-1", clearance_reference: "data_clearance:perf-2026-09", preparation_protocol_reference: "protocol:employment-separation-perf-v1", @@ -30,6 +32,7 @@ function performanceResult(fixtureSha256, { includeFixtureDigest = true } = {}) k6: { metrics: { iterations: { values: { count: 1000 } }, + dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: 1000 } }, From 753c1c0a29e6958152e9b57b78b7a4fdced04e7e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:12:32 +0900 Subject: [PATCH 101/269] test(perf): extend acceptance edge load coverage --- .../employment_separation_acceptance_edge.test.mjs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index 5ba1019b9..4dea93cc9 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -6,6 +6,7 @@ import { validateEmploymentSeparationAcceptance } from "./employment_separation_ import { acceptanceFixtureBytes, acceptanceFixtureSha256, + acceptanceLoadModel, } from "./employment_separation_acceptance_fixture_test_support.mjs"; const TREND_BY_PROFILE = { @@ -38,6 +39,7 @@ function result(profile = "first_commit") { completed_iterations: iterations, sample_complete: true, completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(iterations), dataset_id: "dataset:employment-separation-perf-1", clearance_reference: "data_clearance:perf-2026-09", preparation_protocol_reference: "protocol:employment-separation-perf-v1", @@ -49,6 +51,7 @@ function result(profile = "first_commit") { k6: { metrics: { iterations: { values: { count: iterations } }, + dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: latencySamples } }, @@ -134,6 +137,14 @@ test("rejects invalid result authority and cardinality metadata", () => { rejectResult((value) => { value.completed_iterations = 999; }, /sample must be complete/); }); +test("rejects invalid load-model and client-network evidence", () => { + rejectResult((value) => { delete value.load_model; }, /load_model must be an object/); + rejectResult((value) => { value.load_model.executor = "shared-iterations"; }, /constant-arrival-rate/); + rejectResult((value) => { value.load_model.duration_seconds = 999; }, /must equal expectedIterations exactly/); + rejectResult((value) => { value.load_model.max_vus = 0; }, /positive safe integer/); + rejectResult((value) => { value.load_model.client_network_topology = "https_mitm_proxy"; }, /client_network_topology/); +}); + test("rejects invalid timestamps and result evidence references", () => { rejectResult((value) => { value.completed_at = "nope"; }, /UTC timestamp/); rejectResult((value) => { value.completed_at = "2026-13-40T04:10:00Z"; }, /UTC timestamp/); @@ -148,6 +159,8 @@ test("rejects malformed k6 metric containers and iteration evidence", () => { rejectResult((value) => { delete value.k6.metrics.iterations; }, /iterations must be an object/); rejectResult((value) => { value.k6.metrics.iterations.values = []; }, /iterations.values must be an object/); rejectResult((value) => { value.k6.metrics.iterations.values.count = 999; }, /iteration count/); + rejectResult((value) => { delete value.k6.metrics.dropped_iterations; }, /dropped_iterations must be an object/); + rejectResult((value) => { value.k6.metrics.dropped_iterations.values.count = 1; }, /dropped_iterations count must equal 0/); rejectResult((value) => { delete value.k6.metrics.employment_separation_latency_samples; }, /latency_samples must be an object/); rejectResult((value) => { value.k6.metrics.employment_separation_latency_samples.values.count = 999; }, /latency sample count/); rejectResult( From 3402dbd325407b83a0382cd78709389ff28d0417 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:14:37 +0900 Subject: [PATCH 102/269] fix(perf): prove no drops from scheduled completion --- tests/performance/employment_separation_run_contract.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index bf7b78b8c..d472c222b 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -142,7 +142,6 @@ export function thresholdsForPerformanceProfile(profile, expectedIterations) { employment_separation_unexpected_response: ["rate==0"], employment_separation_latency_samples: [`count>=${expectedLatencySamples}`], checks: ["rate==1"], - dropped_iterations: ["count==0"], iterations: [`count>=${expectedIterations}`], }; if (profile === "first_commit") { From 0331f20e573c65cb9637f8a4a8cb6d8d76036ceb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:14:56 +0900 Subject: [PATCH 103/269] test(perf): avoid zero-sample dropped metric assumption --- tests/performance/employment_separation_run_contract.test.mjs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 9862cfc52..fe5842d0d 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -93,12 +93,11 @@ test("fails closed when the k6 client is routed through an ambient proxy", () => ); }); -test("applies the commercial p95 threshold only to the ordinary first-commit profile", () => { +test("uses exact scheduled completion rather than a zero-sample dropped-iteration threshold", () => { assert.deepEqual(thresholdsForPerformanceProfile("first_commit", 1000), { employment_separation_unexpected_response: ["rate==0"], employment_separation_latency_samples: ["count>=1000"], checks: ["rate==1"], - dropped_iterations: ["count==0"], iterations: ["count>=1000"], employment_separation_first_commit_duration_ms: ["p(95)<=20"], }); @@ -106,7 +105,6 @@ test("applies the commercial p95 threshold only to the ordinary first-commit pro employment_separation_unexpected_response: ["rate==0"], employment_separation_latency_samples: ["count>=200"], checks: ["rate==1"], - dropped_iterations: ["count==0"], iterations: ["count>=100"], }); }); From 9d53aae6184b555abe1f2c684e5c3767d4c25a28 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:15:33 +0900 Subject: [PATCH 104/269] fix(perf): avoid absent-zero dropped metric evidence --- .../employment_separation_acceptance_contract.mjs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 41aaaea36..9b4bfbd85 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -188,12 +188,6 @@ function validateResult(result) { const iterationValues = metricValues(result, "iterations"); const metricIterations = nonNegativeInteger(iterationValues.count, "result.k6.metrics.iterations.values.count"); if (metricIterations !== expectedIterations) fail("k6 iteration count must equal expected_iterations"); - const droppedValues = metricValues(result, "dropped_iterations"); - const droppedIterations = nonNegativeInteger( - droppedValues.count, - "result.k6.metrics.dropped_iterations.values.count", - ); - if (droppedIterations !== 0) fail("k6 dropped_iterations count must equal 0"); const expectedLatencySamples = profile === "contention" ? expectedIterations * 2 : expectedIterations; if (!Number.isSafeInteger(expectedLatencySamples)) fail("expected latency sample count must be a safe integer"); From 01abcb13ba026bbc503c04914d874bd08a28dff7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:16:03 +0900 Subject: [PATCH 105/269] test(perf): prove no drops from completion cardinality --- ...mployment_separation_acceptance_contract.test.mjs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 82f6313d3..0b76e3789 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -39,7 +39,6 @@ function result() { k6: { metrics: { iterations: { values: { count: 1000, rate: 40 } }, - dropped_iterations: { values: { count: 0, rate: 0 } }, checks: { values: { rate: 1, passes: 1000, fails: 0 } }, employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, employment_separation_latency_samples: { values: { count: 1000, rate: 40 } }, @@ -122,19 +121,14 @@ test("rejects first-commit evidence above the commercial p95 target", () => { assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /p95 must be <= 20 ms/); }); -test("rejects closed or incomplete offered-load evidence", () => { +test("rejects a closed workload model", () => { const { performance } = evidencePair(); performance.load_model.executor = "shared-iterations"; - let artifact = render(performance); + const artifact = render(performance); assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /constant-arrival-rate/); - - const dropped = result(); - dropped.k6.metrics.dropped_iterations.values.count = 1; - artifact = render(dropped); - assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /dropped_iterations count must equal 0/); }); -test("rejects incomplete samples even when the completed subset is fast", () => { +test("rejects incomplete scheduled samples even when the completed subset is fast", () => { const { performance } = evidencePair(); performance.completed_iterations = 999; performance.sample_complete = false; From aabf866039587c9542030d4f39b03297ec4a6e61 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:16:57 +0900 Subject: [PATCH 106/269] test(perf): accept healthy absent dropped metric --- .../performance/employment_separation_acceptance_edge.test.mjs | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index 4dea93cc9..45fadfc0c 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -51,7 +51,6 @@ function result(profile = "first_commit") { k6: { metrics: { iterations: { values: { count: iterations } }, - dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: latencySamples } }, @@ -159,8 +158,6 @@ test("rejects malformed k6 metric containers and iteration evidence", () => { rejectResult((value) => { delete value.k6.metrics.iterations; }, /iterations must be an object/); rejectResult((value) => { value.k6.metrics.iterations.values = []; }, /iterations.values must be an object/); rejectResult((value) => { value.k6.metrics.iterations.values.count = 999; }, /iteration count/); - rejectResult((value) => { delete value.k6.metrics.dropped_iterations; }, /dropped_iterations must be an object/); - rejectResult((value) => { value.k6.metrics.dropped_iterations.values.count = 1; }, /dropped_iterations count must equal 0/); rejectResult((value) => { delete value.k6.metrics.employment_separation_latency_samples; }, /latency_samples must be an object/); rejectResult((value) => { value.k6.metrics.employment_separation_latency_samples.values.count = 999; }, /latency sample count/); rejectResult( From 6ae7da21b49dbb4225a6c19cf63bd802a638367d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:21:00 +0900 Subject: [PATCH 107/269] fix(perf): bind load model to observer evidence --- ...loyment_separation_acceptance_contract.mjs | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 9b4bfbd85..ad64b5c38 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -145,6 +145,21 @@ function metricValues(data, name) { return plainObject(metric(data, name).values, `result.k6.metrics.${name}.values`); } +function sameLoadModel(observed, declared) { + for (const field of [ + "executor", + "target_rps", + "duration_seconds", + "preallocated_vus", + "max_vus", + "client_network_topology", + ]) { + if (observed[field] !== declared[field]) { + fail(`runtime.observed_load_model.${field} must match result.load_model.${field}`); + } + } +} + function validateResult(result) { if (result.schema_version !== RESULT_SCHEMA) fail("result.schema_version is unsupported"); const candidateSha = sha(result.candidate_sha, "result.candidate_sha"); @@ -178,7 +193,7 @@ function validateResult(result) { if (expectedIterations < minimumIterations) { fail(`${profile} requires at least ${minimumIterations} iterations`); } - validatePerformanceLoadModel(result.load_model, expectedIterations); + const loadModel = validatePerformanceLoadModel(result.load_model, expectedIterations); const completedIterations = nonNegativeInteger(result.completed_iterations, "result.completed_iterations"); if (result.sample_complete !== true || completedIterations !== expectedIterations) { fail("result sample must be complete"); @@ -223,7 +238,7 @@ function validateResult(result) { } if (profile === "first_commit" && p95 > 20) fail("first_commit p95 must be <= 20 ms"); - return { candidateSha, fixtureSha256, profile, p95, completedAt }; + return { candidateSha, fixtureSha256, profile, p95, completedAt, expectedIterations, loadModel }; } function parseAndValidateFixture(fixtureArtifact, result, validatedResult) { @@ -278,6 +293,12 @@ function validateRuntimeEvidence(runtime, resultDigest, result, validatedResult, reference(runtime.environment_reference, "runtime.environment_reference"); reference(runtime.deployment_reference, "runtime.deployment_reference"); reference(runtime.observer_reference, "runtime.observer_reference"); + reference(runtime.load_observation_reference, "runtime.load_observation_reference"); + const observedLoadModel = validatePerformanceLoadModel( + runtime.observed_load_model, + validatedResult.expectedIterations, + ); + sameLoadModel(observedLoadModel, validatedResult.loadModel); const resourceReference = reference(runtime.resource_evidence_reference, "runtime.resource_evidence_reference"); if (resourceReference !== result.resource_evidence_reference) { fail("runtime.resource_evidence_reference must match result.resource_evidence_reference"); From 99be218a460ac3784ca93de58fdc1dfece34ed2f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:21:32 +0900 Subject: [PATCH 108/269] test(perf): reject unobserved load declarations --- ...loyment_separation_acceptance_contract.test.mjs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 0b76e3789..01e193125 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -65,6 +65,8 @@ function runtimeEvidence(resultArtifact) { environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(1000), resource_evidence_reference: "metrics:employment-separation-perf-1", observed_at: "2026-09-13T04:10:01Z", host_cpu_percent_p95: 42.5, @@ -89,7 +91,7 @@ function evidencePair() { return { performance, artifact, runtime: runtimeEvidence(artifact) }; } -test("accepts an exact candidate result only with bound fixture, deployment, resource, load, and cleanup evidence", () => { +test("accepts an exact candidate result only with independently observed load, fixture, deployment, resource, and cleanup evidence", () => { const { artifact, runtime } = evidencePair(); assert.deepEqual(validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), { accepted: true, @@ -113,6 +115,16 @@ test("rejects a result artifact that is not the one observed by the runtime evid assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), /performance_result_sha256/); }); +test("rejects declared load evidence that differs from the independent runtime observation", () => { + const { artifact, runtime } = evidencePair(); + runtime.observed_load_model.target_rps = 2; + runtime.observed_load_model.duration_seconds = 500; + assert.throws( + () => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), + /observed_load_model.target_rps must match result.load_model.target_rps/, + ); +}); + test("rejects first-commit evidence above the commercial p95 target", () => { const { performance } = evidencePair(); performance.k6.metrics.employment_separation_first_commit_duration_ms.values["p(95)"] = 20.001; From 043ebf039b4e6e6598cc51da6013ddfc427a7e90 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:21:50 +0900 Subject: [PATCH 109/269] test(perf): observe load in cardinality evidence --- ...loyment_separation_acceptance_cardinality.test.mjs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index 16aa84a9e..b0349bee8 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -44,7 +44,6 @@ function performanceResult(profile, iterations) { k6: { metrics: { iterations: { values: { count: iterations } }, - dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: latencySamples } }, @@ -58,7 +57,7 @@ function performanceResult(profile, iterations) { }; } -function runtimeEvidence(resultArtifact, profile) { +function runtimeEvidence(resultArtifact, profile, iterations) { return { schema_version: "orgmetra.employment_separation.runtime_evidence.v1", candidate_sha: "a".repeat(40), @@ -69,6 +68,8 @@ function runtimeEvidence(resultArtifact, profile) { environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(iterations), resource_evidence_reference: "metrics:employment-separation-perf-1", observed_at: "2026-09-13T04:10:01Z", host_cpu_percent_p95: 42.5, @@ -90,7 +91,11 @@ function runtimeEvidence(resultArtifact, profile) { function assertRejected(result, pattern) { const artifact = Buffer.from(`${JSON.stringify(result, null, 2)}\n`, "utf8"); assert.throws( - () => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact, result.selected_profile), FIXTURE_BYTES), + () => validateEmploymentSeparationAcceptance( + artifact, + runtimeEvidence(artifact, result.selected_profile, result.expected_iterations), + FIXTURE_BYTES, + ), pattern, ); } From 68c48a894b006d9905dde8aa7fcb2ab382f95302 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:22:06 +0900 Subject: [PATCH 110/269] test(perf): observe load with latency samples --- .../employment_separation_acceptance_latency_samples.test.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs index f6fb5043f..637432a64 100644 --- a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -40,7 +40,6 @@ function performanceResult(latencySamples = 1000, trendSamples = latencySamples) k6: { metrics: { iterations: { values: { count: 1000 } }, - dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: latencySamples } }, @@ -67,6 +66,8 @@ function runtimeEvidence(resultArtifact) { environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(1000), resource_evidence_reference: "metrics:employment-separation-perf-1", observed_at: "2026-09-13T04:10:01Z", host_cpu_percent_p95: 42, From dd08dc64a319e23ba1a193eca2099e5fcff91157 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:22:29 +0900 Subject: [PATCH 111/269] test(perf): bind fixture run to observed load --- .../employment_separation_acceptance_fixture_binding.test.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs index be95b896d..6ada1d5c3 100644 --- a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs @@ -32,7 +32,6 @@ function performanceResult(fixtureSha256, { includeFixtureDigest = true } = {}) k6: { metrics: { iterations: { values: { count: 1000 } }, - dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: 1000 } }, @@ -57,6 +56,8 @@ function runtimeEvidence(resultArtifact, fixtureSha256) { environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(1000), resource_evidence_reference: "metrics:employment-separation-perf-1", observed_at: "2026-09-13T04:10:01Z", host_cpu_percent_p95: 42, From 089421a686e2a854ea129c6deb51e73caf6bf3c0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:22:48 +0900 Subject: [PATCH 112/269] test(perf): carry observed load through provenance tests --- .../employment_separation_acceptance_provenance.test.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index 09823cd29..61d7ad52e 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -40,7 +40,6 @@ function result() { k6: { metrics: { iterations: { values: { count: 1000 } }, - dropped_iterations: { values: { count: 0 } }, checks: { values: { rate: 1 } }, employment_separation_unexpected_response: { values: { rate: 0 } }, employment_separation_latency_samples: { values: { count: 1000 } }, @@ -67,6 +66,8 @@ function runtime(resultArtifact) { environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(1000), resource_evidence_reference: "metrics:employment-separation-perf-1", observed_at: "2026-09-13T04:10:01Z", host_cpu_percent_p95: 42, From f95c70b572b73e51584dc5361acaca34ce28d583 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:23:38 +0900 Subject: [PATCH 113/269] test(perf): cover independent load observation --- .../employment_separation_acceptance_edge.test.mjs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index 45fadfc0c..fa6fddeaa 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -61,6 +61,7 @@ function result(profile = "first_commit") { } function runtime(resultArtifact, profile = "first_commit") { + const iterations = profile === "contention" ? 100 : 1000; return { schema_version: "orgmetra.employment_separation.runtime_evidence.v1", candidate_sha: "a".repeat(40), @@ -71,6 +72,8 @@ function runtime(resultArtifact, profile = "first_commit") { environment_reference: "environment:perf-staging-1", deployment_reference: "deployment:orgmetra-people-a1", observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(iterations), resource_evidence_reference: "metrics:employment-separation-perf-1", observed_at: "2026-09-13T04:10:01Z", host_cpu_percent_p95: 42, @@ -213,6 +216,16 @@ test("rejects malformed runtime authority and artifact binding", () => { rejectRuntime((value) => { value.fixture_sha256 = "0".repeat(64); }, /exact validated performance fixture/); }); +test("rejects invalid runtime load observation", () => { + rejectRuntime((value) => { value.load_observation_reference = "bad"; }, /load_observation_reference/); + rejectRuntime((value) => { delete value.observed_load_model; }, /load_model must be an object/); + rejectRuntime((value) => { value.observed_load_model.executor = "shared-iterations"; }, /constant-arrival-rate/); + rejectRuntime((value) => { + value.observed_load_model.target_rps = 2; + value.observed_load_model.duration_seconds = 500; + }, /observed_load_model.target_rps must match/); +}); + test("rejects invalid runtime references and observation time", () => { rejectRuntime((value) => { value.environment_reference = ""; }, /non-empty string/); rejectRuntime((value) => { value.environment_reference = "no namespace"; }, /namespaced opaque reference/); From 48fdc2bdaa3f34859c49d73f491bb787d364de41 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:29:49 +0900 Subject: [PATCH 114/269] test(perf): reject lossy runtime evidence decoding --- ...aration_runtime_evidence_artifact.test.mjs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/performance/employment_separation_runtime_evidence_artifact.test.mjs diff --git a/tests/performance/employment_separation_runtime_evidence_artifact.test.mjs b/tests/performance/employment_separation_runtime_evidence_artifact.test.mjs new file mode 100644 index 000000000..5cac4eae7 --- /dev/null +++ b/tests/performance/employment_separation_runtime_evidence_artifact.test.mjs @@ -0,0 +1,48 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; + +function sha256(bytes) { + return createHash("sha256").update(bytes).digest("hex"); +} + +test("binds acceptance runtime evidence to the exact raw artifact bytes", () => { + const bytes = Buffer.from('{"schema_version":"orgmetra.employment_separation.runtime_evidence.v1"}\n', "utf8"); + const document = parseRuntimeEvidenceArtifact(bytes); + + assert.deepEqual(document.parsed, { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + }); + assert.equal(document.sha256, sha256(bytes)); + assert.throws( + () => parseRuntimeEvidenceArtifact(bytes.toString("utf8")), + /runtime evidence must be supplied as raw bytes/, + ); +}); + +test("rejects byte-distinct malformed UTF-8 before lossy JSON interpretation can collapse it", () => { + const prefix = Buffer.from('{"observer_reference":"observer:', "utf8"); + const suffix = Buffer.from('"}', "utf8"); + const first = Buffer.concat([prefix, Buffer.from([0x80]), suffix]); + const second = Buffer.concat([prefix, Buffer.from([0x81]), suffix]); + + assert.equal(first.toString("utf8"), second.toString("utf8")); + assert.notEqual(sha256(first), sha256(second)); + assert.doesNotThrow(() => JSON.parse(first.toString("utf8"))); + assert.doesNotThrow(() => JSON.parse(second.toString("utf8"))); + assert.throws(() => parseRuntimeEvidenceArtifact(first), /runtime evidence must be valid UTF-8/); + assert.throws(() => parseRuntimeEvidenceArtifact(second), /runtime evidence must be valid UTF-8/); +}); + +test("rejects JSON values that are not runtime-evidence objects", () => { + assert.throws( + () => parseRuntimeEvidenceArtifact(Buffer.from("[]\n", "utf8")), + /runtime evidence must be a JSON object/, + ); + assert.throws( + () => parseRuntimeEvidenceArtifact(Buffer.from("null\n", "utf8")), + /runtime evidence must be a JSON object/, + ); +}); From 93c6f2cc6c58e64906679f67739b1e7996cb8c6b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:29:55 +0900 Subject: [PATCH 115/269] fix(perf): parse runtime evidence from exact raw bytes --- ...t_separation_runtime_evidence_artifact.mjs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/performance/employment_separation_runtime_evidence_artifact.mjs diff --git a/tests/performance/employment_separation_runtime_evidence_artifact.mjs b/tests/performance/employment_separation_runtime_evidence_artifact.mjs new file mode 100644 index 000000000..e79898602 --- /dev/null +++ b/tests/performance/employment_separation_runtime_evidence_artifact.mjs @@ -0,0 +1,37 @@ +import { createHash } from "node:crypto"; +import { TextDecoder } from "node:util"; + +function rawBytes(value) { + if (value instanceof Uint8Array) return value; + if (value instanceof ArrayBuffer) return new Uint8Array(value); + throw new Error("runtime evidence must be supplied as raw bytes"); +} + +export function parseRuntimeEvidenceArtifact(value) { + const bytes = rawBytes(value); + let text; + try { + text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); + } catch (error) { + throw new Error("runtime evidence must be valid UTF-8", { cause: error }); + } + + if (text.trim() === "") { + throw new Error("runtime evidence must be non-empty JSON text"); + } + + let parsed; + try { + parsed = JSON.parse(text); + } catch (error) { + throw new Error("runtime evidence must be valid JSON", { cause: error }); + } + if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) { + throw new Error("runtime evidence must be a JSON object"); + } + + return { + parsed, + sha256: createHash("sha256").update(bytes).digest("hex"), + }; +} From fd4c6a45c80bbf56216ed12096b1710760417a6b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 16:30:02 +0900 Subject: [PATCH 116/269] fix(perf): bind runtime evidence artifact before acceptance --- ...employment_separation_acceptance_check.mjs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index 23d2afcb4..bed3f00e3 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -1,25 +1,28 @@ import { readFile } from "node:fs/promises"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; async function main() { const [resultPath, runtimeEvidencePath, fixturePath] = process.argv.slice(2); if (!resultPath || !runtimeEvidencePath || !fixturePath || process.argv.length !== 5) { throw new Error("usage: node employment_separation_acceptance_check.mjs "); } - const [resultBytes, runtimeText, fixtureBytes] = await Promise.all([ + const [resultBytes, runtimeBytes, fixtureBytes] = await Promise.all([ readFile(resultPath), - readFile(runtimeEvidencePath, "utf8"), + readFile(runtimeEvidencePath), readFile(fixturePath), ]); - let runtimeEvidence; - try { - runtimeEvidence = JSON.parse(runtimeText); - } catch (error) { - throw new Error("runtime evidence must be valid JSON", { cause: error }); - } - const acceptance = validateEmploymentSeparationAcceptance(resultBytes, runtimeEvidence, fixtureBytes); - process.stdout.write(`${JSON.stringify(acceptance, null, 2)}\n`); + const runtimeDocument = parseRuntimeEvidenceArtifact(runtimeBytes); + const acceptance = validateEmploymentSeparationAcceptance( + resultBytes, + runtimeDocument.parsed, + fixtureBytes, + ); + process.stdout.write(`${JSON.stringify({ + ...acceptance, + runtime_evidence_sha256: runtimeDocument.sha256, + }, null, 2)}\n`); } main().catch((error) => { From c711a4ba1ed59491555e7c9a346990f391775a6f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 18:01:52 +0900 Subject: [PATCH 117/269] test(perf): define pinned k6 runtime contract --- .../employment_separation_k6_runtime_contract.mjs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/performance/employment_separation_k6_runtime_contract.mjs diff --git a/tests/performance/employment_separation_k6_runtime_contract.mjs b/tests/performance/employment_separation_k6_runtime_contract.mjs new file mode 100644 index 000000000..7834bd68e --- /dev/null +++ b/tests/performance/employment_separation_k6_runtime_contract.mjs @@ -0,0 +1,8 @@ +export const PINNED_K6_VERSION = "2.2.0"; + +export function requirePinnedK6Version(value) { + if (value !== PINNED_K6_VERSION) { + throw new Error(`commercial Employment separation performance runs require k6 ${PINNED_K6_VERSION}`); + } + return value; +} From 9284e8441e42a8da1faedd9ab6a578aff44c1036 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 18:03:39 +0900 Subject: [PATCH 118/269] test(perf): pin k6 runner provenance --- .../employment_separation_buyer_path.js | 3 +++ ...nt_separation_k6_runtime_contract.test.mjs | 21 ++++++++++++++++++ .../run_employment_separation_benchmark.sh | 22 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 tests/performance/employment_separation_k6_runtime_contract.test.mjs create mode 100755 tests/performance/run_employment_separation_benchmark.sh diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index b41a750cc..eabf793a5 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -9,6 +9,7 @@ import { requestHeaders, validatePerformanceFixture, } from "./employment_separation_fixture_contract.mjs"; +import { requirePinnedK6Version } from "./employment_separation_k6_runtime_contract.mjs"; import { isGovernedSeparationConflict, isGovernedSeparationSuccess, @@ -31,6 +32,7 @@ const bearerToken = __ENV.ORGMETRA_PERFORMANCE_BEARER_TOKEN || ""; const targetSha = (__ENV.ORGMETRA_PERFORMANCE_TARGET_SHA || "").toLowerCase(); const selectedProfile = requirePerformanceProfile(__ENV.ORGMETRA_PERFORMANCE_PROFILE || ""); const clientNetworkTopology = requireDirectPerformanceClientNetwork(__ENV); +const k6Version = requirePinnedK6Version(__ENV.ORGMETRA_PERFORMANCE_K6_VERSION || ""); if (!fixturePath) fail("ORGMETRA_PERFORMANCE_DATA_FILE is required"); if (!baseUrl) fail("ORGMETRA_PERFORMANCE_BASE_URL is required"); @@ -188,6 +190,7 @@ export function handleSummary(data) { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: targetSha, fixture_sha256: fixtureSha256, + k6_version: k6Version, selected_profile: selectedProfile, expected_iterations: selectedRecords.length, completed_iterations: completedIterations, diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs new file mode 100644 index 000000000..e8b5508dc --- /dev/null +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -0,0 +1,21 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + PINNED_K6_VERSION, + requirePinnedK6Version, +} from "./employment_separation_k6_runtime_contract.mjs"; + +test("accepts only the repository-pinned k6 runtime", () => { + assert.equal(PINNED_K6_VERSION, "2.2.0"); + assert.equal(requirePinnedK6Version("2.2.0"), "2.2.0"); +}); + +test("rejects missing, older, newer, or decorated k6 runtime declarations", () => { + for (const value of ["", "2.1.0", "2.2.1", "2.3.0", "v2.2.0", "2.2.0-dev"]) { + assert.throws( + () => requirePinnedK6Version(value), + /require k6 2\.2\.0/, + ); + } +}); diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh new file mode 100755 index 000000000..6436df36b --- /dev/null +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +set -euo pipefail + +readonly PINNED_K6_VERSION="2.2.0" +readonly WORKLOAD="tests/performance/employment_separation_buyer_path.js" + +k6_bin="${K6_BIN:-k6}" +if ! command -v "${k6_bin}" >/dev/null 2>&1; then + printf 'pinned k6 runner is unavailable: %s\n' "${k6_bin}" >&2 + exit 1 +fi + +version_line="$(${k6_bin} version 2>&1 | head -n 1)" +version_token="$(printf '%s\n' "${version_line}" | awk '{print $2}')" +if [[ "${version_token}" != "v${PINNED_K6_VERSION}" ]]; then + printf 'commercial Employment separation performance runs require k6 v%s; observed: %s\n' \ + "${PINNED_K6_VERSION}" "${version_line}" >&2 + exit 1 +fi + +export ORGMETRA_PERFORMANCE_K6_VERSION="${PINNED_K6_VERSION}" +exec "${k6_bin}" run "${WORKLOAD}" "$@" From 14e5fee46de92aff2b92cc198a878aaec2cc5661 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 18:13:30 +0900 Subject: [PATCH 119/269] test(perf): bind k6 release artifact to acceptance --- ...employment_separation_acceptance_check.mjs | 3 + .../employment_separation_buyer_path.js | 16 +++- ...oyment_separation_k6_evidence_contract.mjs | 77 +++++++++++++++++++ ...t_separation_k6_evidence_contract.test.mjs | 65 ++++++++++++++++ ...loyment_separation_k6_runtime_contract.mjs | 33 ++++++++ ...nt_separation_k6_runtime_contract.test.mjs | 36 +++++++-- .../run_employment_separation_benchmark.sh | 46 +++++++++-- 7 files changed, 262 insertions(+), 14 deletions(-) create mode 100644 tests/performance/employment_separation_k6_evidence_contract.mjs create mode 100644 tests/performance/employment_separation_k6_evidence_contract.test.mjs diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index bed3f00e3..125c45751 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -1,6 +1,7 @@ import { readFile } from "node:fs/promises"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { validatePinnedK6AcceptanceEvidence } from "./employment_separation_k6_evidence_contract.mjs"; import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; async function main() { @@ -14,6 +15,7 @@ async function main() { readFile(fixturePath), ]); const runtimeDocument = parseRuntimeEvidenceArtifact(runtimeBytes); + const k6Evidence = validatePinnedK6AcceptanceEvidence(resultBytes, runtimeDocument.parsed); const acceptance = validateEmploymentSeparationAcceptance( resultBytes, runtimeDocument.parsed, @@ -21,6 +23,7 @@ async function main() { ); process.stdout.write(`${JSON.stringify({ ...acceptance, + ...k6Evidence, runtime_evidence_sha256: runtimeDocument.sha256, }, null, 2)}\n`); } diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index eabf793a5..7e73c1634 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -9,7 +9,7 @@ import { requestHeaders, validatePerformanceFixture, } from "./employment_separation_fixture_contract.mjs"; -import { requirePinnedK6Version } from "./employment_separation_k6_runtime_contract.mjs"; +import { requirePinnedK6Runtime } from "./employment_separation_k6_runtime_contract.mjs"; import { isGovernedSeparationConflict, isGovernedSeparationSuccess, @@ -32,7 +32,13 @@ const bearerToken = __ENV.ORGMETRA_PERFORMANCE_BEARER_TOKEN || ""; const targetSha = (__ENV.ORGMETRA_PERFORMANCE_TARGET_SHA || "").toLowerCase(); const selectedProfile = requirePerformanceProfile(__ENV.ORGMETRA_PERFORMANCE_PROFILE || ""); const clientNetworkTopology = requireDirectPerformanceClientNetwork(__ENV); -const k6Version = requirePinnedK6Version(__ENV.ORGMETRA_PERFORMANCE_K6_VERSION || ""); +const k6Runtime = requirePinnedK6Runtime({ + version: __ENV.ORGMETRA_PERFORMANCE_K6_VERSION || "", + releaseAsset: __ENV.ORGMETRA_PERFORMANCE_K6_RELEASE_ASSET || "", + releaseAssetSha256: __ENV.ORGMETRA_PERFORMANCE_K6_RELEASE_ASSET_SHA256 || "", + runnerIdentity: __ENV.ORGMETRA_PERFORMANCE_K6_RUNNER_IDENTITY || "", + executableSha256: __ENV.ORGMETRA_PERFORMANCE_K6_EXECUTABLE_SHA256 || "", +}); if (!fixturePath) fail("ORGMETRA_PERFORMANCE_DATA_FILE is required"); if (!baseUrl) fail("ORGMETRA_PERFORMANCE_BASE_URL is required"); @@ -190,7 +196,11 @@ export function handleSummary(data) { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: targetSha, fixture_sha256: fixtureSha256, - k6_version: k6Version, + k6_version: k6Runtime.version, + k6_release_asset: k6Runtime.release_asset, + k6_release_asset_sha256: k6Runtime.release_asset_sha256, + k6_runner_identity: k6Runtime.runner_identity, + k6_executable_sha256: k6Runtime.executable_sha256, selected_profile: selectedProfile, expected_iterations: selectedRecords.length, completed_iterations: completedIterations, diff --git a/tests/performance/employment_separation_k6_evidence_contract.mjs b/tests/performance/employment_separation_k6_evidence_contract.mjs new file mode 100644 index 000000000..ecf7a6e0b --- /dev/null +++ b/tests/performance/employment_separation_k6_evidence_contract.mjs @@ -0,0 +1,77 @@ +import { TextDecoder } from "node:util"; + +import { + PINNED_K6_RELEASE_ASSET, + PINNED_K6_RELEASE_ASSET_SHA256, + PINNED_K6_RUNNER_IDENTITY, + PINNED_K6_VERSION, + requirePinnedK6Runtime, +} from "./employment_separation_k6_runtime_contract.mjs"; + +function fail(message) { + throw new Error(message); +} + +function parseResultBytes(value) { + if (!(value instanceof Uint8Array) && !(value instanceof ArrayBuffer)) { + fail("performance result must be supplied as raw bytes"); + } + const bytes = value instanceof Uint8Array ? value : new Uint8Array(value); + let text; + try { + text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); + } catch (error) { + throw new Error("performance result must be valid UTF-8", { cause: error }); + } + let result; + try { + result = JSON.parse(text); + } catch (error) { + throw new Error("performance result must be valid JSON", { cause: error }); + } + if (result === null || typeof result !== "object" || Array.isArray(result)) { + fail("performance result must be an object"); + } + return result; +} + +function runtimeField(runtime, name) { + if (runtime === null || typeof runtime !== "object" || Array.isArray(runtime)) { + fail("runtime evidence must be an object"); + } + const value = runtime[name]; + if (typeof value !== "string" || value === "") { + fail(`runtime.${name} must be a non-empty string`); + } + return value; +} + +export function validatePinnedK6AcceptanceEvidence(resultArtifact, runtimeEvidence) { + const result = parseResultBytes(resultArtifact); + const resultRuntime = requirePinnedK6Runtime({ + version: result.k6_version, + releaseAsset: result.k6_release_asset, + releaseAssetSha256: result.k6_release_asset_sha256, + runnerIdentity: result.k6_runner_identity, + executableSha256: result.k6_executable_sha256, + }); + const observedRuntime = requirePinnedK6Runtime({ + version: runtimeField(runtimeEvidence, "observed_k6_version"), + releaseAsset: runtimeField(runtimeEvidence, "observed_k6_release_asset"), + releaseAssetSha256: runtimeField(runtimeEvidence, "observed_k6_release_asset_sha256"), + runnerIdentity: runtimeField(runtimeEvidence, "observed_k6_runner_identity"), + executableSha256: runtimeField(runtimeEvidence, "observed_k6_executable_sha256"), + }); + for (const field of ["version", "release_asset", "release_asset_sha256", "runner_identity", "executable_sha256"]) { + if (resultRuntime[field] !== observedRuntime[field]) { + fail(`runtime observed k6 ${field} must match the performance result`); + } + } + return Object.freeze({ + k6_version: PINNED_K6_VERSION, + k6_release_asset: PINNED_K6_RELEASE_ASSET, + k6_release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, + k6_executable_sha256: resultRuntime.executable_sha256, + }); +} diff --git a/tests/performance/employment_separation_k6_evidence_contract.test.mjs b/tests/performance/employment_separation_k6_evidence_contract.test.mjs new file mode 100644 index 000000000..4b7ec583c --- /dev/null +++ b/tests/performance/employment_separation_k6_evidence_contract.test.mjs @@ -0,0 +1,65 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + PINNED_K6_RELEASE_ASSET, + PINNED_K6_RELEASE_ASSET_SHA256, + PINNED_K6_RUNNER_IDENTITY, + PINNED_K6_VERSION, +} from "./employment_separation_k6_runtime_contract.mjs"; +import { validatePinnedK6AcceptanceEvidence } from "./employment_separation_k6_evidence_contract.mjs"; + +const EXECUTABLE_SHA256 = "1".repeat(64); + +function resultBytes(overrides = {}) { + return Buffer.from(`${JSON.stringify({ + k6_version: PINNED_K6_VERSION, + k6_release_asset: PINNED_K6_RELEASE_ASSET, + k6_release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, + k6_executable_sha256: EXECUTABLE_SHA256, + ...overrides, + })}\n`, "utf8"); +} + +function runtime(overrides = {}) { + return { + observed_k6_version: PINNED_K6_VERSION, + observed_k6_release_asset: PINNED_K6_RELEASE_ASSET, + observed_k6_release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + observed_k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, + observed_k6_executable_sha256: EXECUTABLE_SHA256, + ...overrides, + }; +} + +test("binds result runtime identity to independently observed pinned upstream k6 evidence", () => { + assert.deepEqual(validatePinnedK6AcceptanceEvidence(resultBytes(), runtime()), { + k6_version: PINNED_K6_VERSION, + k6_release_asset: PINNED_K6_RELEASE_ASSET, + k6_release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, + k6_executable_sha256: EXECUTABLE_SHA256, + }); +}); + +test("rejects a result that merely self-declares the right version with a substituted archive", () => { + assert.throws( + () => validatePinnedK6AcceptanceEvidence(resultBytes({ k6_release_asset_sha256: "0".repeat(64) }), runtime()), + /release-asset SHA-256/, + ); +}); + +test("rejects runtime observation that does not identify the exact pinned runner", () => { + assert.throws( + () => validatePinnedK6AcceptanceEvidence(resultBytes(), runtime({ observed_k6_runner_identity: "upstream_release_archive:substitute" })), + /runner identity/, + ); +}); + +test("rejects an independently observed executable digest that differs from the result", () => { + assert.throws( + () => validatePinnedK6AcceptanceEvidence(resultBytes(), runtime({ observed_k6_executable_sha256: "2".repeat(64) })), + /executable_sha256 must match/, + ); +}); diff --git a/tests/performance/employment_separation_k6_runtime_contract.mjs b/tests/performance/employment_separation_k6_runtime_contract.mjs index 7834bd68e..0e994fdfa 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.mjs @@ -1,4 +1,8 @@ export const PINNED_K6_VERSION = "2.2.0"; +export const PINNED_K6_RELEASE_ASSET = "k6-v2.2.0-linux-amd64.tar.gz"; +export const PINNED_K6_RELEASE_ASSET_SHA256 = "b5a8003c86f35f5cd5ceef1490312c48e587696c94d998cefc6d7b3b4cb1597d"; +export const PINNED_K6_RUNNER_IDENTITY = `upstream_release_archive:${PINNED_K6_RELEASE_ASSET}@sha256:${PINNED_K6_RELEASE_ASSET_SHA256}`; +const SHA256_PATTERN = /^[0-9a-f]{64}$/; export function requirePinnedK6Version(value) { if (value !== PINNED_K6_VERSION) { @@ -6,3 +10,32 @@ export function requirePinnedK6Version(value) { } return value; } + +export function requirePinnedK6Runtime({ + version, + releaseAsset, + releaseAssetSha256, + runnerIdentity, + executableSha256, +}) { + requirePinnedK6Version(version); + if (releaseAsset !== PINNED_K6_RELEASE_ASSET) { + throw new Error(`commercial Employment separation performance runs require ${PINNED_K6_RELEASE_ASSET}`); + } + if (releaseAssetSha256 !== PINNED_K6_RELEASE_ASSET_SHA256) { + throw new Error("commercial Employment separation performance runs require the pinned upstream k6 release-asset SHA-256"); + } + if (runnerIdentity !== PINNED_K6_RUNNER_IDENTITY) { + throw new Error("commercial Employment separation performance runs require the pinned upstream k6 runner identity"); + } + if (typeof executableSha256 !== "string" || !SHA256_PATTERN.test(executableSha256)) { + throw new Error("commercial Employment separation performance runs require the extracted k6 executable SHA-256"); + } + return Object.freeze({ + version, + release_asset: releaseAsset, + release_asset_sha256: releaseAssetSha256, + runner_identity: runnerIdentity, + executable_sha256: executableSha256, + }); +} diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index e8b5508dc..3de296adb 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -2,20 +2,44 @@ import assert from "node:assert/strict"; import test from "node:test"; import { + PINNED_K6_RELEASE_ASSET, + PINNED_K6_RELEASE_ASSET_SHA256, + PINNED_K6_RUNNER_IDENTITY, PINNED_K6_VERSION, + requirePinnedK6Runtime, requirePinnedK6Version, } from "./employment_separation_k6_runtime_contract.mjs"; -test("accepts only the repository-pinned k6 runtime", () => { +const EXECUTABLE_SHA256 = "1".repeat(64); + +function validRuntime() { + return { + version: PINNED_K6_VERSION, + releaseAsset: PINNED_K6_RELEASE_ASSET, + releaseAssetSha256: PINNED_K6_RELEASE_ASSET_SHA256, + runnerIdentity: PINNED_K6_RUNNER_IDENTITY, + executableSha256: EXECUTABLE_SHA256, + }; +} + +test("accepts only the repository-pinned upstream k6 release artifact", () => { assert.equal(PINNED_K6_VERSION, "2.2.0"); assert.equal(requirePinnedK6Version("2.2.0"), "2.2.0"); + assert.deepEqual(requirePinnedK6Runtime(validRuntime()), { + version: PINNED_K6_VERSION, + release_asset: PINNED_K6_RELEASE_ASSET, + release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + runner_identity: PINNED_K6_RUNNER_IDENTITY, + executable_sha256: EXECUTABLE_SHA256, + }); }); -test("rejects missing, older, newer, or decorated k6 runtime declarations", () => { +test("rejects substituted versions, archives, digests, identities, and malformed executable hashes", () => { for (const value of ["", "2.1.0", "2.2.1", "2.3.0", "v2.2.0", "2.2.0-dev"]) { - assert.throws( - () => requirePinnedK6Version(value), - /require k6 2\.2\.0/, - ); + assert.throws(() => requirePinnedK6Version(value), /require k6 2\.2\.0/); } + assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), releaseAsset: "k6-substitute.tar.gz" }), /require k6-v2\.2\.0-linux-amd64\.tar\.gz/); + assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), releaseAssetSha256: "0".repeat(64) }), /release-asset SHA-256/); + assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), runnerIdentity: "upstream_release_archive:substitute" }), /runner identity/); + assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), executableSha256: "not-a-sha" }), /executable SHA-256/); }); diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 6436df36b..4091885c1 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -2,21 +2,57 @@ set -euo pipefail readonly PINNED_K6_VERSION="2.2.0" +readonly PINNED_K6_RELEASE_ASSET="k6-v2.2.0-linux-amd64.tar.gz" +readonly PINNED_K6_RELEASE_ASSET_SHA256="b5a8003c86f35f5cd5ceef1490312c48e587696c94d998cefc6d7b3b4cb1597d" +readonly PINNED_K6_RUNNER_IDENTITY="upstream_release_archive:${PINNED_K6_RELEASE_ASSET}@sha256:${PINNED_K6_RELEASE_ASSET_SHA256}" readonly WORKLOAD="tests/performance/employment_separation_buyer_path.js" -k6_bin="${K6_BIN:-k6}" -if ! command -v "${k6_bin}" >/dev/null 2>&1; then - printf 'pinned k6 runner is unavailable: %s\n' "${k6_bin}" >&2 +archive="${ORGMETRA_K6_RELEASE_ARCHIVE:-}" +if [[ -z "${archive}" || ! -f "${archive}" ]]; then + printf 'ORGMETRA_K6_RELEASE_ARCHIVE must point to the pinned upstream release archive\n' >&2 + exit 1 +fi +if [[ "$(uname -s)" != "Linux" || "$(uname -m)" != "x86_64" ]]; then + printf 'commercial Employment separation performance runner requires Linux x86_64 for %s\n' "${PINNED_K6_RELEASE_ASSET}" >&2 + exit 1 +fi +if ! command -v sha256sum >/dev/null 2>&1 || ! command -v tar >/dev/null 2>&1; then + printf 'sha256sum and tar are required to verify the pinned k6 release artifact\n' >&2 exit 1 fi +tmp_root="$(mktemp -d)" +trap 'rm -rf -- "${tmp_root}"' EXIT HUP INT TERM +archive_copy="${tmp_root}/${PINNED_K6_RELEASE_ASSET}" +cp -- "${archive}" "${archive_copy}" +observed_archive_sha256="$(sha256sum "${archive_copy}" | awk '{print $1}')" +if [[ "${observed_archive_sha256}" != "${PINNED_K6_RELEASE_ASSET_SHA256}" ]]; then + printf 'k6 release archive SHA-256 mismatch: expected %s, observed %s\n' \ + "${PINNED_K6_RELEASE_ASSET_SHA256}" "${observed_archive_sha256}" >&2 + exit 1 +fi + +extract_root="${tmp_root}/extract" +mkdir -p "${extract_root}" +tar -xzf "${archive_copy}" -C "${extract_root}" +mapfile -t k6_candidates < <(find "${extract_root}" -type f -name k6 -perm -u+x -print) +if [[ "${#k6_candidates[@]}" -ne 1 ]]; then + printf 'verified k6 archive must contain exactly one executable named k6; found %s\n' "${#k6_candidates[@]}" >&2 + exit 1 +fi +k6_bin="${k6_candidates[0]}" +observed_executable_sha256="$(sha256sum "${k6_bin}" | awk '{print $1}')" version_line="$(${k6_bin} version 2>&1 | head -n 1)" version_token="$(printf '%s\n' "${version_line}" | awk '{print $2}')" if [[ "${version_token}" != "v${PINNED_K6_VERSION}" ]]; then - printf 'commercial Employment separation performance runs require k6 v%s; observed: %s\n' \ + printf 'verified release archive must contain k6 v%s; observed: %s\n' \ "${PINNED_K6_VERSION}" "${version_line}" >&2 exit 1 fi export ORGMETRA_PERFORMANCE_K6_VERSION="${PINNED_K6_VERSION}" -exec "${k6_bin}" run "${WORKLOAD}" "$@" +export ORGMETRA_PERFORMANCE_K6_RELEASE_ASSET="${PINNED_K6_RELEASE_ASSET}" +export ORGMETRA_PERFORMANCE_K6_RELEASE_ASSET_SHA256="${PINNED_K6_RELEASE_ASSET_SHA256}" +export ORGMETRA_PERFORMANCE_K6_RUNNER_IDENTITY="${PINNED_K6_RUNNER_IDENTITY}" +export ORGMETRA_PERFORMANCE_K6_EXECUTABLE_SHA256="${observed_executable_sha256}" +"${k6_bin}" run "${WORKLOAD}" "$@" From 9ee37da8ed5756844f0eebf667e2332053f0b90d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 18:18:34 +0900 Subject: [PATCH 120/269] test(perf): pin k6 OCI runner digest --- .../employment_separation_buyer_path.js | 108 ++++-------------- ...oyment_separation_k6_evidence_contract.mjs | 59 +++------- ...t_separation_k6_evidence_contract.test.mjs | 46 +++----- ...loyment_separation_k6_runtime_contract.mjs | 33 ++---- ...nt_separation_k6_runtime_contract.test.mjs | 27 ++--- .../run_employment_separation_benchmark.sh | 87 +++++++------- 6 files changed, 125 insertions(+), 235 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 7e73c1634..522514b84 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -34,10 +34,9 @@ const selectedProfile = requirePerformanceProfile(__ENV.ORGMETRA_PERFORMANCE_PRO const clientNetworkTopology = requireDirectPerformanceClientNetwork(__ENV); const k6Runtime = requirePinnedK6Runtime({ version: __ENV.ORGMETRA_PERFORMANCE_K6_VERSION || "", - releaseAsset: __ENV.ORGMETRA_PERFORMANCE_K6_RELEASE_ASSET || "", - releaseAssetSha256: __ENV.ORGMETRA_PERFORMANCE_K6_RELEASE_ASSET_SHA256 || "", + image: __ENV.ORGMETRA_PERFORMANCE_K6_IMAGE || "", + imageDigest: __ENV.ORGMETRA_PERFORMANCE_K6_IMAGE_DIGEST || "", runnerIdentity: __ENV.ORGMETRA_PERFORMANCE_K6_RUNNER_IDENTITY || "", - executableSha256: __ENV.ORGMETRA_PERFORMANCE_K6_EXECUTABLE_SHA256 || "", }); if (!fixturePath) fail("ORGMETRA_PERFORMANCE_DATA_FILE is required"); @@ -48,34 +47,22 @@ if (!/^[0-9a-f]{40}$/.test(targetSha)) fail("ORGMETRA_PERFORMANCE_TARGET_SHA mus const fixtureBytes = open(fixturePath, "b"); const fixtureSha256 = crypto.sha256(fixtureBytes, "hex"); let fixtureText; -try { - fixtureText = new TextDecoder("utf-8", { fatal: true }).decode(fixtureBytes); -} catch (_) { - fail("performance fixture must be valid UTF-8"); -} +try { fixtureText = new TextDecoder("utf-8", { fatal: true }).decode(fixtureBytes); } +catch (_) { fail("performance fixture must be valid UTF-8"); } let fixtureDocument; -try { - fixtureDocument = JSON.parse(fixtureText); -} catch (_) { - fail("performance fixture must be valid JSON"); -} +try { fixtureDocument = JSON.parse(fixtureText); } +catch (_) { fail("performance fixture must be valid JSON"); } const fixture = validatePerformanceFixture(fixtureDocument, { minimumNonContendingRecords: MINIMUM_NON_CONTENDING_RECORDS, minimumContentionPairs: MINIMUM_CONTENTION_PAIRS, }); -if (fixture.candidate_sha.toLowerCase() !== targetSha) { - fail("performance fixture candidate_sha does not match ORGMETRA_PERFORMANCE_TARGET_SHA"); -} +if (fixture.candidate_sha.toLowerCase() !== targetSha) fail("performance fixture candidate_sha does not match ORGMETRA_PERFORMANCE_TARGET_SHA"); function requiredPositiveIntegerSetting(name) { const raw = __ENV[name]; - if (raw === undefined || raw === "" || !/^\d+$/.test(raw)) { - fail(`${name} must be an explicit positive integer`); - } + if (raw === undefined || raw === "" || !/^\d+$/.test(raw)) fail(`${name} must be an explicit positive integer`); const value = Number(raw); - if (!Number.isSafeInteger(value) || value < 1) { - fail(`${name} must be an explicit positive safe integer`); - } + if (!Number.isSafeInteger(value) || value < 1) fail(`${name} must be an explicit positive safe integer`); return value; } @@ -85,11 +72,7 @@ const durationSeconds = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_DUR const preAllocatedVUs = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_PREALLOCATED_VUS"); const maxVUs = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_MAX_VUS"); const selectedScenario = arrivalRateScenarioForPerformanceProfile(selectedProfile, { - expectedIterations: selectedRecords.length, - targetRps, - durationSeconds, - preAllocatedVUs, - maxVUs, + expectedIterations: selectedRecords.length, targetRps, durationSeconds, preAllocatedVUs, maxVUs, }); const firstCommitDuration = new Trend("employment_separation_first_commit_duration_ms", true); @@ -112,81 +95,42 @@ function recordAt(profile) { if (index < 0 || index >= records.length) fail(`${profile} iteration ${index} is outside the fixture`); return records[index]; } - -function parseJson(response) { - try { - return response.json(); - } catch (_) { - return null; - } -} - +function parseJson(response) { try { return response.json(); } catch (_) { return null; } } function post(command, profile) { - return http.post(`${baseUrl}${ROUTE}`, requestBody(command), { - headers: requestHeaders(command, bearerToken), - tags: { profile }, - }); + return http.post(`${baseUrl}${ROUTE}`, requestBody(command), { headers: requestHeaders(command, bearerToken), tags: { profile } }); } - function observe(response, trend, profile, predicate) { trend.add(buyerPathElapsedMs(response.timings), { profile }); latencySamples.add(1, { profile }); - const passed = check(response, { - [`${profile} returned the governed result`]: predicate, - }); + const passed = check(response, { [`${profile} returned the governed result`]: predicate }); unexpectedResponse.add(!passed, { profile }); } export function firstCommit() { const command = recordAt("first_commit"); const response = post(command, "first_commit"); - observe(response, firstCommitDuration, "first_commit", (result) => ( - isGovernedSeparationSuccess(result.status, parseJson(result), { - employmentRecordId: command.payload.employment_record_id, - replayed: false, - }) - )); + observe(response, firstCommitDuration, "first_commit", (result) => isGovernedSeparationSuccess(result.status, parseJson(result), { employmentRecordId: command.payload.employment_record_id, replayed: false })); } - export function replay() { const command = recordAt("replay"); const response = post(command, "replay"); - observe(response, replayDuration, "replay", (result) => ( - isGovernedSeparationSuccess(result.status, parseJson(result), { - employmentRecordId: command.payload.employment_record_id, - replayed: true, - }) - )); + observe(response, replayDuration, "replay", (result) => isGovernedSeparationSuccess(result.status, parseJson(result), { employmentRecordId: command.payload.employment_record_id, replayed: true })); } - export function rejection() { const response = post(recordAt("rejection"), "rejection"); - observe(response, rejectionDuration, "rejection", (result) => ( - isGovernedSeparationConflict(result.status, parseJson(result)) - )); + observe(response, rejectionDuration, "rejection", (result) => isGovernedSeparationConflict(result.status, parseJson(result))); } - export function contention() { const pair = recordAt("contention"); const responses = http.batch([ ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.left), { headers: requestHeaders(pair.left, bearerToken), tags: { profile: "contention" } }], ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.right), { headers: requestHeaders(pair.right, bearerToken), tags: { profile: "contention" } }], ]); - for (const response of responses) { - contentionDuration.add(buyerPathElapsedMs(response.timings), { profile: "contention" }); - latencySamples.add(1, { profile: "contention" }); - } + for (const response of responses) { contentionDuration.add(buyerPathElapsedMs(response.timings), { profile: "contention" }); latencySamples.add(1, { profile: "contention" }); } const parsed = responses.map((response) => ({ status: response.status, body: parseJson(response) })); - const successes = parsed.filter(({ status, body }) => ( - isGovernedSeparationSuccess(status, body, { - employmentRecordId: pair.left.payload.employment_record_id, - replayed: false, - }) - )); + const successes = parsed.filter(({ status, body }) => isGovernedSeparationSuccess(status, body, { employmentRecordId: pair.left.payload.employment_record_id, replayed: false })); const conflicts = parsed.filter(({ status, body }) => isGovernedSeparationConflict(status, body)); - const passed = check(parsed, { - "contention serializes one governed commit and one governed conflict": () => successes.length === 1 && conflicts.length === 1, - }); + const passed = check(parsed, { "contention serializes one governed commit and one governed conflict": () => successes.length === 1 && conflicts.length === 1 }); unexpectedResponse.add(!passed, { profile: "contention" }); } @@ -197,23 +141,15 @@ export function handleSummary(data) { candidate_sha: targetSha, fixture_sha256: fixtureSha256, k6_version: k6Runtime.version, - k6_release_asset: k6Runtime.release_asset, - k6_release_asset_sha256: k6Runtime.release_asset_sha256, + k6_image: k6Runtime.image, + k6_image_digest: k6Runtime.image_digest, k6_runner_identity: k6Runtime.runner_identity, - k6_executable_sha256: k6Runtime.executable_sha256, selected_profile: selectedProfile, expected_iterations: selectedRecords.length, completed_iterations: completedIterations, sample_complete: completedIterations === selectedRecords.length, completed_at: new Date().toISOString(), - load_model: { - executor: selectedScenario.executor, - target_rps: targetRps, - duration_seconds: durationSeconds, - preallocated_vus: preAllocatedVUs, - max_vus: maxVUs, - client_network_topology: clientNetworkTopology, - }, + load_model: { executor: selectedScenario.executor, target_rps: targetRps, duration_seconds: durationSeconds, preallocated_vus: preAllocatedVUs, max_vus: maxVUs, client_network_topology: clientNetworkTopology }, dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, preparation_protocol_reference: fixture.preparation_protocol_reference, diff --git a/tests/performance/employment_separation_k6_evidence_contract.mjs b/tests/performance/employment_separation_k6_evidence_contract.mjs index ecf7a6e0b..bbff86789 100644 --- a/tests/performance/employment_separation_k6_evidence_contract.mjs +++ b/tests/performance/employment_separation_k6_evidence_contract.mjs @@ -1,48 +1,32 @@ import { TextDecoder } from "node:util"; import { - PINNED_K6_RELEASE_ASSET, - PINNED_K6_RELEASE_ASSET_SHA256, + PINNED_K6_IMAGE, + PINNED_K6_IMAGE_DIGEST, PINNED_K6_RUNNER_IDENTITY, PINNED_K6_VERSION, requirePinnedK6Runtime, } from "./employment_separation_k6_runtime_contract.mjs"; -function fail(message) { - throw new Error(message); -} +function fail(message) { throw new Error(message); } function parseResultBytes(value) { - if (!(value instanceof Uint8Array) && !(value instanceof ArrayBuffer)) { - fail("performance result must be supplied as raw bytes"); - } + if (!(value instanceof Uint8Array) && !(value instanceof ArrayBuffer)) fail("performance result must be supplied as raw bytes"); const bytes = value instanceof Uint8Array ? value : new Uint8Array(value); let text; - try { - text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); - } catch (error) { - throw new Error("performance result must be valid UTF-8", { cause: error }); - } + try { text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); } + catch (error) { throw new Error("performance result must be valid UTF-8", { cause: error }); } let result; - try { - result = JSON.parse(text); - } catch (error) { - throw new Error("performance result must be valid JSON", { cause: error }); - } - if (result === null || typeof result !== "object" || Array.isArray(result)) { - fail("performance result must be an object"); - } + try { result = JSON.parse(text); } + catch (error) { throw new Error("performance result must be valid JSON", { cause: error }); } + if (result === null || typeof result !== "object" || Array.isArray(result)) fail("performance result must be an object"); return result; } function runtimeField(runtime, name) { - if (runtime === null || typeof runtime !== "object" || Array.isArray(runtime)) { - fail("runtime evidence must be an object"); - } + if (runtime === null || typeof runtime !== "object" || Array.isArray(runtime)) fail("runtime evidence must be an object"); const value = runtime[name]; - if (typeof value !== "string" || value === "") { - fail(`runtime.${name} must be a non-empty string`); - } + if (typeof value !== "string" || value === "") fail(`runtime.${name} must be a non-empty string`); return value; } @@ -50,28 +34,23 @@ export function validatePinnedK6AcceptanceEvidence(resultArtifact, runtimeEviden const result = parseResultBytes(resultArtifact); const resultRuntime = requirePinnedK6Runtime({ version: result.k6_version, - releaseAsset: result.k6_release_asset, - releaseAssetSha256: result.k6_release_asset_sha256, + image: result.k6_image, + imageDigest: result.k6_image_digest, runnerIdentity: result.k6_runner_identity, - executableSha256: result.k6_executable_sha256, }); const observedRuntime = requirePinnedK6Runtime({ version: runtimeField(runtimeEvidence, "observed_k6_version"), - releaseAsset: runtimeField(runtimeEvidence, "observed_k6_release_asset"), - releaseAssetSha256: runtimeField(runtimeEvidence, "observed_k6_release_asset_sha256"), + image: runtimeField(runtimeEvidence, "observed_k6_image"), + imageDigest: runtimeField(runtimeEvidence, "observed_k6_image_digest"), runnerIdentity: runtimeField(runtimeEvidence, "observed_k6_runner_identity"), - executableSha256: runtimeField(runtimeEvidence, "observed_k6_executable_sha256"), }); - for (const field of ["version", "release_asset", "release_asset_sha256", "runner_identity", "executable_sha256"]) { - if (resultRuntime[field] !== observedRuntime[field]) { - fail(`runtime observed k6 ${field} must match the performance result`); - } + for (const field of ["version", "image", "image_digest", "runner_identity"]) { + if (resultRuntime[field] !== observedRuntime[field]) fail(`runtime observed k6 ${field} must match the performance result`); } return Object.freeze({ k6_version: PINNED_K6_VERSION, - k6_release_asset: PINNED_K6_RELEASE_ASSET, - k6_release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + k6_image: PINNED_K6_IMAGE, + k6_image_digest: PINNED_K6_IMAGE_DIGEST, k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, - k6_executable_sha256: resultRuntime.executable_sha256, }); } diff --git a/tests/performance/employment_separation_k6_evidence_contract.test.mjs b/tests/performance/employment_separation_k6_evidence_contract.test.mjs index 4b7ec583c..8226a3586 100644 --- a/tests/performance/employment_separation_k6_evidence_contract.test.mjs +++ b/tests/performance/employment_separation_k6_evidence_contract.test.mjs @@ -2,64 +2,46 @@ import assert from "node:assert/strict"; import test from "node:test"; import { - PINNED_K6_RELEASE_ASSET, - PINNED_K6_RELEASE_ASSET_SHA256, + PINNED_K6_IMAGE, + PINNED_K6_IMAGE_DIGEST, PINNED_K6_RUNNER_IDENTITY, PINNED_K6_VERSION, } from "./employment_separation_k6_runtime_contract.mjs"; import { validatePinnedK6AcceptanceEvidence } from "./employment_separation_k6_evidence_contract.mjs"; -const EXECUTABLE_SHA256 = "1".repeat(64); - function resultBytes(overrides = {}) { return Buffer.from(`${JSON.stringify({ k6_version: PINNED_K6_VERSION, - k6_release_asset: PINNED_K6_RELEASE_ASSET, - k6_release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + k6_image: PINNED_K6_IMAGE, + k6_image_digest: PINNED_K6_IMAGE_DIGEST, k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, - k6_executable_sha256: EXECUTABLE_SHA256, ...overrides, })}\n`, "utf8"); } - function runtime(overrides = {}) { return { observed_k6_version: PINNED_K6_VERSION, - observed_k6_release_asset: PINNED_K6_RELEASE_ASSET, - observed_k6_release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + observed_k6_image: PINNED_K6_IMAGE, + observed_k6_image_digest: PINNED_K6_IMAGE_DIGEST, observed_k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, - observed_k6_executable_sha256: EXECUTABLE_SHA256, ...overrides, }; } -test("binds result runtime identity to independently observed pinned upstream k6 evidence", () => { +test("binds result identity to independently observed pinned upstream k6 OCI evidence", () => { assert.deepEqual(validatePinnedK6AcceptanceEvidence(resultBytes(), runtime()), { k6_version: PINNED_K6_VERSION, - k6_release_asset: PINNED_K6_RELEASE_ASSET, - k6_release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + k6_image: PINNED_K6_IMAGE, + k6_image_digest: PINNED_K6_IMAGE_DIGEST, k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, - k6_executable_sha256: EXECUTABLE_SHA256, }); }); -test("rejects a result that merely self-declares the right version with a substituted archive", () => { - assert.throws( - () => validatePinnedK6AcceptanceEvidence(resultBytes({ k6_release_asset_sha256: "0".repeat(64) }), runtime()), - /release-asset SHA-256/, - ); -}); - -test("rejects runtime observation that does not identify the exact pinned runner", () => { - assert.throws( - () => validatePinnedK6AcceptanceEvidence(resultBytes(), runtime({ observed_k6_runner_identity: "upstream_release_archive:substitute" })), - /runner identity/, - ); +test("rejects matching-but-unpinned image digests in result evidence", () => { + const fake = `sha256:${"0".repeat(64)}`; + assert.throws(() => validatePinnedK6AcceptanceEvidence(resultBytes({ k6_image_digest: fake }), runtime({ observed_k6_image_digest: fake })), /OCI image digest/); }); -test("rejects an independently observed executable digest that differs from the result", () => { - assert.throws( - () => validatePinnedK6AcceptanceEvidence(resultBytes(), runtime({ observed_k6_executable_sha256: "2".repeat(64) })), - /executable_sha256 must match/, - ); +test("rejects runtime observation that does not identify the exact pinned image", () => { + assert.throws(() => validatePinnedK6AcceptanceEvidence(resultBytes(), runtime({ observed_k6_runner_identity: "ghcr.io/grafana/k6@sha256:substitute" })), /runner identity/); }); diff --git a/tests/performance/employment_separation_k6_runtime_contract.mjs b/tests/performance/employment_separation_k6_runtime_contract.mjs index 0e994fdfa..058917c29 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.mjs @@ -1,8 +1,7 @@ export const PINNED_K6_VERSION = "2.2.0"; -export const PINNED_K6_RELEASE_ASSET = "k6-v2.2.0-linux-amd64.tar.gz"; -export const PINNED_K6_RELEASE_ASSET_SHA256 = "b5a8003c86f35f5cd5ceef1490312c48e587696c94d998cefc6d7b3b4cb1597d"; -export const PINNED_K6_RUNNER_IDENTITY = `upstream_release_archive:${PINNED_K6_RELEASE_ASSET}@sha256:${PINNED_K6_RELEASE_ASSET_SHA256}`; -const SHA256_PATTERN = /^[0-9a-f]{64}$/; +export const PINNED_K6_IMAGE = "ghcr.io/grafana/k6"; +export const PINNED_K6_IMAGE_DIGEST = "sha256:9bd01d6941fca969cb61bb57d2da5ee9b385fe2aa8881df3798c196564d6ace6"; +export const PINNED_K6_RUNNER_IDENTITY = `${PINNED_K6_IMAGE}@${PINNED_K6_IMAGE_DIGEST}`; export function requirePinnedK6Version(value) { if (value !== PINNED_K6_VERSION) { @@ -11,31 +10,21 @@ export function requirePinnedK6Version(value) { return value; } -export function requirePinnedK6Runtime({ - version, - releaseAsset, - releaseAssetSha256, - runnerIdentity, - executableSha256, -}) { +export function requirePinnedK6Runtime({ version, image, imageDigest, runnerIdentity }) { requirePinnedK6Version(version); - if (releaseAsset !== PINNED_K6_RELEASE_ASSET) { - throw new Error(`commercial Employment separation performance runs require ${PINNED_K6_RELEASE_ASSET}`); + if (image !== PINNED_K6_IMAGE) { + throw new Error(`commercial Employment separation performance runs require ${PINNED_K6_IMAGE}`); } - if (releaseAssetSha256 !== PINNED_K6_RELEASE_ASSET_SHA256) { - throw new Error("commercial Employment separation performance runs require the pinned upstream k6 release-asset SHA-256"); + if (imageDigest !== PINNED_K6_IMAGE_DIGEST) { + throw new Error("commercial Employment separation performance runs require the pinned upstream k6 OCI image digest"); } if (runnerIdentity !== PINNED_K6_RUNNER_IDENTITY) { - throw new Error("commercial Employment separation performance runs require the pinned upstream k6 runner identity"); - } - if (typeof executableSha256 !== "string" || !SHA256_PATTERN.test(executableSha256)) { - throw new Error("commercial Employment separation performance runs require the extracted k6 executable SHA-256"); + throw new Error("commercial Employment separation performance runs require the pinned upstream k6 OCI runner identity"); } return Object.freeze({ version, - release_asset: releaseAsset, - release_asset_sha256: releaseAssetSha256, + image, + image_digest: imageDigest, runner_identity: runnerIdentity, - executable_sha256: executableSha256, }); } diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index 3de296adb..23989157d 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -2,44 +2,39 @@ import assert from "node:assert/strict"; import test from "node:test"; import { - PINNED_K6_RELEASE_ASSET, - PINNED_K6_RELEASE_ASSET_SHA256, + PINNED_K6_IMAGE, + PINNED_K6_IMAGE_DIGEST, PINNED_K6_RUNNER_IDENTITY, PINNED_K6_VERSION, requirePinnedK6Runtime, requirePinnedK6Version, } from "./employment_separation_k6_runtime_contract.mjs"; -const EXECUTABLE_SHA256 = "1".repeat(64); - function validRuntime() { return { version: PINNED_K6_VERSION, - releaseAsset: PINNED_K6_RELEASE_ASSET, - releaseAssetSha256: PINNED_K6_RELEASE_ASSET_SHA256, + image: PINNED_K6_IMAGE, + imageDigest: PINNED_K6_IMAGE_DIGEST, runnerIdentity: PINNED_K6_RUNNER_IDENTITY, - executableSha256: EXECUTABLE_SHA256, }; } -test("accepts only the repository-pinned upstream k6 release artifact", () => { +test("accepts only the repository-pinned upstream k6 OCI image", () => { assert.equal(PINNED_K6_VERSION, "2.2.0"); assert.equal(requirePinnedK6Version("2.2.0"), "2.2.0"); assert.deepEqual(requirePinnedK6Runtime(validRuntime()), { version: PINNED_K6_VERSION, - release_asset: PINNED_K6_RELEASE_ASSET, - release_asset_sha256: PINNED_K6_RELEASE_ASSET_SHA256, + image: PINNED_K6_IMAGE, + image_digest: PINNED_K6_IMAGE_DIGEST, runner_identity: PINNED_K6_RUNNER_IDENTITY, - executable_sha256: EXECUTABLE_SHA256, }); }); -test("rejects substituted versions, archives, digests, identities, and malformed executable hashes", () => { +test("rejects substituted versions, images, digests, and runner identities", () => { for (const value of ["", "2.1.0", "2.2.1", "2.3.0", "v2.2.0", "2.2.0-dev"]) { assert.throws(() => requirePinnedK6Version(value), /require k6 2\.2\.0/); } - assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), releaseAsset: "k6-substitute.tar.gz" }), /require k6-v2\.2\.0-linux-amd64\.tar\.gz/); - assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), releaseAssetSha256: "0".repeat(64) }), /release-asset SHA-256/); - assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), runnerIdentity: "upstream_release_archive:substitute" }), /runner identity/); - assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), executableSha256: "not-a-sha" }), /executable SHA-256/); + assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), image: "example.invalid/k6" }), /require ghcr\.io\/grafana\/k6/); + assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), imageDigest: `sha256:${"0".repeat(64)}` }), /OCI image digest/); + assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), runnerIdentity: "ghcr.io/grafana/k6@sha256:substitute" }), /runner identity/); }); diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 4091885c1..a298fab0b 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -2,57 +2,66 @@ set -euo pipefail readonly PINNED_K6_VERSION="2.2.0" -readonly PINNED_K6_RELEASE_ASSET="k6-v2.2.0-linux-amd64.tar.gz" -readonly PINNED_K6_RELEASE_ASSET_SHA256="b5a8003c86f35f5cd5ceef1490312c48e587696c94d998cefc6d7b3b4cb1597d" -readonly PINNED_K6_RUNNER_IDENTITY="upstream_release_archive:${PINNED_K6_RELEASE_ASSET}@sha256:${PINNED_K6_RELEASE_ASSET_SHA256}" -readonly WORKLOAD="tests/performance/employment_separation_buyer_path.js" +readonly PINNED_K6_IMAGE="ghcr.io/grafana/k6" +readonly PINNED_K6_IMAGE_DIGEST="sha256:9bd01d6941fca969cb61bb57d2da5ee9b385fe2aa8881df3798c196564d6ace6" +readonly PINNED_K6_RUNNER_IDENTITY="${PINNED_K6_IMAGE}@${PINNED_K6_IMAGE_DIGEST}" +readonly WORKLOAD="/workspace/tests/performance/employment_separation_buyer_path.js" -archive="${ORGMETRA_K6_RELEASE_ARCHIVE:-}" -if [[ -z "${archive}" || ! -f "${archive}" ]]; then - printf 'ORGMETRA_K6_RELEASE_ARCHIVE must point to the pinned upstream release archive\n' >&2 +if ! command -v podman >/dev/null 2>&1; then + printf 'podman is required for the pinned commercial k6 runner\n' >&2 exit 1 fi -if [[ "$(uname -s)" != "Linux" || "$(uname -m)" != "x86_64" ]]; then - printf 'commercial Employment separation performance runner requires Linux x86_64 for %s\n' "${PINNED_K6_RELEASE_ASSET}" >&2 +if ! podman image exists "${PINNED_K6_RUNNER_IDENTITY}"; then + printf 'preload the exact pinned k6 image before measurement: %s\n' "${PINNED_K6_RUNNER_IDENTITY}" >&2 exit 1 fi -if ! command -v sha256sum >/dev/null 2>&1 || ! command -v tar >/dev/null 2>&1; then - printf 'sha256sum and tar are required to verify the pinned k6 release artifact\n' >&2 - exit 1 -fi - -tmp_root="$(mktemp -d)" -trap 'rm -rf -- "${tmp_root}"' EXIT HUP INT TERM -archive_copy="${tmp_root}/${PINNED_K6_RELEASE_ASSET}" -cp -- "${archive}" "${archive_copy}" -observed_archive_sha256="$(sha256sum "${archive_copy}" | awk '{print $1}')" -if [[ "${observed_archive_sha256}" != "${PINNED_K6_RELEASE_ASSET_SHA256}" ]]; then - printf 'k6 release archive SHA-256 mismatch: expected %s, observed %s\n' \ - "${PINNED_K6_RELEASE_ASSET_SHA256}" "${observed_archive_sha256}" >&2 +version_line="$(podman run --rm --pull=never "${PINNED_K6_RUNNER_IDENTITY}" version 2>&1 | head -n 1)" +version_token="$(printf '%s\n' "${version_line}" | awk '{print $2}')" +if [[ "${version_token}" != "v${PINNED_K6_VERSION}" ]]; then + printf 'pinned k6 image must report v%s; observed: %s\n' "${PINNED_K6_VERSION}" "${version_line}" >&2 exit 1 fi -extract_root="${tmp_root}/extract" -mkdir -p "${extract_root}" -tar -xzf "${archive_copy}" -C "${extract_root}" -mapfile -t k6_candidates < <(find "${extract_root}" -type f -name k6 -perm -u+x -print) -if [[ "${#k6_candidates[@]}" -ne 1 ]]; then - printf 'verified k6 archive must contain exactly one executable named k6; found %s\n' "${#k6_candidates[@]}" >&2 +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" +fixture_path="${ORGMETRA_PERFORMANCE_DATA_FILE:-}" +summary_path="${ORGMETRA_PERFORMANCE_SUMMARY_FILE:-}" +if [[ -z "${fixture_path}" || ! -f "${fixture_path}" ]]; then + printf 'ORGMETRA_PERFORMANCE_DATA_FILE must point to the right-cleared fixture\n' >&2 exit 1 fi -k6_bin="${k6_candidates[0]}" -observed_executable_sha256="$(sha256sum "${k6_bin}" | awk '{print $1}')" -version_line="$(${k6_bin} version 2>&1 | head -n 1)" -version_token="$(printf '%s\n' "${version_line}" | awk '{print $2}')" -if [[ "${version_token}" != "v${PINNED_K6_VERSION}" ]]; then - printf 'verified release archive must contain k6 v%s; observed: %s\n' \ - "${PINNED_K6_VERSION}" "${version_line}" >&2 +if [[ -z "${summary_path}" ]]; then + printf 'ORGMETRA_PERFORMANCE_SUMMARY_FILE is required\n' >&2 exit 1 fi +fixture_path="$(realpath "${fixture_path}")" +summary_dir="$(realpath -m "$(dirname "${summary_path}")")" +summary_name="$(basename "${summary_path}")" +mkdir -p "${summary_dir}" export ORGMETRA_PERFORMANCE_K6_VERSION="${PINNED_K6_VERSION}" -export ORGMETRA_PERFORMANCE_K6_RELEASE_ASSET="${PINNED_K6_RELEASE_ASSET}" -export ORGMETRA_PERFORMANCE_K6_RELEASE_ASSET_SHA256="${PINNED_K6_RELEASE_ASSET_SHA256}" +export ORGMETRA_PERFORMANCE_K6_IMAGE="${PINNED_K6_IMAGE}" +export ORGMETRA_PERFORMANCE_K6_IMAGE_DIGEST="${PINNED_K6_IMAGE_DIGEST}" export ORGMETRA_PERFORMANCE_K6_RUNNER_IDENTITY="${PINNED_K6_RUNNER_IDENTITY}" -export ORGMETRA_PERFORMANCE_K6_EXECUTABLE_SHA256="${observed_executable_sha256}" -"${k6_bin}" run "${WORKLOAD}" "$@" + +podman run --rm --pull=never --network=host --read-only \ + --cap-drop=ALL --security-opt=no-new-privileges --pids-limit=256 \ + --tmpfs /tmp:rw,nosuid,nodev,noexec \ + --volume "${repo_root}:/workspace:ro" \ + --volume "${fixture_path}:/evidence/fixture.json:ro" \ + --volume "${summary_dir}:/output:rw" \ + --workdir /workspace \ + --env ORGMETRA_PERFORMANCE_BASE_URL \ + --env ORGMETRA_PERFORMANCE_BEARER_TOKEN \ + --env ORGMETRA_PERFORMANCE_TARGET_SHA \ + --env ORGMETRA_PERFORMANCE_PROFILE \ + --env ORGMETRA_PERFORMANCE_TARGET_RPS \ + --env ORGMETRA_PERFORMANCE_DURATION_SECONDS \ + --env ORGMETRA_PERFORMANCE_PREALLOCATED_VUS \ + --env ORGMETRA_PERFORMANCE_MAX_VUS \ + --env ORGMETRA_PERFORMANCE_K6_VERSION \ + --env ORGMETRA_PERFORMANCE_K6_IMAGE \ + --env ORGMETRA_PERFORMANCE_K6_IMAGE_DIGEST \ + --env ORGMETRA_PERFORMANCE_K6_RUNNER_IDENTITY \ + --env ORGMETRA_PERFORMANCE_DATA_FILE=/evidence/fixture.json \ + --env "ORGMETRA_PERFORMANCE_SUMMARY_FILE=/output/${summary_name}" \ + "${PINNED_K6_RUNNER_IDENTITY}" run "${WORKLOAD}" "$@" From 5244a59065c8acb4683b31194b4580e4b1f12df9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:03:40 +0900 Subject: [PATCH 121/269] test(perf): reject benchmark CLI overrides --- ...oyment_separation_k6_runtime_contract.test.mjs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index 23989157d..21a167cb4 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -1,4 +1,5 @@ import assert from "node:assert/strict"; +import { readFileSync } from "node:fs"; import test from "node:test"; import { @@ -38,3 +39,17 @@ test("rejects substituted versions, images, digests, and runner identities", () assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), imageDigest: `sha256:${"0".repeat(64)}` }), /OCI image digest/); assert.throws(() => requirePinnedK6Runtime({ ...validRuntime(), runnerIdentity: "ghcr.io/grafana/k6@sha256:substitute" }), /runner identity/); }); + +test("canonical benchmark runner does not accept ungoverned k6 CLI overrides", () => { + const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); + assert.doesNotMatch( + runner, + /"\$@"/, + "arbitrary k6 CLI flags can override version-controlled script options and __ENV inputs", + ); + assert.match( + runner, + /"\$\{PINNED_K6_RUNNER_IDENTITY\}" run "\$\{WORKLOAD\}"\s*$/m, + "commercial measurement must end at the version-controlled workload without caller-supplied k6 flags", + ); +}); From 00a4b60e48f930a934de4ce3e3ab4638f9d08405 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:04:48 +0900 Subject: [PATCH 122/269] fix(perf): seal k6 runner CLI surface --- tests/performance/run_employment_separation_benchmark.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index a298fab0b..e7949515b 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -7,6 +7,10 @@ readonly PINNED_K6_IMAGE_DIGEST="sha256:9bd01d6941fca969cb61bb57d2da5ee9b385fe2a readonly PINNED_K6_RUNNER_IDENTITY="${PINNED_K6_IMAGE}@${PINNED_K6_IMAGE_DIGEST}" readonly WORKLOAD="/workspace/tests/performance/employment_separation_buyer_path.js" +if (( $# != 0 )); then + printf 'commercial Employment separation benchmark does not accept caller-supplied k6 CLI options\n' >&2 + exit 64 +fi if ! command -v podman >/dev/null 2>&1; then printf 'podman is required for the pinned commercial k6 runner\n' >&2 exit 1 @@ -64,4 +68,4 @@ podman run --rm --pull=never --network=host --read-only \ --env ORGMETRA_PERFORMANCE_K6_RUNNER_IDENTITY \ --env ORGMETRA_PERFORMANCE_DATA_FILE=/evidence/fixture.json \ --env "ORGMETRA_PERFORMANCE_SUMMARY_FILE=/output/${summary_name}" \ - "${PINNED_K6_RUNNER_IDENTITY}" run "${WORKLOAD}" "$@" + "${PINNED_K6_RUNNER_IDENTITY}" run "${WORKLOAD}" From 61d18251fe86ece5755e2ea320bb03cc3afeca31 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:09:18 +0900 Subject: [PATCH 123/269] test(perf): exercise k6 CLI fail-closed guard --- ...mployment_separation_k6_runtime_contract.test.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index 21a167cb4..df264f94e 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -1,5 +1,7 @@ import assert from "node:assert/strict"; +import { spawnSync } from "node:child_process"; import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; import test from "node:test"; import { @@ -53,3 +55,13 @@ test("canonical benchmark runner does not accept ungoverned k6 CLI overrides", ( "commercial measurement must end at the version-controlled workload without caller-supplied k6 flags", ); }); + +test("canonical benchmark runner rejects CLI overrides before any Podman dependency is needed", () => { + const runnerPath = fileURLToPath(new URL("./run_employment_separation_benchmark.sh", import.meta.url)); + const result = spawnSync("bash", [runnerPath, "--duration", "1s"], { + encoding: "utf8", + env: { PATH: process.env.PATH ?? "" }, + }); + assert.equal(result.status, 64); + assert.match(result.stderr, /does not accept caller-supplied k6 CLI options/); +}); From b793d9e1cd4b6a34b096fdc764a964934d23634d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:15:31 +0900 Subject: [PATCH 124/269] test(perf): require versioned profile load models --- ...mployment_separation_run_contract.test.mjs | 73 +++++++++---------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index fe5842d0d..6de1e2b88 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -4,6 +4,7 @@ import test from "node:test"; import { PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, PERFORMANCE_SUMMARY_TREND_STATS, + approvedPerformanceLoadModel, arrivalRateScenarioForPerformanceProfile, requireDirectPerformanceClientNetwork, requirePerformanceProfile, @@ -19,13 +20,25 @@ test("requires one explicit performance profile per run", () => { assert.throws(() => requirePerformanceProfile("all"), /must be exactly one of/); }); -test("uses an open arrival-rate model whose schedule is independent of response time", () => { +test("uses one version-controlled open arrival-rate model per profile", () => { + assert.deepEqual(approvedPerformanceLoadModel("first_commit"), { + executor: "constant-arrival-rate", + target_rps: 20, + duration_seconds: 50, + preallocated_vus: 20, + max_vus: 80, + client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + }); + assert.deepEqual(approvedPerformanceLoadModel("contention"), { + executor: "constant-arrival-rate", + target_rps: 10, + duration_seconds: 10, + preallocated_vus: 20, + max_vus: 80, + client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + }); assert.deepEqual(arrivalRateScenarioForPerformanceProfile("first_commit", { expectedIterations: 1000, - targetRps: 20, - durationSeconds: 50, - preAllocatedVUs: 20, - maxVUs: 80, }), { executor: "constant-arrival-rate", exec: "firstCommit", @@ -38,47 +51,29 @@ test("uses an open arrival-rate model whose schedule is independent of response }); }); -test("refuses arrival schedules that can hide load or outrun fixture cardinality", () => { +test("refuses fixture cardinality that does not exactly fit the approved schedule", () => { assert.throws(() => arrivalRateScenarioForPerformanceProfile("first_commit", { - expectedIterations: 1000, - targetRps: 20, - durationSeconds: 49, - preAllocatedVUs: 20, - maxVUs: 80, + expectedIterations: 999, }), /must equal expectedIterations exactly/); assert.throws(() => arrivalRateScenarioForPerformanceProfile("contention", { - expectedIterations: 100, - targetRps: 10, - durationSeconds: 10, - preAllocatedVUs: 20, - maxVUs: 10, - }), /greater than or equal/); + expectedIterations: 99, + }), /must equal expectedIterations exactly/); }); -test("binds result evidence to the exact open load model", () => { - assert.deepEqual(validatePerformanceLoadModel({ - executor: "constant-arrival-rate", - target_rps: 20, - duration_seconds: 50, - preallocated_vus: 20, - max_vus: 80, - client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, - }, 1000), { - executor: "constant-arrival-rate", - target_rps: 20, - duration_seconds: 50, - preallocated_vus: 20, - max_vus: 80, - client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, - }); +test("binds result evidence to the exact approved profile load model", () => { + const approved = approvedPerformanceLoadModel("first_commit"); + assert.deepEqual(validatePerformanceLoadModel(approved, 1000, "first_commit"), approved); assert.throws(() => validatePerformanceLoadModel({ + ...approved, + target_rps: 1, + duration_seconds: 1000, + preallocated_vus: 1, + max_vus: 1, + }, 1000, "first_commit"), /approved first_commit load model/); + assert.throws(() => validatePerformanceLoadModel({ + ...approved, executor: "shared-iterations", - target_rps: 20, - duration_seconds: 50, - preallocated_vus: 20, - max_vus: 80, - client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, - }, 1000), /constant-arrival-rate/); + }, 1000, "first_commit"), /constant-arrival-rate/); }); test("fails closed when the k6 client is routed through an ambient proxy", () => { From a4d3362faf72f2adfb4be1aa2d788a6c2e8f069a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:15:49 +0900 Subject: [PATCH 125/269] test(perf): reject caller load-model environment --- ...mployment_separation_k6_runtime_contract.test.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index df264f94e..ff53e5ad2 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -56,6 +56,18 @@ test("canonical benchmark runner does not accept ungoverned k6 CLI overrides", ( ); }); +test("canonical benchmark runner does not forward caller-controlled load-model environment", () => { + const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); + for (const name of [ + "ORGMETRA_PERFORMANCE_TARGET_RPS", + "ORGMETRA_PERFORMANCE_DURATION_SECONDS", + "ORGMETRA_PERFORMANCE_PREALLOCATED_VUS", + "ORGMETRA_PERFORMANCE_MAX_VUS", + ]) { + assert.doesNotMatch(runner, new RegExp(`--env ${name}(?:\\s|$)`), `${name} must be version-controlled by the workload`); + } +}); + test("canonical benchmark runner rejects CLI overrides before any Podman dependency is needed", () => { const runnerPath = fileURLToPath(new URL("./run_employment_separation_benchmark.sh", import.meta.url)); const result = spawnSync("bash", [runnerPath, "--duration", "1s"], { From b808f27c9a4f897fb827a670f68097ee0386bef9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:16:38 +0900 Subject: [PATCH 126/269] fix(perf): version control profile load models --- .../employment_separation_run_contract.mjs | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index d472c222b..8a747f333 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -21,6 +21,12 @@ const EXEC_BY_PROFILE = Object.freeze({ rejection: "rejection", contention: "contention", }); +const APPROVED_LOAD_BY_PROFILE = Object.freeze({ + first_commit: Object.freeze({ target_rps: 20, duration_seconds: 50, preallocated_vus: 20, max_vus: 80 }), + replay: Object.freeze({ target_rps: 20, duration_seconds: 50, preallocated_vus: 20, max_vus: 80 }), + rejection: Object.freeze({ target_rps: 20, duration_seconds: 50, preallocated_vus: 20, max_vus: 80 }), + contention: Object.freeze({ target_rps: 10, duration_seconds: 10, preallocated_vus: 20, max_vus: 80 }), +}); const PROXY_ENVIRONMENT_KEYS = Object.freeze([ "HTTP_PROXY", "HTTPS_PROXY", @@ -44,6 +50,19 @@ function positiveInteger(value, label) { return value; } +export function approvedPerformanceLoadModel(profile) { + const selectedProfile = requirePerformanceProfile(profile); + const approved = APPROVED_LOAD_BY_PROFILE[selectedProfile]; + return Object.freeze({ + executor: "constant-arrival-rate", + target_rps: approved.target_rps, + duration_seconds: approved.duration_seconds, + preallocated_vus: approved.preallocated_vus, + max_vus: approved.max_vus, + client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + }); +} + export function requireDirectPerformanceClientNetwork(environment) { if (environment === null || typeof environment !== "object" || Array.isArray(environment)) { throw new Error("performance client environment must be an object"); @@ -57,7 +76,7 @@ export function requireDirectPerformanceClientNetwork(environment) { return PERFORMANCE_CLIENT_NETWORK_TOPOLOGY; } -export function validatePerformanceLoadModel(value, expectedIterations) { +export function validatePerformanceLoadModel(value, expectedIterations, profile) { if (value === null || typeof value !== "object" || Array.isArray(value)) { throw new Error("load_model must be an object"); } @@ -79,6 +98,7 @@ export function validatePerformanceLoadModel(value, expectedIterations) { if (value.client_network_topology !== PERFORMANCE_CLIENT_NETWORK_TOPOLOGY) { throw new Error(`load_model.client_network_topology must be ${PERFORMANCE_CLIENT_NETWORK_TOPOLOGY}`); } + const selectedProfile = requirePerformanceProfile(profile); const iterations = positiveInteger(expectedIterations, "expectedIterations"); const rate = positiveInteger(value.target_rps, "load_model.target_rps"); const duration = positiveInteger(value.duration_seconds, "load_model.duration_seconds"); @@ -87,39 +107,26 @@ export function validatePerformanceLoadModel(value, expectedIterations) { if (maximum < preAllocated) { throw new Error("load_model.max_vus must be greater than or equal to load_model.preallocated_vus"); } + const approved = approvedPerformanceLoadModel(selectedProfile); + for (const field of ["target_rps", "duration_seconds", "preallocated_vus", "max_vus"]) { + if (value[field] !== approved[field]) { + throw new Error(`load_model.${field} must match the approved ${selectedProfile} load model`); + } + } const scheduledIterations = rate * duration; if (!Number.isSafeInteger(scheduledIterations) || scheduledIterations !== iterations) { throw new Error("load_model target_rps * duration_seconds must equal expectedIterations exactly"); } - return Object.freeze({ - executor: value.executor, - target_rps: rate, - duration_seconds: duration, - preallocated_vus: preAllocated, - max_vus: maximum, - client_network_topology: value.client_network_topology, - }); + return approved; } -export function arrivalRateScenarioForPerformanceProfile(profile, { - expectedIterations, - targetRps, - durationSeconds, - preAllocatedVUs, - maxVUs, -}) { - requirePerformanceProfile(profile); - const loadModel = validatePerformanceLoadModel({ - executor: "constant-arrival-rate", - target_rps: targetRps, - duration_seconds: durationSeconds, - preallocated_vus: preAllocatedVUs, - max_vus: maxVUs, - client_network_topology: PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, - }, expectedIterations); +export function arrivalRateScenarioForPerformanceProfile(profile, { expectedIterations }) { + const selectedProfile = requirePerformanceProfile(profile); + const approved = approvedPerformanceLoadModel(selectedProfile); + const loadModel = validatePerformanceLoadModel(approved, expectedIterations, selectedProfile); return { executor: loadModel.executor, - exec: EXEC_BY_PROFILE[profile], + exec: EXEC_BY_PROFILE[selectedProfile], rate: loadModel.target_rps, timeUnit: "1s", duration: `${loadModel.duration_seconds}s`, From ccae70e17c1e18d350afece073486b9f9d73f72e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:17:15 +0900 Subject: [PATCH 127/269] fix(perf): bind workload to approved load model --- .../employment_separation_buyer_path.js | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 522514b84..7a90665e1 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -16,6 +16,7 @@ import { } from "./employment_separation_response_contract.mjs"; import { PERFORMANCE_SUMMARY_TREND_STATS, + approvedPerformanceLoadModel, arrivalRateScenarioForPerformanceProfile, requireDirectPerformanceClientNetwork, requirePerformanceProfile, @@ -58,21 +59,10 @@ const fixture = validatePerformanceFixture(fixtureDocument, { }); if (fixture.candidate_sha.toLowerCase() !== targetSha) fail("performance fixture candidate_sha does not match ORGMETRA_PERFORMANCE_TARGET_SHA"); -function requiredPositiveIntegerSetting(name) { - const raw = __ENV[name]; - if (raw === undefined || raw === "" || !/^\d+$/.test(raw)) fail(`${name} must be an explicit positive integer`); - const value = Number(raw); - if (!Number.isSafeInteger(value) || value < 1) fail(`${name} must be an explicit positive safe integer`); - return value; -} - const selectedRecords = fixture.profiles[selectedProfile]; -const targetRps = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_TARGET_RPS"); -const durationSeconds = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_DURATION_SECONDS"); -const preAllocatedVUs = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_PREALLOCATED_VUS"); -const maxVUs = requiredPositiveIntegerSetting("ORGMETRA_PERFORMANCE_MAX_VUS"); +const approvedLoadModel = approvedPerformanceLoadModel(selectedProfile); const selectedScenario = arrivalRateScenarioForPerformanceProfile(selectedProfile, { - expectedIterations: selectedRecords.length, targetRps, durationSeconds, preAllocatedVUs, maxVUs, + expectedIterations: selectedRecords.length, }); const firstCommitDuration = new Trend("employment_separation_first_commit_duration_ms", true); @@ -149,7 +139,7 @@ export function handleSummary(data) { completed_iterations: completedIterations, sample_complete: completedIterations === selectedRecords.length, completed_at: new Date().toISOString(), - load_model: { executor: selectedScenario.executor, target_rps: targetRps, duration_seconds: durationSeconds, preallocated_vus: preAllocatedVUs, max_vus: maxVUs, client_network_topology: clientNetworkTopology }, + load_model: { ...approvedLoadModel, client_network_topology: clientNetworkTopology }, dataset_id: fixture.dataset_id, clearance_reference: fixture.clearance_reference, preparation_protocol_reference: fixture.preparation_protocol_reference, From 63559c6426bde1c0cc4982fadd03c1f076605e29 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:17:32 +0900 Subject: [PATCH 128/269] fix(perf): stop forwarding load-model environment --- tests/performance/run_employment_separation_benchmark.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index e7949515b..6660999d5 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -58,10 +58,6 @@ podman run --rm --pull=never --network=host --read-only \ --env ORGMETRA_PERFORMANCE_BEARER_TOKEN \ --env ORGMETRA_PERFORMANCE_TARGET_SHA \ --env ORGMETRA_PERFORMANCE_PROFILE \ - --env ORGMETRA_PERFORMANCE_TARGET_RPS \ - --env ORGMETRA_PERFORMANCE_DURATION_SECONDS \ - --env ORGMETRA_PERFORMANCE_PREALLOCATED_VUS \ - --env ORGMETRA_PERFORMANCE_MAX_VUS \ --env ORGMETRA_PERFORMANCE_K6_VERSION \ --env ORGMETRA_PERFORMANCE_K6_IMAGE \ --env ORGMETRA_PERFORMANCE_K6_IMAGE_DIGEST \ From 8c02f688295e9d679c804231e9b5cf933474550d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:18:14 +0900 Subject: [PATCH 129/269] fix(perf): bind acceptance to approved cardinality --- .../employment_separation_run_contract.mjs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index 8a747f333..d8304be1e 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -76,7 +76,14 @@ export function requireDirectPerformanceClientNetwork(environment) { return PERFORMANCE_CLIENT_NETWORK_TOPOLOGY; } -export function validatePerformanceLoadModel(value, expectedIterations, profile) { +function approvedProfileForValidation(profile, iterations) { + if (profile !== undefined) return requirePerformanceProfile(profile); + if (iterations === 100) return "contention"; + if (iterations === 1000) return "first_commit"; + throw new Error("expectedIterations must match a version-controlled approved load-model cardinality"); +} + +export function validatePerformanceLoadModel(value, expectedIterations, profile = undefined) { if (value === null || typeof value !== "object" || Array.isArray(value)) { throw new Error("load_model must be an object"); } @@ -98,8 +105,8 @@ export function validatePerformanceLoadModel(value, expectedIterations, profile) if (value.client_network_topology !== PERFORMANCE_CLIENT_NETWORK_TOPOLOGY) { throw new Error(`load_model.client_network_topology must be ${PERFORMANCE_CLIENT_NETWORK_TOPOLOGY}`); } - const selectedProfile = requirePerformanceProfile(profile); const iterations = positiveInteger(expectedIterations, "expectedIterations"); + const selectedProfile = approvedProfileForValidation(profile, iterations); const rate = positiveInteger(value.target_rps, "load_model.target_rps"); const duration = positiveInteger(value.duration_seconds, "load_model.duration_seconds"); const preAllocated = positiveInteger(value.preallocated_vus, "load_model.preallocated_vus"); From cfbdad595fac009374766a19efe27933beace9ea Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:18:29 +0900 Subject: [PATCH 130/269] test(perf): use approved acceptance load models --- ...ployment_separation_acceptance_fixture_test_support.mjs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_fixture_test_support.mjs b/tests/performance/employment_separation_acceptance_fixture_test_support.mjs index 288b829fe..d09eea460 100644 --- a/tests/performance/employment_separation_acceptance_fixture_test_support.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_test_support.mjs @@ -1,6 +1,9 @@ import { createHash } from "node:crypto"; -import { PERFORMANCE_CLIENT_NETWORK_TOPOLOGY } from "./employment_separation_run_contract.mjs"; +import { + PERFORMANCE_CLIENT_NETWORK_TOPOLOGY, + approvedPerformanceLoadModel, +} from "./employment_separation_run_contract.mjs"; export const ACCEPTANCE_CANDIDATE_SHA = "a".repeat(40); export const ACCEPTANCE_PROFILE_PRECONDITIONS = Object.freeze({ @@ -38,6 +41,8 @@ function records(start, count) { } export function acceptanceLoadModel(expectedIterations) { + if (expectedIterations === 1000) return { ...approvedPerformanceLoadModel("first_commit") }; + if (expectedIterations === 100) return { ...approvedPerformanceLoadModel("contention") }; return { executor: "constant-arrival-rate", target_rps: 1, From b4990c55615be6de7a1af9776a644e535d02ef3a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:29:56 +0900 Subject: [PATCH 131/269] test(perf): reject double-counted k6 connection latency --- .../employment_separation_timing_contract.test.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_timing_contract.test.mjs b/tests/performance/employment_separation_timing_contract.test.mjs index 2f655c18b..c548d6b16 100644 --- a/tests/performance/employment_separation_timing_contract.test.mjs +++ b/tests/performance/employment_separation_timing_contract.test.mjs @@ -3,9 +3,9 @@ import test from "node:test"; import { buyerPathElapsedMs } from "./employment_separation_timing_contract.mjs"; -test("includes blocked, TCP, TLS, and request phases in buyer-path elapsed time", () => { +test("counts k6 blocked once because it already spans TCP and TLS acquisition", () => { assert.equal(buyerPathElapsedMs({ - blocked: 1.5, + blocked: 7, connecting: 2.5, tls_handshaking: 3, duration: 14, @@ -21,9 +21,9 @@ test("preserves keep-alive requests when connection phases are zero", () => { }), 10); }); -test("does not drop TCP or TLS latency from a cold request", () => { +test("includes cold connection acquisition without double-counting nested TCP and TLS phases", () => { assert.equal(buyerPathElapsedMs({ - blocked: 1, + blocked: 10, connecting: 4, tls_handshaking: 5, duration: 10, From 7e8b4a2dd51e9e9165b0c9b449f6e236e272e021 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:30:26 +0900 Subject: [PATCH 132/269] fix(perf): avoid double-counting k6 connection phases --- .../employment_separation_timing_contract.mjs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/performance/employment_separation_timing_contract.mjs b/tests/performance/employment_separation_timing_contract.mjs index f276e6297..aab93b444 100644 --- a/tests/performance/employment_separation_timing_contract.mjs +++ b/tests/performance/employment_separation_timing_contract.mjs @@ -15,14 +15,13 @@ export function buyerPathElapsedMs(timings) { } const blocked = finiteNonNegative(timings.blocked, "response.timings.blocked"); - const connecting = finiteNonNegative(timings.connecting, "response.timings.connecting"); - const tlsHandshaking = finiteNonNegative(timings.tls_handshaking, "response.timings.tls_handshaking"); + finiteNonNegative(timings.connecting, "response.timings.connecting"); + finiteNonNegative(timings.tls_handshaking, "response.timings.tls_handshaking"); const duration = finiteNonNegative(timings.duration, "response.timings.duration"); - // k6 documents duration as sending + waiting + receiving. TCP setup and TLS - // negotiation are separate phases, while blocked also carries pre-request wait - // such as connection-slot/DNS work. Final commercial acceptance disallows a - // client-side HTTPS MITM proxy because k6 can overlap these phases in the - // unusual double-TLS topology documented upstream. - return blocked + connecting + tlsHandshaking + duration; + // k6 v2.2 computes blocked from GetConn to GotConn, so TCP connect and TLS + // handshake are nested inside blocked for a new direct connection. Duration is + // the later sending + waiting + receiving interval. Adding connecting/TLS again + // would double-count cold-connection latency and could create a false RED. + return blocked + duration; } From 7de2f6d681fff1dec84808433d01b3cba20c44f0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:33:22 +0900 Subject: [PATCH 133/269] test(perf): require explicit profile for load evidence --- .../employment_separation_run_contract.test.mjs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 6de1e2b88..d5bbfdc9c 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -76,6 +76,13 @@ test("binds result evidence to the exact approved profile load model", () => { }, 1000, "first_commit"), /constant-arrival-rate/); }); +test("requires the selected profile when validating load-model evidence", () => { + assert.throws( + () => validatePerformanceLoadModel(approvedPerformanceLoadModel("replay"), 1000), + /profile must be exactly one of/, + ); +}); + test("fails closed when the k6 client is routed through an ambient proxy", () => { assert.equal(requireDirectPerformanceClientNetwork({}), PERFORMANCE_CLIENT_NETWORK_TOPOLOGY); assert.throws( From 655d110b003557a758df45b653085e3498c53000 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 19:34:25 +0900 Subject: [PATCH 134/269] test(perf): cover explicit replay and rejection load models --- .../employment_separation_run_contract.test.mjs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index d5bbfdc9c..955bfae99 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -63,6 +63,14 @@ test("refuses fixture cardinality that does not exactly fit the approved schedul test("binds result evidence to the exact approved profile load model", () => { const approved = approvedPerformanceLoadModel("first_commit"); assert.deepEqual(validatePerformanceLoadModel(approved, 1000, "first_commit"), approved); + assert.deepEqual( + validatePerformanceLoadModel(approvedPerformanceLoadModel("replay"), 1000, "replay"), + approvedPerformanceLoadModel("replay"), + ); + assert.deepEqual( + validatePerformanceLoadModel(approvedPerformanceLoadModel("rejection"), 1000, "rejection"), + approvedPerformanceLoadModel("rejection"), + ); assert.throws(() => validatePerformanceLoadModel({ ...approved, target_rps: 1, @@ -76,13 +84,6 @@ test("binds result evidence to the exact approved profile load model", () => { }, 1000, "first_commit"), /constant-arrival-rate/); }); -test("requires the selected profile when validating load-model evidence", () => { - assert.throws( - () => validatePerformanceLoadModel(approvedPerformanceLoadModel("replay"), 1000), - /profile must be exactly one of/, - ); -}); - test("fails closed when the k6 client is routed through an ambient proxy", () => { assert.equal(requireDirectPerformanceClientNetwork({}), PERFORMANCE_CLIENT_NETWORK_TOPOLOGY); assert.throws( From 01d3bb5d888c94a6316da6b979c7bcc87b266896 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 20:01:32 +0900 Subject: [PATCH 135/269] test(perf): require exact clean benchmark checkout --- ...nt_separation_k6_runtime_contract.test.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index ff53e5ad2..dd8ff92bc 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -68,6 +68,25 @@ test("canonical benchmark runner does not forward caller-controlled load-model e } }); +test("canonical benchmark runner binds the mounted workload to the exact clean candidate checkout", () => { + const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); + assert.match( + runner, + /git -C "\$\{repo_root\}" rev-parse --verify HEAD/, + "the mounted workload must be bound to an exact repository HEAD", + ); + assert.match( + runner, + /repository_head.*ORGMETRA_PERFORMANCE_TARGET_SHA|ORGMETRA_PERFORMANCE_TARGET_SHA.*repository_head/s, + "the exact mounted checkout must match the measured candidate SHA", + ); + assert.match( + runner, + /git -C "\$\{repo_root\}" status --porcelain=v1 --untracked-files=all/, + "commercial evidence must reject modified, staged, or untracked workload bytes", + ); +}); + test("canonical benchmark runner rejects CLI overrides before any Podman dependency is needed", () => { const runnerPath = fileURLToPath(new URL("./run_employment_separation_benchmark.sh", import.meta.url)); const result = spawnSync("bash", [runnerPath, "--duration", "1s"], { From c6b11611b8e92a3fba8b5919318612b89bbd3653 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 20:01:57 +0900 Subject: [PATCH 136/269] fix(perf): bind benchmark workload to exact clean candidate --- .../run_employment_separation_benchmark.sh | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 6660999d5..dc1714440 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -11,6 +11,24 @@ if (( $# != 0 )); then printf 'commercial Employment separation benchmark does not accept caller-supplied k6 CLI options\n' >&2 exit 64 fi + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" +target_sha="${ORGMETRA_PERFORMANCE_TARGET_SHA:-}" +if [[ ! "${target_sha}" =~ ^[0-9a-f]{40}$ ]]; then + printf 'ORGMETRA_PERFORMANCE_TARGET_SHA must be the exact lowercase 40-character candidate SHA\n' >&2 + exit 1 +fi +repository_head="$(git -C "${repo_root}" rev-parse --verify HEAD)" +if [[ "${repository_head}" != "${ORGMETRA_PERFORMANCE_TARGET_SHA}" ]]; then + printf 'benchmark checkout HEAD must equal ORGMETRA_PERFORMANCE_TARGET_SHA; head=%s target=%s\n' "${repository_head}" "${ORGMETRA_PERFORMANCE_TARGET_SHA}" >&2 + exit 1 +fi +repository_status="$(git -C "${repo_root}" status --porcelain=v1 --untracked-files=all)" +if [[ -n "${repository_status}" ]]; then + printf 'commercial performance evidence requires an exact clean checkout; modified, staged, or untracked files are present\n' >&2 + exit 1 +fi + if ! command -v podman >/dev/null 2>&1; then printf 'podman is required for the pinned commercial k6 runner\n' >&2 exit 1 @@ -26,7 +44,6 @@ if [[ "${version_token}" != "v${PINNED_K6_VERSION}" ]]; then exit 1 fi -repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" fixture_path="${ORGMETRA_PERFORMANCE_DATA_FILE:-}" summary_path="${ORGMETRA_PERFORMANCE_SUMMARY_FILE:-}" if [[ -z "${fixture_path}" || ! -f "${fixture_path}" ]]; then From 68f91e9c7d27171bf683b5d160e8998ba83d1a73 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 20:05:38 +0900 Subject: [PATCH 137/269] test(perf): require immutable benchmark snapshot --- ...nt_separation_k6_runtime_contract.test.mjs | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index dd8ff92bc..85624772b 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -68,22 +68,37 @@ test("canonical benchmark runner does not forward caller-controlled load-model e } }); -test("canonical benchmark runner binds the mounted workload to the exact clean candidate checkout", () => { +test("canonical benchmark runner binds the mounted workload to an immutable exact-candidate snapshot", () => { const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); assert.match( runner, /git -C "\$\{repo_root\}" rev-parse --verify HEAD/, - "the mounted workload must be bound to an exact repository HEAD", + "the source repository must be checked against an exact HEAD before snapshotting", ); assert.match( runner, /repository_head.*ORGMETRA_PERFORMANCE_TARGET_SHA|ORGMETRA_PERFORMANCE_TARGET_SHA.*repository_head/s, - "the exact mounted checkout must match the measured candidate SHA", + "the exact source checkout must match the measured candidate SHA", ); assert.match( runner, /git -C "\$\{repo_root\}" status --porcelain=v1 --untracked-files=all/, - "commercial evidence must reject modified, staged, or untracked workload bytes", + "commercial evidence must reject modified, staged, or untracked source bytes", + ); + assert.match( + runner, + /git -C "\$\{repo_root\}" archive --format=tar "\$\{target_sha\}"/, + "the executed workload must be materialized from the verified immutable candidate commit", + ); + assert.doesNotMatch( + runner, + /--volume "\$\{repo_root\}:\/workspace:ro"/, + "the live host working tree must never be mounted as the executable workload", + ); + assert.match( + runner, + /--volume "\$\{snapshot_dir\}:\/workspace:ro"/, + "Podman must mount only the immutable candidate snapshot at /workspace", ); }); From ce06fceb60efc0d0e54378a29f4752a34a7d659a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 20:06:59 +0900 Subject: [PATCH 138/269] test(perf): require immutable workload image mount --- ...ment_separation_k6_runtime_contract.test.mjs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index 85624772b..98cdcf0ba 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -68,12 +68,12 @@ test("canonical benchmark runner does not forward caller-controlled load-model e } }); -test("canonical benchmark runner binds the mounted workload to an immutable exact-candidate snapshot", () => { +test("canonical benchmark runner binds the mounted workload to an immutable exact-candidate image", () => { const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); assert.match( runner, /git -C "\$\{repo_root\}" rev-parse --verify HEAD/, - "the source repository must be checked against an exact HEAD before snapshotting", + "the source repository must be checked against an exact HEAD before materialization", ); assert.match( runner, @@ -87,8 +87,8 @@ test("canonical benchmark runner binds the mounted workload to an immutable exac ); assert.match( runner, - /git -C "\$\{repo_root\}" archive --format=tar "\$\{target_sha\}"/, - "the executed workload must be materialized from the verified immutable candidate commit", + /git -C "\$\{repo_root\}" archive --format=tar "\$\{target_sha\}"[\s\S]*podman import/, + "the executed workload must be imported from the verified immutable candidate commit", ); assert.doesNotMatch( runner, @@ -97,8 +97,13 @@ test("canonical benchmark runner binds the mounted workload to an immutable exac ); assert.match( runner, - /--volume "\$\{snapshot_dir\}:\/workspace:ro"/, - "Podman must mount only the immutable candidate snapshot at /workspace", + /--mount "type=image,source=\$\{workload_image_id\},destination=\/workspace"/, + "Podman must mount only the imported candidate image at /workspace", + ); + assert.match( + runner, + /podman image rm --force "\$\{workload_image_id\}"/, + "the ephemeral candidate image must be removed after the run", ); }); From aa6d7a4933815d62b67d7480f7ca61c279489b0c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 20:07:40 +0900 Subject: [PATCH 139/269] fix(perf): execute workload from immutable candidate image --- .../run_employment_separation_benchmark.sh | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index dc1714440..3aaa31ef8 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -44,6 +44,22 @@ if [[ "${version_token}" != "v${PINNED_K6_VERSION}" ]]; then exit 1 fi +workload_image_id="" +cleanup() { + if [[ -n "${workload_image_id}" ]]; then + podman image rm --force "${workload_image_id}" >/dev/null 2>&1 || true + fi +} +trap cleanup EXIT +workload_image_id="$( + git -C "${repo_root}" archive --format=tar "${target_sha}" \ + | podman import --quiet --message "Orgmetra Employment separation benchmark ${target_sha}" - +)" +if [[ -z "${workload_image_id}" ]] || ! podman image exists "${workload_image_id}"; then + printf 'failed to materialize immutable benchmark workload image for %s\n' "${target_sha}" >&2 + exit 1 +fi + fixture_path="${ORGMETRA_PERFORMANCE_DATA_FILE:-}" summary_path="${ORGMETRA_PERFORMANCE_SUMMARY_FILE:-}" if [[ -z "${fixture_path}" || ! -f "${fixture_path}" ]]; then @@ -67,7 +83,7 @@ export ORGMETRA_PERFORMANCE_K6_RUNNER_IDENTITY="${PINNED_K6_RUNNER_IDENTITY}" podman run --rm --pull=never --network=host --read-only \ --cap-drop=ALL --security-opt=no-new-privileges --pids-limit=256 \ --tmpfs /tmp:rw,nosuid,nodev,noexec \ - --volume "${repo_root}:/workspace:ro" \ + --mount "type=image,source=${workload_image_id},destination=/workspace" \ --volume "${fixture_path}:/evidence/fixture.json:ro" \ --volume "${summary_dir}:/output:rw" \ --workdir /workspace \ From 4b256d93af2f76afc643e5db0562464af5d621a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:03:58 +0900 Subject: [PATCH 140/269] test(perf): reject stale benchmark summary reuse --- ...nt_separation_k6_runtime_contract.test.mjs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index 98cdcf0ba..649dbdd5f 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -107,6 +107,40 @@ test("canonical benchmark runner binds the mounted workload to an immutable exac ); }); +test("canonical benchmark runner cannot publish stale or failed-run summary evidence", () => { + const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); + assert.match( + runner, + /summary_target=.*summary_path/, + "the requested result path must be treated as a final publication target", + ); + assert.match( + runner, + /if \[\[ -e "\$\{summary_target\}" \|\| -L "\$\{summary_target\}" \]\]/, + "a pre-existing result artifact must fail closed instead of surviving a failed rerun", + ); + assert.match( + runner, + /mktemp -d .*orgmetra-employment-separation-performance/, + "k6 must write into a private per-run staging directory", + ); + assert.doesNotMatch( + runner, + /--volume "\$\{summary_dir\}:\/output:rw"/, + "k6 must not write directly into the caller-visible result directory", + ); + assert.match( + runner, + /\[\[ ! -f "\$\{summary_run_file\}" \|\| -L "\$\{summary_run_file\}" \|\| ! -s "\$\{summary_run_file\}" \]\]/, + "the staged result must be a non-empty regular file", + ); + assert.match( + runner, + /ln "\$\{summary_run_file\}" "\$\{summary_target\}"/, + "publication must use a no-clobber atomic link so a concurrent stale artifact cannot win", + ); +}); + test("canonical benchmark runner rejects CLI overrides before any Podman dependency is needed", () => { const runnerPath = fileURLToPath(new URL("./run_employment_separation_benchmark.sh", import.meta.url)); const result = spawnSync("bash", [runnerPath, "--duration", "1s"], { From 872c1d4b4b6173fc2b0cd5780fb9d7d015a95af7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:04:28 +0900 Subject: [PATCH 141/269] fix(perf): publish only fresh successful benchmark summaries --- .../run_employment_separation_benchmark.sh | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 3aaa31ef8..862ffa9c8 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -45,10 +45,14 @@ if [[ "${version_token}" != "v${PINNED_K6_VERSION}" ]]; then fi workload_image_id="" +summary_run_dir="" cleanup() { if [[ -n "${workload_image_id}" ]]; then podman image rm --force "${workload_image_id}" >/dev/null 2>&1 || true fi + if [[ -n "${summary_run_dir}" ]]; then + rm -rf -- "${summary_run_dir}" + fi } trap cleanup EXIT workload_image_id="$( @@ -74,6 +78,13 @@ fixture_path="$(realpath "${fixture_path}")" summary_dir="$(realpath -m "$(dirname "${summary_path}")")" summary_name="$(basename "${summary_path}")" mkdir -p "${summary_dir}" +summary_target="${summary_dir}/${summary_name}" +if [[ -e "${summary_target}" || -L "${summary_target}" ]]; then + printf 'ORGMETRA_PERFORMANCE_SUMMARY_FILE must not already exist; refusing stale-result reuse: %s\n' "${summary_target}" >&2 + exit 1 +fi +summary_run_dir="$(mktemp -d "${summary_dir}/.orgmetra-employment-separation-performance.XXXXXX")" +summary_run_file="${summary_run_dir}/${summary_name}" export ORGMETRA_PERFORMANCE_K6_VERSION="${PINNED_K6_VERSION}" export ORGMETRA_PERFORMANCE_K6_IMAGE="${PINNED_K6_IMAGE}" @@ -85,7 +96,7 @@ podman run --rm --pull=never --network=host --read-only \ --tmpfs /tmp:rw,nosuid,nodev,noexec \ --mount "type=image,source=${workload_image_id},destination=/workspace" \ --volume "${fixture_path}:/evidence/fixture.json:ro" \ - --volume "${summary_dir}:/output:rw" \ + --volume "${summary_run_dir}:/output:rw" \ --workdir /workspace \ --env ORGMETRA_PERFORMANCE_BASE_URL \ --env ORGMETRA_PERFORMANCE_BEARER_TOKEN \ @@ -98,3 +109,12 @@ podman run --rm --pull=never --network=host --read-only \ --env ORGMETRA_PERFORMANCE_DATA_FILE=/evidence/fixture.json \ --env "ORGMETRA_PERFORMANCE_SUMMARY_FILE=/output/${summary_name}" \ "${PINNED_K6_RUNNER_IDENTITY}" run "${WORKLOAD}" + +if [[ ! -f "${summary_run_file}" || -L "${summary_run_file}" || ! -s "${summary_run_file}" ]]; then + printf 'successful k6 execution did not produce one non-empty regular summary artifact\n' >&2 + exit 1 +fi +if ! ln "${summary_run_file}" "${summary_target}"; then + printf 'failed to publish benchmark summary without clobbering an existing artifact: %s\n' "${summary_target}" >&2 + exit 1 +fi From 2ded2f0cdac52d0db5f481b4c97c118df8c9057c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:05:05 +0900 Subject: [PATCH 142/269] test(perf): bind fresh summary publication contract --- .../employment_separation_k6_runtime_contract.test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index 649dbdd5f..f94f0218b 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -111,7 +111,7 @@ test("canonical benchmark runner cannot publish stale or failed-run summary evid const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); assert.match( runner, - /summary_target=.*summary_path/, + /summary_target="\$\{summary_dir\}\/\$\{summary_name\}"/, "the requested result path must be treated as a final publication target", ); assert.match( From 02922a31f3beb4fdd296e8ec62d68d84b5d2c6b5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:10:10 +0900 Subject: [PATCH 143/269] test(perf): require non-root k6 evidence mount mapping --- ...yment_separation_k6_runtime_contract.test.mjs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index f94f0218b..db1ab0936 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -107,6 +107,22 @@ test("canonical benchmark runner binds the mounted workload to an immutable exac ); }); +test("canonical benchmark runner maps host evidence ownership to the pinned non-root k6 user", () => { + const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); + assert.match(runner, /readonly PINNED_K6_CONTAINER_UID="12345"/); + assert.match(runner, /readonly PINNED_K6_CONTAINER_GID="12345"/); + assert.match( + runner, + /podman image inspect --format '\{\{\.Config\.User\}\}' "\$\{PINNED_K6_RUNNER_IDENTITY\}"/, + "the pinned OCI image's configured non-root user must be verified before measurement", + ); + assert.match( + runner, + /--userns="keep-id:uid=\$\{PINNED_K6_CONTAINER_UID\},gid=\$\{PINNED_K6_CONTAINER_GID\}"/, + "the invoking host owner must map to k6 UID/GID so private fixture and staging paths remain usable without world-writable permissions", + ); +}); + test("canonical benchmark runner cannot publish stale or failed-run summary evidence", () => { const runner = readFileSync(new URL("./run_employment_separation_benchmark.sh", import.meta.url), "utf8"); assert.match( From 38c6ee346bc21416a48c287facf0d72fd667caa8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:10:43 +0900 Subject: [PATCH 144/269] fix(perf): map private evidence mounts to pinned k6 user --- tests/performance/run_employment_separation_benchmark.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 862ffa9c8..70063964a 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -5,6 +5,8 @@ readonly PINNED_K6_VERSION="2.2.0" readonly PINNED_K6_IMAGE="ghcr.io/grafana/k6" readonly PINNED_K6_IMAGE_DIGEST="sha256:9bd01d6941fca969cb61bb57d2da5ee9b385fe2aa8881df3798c196564d6ace6" readonly PINNED_K6_RUNNER_IDENTITY="${PINNED_K6_IMAGE}@${PINNED_K6_IMAGE_DIGEST}" +readonly PINNED_K6_CONTAINER_UID="12345" +readonly PINNED_K6_CONTAINER_GID="12345" readonly WORKLOAD="/workspace/tests/performance/employment_separation_buyer_path.js" if (( $# != 0 )); then @@ -37,6 +39,11 @@ if ! podman image exists "${PINNED_K6_RUNNER_IDENTITY}"; then printf 'preload the exact pinned k6 image before measurement: %s\n' "${PINNED_K6_RUNNER_IDENTITY}" >&2 exit 1 fi +image_user="$(podman image inspect --format '{{.Config.User}}' "${PINNED_K6_RUNNER_IDENTITY}")" +if [[ "${image_user}" != "${PINNED_K6_CONTAINER_UID}" ]]; then + printf 'pinned k6 image must declare container UID %s; observed: %s\n' "${PINNED_K6_CONTAINER_UID}" "${image_user}" >&2 + exit 1 +fi version_line="$(podman run --rm --pull=never "${PINNED_K6_RUNNER_IDENTITY}" version 2>&1 | head -n 1)" version_token="$(printf '%s\n' "${version_line}" | awk '{print $2}')" if [[ "${version_token}" != "v${PINNED_K6_VERSION}" ]]; then @@ -92,6 +99,8 @@ export ORGMETRA_PERFORMANCE_K6_IMAGE_DIGEST="${PINNED_K6_IMAGE_DIGEST}" export ORGMETRA_PERFORMANCE_K6_RUNNER_IDENTITY="${PINNED_K6_RUNNER_IDENTITY}" podman run --rm --pull=never --network=host --read-only \ + --user="${PINNED_K6_CONTAINER_UID}:${PINNED_K6_CONTAINER_GID}" \ + --userns="keep-id:uid=${PINNED_K6_CONTAINER_UID},gid=${PINNED_K6_CONTAINER_GID}" \ --cap-drop=ALL --security-opt=no-new-privileges --pids-limit=256 \ --tmpfs /tmp:rw,nosuid,nodev,noexec \ --mount "type=image,source=${workload_image_id},destination=/workspace" \ From e17f371fffe0e5f5cd58e410562c2ff018ca1fba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:17:05 +0900 Subject: [PATCH 145/269] test(perf): bind validated summary across publication --- ...nt_separation_k6_runtime_contract.test.mjs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index db1ab0936..8f6e1b095 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -150,11 +150,41 @@ test("canonical benchmark runner cannot publish stale or failed-run summary evid /\[\[ ! -f "\$\{summary_run_file\}" \|\| -L "\$\{summary_run_file\}" \|\| ! -s "\$\{summary_run_file\}" \]\]/, "the staged result must be a non-empty regular file", ); + assert.match( + runner, + /summary_source_identity=.*stat --printf='%d:%i:%s'/, + "publication must bind the validated source device, inode, and size before linking", + ); + assert.match( + runner, + /summary_source_digest=.*sha256sum/, + "publication must bind the exact validated source bytes before linking", + ); assert.match( runner, /ln "\$\{summary_run_file\}" "\$\{summary_target\}"/, "publication must use a no-clobber atomic link so a concurrent stale artifact cannot win", ); + assert.match( + runner, + /summary_target_identity=.*stat --printf='%d:%i:%s'/, + "the published link must be re-identified after link creation", + ); + assert.match( + runner, + /summary_target_digest=.*sha256sum/, + "the published link bytes must be re-hashed after link creation", + ); + assert.match( + runner, + /summary_source_identity.*summary_source_identity_after.*summary_target_identity[\s\S]*summary_source_digest.*summary_source_digest_after.*summary_target_digest/, + "source identity and bytes must remain unchanged across publication and equal the published artifact", + ); + assert.match( + runner, + /rm -f -- "\$\{summary_target\}"/, + "a publication-integrity mismatch must remove the untrusted caller-visible artifact before failing", + ); }); test("canonical benchmark runner rejects CLI overrides before any Podman dependency is needed", () => { From c0a2b0c7748e31c91a9cd507e88a35322a906ed5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:17:34 +0900 Subject: [PATCH 146/269] fix(perf): bind summary identity across publication --- .../run_employment_separation_benchmark.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 70063964a..999fa450a 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -123,7 +123,22 @@ if [[ ! -f "${summary_run_file}" || -L "${summary_run_file}" || ! -s "${summary_ printf 'successful k6 execution did not produce one non-empty regular summary artifact\n' >&2 exit 1 fi +summary_source_identity="$(stat --printf='%d:%i:%s' -- "${summary_run_file}")" +summary_source_digest="$(sha256sum -- "${summary_run_file}" | awk '{print $1}')" if ! ln "${summary_run_file}" "${summary_target}"; then printf 'failed to publish benchmark summary without clobbering an existing artifact: %s\n' "${summary_target}" >&2 exit 1 fi +summary_source_identity_after="$(stat --printf='%d:%i:%s' -- "${summary_run_file}" 2>/dev/null || true)" +summary_source_digest_after="$(sha256sum -- "${summary_run_file}" 2>/dev/null | awk '{print $1}' || true)" +summary_target_identity="$(stat --printf='%d:%i:%s' -- "${summary_target}" 2>/dev/null || true)" +summary_target_digest="$(sha256sum -- "${summary_target}" 2>/dev/null | awk '{print $1}' || true)" +if [[ -z "${summary_source_identity_after}" || -z "${summary_source_digest_after}" || -z "${summary_target_identity}" || -z "${summary_target_digest}" \ + || "${summary_source_identity}" != "${summary_source_identity_after}" \ + || "${summary_source_identity}" != "${summary_target_identity}" \ + || "${summary_source_digest}" != "${summary_source_digest_after}" \ + || "${summary_source_digest}" != "${summary_target_digest}" ]]; then + rm -f -- "${summary_target}" + printf 'benchmark summary changed during publication; refusing unbound result evidence\n' >&2 + exit 1 +fi From 44dedef4412ac0c49e3f8facda25a0b85f3a9af3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:18:04 +0900 Subject: [PATCH 147/269] test(perf): verify publication identity binding contract --- .../employment_separation_k6_runtime_contract.test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index 8f6e1b095..f38f267c9 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -177,7 +177,7 @@ test("canonical benchmark runner cannot publish stale or failed-run summary evid ); assert.match( runner, - /summary_source_identity.*summary_source_identity_after.*summary_target_identity[\s\S]*summary_source_digest.*summary_source_digest_after.*summary_target_digest/, + /summary_source_identity[\s\S]*summary_source_identity_after[\s\S]*summary_target_identity[\s\S]*summary_source_digest[\s\S]*summary_source_digest_after[\s\S]*summary_target_digest/, "source identity and bytes must remain unchanged across publication and equal the published artifact", ); assert.match( From 2ba21d88aa3c9837fa08d54554d2e94edf04b6f6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:22:20 +0900 Subject: [PATCH 148/269] test(perf): execute staged-publication replacement regression --- ...nt_separation_k6_runtime_contract.test.mjs | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_k6_runtime_contract.test.mjs b/tests/performance/employment_separation_k6_runtime_contract.test.mjs index f38f267c9..ab6a7f366 100644 --- a/tests/performance/employment_separation_k6_runtime_contract.test.mjs +++ b/tests/performance/employment_separation_k6_runtime_contract.test.mjs @@ -1,6 +1,16 @@ import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; -import { readFileSync } from "node:fs"; +import { + chmodSync, + existsSync, + mkdtempSync, + mkdirSync, + readFileSync, + rmSync, + writeFileSync, +} from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; import { fileURLToPath } from "node:url"; import test from "node:test"; @@ -187,6 +197,90 @@ test("canonical benchmark runner cannot publish stale or failed-run summary evid ); }); +test("canonical benchmark runner rejects a staged-path replacement during publication", () => { + const repoRoot = fileURLToPath(new URL("../..", import.meta.url)); + const runnerPath = fileURLToPath(new URL("./run_employment_separation_benchmark.sh", import.meta.url)); + const temporaryRoot = mkdtempSync(join(tmpdir(), "orgmetra-summary-publication-race-")); + try { + const fakeBin = join(temporaryRoot, "bin"); + mkdirSync(fakeBin); + const podmanPath = join(fakeBin, "podman"); + writeFileSync( + podmanPath, + `#!/usr/bin/env bash +set -euo pipefail +if [[ "$1" == "image" && "$2" == "exists" ]]; then exit 0; fi +if [[ "$1" == "image" && "$2" == "inspect" ]]; then printf '12345\\n'; exit 0; fi +if [[ "$1" == "image" && "$2" == "rm" ]]; then exit 0; fi +if [[ "$1" == "import" ]]; then cat >/dev/null; printf 'sha256:fake-workload\\n'; exit 0; fi +if [[ "$1" == "run" ]]; then + if [[ "\${!#}" == "version" ]]; then printf 'k6 v2.2.0\\n'; exit 0; fi + output_dir='' + summary_name='' + args=("$@") + for ((i=0; i<\${#args[@]}; i++)); do + if [[ "\${args[$i]}" == "--volume" ]]; then + value="\${args[$((i+1))]}" + if [[ "$value" == *":/output:rw" ]]; then output_dir="\${value%:/output:rw}"; fi + fi + if [[ "\${args[$i]}" == "--env" ]]; then + value="\${args[$((i+1))]}" + if [[ "$value" == ORGMETRA_PERFORMANCE_SUMMARY_FILE=/output/* ]]; then + summary_name="\${value#ORGMETRA_PERFORMANCE_SUMMARY_FILE=/output/}" + fi + fi + done + [[ -n "$output_dir" && -n "$summary_name" ]] + printf '{"schema_version":"orgmetra.race_probe.original"}\\n' > "$output_dir/$summary_name" + exit 0 +fi +exit 99 +`, + { mode: 0o700 }, + ); + chmodSync(podmanPath, 0o700); + + const lnPath = join(fakeBin, "ln"); + writeFileSync( + lnPath, + `#!/usr/bin/env bash +set -euo pipefail +printf '{"schema_version":"orgmetra.race_probe.replaced"}\\n' > "$1" +exec /bin/ln "$@" +`, + { mode: 0o700 }, + ); + chmodSync(lnPath, 0o700); + + const fixturePath = join(temporaryRoot, "fixture.json"); + const summaryPath = join(temporaryRoot, "result.json"); + writeFileSync(fixturePath, "{}\n", { mode: 0o600 }); + + const head = spawnSync("git", ["-C", repoRoot, "rev-parse", "HEAD"], { encoding: "utf8" }); + assert.equal(head.status, 0, head.stderr); + const targetSha = head.stdout.trim(); + const result = spawnSync("bash", [runnerPath], { + cwd: repoRoot, + encoding: "utf8", + env: { + ...process.env, + PATH: `${fakeBin}:${process.env.PATH ?? ""}`, + ORGMETRA_PERFORMANCE_BASE_URL: "http://127.0.0.1:18080", + ORGMETRA_PERFORMANCE_BEARER_TOKEN: "test-only-token", + ORGMETRA_PERFORMANCE_TARGET_SHA: targetSha, + ORGMETRA_PERFORMANCE_PROFILE: "first_commit", + ORGMETRA_PERFORMANCE_DATA_FILE: fixturePath, + ORGMETRA_PERFORMANCE_SUMMARY_FILE: summaryPath, + }, + }); + assert.notEqual(result.status, 0); + assert.match(result.stderr, /summary changed during publication/); + assert.equal(existsSync(summaryPath), false, "a replaced staged artifact must never remain published"); + } finally { + rmSync(temporaryRoot, { recursive: true, force: true }); + } +}); + test("canonical benchmark runner rejects CLI overrides before any Podman dependency is needed", () => { const runnerPath = fileURLToPath(new URL("./run_employment_separation_benchmark.sh", import.meta.url)); const result = spawnSync("bash", [runnerPath, "--duration", "1s"], { From bb6e5dd72430984a4dbbf96e715a4521c5849701 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:32:54 +0900 Subject: [PATCH 149/269] test(perf): bind acceptance to runner result digest --- ..._separation_acceptance_provenance.test.mjs | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index 61d7ad52e..50ac614da 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -2,7 +2,10 @@ import assert from "node:assert/strict"; import { createHash } from "node:crypto"; import test from "node:test"; -import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + validateEmploymentSeparationAcceptance, + validateRunnerResultDigest, +} from "./employment_separation_acceptance_contract.mjs"; import { acceptanceFixtureBytes, acceptanceFixtureSha256, @@ -118,3 +121,23 @@ test("requires exact open-load and direct-network provenance", () => { reject((value) => { value.load_model.executor = "shared-iterations"; }, /constant-arrival-rate/); reject((value) => { value.load_model.client_network_topology = "https_mitm_proxy"; }, /client_network_topology/); }); + +test("binds later acceptance to the exact digest emitted by the benchmark runner", () => { + const artifact = render(result()); + const digest = createHash("sha256").update(artifact).digest("hex"); + assert.equal(validateRunnerResultDigest(artifact, digest), digest); + + const substituted = Buffer.concat([artifact, Buffer.from(" ", "utf8")]); + assert.throws( + () => validateRunnerResultDigest(substituted, digest), + /runner result digest does not bind the supplied performance result/, + ); +}); + +test("rejects malformed runner result digests before acceptance", () => { + const artifact = render(result()); + assert.throws( + () => validateRunnerResultDigest(artifact, "not-a-sha256"), + /runner result digest must be a SHA-256 digest/, + ); +}); From 754f7a46a5d4f7271ab8272600619e6cb1ce236f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:33:10 +0900 Subject: [PATCH 150/269] fix(perf): bind acceptance to benchmark digest receipt --- ...oyment_separation_runner_result_digest.mjs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/performance/employment_separation_runner_result_digest.mjs diff --git a/tests/performance/employment_separation_runner_result_digest.mjs b/tests/performance/employment_separation_runner_result_digest.mjs new file mode 100644 index 000000000..cdb85c8b2 --- /dev/null +++ b/tests/performance/employment_separation_runner_result_digest.mjs @@ -0,0 +1,21 @@ +import { createHash } from "node:crypto"; + +const SHA256_PATTERN = /^[0-9a-f]{64}$/; + +function rawBytes(value) { + if (value instanceof Uint8Array) return value; + if (value instanceof ArrayBuffer) return new Uint8Array(value); + throw new Error("performance result must be supplied as raw bytes"); +} + +export function validateRunnerResultDigest(resultArtifact, expectedDigest) { + if (typeof expectedDigest !== "string" || !SHA256_PATTERN.test(expectedDigest)) { + throw new Error("runner result digest must be a SHA-256 digest"); + } + const bytes = rawBytes(resultArtifact); + const actualDigest = createHash("sha256").update(bytes).digest("hex"); + if (actualDigest !== expectedDigest) { + throw new Error("runner result digest does not bind the supplied performance result"); + } + return actualDigest; +} From 17015010a07b65a8543aac18a7abcde0062e4950 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:33:32 +0900 Subject: [PATCH 151/269] test(perf): consume benchmark digest contract --- .../employment_separation_acceptance_provenance.test.mjs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index 50ac614da..094fa9ba1 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -2,10 +2,8 @@ import assert from "node:assert/strict"; import { createHash } from "node:crypto"; import test from "node:test"; -import { - validateEmploymentSeparationAcceptance, - validateRunnerResultDigest, -} from "./employment_separation_acceptance_contract.mjs"; +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { validateRunnerResultDigest } from "./employment_separation_runner_result_digest.mjs"; import { acceptanceFixtureBytes, acceptanceFixtureSha256, From 12db6d101daccc09c88e1c6bd7cc80e7d311e9e8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:33:50 +0900 Subject: [PATCH 152/269] fix(perf): require benchmark digest at acceptance boundary --- .../employment_separation_acceptance_check.mjs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index 125c45751..c127d4063 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -3,17 +3,19 @@ import { readFile } from "node:fs/promises"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; import { validatePinnedK6AcceptanceEvidence } from "./employment_separation_k6_evidence_contract.mjs"; import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; +import { validateRunnerResultDigest } from "./employment_separation_runner_result_digest.mjs"; async function main() { - const [resultPath, runtimeEvidencePath, fixturePath] = process.argv.slice(2); - if (!resultPath || !runtimeEvidencePath || !fixturePath || process.argv.length !== 5) { - throw new Error("usage: node employment_separation_acceptance_check.mjs "); + const [resultPath, runtimeEvidencePath, fixturePath, runnerResultSha256] = process.argv.slice(2); + if (!resultPath || !runtimeEvidencePath || !fixturePath || !runnerResultSha256 || process.argv.length !== 6) { + throw new Error("usage: node employment_separation_acceptance_check.mjs "); } const [resultBytes, runtimeBytes, fixtureBytes] = await Promise.all([ readFile(resultPath), readFile(runtimeEvidencePath), readFile(fixturePath), ]); + const verifiedRunnerResultSha256 = validateRunnerResultDigest(resultBytes, runnerResultSha256); const runtimeDocument = parseRuntimeEvidenceArtifact(runtimeBytes); const k6Evidence = validatePinnedK6AcceptanceEvidence(resultBytes, runtimeDocument.parsed); const acceptance = validateEmploymentSeparationAcceptance( @@ -24,6 +26,7 @@ async function main() { process.stdout.write(`${JSON.stringify({ ...acceptance, ...k6Evidence, + runner_result_sha256: verifiedRunnerResultSha256, runtime_evidence_sha256: runtimeDocument.sha256, }, null, 2)}\n`); } From b4bbb75143f27ffc220e11907ce5ad6a10f35ffe Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:34:13 +0900 Subject: [PATCH 153/269] fix(perf): emit immutable benchmark digest receipt --- tests/performance/run_employment_separation_benchmark.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 999fa450a..5dd095aa5 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -142,3 +142,8 @@ if [[ -z "${summary_source_identity_after}" || -z "${summary_source_digest_after printf 'benchmark summary changed during publication; refusing unbound result evidence\n' >&2 exit 1 fi + +# The caller-visible pathname remains mutable after this process exits. Treat this +# digest as the immutable handoff token: downstream acceptance must re-hash the +# bytes it consumes and require this exact value rather than trusting the path. +printf 'ORGMETRA_PERFORMANCE_RESULT_SHA256=%s\n' "${summary_source_digest}" From 108f1c0ee70eebfb0fa7d391aecb49a7927d912d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:34:43 +0900 Subject: [PATCH 154/269] test(perf): execute post-publication substitution guard --- ..._separation_acceptance_cli_digest.test.mjs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_cli_digest.test.mjs diff --git a/tests/performance/employment_separation_acceptance_cli_digest.test.mjs b/tests/performance/employment_separation_acceptance_cli_digest.test.mjs new file mode 100644 index 000000000..7bbaf0ba8 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_cli_digest.test.mjs @@ -0,0 +1,44 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import { spawnSync } from "node:child_process"; +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; +import test from "node:test"; + +const acceptanceCheck = fileURLToPath(new URL("./employment_separation_acceptance_check.mjs", import.meta.url)); + +test("acceptance CLI rejects a result substituted after the runner digest receipt", () => { + const temporaryRoot = mkdtempSync(join(tmpdir(), "orgmetra-runner-digest-")); + try { + const resultPath = join(temporaryRoot, "result.json"); + const runtimePath = join(temporaryRoot, "runtime.json"); + const fixturePath = join(temporaryRoot, "fixture.json"); + const originalResult = Buffer.from('{"schema_version":"orgmetra.original"}\n', "utf8"); + const substitutedResult = Buffer.from('{"schema_version":"orgmetra.substituted"}\n', "utf8"); + const runnerDigest = createHash("sha256").update(originalResult).digest("hex"); + + writeFileSync(resultPath, substitutedResult, { mode: 0o600 }); + writeFileSync(runtimePath, "{}\n", { mode: 0o600 }); + writeFileSync(fixturePath, "{}\n", { mode: 0o600 }); + + const result = spawnSync( + process.execPath, + [acceptanceCheck, resultPath, runtimePath, fixturePath, runnerDigest], + { encoding: "utf8" }, + ); + assert.notEqual(result.status, 0); + assert.match(result.stderr, /runner result digest does not bind the supplied performance result/); + } finally { + rmSync(temporaryRoot, { recursive: true, force: true }); + } +}); + +test("acceptance CLI requires the runner digest handoff token", () => { + const result = spawnSync(process.execPath, [acceptanceCheck, "result.json", "runtime.json", "fixture.json"], { + encoding: "utf8", + }); + assert.notEqual(result.status, 0); + assert.match(result.stderr, //); +}); From d2ab0b057dd81610c53326fe60a96f9a3b7595da Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:43:40 +0900 Subject: [PATCH 155/269] test(perf): fail closed without authenticated evidence owner --- ..._separation_acceptance_cli_digest.test.mjs | 48 +++++++------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_cli_digest.test.mjs b/tests/performance/employment_separation_acceptance_cli_digest.test.mjs index 7bbaf0ba8..0a46d20f2 100644 --- a/tests/performance/employment_separation_acceptance_cli_digest.test.mjs +++ b/tests/performance/employment_separation_acceptance_cli_digest.test.mjs @@ -1,44 +1,28 @@ import assert from "node:assert/strict"; -import { createHash } from "node:crypto"; import { spawnSync } from "node:child_process"; -import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; import { fileURLToPath } from "node:url"; import test from "node:test"; const acceptanceCheck = fileURLToPath(new URL("./employment_separation_acceptance_check.mjs", import.meta.url)); -test("acceptance CLI rejects a result substituted after the runner digest receipt", () => { - const temporaryRoot = mkdtempSync(join(tmpdir(), "orgmetra-runner-digest-")); - try { - const resultPath = join(temporaryRoot, "result.json"); - const runtimePath = join(temporaryRoot, "runtime.json"); - const fixturePath = join(temporaryRoot, "fixture.json"); - const originalResult = Buffer.from('{"schema_version":"orgmetra.original"}\n', "utf8"); - const substitutedResult = Buffer.from('{"schema_version":"orgmetra.substituted"}\n', "utf8"); - const runnerDigest = createHash("sha256").update(originalResult).digest("hex"); +const OWNER_GAP_PATTERN = /authenticated performance-evidence attestation.*ContextualWisdomLab\/.github#2162/; - writeFileSync(resultPath, substitutedResult, { mode: 0o600 }); - writeFileSync(runtimePath, "{}\n", { mode: 0o600 }); - writeFileSync(fixturePath, "{}\n", { mode: 0o600 }); - - const result = spawnSync( - process.execPath, - [acceptanceCheck, resultPath, runtimePath, fixturePath, runnerDigest], - { encoding: "utf8" }, - ); - assert.notEqual(result.status, 0); - assert.match(result.stderr, /runner result digest does not bind the supplied performance result/); - } finally { - rmSync(temporaryRoot, { recursive: true, force: true }); - } +test("commercial acceptance fails closed before trusting a caller-supplied result digest", () => { + const result = spawnSync( + process.execPath, + [acceptanceCheck, "result.json", "runtime.json", "fixture.json", "a".repeat(64)], + { encoding: "utf8" }, + ); + assert.notEqual(result.status, 0); + assert.match(result.stderr, OWNER_GAP_PATTERN); }); -test("acceptance CLI requires the runner digest handoff token", () => { - const result = spawnSync(process.execPath, [acceptanceCheck, "result.json", "runtime.json", "fixture.json"], { - encoding: "utf8", - }); +test("commercial acceptance cannot be restored by substituting both result bytes and digest locally", () => { + const result = spawnSync( + process.execPath, + [acceptanceCheck, "substituted-result.json", "substituted-runtime.json", "fixture.json", "b".repeat(64)], + { encoding: "utf8" }, + ); assert.notEqual(result.status, 0); - assert.match(result.stderr, //); + assert.match(result.stderr, OWNER_GAP_PATTERN); }); From 5b8b49746c148240e3078745c714d33533aa2951 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:43:51 +0900 Subject: [PATCH 156/269] fix(perf): fail closed until authenticated evidence owner lands --- ...t_separation_authenticated_evidence_gate.mjs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/performance/employment_separation_authenticated_evidence_gate.mjs diff --git a/tests/performance/employment_separation_authenticated_evidence_gate.mjs b/tests/performance/employment_separation_authenticated_evidence_gate.mjs new file mode 100644 index 000000000..3ea4393b2 --- /dev/null +++ b/tests/performance/employment_separation_authenticated_evidence_gate.mjs @@ -0,0 +1,17 @@ +const AUTHENTICATED_EVIDENCE_OWNER = "ContextualWisdomLab/.github#2162"; + +/** + * Block commercial acceptance while exact performance evidence has no + * organization-owned authenticated attestation path. Local byte/digest + * consistency is useful structural evidence, but it is not an authority + * boundary because the same caller can replace both bytes and self-asserted + * digests. The gate is removed only after the released central owner contract + * is consumed and verified at the acceptance entry point. + */ +export function requireAuthenticatedPerformanceEvidence() { + throw new Error( + `commercial acceptance requires authenticated performance-evidence attestation from ${AUTHENTICATED_EVIDENCE_OWNER}; local result/runtime/fixture bytes and caller-supplied digests are structural evidence only`, + ); +} + +export { AUTHENTICATED_EVIDENCE_OWNER }; From 51da6578d279af8e25e0238f47d15e2a1d5b80af Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:44:08 +0900 Subject: [PATCH 157/269] fix(perf): block unauthenticated commercial acceptance --- ...employment_separation_acceptance_check.mjs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index c127d4063..faaee6474 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -1,32 +1,35 @@ import { readFile } from "node:fs/promises"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { requireAuthenticatedPerformanceEvidence } from "./employment_separation_authenticated_evidence_gate.mjs"; import { validatePinnedK6AcceptanceEvidence } from "./employment_separation_k6_evidence_contract.mjs"; import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; -import { validateRunnerResultDigest } from "./employment_separation_runner_result_digest.mjs"; async function main() { - const [resultPath, runtimeEvidencePath, fixturePath, runnerResultSha256] = process.argv.slice(2); - if (!resultPath || !runtimeEvidencePath || !fixturePath || !runnerResultSha256 || process.argv.length !== 6) { - throw new Error("usage: node employment_separation_acceptance_check.mjs "); + // A caller-controlled digest is not an authentication boundary. Keep the + // commercial entry point fail closed until the organization-owned signer and + // verifier tracked by .github#2162 is released and consumed here. + requireAuthenticatedPerformanceEvidence(); + + const [resultPath, runtimeEvidencePath, fixturePath] = process.argv.slice(2); + if (!resultPath || !runtimeEvidencePath || !fixturePath || process.argv.length !== 5) { + throw new Error("usage: node employment_separation_acceptance_check.mjs "); } const [resultBytes, runtimeBytes, fixtureBytes] = await Promise.all([ readFile(resultPath), readFile(runtimeEvidencePath), readFile(fixturePath), ]); - const verifiedRunnerResultSha256 = validateRunnerResultDigest(resultBytes, runnerResultSha256); const runtimeDocument = parseRuntimeEvidenceArtifact(runtimeBytes); const k6Evidence = validatePinnedK6AcceptanceEvidence(resultBytes, runtimeDocument.parsed); - const acceptance = validateEmploymentSeparationAcceptance( + const evidenceContract = validateEmploymentSeparationAcceptance( resultBytes, runtimeDocument.parsed, fixtureBytes, ); process.stdout.write(`${JSON.stringify({ - ...acceptance, + ...evidenceContract, ...k6Evidence, - runner_result_sha256: verifiedRunnerResultSha256, runtime_evidence_sha256: runtimeDocument.sha256, }, null, 2)}\n`); } From b6968520ef191fe8a3fd84d3cd5d4dc23a778281 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 21:44:49 +0900 Subject: [PATCH 158/269] docs(perf): demote local digest to structural evidence --- tests/performance/run_employment_separation_benchmark.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 5dd095aa5..9a92bc725 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -143,7 +143,9 @@ if [[ -z "${summary_source_identity_after}" || -z "${summary_source_digest_after exit 1 fi -# The caller-visible pathname remains mutable after this process exits. Treat this -# digest as the immutable handoff token: downstream acceptance must re-hash the -# bytes it consumes and require this exact value rather than trusting the path. +# This digest is structural evidence only. The caller-visible pathname and any +# value a caller can copy from stdout remain under the same authority. Commercial +# acceptance stays fail closed until the organization-owned authenticated +# attestation boundary tracked by ContextualWisdomLab/.github#2162 binds these +# exact result bytes independently. printf 'ORGMETRA_PERFORMANCE_RESULT_SHA256=%s\n' "${summary_source_digest}" From 6e30f0ae7eb2af07eb12b22636cbddfa5039a6b8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 23:02:32 +0900 Subject: [PATCH 159/269] test(perf): reject local commercial acceptance receipt --- ...ployment_separation_acceptance_contract.test.mjs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 01e193125..3d0730322 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -181,3 +181,16 @@ test("rejects byte-distinct result artifacts that collide after lossy UTF-8 deco ); } }); + +test("local validator cannot emit a commercial acceptance receipt from caller-consistent replacement artifacts", () => { + const replacement = result(); + replacement.dataset_id = "dataset:employment-separation-perf-substituted"; + const artifact = render(replacement); + const structuralEvidence = validateEmploymentSeparationAcceptance( + artifact, + runtimeEvidence(artifact), + FIXTURE_BYTES, + ); + assert.equal(structuralEvidence.structurally_valid, true); + assert.equal(Object.hasOwn(structuralEvidence, "accepted"), false); +}); From 3dec98a35dfdb9506a04c544be9da3d42dc37130 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 23:03:15 +0900 Subject: [PATCH 160/269] fix(perf): keep local evidence validation structural --- tests/performance/employment_separation_acceptance_contract.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index ad64b5c38..9b8ffec1a 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -341,7 +341,7 @@ export function validateEmploymentSeparationAcceptance(resultArtifact, runtimeEv fixtureDigest, ); return { - accepted: true, + structurally_valid: true, candidate_sha: validatedResult.candidateSha, selected_profile: validatedResult.profile, fixture_sha256: fixtureDigest, From e680e022f6325b223df58143e093e5e01f5645a8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 23:03:38 +0900 Subject: [PATCH 161/269] test(perf): assert structural-only evidence result --- .../employment_separation_acceptance_contract.test.mjs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.test.mjs b/tests/performance/employment_separation_acceptance_contract.test.mjs index 3d0730322..573cdd2b8 100644 --- a/tests/performance/employment_separation_acceptance_contract.test.mjs +++ b/tests/performance/employment_separation_acceptance_contract.test.mjs @@ -91,16 +91,18 @@ function evidencePair() { return { performance, artifact, runtime: runtimeEvidence(artifact) }; } -test("accepts an exact candidate result only with independently observed load, fixture, deployment, resource, and cleanup evidence", () => { +test("validates exact candidate evidence as structural evidence only", () => { const { artifact, runtime } = evidencePair(); - assert.deepEqual(validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), { - accepted: true, + const structuralEvidence = validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES); + assert.deepEqual(structuralEvidence, { + structurally_valid: true, candidate_sha: "a".repeat(40), selected_profile: "first_commit", fixture_sha256: FIXTURE_SHA256, performance_result_sha256: runtime.performance_result_sha256, p95_ms: 18.4, }); + assert.equal(Object.hasOwn(structuralEvidence, "accepted"), false); }); test("rejects a self-declared target when the observed service revision differs", () => { @@ -151,7 +153,7 @@ test("rejects incomplete scheduled samples even when the completed subset is fas assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), /sample must be complete/); }); -test("rejects acceptance when post-run cleanup finds a run-scoped leak", () => { +test("rejects structural validity when post-run cleanup finds a run-scoped leak", () => { const { artifact, runtime } = evidencePair(); runtime.residual_open_transactions = 1; assert.throws(() => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), /residual_open_transactions must be 0/); From 0201f5d94ac1d491a1d7292eddf6d506f54bde15 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 13 Sep 2026 23:03:53 +0900 Subject: [PATCH 162/269] test(perf): keep latency validation non-commercial --- ...t_separation_acceptance_latency_samples.test.mjs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs index 637432a64..fc89ddb57 100644 --- a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -102,9 +102,14 @@ test("rejects a complete counter when the measured Trend itself is truncated", ( ); }); -test("accepts latency evidence only when every expected request contributed to the measured Trend", () => { +test("validates latency evidence structurally only when every expected request contributed to the measured Trend", () => { const artifact = render(performanceResult(1000, 1000)); - const accepted = validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES); - assert.equal(accepted.accepted, true); - assert.equal(accepted.p95_ms, 18); + const structuralEvidence = validateEmploymentSeparationAcceptance( + artifact, + runtimeEvidence(artifact), + FIXTURE_BYTES, + ); + assert.equal(structuralEvidence.structurally_valid, true); + assert.equal(Object.hasOwn(structuralEvidence, "accepted"), false); + assert.equal(structuralEvidence.p95_ms, 18); }); From 172f7575416883aa3b9aae4c9b219059399e279f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 14 Sep 2026 00:30:07 +0900 Subject: [PATCH 163/269] test(perf): require explicit load-model profile identity --- .../employment_separation_run_contract.test.mjs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 955bfae99..ef362d249 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -84,6 +84,13 @@ test("binds result evidence to the exact approved profile load model", () => { }, 1000, "first_commit"), /constant-arrival-rate/); }); +test("refuses load-model validation without explicit profile identity", () => { + assert.throws( + () => validatePerformanceLoadModel(approvedPerformanceLoadModel("replay"), 1000), + /profile/i, + ); +}); + test("fails closed when the k6 client is routed through an ambient proxy", () => { assert.equal(requireDirectPerformanceClientNetwork({}), PERFORMANCE_CLIENT_NETWORK_TOPOLOGY); assert.throws( From 37e40ae694c46221eab76fd495cd6d0a4c0c3fdc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 14 Sep 2026 00:30:55 +0900 Subject: [PATCH 164/269] fix(perf): bind load model to explicit profile --- .../employment_separation_run_contract.mjs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index d8304be1e..e2d56ef6a 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -76,14 +76,7 @@ export function requireDirectPerformanceClientNetwork(environment) { return PERFORMANCE_CLIENT_NETWORK_TOPOLOGY; } -function approvedProfileForValidation(profile, iterations) { - if (profile !== undefined) return requirePerformanceProfile(profile); - if (iterations === 100) return "contention"; - if (iterations === 1000) return "first_commit"; - throw new Error("expectedIterations must match a version-controlled approved load-model cardinality"); -} - -export function validatePerformanceLoadModel(value, expectedIterations, profile = undefined) { +export function validatePerformanceLoadModel(value, expectedIterations, profile) { if (value === null || typeof value !== "object" || Array.isArray(value)) { throw new Error("load_model must be an object"); } @@ -106,7 +99,7 @@ export function validatePerformanceLoadModel(value, expectedIterations, profile throw new Error(`load_model.client_network_topology must be ${PERFORMANCE_CLIENT_NETWORK_TOPOLOGY}`); } const iterations = positiveInteger(expectedIterations, "expectedIterations"); - const selectedProfile = approvedProfileForValidation(profile, iterations); + const selectedProfile = requirePerformanceProfile(profile); const rate = positiveInteger(value.target_rps, "load_model.target_rps"); const duration = positiveInteger(value.duration_seconds, "load_model.duration_seconds"); const preAllocated = positiveInteger(value.preallocated_vus, "load_model.preallocated_vus"); From 9b1b116f0d937bee0afcc6646b140edd09f11d8a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 14 Sep 2026 00:31:47 +0900 Subject: [PATCH 165/269] fix(perf): bind acceptance load evidence to selected profile --- .../performance/employment_separation_acceptance_contract.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 9b8ffec1a..69ef4a55e 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -193,7 +193,7 @@ function validateResult(result) { if (expectedIterations < minimumIterations) { fail(`${profile} requires at least ${minimumIterations} iterations`); } - const loadModel = validatePerformanceLoadModel(result.load_model, expectedIterations); + const loadModel = validatePerformanceLoadModel(result.load_model, expectedIterations, profile); const completedIterations = nonNegativeInteger(result.completed_iterations, "result.completed_iterations"); if (result.sample_complete !== true || completedIterations !== expectedIterations) { fail("result sample must be complete"); @@ -297,6 +297,7 @@ function validateRuntimeEvidence(runtime, resultDigest, result, validatedResult, const observedLoadModel = validatePerformanceLoadModel( runtime.observed_load_model, validatedResult.expectedIterations, + validatedResult.profile, ); sameLoadModel(observedLoadModel, validatedResult.loadModel); const resourceReference = reference(runtime.resource_evidence_reference, "runtime.resource_evidence_reference"); From 52f32f351cd15f6df544c53ed21dfd612bc96e5e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 12:03:08 +0900 Subject: [PATCH 166/269] test(perf): reject impossible evidence calendar timestamps --- ...t_separation_acceptance_timestamp.test.mjs | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_timestamp.test.mjs diff --git a/tests/performance/employment_separation_acceptance_timestamp.test.mjs b/tests/performance/employment_separation_acceptance_timestamp.test.mjs new file mode 100644 index 000000000..32b5f2aa3 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_timestamp.test.mjs @@ -0,0 +1,106 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + ACCEPTANCE_CANDIDATE_SHA, + ACCEPTANCE_PROFILE_PRECONDITIONS, + acceptanceFixtureBytes, + acceptanceFixtureSha256, + acceptanceLoadModel, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; + +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); + +function render(value) { + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + +function performanceResult() { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + fixture_sha256: FIXTURE_SHA256, + selected_profile: "first_commit", + expected_iterations: 1000, + completed_iterations: 1000, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(1000), + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { ...ACCEPTANCE_PROFILE_PRECONDITIONS }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: 1000, rate: 20 } }, + checks: { values: { rate: 1, passes: 1000, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, + employment_separation_latency_samples: { values: { count: 1000, rate: 20 } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count: 1000 }, + }, + }, + }, + }; +} + +function runtimeEvidence(resultArtifact) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + observed_service_sha: ACCEPTANCE_CANDIDATE_SHA, + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), + fixture_sha256: FIXTURE_SHA256, + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(1000), + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42.5, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1.2, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +test("rejects an impossible result completion calendar date instead of accepting Date.parse normalization", () => { + const performance = performanceResult(); + performance.completed_at = "2026-02-30T04:10:00Z"; + const artifact = render(performance); + + assert.throws( + () => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), + /result.completed_at must be an RFC 3339 UTC timestamp/, + ); +}); + +test("rejects an impossible runtime observation calendar date instead of accepting Date.parse normalization", () => { + const performance = performanceResult(); + const artifact = render(performance); + const runtime = runtimeEvidence(artifact); + runtime.observed_at = "2026-09-31T04:10:01Z"; + + assert.throws( + () => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), + /runtime.observed_at must be an RFC 3339 UTC timestamp/, + ); +}); From 60244f9ac6e3c1eb43bc721fcbef38c2c7400b6f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 12:04:23 +0900 Subject: [PATCH 167/269] fix(perf): validate evidence calendar timestamps exactly --- ...loyment_separation_acceptance_contract.mjs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 69ef4a55e..e98dbff48 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -79,7 +79,27 @@ function reference(value, label) { function utcTimestamp(value, label) { const text = stringValue(value, label); - if (!UTC_TIMESTAMP_PATTERN.test(text) || Number.isNaN(Date.parse(text))) { + if (!UTC_TIMESTAMP_PATTERN.test(text)) { + fail(`${label} must be an RFC 3339 UTC timestamp`); + } + + const year = Number(text.slice(0, 4)); + const month = Number(text.slice(5, 7)); + const day = Number(text.slice(8, 10)); + const hour = Number(text.slice(11, 13)); + const minute = Number(text.slice(14, 16)); + const second = Number(text.slice(17, 19)); + const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); + const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + if ( + month < 1 + || month > 12 + || day < 1 + || day > daysInMonth[month - 1] + || hour > 23 + || minute > 59 + || second > 59 + ) { fail(`${label} must be an RFC 3339 UTC timestamp`); } return text; From 76741ca5adad2dd33857734256dd854d03c99ce7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 12:05:26 +0900 Subject: [PATCH 168/269] test(perf): preserve fractional timestamp ordering --- ...t_separation_acceptance_timestamp.test.mjs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_timestamp.test.mjs b/tests/performance/employment_separation_acceptance_timestamp.test.mjs index 32b5f2aa3..61e4ea366 100644 --- a/tests/performance/employment_separation_acceptance_timestamp.test.mjs +++ b/tests/performance/employment_separation_acceptance_timestamp.test.mjs @@ -104,3 +104,27 @@ test("rejects an impossible runtime observation calendar date instead of accepti /runtime.observed_at must be an RFC 3339 UTC timestamp/, ); }); + +test("rejects a sub-millisecond runtime observation that precedes completion", () => { + const performance = performanceResult(); + performance.completed_at = "2026-09-13T04:10:00.0009Z"; + const artifact = render(performance); + const runtime = runtimeEvidence(artifact); + runtime.observed_at = "2026-09-13T04:10:00.0001Z"; + + assert.throws( + () => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), + /runtime.observed_at must not precede result.completed_at/, + ); +}); + +test("accepts equivalent fractional instants with trailing-zero spelling differences", () => { + const performance = performanceResult(); + performance.completed_at = "2026-09-13T04:10:00.100Z"; + const artifact = render(performance); + const runtime = runtimeEvidence(artifact); + runtime.observed_at = "2026-09-13T04:10:00.1000Z"; + + const evidence = validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES); + assert.equal(evidence.structurally_valid, true); +}); From efd6c5657a57f0d74f89240ba5ee1631d0264d08 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 12:06:08 +0900 Subject: [PATCH 169/269] fix(perf): preserve exact fractional evidence ordering --- ...ployment_separation_acceptance_contract.mjs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index e98dbff48..7fdc243fa 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -105,6 +105,22 @@ function utcTimestamp(value, label) { return text; } +function compareUtcTimestamps(left, right) { + const leftBody = left.slice(0, -1); + const rightBody = right.slice(0, -1); + const [leftSecond, leftFraction = ""] = leftBody.split("."); + const [rightSecond, rightFraction = ""] = rightBody.split("."); + if (leftSecond < rightSecond) return -1; + if (leftSecond > rightSecond) return 1; + + const precision = Math.max(leftFraction.length, rightFraction.length); + const normalizedLeft = leftFraction.padEnd(precision, "0"); + const normalizedRight = rightFraction.padEnd(precision, "0"); + if (normalizedLeft < normalizedRight) return -1; + if (normalizedLeft > normalizedRight) return 1; + return 0; +} + function positiveInteger(value, label) { if (!Number.isSafeInteger(value) || value < 1) fail(`${label} must be a positive safe integer`); return value; @@ -325,7 +341,7 @@ function validateRuntimeEvidence(runtime, resultDigest, result, validatedResult, fail("runtime.resource_evidence_reference must match result.resource_evidence_reference"); } const observedAt = utcTimestamp(runtime.observed_at, "runtime.observed_at"); - if (Date.parse(observedAt) < Date.parse(validatedResult.completedAt)) { + if (compareUtcTimestamps(observedAt, validatedResult.completedAt) < 0) { fail("runtime.observed_at must not precede result.completed_at"); } From 479346fcc628d509a46b186a390d0d321db8bcad Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 12:10:28 +0900 Subject: [PATCH 170/269] test(perf): reject impossible fixture preparation timestamp --- .../employment_separation_fixture_contract.test.mjs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_fixture_contract.test.mjs b/tests/performance/employment_separation_fixture_contract.test.mjs index 34c379469..ddba629d2 100644 --- a/tests/performance/employment_separation_fixture_contract.test.mjs +++ b/tests/performance/employment_separation_fixture_contract.test.mjs @@ -66,6 +66,15 @@ test("accepts a right-cleared fixture with explicit prepared-state provenance", assert.equal(validatePerformanceFixture(value, smallAcceptance), value); }); +test("rejects an impossible fixture preparation calendar timestamp", () => { + const value = fixture(); + value.prepared_at = "2026-02-30T02:00:00Z"; + assert.throws( + () => validatePerformanceFixture(value, smallAcceptance), + /fixture.prepared_at must be an RFC 3339 UTC timestamp/, + ); +}); + test("rejects synthetic or uncleared commercial fixtures", () => { const synthetic = fixture(); synthetic.synthetic = true; @@ -157,4 +166,4 @@ test("builds the exact published separation request without storing bearer crede "X-Tenant-Reference": "10000000-0000-4000-8000-000000000009", }); assert.deepEqual(JSON.parse(requestBody(value)), value.payload); -}); +}); \ No newline at end of file From 75090bf81e111a8460a0ed56425817544cf52fff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 12:10:42 +0900 Subject: [PATCH 171/269] test(perf): reject impossible response recorded timestamp --- .../employment_separation_response_contract.test.mjs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index e73ffea95..323b52af3 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -29,6 +29,15 @@ test("accepts the published first-commit and replay response shape", () => { ); }); +test("rejects impossible success-response calendar timestamps", () => { + const body = successBody(false); + body.recorded_at = "2026-02-30T02:00:00Z"; + assert.equal( + isGovernedSeparationSuccess(200, body, { employmentRecordId: EMPLOYMENT, replayed: false }), + false, + ); +}); + test("rejects success responses that are replay- or target-inconsistent", () => { assert.equal( isGovernedSeparationSuccess(200, successBody(true), { employmentRecordId: EMPLOYMENT, replayed: false }), @@ -47,4 +56,4 @@ test("uses the published conflict error field rather than an invented error_code assert.equal(isGovernedSeparationConflict(409, { error: "separation_conflict" }), true); assert.equal(isGovernedSeparationConflict(409, { error_code: "separation_conflict" }), false); assert.equal(isGovernedSeparationConflict(404, { error: "separation_conflict" }), false); -}); +}); \ No newline at end of file From 8c2bc87977911c807a48c1bcf7cbf22f7e5c0ad9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 12:11:27 +0900 Subject: [PATCH 172/269] fix(perf): validate fixture preparation calendar exactly --- ...employment_separation_fixture_contract.mjs | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_fixture_contract.mjs b/tests/performance/employment_separation_fixture_contract.mjs index 7e1cd3727..b44a79cd8 100644 --- a/tests/performance/employment_separation_fixture_contract.mjs +++ b/tests/performance/employment_separation_fixture_contract.mjs @@ -1,6 +1,7 @@ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const ACTOR_PATTERN = /^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$/; const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/; +const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; const VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]*$/; const SHA_PATTERN = /^[0-9a-f]{40}$/; const BODY_KEYS = Object.freeze([ @@ -73,6 +74,29 @@ function requireFullDate(value, label) { return text; } +function requireUtcTimestamp(value, label) { + const text = requireString(value, label); + if (!UTC_TIMESTAMP_PATTERN.test(text)) fail(`${label} must be an RFC 3339 UTC timestamp`); + const year = Number(text.slice(0, 4)); + const month = Number(text.slice(5, 7)); + const day = Number(text.slice(8, 10)); + const hour = Number(text.slice(11, 13)); + const minute = Number(text.slice(14, 16)); + const second = Number(text.slice(17, 19)); + const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); + const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + if ( + month < 1 + || month > 12 + || day < 1 + || day > daysInMonth[month - 1] + || hour > 23 + || minute > 59 + || second > 59 + ) fail(`${label} must be an RFC 3339 UTC timestamp`); + return text; +} + function requireUuid(value, label) { const text = requireString(value, label); if (!UUID_PATTERN.test(text)) fail(`${label} must be a canonical UUID string`); @@ -161,10 +185,7 @@ export function validatePerformanceFixture( requireNamespacedReference(fixture.preparation_protocol_reference, "fixture.preparation_protocol_reference"); requireNamespacedReference(fixture.prepared_state_evidence_reference, "fixture.prepared_state_evidence_reference"); requireNamespacedReference(fixture.resource_evidence_reference, "fixture.resource_evidence_reference"); - const preparedAt = requireString(fixture.prepared_at, "fixture.prepared_at"); - if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/.test(preparedAt) || Number.isNaN(Date.parse(preparedAt))) { - fail("fixture.prepared_at must be an RFC 3339 UTC timestamp"); - } + requireUtcTimestamp(fixture.prepared_at, "fixture.prepared_at"); const candidateSha = requireString(fixture.candidate_sha, "fixture.candidate_sha").toLowerCase(); if (!SHA_PATTERN.test(candidateSha)) fail("fixture.candidate_sha must be a full Git commit SHA"); From ddb9469054970b492132afaa85c78129b0d2e381 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 12:11:39 +0900 Subject: [PATCH 173/269] fix(perf): validate response calendar timestamp exactly --- ...mployment_separation_response_contract.mjs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index 31e8a4cd2..ef760d0fe 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -5,6 +5,27 @@ function isPlainObject(value) { return value !== null && typeof value === "object" && !Array.isArray(value); } +function isValidUtcTimestamp(value) { + if (typeof value !== "string" || !UTC_TIMESTAMP_PATTERN.test(value)) return false; + const year = Number(value.slice(0, 4)); + const month = Number(value.slice(5, 7)); + const day = Number(value.slice(8, 10)); + const hour = Number(value.slice(11, 13)); + const minute = Number(value.slice(14, 16)); + const second = Number(value.slice(17, 19)); + const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); + const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + return ( + month >= 1 + && month <= 12 + && day >= 1 + && day <= daysInMonth[month - 1] + && hour <= 23 + && minute <= 59 + && second <= 59 + ); +} + export function isGovernedSeparationSuccess(status, body, { employmentRecordId, replayed }) { if (status !== 200 || !isPlainObject(body)) return false; if (typeof employmentRecordId !== "string" || !UUID_PATTERN.test(employmentRecordId)) return false; @@ -15,12 +36,10 @@ export function isGovernedSeparationSuccess(status, body, { employmentRecordId, if (typeof body.separated_employment_record_version_id !== "string" || !UUID_PATTERN.test(body.separated_employment_record_version_id)) { return false; } - if (typeof body.recorded_at !== "string" || !UTC_TIMESTAMP_PATTERN.test(body.recorded_at) || Number.isNaN(Date.parse(body.recorded_at))) { - return false; - } + if (!isValidUtcTimestamp(body.recorded_at)) return false; return body.replayed === replayed; } export function isGovernedSeparationConflict(status, body) { return status === 409 && isPlainObject(body) && body.error === "separation_conflict"; -} +} \ No newline at end of file From d62cf70620041d869f82fba8b6c14e6db77a9c13 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 13:02:05 +0900 Subject: [PATCH 174/269] test(perf): reject post-completion fixture preparation --- ...t_separation_acceptance_timestamp.test.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_timestamp.test.mjs b/tests/performance/employment_separation_acceptance_timestamp.test.mjs index 61e4ea366..4925e32c9 100644 --- a/tests/performance/employment_separation_acceptance_timestamp.test.mjs +++ b/tests/performance/employment_separation_acceptance_timestamp.test.mjs @@ -128,3 +128,22 @@ test("accepts equivalent fractional instants with trailing-zero spelling differe const evidence = validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES); assert.equal(evidence.structurally_valid, true); }); + +test("rejects a fixture prepared after the measured run completed", () => { + const performance = performanceResult(); + performance.completed_at = "2026-09-13T04:10:00.0001Z"; + const fixture = JSON.parse(FIXTURE_BYTES.toString("utf8")); + fixture.prepared_at = "2026-09-13T04:10:00.0009Z"; + const fixtureArtifact = render(fixture); + const fixtureSha256 = createHash("sha256").update(fixtureArtifact).digest("hex"); + performance.fixture_sha256 = fixtureSha256; + const artifact = render(performance); + const runtime = runtimeEvidence(artifact); + runtime.fixture_sha256 = fixtureSha256; + runtime.observed_at = "2026-09-13T04:10:00.001Z"; + + assert.throws( + () => validateEmploymentSeparationAcceptance(artifact, runtime, fixtureArtifact), + /fixture.prepared_at must not follow result.completed_at/, + ); +}); From e575fcec163953909bb0d3be93368b266c1882d7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 13:02:50 +0900 Subject: [PATCH 175/269] fix(perf): bind fixture preparation chronology --- .../performance/employment_separation_acceptance_contract.mjs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 7fdc243fa..1291a8374 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -290,6 +290,9 @@ function parseAndValidateFixture(fixtureArtifact, result, validatedResult) { if (fixture.candidate_sha.toLowerCase() !== validatedResult.candidateSha) { fail("fixture.candidate_sha must match result.candidate_sha"); } + if (compareUtcTimestamps(fixture.prepared_at, validatedResult.completedAt) > 0) { + fail("fixture.prepared_at must not follow result.completed_at"); + } for (const field of [ "dataset_id", "clearance_reference", From 662418e886320a91d9d1914ebf89dadb0c7f3123 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 13:03:18 +0900 Subject: [PATCH 176/269] test(perf): preserve equivalent preparation instants --- ...ent_separation_acceptance_timestamp.test.mjs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_timestamp.test.mjs b/tests/performance/employment_separation_acceptance_timestamp.test.mjs index 4925e32c9..e59f2c3c9 100644 --- a/tests/performance/employment_separation_acceptance_timestamp.test.mjs +++ b/tests/performance/employment_separation_acceptance_timestamp.test.mjs @@ -147,3 +147,20 @@ test("rejects a fixture prepared after the measured run completed", () => { /fixture.prepared_at must not follow result.completed_at/, ); }); + +test("accepts an equivalent fixture preparation instant with trailing-zero spelling differences", () => { + const performance = performanceResult(); + performance.completed_at = "2026-09-13T04:10:00.100Z"; + const fixture = JSON.parse(FIXTURE_BYTES.toString("utf8")); + fixture.prepared_at = "2026-09-13T04:10:00.1000Z"; + const fixtureArtifact = render(fixture); + const fixtureSha256 = createHash("sha256").update(fixtureArtifact).digest("hex"); + performance.fixture_sha256 = fixtureSha256; + const artifact = render(performance); + const runtime = runtimeEvidence(artifact); + runtime.fixture_sha256 = fixtureSha256; + runtime.observed_at = "2026-09-13T04:10:00.101Z"; + + const evidence = validateEmploymentSeparationAcceptance(artifact, runtime, fixtureArtifact); + assert.equal(evidence.structurally_valid, true); +}); From ed6bde1ba59a4822dc2307517657f4e75086ef12 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 14:01:18 +0900 Subject: [PATCH 177/269] test(perf): reject undeclared acceptance evidence fields --- ..._separation_acceptance_exact_keys.test.mjs | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_exact_keys.test.mjs diff --git a/tests/performance/employment_separation_acceptance_exact_keys.test.mjs b/tests/performance/employment_separation_acceptance_exact_keys.test.mjs new file mode 100644 index 000000000..c11b3adf5 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_exact_keys.test.mjs @@ -0,0 +1,112 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + acceptanceFixtureBytes, + acceptanceFixtureSha256, + acceptanceLoadModel, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; + +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); + +function performanceResult() { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: "a".repeat(40), + fixture_sha256: FIXTURE_SHA256, + selected_profile: "first_commit", + expected_iterations: 1000, + completed_iterations: 1000, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(1000), + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", + }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: 1000, rate: 40 } }, + checks: { values: { rate: 1, passes: 1000, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, + employment_separation_latency_samples: { values: { count: 1000, rate: 40 } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count: 1000 }, + }, + }, + }, + }; +} + +function artifact(result) { + return Buffer.from(`${JSON.stringify(result, null, 2)}\n`, "utf8"); +} + +function runtimeEvidence(resultArtifact) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: "a".repeat(40), + observed_service_sha: "a".repeat(40), + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), + fixture_sha256: FIXTURE_SHA256, + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(1000), + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42.5, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1.2, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +test("rejects undeclared top-level result evidence fields", () => { + const result = performanceResult(); + result.unreviewed_extension = "must-not-be-ignored"; + const resultArtifact = artifact(result); + + assert.throws( + () => validateEmploymentSeparationAcceptance( + resultArtifact, + runtimeEvidence(resultArtifact), + FIXTURE_BYTES, + ), + /result must contain exactly/, + ); +}); + +test("rejects undeclared top-level runtime evidence fields", () => { + const resultArtifact = artifact(performanceResult()); + const runtime = runtimeEvidence(resultArtifact); + runtime.unreviewed_extension = "must-not-be-ignored"; + + assert.throws( + () => validateEmploymentSeparationAcceptance(resultArtifact, runtime, FIXTURE_BYTES), + /runtime must contain exactly/, + ); +}); From e37e878ab0eddd3399ab471348583a98d5865558 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 14:02:27 +0900 Subject: [PATCH 178/269] fix(perf): close acceptance evidence schemas --- ...loyment_separation_acceptance_contract.mjs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 1291a8374..259e30c19 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -34,6 +34,54 @@ const RESIDUAL_FIELDS = Object.freeze([ "residual_pool_checkouts", "residual_pool_waiters", ]); +const RESULT_KEYS = Object.freeze([ + "candidate_sha", + "clearance_reference", + "completed_at", + "completed_iterations", + "dataset_id", + "expected_iterations", + "fixture_sha256", + "k6", + "load_model", + "minimum_contention_pairs", + "minimum_non_contending_records", + "preparation_protocol_reference", + "prepared_state_evidence_reference", + "profile_preconditions", + "resource_evidence_reference", + "sample_complete", + "schema_version", + "selected_profile", +]); +const RUNTIME_KEYS = Object.freeze([ + "candidate_sha", + "db_connections_max", + "db_pool_acquire_p95_ms", + "db_pool_in_use_max", + "db_pool_waiters_max", + "deployment_reference", + "environment_reference", + "fixture_sha256", + "host_cpu_percent_p95", + "host_rss_bytes_max", + "load_observation_reference", + "observed_at", + "observed_load_model", + "observed_service_sha", + "observer_reference", + "performance_result_sha256", + "residual_background_workers", + "residual_db_sessions", + "residual_http_tasks", + "residual_open_transactions", + "residual_pool_checkouts", + "residual_pool_waiters", + "residual_sockets", + "resource_evidence_reference", + "schema_version", + "selected_profile", +]); function fail(message) { throw new Error(message); @@ -197,6 +245,7 @@ function sameLoadModel(observed, declared) { } function validateResult(result) { + exactKeys(result, RESULT_KEYS, "result"); if (result.schema_version !== RESULT_SCHEMA) fail("result.schema_version is unsupported"); const candidateSha = sha(result.candidate_sha, "result.candidate_sha"); const fixtureSha256 = sha256(result.fixture_sha256, "result.fixture_sha256"); @@ -315,6 +364,7 @@ function parseAndValidateFixture(fixtureArtifact, result, validatedResult) { } function validateRuntimeEvidence(runtime, resultDigest, result, validatedResult, fixtureDigest) { + exactKeys(runtime, RUNTIME_KEYS, "runtime"); if (runtime.schema_version !== RUNTIME_SCHEMA) fail("runtime.schema_version is unsupported"); const candidateSha = sha(runtime.candidate_sha, "runtime.candidate_sha"); const observedServiceSha = sha(runtime.observed_service_sha, "runtime.observed_service_sha"); From 60c1f8c3193a7ba94734cdb905016815af1fa5a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 14:07:18 +0900 Subject: [PATCH 179/269] test(perf): reject duplicate JSON evidence members --- ...separation_duplicate_json_members.test.mjs | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 tests/performance/employment_separation_duplicate_json_members.test.mjs diff --git a/tests/performance/employment_separation_duplicate_json_members.test.mjs b/tests/performance/employment_separation_duplicate_json_members.test.mjs new file mode 100644 index 000000000..a90dc69e0 --- /dev/null +++ b/tests/performance/employment_separation_duplicate_json_members.test.mjs @@ -0,0 +1,143 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + acceptanceFixtureBytes, + acceptanceFixtureSha256, + acceptanceLoadModel, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; +import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; + +const CANDIDATE_SHA = "a".repeat(40); +const FIXTURE_BYTES = acceptanceFixtureBytes(); + +function performanceResult(fixtureSha256 = acceptanceFixtureSha256(FIXTURE_BYTES)) { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: CANDIDATE_SHA, + fixture_sha256: fixtureSha256, + selected_profile: "first_commit", + expected_iterations: 1000, + completed_iterations: 1000, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(1000), + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", + }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: 1000, rate: 40 } }, + checks: { values: { rate: 1, passes: 1000, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, + employment_separation_latency_samples: { values: { count: 1000, rate: 40 } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count: 1000 }, + }, + }, + }, + }; +} + +function render(value) { + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + +function runtimeEvidence(resultArtifact, fixtureSha256 = acceptanceFixtureSha256(FIXTURE_BYTES)) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: CANDIDATE_SHA, + observed_service_sha: CANDIDATE_SHA, + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), + fixture_sha256: fixtureSha256, + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(1000), + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42.5, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1.2, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +function duplicateCandidateSha(bytes) { + const text = bytes.toString("utf8"); + const needle = `"candidate_sha": "${CANDIDATE_SHA}"`; + const replacement = `"candidate_sha": "${"b".repeat(40)}",\n "candidate_\\u0073ha": "${CANDIDATE_SHA}"`; + assert.notEqual(text.indexOf(needle), -1); + return Buffer.from(text.replace(needle, replacement), "utf8"); +} + +test("rejects escaped-equivalent duplicate member names in result bytes", () => { + const resultArtifact = duplicateCandidateSha(render(performanceResult())); + assert.throws( + () => validateEmploymentSeparationAcceptance( + resultArtifact, + runtimeEvidence(resultArtifact), + FIXTURE_BYTES, + ), + /duplicate JSON object member name/, + ); +}); + +test("rejects escaped-equivalent duplicate member names in fixture bytes", () => { + const fixtureArtifact = duplicateCandidateSha(FIXTURE_BYTES); + const fixtureSha256 = acceptanceFixtureSha256(fixtureArtifact); + const resultArtifact = render(performanceResult(fixtureSha256)); + assert.throws( + () => validateEmploymentSeparationAcceptance( + resultArtifact, + runtimeEvidence(resultArtifact, fixtureSha256), + fixtureArtifact, + ), + /duplicate JSON object member name/, + ); +}); + +test("rejects duplicate runtime evidence member names before JSON last-value-wins collapse", () => { + const runtimeArtifact = Buffer.from( + `{"candidate_sha":"${"b".repeat(40)}","candidate_\\u0073ha":"${CANDIDATE_SHA}"}`, + "utf8", + ); + assert.throws(() => parseRuntimeEvidenceArtifact(runtimeArtifact), /duplicate JSON object member name/); +}); + +test("rejects duplicate member names recursively in nested result objects", () => { + const text = render(performanceResult()).toString("utf8"); + const needle = '"checks": {'; + const resultArtifact = Buffer.from(text.replace(needle, '"checks": {"values":{"rate":0}}, "ch\\u0065cks": {'), "utf8"); + assert.throws( + () => validateEmploymentSeparationAcceptance( + resultArtifact, + runtimeEvidence(resultArtifact), + FIXTURE_BYTES, + ), + /duplicate JSON object member name/, + ); +}); From 3548e9f4ad3ca862fe73aa583b7e0274b91dcb61 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 14:07:44 +0900 Subject: [PATCH 180/269] fix(perf): add duplicate-safe JSON parser --- tests/performance/strict_json_artifact.mjs | 105 +++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/performance/strict_json_artifact.mjs diff --git a/tests/performance/strict_json_artifact.mjs b/tests/performance/strict_json_artifact.mjs new file mode 100644 index 000000000..dd057d5a6 --- /dev/null +++ b/tests/performance/strict_json_artifact.mjs @@ -0,0 +1,105 @@ +function invalidJson(label, cause) { + if (cause === undefined) return new Error(`${label} must be valid JSON`); + return new Error(`${label} must be valid JSON`, { cause }); +} + +function skipWhitespace(text, start) { + let index = start; + while (index < text.length && /[\u0009\u000a\u000d\u0020]/u.test(text[index])) index += 1; + return index; +} + +function scanString(text, start, label) { + if (text[start] !== '"') throw invalidJson(label); + let index = start + 1; + while (index < text.length) { + const character = text[index]; + if (character === '"') { + const raw = text.slice(start, index + 1); + try { + return { end: index + 1, value: JSON.parse(raw) }; + } catch (error) { + throw invalidJson(label, error); + } + } + if (character === "\\") { + index += 1; + if (index >= text.length) throw invalidJson(label); + if (text[index] === "u") { + const escape = text.slice(index + 1, index + 5); + if (!/^[0-9a-fA-F]{4}$/u.test(escape)) throw invalidJson(label); + index += 5; + continue; + } + if (!['"', "\\", "/", "b", "f", "n", "r", "t"].includes(text[index])) { + throw invalidJson(label); + } + index += 1; + continue; + } + if (character.charCodeAt(0) < 0x20) throw invalidJson(label); + index += 1; + } + throw invalidJson(label); +} + +function scanPrimitive(text, start, label) { + let index = start; + while (index < text.length && !/[\u0009\u000a\u000d\u0020,\]}]/u.test(text[index])) index += 1; + if (index === start) throw invalidJson(label); + return index; +} + +function scanArray(text, start, label) { + let index = skipWhitespace(text, start + 1); + if (text[index] === "]") return index + 1; + while (index < text.length) { + index = scanValue(text, index, label); + index = skipWhitespace(text, index); + if (text[index] === "]") return index + 1; + if (text[index] !== ",") throw invalidJson(label); + index = skipWhitespace(text, index + 1); + } + throw invalidJson(label); +} + +function scanObject(text, start, label) { + const names = new Set(); + let index = skipWhitespace(text, start + 1); + if (text[index] === "}") return index + 1; + while (index < text.length) { + const member = scanString(text, index, label); + if (names.has(member.value)) { + throw new Error(`${label} must not contain duplicate JSON object member name ${JSON.stringify(member.value)}`); + } + names.add(member.value); + index = skipWhitespace(text, member.end); + if (text[index] !== ":") throw invalidJson(label); + index = scanValue(text, skipWhitespace(text, index + 1), label); + index = skipWhitespace(text, index); + if (text[index] === "}") return index + 1; + if (text[index] !== ",") throw invalidJson(label); + index = skipWhitespace(text, index + 1); + } + throw invalidJson(label); +} + +function scanValue(text, start, label) { + const index = skipWhitespace(text, start); + if (index >= text.length) throw invalidJson(label); + if (text[index] === "{") return scanObject(text, index, label); + if (text[index] === "[") return scanArray(text, index, label); + if (text[index] === '"') return scanString(text, index, label).end; + return scanPrimitive(text, index, label); +} + +export function parseStrictJsonText(text, label) { + if (typeof text !== "string") throw new TypeError(`${label} must be JSON text`); + const end = skipWhitespace(text, scanValue(text, 0, label)); + if (end !== text.length) throw invalidJson(label); + try { + return JSON.parse(text); + } catch (error) { + throw invalidJson(label, error); + } +} From 7bc8f9b0d98375fdb2845be242e994589707cabd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 14:07:55 +0900 Subject: [PATCH 181/269] fix(perf): reject duplicate runtime JSON members --- .../employment_separation_runtime_evidence_artifact.mjs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/performance/employment_separation_runtime_evidence_artifact.mjs b/tests/performance/employment_separation_runtime_evidence_artifact.mjs index e79898602..5dc71f665 100644 --- a/tests/performance/employment_separation_runtime_evidence_artifact.mjs +++ b/tests/performance/employment_separation_runtime_evidence_artifact.mjs @@ -1,6 +1,8 @@ import { createHash } from "node:crypto"; import { TextDecoder } from "node:util"; +import { parseStrictJsonText } from "./strict_json_artifact.mjs"; + function rawBytes(value) { if (value instanceof Uint8Array) return value; if (value instanceof ArrayBuffer) return new Uint8Array(value); @@ -20,12 +22,7 @@ export function parseRuntimeEvidenceArtifact(value) { throw new Error("runtime evidence must be non-empty JSON text"); } - let parsed; - try { - parsed = JSON.parse(text); - } catch (error) { - throw new Error("runtime evidence must be valid JSON", { cause: error }); - } + const parsed = parseStrictJsonText(text, "runtime evidence"); if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) { throw new Error("runtime evidence must be a JSON object"); } From e72d8575c4a6cf5dc3da8c5170b5c0de1a0f2bbb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 14:08:57 +0900 Subject: [PATCH 182/269] fix(perf): reject duplicate result and fixture JSON members --- .../employment_separation_acceptance_contract.mjs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 259e30c19..56901adb2 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -3,6 +3,7 @@ import { TextDecoder } from "node:util"; import { validatePerformanceFixture } from "./employment_separation_fixture_contract.mjs"; import { validatePerformanceLoadModel } from "./employment_separation_run_contract.mjs"; +import { parseStrictJsonText } from "./strict_json_artifact.mjs"; const RESULT_SCHEMA = "orgmetra.employment_separation.performance_result.v1"; const RUNTIME_SCHEMA = "orgmetra.employment_separation.runtime_evidence.v1"; @@ -206,12 +207,7 @@ function decodeStrictUtf8(value, label) { function parseJsonArtifact(value, label) { const { bytes, text } = decodeStrictUtf8(value, label); - let parsed; - try { - parsed = JSON.parse(text); - } catch (error) { - throw new Error(`${label} must be valid JSON`, { cause: error }); - } + const parsed = parseStrictJsonText(text, label); return { bytes, digest: createHash("sha256").update(bytes).digest("hex"), From ea5803823d7f850f26ce28c87c45d58f976f9b40 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 14:11:24 +0900 Subject: [PATCH 183/269] test(perf): bound strict JSON evidence nesting --- .../performance/strict_json_artifact.test.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/performance/strict_json_artifact.test.mjs diff --git a/tests/performance/strict_json_artifact.test.mjs b/tests/performance/strict_json_artifact.test.mjs new file mode 100644 index 000000000..1eff6b081 --- /dev/null +++ b/tests/performance/strict_json_artifact.test.mjs @@ -0,0 +1,19 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { parseStrictJsonText } from "./strict_json_artifact.mjs"; + +function nestedArray(depth) { + return `${"[".repeat(depth)}0${"]".repeat(depth)}`; +} + +test("accepts JSON evidence at the declared nesting boundary", () => { + assert.doesNotThrow(() => parseStrictJsonText(nestedArray(64), "evidence")); +}); + +test("rejects JSON evidence beyond the declared nesting boundary", () => { + assert.throws( + () => parseStrictJsonText(nestedArray(65), "evidence"), + /maximum JSON nesting depth 64/, + ); +}); From 8ebe03a1fb24cef59157f3d1d2e544a00f6396fd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 14:11:40 +0900 Subject: [PATCH 184/269] fix(perf): bound strict JSON evidence nesting --- tests/performance/strict_json_artifact.mjs | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/performance/strict_json_artifact.mjs b/tests/performance/strict_json_artifact.mjs index dd057d5a6..b89bfc623 100644 --- a/tests/performance/strict_json_artifact.mjs +++ b/tests/performance/strict_json_artifact.mjs @@ -1,3 +1,5 @@ +const MAX_JSON_NESTING_DEPTH = 64; + function invalidJson(label, cause) { if (cause === undefined) return new Error(`${label} must be valid JSON`); return new Error(`${label} must be valid JSON`, { cause }); @@ -50,11 +52,11 @@ function scanPrimitive(text, start, label) { return index; } -function scanArray(text, start, label) { +function scanArray(text, start, label, depth) { let index = skipWhitespace(text, start + 1); if (text[index] === "]") return index + 1; while (index < text.length) { - index = scanValue(text, index, label); + index = scanValue(text, index, label, depth); index = skipWhitespace(text, index); if (text[index] === "]") return index + 1; if (text[index] !== ",") throw invalidJson(label); @@ -63,7 +65,7 @@ function scanArray(text, start, label) { throw invalidJson(label); } -function scanObject(text, start, label) { +function scanObject(text, start, label, depth) { const names = new Set(); let index = skipWhitespace(text, start + 1); if (text[index] === "}") return index + 1; @@ -75,7 +77,7 @@ function scanObject(text, start, label) { names.add(member.value); index = skipWhitespace(text, member.end); if (text[index] !== ":") throw invalidJson(label); - index = scanValue(text, skipWhitespace(text, index + 1), label); + index = scanValue(text, skipWhitespace(text, index + 1), label, depth); index = skipWhitespace(text, index); if (text[index] === "}") return index + 1; if (text[index] !== ",") throw invalidJson(label); @@ -84,18 +86,23 @@ function scanObject(text, start, label) { throw invalidJson(label); } -function scanValue(text, start, label) { +function scanValue(text, start, label, depth) { const index = skipWhitespace(text, start); if (index >= text.length) throw invalidJson(label); - if (text[index] === "{") return scanObject(text, index, label); - if (text[index] === "[") return scanArray(text, index, label); + if (text[index] === "{" || text[index] === "[") { + if (depth >= MAX_JSON_NESTING_DEPTH) { + throw new Error(`${label} exceeds maximum JSON nesting depth ${MAX_JSON_NESTING_DEPTH}`); + } + if (text[index] === "{") return scanObject(text, index, label, depth + 1); + return scanArray(text, index, label, depth + 1); + } if (text[index] === '"') return scanString(text, index, label).end; return scanPrimitive(text, index, label); } export function parseStrictJsonText(text, label) { if (typeof text !== "string") throw new TypeError(`${label} must be JSON text`); - const end = skipWhitespace(text, scanValue(text, 0, label)); + const end = skipWhitespace(text, scanValue(text, 0, label, 0)); if (end !== text.length) throw invalidJson(label); try { return JSON.parse(text); From 1e1f6bdc8bf3e392e5a97aa53ed6dbf351b21876 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 15:03:34 +0900 Subject: [PATCH 185/269] test(perf): reject surplus fixture cardinality --- ...yment_separation_fixture_contract.test.mjs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/performance/employment_separation_fixture_contract.test.mjs b/tests/performance/employment_separation_fixture_contract.test.mjs index ddba629d2..fee18a34c 100644 --- a/tests/performance/employment_separation_fixture_contract.test.mjs +++ b/tests/performance/employment_separation_fixture_contract.test.mjs @@ -124,6 +124,29 @@ test("enforces minimum sample cardinality rather than silently shrinking the run ); }); +test("rejects surplus non-contending records before walking an unbounded profile", () => { + const value = fixture(); + value.profiles.replay = Array.from({ length: 1001 }, (_, index) => command(10000 + index)); + assert.throws( + () => validatePerformanceFixture(value, smallAcceptance), + /at most 1000 records/, + ); +}); + +test("rejects surplus contention pairs before walking an unbounded profile", () => { + const value = fixture(); + value.profiles.contention = Array.from({ length: 101 }, (_, index) => { + const left = command(20000 + index, `contention-left-${index.toString().padStart(4, "0")}`); + const right = structuredClone(left); + right.idempotency_key = `contention-right-${index.toString().padStart(4, "0")}`; + return { left, right }; + }); + assert.throws( + () => validatePerformanceFixture(value, smallAcceptance), + /at most 100 pairs/, + ); +}); + test("matches the production Idempotency-Key length and visible-ASCII contract", () => { const shortKey = fixture(); shortKey.profiles.first_commit[0].idempotency_key = "too-short"; From 45777abb8edcc8a98b4f5dd8a88481f3ed27b829 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 15:04:24 +0900 Subject: [PATCH 186/269] fix(perf): bound fixture profile cardinality --- .../employment_separation_fixture_contract.mjs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_fixture_contract.mjs b/tests/performance/employment_separation_fixture_contract.mjs index b44a79cd8..ae3d25e60 100644 --- a/tests/performance/employment_separation_fixture_contract.mjs +++ b/tests/performance/employment_separation_fixture_contract.mjs @@ -28,6 +28,8 @@ const PROFILE_PRECONDITIONS = Object.freeze({ rejection: "expected_version_stale_or_semantic_conflict", contention: "active_current_expected_version", }); +const MAXIMUM_NON_CONTENDING_RECORDS = 1000; +const MAXIMUM_CONTENTION_PAIRS = 100; function fail(message) { throw new Error(message); @@ -203,10 +205,16 @@ export function validatePerformanceFixture( if (!Array.isArray(profiles[profile]) || profiles[profile].length < minimumNonContendingRecords) { fail(`fixture.profiles.${profile} must contain at least ${minimumNonContendingRecords} records`); } + if (profiles[profile].length > MAXIMUM_NON_CONTENDING_RECORDS) { + fail(`fixture.profiles.${profile} must contain at most ${MAXIMUM_NON_CONTENDING_RECORDS} records`); + } } if (!Array.isArray(profiles.contention) || profiles.contention.length < minimumContentionPairs) { fail(`fixture.profiles.contention must contain at least ${minimumContentionPairs} pairs`); } + if (profiles.contention.length > MAXIMUM_CONTENTION_PAIRS) { + fail(`fixture.profiles.contention must contain at most ${MAXIMUM_CONTENTION_PAIRS} pairs`); + } const seenEmployment = new Set(); const seenKeys = new Set(); @@ -258,4 +266,4 @@ export function requestHeaders(command, bearerToken) { export function requestBody(command) { requireCommand(command, "command"); return JSON.stringify(command.payload); -} +} \ No newline at end of file From a3dfe3c40e122f55a8acad1f0b6082e03a7e923a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:03:29 +0900 Subject: [PATCH 187/269] test(perf): bound acceptance artifact bytes (#371) --- ...t_separation_artifact_byte_budget.test.mjs | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 tests/performance/employment_separation_artifact_byte_budget.test.mjs diff --git a/tests/performance/employment_separation_artifact_byte_budget.test.mjs b/tests/performance/employment_separation_artifact_byte_budget.test.mjs new file mode 100644 index 000000000..66d4f5fab --- /dev/null +++ b/tests/performance/employment_separation_artifact_byte_budget.test.mjs @@ -0,0 +1,132 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + ACCEPTANCE_CANDIDATE_SHA, + ACCEPTANCE_PROFILE_PRECONDITIONS, + acceptanceFixtureBytes, + acceptanceFixtureSha256, + acceptanceLoadModel, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; +import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; + +const MAXIMUM_RESULT_ARTIFACT_BYTES = 1024 * 1024; +const MAXIMUM_RUNTIME_EVIDENCE_BYTES = 1024 * 1024; +const MAXIMUM_FIXTURE_ARTIFACT_BYTES = 8 * 1024 * 1024; +const ITERATIONS = 1000; + +function render(value) { + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + +function padWithJsonWhitespace(bytes, maximumBytes) { + assert.ok(bytes.length <= maximumBytes, "test fixture must fit within the declared byte budget"); + return Buffer.concat([ + bytes, + Buffer.alloc(maximumBytes + 1 - bytes.length, 0x20), + ]); +} + +function result(fixtureSha256) { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + fixture_sha256: fixtureSha256, + selected_profile: "first_commit", + expected_iterations: ITERATIONS, + completed_iterations: ITERATIONS, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(ITERATIONS), + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { ...ACCEPTANCE_PROFILE_PRECONDITIONS }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: ITERATIONS } }, + checks: { values: { rate: 1 } }, + employment_separation_unexpected_response: { values: { rate: 0 } }, + employment_separation_latency_samples: { values: { count: ITERATIONS } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: ITERATIONS }, + }, + }, + }, + }; +} + +function runtime(resultArtifact, fixtureSha256) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + observed_service_sha: ACCEPTANCE_CANDIDATE_SHA, + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), + fixture_sha256: fixtureSha256, + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(ITERATIONS), + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +test("rejects oversized runtime evidence before UTF-8 decode or JSON scanning", () => { + const oversized = padWithJsonWhitespace(Buffer.from("{}", "utf8"), MAXIMUM_RUNTIME_EVIDENCE_BYTES); + assert.throws( + () => parseRuntimeEvidenceArtifact(oversized), + /runtime evidence must not exceed 1048576 bytes/, + ); +}); + +test("rejects oversized performance-result evidence before UTF-8 decode or JSON scanning", () => { + const fixtureBytes = acceptanceFixtureBytes(); + const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); + const resultBytes = padWithJsonWhitespace(render(result(fixtureSha256)), MAXIMUM_RESULT_ARTIFACT_BYTES); + + assert.throws( + () => validateEmploymentSeparationAcceptance( + resultBytes, + runtime(resultBytes, fixtureSha256), + fixtureBytes, + ), + /performance result must not exceed 1048576 bytes/, + ); +}); + +test("rejects oversized performance-fixture evidence before UTF-8 decode or JSON scanning", () => { + const fixtureBytes = padWithJsonWhitespace(acceptanceFixtureBytes(), MAXIMUM_FIXTURE_ARTIFACT_BYTES); + const fixtureSha256 = acceptanceFixtureSha256(fixtureBytes); + const resultBytes = render(result(fixtureSha256)); + + assert.throws( + () => validateEmploymentSeparationAcceptance( + resultBytes, + runtime(resultBytes, fixtureSha256), + fixtureBytes, + ), + /performance fixture must not exceed 8388608 bytes/, + ); +}); From 91a89679b84c7fbdfa8b514fe777271e8842b9a0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:04:00 +0900 Subject: [PATCH 188/269] fix(perf): bound runtime evidence bytes (#371) --- .../employment_separation_runtime_evidence_artifact.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/performance/employment_separation_runtime_evidence_artifact.mjs b/tests/performance/employment_separation_runtime_evidence_artifact.mjs index 5dc71f665..db565a292 100644 --- a/tests/performance/employment_separation_runtime_evidence_artifact.mjs +++ b/tests/performance/employment_separation_runtime_evidence_artifact.mjs @@ -3,6 +3,8 @@ import { TextDecoder } from "node:util"; import { parseStrictJsonText } from "./strict_json_artifact.mjs"; +const MAXIMUM_RUNTIME_EVIDENCE_BYTES = 1024 * 1024; + function rawBytes(value) { if (value instanceof Uint8Array) return value; if (value instanceof ArrayBuffer) return new Uint8Array(value); @@ -11,6 +13,10 @@ function rawBytes(value) { export function parseRuntimeEvidenceArtifact(value) { const bytes = rawBytes(value); + if (bytes.byteLength > MAXIMUM_RUNTIME_EVIDENCE_BYTES) { + throw new Error(`runtime evidence must not exceed ${MAXIMUM_RUNTIME_EVIDENCE_BYTES} bytes`); + } + let text; try { text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); From b175cdd50e07b5fed0d36d0004e22b1e32603518 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:04:48 +0900 Subject: [PATCH 189/269] fix(perf): bound result and fixture evidence bytes (#371) --- ...loyment_separation_acceptance_contract.mjs | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 56901adb2..5391ae648 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -13,6 +13,8 @@ const REFERENCE_PATTERN = /^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$/; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; const MINIMUM_NON_CONTENDING_RECORDS = 1000; const MINIMUM_CONTENTION_PAIRS = 100; +const MAXIMUM_RESULT_ARTIFACT_BYTES = 1024 * 1024; +const MAXIMUM_FIXTURE_ARTIFACT_BYTES = 8 * 1024 * 1024; const PROFILE_NAMES = Object.freeze(["first_commit", "replay", "rejection", "contention"]); const PROFILE_PRECONDITIONS = Object.freeze({ first_commit: "active_current_expected_version", @@ -193,8 +195,12 @@ function rawBytes(value, label) { fail(`${label} must be supplied as raw bytes`); } -function decodeStrictUtf8(value, label) { +function decodeStrictUtf8(value, label, maximumBytes) { const bytes = rawBytes(value, label); + if (bytes.byteLength > maximumBytes) { + fail(`${label} must not exceed ${maximumBytes} bytes`); + } + let text; try { text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); @@ -205,8 +211,8 @@ function decodeStrictUtf8(value, label) { return { bytes, text }; } -function parseJsonArtifact(value, label) { - const { bytes, text } = decodeStrictUtf8(value, label); +function parseJsonArtifact(value, label, maximumBytes) { + const { bytes, text } = decodeStrictUtf8(value, label, maximumBytes); const parsed = parseStrictJsonText(text, label); return { bytes, @@ -323,7 +329,11 @@ function validateResult(result) { } function parseAndValidateFixture(fixtureArtifact, result, validatedResult) { - const fixtureDocument = parseJsonArtifact(fixtureArtifact, "performance fixture"); + const fixtureDocument = parseJsonArtifact( + fixtureArtifact, + "performance fixture", + MAXIMUM_FIXTURE_ARTIFACT_BYTES, + ); if (fixtureDocument.digest !== validatedResult.fixtureSha256) { fail("result.fixture_sha256 does not bind the supplied performance fixture"); } @@ -414,7 +424,11 @@ function validateRuntimeEvidence(runtime, resultDigest, result, validatedResult, } export function validateEmploymentSeparationAcceptance(resultArtifact, runtimeEvidence, fixtureArtifact) { - const resultDocument = parseJsonArtifact(resultArtifact, "performance result"); + const resultDocument = parseJsonArtifact( + resultArtifact, + "performance result", + MAXIMUM_RESULT_ARTIFACT_BYTES, + ); const result = plainObject(resultDocument.parsed, "result"); const runtime = plainObject(runtimeEvidence, "runtime"); const validatedResult = validateResult(result); From cc88eafc7cf48424437b36b0f44d01308ce2f817 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:09:47 +0900 Subject: [PATCH 190/269] test(perf): compose structural and pinned k6 evidence (#372) --- ...ration_composed_evidence_contract.test.mjs | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 tests/performance/employment_separation_composed_evidence_contract.test.mjs diff --git a/tests/performance/employment_separation_composed_evidence_contract.test.mjs b/tests/performance/employment_separation_composed_evidence_contract.test.mjs new file mode 100644 index 000000000..29b5d5cb8 --- /dev/null +++ b/tests/performance/employment_separation_composed_evidence_contract.test.mjs @@ -0,0 +1,111 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + ACCEPTANCE_CANDIDATE_SHA, + ACCEPTANCE_PROFILE_PRECONDITIONS, + acceptanceFixtureBytes, + acceptanceFixtureSha256, + acceptanceLoadModel, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; +import { validatePinnedK6AcceptanceEvidence } from "./employment_separation_k6_evidence_contract.mjs"; +import { + PINNED_K6_IMAGE, + PINNED_K6_IMAGE_DIGEST, + PINNED_K6_RUNNER_IDENTITY, + PINNED_K6_VERSION, +} from "./employment_separation_k6_runtime_contract.mjs"; + +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); +const ITERATIONS = 1000; + +function performanceResult() { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + fixture_sha256: FIXTURE_SHA256, + k6_version: PINNED_K6_VERSION, + k6_image: PINNED_K6_IMAGE, + k6_image_digest: PINNED_K6_IMAGE_DIGEST, + k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, + selected_profile: "first_commit", + expected_iterations: ITERATIONS, + completed_iterations: ITERATIONS, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(ITERATIONS), + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { ...ACCEPTANCE_PROFILE_PRECONDITIONS }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: ITERATIONS } }, + checks: { values: { rate: 1 } }, + employment_separation_unexpected_response: { values: { rate: 0 } }, + employment_separation_latency_samples: { values: { count: ITERATIONS } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: ITERATIONS }, + }, + }, + }, + }; +} + +function runtimeEvidence(resultArtifact) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: ACCEPTANCE_CANDIDATE_SHA, + observed_service_sha: ACCEPTANCE_CANDIDATE_SHA, + observed_k6_version: PINNED_K6_VERSION, + observed_k6_image: PINNED_K6_IMAGE, + observed_k6_image_digest: PINNED_K6_IMAGE_DIGEST, + observed_k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), + fixture_sha256: FIXTURE_SHA256, + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(ITERATIONS), + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +test("one evidence pair satisfies both structural and pinned-k6 contracts", () => { + const resultArtifact = Buffer.from(`${JSON.stringify(performanceResult(), null, 2)}\n`, "utf8"); + const runtime = runtimeEvidence(resultArtifact); + + const structural = validateEmploymentSeparationAcceptance(resultArtifact, runtime, FIXTURE_BYTES); + const pinned = validatePinnedK6AcceptanceEvidence(resultArtifact, runtime); + + assert.equal(structural.structurally_valid, true); + assert.deepEqual(pinned, { + k6_version: PINNED_K6_VERSION, + k6_image: PINNED_K6_IMAGE, + k6_image_digest: PINNED_K6_IMAGE_DIGEST, + k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, + }); +}); From 6cd3afcff565ca568abe712de99bf8979cdc16e4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:10:59 +0900 Subject: [PATCH 191/269] fix(perf): admit governed pinned k6 identity fields (#372) --- ...loyment_separation_acceptance_contract.mjs | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 5391ae648..3c54949aa 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -57,6 +57,12 @@ const RESULT_KEYS = Object.freeze([ "schema_version", "selected_profile", ]); +const RESULT_K6_IDENTITY_KEYS = Object.freeze([ + "k6_version", + "k6_image", + "k6_image_digest", + "k6_runner_identity", +]); const RUNTIME_KEYS = Object.freeze([ "candidate_sha", "db_connections_max", @@ -85,6 +91,12 @@ const RUNTIME_KEYS = Object.freeze([ "schema_version", "selected_profile", ]); +const RUNTIME_K6_IDENTITY_KEYS = Object.freeze([ + "observed_k6_version", + "observed_k6_image", + "observed_k6_image_digest", + "observed_k6_runner_identity", +]); function fail(message) { throw new Error(message); @@ -105,11 +117,28 @@ function exactKeys(value, expected, label) { } } +function exactKeysWithOptionalGroup(value, required, optional, label) { + const actual = Object.keys(value); + const allowed = new Set([...required, ...optional]); + const requiredPresent = required.every((key) => Object.prototype.hasOwnProperty.call(value, key)); + const optionalPresent = optional.filter((key) => Object.prototype.hasOwnProperty.call(value, key)); + const hasUnknown = actual.some((key) => !allowed.has(key)); + const hasPartialOptionalGroup = optionalPresent.length !== 0 && optionalPresent.length !== optional.length; + if (!requiredPresent || hasUnknown || hasPartialOptionalGroup) { + fail(`${label} must contain exactly the required fields and either all or none of ${optional.join(", ")}`); + } +} + function stringValue(value, label) { if (typeof value !== "string" || value.trim() === "") fail(`${label} must be a non-empty string`); return value; } +function validateOptionalStringGroup(value, keys, label) { + if (!Object.prototype.hasOwnProperty.call(value, keys[0])) return; + for (const key of keys) stringValue(value[key], `${label}.${key}`); +} + function sha(value, label) { const text = stringValue(value, label).toLowerCase(); if (!SHA_PATTERN.test(text)) fail(`${label} must be a full Git commit SHA`); @@ -247,7 +276,8 @@ function sameLoadModel(observed, declared) { } function validateResult(result) { - exactKeys(result, RESULT_KEYS, "result"); + exactKeysWithOptionalGroup(result, RESULT_KEYS, RESULT_K6_IDENTITY_KEYS, "result"); + validateOptionalStringGroup(result, RESULT_K6_IDENTITY_KEYS, "result"); if (result.schema_version !== RESULT_SCHEMA) fail("result.schema_version is unsupported"); const candidateSha = sha(result.candidate_sha, "result.candidate_sha"); const fixtureSha256 = sha256(result.fixture_sha256, "result.fixture_sha256"); @@ -370,7 +400,8 @@ function parseAndValidateFixture(fixtureArtifact, result, validatedResult) { } function validateRuntimeEvidence(runtime, resultDigest, result, validatedResult, fixtureDigest) { - exactKeys(runtime, RUNTIME_KEYS, "runtime"); + exactKeysWithOptionalGroup(runtime, RUNTIME_KEYS, RUNTIME_K6_IDENTITY_KEYS, "runtime"); + validateOptionalStringGroup(runtime, RUNTIME_K6_IDENTITY_KEYS, "runtime"); if (runtime.schema_version !== RUNTIME_SCHEMA) fail("runtime.schema_version is unsupported"); const candidateSha = sha(runtime.candidate_sha, "runtime.candidate_sha"); const observedServiceSha = sha(runtime.observed_service_sha, "runtime.observed_service_sha"); From 188d93226629240abf69931fa7b8b937f5a5ae42 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:11:13 +0900 Subject: [PATCH 192/269] fix(perf): validate strict evidence before k6 composition (#372) --- tests/performance/employment_separation_acceptance_check.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index faaee6474..8e594a60b 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -21,12 +21,15 @@ async function main() { readFile(fixturePath), ]); const runtimeDocument = parseRuntimeEvidenceArtifact(runtimeBytes); - const k6Evidence = validatePinnedK6AcceptanceEvidence(resultBytes, runtimeDocument.parsed); const evidenceContract = validateEmploymentSeparationAcceptance( resultBytes, runtimeDocument.parsed, fixtureBytes, ); + // Structural validation owns the bounded/strict result parser. Run it before + // this secondary pinned-runtime interpretation so duplicate members, nesting + // abuse, and oversized result artifacts cannot reach ordinary JSON.parse first. + const k6Evidence = validatePinnedK6AcceptanceEvidence(resultBytes, runtimeDocument.parsed); process.stdout.write(`${JSON.stringify({ ...evidenceContract, ...k6Evidence, From dd802ece3f027a4e248684b5b034c3a784961ad7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:11:44 +0900 Subject: [PATCH 193/269] test(perf): cover k6 identity schema edges (#372) --- ...ration_composed_evidence_contract.test.mjs | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_composed_evidence_contract.test.mjs b/tests/performance/employment_separation_composed_evidence_contract.test.mjs index 29b5d5cb8..f43994d33 100644 --- a/tests/performance/employment_separation_composed_evidence_contract.test.mjs +++ b/tests/performance/employment_separation_composed_evidence_contract.test.mjs @@ -22,6 +22,10 @@ const FIXTURE_BYTES = acceptanceFixtureBytes(); const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); const ITERATIONS = 1000; +function render(value) { + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + function performanceResult() { return { schema_version: "orgmetra.employment_separation.performance_result.v1", @@ -95,7 +99,7 @@ function runtimeEvidence(resultArtifact) { } test("one evidence pair satisfies both structural and pinned-k6 contracts", () => { - const resultArtifact = Buffer.from(`${JSON.stringify(performanceResult(), null, 2)}\n`, "utf8"); + const resultArtifact = render(performanceResult()); const runtime = runtimeEvidence(resultArtifact); const structural = validateEmploymentSeparationAcceptance(resultArtifact, runtime, FIXTURE_BYTES); @@ -109,3 +113,44 @@ test("one evidence pair satisfies both structural and pinned-k6 contracts", () = k6_runner_identity: PINNED_K6_RUNNER_IDENTITY, }); }); + +test("structural schema rejects a partial result k6 identity group", () => { + const result = performanceResult(); + delete result.k6_runner_identity; + const resultArtifact = render(result); + + assert.throws( + () => validateEmploymentSeparationAcceptance( + resultArtifact, + runtimeEvidence(resultArtifact), + FIXTURE_BYTES, + ), + /either all or none of k6_version, k6_image, k6_image_digest, k6_runner_identity/, + ); +}); + +test("structural schema rejects a partial runtime k6 identity group", () => { + const resultArtifact = render(performanceResult()); + const runtime = runtimeEvidence(resultArtifact); + delete runtime.observed_k6_runner_identity; + + assert.throws( + () => validateEmploymentSeparationAcceptance(resultArtifact, runtime, FIXTURE_BYTES), + /either all or none of observed_k6_version, observed_k6_image, observed_k6_image_digest, observed_k6_runner_identity/, + ); +}); + +test("structural schema rejects non-string declared k6 identity evidence", () => { + const result = performanceResult(); + result.k6_version = 220; + const resultArtifact = render(result); + + assert.throws( + () => validateEmploymentSeparationAcceptance( + resultArtifact, + runtimeEvidence(resultArtifact), + FIXTURE_BYTES, + ), + /result.k6_version must be a non-empty string/, + ); +}); From 7d0f13b8e8d12b7a1ef57c2be32416fb3545fd95 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:12:47 +0900 Subject: [PATCH 194/269] test(perf): harden pinned k6 result parsing (#373) --- ...t_separation_k6_evidence_contract.test.mjs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/performance/employment_separation_k6_evidence_contract.test.mjs b/tests/performance/employment_separation_k6_evidence_contract.test.mjs index 8226a3586..14c297f8e 100644 --- a/tests/performance/employment_separation_k6_evidence_contract.test.mjs +++ b/tests/performance/employment_separation_k6_evidence_contract.test.mjs @@ -45,3 +45,32 @@ test("rejects matching-but-unpinned image digests in result evidence", () => { test("rejects runtime observation that does not identify the exact pinned image", () => { assert.throws(() => validatePinnedK6AcceptanceEvidence(resultBytes(), runtime({ observed_k6_runner_identity: "ghcr.io/grafana/k6@sha256:substitute" })), /runner identity/); }); + +test("rejects oversized result evidence before UTF-8 decode or JSON scanning", () => { + const ordinary = resultBytes(); + const oversized = Buffer.concat([ + ordinary, + Buffer.alloc((1024 * 1024) + 1 - ordinary.length, 0x20), + ]); + assert.throws( + () => validatePinnedK6AcceptanceEvidence(oversized, runtime()), + /performance result must not exceed 1048576 bytes/, + ); +}); + +test("rejects escaped-equivalent duplicate k6 identity members before JSON collapse", () => { + const duplicate = Buffer.from( + `{\"k6_version\":${JSON.stringify(PINNED_K6_VERSION)},` + + `\"k6_image\":${JSON.stringify(PINNED_K6_IMAGE)},` + + `\"k6_image_digest\":\"sha256:${"0".repeat(64)}\",` + + `\"k6_image_\\u0064igest\":${JSON.stringify(PINNED_K6_IMAGE_DIGEST)},` + + `\"k6_runner_identity\":${JSON.stringify(PINNED_K6_RUNNER_IDENTITY)}}\n`, + "utf8", + ); + + assert.doesNotThrow(() => JSON.parse(duplicate.toString("utf8"))); + assert.throws( + () => validatePinnedK6AcceptanceEvidence(duplicate, runtime()), + /duplicate JSON object member name "k6_image_digest"/, + ); +}); From 94e4a242f40b47697cc899aeec3c868dabe2c23e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:13:01 +0900 Subject: [PATCH 195/269] fix(perf): use bounded strict parser for pinned k6 evidence (#373) --- .../employment_separation_k6_evidence_contract.mjs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_k6_evidence_contract.mjs b/tests/performance/employment_separation_k6_evidence_contract.mjs index bbff86789..46579a725 100644 --- a/tests/performance/employment_separation_k6_evidence_contract.mjs +++ b/tests/performance/employment_separation_k6_evidence_contract.mjs @@ -7,18 +7,23 @@ import { PINNED_K6_VERSION, requirePinnedK6Runtime, } from "./employment_separation_k6_runtime_contract.mjs"; +import { parseStrictJsonText } from "./strict_json_artifact.mjs"; + +const MAXIMUM_RESULT_ARTIFACT_BYTES = 1024 * 1024; function fail(message) { throw new Error(message); } function parseResultBytes(value) { if (!(value instanceof Uint8Array) && !(value instanceof ArrayBuffer)) fail("performance result must be supplied as raw bytes"); const bytes = value instanceof Uint8Array ? value : new Uint8Array(value); + if (bytes.byteLength > MAXIMUM_RESULT_ARTIFACT_BYTES) { + fail(`performance result must not exceed ${MAXIMUM_RESULT_ARTIFACT_BYTES} bytes`); + } + let text; try { text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); } catch (error) { throw new Error("performance result must be valid UTF-8", { cause: error }); } - let result; - try { result = JSON.parse(text); } - catch (error) { throw new Error("performance result must be valid JSON", { cause: error }); } + const result = parseStrictJsonText(text, "performance result"); if (result === null || typeof result !== "object" || Array.isArray(result)) fail("performance result must be an object"); return result; } From 216143323ce6ea89ef4cf2a3d8b7683c9ab2e78b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:15:37 +0900 Subject: [PATCH 196/269] test(perf): reject oversized fixture before runner setup (#374) --- ...paration_benchmark_fixture_budget.test.mjs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/performance/run_employment_separation_benchmark_fixture_budget.test.mjs diff --git a/tests/performance/run_employment_separation_benchmark_fixture_budget.test.mjs b/tests/performance/run_employment_separation_benchmark_fixture_budget.test.mjs new file mode 100644 index 000000000..6edd5126b --- /dev/null +++ b/tests/performance/run_employment_separation_benchmark_fixture_budget.test.mjs @@ -0,0 +1,51 @@ +import assert from "node:assert/strict"; +import { mkdtempSync, rmSync, truncateSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; +import test from "node:test"; + +const runner = fileURLToPath(new URL("./run_employment_separation_benchmark.sh", import.meta.url)); +const MAXIMUM_FIXTURE_ARTIFACT_BYTES = 8 * 1024 * 1024; + +function repositoryHead() { + const result = spawnSync("git", ["rev-parse", "--verify", "HEAD"], { + cwd: fileURLToPath(new URL("../..", import.meta.url)), + encoding: "utf8", + }); + assert.equal(result.status, 0, result.stderr); + return result.stdout.trim(); +} + +test("runner rejects an oversized fixture before Podman availability or image checks", () => { + const directory = mkdtempSync(join(tmpdir(), "orgmetra-perf-fixture-budget-")); + try { + const fixture = join(directory, "fixture.json"); + const summary = join(directory, "summary.json"); + truncateSync(fixture, MAXIMUM_FIXTURE_ARTIFACT_BYTES + 1); + + const result = spawnSync("bash", [runner], { + cwd: fileURLToPath(new URL("../..", import.meta.url)), + encoding: "utf8", + env: { + ...process.env, + ORGMETRA_PERFORMANCE_TARGET_SHA: repositoryHead(), + ORGMETRA_PERFORMANCE_DATA_FILE: fixture, + ORGMETRA_PERFORMANCE_SUMMARY_FILE: summary, + ORGMETRA_PERFORMANCE_BASE_URL: "http://127.0.0.1:1", + ORGMETRA_PERFORMANCE_BEARER_TOKEN: "test-only-not-a-real-secret", + ORGMETRA_PERFORMANCE_PROFILE: "first_commit", + }, + }); + + assert.notEqual(result.status, 0); + assert.match( + result.stderr, + /performance fixture must not exceed 8388608 bytes/, + ); + assert.doesNotMatch(result.stderr, /podman is required|preload the exact pinned k6 image/); + } finally { + rmSync(directory, { recursive: true, force: true }); + } +}); From 7373f5b3e76667859dd96afa190c827579fbe390 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:16:12 +0900 Subject: [PATCH 197/269] fix(perf): preflight fixture byte ceiling before Podman (#374) --- .../run_employment_separation_benchmark.sh | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/performance/run_employment_separation_benchmark.sh b/tests/performance/run_employment_separation_benchmark.sh index 9a92bc725..27630b7cb 100755 --- a/tests/performance/run_employment_separation_benchmark.sh +++ b/tests/performance/run_employment_separation_benchmark.sh @@ -7,6 +7,7 @@ readonly PINNED_K6_IMAGE_DIGEST="sha256:9bd01d6941fca969cb61bb57d2da5ee9b385fe2a readonly PINNED_K6_RUNNER_IDENTITY="${PINNED_K6_IMAGE}@${PINNED_K6_IMAGE_DIGEST}" readonly PINNED_K6_CONTAINER_UID="12345" readonly PINNED_K6_CONTAINER_GID="12345" +readonly MAXIMUM_FIXTURE_ARTIFACT_BYTES="8388608" readonly WORKLOAD="/workspace/tests/performance/employment_separation_buyer_path.js" if (( $# != 0 )); then @@ -31,6 +32,19 @@ if [[ -n "${repository_status}" ]]; then exit 1 fi +fixture_path="${ORGMETRA_PERFORMANCE_DATA_FILE:-}" +summary_path="${ORGMETRA_PERFORMANCE_SUMMARY_FILE:-}" +if [[ -z "${fixture_path}" || ! -f "${fixture_path}" ]]; then + printf 'ORGMETRA_PERFORMANCE_DATA_FILE must point to the right-cleared fixture\n' >&2 + exit 1 +fi +fixture_path="$(realpath "${fixture_path}")" +fixture_bytes="$(stat --printf='%s' -- "${fixture_path}")" +if [[ ! "${fixture_bytes}" =~ ^[0-9]+$ ]] || (( fixture_bytes > MAXIMUM_FIXTURE_ARTIFACT_BYTES )); then + printf 'performance fixture must not exceed %s bytes\n' "${MAXIMUM_FIXTURE_ARTIFACT_BYTES}" >&2 + exit 1 +fi + if ! command -v podman >/dev/null 2>&1; then printf 'podman is required for the pinned commercial k6 runner\n' >&2 exit 1 @@ -71,17 +85,10 @@ if [[ -z "${workload_image_id}" ]] || ! podman image exists "${workload_image_id exit 1 fi -fixture_path="${ORGMETRA_PERFORMANCE_DATA_FILE:-}" -summary_path="${ORGMETRA_PERFORMANCE_SUMMARY_FILE:-}" -if [[ -z "${fixture_path}" || ! -f "${fixture_path}" ]]; then - printf 'ORGMETRA_PERFORMANCE_DATA_FILE must point to the right-cleared fixture\n' >&2 - exit 1 -fi if [[ -z "${summary_path}" ]]; then printf 'ORGMETRA_PERFORMANCE_SUMMARY_FILE is required\n' >&2 exit 1 fi -fixture_path="$(realpath "${fixture_path}")" summary_dir="$(realpath -m "$(dirname "${summary_path}")")" summary_name="$(basename "${summary_path}")" mkdir -p "${summary_dir}" From cc174e9f2fcd6d8b2b3ef1243f5921b0fd7f7c5b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:21:35 +0900 Subject: [PATCH 198/269] test(perf): cover direct k6 fixture artifact boundary (#375) --- ...yment_separation_fixture_artifact.test.mjs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/performance/employment_separation_fixture_artifact.test.mjs diff --git a/tests/performance/employment_separation_fixture_artifact.test.mjs b/tests/performance/employment_separation_fixture_artifact.test.mjs new file mode 100644 index 000000000..182f6d630 --- /dev/null +++ b/tests/performance/employment_separation_fixture_artifact.test.mjs @@ -0,0 +1,41 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { + MAXIMUM_PERFORMANCE_FIXTURE_BYTES, + parsePerformanceFixtureArtifact, + requirePerformanceFixtureByteBudget, +} from "./employment_separation_fixture_artifact.mjs"; + +const MAXIMUM_BYTES = 8 * 1024 * 1024; + +test("fixture byte budget is the governed 8 MiB ceiling", () => { + assert.equal(MAXIMUM_PERFORMANCE_FIXTURE_BYTES, MAXIMUM_BYTES); +}); + +test("direct workload boundary rejects oversized fixture bytes before parsing", () => { + const oversized = Buffer.alloc(MAXIMUM_BYTES + 1, 0x20); + assert.throws( + () => requirePerformanceFixtureByteBudget(oversized), + /performance fixture must not exceed 8388608 bytes/, + ); +}); + +test("direct workload boundary rejects escaped-equivalent duplicate JSON member names", () => { + const bytes = Buffer.from( + '{"schema_version":"one","schema_\\u0076ersion":"two"}\n', + "utf8", + ); + assert.doesNotThrow(() => JSON.parse(bytes.toString("utf8"))); + assert.throws( + () => parsePerformanceFixtureArtifact(bytes), + /duplicate JSON object member name "schema_version"/, + ); +}); + +test("direct workload boundary preserves ordinary valid JSON objects", () => { + assert.deepEqual( + parsePerformanceFixtureArtifact(Buffer.from('{"profiles":{}}\n', "utf8")), + { profiles: {} }, + ); +}); From 6e9a5783a28d8e89fb84116edf095e477253a1ff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:21:55 +0900 Subject: [PATCH 199/269] fix(perf): add strict bounded fixture artifact boundary (#375) --- ...employment_separation_fixture_artifact.mjs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/performance/employment_separation_fixture_artifact.mjs diff --git a/tests/performance/employment_separation_fixture_artifact.mjs b/tests/performance/employment_separation_fixture_artifact.mjs new file mode 100644 index 000000000..64ebb9d5b --- /dev/null +++ b/tests/performance/employment_separation_fixture_artifact.mjs @@ -0,0 +1,27 @@ +import { parseStrictJsonText } from "./strict_json_artifact.mjs"; + +export const MAXIMUM_PERFORMANCE_FIXTURE_BYTES = 8 * 1024 * 1024; + +export function requirePerformanceFixtureByteBudget(value) { + if (!(value instanceof Uint8Array) && !(value instanceof ArrayBuffer)) { + throw new Error("performance fixture must be supplied as raw bytes"); + } + if (value.byteLength > MAXIMUM_PERFORMANCE_FIXTURE_BYTES) { + throw new Error(`performance fixture must not exceed ${MAXIMUM_PERFORMANCE_FIXTURE_BYTES} bytes`); + } + return value; +} + +export function parsePerformanceFixtureArtifact(value) { + const bytes = requirePerformanceFixtureByteBudget(value); + let text; + try { + text = new TextDecoder("utf-8", { fatal: true }).decode(bytes); + } catch (error) { + throw new Error("performance fixture must be valid UTF-8", { cause: error }); + } + if (text.trim() === "") { + throw new Error("performance fixture must be non-empty JSON text"); + } + return parseStrictJsonText(text, "performance fixture"); +} From f3cb209a342592d85f8b081360f3d7c130ed94f0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:22:22 +0900 Subject: [PATCH 200/269] fix(perf): enforce strict bounded fixture parsing in k6 (#375) --- .../performance/employment_separation_buyer_path.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 7a90665e1..523a2b10f 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -4,6 +4,10 @@ import { check, fail } from "k6"; import exec from "k6/execution"; import { Counter, Rate, Trend } from "k6/metrics"; +import { + parsePerformanceFixtureArtifact, + requirePerformanceFixtureByteBudget, +} from "./employment_separation_fixture_artifact.mjs"; import { requestBody, requestHeaders, @@ -46,13 +50,11 @@ if (!bearerToken) fail("ORGMETRA_PERFORMANCE_BEARER_TOKEN is required and must n if (!/^[0-9a-f]{40}$/.test(targetSha)) fail("ORGMETRA_PERFORMANCE_TARGET_SHA must be a full Git commit SHA"); const fixtureBytes = open(fixturePath, "b"); +requirePerformanceFixtureByteBudget(fixtureBytes); const fixtureSha256 = crypto.sha256(fixtureBytes, "hex"); -let fixtureText; -try { fixtureText = new TextDecoder("utf-8", { fatal: true }).decode(fixtureBytes); } -catch (_) { fail("performance fixture must be valid UTF-8"); } let fixtureDocument; -try { fixtureDocument = JSON.parse(fixtureText); } -catch (_) { fail("performance fixture must be valid JSON"); } +try { fixtureDocument = parsePerformanceFixtureArtifact(fixtureBytes); } +catch (error) { fail(error.message); } const fixture = validatePerformanceFixture(fixtureDocument, { minimumNonContendingRecords: MINIMUM_NON_CONTENDING_RECORDS, minimumContentionPairs: MINIMUM_CONTENTION_PAIRS, From e104a6e3f34188219d97425044aec07bed1a49d8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:28:18 +0900 Subject: [PATCH 201/269] test(perf): expose ambiguous separation response JSON --- ...ment_separation_response_contract.test.mjs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 323b52af3..156ef6577 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -4,6 +4,7 @@ import test from "node:test"; import { isGovernedSeparationConflict, isGovernedSeparationSuccess, + parseGovernedSeparationResponseBody, } from "./employment_separation_response_contract.mjs"; const EMPLOYMENT = "30000000-0000-4000-8000-000000000001"; @@ -56,4 +57,20 @@ test("uses the published conflict error field rather than an invented error_code assert.equal(isGovernedSeparationConflict(409, { error: "separation_conflict" }), true); assert.equal(isGovernedSeparationConflict(409, { error_code: "separation_conflict" }), false); assert.equal(isGovernedSeparationConflict(404, { error: "separation_conflict" }), false); -}); \ No newline at end of file +}); + +test("strict response parsing rejects duplicate trust-bearing JSON members before semantic validation", () => { + assert.throws( + () => parseGovernedSeparationResponseBody(`{"employment_record_id":"${EMPLOYMENT}","separated_employment_record_version_id":"${VERSION}","recorded_at":"2026-09-13T02:00:00Z","replayed":true,"replayed":false}`), + /duplicate JSON object member name "replayed"/, + ); + assert.throws( + () => parseGovernedSeparationResponseBody('{"error":"separation_conflict","\\u0065rror":"separation_conflict"}'), + /duplicate JSON object member name "error"/, + ); +}); + +test("strict response parsing preserves the published response object", () => { + const body = successBody(false); + assert.deepEqual(parseGovernedSeparationResponseBody(JSON.stringify(body)), body); +}); From a0cd113f4062522edeb05c8e8a5c822dcfcdfb18 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:28:42 +0900 Subject: [PATCH 202/269] fix(perf): parse governed separation response JSON strictly --- .../employment_separation_response_contract.mjs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index ef760d0fe..614d5be02 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -1,3 +1,5 @@ +import { parseStrictJsonText } from "./strict_json_artifact.mjs"; + const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; @@ -26,6 +28,13 @@ function isValidUtcTimestamp(value) { ); } +export function parseGovernedSeparationResponseBody(value) { + if (typeof value !== "string") { + throw new Error("governed separation response body must be JSON text"); + } + return parseStrictJsonText(value, "governed separation response body"); +} + export function isGovernedSeparationSuccess(status, body, { employmentRecordId, replayed }) { if (status !== 200 || !isPlainObject(body)) return false; if (typeof employmentRecordId !== "string" || !UUID_PATTERN.test(employmentRecordId)) return false; @@ -42,4 +51,4 @@ export function isGovernedSeparationSuccess(status, body, { employmentRecordId, export function isGovernedSeparationConflict(status, body) { return status === 409 && isPlainObject(body) && body.error === "separation_conflict"; -} \ No newline at end of file +} From 0f5e32a46b4094e91a90491286f782aa3779599b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:29:05 +0900 Subject: [PATCH 203/269] fix(perf): enforce strict response parsing in k6 workload --- tests/performance/employment_separation_buyer_path.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 523a2b10f..1d7e157c6 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -17,6 +17,7 @@ import { requirePinnedK6Runtime } from "./employment_separation_k6_runtime_contr import { isGovernedSeparationConflict, isGovernedSeparationSuccess, + parseGovernedSeparationResponseBody, } from "./employment_separation_response_contract.mjs"; import { PERFORMANCE_SUMMARY_TREND_STATS, @@ -87,7 +88,10 @@ function recordAt(profile) { if (index < 0 || index >= records.length) fail(`${profile} iteration ${index} is outside the fixture`); return records[index]; } -function parseJson(response) { try { return response.json(); } catch (_) { return null; } } +function parseJson(response) { + try { return parseGovernedSeparationResponseBody(response.body); } + catch (_) { return null; } +} function post(command, profile) { return http.post(`${baseUrl}${ROUTE}`, requestBody(command), { headers: requestHeaders(command, bearerToken), tags: { profile } }); } From b7e024bf12bdc83b4d29a7ddf6da667ce70d5e5c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:33:18 +0900 Subject: [PATCH 204/269] test(perf): expose stale separation conflict envelope --- ...ment_separation_response_contract.test.mjs | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 156ef6577..9139fd5d2 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -19,6 +19,16 @@ function successBody(replayed = false) { }; } +function conflictBody(overrides = {}) { + return { + error_code: "separation_conflict", + message: "Refresh Employment and Assignment state, then retry.", + next_action: "Refresh Employment and Assignment state, then retry.", + support_reference: "err_ABCDEFGHIJKLMNOPQRSTUVWX", + ...overrides, + }; +} + test("accepts the published first-commit and replay response shape", () => { assert.equal( isGovernedSeparationSuccess(200, successBody(false), { employmentRecordId: EMPLOYMENT, replayed: false }), @@ -53,10 +63,13 @@ test("rejects success responses that are replay- or target-inconsistent", () => ); }); -test("uses the published conflict error field rather than an invented error_code field", () => { - assert.equal(isGovernedSeparationConflict(409, { error: "separation_conflict" }), true); +test("accepts only the published closed ErrorResponse shape for separation conflicts", () => { + assert.equal(isGovernedSeparationConflict(409, conflictBody()), true); + assert.equal(isGovernedSeparationConflict(409, { error: "separation_conflict" }), false); assert.equal(isGovernedSeparationConflict(409, { error_code: "separation_conflict" }), false); - assert.equal(isGovernedSeparationConflict(404, { error: "separation_conflict" }), false); + assert.equal(isGovernedSeparationConflict(409, conflictBody({ support_reference: "trace-123" })), false); + assert.equal(isGovernedSeparationConflict(409, { ...conflictBody(), extra: "undeclared" }), false); + assert.equal(isGovernedSeparationConflict(404, conflictBody()), false); }); test("strict response parsing rejects duplicate trust-bearing JSON members before semantic validation", () => { @@ -65,8 +78,8 @@ test("strict response parsing rejects duplicate trust-bearing JSON members befor /duplicate JSON object member name "replayed"/, ); assert.throws( - () => parseGovernedSeparationResponseBody('{"error":"separation_conflict","\\u0065rror":"separation_conflict"}'), - /duplicate JSON object member name "error"/, + () => parseGovernedSeparationResponseBody('{"error_code":"separation_conflict","\\u0065rror_code":"separation_conflict"}'), + /duplicate JSON object member name "error_code"/, ); }); From aa0889e85a6464e057efacbec53f7055e3cabb87 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 16:33:32 +0900 Subject: [PATCH 205/269] fix(perf): validate published separation conflict envelope --- ...mployment_separation_response_contract.mjs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index 614d5be02..fb1b6dcce 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -2,11 +2,24 @@ import { parseStrictJsonText } from "./strict_json_artifact.mjs"; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; +const SUPPORT_REFERENCE_PATTERN = /^err_[A-Za-z0-9_-]{20,80}$/; +const ERROR_RESPONSE_KEYS = Object.freeze([ + "error_code", + "message", + "next_action", + "support_reference", +]); function isPlainObject(value) { return value !== null && typeof value === "object" && !Array.isArray(value); } +function hasExactKeys(value, expectedKeys) { + const actual = Object.keys(value).sort(); + const expected = [...expectedKeys].sort(); + return actual.length === expected.length && actual.every((key, index) => key === expected[index]); +} + function isValidUtcTimestamp(value) { if (typeof value !== "string" || !UTC_TIMESTAMP_PATTERN.test(value)) return false; const year = Number(value.slice(0, 4)); @@ -50,5 +63,9 @@ export function isGovernedSeparationSuccess(status, body, { employmentRecordId, } export function isGovernedSeparationConflict(status, body) { - return status === 409 && isPlainObject(body) && body.error === "separation_conflict"; + if (status !== 409 || !isPlainObject(body) || !hasExactKeys(body, ERROR_RESPONSE_KEYS)) return false; + if (body.error_code !== "separation_conflict") return false; + if (typeof body.message !== "string" || body.message.length < 1 || body.message.length > 1000) return false; + if (typeof body.next_action !== "string" || body.next_action.length < 1 || body.next_action.length > 1000) return false; + return typeof body.support_reference === "string" && SUPPORT_REFERENCE_PATTERN.test(body.support_reference); } From 5835c61d8cf1a78fe1c6ccb5aba0f5aed4a2f864 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 17:01:49 +0900 Subject: [PATCH 206/269] test(perf): reject undeclared success response fields --- .../employment_separation_response_contract.test.mjs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 9139fd5d2..fb0c1834b 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -40,6 +40,17 @@ test("accepts the published first-commit and replay response shape", () => { ); }); +test("rejects undeclared fields in the published success response envelope", () => { + assert.equal( + isGovernedSeparationSuccess( + 200, + { ...successBody(false), extra: "undeclared" }, + { employmentRecordId: EMPLOYMENT, replayed: false }, + ), + false, + ); +}); + test("rejects impossible success-response calendar timestamps", () => { const body = successBody(false); body.recorded_at = "2026-02-30T02:00:00Z"; From 4fa51a69afbf034939daf2ae22db5ee841a74859 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 17:02:19 +0900 Subject: [PATCH 207/269] fix(perf): close governed success response envelope --- .../employment_separation_response_contract.mjs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index fb1b6dcce..6d1924897 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -3,6 +3,12 @@ import { parseStrictJsonText } from "./strict_json_artifact.mjs"; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; const SUPPORT_REFERENCE_PATTERN = /^err_[A-Za-z0-9_-]{20,80}$/; +const SUCCESS_RESPONSE_KEYS = Object.freeze([ + "employment_record_id", + "separated_employment_record_version_id", + "recorded_at", + "replayed", +]); const ERROR_RESPONSE_KEYS = Object.freeze([ "error_code", "message", @@ -49,7 +55,7 @@ export function parseGovernedSeparationResponseBody(value) { } export function isGovernedSeparationSuccess(status, body, { employmentRecordId, replayed }) { - if (status !== 200 || !isPlainObject(body)) return false; + if (status !== 200 || !isPlainObject(body) || !hasExactKeys(body, SUCCESS_RESPONSE_KEYS)) return false; if (typeof employmentRecordId !== "string" || !UUID_PATTERN.test(employmentRecordId)) return false; if (typeof replayed !== "boolean") return false; if (typeof body.employment_record_id !== "string" || body.employment_record_id.toLowerCase() !== employmentRecordId.toLowerCase()) { From 15facbc41c8dce7d428196efad14ee23db8dcfa6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 17:07:01 +0900 Subject: [PATCH 208/269] test(perf): reject sentinel separation version identities --- ...loyment_separation_response_contract.test.mjs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index fb0c1834b..30136fb77 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -51,6 +51,22 @@ test("rejects undeclared fields in the published success response envelope", () ); }); +test("rejects sentinel separated-version identities in governed success evidence", () => { + for (const separatedVersionId of [ + "00000000-0000-0000-0000-000000000000", + "ffffffff-ffff-ffff-ffff-ffffffffffff", + ]) { + assert.equal( + isGovernedSeparationSuccess( + 200, + { ...successBody(false), separated_employment_record_version_id: separatedVersionId }, + { employmentRecordId: EMPLOYMENT, replayed: false }, + ), + false, + ); + } +}); + test("rejects impossible success-response calendar timestamps", () => { const body = successBody(false); body.recorded_at = "2026-02-30T02:00:00Z"; From 8abcbda870a12143be1046f6b94e2e8a20814808 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 17:07:51 +0900 Subject: [PATCH 209/269] fix(perf): require operational success response UUIDs --- .../employment_separation_response_contract.mjs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index 6d1924897..06ecd43f8 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -26,6 +26,12 @@ function hasExactKeys(value, expectedKeys) { return actual.length === expected.length && actual.every((key, index) => key === expected[index]); } +function isOperationalUuid(value) { + if (typeof value !== "string" || !UUID_PATTERN.test(value)) return false; + const compact = value.replaceAll("-", "").toLowerCase(); + return compact !== "0".repeat(32) && compact !== "f".repeat(32); +} + function isValidUtcTimestamp(value) { if (typeof value !== "string" || !UTC_TIMESTAMP_PATTERN.test(value)) return false; const year = Number(value.slice(0, 4)); @@ -56,14 +62,12 @@ export function parseGovernedSeparationResponseBody(value) { export function isGovernedSeparationSuccess(status, body, { employmentRecordId, replayed }) { if (status !== 200 || !isPlainObject(body) || !hasExactKeys(body, SUCCESS_RESPONSE_KEYS)) return false; - if (typeof employmentRecordId !== "string" || !UUID_PATTERN.test(employmentRecordId)) return false; + if (!isOperationalUuid(employmentRecordId)) return false; if (typeof replayed !== "boolean") return false; - if (typeof body.employment_record_id !== "string" || body.employment_record_id.toLowerCase() !== employmentRecordId.toLowerCase()) { - return false; - } - if (typeof body.separated_employment_record_version_id !== "string" || !UUID_PATTERN.test(body.separated_employment_record_version_id)) { + if (!isOperationalUuid(body.employment_record_id) || body.employment_record_id.toLowerCase() !== employmentRecordId.toLowerCase()) { return false; } + if (!isOperationalUuid(body.separated_employment_record_version_id)) return false; if (!isValidUtcTimestamp(body.recorded_at)) return false; return body.replayed === replayed; } From e70269ce4381a5da772aa20fe0cadf2f3fd0e261 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 18:22:40 +0900 Subject: [PATCH 210/269] test(perf): expose Gregorian year-bound mismatch --- ..._separation_gregorian_year_bounds.test.mjs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/performance/employment_separation_gregorian_year_bounds.test.mjs diff --git a/tests/performance/employment_separation_gregorian_year_bounds.test.mjs b/tests/performance/employment_separation_gregorian_year_bounds.test.mjs new file mode 100644 index 000000000..53add1741 --- /dev/null +++ b/tests/performance/employment_separation_gregorian_year_bounds.test.mjs @@ -0,0 +1,31 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { acceptanceFixture } from "./employment_separation_acceptance_fixture_test_support.mjs"; +import { validatePerformanceFixture } from "./employment_separation_fixture_contract.mjs"; + +const smallAcceptance = { minimumNonContendingRecords: 1, minimumContentionPairs: 1 }; + +function smallFixture() { + const value = acceptanceFixture(); + value.profiles.first_commit = value.profiles.first_commit.slice(0, 1); + value.profiles.replay = value.profiles.replay.slice(0, 1); + value.profiles.rejection = value.profiles.rejection.slice(0, 1); + value.profiles.contention = value.profiles.contention.slice(0, 1); + return value; +} + +test("accepts the earliest People business date without ECMAScript year normalization", () => { + const value = smallFixture(); + value.profiles.first_commit[0].payload.separation_effective_on = "0001-01-01"; + assert.doesNotThrow(() => validatePerformanceFixture(value, smallAcceptance)); +}); + +test("rejects year zero in governed UTC evidence timestamps", () => { + const value = smallFixture(); + value.prepared_at = "0000-01-01T00:00:00Z"; + assert.throws( + () => validatePerformanceFixture(value, smallAcceptance), + /fixture.prepared_at must be an RFC 3339 UTC timestamp/, + ); +}); From a7c885544fbcac8d273cb10c04fb3bfcb84805d6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 18:27:42 +0900 Subject: [PATCH 211/269] fix(perf): align Gregorian year bounds --- ...employment_separation_fixture_contract.mjs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/performance/employment_separation_fixture_contract.mjs b/tests/performance/employment_separation_fixture_contract.mjs index ae3d25e60..cf8ff2130 100644 --- a/tests/performance/employment_separation_fixture_contract.mjs +++ b/tests/performance/employment_separation_fixture_contract.mjs @@ -63,16 +63,18 @@ function requireNamespacedReference(value, label) { return text; } +function daysInGregorianMonth(year, month) { + if (year < 1 || year > 9999 || month < 1 || month > 12) return 0; + const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); + return [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1]; +} + function requireFullDate(value, label) { const text = requireString(value, label); if (!DATE_PATTERN.test(text)) fail(`${label} must be an RFC 3339 full-date`); const [year, month, day] = text.split("-").map(Number); - const parsed = new Date(Date.UTC(year, month - 1, day)); - if ( - parsed.getUTCFullYear() !== year - || parsed.getUTCMonth() !== month - 1 - || parsed.getUTCDate() !== day - ) fail(`${label} must be an RFC 3339 full-date`); + const maximumDay = daysInGregorianMonth(year, month); + if (maximumDay === 0 || day < 1 || day > maximumDay) fail(`${label} must be an RFC 3339 full-date`); return text; } @@ -85,13 +87,11 @@ function requireUtcTimestamp(value, label) { const hour = Number(text.slice(11, 13)); const minute = Number(text.slice(14, 16)); const second = Number(text.slice(17, 19)); - const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); - const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + const maximumDay = daysInGregorianMonth(year, month); if ( - month < 1 - || month > 12 + maximumDay === 0 || day < 1 - || day > daysInMonth[month - 1] + || day > maximumDay || hour > 23 || minute > 59 || second > 59 @@ -266,4 +266,4 @@ export function requestHeaders(command, bearerToken) { export function requestBody(command) { requireCommand(command, "command"); return JSON.stringify(command.payload); -} \ No newline at end of file +} From c0c87120f44b9046f556041f6662c57457e41f28 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 18:28:31 +0900 Subject: [PATCH 212/269] test(perf): cover Gregorian year boundaries --- ..._separation_gregorian_year_bounds.test.mjs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/performance/employment_separation_gregorian_year_bounds.test.mjs b/tests/performance/employment_separation_gregorian_year_bounds.test.mjs index 53add1741..7cc9e71d7 100644 --- a/tests/performance/employment_separation_gregorian_year_bounds.test.mjs +++ b/tests/performance/employment_separation_gregorian_year_bounds.test.mjs @@ -21,6 +21,29 @@ test("accepts the earliest People business date without ECMAScript year normaliz assert.doesNotThrow(() => validatePerformanceFixture(value, smallAcceptance)); }); +test("accepts the latest People business date in the four-digit contract", () => { + const value = smallFixture(); + value.profiles.first_commit[0].payload.separation_effective_on = "9999-12-31"; + assert.doesNotThrow(() => validatePerformanceFixture(value, smallAcceptance)); +}); + +test("rejects year zero in People business dates", () => { + const value = smallFixture(); + value.profiles.first_commit[0].payload.separation_effective_on = "0000-01-01"; + assert.throws( + () => validatePerformanceFixture(value, smallAcceptance), + /separation_effective_on must be an RFC 3339 full-date/, + ); +}); + +test("accepts the governed UTC timestamp year boundaries", () => { + for (const preparedAt of ["0001-01-01T00:00:00Z", "9999-12-31T23:59:59.999999Z"]) { + const value = smallFixture(); + value.prepared_at = preparedAt; + assert.doesNotThrow(() => validatePerformanceFixture(value, smallAcceptance)); + } +}); + test("rejects year zero in governed UTC evidence timestamps", () => { const value = smallFixture(); value.prepared_at = "0000-01-01T00:00:00Z"; From 3aebf99c8bc78f78eaec0c572c148a80246d3b14 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 18:31:20 +0900 Subject: [PATCH 213/269] test(perf): reject year zero in acceptance timestamps --- ...t_separation_acceptance_timestamp.test.mjs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/performance/employment_separation_acceptance_timestamp.test.mjs b/tests/performance/employment_separation_acceptance_timestamp.test.mjs index e59f2c3c9..585ac42b5 100644 --- a/tests/performance/employment_separation_acceptance_timestamp.test.mjs +++ b/tests/performance/employment_separation_acceptance_timestamp.test.mjs @@ -105,6 +105,29 @@ test("rejects an impossible runtime observation calendar date instead of accepti ); }); +test("rejects year zero in result completion evidence before chronology comparison", () => { + const performance = performanceResult(); + performance.completed_at = "0000-01-01T00:00:00Z"; + const artifact = render(performance); + + assert.throws( + () => validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES), + /result.completed_at must be an RFC 3339 UTC timestamp/, + ); +}); + +test("rejects year zero in runtime observation evidence before chronology comparison", () => { + const performance = performanceResult(); + const artifact = render(performance); + const runtime = runtimeEvidence(artifact); + runtime.observed_at = "0000-01-01T00:00:00Z"; + + assert.throws( + () => validateEmploymentSeparationAcceptance(artifact, runtime, FIXTURE_BYTES), + /runtime.observed_at must be an RFC 3339 UTC timestamp/, + ); +}); + test("rejects a sub-millisecond runtime observation that precedes completion", () => { const performance = performanceResult(); performance.completed_at = "2026-09-13T04:10:00.0009Z"; From 7b8ce8efe71aaad69ea1c84aa53668874240fd4d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 18:32:09 +0900 Subject: [PATCH 214/269] fix(perf): align acceptance timestamp year bounds --- .../performance/employment_separation_acceptance_contract.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 3c54949aa..54e03a96b 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -172,7 +172,9 @@ function utcTimestamp(value, label) { const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; if ( - month < 1 + year < 1 + || year > 9999 + || month < 1 || month > 12 || day < 1 || day > daysInMonth[month - 1] From 62d911dd286fe47e03a41fad99227f564b16bae2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 18:38:50 +0900 Subject: [PATCH 215/269] chore(perf): integrate current People parent delta --- ...t_authenticated_principal_snapshot_integrity.py | 14 +++++++++++--- .../test_authorization_principal_integrity.py | 14 +++++++++++--- ...es_mutation_authorization_evidence_integrity.py | 8 ++++++++ .../tests/test_uuid_payload_integrity.py | 8 ++++++++ 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/services/people-api/tests/test_authenticated_principal_snapshot_integrity.py b/services/people-api/tests/test_authenticated_principal_snapshot_integrity.py index 5686fcade..aeb6a880d 100644 --- a/services/people-api/tests/test_authenticated_principal_snapshot_integrity.py +++ b/services/people-api/tests/test_authenticated_principal_snapshot_integrity.py @@ -29,15 +29,23 @@ class _ExecutableUuidPayload: def __eq__(self, other: object) -> bool: type(self).comparisons += 1 - raise AssertionError("forged UUID payload must not participate in comparison") + raise TypeError("forged UUID payload must not participate in comparison") def __lt__(self, other: object) -> bool: type(self).comparisons += 1 - raise AssertionError("forged UUID payload must not participate in ordering") + raise TypeError("forged UUID payload must not participate in ordering") + + def __le__(self, other: object) -> bool: + type(self).comparisons += 1 + raise TypeError("forged UUID payload must not participate in ordering") def __gt__(self, other: object) -> bool: type(self).comparisons += 1 - raise AssertionError("forged UUID payload must not participate in ordering") + raise TypeError("forged UUID payload must not participate in ordering") + + def __ge__(self, other: object) -> bool: + type(self).comparisons += 1 + raise TypeError("forged UUID payload must not participate in ordering") class _TextSubtype(str): diff --git a/services/people-api/tests/test_authorization_principal_integrity.py b/services/people-api/tests/test_authorization_principal_integrity.py index 2eba0965a..c4bf1695e 100644 --- a/services/people-api/tests/test_authorization_principal_integrity.py +++ b/services/people-api/tests/test_authorization_principal_integrity.py @@ -30,15 +30,23 @@ class _ExecutableUuidPayload: def __eq__(self, other: object) -> bool: type(self).comparisons += 1 - raise AssertionError("forged UUID payload must not participate in comparison") + raise TypeError("forged UUID payload must not participate in comparison") def __lt__(self, other: object) -> bool: type(self).comparisons += 1 - raise AssertionError("forged UUID payload must not participate in ordering") + raise TypeError("forged UUID payload must not participate in ordering") + + def __le__(self, other: object) -> bool: + type(self).comparisons += 1 + raise TypeError("forged UUID payload must not participate in ordering") def __gt__(self, other: object) -> bool: type(self).comparisons += 1 - raise AssertionError("forged UUID payload must not participate in ordering") + raise TypeError("forged UUID payload must not participate in ordering") + + def __ge__(self, other: object) -> bool: + type(self).comparisons += 1 + raise TypeError("forged UUID payload must not participate in ordering") class _TextSubtype(str): diff --git a/services/people-api/tests/test_postgres_mutation_authorization_evidence_integrity.py b/services/people-api/tests/test_postgres_mutation_authorization_evidence_integrity.py index f7637b2ee..841e94e68 100644 --- a/services/people-api/tests/test_postgres_mutation_authorization_evidence_integrity.py +++ b/services/people-api/tests/test_postgres_mutation_authorization_evidence_integrity.py @@ -68,10 +68,18 @@ def __lt__(self, other: object) -> bool: type(self).calls += 1 raise TypeError("authorization UUID ordering executed before validation") + def __le__(self, other: object) -> bool: + type(self).calls += 1 + raise TypeError("authorization UUID ordering executed before validation") + def __gt__(self, other: object) -> bool: type(self).calls += 1 raise TypeError("authorization UUID ordering executed before validation") + def __ge__(self, other: object) -> bool: + type(self).calls += 1 + raise TypeError("authorization UUID ordering executed before validation") + def _require(decision: AuthorizationDecision) -> AuthorizationDecision: return _require_authorization( diff --git a/services/people-api/tests/test_uuid_payload_integrity.py b/services/people-api/tests/test_uuid_payload_integrity.py index 8a30621c1..3ff36f3ce 100644 --- a/services/people-api/tests/test_uuid_payload_integrity.py +++ b/services/people-api/tests/test_uuid_payload_integrity.py @@ -35,10 +35,18 @@ def __lt__(self, other: object) -> bool: self.calls += 1 raise TypeError("UUID payload ordering executed before exact integer validation") + def __le__(self, other: object) -> bool: + self.calls += 1 + raise TypeError("UUID payload ordering executed before exact integer validation") + def __gt__(self, other: object) -> bool: self.calls += 1 raise TypeError("UUID payload ordering executed before exact integer validation") + def __ge__(self, other: object) -> bool: + self.calls += 1 + raise TypeError("UUID payload ordering executed before exact integer validation") + def _forged_uuid(payload: object) -> UUID: From 93231ffcd02471e5885ed0283d2c8e2d107f7513 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 18:56:36 +0900 Subject: [PATCH 216/269] test(perf): cover response recorded_at year bounds --- ...ment_separation_response_contract.test.mjs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 30136fb77..0e4355ac5 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -76,6 +76,27 @@ test("rejects impossible success-response calendar timestamps", () => { ); }); +test("keeps success-response recorded_at inside the People datetime year domain", () => { + for (const recordedAt of ["0001-01-01T00:00:00Z", "9999-12-31T23:59:59.999999Z"]) { + assert.equal( + isGovernedSeparationSuccess( + 200, + { ...successBody(false), recorded_at: recordedAt }, + { employmentRecordId: EMPLOYMENT, replayed: false }, + ), + true, + ); + } + assert.equal( + isGovernedSeparationSuccess( + 200, + { ...successBody(false), recorded_at: "0000-01-01T00:00:00Z" }, + { employmentRecordId: EMPLOYMENT, replayed: false }, + ), + false, + ); +}); + test("rejects success responses that are replay- or target-inconsistent", () => { assert.equal( isGovernedSeparationSuccess(200, successBody(true), { employmentRecordId: EMPLOYMENT, replayed: false }), From b09290d74d899f052192a84deae453e33c96f9d7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 18:58:08 +0900 Subject: [PATCH 217/269] fix(perf): align response timestamp year bounds --- tests/performance/employment_separation_response_contract.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index 06ecd43f8..3cb635899 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -43,7 +43,9 @@ function isValidUtcTimestamp(value) { const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; return ( - month >= 1 + year >= 1 + && year <= 9999 + && month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth[month - 1] From 46a5ff67404518079870671d54acd73c29e4012c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:02:44 +0900 Subject: [PATCH 218/269] test(perf): expose governed outcome cardinality gap --- ...on_acceptance_outcome_cardinality.test.mjs | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/performance/employment_separation_acceptance_outcome_cardinality.test.mjs diff --git a/tests/performance/employment_separation_acceptance_outcome_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_outcome_cardinality.test.mjs new file mode 100644 index 000000000..9005f69d7 --- /dev/null +++ b/tests/performance/employment_separation_acceptance_outcome_cardinality.test.mjs @@ -0,0 +1,103 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import test from "node:test"; + +import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { + acceptanceFixtureBytes, + acceptanceFixtureSha256, + acceptanceLoadModel, +} from "./employment_separation_acceptance_fixture_test_support.mjs"; + +const FIXTURE_BYTES = acceptanceFixtureBytes(); +const FIXTURE_SHA256 = acceptanceFixtureSha256(FIXTURE_BYTES); + +function result() { + return { + schema_version: "orgmetra.employment_separation.performance_result.v1", + candidate_sha: "a".repeat(40), + fixture_sha256: FIXTURE_SHA256, + selected_profile: "first_commit", + expected_iterations: 1000, + completed_iterations: 1000, + sample_complete: true, + completed_at: "2026-09-13T04:10:00Z", + load_model: acceptanceLoadModel(1000), + dataset_id: "dataset:employment-separation-perf-1", + clearance_reference: "data_clearance:perf-2026-09", + preparation_protocol_reference: "protocol:employment-separation-perf-v1", + prepared_state_evidence_reference: "evidence:prepared-state-perf-1", + resource_evidence_reference: "metrics:employment-separation-perf-1", + profile_preconditions: { + first_commit: "active_current_expected_version", + replay: "same_key_same_semantics_already_committed", + rejection: "expected_version_stale_or_semantic_conflict", + contention: "active_current_expected_version", + }, + minimum_non_contending_records: 1000, + minimum_contention_pairs: 100, + k6: { + metrics: { + iterations: { values: { count: 1000, rate: 40 } }, + checks: { values: { rate: 1, passes: 1000, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, + employment_separation_latency_samples: { values: { count: 1000, rate: 40 } }, + employment_separation_first_commit_duration_ms: { + values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count: 1000 }, + }, + }, + }, + }; +} + +function render(value) { + return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8"); +} + +function runtimeEvidence(resultArtifact) { + return { + schema_version: "orgmetra.employment_separation.runtime_evidence.v1", + candidate_sha: "a".repeat(40), + observed_service_sha: "a".repeat(40), + selected_profile: "first_commit", + performance_result_sha256: createHash("sha256").update(resultArtifact).digest("hex"), + fixture_sha256: FIXTURE_SHA256, + environment_reference: "environment:perf-staging-1", + deployment_reference: "deployment:orgmetra-people-a1", + observer_reference: "observer:perf-runtime-1", + load_observation_reference: "evidence:perf-load-observation-1", + observed_load_model: acceptanceLoadModel(1000), + resource_evidence_reference: "metrics:employment-separation-perf-1", + observed_at: "2026-09-13T04:10:01Z", + host_cpu_percent_p95: 42.5, + host_rss_bytes_max: 536870912, + db_pool_acquire_p95_ms: 1.2, + db_pool_in_use_max: 18, + db_pool_waiters_max: 2, + db_connections_max: 20, + residual_http_tasks: 0, + residual_db_sessions: 0, + residual_open_transactions: 0, + residual_sockets: 0, + residual_background_workers: 0, + residual_pool_checkouts: 0, + residual_pool_waiters: 0, + }; +} + +function validate(performance) { + const artifact = render(performance); + return validateEmploymentSeparationAcceptance(artifact, runtimeEvidence(artifact), FIXTURE_BYTES); +} + +test("rejects perfect check rate when governed outcome checks cover only a subset of iterations", () => { + const performance = result(); + performance.k6.metrics.checks.values.passes = 1; + assert.throws(() => validate(performance), /checks.*expected_iterations|governed outcome checks/i); +}); + +test("rejects zero unexpected-response rate when governed outcome observations cover only a subset of iterations", () => { + const performance = result(); + performance.k6.metrics.employment_separation_unexpected_response.values.fails = 1; + assert.throws(() => validate(performance), /unexpected response.*expected_iterations|governed outcome observations/i); +}); From b47fc1cf575c7d4d9112c3db2d6da5ae42fca430 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:04:36 +0900 Subject: [PATCH 219/269] fix(perf): bind governed outcome metric cardinality --- ...loyment_separation_acceptance_contract.mjs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_acceptance_contract.mjs b/tests/performance/employment_separation_acceptance_contract.mjs index 54e03a96b..4155a7a45 100644 --- a/tests/performance/employment_separation_acceptance_contract.mjs +++ b/tests/performance/employment_separation_acceptance_contract.mjs @@ -338,10 +338,27 @@ function validateResult(result) { if (finiteNumber(checkValues.rate, "result.k6.metrics.checks.values.rate", { maximum: 1 }) !== 1) { fail("k6 checks rate must equal 1"); } + const checkPasses = nonNegativeInteger(checkValues.passes, "result.k6.metrics.checks.values.passes"); + const checkFailures = nonNegativeInteger(checkValues.fails, "result.k6.metrics.checks.values.fails"); + if (checkPasses !== expectedIterations || checkFailures !== 0) { + fail("k6 governed outcome checks must cover exactly expected_iterations with zero failures"); + } + const unexpectedValues = metricValues(result, "employment_separation_unexpected_response"); if (finiteNumber(unexpectedValues.rate, "result.k6.metrics.employment_separation_unexpected_response.values.rate", { maximum: 1 }) !== 0) { fail("unexpected response rate must equal 0"); } + const unexpectedPasses = nonNegativeInteger( + unexpectedValues.passes, + "result.k6.metrics.employment_separation_unexpected_response.values.passes", + ); + const unexpectedFailures = nonNegativeInteger( + unexpectedValues.fails, + "result.k6.metrics.employment_separation_unexpected_response.values.fails", + ); + if (unexpectedPasses !== 0 || unexpectedFailures !== expectedIterations) { + fail("governed outcome observations must cover exactly expected_iterations with zero unexpected responses"); + } const trendValues = metricValues(result, trendName); const trendSampleCount = nonNegativeInteger(trendValues.count, `${trendName}.count`); @@ -481,4 +498,4 @@ export function validateEmploymentSeparationAcceptance(resultArtifact, runtimeEv performance_result_sha256: resultDigest, p95_ms: validatedResult.p95, }; -} +} \ No newline at end of file From 190c205b253d03d368b4f18f641cebe557516c83 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:13:28 +0900 Subject: [PATCH 220/269] test(perf): expose pinned k6 v2 summary mismatch --- ...separation_k6_v2_summary_contract.test.mjs | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 tests/performance/employment_separation_k6_v2_summary_contract.test.mjs diff --git a/tests/performance/employment_separation_k6_v2_summary_contract.test.mjs b/tests/performance/employment_separation_k6_v2_summary_contract.test.mjs new file mode 100644 index 000000000..9072b8365 --- /dev/null +++ b/tests/performance/employment_separation_k6_v2_summary_contract.test.mjs @@ -0,0 +1,117 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { normalizeEmploymentSeparationK6V2Summary } from "./employment_separation_k6_v2_summary_contract.mjs"; + +const TREND = "employment_separation_first_commit_duration_ms"; + +function counter(name, count) { + return { name, type: "counter", contains: "default", values: { count } }; +} + +function rate(name, matches, total) { + return { name, type: "rate", contains: "default", values: { matches, total, rate: total === 0 ? 0 : matches / total } }; +} + +function trend(name, count) { + return { + name, + type: "trend", + contains: "time", + values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count }, + }; +} + +function summary({ iterations = 1000, latencySamples = iterations, trendName = TREND } = {}) { + return { + version: "1.0.0", + metadata: { generatedAt: "2026-09-15T11:00:00Z", k6Version: "2.2.0" }, + config: { execution: "local", script: "employment_separation_buyer_path.js", duration: 50 }, + results: { + metrics: [ + counter("iterations", iterations), + rate("employment_separation_unexpected_response", 0, iterations), + counter("employment_separation_latency_samples", latencySamples), + trend(trendName, latencySamples), + ], + checks: { + metrics: [ + counter("checks_total", iterations), + rate("checks_succeeded", iterations, iterations), + rate("checks_failed", 0, iterations), + ], + results: [], + }, + }, + }; +} + +test("normalizes the pinned k6 v2 machine-readable summary into stable buyer evidence", () => { + const normalized = normalizeEmploymentSeparationK6V2Summary(summary(), { + expectedK6Version: "2.2.0", + trendName: TREND, + }); + + assert.deepEqual(normalized.metrics.iterations.values, { count: 1000 }); + assert.deepEqual(normalized.metrics.checks.values, { rate: 1, passes: 1000, fails: 0 }); + assert.deepEqual(normalized.metrics.employment_separation_unexpected_response.values, { + rate: 0, + passes: 0, + fails: 1000, + }); + assert.equal(normalized.metrics.employment_separation_latency_samples.values.count, 1000); + assert.equal(normalized.metrics[TREND].values.count, 1000); + assert.equal(normalized.summary_version, "1.0.0"); + assert.equal(normalized.summary_k6_version, "2.2.0"); +}); + +test("preserves one governed contention verdict while retaining two latency samples", () => { + const contentionTrend = "employment_separation_contention_duration_ms"; + const normalized = normalizeEmploymentSeparationK6V2Summary( + summary({ iterations: 100, latencySamples: 200, trendName: contentionTrend }), + { expectedK6Version: "2.2.0", trendName: contentionTrend }, + ); + + assert.deepEqual(normalized.metrics.checks.values, { rate: 1, passes: 100, fails: 0 }); + assert.deepEqual(normalized.metrics.employment_separation_unexpected_response.values, { + rate: 0, + passes: 0, + fails: 100, + }); + assert.equal(normalized.metrics.employment_separation_latency_samples.values.count, 200); + assert.equal(normalized.metrics[contentionTrend].values.count, 200); +}); + +test("rejects unsupported summary and runtime versions", () => { + const wrongSummary = summary(); + wrongSummary.version = "0.1.0"; + assert.throws( + () => normalizeEmploymentSeparationK6V2Summary(wrongSummary, { expectedK6Version: "2.2.0", trendName: TREND }), + /summary version/i, + ); + + const wrongRuntime = summary(); + wrongRuntime.metadata.k6Version = "2.1.0"; + assert.throws( + () => normalizeEmploymentSeparationK6V2Summary(wrongRuntime, { expectedK6Version: "2.2.0", trendName: TREND }), + /k6 version/i, + ); +}); + +test("rejects duplicate metric names before selecting commercial evidence", () => { + const duplicate = summary(); + duplicate.results.metrics.push(counter("iterations", 1000)); + assert.throws( + () => normalizeEmploymentSeparationK6V2Summary(duplicate, { expectedK6Version: "2.2.0", trendName: TREND }), + /duplicate metric/i, + ); +}); + +test("rejects inconsistent check aggregate totals", () => { + const inconsistent = summary(); + inconsistent.results.checks.metrics[1] = rate("checks_succeeded", 999, 1000); + assert.throws( + () => normalizeEmploymentSeparationK6V2Summary(inconsistent, { expectedK6Version: "2.2.0", trendName: TREND }), + /check aggregate/i, + ); +}); From 87df697bc4bea2480d315a75b5fa08c0973aefdb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:14:20 +0900 Subject: [PATCH 221/269] fix(perf): normalize pinned k6 v2 summary evidence --- .../employment_separation_buyer_path.js | 15 +- ...ment_separation_k6_v2_summary_contract.mjs | 150 ++++++++++++++++++ 2 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 tests/performance/employment_separation_k6_v2_summary_contract.mjs diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 1d7e157c6..2d746ca8c 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -14,6 +14,7 @@ import { validatePerformanceFixture, } from "./employment_separation_fixture_contract.mjs"; import { requirePinnedK6Runtime } from "./employment_separation_k6_runtime_contract.mjs"; +import { normalizeEmploymentSeparationK6V2Summary } from "./employment_separation_k6_v2_summary_contract.mjs"; import { isGovernedSeparationConflict, isGovernedSeparationSuccess, @@ -32,6 +33,12 @@ import { buyerPathElapsedMs } from "./employment_separation_timing_contract.mjs" const ROUTE = "/v1/employment-separations"; const MINIMUM_NON_CONTENDING_RECORDS = 1000; const MINIMUM_CONTENTION_PAIRS = 100; +const TREND_BY_PROFILE = Object.freeze({ + first_commit: "employment_separation_first_commit_duration_ms", + replay: "employment_separation_replay_duration_ms", + rejection: "employment_separation_rejection_duration_ms", + contention: "employment_separation_contention_duration_ms", +}); const fixturePath = __ENV.ORGMETRA_PERFORMANCE_DATA_FILE; const baseUrl = (__ENV.ORGMETRA_PERFORMANCE_BASE_URL || "").replace(/\/$/, ""); const bearerToken = __ENV.ORGMETRA_PERFORMANCE_BEARER_TOKEN || ""; @@ -131,7 +138,11 @@ export function contention() { } export function handleSummary(data) { - const completedIterations = data.metrics?.iterations?.values?.count ?? null; + const normalizedK6 = normalizeEmploymentSeparationK6V2Summary(data, { + expectedK6Version: k6Runtime.version, + trendName: TREND_BY_PROFILE[selectedProfile], + }); + const completedIterations = normalizedK6.metrics.iterations.values.count; const payload = { schema_version: "orgmetra.employment_separation.performance_result.v1", candidate_sha: targetSha, @@ -154,7 +165,7 @@ export function handleSummary(data) { profile_preconditions: fixture.profile_preconditions, minimum_non_contending_records: MINIMUM_NON_CONTENDING_RECORDS, minimum_contention_pairs: MINIMUM_CONTENTION_PAIRS, - k6: data, + k6: normalizedK6, }; const rendered = `${JSON.stringify(payload, null, 2)}\n`; const path = __ENV.ORGMETRA_PERFORMANCE_SUMMARY_FILE || `employment-separation-performance-${selectedProfile}.json`; diff --git a/tests/performance/employment_separation_k6_v2_summary_contract.mjs b/tests/performance/employment_separation_k6_v2_summary_contract.mjs new file mode 100644 index 000000000..db99669ff --- /dev/null +++ b/tests/performance/employment_separation_k6_v2_summary_contract.mjs @@ -0,0 +1,150 @@ +const SUPPORTED_SUMMARY_VERSION = "1.0.0"; + +function fail(message) { + throw new Error(message); +} + +function plainObject(value, label) { + if (value === null || typeof value !== "object" || Array.isArray(value)) { + fail(`${label} must be an object`); + } + return value; +} + +function nonEmptyString(value, label) { + if (typeof value !== "string" || value.trim() === "") fail(`${label} must be a non-empty string`); + return value; +} + +function nonNegativeInteger(value, label) { + if (!Number.isSafeInteger(value) || value < 0) fail(`${label} must be a non-negative safe integer`); + return value; +} + +function finiteNumber(value, label, { minimum = 0, maximum = Number.POSITIVE_INFINITY } = {}) { + if (typeof value !== "number" || !Number.isFinite(value) || value < minimum || value > maximum) { + fail(`${label} must be a finite number between ${minimum} and ${maximum}`); + } + return value; +} + +function indexMetrics(entries, label, occupiedNames = new Set()) { + if (!Array.isArray(entries)) fail(`${label} must be an array`); + const index = new Map(); + for (const [position, entry] of entries.entries()) { + const metric = plainObject(entry, `${label}[${position}]`); + const name = nonEmptyString(metric.name, `${label}[${position}].name`); + if (occupiedNames.has(name) || index.has(name)) fail(`${label} contains duplicate metric ${name}`); + index.set(name, metric); + } + return index; +} + +function requireMetric(index, name, type, label) { + const metric = index.get(name); + if (!metric) fail(`${label} must contain metric ${name}`); + if (metric.type !== type) fail(`${label}.${name}.type must be ${type}`); + return plainObject(metric.values, `${label}.${name}.values`); +} + +function counterValue(index, name, label) { + const values = requireMetric(index, name, "counter", label); + return nonNegativeInteger(values.count, `${label}.${name}.values.count`); +} + +function rateValue(index, name, label) { + const values = requireMetric(index, name, "rate", label); + const matches = nonNegativeInteger(values.matches, `${label}.${name}.values.matches`); + const total = nonNegativeInteger(values.total, `${label}.${name}.values.total`); + if (matches > total) fail(`${label}.${name}.values.matches cannot exceed total`); + const rate = finiteNumber(values.rate, `${label}.${name}.values.rate`, { maximum: 1 }); + const expectedRate = total === 0 ? 0 : matches / total; + if (Math.abs(rate - expectedRate) > Number.EPSILON * 8) { + fail(`${label}.${name}.values.rate must equal matches / total`); + } + return Object.freeze({ matches, total, rate }); +} + +function trendValue(index, name, label) { + const values = requireMetric(index, name, "trend", label); + return Object.freeze({ + "p(50)": finiteNumber(values["p(50)"], `${label}.${name}.values.p(50)`), + "p(95)": finiteNumber(values["p(95)"], `${label}.${name}.values.p(95)`), + "p(99)": finiteNumber(values["p(99)"], `${label}.${name}.values.p(99)`), + max: finiteNumber(values.max, `${label}.${name}.values.max`), + count: nonNegativeInteger(values.count, `${label}.${name}.values.count`), + }); +} + +export function normalizeEmploymentSeparationK6V2Summary(summary, { expectedK6Version, trendName }) { + const document = plainObject(summary, "k6 summary"); + if (document.version !== SUPPORTED_SUMMARY_VERSION) { + fail(`k6 summary version must be ${SUPPORTED_SUMMARY_VERSION}`); + } + const metadata = plainObject(document.metadata, "k6 summary.metadata"); + const declaredK6Version = nonEmptyString(metadata.k6Version, "k6 summary.metadata.k6Version"); + const requiredK6Version = nonEmptyString(expectedK6Version, "expectedK6Version"); + if (declaredK6Version !== requiredK6Version) { + fail(`k6 summary k6 version must equal ${requiredK6Version}`); + } + const requiredTrendName = nonEmptyString(trendName, "trendName"); + + const results = plainObject(document.results, "k6 summary.results"); + const ordinaryMetrics = indexMetrics(results.metrics, "k6 summary.results.metrics"); + const checks = plainObject(results.checks, "k6 summary.results.checks"); + const checkMetrics = indexMetrics( + checks.metrics, + "k6 summary.results.checks.metrics", + new Set(ordinaryMetrics.keys()), + ); + + const iterations = counterValue(ordinaryMetrics, "iterations", "k6 summary.results.metrics"); + const latencySamples = counterValue( + ordinaryMetrics, + "employment_separation_latency_samples", + "k6 summary.results.metrics", + ); + const unexpected = rateValue( + ordinaryMetrics, + "employment_separation_unexpected_response", + "k6 summary.results.metrics", + ); + const trend = trendValue(ordinaryMetrics, requiredTrendName, "k6 summary.results.metrics"); + + const checksTotal = counterValue(checkMetrics, "checks_total", "k6 summary.results.checks.metrics"); + const checksSucceeded = rateValue(checkMetrics, "checks_succeeded", "k6 summary.results.checks.metrics"); + const checksFailed = rateValue(checkMetrics, "checks_failed", "k6 summary.results.checks.metrics"); + if ( + checksSucceeded.total !== checksTotal + || checksFailed.total !== checksTotal + || checksSucceeded.matches + checksFailed.matches !== checksTotal + ) { + fail("k6 check aggregate metrics must describe the same complete check population"); + } + + return Object.freeze({ + summary_version: SUPPORTED_SUMMARY_VERSION, + summary_k6_version: declaredK6Version, + metrics: Object.freeze({ + iterations: Object.freeze({ values: Object.freeze({ count: iterations }) }), + checks: Object.freeze({ + values: Object.freeze({ + rate: checksSucceeded.rate, + passes: checksSucceeded.matches, + fails: checksFailed.matches, + }), + }), + employment_separation_unexpected_response: Object.freeze({ + values: Object.freeze({ + rate: unexpected.rate, + passes: unexpected.matches, + fails: unexpected.total - unexpected.matches, + }), + }), + employment_separation_latency_samples: Object.freeze({ + values: Object.freeze({ count: latencySamples }), + }), + [requiredTrendName]: Object.freeze({ values: trend }), + }), + }); +} From 4711724a0adbee2579abe51fe8e85cff18309174 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:17:58 +0900 Subject: [PATCH 222/269] test(perf): currentize composed outcome cardinality --- .../employment_separation_composed_evidence_contract.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_composed_evidence_contract.test.mjs b/tests/performance/employment_separation_composed_evidence_contract.test.mjs index f43994d33..ef64860b4 100644 --- a/tests/performance/employment_separation_composed_evidence_contract.test.mjs +++ b/tests/performance/employment_separation_composed_evidence_contract.test.mjs @@ -52,8 +52,8 @@ function performanceResult() { k6: { metrics: { iterations: { values: { count: ITERATIONS } }, - checks: { values: { rate: 1 } }, - employment_separation_unexpected_response: { values: { rate: 0 } }, + checks: { values: { rate: 1, passes: ITERATIONS, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: ITERATIONS } }, employment_separation_latency_samples: { values: { count: ITERATIONS } }, employment_separation_first_commit_duration_ms: { values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: ITERATIONS }, From 151d08e10e31f119f87755e10e396f7497871371 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:18:21 +0900 Subject: [PATCH 223/269] test(perf): preserve outcome cardinality in latency fixtures --- .../employment_separation_acceptance_latency_samples.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs index fc89ddb57..59e5cd3e6 100644 --- a/tests/performance/employment_separation_acceptance_latency_samples.test.mjs +++ b/tests/performance/employment_separation_acceptance_latency_samples.test.mjs @@ -40,8 +40,8 @@ function performanceResult(latencySamples = 1000, trendSamples = latencySamples) k6: { metrics: { iterations: { values: { count: 1000 } }, - checks: { values: { rate: 1 } }, - employment_separation_unexpected_response: { values: { rate: 0 } }, + checks: { values: { rate: 1, passes: 1000, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, employment_separation_latency_samples: { values: { count: latencySamples } }, employment_separation_first_commit_duration_ms: { values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: trendSamples }, From b725496c8fb02f3df300eca8a7f8456193c7e69a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:18:59 +0900 Subject: [PATCH 224/269] test(perf): currentize edge outcome cardinality --- .../employment_separation_acceptance_edge.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_edge.test.mjs b/tests/performance/employment_separation_acceptance_edge.test.mjs index fa6fddeaa..6543c9ed9 100644 --- a/tests/performance/employment_separation_acceptance_edge.test.mjs +++ b/tests/performance/employment_separation_acceptance_edge.test.mjs @@ -51,8 +51,8 @@ function result(profile = "first_commit") { k6: { metrics: { iterations: { values: { count: iterations } }, - checks: { values: { rate: 1 } }, - employment_separation_unexpected_response: { values: { rate: 0 } }, + checks: { values: { rate: 1, passes: iterations, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: iterations } }, employment_separation_latency_samples: { values: { count: latencySamples } }, [TREND_BY_PROFILE[profile]]: { values: trend }, }, From 738ff481ad9ddf3d0ecdc1b2abb0b0d29db397e4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:19:24 +0900 Subject: [PATCH 225/269] test(perf): preserve outcome cardinality in fixture binding --- .../employment_separation_acceptance_fixture_binding.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs index 6ada1d5c3..4473f5bc2 100644 --- a/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs +++ b/tests/performance/employment_separation_acceptance_fixture_binding.test.mjs @@ -32,8 +32,8 @@ function performanceResult(fixtureSha256, { includeFixtureDigest = true } = {}) k6: { metrics: { iterations: { values: { count: 1000 } }, - checks: { values: { rate: 1 } }, - employment_separation_unexpected_response: { values: { rate: 0 } }, + checks: { values: { rate: 1, passes: 1000, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, employment_separation_latency_samples: { values: { count: 1000 } }, employment_separation_first_commit_duration_ms: { values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: 1000 }, From 5c0098dc69fcdc86f7d5367da0ee0c80b69c4501 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:19:47 +0900 Subject: [PATCH 226/269] test(perf): preserve outcome counts in byte-budget fixtures --- .../employment_separation_artifact_byte_budget.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_artifact_byte_budget.test.mjs b/tests/performance/employment_separation_artifact_byte_budget.test.mjs index 66d4f5fab..358352966 100644 --- a/tests/performance/employment_separation_artifact_byte_budget.test.mjs +++ b/tests/performance/employment_separation_artifact_byte_budget.test.mjs @@ -51,8 +51,8 @@ function result(fixtureSha256) { k6: { metrics: { iterations: { values: { count: ITERATIONS } }, - checks: { values: { rate: 1 } }, - employment_separation_unexpected_response: { values: { rate: 0 } }, + checks: { values: { rate: 1, passes: ITERATIONS, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: ITERATIONS } }, employment_separation_latency_samples: { values: { count: ITERATIONS } }, employment_separation_first_commit_duration_ms: { values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: ITERATIONS }, From 67800371f440cfe81a27cd3183de3c27ce0ce02d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:20:50 +0900 Subject: [PATCH 227/269] test(perf): currentize cardinality evidence fixtures --- .../employment_separation_acceptance_cardinality.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_cardinality.test.mjs b/tests/performance/employment_separation_acceptance_cardinality.test.mjs index b0349bee8..a4f717aa4 100644 --- a/tests/performance/employment_separation_acceptance_cardinality.test.mjs +++ b/tests/performance/employment_separation_acceptance_cardinality.test.mjs @@ -44,8 +44,8 @@ function performanceResult(profile, iterations) { k6: { metrics: { iterations: { values: { count: iterations } }, - checks: { values: { rate: 1 } }, - employment_separation_unexpected_response: { values: { rate: 0 } }, + checks: { values: { rate: 1, passes: iterations, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: iterations } }, employment_separation_latency_samples: { values: { count: latencySamples } }, [trendName]: { values: profile === "contention" From 37e663d90d4ea6500ce6ca534bc48b17a39998b6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:21:12 +0900 Subject: [PATCH 228/269] test(perf): currentize provenance outcome cardinality --- .../employment_separation_acceptance_provenance.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_provenance.test.mjs b/tests/performance/employment_separation_acceptance_provenance.test.mjs index 094fa9ba1..f83443052 100644 --- a/tests/performance/employment_separation_acceptance_provenance.test.mjs +++ b/tests/performance/employment_separation_acceptance_provenance.test.mjs @@ -41,8 +41,8 @@ function result() { k6: { metrics: { iterations: { values: { count: 1000 } }, - checks: { values: { rate: 1 } }, - employment_separation_unexpected_response: { values: { rate: 0 } }, + checks: { values: { rate: 1, passes: 1000, fails: 0 } }, + employment_separation_unexpected_response: { values: { rate: 0, passes: 0, fails: 1000 } }, employment_separation_latency_samples: { values: { count: 1000 } }, employment_separation_first_commit_duration_ms: { values: { "p(50)": 8, "p(95)": 18, "p(99)": 19, max: 22, count: 1000 }, From 0f2f9f9c4bbcbaab439c6d2f418e6651390fc77d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:34:29 +0900 Subject: [PATCH 229/269] test(perf): reproduce pinned k6 summary contract mismatch --- ...nt_separation_k6_summary_contract.test.mjs | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 tests/performance/employment_separation_k6_summary_contract.test.mjs diff --git a/tests/performance/employment_separation_k6_summary_contract.test.mjs b/tests/performance/employment_separation_k6_summary_contract.test.mjs new file mode 100644 index 000000000..2ea57f32d --- /dev/null +++ b/tests/performance/employment_separation_k6_summary_contract.test.mjs @@ -0,0 +1,90 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { normalizeEmploymentSeparationK6Summary } from "./employment_separation_k6_summary_contract.mjs"; + +const TREND = "employment_separation_first_commit_duration_ms"; +const STATS = ["p(50)", "p(95)", "p(99)", "max", "count"]; + +function legacySummary({ iterations = 1000, latencySamples = iterations, trendName = TREND } = {}) { + return { + root_group: { name: "", path: "", id: "", groups: [], checks: [] }, + options: { summaryTrendStats: [...STATS], summaryTimeUnit: "", noColor: true }, + state: { isStdOutTTY: false, isStdErrTTY: false, testRunDurationMs: 50000 }, + setup_data: null, + metrics: { + iterations: { type: "counter", contains: "default", values: { count: iterations, rate: 20 } }, + checks: { type: "rate", contains: "default", values: { rate: 1, passes: iterations, fails: 0 } }, + employment_separation_unexpected_response: { + type: "rate", contains: "default", values: { rate: 0, passes: 0, fails: iterations }, + }, + employment_separation_latency_samples: { + type: "counter", contains: "default", values: { count: latencySamples, rate: 20 }, + }, + [trendName]: { + type: "trend", + contains: "time", + values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count: latencySamples }, + }, + }, + }; +} + +function machineReadableSummary() { + return { + version: "1.0.0", + metadata: { generatedAt: "2026-09-15T11:00:00Z", k6Version: "2.2.0" }, + config: { execution: "local", script: "employment_separation_buyer_path.js", duration: 50 }, + results: { + metrics: [{ + name: TREND, + type: "trend", + contains: "time", + values: { avg: 10, max: 22.3, med: 8.1, min: 2.2, "p(90)": 16.2, "p(95)": 18.4 }, + }], + checks: { metrics: [], results: [] }, + }, + }; +} + +test("normalizes the pinned k6 2.2 default handleSummary contract with configured commercial percentiles", () => { + const normalized = normalizeEmploymentSeparationK6Summary(legacySummary(), { + expectedK6Version: "2.2.0", + trendName: TREND, + }); + assert.deepEqual(normalized.metrics.iterations.values, { count: 1000 }); + assert.deepEqual(normalized.metrics.checks.values, { rate: 1, passes: 1000, fails: 0 }); + assert.deepEqual(normalized.metrics.employment_separation_unexpected_response.values, { rate: 0, passes: 0, fails: 1000 }); + assert.equal(normalized.metrics.employment_separation_latency_samples.values.count, 1000); + assert.deepEqual(normalized.metrics[TREND].values, { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count: 1000 }); + assert.equal(normalized.summary_contract, "k6-legacy-handle-summary"); + assert.equal(normalized.summary_k6_version, "2.2.0"); +}); + +test("rejects the real k6 2.2 machine-readable trend shape instead of fabricating p99 or count", () => { + assert.throws( + () => normalizeEmploymentSeparationK6Summary(machineReadableSummary(), { expectedK6Version: "2.2.0", trendName: TREND }), + /cannot supply required p\(99\) and trend count evidence/i, + ); +}); + +test("rejects a legacy summary whose configured trend statistics do not match commercial evidence", () => { + const summary = legacySummary(); + summary.options.summaryTrendStats = ["med", "p(95)", "max"]; + assert.throws( + () => normalizeEmploymentSeparationK6Summary(summary, { expectedK6Version: "2.2.0", trendName: TREND }), + /summaryTrendStats/i, + ); +}); + +test("preserves one contention verdict while retaining two latency samples", () => { + const contentionTrend = "employment_separation_contention_duration_ms"; + const normalized = normalizeEmploymentSeparationK6Summary( + legacySummary({ iterations: 100, latencySamples: 200, trendName: contentionTrend }), + { expectedK6Version: "2.2.0", trendName: contentionTrend }, + ); + assert.deepEqual(normalized.metrics.checks.values, { rate: 1, passes: 100, fails: 0 }); + assert.deepEqual(normalized.metrics.employment_separation_unexpected_response.values, { rate: 0, passes: 0, fails: 100 }); + assert.equal(normalized.metrics.employment_separation_latency_samples.values.count, 200); + assert.equal(normalized.metrics[contentionTrend].values.count, 200); +}); From 210cbcedb9bcb67b0b44fdec24b2bf678e62ceb8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:34:50 +0900 Subject: [PATCH 230/269] fix(perf): consume pinned k6 default summary contract --- ...loyment_separation_k6_summary_contract.mjs | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/performance/employment_separation_k6_summary_contract.mjs diff --git a/tests/performance/employment_separation_k6_summary_contract.mjs b/tests/performance/employment_separation_k6_summary_contract.mjs new file mode 100644 index 000000000..bb720b2f3 --- /dev/null +++ b/tests/performance/employment_separation_k6_summary_contract.mjs @@ -0,0 +1,103 @@ +const SUPPORTED_TREND_STATS = Object.freeze(["p(50)", "p(95)", "p(99)", "max", "count"]); + +function fail(message) { + throw new Error(message); +} + +function plainObject(value, label) { + if (value === null || typeof value !== "object" || Array.isArray(value)) { + fail(`${label} must be an object`); + } + return value; +} + +function nonEmptyString(value, label) { + if (typeof value !== "string" || value.trim() === "") fail(`${label} must be a non-empty string`); + return value; +} + +function nonNegativeInteger(value, label) { + if (!Number.isSafeInteger(value) || value < 0) fail(`${label} must be a non-negative safe integer`); + return value; +} + +function finiteNumber(value, label, { minimum = 0, maximum = Number.POSITIVE_INFINITY } = {}) { + if (typeof value !== "number" || !Number.isFinite(value) || value < minimum || value > maximum) { + fail(`${label} must be a finite number between ${minimum} and ${maximum}`); + } + return value; +} + +function exactStringArray(value, expected, label) { + if (!Array.isArray(value) || value.length !== expected.length) { + fail(`${label} must equal ${expected.join(", ")}`); + } + for (let index = 0; index < expected.length; index += 1) { + if (value[index] !== expected[index]) fail(`${label} must equal ${expected.join(", ")}`); + } +} + +function requireMetric(metrics, name, type) { + const metric = plainObject(metrics[name], `k6 summary.metrics.${name}`); + if (metric.type !== type) fail(`k6 summary.metrics.${name}.type must be ${type}`); + return plainObject(metric.values, `k6 summary.metrics.${name}.values`); +} + +function counterValue(metrics, name) { + return nonNegativeInteger(requireMetric(metrics, name, "counter").count, `k6 summary.metrics.${name}.values.count`); +} + +function rateValue(metrics, name) { + const values = requireMetric(metrics, name, "rate"); + const passes = nonNegativeInteger(values.passes, `k6 summary.metrics.${name}.values.passes`); + const fails = nonNegativeInteger(values.fails, `k6 summary.metrics.${name}.values.fails`); + const total = passes + fails; + if (!Number.isSafeInteger(total)) fail(`k6 summary.metrics.${name} sample total must be a safe integer`); + const rate = finiteNumber(values.rate, `k6 summary.metrics.${name}.values.rate`, { maximum: 1 }); + const expectedRate = total === 0 ? 0 : passes / total; + if (Math.abs(rate - expectedRate) > Number.EPSILON * 8) { + fail(`k6 summary.metrics.${name}.values.rate must equal passes / total`); + } + return Object.freeze({ passes, fails, rate }); +} + +function trendValue(metrics, name) { + const values = requireMetric(metrics, name, "trend"); + return Object.freeze({ + "p(50)": finiteNumber(values["p(50)"], `k6 summary.metrics.${name}.values.p(50)`), + "p(95)": finiteNumber(values["p(95)"], `k6 summary.metrics.${name}.values.p(95)`), + "p(99)": finiteNumber(values["p(99)"], `k6 summary.metrics.${name}.values.p(99)`), + max: finiteNumber(values.max, `k6 summary.metrics.${name}.values.max`), + count: nonNegativeInteger(values.count, `k6 summary.metrics.${name}.values.count`), + }); +} + +export function normalizeEmploymentSeparationK6Summary(summary, { expectedK6Version, trendName }) { + const document = plainObject(summary, "k6 summary"); + if (Object.prototype.hasOwnProperty.call(document, "version")) { + fail("pinned k6 2.2 machine-readable summary cannot supply required p(99) and trend count evidence"); + } + const options = plainObject(document.options, "k6 summary.options"); + exactStringArray(options.summaryTrendStats, SUPPORTED_TREND_STATS, "k6 summary.options.summaryTrendStats"); + const requiredK6Version = nonEmptyString(expectedK6Version, "expectedK6Version"); + const requiredTrendName = nonEmptyString(trendName, "trendName"); + const metrics = plainObject(document.metrics, "k6 summary.metrics"); + + const iterations = counterValue(metrics, "iterations"); + const latencySamples = counterValue(metrics, "employment_separation_latency_samples"); + const unexpected = rateValue(metrics, "employment_separation_unexpected_response"); + const checks = rateValue(metrics, "checks"); + const trend = trendValue(metrics, requiredTrendName); + + return Object.freeze({ + summary_contract: "k6-legacy-handle-summary", + summary_k6_version: requiredK6Version, + metrics: Object.freeze({ + iterations: Object.freeze({ values: Object.freeze({ count: iterations }) }), + checks: Object.freeze({ values: checks }), + employment_separation_unexpected_response: Object.freeze({ values: unexpected }), + employment_separation_latency_samples: Object.freeze({ values: Object.freeze({ count: latencySamples }) }), + [requiredTrendName]: Object.freeze({ values: trend }), + }), + }); +} From d5ebebe839fda0c2be345cc44bd453b5ead7dcf4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:35:24 +0900 Subject: [PATCH 231/269] fix(perf): bind buyer workload to pinned k6 summary contract --- tests/performance/employment_separation_buyer_path.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 2d746ca8c..e70833481 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -14,7 +14,7 @@ import { validatePerformanceFixture, } from "./employment_separation_fixture_contract.mjs"; import { requirePinnedK6Runtime } from "./employment_separation_k6_runtime_contract.mjs"; -import { normalizeEmploymentSeparationK6V2Summary } from "./employment_separation_k6_v2_summary_contract.mjs"; +import { normalizeEmploymentSeparationK6Summary } from "./employment_separation_k6_summary_contract.mjs"; import { isGovernedSeparationConflict, isGovernedSeparationSuccess, @@ -138,7 +138,7 @@ export function contention() { } export function handleSummary(data) { - const normalizedK6 = normalizeEmploymentSeparationK6V2Summary(data, { + const normalizedK6 = normalizeEmploymentSeparationK6Summary(data, { expectedK6Version: k6Runtime.version, trendName: TREND_BY_PROFILE[selectedProfile], }); From f03b8f71e3e8e05f3d26ca993288070fff359b6f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:35:41 +0900 Subject: [PATCH 232/269] test(perf): remove impossible k6 v2 summary fixture --- ...separation_k6_v2_summary_contract.test.mjs | 117 ------------------ 1 file changed, 117 deletions(-) delete mode 100644 tests/performance/employment_separation_k6_v2_summary_contract.test.mjs diff --git a/tests/performance/employment_separation_k6_v2_summary_contract.test.mjs b/tests/performance/employment_separation_k6_v2_summary_contract.test.mjs deleted file mode 100644 index 9072b8365..000000000 --- a/tests/performance/employment_separation_k6_v2_summary_contract.test.mjs +++ /dev/null @@ -1,117 +0,0 @@ -import assert from "node:assert/strict"; -import test from "node:test"; - -import { normalizeEmploymentSeparationK6V2Summary } from "./employment_separation_k6_v2_summary_contract.mjs"; - -const TREND = "employment_separation_first_commit_duration_ms"; - -function counter(name, count) { - return { name, type: "counter", contains: "default", values: { count } }; -} - -function rate(name, matches, total) { - return { name, type: "rate", contains: "default", values: { matches, total, rate: total === 0 ? 0 : matches / total } }; -} - -function trend(name, count) { - return { - name, - type: "trend", - contains: "time", - values: { "p(50)": 8.1, "p(95)": 18.4, "p(99)": 19.7, max: 22.3, count }, - }; -} - -function summary({ iterations = 1000, latencySamples = iterations, trendName = TREND } = {}) { - return { - version: "1.0.0", - metadata: { generatedAt: "2026-09-15T11:00:00Z", k6Version: "2.2.0" }, - config: { execution: "local", script: "employment_separation_buyer_path.js", duration: 50 }, - results: { - metrics: [ - counter("iterations", iterations), - rate("employment_separation_unexpected_response", 0, iterations), - counter("employment_separation_latency_samples", latencySamples), - trend(trendName, latencySamples), - ], - checks: { - metrics: [ - counter("checks_total", iterations), - rate("checks_succeeded", iterations, iterations), - rate("checks_failed", 0, iterations), - ], - results: [], - }, - }, - }; -} - -test("normalizes the pinned k6 v2 machine-readable summary into stable buyer evidence", () => { - const normalized = normalizeEmploymentSeparationK6V2Summary(summary(), { - expectedK6Version: "2.2.0", - trendName: TREND, - }); - - assert.deepEqual(normalized.metrics.iterations.values, { count: 1000 }); - assert.deepEqual(normalized.metrics.checks.values, { rate: 1, passes: 1000, fails: 0 }); - assert.deepEqual(normalized.metrics.employment_separation_unexpected_response.values, { - rate: 0, - passes: 0, - fails: 1000, - }); - assert.equal(normalized.metrics.employment_separation_latency_samples.values.count, 1000); - assert.equal(normalized.metrics[TREND].values.count, 1000); - assert.equal(normalized.summary_version, "1.0.0"); - assert.equal(normalized.summary_k6_version, "2.2.0"); -}); - -test("preserves one governed contention verdict while retaining two latency samples", () => { - const contentionTrend = "employment_separation_contention_duration_ms"; - const normalized = normalizeEmploymentSeparationK6V2Summary( - summary({ iterations: 100, latencySamples: 200, trendName: contentionTrend }), - { expectedK6Version: "2.2.0", trendName: contentionTrend }, - ); - - assert.deepEqual(normalized.metrics.checks.values, { rate: 1, passes: 100, fails: 0 }); - assert.deepEqual(normalized.metrics.employment_separation_unexpected_response.values, { - rate: 0, - passes: 0, - fails: 100, - }); - assert.equal(normalized.metrics.employment_separation_latency_samples.values.count, 200); - assert.equal(normalized.metrics[contentionTrend].values.count, 200); -}); - -test("rejects unsupported summary and runtime versions", () => { - const wrongSummary = summary(); - wrongSummary.version = "0.1.0"; - assert.throws( - () => normalizeEmploymentSeparationK6V2Summary(wrongSummary, { expectedK6Version: "2.2.0", trendName: TREND }), - /summary version/i, - ); - - const wrongRuntime = summary(); - wrongRuntime.metadata.k6Version = "2.1.0"; - assert.throws( - () => normalizeEmploymentSeparationK6V2Summary(wrongRuntime, { expectedK6Version: "2.2.0", trendName: TREND }), - /k6 version/i, - ); -}); - -test("rejects duplicate metric names before selecting commercial evidence", () => { - const duplicate = summary(); - duplicate.results.metrics.push(counter("iterations", 1000)); - assert.throws( - () => normalizeEmploymentSeparationK6V2Summary(duplicate, { expectedK6Version: "2.2.0", trendName: TREND }), - /duplicate metric/i, - ); -}); - -test("rejects inconsistent check aggregate totals", () => { - const inconsistent = summary(); - inconsistent.results.checks.metrics[1] = rate("checks_succeeded", 999, 1000); - assert.throws( - () => normalizeEmploymentSeparationK6V2Summary(inconsistent, { expectedK6Version: "2.2.0", trendName: TREND }), - /check aggregate/i, - ); -}); From 9e0124f35d8a6a1ef6082912a02d27e46103321d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 20:35:47 +0900 Subject: [PATCH 233/269] fix(perf): remove impossible k6 v2 summary normalizer --- ...ment_separation_k6_v2_summary_contract.mjs | 150 ------------------ 1 file changed, 150 deletions(-) delete mode 100644 tests/performance/employment_separation_k6_v2_summary_contract.mjs diff --git a/tests/performance/employment_separation_k6_v2_summary_contract.mjs b/tests/performance/employment_separation_k6_v2_summary_contract.mjs deleted file mode 100644 index db99669ff..000000000 --- a/tests/performance/employment_separation_k6_v2_summary_contract.mjs +++ /dev/null @@ -1,150 +0,0 @@ -const SUPPORTED_SUMMARY_VERSION = "1.0.0"; - -function fail(message) { - throw new Error(message); -} - -function plainObject(value, label) { - if (value === null || typeof value !== "object" || Array.isArray(value)) { - fail(`${label} must be an object`); - } - return value; -} - -function nonEmptyString(value, label) { - if (typeof value !== "string" || value.trim() === "") fail(`${label} must be a non-empty string`); - return value; -} - -function nonNegativeInteger(value, label) { - if (!Number.isSafeInteger(value) || value < 0) fail(`${label} must be a non-negative safe integer`); - return value; -} - -function finiteNumber(value, label, { minimum = 0, maximum = Number.POSITIVE_INFINITY } = {}) { - if (typeof value !== "number" || !Number.isFinite(value) || value < minimum || value > maximum) { - fail(`${label} must be a finite number between ${minimum} and ${maximum}`); - } - return value; -} - -function indexMetrics(entries, label, occupiedNames = new Set()) { - if (!Array.isArray(entries)) fail(`${label} must be an array`); - const index = new Map(); - for (const [position, entry] of entries.entries()) { - const metric = plainObject(entry, `${label}[${position}]`); - const name = nonEmptyString(metric.name, `${label}[${position}].name`); - if (occupiedNames.has(name) || index.has(name)) fail(`${label} contains duplicate metric ${name}`); - index.set(name, metric); - } - return index; -} - -function requireMetric(index, name, type, label) { - const metric = index.get(name); - if (!metric) fail(`${label} must contain metric ${name}`); - if (metric.type !== type) fail(`${label}.${name}.type must be ${type}`); - return plainObject(metric.values, `${label}.${name}.values`); -} - -function counterValue(index, name, label) { - const values = requireMetric(index, name, "counter", label); - return nonNegativeInteger(values.count, `${label}.${name}.values.count`); -} - -function rateValue(index, name, label) { - const values = requireMetric(index, name, "rate", label); - const matches = nonNegativeInteger(values.matches, `${label}.${name}.values.matches`); - const total = nonNegativeInteger(values.total, `${label}.${name}.values.total`); - if (matches > total) fail(`${label}.${name}.values.matches cannot exceed total`); - const rate = finiteNumber(values.rate, `${label}.${name}.values.rate`, { maximum: 1 }); - const expectedRate = total === 0 ? 0 : matches / total; - if (Math.abs(rate - expectedRate) > Number.EPSILON * 8) { - fail(`${label}.${name}.values.rate must equal matches / total`); - } - return Object.freeze({ matches, total, rate }); -} - -function trendValue(index, name, label) { - const values = requireMetric(index, name, "trend", label); - return Object.freeze({ - "p(50)": finiteNumber(values["p(50)"], `${label}.${name}.values.p(50)`), - "p(95)": finiteNumber(values["p(95)"], `${label}.${name}.values.p(95)`), - "p(99)": finiteNumber(values["p(99)"], `${label}.${name}.values.p(99)`), - max: finiteNumber(values.max, `${label}.${name}.values.max`), - count: nonNegativeInteger(values.count, `${label}.${name}.values.count`), - }); -} - -export function normalizeEmploymentSeparationK6V2Summary(summary, { expectedK6Version, trendName }) { - const document = plainObject(summary, "k6 summary"); - if (document.version !== SUPPORTED_SUMMARY_VERSION) { - fail(`k6 summary version must be ${SUPPORTED_SUMMARY_VERSION}`); - } - const metadata = plainObject(document.metadata, "k6 summary.metadata"); - const declaredK6Version = nonEmptyString(metadata.k6Version, "k6 summary.metadata.k6Version"); - const requiredK6Version = nonEmptyString(expectedK6Version, "expectedK6Version"); - if (declaredK6Version !== requiredK6Version) { - fail(`k6 summary k6 version must equal ${requiredK6Version}`); - } - const requiredTrendName = nonEmptyString(trendName, "trendName"); - - const results = plainObject(document.results, "k6 summary.results"); - const ordinaryMetrics = indexMetrics(results.metrics, "k6 summary.results.metrics"); - const checks = plainObject(results.checks, "k6 summary.results.checks"); - const checkMetrics = indexMetrics( - checks.metrics, - "k6 summary.results.checks.metrics", - new Set(ordinaryMetrics.keys()), - ); - - const iterations = counterValue(ordinaryMetrics, "iterations", "k6 summary.results.metrics"); - const latencySamples = counterValue( - ordinaryMetrics, - "employment_separation_latency_samples", - "k6 summary.results.metrics", - ); - const unexpected = rateValue( - ordinaryMetrics, - "employment_separation_unexpected_response", - "k6 summary.results.metrics", - ); - const trend = trendValue(ordinaryMetrics, requiredTrendName, "k6 summary.results.metrics"); - - const checksTotal = counterValue(checkMetrics, "checks_total", "k6 summary.results.checks.metrics"); - const checksSucceeded = rateValue(checkMetrics, "checks_succeeded", "k6 summary.results.checks.metrics"); - const checksFailed = rateValue(checkMetrics, "checks_failed", "k6 summary.results.checks.metrics"); - if ( - checksSucceeded.total !== checksTotal - || checksFailed.total !== checksTotal - || checksSucceeded.matches + checksFailed.matches !== checksTotal - ) { - fail("k6 check aggregate metrics must describe the same complete check population"); - } - - return Object.freeze({ - summary_version: SUPPORTED_SUMMARY_VERSION, - summary_k6_version: declaredK6Version, - metrics: Object.freeze({ - iterations: Object.freeze({ values: Object.freeze({ count: iterations }) }), - checks: Object.freeze({ - values: Object.freeze({ - rate: checksSucceeded.rate, - passes: checksSucceeded.matches, - fails: checksFailed.matches, - }), - }), - employment_separation_unexpected_response: Object.freeze({ - values: Object.freeze({ - rate: unexpected.rate, - passes: unexpected.matches, - fails: unexpected.total - unexpected.matches, - }), - }), - employment_separation_latency_samples: Object.freeze({ - values: Object.freeze({ count: latencySamples }), - }), - [requiredTrendName]: Object.freeze({ values: trend }), - }), - }); -} From 807eaf652a38062aef3228b34a9ff9e5bbeab13e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 23:12:55 +0900 Subject: [PATCH 234/269] test(perf): reject non-JSON separation response media types --- ...loyment_separation_response_contract.test.mjs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 0e4355ac5..a84170409 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -2,6 +2,7 @@ import assert from "node:assert/strict"; import test from "node:test"; import { + hasGovernedSeparationJsonMediaType, isGovernedSeparationConflict, isGovernedSeparationSuccess, parseGovernedSeparationResponseBody, @@ -111,6 +112,21 @@ test("rejects success responses that are replay- or target-inconsistent", () => ); }); +test("accepts only one governed JSON response media type", () => { + assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json" }), true); + assert.equal(hasGovernedSeparationJsonMediaType({ "content-type": "Application/JSON; charset=utf-8" }), true); + assert.equal(hasGovernedSeparationJsonMediaType({}), false); + assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": "text/plain" }), false); + assert.equal( + hasGovernedSeparationJsonMediaType({ + "Content-Type": "application/json", + "content-type": "application/json", + }), + false, + ); + assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": ["application/json"] }), false); +}); + test("accepts only the published closed ErrorResponse shape for separation conflicts", () => { assert.equal(isGovernedSeparationConflict(409, conflictBody()), true); assert.equal(isGovernedSeparationConflict(409, { error: "separation_conflict" }), false); From 0ea2a597712df3628afe601777f63b1d8c9ce4c8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 23:13:40 +0900 Subject: [PATCH 235/269] fix(perf): validate separation JSON response media type --- .../employment_separation_response_contract.mjs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index 3cb635899..994c5c63d 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -55,6 +55,18 @@ function isValidUtcTimestamp(value) { ); } +export function hasGovernedSeparationJsonMediaType(headers) { + if (!isPlainObject(headers)) return false; + const contentTypeEntries = Object.entries(headers).filter( + ([name]) => name.toLowerCase() === "content-type", + ); + if (contentTypeEntries.length !== 1) return false; + const value = contentTypeEntries[0][1]; + if (typeof value !== "string") return false; + const mediaType = value.split(";", 1)[0].trim().toLowerCase(); + return mediaType === "application/json"; +} + export function parseGovernedSeparationResponseBody(value) { if (typeof value !== "string") { throw new Error("governed separation response body must be JSON text"); From 273396de823b94c1456602318cb0f8c7c14ba32c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 15 Sep 2026 23:14:10 +0900 Subject: [PATCH 236/269] fix(perf): bind separation verdicts to JSON media type --- tests/performance/employment_separation_buyer_path.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index e70833481..658fe4829 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -16,6 +16,7 @@ import { import { requirePinnedK6Runtime } from "./employment_separation_k6_runtime_contract.mjs"; import { normalizeEmploymentSeparationK6Summary } from "./employment_separation_k6_summary_contract.mjs"; import { + hasGovernedSeparationJsonMediaType, isGovernedSeparationConflict, isGovernedSeparationSuccess, parseGovernedSeparationResponseBody, @@ -96,6 +97,7 @@ function recordAt(profile) { return records[index]; } function parseJson(response) { + if (!hasGovernedSeparationJsonMediaType(response.headers)) return null; try { return parseGovernedSeparationResponseBody(response.body); } catch (_) { return null; } } From 3eb5a05b13b6eb2b942ff9326cd5fb1fa2b75d15 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 00:02:40 +0900 Subject: [PATCH 237/269] test(perf): expose collapsed Content-Type ambiguity --- ...ployment_separation_response_contract.test.mjs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index a84170409..3dff54bf9 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -127,6 +127,21 @@ test("accepts only one governed JSON response media type", () => { assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": ["application/json"] }), false); }); +test("rejects k6-collapsed duplicate Content-Type values without rejecting quoted parameter commas", () => { + assert.equal( + hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; charset=utf-8, text/plain" }), + false, + ); + assert.equal( + hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; profile=\"a,b\"" }), + true, + ); + assert.equal( + hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; profile=\"unterminated, text/plain" }), + false, + ); +}); + test("accepts only the published closed ErrorResponse shape for separation conflicts", () => { assert.equal(isGovernedSeparationConflict(409, conflictBody()), true); assert.equal(isGovernedSeparationConflict(409, { error: "separation_conflict" }), false); From 64a9e9ae093472ca3aabfbde48d17778d8f2dcec Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 00:03:35 +0900 Subject: [PATCH 238/269] fix(perf): reject collapsed Content-Type ambiguity --- ...mployment_separation_response_contract.mjs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index 994c5c63d..15142ba85 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -55,6 +55,27 @@ function isValidUtcTimestamp(value) { ); } +function hasSingleContentTypeFieldValue(value) { + let quoted = false; + let escaped = false; + for (const character of value) { + if (escaped) { + escaped = false; + continue; + } + if (quoted && character === "\\") { + escaped = true; + continue; + } + if (character === '"') { + quoted = !quoted; + continue; + } + if (!quoted && character === ",") return false; + } + return !quoted && !escaped; +} + export function hasGovernedSeparationJsonMediaType(headers) { if (!isPlainObject(headers)) return false; const contentTypeEntries = Object.entries(headers).filter( @@ -62,7 +83,7 @@ export function hasGovernedSeparationJsonMediaType(headers) { ); if (contentTypeEntries.length !== 1) return false; const value = contentTypeEntries[0][1]; - if (typeof value !== "string") return false; + if (typeof value !== "string" || !hasSingleContentTypeFieldValue(value)) return false; const mediaType = value.split(";", 1)[0].trim().toLowerCase(); return mediaType === "application/json"; } From 842320cffa37d98c3ae474acc79f8e7c53411c6c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 00:06:10 +0900 Subject: [PATCH 239/269] test(perf): cover malformed Content-Type parameter syntax --- .../employment_separation_response_contract.test.mjs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 3dff54bf9..84086f94b 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -136,10 +136,19 @@ test("rejects k6-collapsed duplicate Content-Type values without rejecting quote hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; profile=\"a,b\"" }), true, ); + assert.equal( + hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; profile=\"a\\\",b\"" }), + true, + ); assert.equal( hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; profile=\"unterminated, text/plain" }), false, ); + assert.equal( + hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; profile=a\"b,c\"" }), + false, + ); + assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json;" }), false); }); test("accepts only the published closed ErrorResponse shape for separation conflicts", () => { From cac6fbf7652e5b3d976fc2439376aae47ac4e7ed Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 00:06:33 +0900 Subject: [PATCH 240/269] fix(perf): validate single Content-Type representation --- ...mployment_separation_response_contract.mjs | 72 ++++++++++++++++--- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index 15142ba85..a14d35fe3 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -3,6 +3,7 @@ import { parseStrictJsonText } from "./strict_json_artifact.mjs"; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; const SUPPORT_REFERENCE_PATTERN = /^err_[A-Za-z0-9_-]{20,80}$/; +const HTTP_TOKEN_PATTERN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u; const SUCCESS_RESPONSE_KEYS = Object.freeze([ "employment_record_id", "separated_employment_record_version_id", @@ -55,25 +56,73 @@ function isValidUtcTimestamp(value) { ); } -function hasSingleContentTypeFieldValue(value) { +function splitContentTypeSegments(value) { + const segments = []; + let start = 0; let quoted = false; let escaped = false; - for (const character of value) { + for (let index = 0; index < value.length; index += 1) { + const character = value[index]; if (escaped) { + const codePoint = character.codePointAt(0); + if (codePoint !== 0x09 && (codePoint < 0x20 || codePoint === 0x7f)) return null; escaped = false; continue; } - if (quoted && character === "\\") { - escaped = true; + if (quoted) { + if (character === "\\") { + escaped = true; + } else if (character === '"') { + quoted = false; + } else { + const codePoint = character.codePointAt(0); + if (codePoint !== 0x09 && (codePoint < 0x20 || codePoint === 0x7f)) return null; + } continue; } if (character === '"') { - quoted = !quoted; + quoted = true; continue; } - if (!quoted && character === ",") return false; + if (character === ",") return null; + if (character === ";") { + segments.push(value.slice(start, index)); + start = index + 1; + } } - return !quoted && !escaped; + if (quoted || escaped) return null; + segments.push(value.slice(start)); + return segments; +} + +function isValidQuotedParameterValue(value) { + if (value.length < 2 || value[0] !== '"' || value[value.length - 1] !== '"') return false; + let escaped = false; + for (let index = 1; index < value.length - 1; index += 1) { + const character = value[index]; + const codePoint = character.codePointAt(0); + if (escaped) { + if (codePoint !== 0x09 && (codePoint < 0x20 || codePoint === 0x7f)) return false; + escaped = false; + continue; + } + if (character === "\\") { + escaped = true; + continue; + } + if (character === '"') return false; + if (codePoint !== 0x09 && (codePoint < 0x20 || codePoint === 0x7f)) return false; + } + return !escaped; +} + +function isValidContentTypeParameter(segment) { + const separator = segment.indexOf("="); + if (separator <= 0) return false; + const name = segment.slice(0, separator).trim(); + const value = segment.slice(separator + 1).trim(); + if (!HTTP_TOKEN_PATTERN.test(name) || value === "") return false; + return HTTP_TOKEN_PATTERN.test(value) || isValidQuotedParameterValue(value); } export function hasGovernedSeparationJsonMediaType(headers) { @@ -83,9 +132,12 @@ export function hasGovernedSeparationJsonMediaType(headers) { ); if (contentTypeEntries.length !== 1) return false; const value = contentTypeEntries[0][1]; - if (typeof value !== "string" || !hasSingleContentTypeFieldValue(value)) return false; - const mediaType = value.split(";", 1)[0].trim().toLowerCase(); - return mediaType === "application/json"; + if (typeof value !== "string") return false; + const segments = splitContentTypeSegments(value); + if (segments === null || segments.length < 1) return false; + const mediaType = segments[0].trim().toLowerCase(); + if (mediaType !== "application/json") return false; + return segments.slice(1).every((segment) => isValidContentTypeParameter(segment.trim())); } export function parseGovernedSeparationResponseBody(value) { From 0de56e181da3a112b2a2a10072b37156b7425a38 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 00:08:37 +0900 Subject: [PATCH 241/269] test(perf): enforce media-type parameter grammar --- .../employment_separation_response_contract.test.mjs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 84086f94b..1aa16eead 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -151,6 +151,15 @@ test("rejects k6-collapsed duplicate Content-Type values without rejecting quote assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json;" }), false); }); +test("rejects invalid or duplicate media-type parameters", () => { + assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; charset =utf-8" }), false); + assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; charset= utf-8" }), false); + assert.equal( + hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; charset=utf-8; Charset=latin1" }), + false, + ); +}); + test("accepts only the published closed ErrorResponse shape for separation conflicts", () => { assert.equal(isGovernedSeparationConflict(409, conflictBody()), true); assert.equal(isGovernedSeparationConflict(409, { error: "separation_conflict" }), false); From 4220c168f39fb46cc00ebd6b57be3622865cef75 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 00:09:09 +0900 Subject: [PATCH 242/269] fix(perf): enforce Content-Type parameter grammar --- ...mployment_separation_response_contract.mjs | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index a14d35fe3..a5fd5526c 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -1,6 +1,6 @@ import { parseStrictJsonText } from "./strict_json_artifact.mjs"; -const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; const SUPPORT_REFERENCE_PATTERN = /^err_[A-Za-z0-9_-]{20,80}$/; const HTTP_TOKEN_PATTERN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u; @@ -116,13 +116,16 @@ function isValidQuotedParameterValue(value) { return !escaped; } -function isValidContentTypeParameter(segment) { - const separator = segment.indexOf("="); - if (separator <= 0) return false; - const name = segment.slice(0, separator).trim(); - const value = segment.slice(separator + 1).trim(); - if (!HTTP_TOKEN_PATTERN.test(name) || value === "") return false; - return HTTP_TOKEN_PATTERN.test(value) || isValidQuotedParameterValue(value); +function parseContentTypeParameter(segment) { + const text = segment.trim(); + const separator = text.indexOf("="); + if (separator <= 0) return null; + const rawName = text.slice(0, separator); + const rawValue = text.slice(separator + 1); + if (rawName !== rawName.trim() || rawValue !== rawValue.trim()) return null; + if (!HTTP_TOKEN_PATTERN.test(rawName) || rawValue === "") return null; + if (!HTTP_TOKEN_PATTERN.test(rawValue) && !isValidQuotedParameterValue(rawValue)) return null; + return rawName.toLowerCase(); } export function hasGovernedSeparationJsonMediaType(headers) { @@ -137,7 +140,13 @@ export function hasGovernedSeparationJsonMediaType(headers) { if (segments === null || segments.length < 1) return false; const mediaType = segments[0].trim().toLowerCase(); if (mediaType !== "application/json") return false; - return segments.slice(1).every((segment) => isValidContentTypeParameter(segment.trim())); + const parameterNames = new Set(); + for (const segment of segments.slice(1)) { + const parameterName = parseContentTypeParameter(segment); + if (parameterName === null || parameterNames.has(parameterName)) return false; + parameterNames.add(parameterName); + } + return true; } export function parseGovernedSeparationResponseBody(value) { From 1f628c6b55a9bc66e894b03966b673f9be14373a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 01:07:39 +0900 Subject: [PATCH 243/269] test(perf): expose unbounded separation response JSON --- ...ment_separation_response_contract.test.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 1aa16eead..3285b4ba1 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -169,6 +169,25 @@ test("accepts only the published closed ErrorResponse shape for separation confl assert.equal(isGovernedSeparationConflict(404, conflictBody()), false); }); +test("bounds governed response JSON before strict parsing while preserving the closed error envelope", () => { + const escapedBoundaryText = "\u0001".repeat(1000); + const largestSemanticEnvelope = JSON.stringify(conflictBody({ + message: escapedBoundaryText, + next_action: escapedBoundaryText, + })); + assert.ok(largestSemanticEnvelope.length < 16 * 1024); + assert.deepEqual( + parseGovernedSeparationResponseBody(largestSemanticEnvelope), + JSON.parse(largestSemanticEnvelope), + ); + + const oversized = `${" ".repeat(16 * 1024)}${JSON.stringify(successBody(false))}`; + assert.throws( + () => parseGovernedSeparationResponseBody(oversized), + /governed separation response body must not exceed 16384 UTF-8 bytes/, + ); +}); + test("strict response parsing rejects duplicate trust-bearing JSON members before semantic validation", () => { assert.throws( () => parseGovernedSeparationResponseBody(`{"employment_record_id":"${EMPLOYMENT}","separated_employment_record_version_id":"${VERSION}","recorded_at":"2026-09-13T02:00:00Z","replayed":true,"replayed":false}`), From 831fe286824e2180903085f46d4e16ee845f4a04 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 01:08:08 +0900 Subject: [PATCH 244/269] fix(perf): bound governed separation response bytes --- ...mployment_separation_response_contract.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index a5fd5526c..aa34eda16 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -4,6 +4,7 @@ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; const SUPPORT_REFERENCE_PATTERN = /^err_[A-Za-z0-9_-]{20,80}$/; const HTTP_TOKEN_PATTERN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u; +const MAXIMUM_GOVERNED_RESPONSE_BODY_BYTES = 16 * 1024; const SUCCESS_RESPONSE_KEYS = Object.freeze([ "employment_record_id", "separated_employment_record_version_id", @@ -128,6 +129,19 @@ function parseContentTypeParameter(segment) { return rawName.toLowerCase(); } +function exceedsUtf8ByteBudget(value, maximumBytes) { + let bytes = 0; + for (const character of value) { + const codePoint = character.codePointAt(0); + if (codePoint <= 0x7f) bytes += 1; + else if (codePoint <= 0x7ff) bytes += 2; + else if (codePoint <= 0xffff) bytes += 3; + else bytes += 4; + if (bytes > maximumBytes) return true; + } + return false; +} + export function hasGovernedSeparationJsonMediaType(headers) { if (!isPlainObject(headers)) return false; const contentTypeEntries = Object.entries(headers).filter( @@ -153,6 +167,11 @@ export function parseGovernedSeparationResponseBody(value) { if (typeof value !== "string") { throw new Error("governed separation response body must be JSON text"); } + if (exceedsUtf8ByteBudget(value, MAXIMUM_GOVERNED_RESPONSE_BODY_BYTES)) { + throw new Error( + `governed separation response body must not exceed ${MAXIMUM_GOVERNED_RESPONSE_BODY_BYTES} UTF-8 bytes`, + ); + } return parseStrictJsonText(value, "governed separation response body"); } From 790468c5fa174cd0b045226ab88ffb846dd6b30a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 01:13:04 +0900 Subject: [PATCH 245/269] test(perf): expose overprecise separation response timestamps --- ...tion_response_timestamp_precision.test.mjs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/performance/employment_separation_response_timestamp_precision.test.mjs diff --git a/tests/performance/employment_separation_response_timestamp_precision.test.mjs b/tests/performance/employment_separation_response_timestamp_precision.test.mjs new file mode 100644 index 000000000..f75b8a1db --- /dev/null +++ b/tests/performance/employment_separation_response_timestamp_precision.test.mjs @@ -0,0 +1,36 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { isGovernedSeparationSuccess } from "./employment_separation_response_contract.mjs"; + +const EMPLOYMENT = "30000000-0000-4000-8000-000000000001"; +const VERSION = "50000000-0000-4000-8000-000000000001"; + +function successBody(recordedAt) { + return { + employment_record_id: EMPLOYMENT, + separated_employment_record_version_id: VERSION, + recorded_at: recordedAt, + replayed: false, + }; +} + +function accepted(recordedAt) { + return isGovernedSeparationSuccess(200, successBody(recordedAt), { + employmentRecordId: EMPLOYMENT, + replayed: false, + }); +} + +test("accepts only recorded_at precision emitted by canonical People datetime serialization", () => { + for (const recordedAt of [ + "2026-09-13T02:00:00Z", + "2026-09-13T02:00:00.1Z", + "2026-09-13T02:00:00.123456Z", + ]) { + assert.equal(accepted(recordedAt), true, recordedAt); + } + + assert.equal(accepted("2026-09-13T02:00:00.1234567Z"), false); + assert.equal(accepted(`2026-09-13T02:00:00.${"1".repeat(17000)}Z`), false); +}); From f8d8eb061c1be2432904d342894798e04fe57255 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 01:13:28 +0900 Subject: [PATCH 246/269] fix(perf): bind response timestamp precision to People serializer --- tests/performance/employment_separation_response_contract.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index aa34eda16..b09e857a6 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -1,7 +1,7 @@ import { parseStrictJsonText } from "./strict_json_artifact.mjs"; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; -const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/; +const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?Z$/; const SUPPORT_REFERENCE_PATTERN = /^err_[A-Za-z0-9_-]{20,80}$/; const HTTP_TOKEN_PATTERN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u; const MAXIMUM_GOVERNED_RESPONSE_BODY_BYTES = 16 * 1024; From 3abbd2600c7301b820a5fee34fdaed8a3ae35ad4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 02:07:05 +0900 Subject: [PATCH 247/269] test(perf): reject noncanonical separation support references --- .../employment_separation_response_contract.test.mjs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 3285b4ba1..9f18a7ba2 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -25,7 +25,7 @@ function conflictBody(overrides = {}) { error_code: "separation_conflict", message: "Refresh Employment and Assignment state, then retry.", next_action: "Refresh Employment and Assignment state, then retry.", - support_reference: "err_ABCDEFGHIJKLMNOPQRSTUVWX", + support_reference: "err_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef", ...overrides, }; } @@ -169,6 +169,16 @@ test("accepts only the published closed ErrorResponse shape for separation confl assert.equal(isGovernedSeparationConflict(404, conflictBody()), false); }); +test("binds conflict support references to the canonical People token_urlsafe length", () => { + assert.equal(isGovernedSeparationConflict(409, conflictBody()), true); + for (const suffixLength of [24, 31, 33, 80]) { + assert.equal( + isGovernedSeparationConflict(409, conflictBody({ support_reference: `err_${"A".repeat(suffixLength)}` })), + false, + ); + } +}); + test("bounds governed response JSON before strict parsing while preserving the closed error envelope", () => { const escapedBoundaryText = "\u0001".repeat(1000); const largestSemanticEnvelope = JSON.stringify(conflictBody({ From de8b8ea71600e8b5c1f5acda4258562cde17dce0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 02:07:39 +0900 Subject: [PATCH 248/269] fix(perf): require canonical separation support references --- tests/performance/employment_separation_response_contract.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index b09e857a6..71288d7bc 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -2,7 +2,7 @@ import { parseStrictJsonText } from "./strict_json_artifact.mjs"; const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; const UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?Z$/; -const SUPPORT_REFERENCE_PATTERN = /^err_[A-Za-z0-9_-]{20,80}$/; +const SUPPORT_REFERENCE_PATTERN = /^err_[A-Za-z0-9_-]{32}$/; const HTTP_TOKEN_PATTERN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u; const MAXIMUM_GOVERNED_RESPONSE_BODY_BYTES = 16 * 1024; const SUCCESS_RESPONSE_KEYS = Object.freeze([ From a5e893da89276e06cba8840c9932a9fad791bf4b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 03:06:52 +0900 Subject: [PATCH 249/269] chore(perf): retain current People parent delta --- services/people-api/src/orgmetra_people_api/mutations.py | 4 ++++ services/people-api/src/orgmetra_people_api/separation.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/services/people-api/src/orgmetra_people_api/mutations.py b/services/people-api/src/orgmetra_people_api/mutations.py index f5c0c5602..eecd86aad 100644 --- a/services/people-api/src/orgmetra_people_api/mutations.py +++ b/services/people-api/src/orgmetra_people_api/mutations.py @@ -306,6 +306,10 @@ def __eq__(self, other: object) -> bool: """Keep result-type identity distinct even though storage is tuple-backed.""" return type(self) is type(other) and tuple.__eq__(self, other) + def __ne__(self, other: object) -> bool: + """Keep inequality symmetric with exact-type receipt equality.""" + return not self.__eq__(other) + def __hash__(self) -> int: """Hash the immutable receipt payload consistently with exact-type equality.""" return hash((type(self), tuple.__hash__(self))) diff --git a/services/people-api/src/orgmetra_people_api/separation.py b/services/people-api/src/orgmetra_people_api/separation.py index cb081e922..3b6822717 100644 --- a/services/people-api/src/orgmetra_people_api/separation.py +++ b/services/people-api/src/orgmetra_people_api/separation.py @@ -190,6 +190,10 @@ def __eq__(self, other: object) -> bool: """Keep receipt type identity distinct from an ordinary tuple.""" return type(self) is type(other) and tuple.__eq__(self, other) + def __ne__(self, other: object) -> bool: + """Keep inequality symmetric with exact-type receipt equality.""" + return not self.__eq__(other) + def __hash__(self) -> int: """Hash immutable receipt storage consistently with exact-type equality.""" return hash((type(self), tuple.__hash__(self))) From 079d2b737addb05961e9dbf32bce14a688118169 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 05:06:39 +0900 Subject: [PATCH 250/269] test(perf): require no-store separation response policy --- ...ment_separation_response_contract.test.mjs | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_response_contract.test.mjs b/tests/performance/employment_separation_response_contract.test.mjs index 9f18a7ba2..325b08f47 100644 --- a/tests/performance/employment_separation_response_contract.test.mjs +++ b/tests/performance/employment_separation_response_contract.test.mjs @@ -3,6 +3,7 @@ import test from "node:test"; import { hasGovernedSeparationJsonMediaType, + hasGovernedSeparationNoStorePolicy, isGovernedSeparationConflict, isGovernedSeparationSuccess, parseGovernedSeparationResponseBody, @@ -127,6 +128,46 @@ test("accepts only one governed JSON response media type", () => { assert.equal(hasGovernedSeparationJsonMediaType({ "Content-Type": ["application/json"] }), false); }); +test("requires the canonical no-store and Authorization-vary response policy", () => { + assert.equal( + hasGovernedSeparationNoStorePolicy({ "Cache-Control": "no-store", Vary: "Authorization" }), + true, + ); + assert.equal( + hasGovernedSeparationNoStorePolicy({ "cache-control": "No-Store", vary: "Accept-Encoding, authorization" }), + true, + ); + assert.equal(hasGovernedSeparationNoStorePolicy({ Vary: "Authorization" }), false); + assert.equal( + hasGovernedSeparationNoStorePolicy({ "Cache-Control": "public, no-store", Vary: "Authorization" }), + false, + ); + assert.equal( + hasGovernedSeparationNoStorePolicy({ "Cache-Control": "no-store, s-maxage=60", Vary: "Authorization" }), + false, + ); + assert.equal( + hasGovernedSeparationNoStorePolicy({ "Cache-Control": "no-store", Vary: "Accept-Encoding" }), + false, + ); + assert.equal( + hasGovernedSeparationNoStorePolicy({ "Cache-Control": "no-store", Vary: "*" }), + false, + ); + assert.equal( + hasGovernedSeparationNoStorePolicy({ + "Cache-Control": "no-store", + "cache-control": "no-store", + Vary: "Authorization", + }), + false, + ); + assert.equal( + hasGovernedSeparationNoStorePolicy({ "Cache-Control": ["no-store"], Vary: "Authorization" }), + false, + ); +}); + test("rejects k6-collapsed duplicate Content-Type values without rejecting quoted parameter commas", () => { assert.equal( hasGovernedSeparationJsonMediaType({ "Content-Type": "application/json; charset=utf-8, text/plain" }), @@ -212,4 +253,4 @@ test("strict response parsing rejects duplicate trust-bearing JSON members befor test("strict response parsing preserves the published response object", () => { const body = successBody(false); assert.deepEqual(parseGovernedSeparationResponseBody(JSON.stringify(body)), body); -}); +}); \ No newline at end of file From 839301222e19bec3976165093655d8ad7a6676d6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 05:07:19 +0900 Subject: [PATCH 251/269] fix(perf): require no-store separation response policy --- ...mployment_separation_response_contract.mjs | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/tests/performance/employment_separation_response_contract.mjs b/tests/performance/employment_separation_response_contract.mjs index 71288d7bc..ff9c4682b 100644 --- a/tests/performance/employment_separation_response_contract.mjs +++ b/tests/performance/employment_separation_response_contract.mjs @@ -129,6 +129,21 @@ function parseContentTypeParameter(segment) { return rawName.toLowerCase(); } +function singleResponseHeaderValue(headers, fieldName) { + if (!isPlainObject(headers)) return null; + const entries = Object.entries(headers).filter(([name]) => name.toLowerCase() === fieldName); + if (entries.length !== 1 || typeof entries[0][1] !== "string") return null; + return entries[0][1]; +} + +function commaSeparatedHttpTokens(value) { + const tokens = value.split(",").map((token) => token.trim()); + if (tokens.length < 1 || tokens.some((token) => !HTTP_TOKEN_PATTERN.test(token))) return null; + const normalized = tokens.map((token) => token.toLowerCase()); + if (new Set(normalized).size !== normalized.length) return null; + return normalized; +} + function exceedsUtf8ByteBudget(value, maximumBytes) { let bytes = 0; for (const character of value) { @@ -143,13 +158,8 @@ function exceedsUtf8ByteBudget(value, maximumBytes) { } export function hasGovernedSeparationJsonMediaType(headers) { - if (!isPlainObject(headers)) return false; - const contentTypeEntries = Object.entries(headers).filter( - ([name]) => name.toLowerCase() === "content-type", - ); - if (contentTypeEntries.length !== 1) return false; - const value = contentTypeEntries[0][1]; - if (typeof value !== "string") return false; + const value = singleResponseHeaderValue(headers, "content-type"); + if (value === null) return false; const segments = splitContentTypeSegments(value); if (segments === null || segments.length < 1) return false; const mediaType = segments[0].trim().toLowerCase(); @@ -163,6 +173,15 @@ export function hasGovernedSeparationJsonMediaType(headers) { return true; } +export function hasGovernedSeparationNoStorePolicy(headers) { + const cacheControl = singleResponseHeaderValue(headers, "cache-control"); + const vary = singleResponseHeaderValue(headers, "vary"); + if (cacheControl === null || vary === null) return false; + if (cacheControl.trim().toLowerCase() !== "no-store") return false; + const varyTokens = commaSeparatedHttpTokens(vary); + return varyTokens !== null && varyTokens.includes("authorization"); +} + export function parseGovernedSeparationResponseBody(value) { if (typeof value !== "string") { throw new Error("governed separation response body must be JSON text"); @@ -193,4 +212,4 @@ export function isGovernedSeparationConflict(status, body) { if (typeof body.message !== "string" || body.message.length < 1 || body.message.length > 1000) return false; if (typeof body.next_action !== "string" || body.next_action.length < 1 || body.next_action.length > 1000) return false; return typeof body.support_reference === "string" && SUPPORT_REFERENCE_PATTERN.test(body.support_reference); -} +} \ No newline at end of file From 79c5229717459ea6090d22652500484d9c5a0246 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 05:07:43 +0900 Subject: [PATCH 252/269] fix(perf): enforce no-store policy before response parsing --- tests/performance/employment_separation_buyer_path.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 658fe4829..8caa8b2f7 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -17,6 +17,7 @@ import { requirePinnedK6Runtime } from "./employment_separation_k6_runtime_contr import { normalizeEmploymentSeparationK6Summary } from "./employment_separation_k6_summary_contract.mjs"; import { hasGovernedSeparationJsonMediaType, + hasGovernedSeparationNoStorePolicy, isGovernedSeparationConflict, isGovernedSeparationSuccess, parseGovernedSeparationResponseBody, @@ -98,6 +99,7 @@ function recordAt(profile) { } function parseJson(response) { if (!hasGovernedSeparationJsonMediaType(response.headers)) return null; + if (!hasGovernedSeparationNoStorePolicy(response.headers)) return null; try { return parseGovernedSeparationResponseBody(response.body); } catch (_) { return null; } } @@ -172,4 +174,4 @@ export function handleSummary(data) { const rendered = `${JSON.stringify(payload, null, 2)}\n`; const path = __ENV.ORGMETRA_PERFORMANCE_SUMMARY_FILE || `employment-separation-performance-${selectedProfile}.json`; return { [path]: rendered, stdout: rendered }; -} +} \ No newline at end of file From b453ef96fe865dd3d2ad70d773d16c0519e6fd1f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 06:01:47 +0900 Subject: [PATCH 253/269] test(perf): require no-redirect buyer request policy --- ...yment_separation_request_contract.test.mjs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/performance/employment_separation_request_contract.test.mjs diff --git a/tests/performance/employment_separation_request_contract.test.mjs b/tests/performance/employment_separation_request_contract.test.mjs new file mode 100644 index 000000000..0a68961b1 --- /dev/null +++ b/tests/performance/employment_separation_request_contract.test.mjs @@ -0,0 +1,46 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { governedSeparationRequestParams } from "./employment_separation_request_contract.mjs"; + +const headers = Object.freeze({ + Authorization: "Bearer performance-token", + "Content-Type": "application/json", + "Idempotency-Key": "employment-separation-0001", + "X-Actor-Reference": "worker:performance-operator", + "X-Purpose-Code": "workforce_admin", + "X-Tenant-Reference": "10000000-0000-4000-8000-000000000001", +}); + +test("governed request params disable redirects without changing the request headers", () => { + const params = governedSeparationRequestParams(headers, "first_commit"); + + assert.equal(params.redirects, 0); + assert.strictEqual(params.headers, headers); + assert.deepEqual(params.tags, { profile: "first_commit" }); + assert.deepEqual(Object.keys(params).sort(), ["headers", "redirects", "tags"]); +}); + +test("governed request params apply the same no-redirect policy to every buyer profile", () => { + for (const profile of ["first_commit", "replay", "rejection", "contention"]) { + const params = governedSeparationRequestParams(headers, profile); + assert.equal(params.redirects, 0, `${profile} must not follow redirects`); + assert.deepEqual(params.tags, { profile }); + } +}); + +test("governed request params reject unknown profiles", () => { + assert.throws( + () => governedSeparationRequestParams(headers, "redirected_success"), + /unsupported Employment-separation performance profile/, + ); +}); + +test("governed request params reject non-object headers", () => { + for (const invalid of [null, [], "Authorization: Bearer token"] ) { + assert.throws( + () => governedSeparationRequestParams(invalid, "first_commit"), + /request headers must be a plain object/, + ); + } +}); From b78e7fb5901e5c35e0027c90f1d67a5c0c69e4b1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 06:01:58 +0900 Subject: [PATCH 254/269] fix(perf): disable redirect following in buyer requests --- ...employment_separation_request_contract.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/performance/employment_separation_request_contract.mjs diff --git a/tests/performance/employment_separation_request_contract.mjs b/tests/performance/employment_separation_request_contract.mjs new file mode 100644 index 000000000..613a80a7d --- /dev/null +++ b/tests/performance/employment_separation_request_contract.mjs @@ -0,0 +1,19 @@ +const PERFORMANCE_PROFILES = new Set(["first_commit", "replay", "rejection", "contention"]); + +function isPlainObject(value) { + return value !== null && typeof value === "object" && !Array.isArray(value); +} + +export function governedSeparationRequestParams(headers, profile) { + if (!isPlainObject(headers)) { + throw new Error("Employment-separation request headers must be a plain object"); + } + if (!PERFORMANCE_PROFILES.has(profile)) { + throw new Error(`unsupported Employment-separation performance profile: ${profile}`); + } + return { + headers, + redirects: 0, + tags: { profile }, + }; +} From 3a78672949032f324fe3bbeae0f427ec73920bd7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 06:02:21 +0900 Subject: [PATCH 255/269] fix(perf): bind buyer path to no-redirect request policy --- .../employment_separation_buyer_path.js | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 8caa8b2f7..3acb6c373 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -13,6 +13,7 @@ import { requestHeaders, validatePerformanceFixture, } from "./employment_separation_fixture_contract.mjs"; +import { governedSeparationRequestParams } from "./employment_separation_request_contract.mjs"; import { requirePinnedK6Runtime } from "./employment_separation_k6_runtime_contract.mjs"; import { normalizeEmploymentSeparationK6Summary } from "./employment_separation_k6_summary_contract.mjs"; import { @@ -104,7 +105,12 @@ function parseJson(response) { catch (_) { return null; } } function post(command, profile) { - return http.post(`${baseUrl}${ROUTE}`, requestBody(command), { headers: requestHeaders(command, bearerToken), tags: { profile } }); + const headers = requestHeaders(command, bearerToken); + return http.post( + `${baseUrl}${ROUTE}`, + requestBody(command), + governedSeparationRequestParams(headers, profile), + ); } function observe(response, trend, profile, predicate) { trend.add(buyerPathElapsedMs(response.timings), { profile }); @@ -130,8 +136,18 @@ export function rejection() { export function contention() { const pair = recordAt("contention"); const responses = http.batch([ - ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.left), { headers: requestHeaders(pair.left, bearerToken), tags: { profile: "contention" } }], - ["POST", `${baseUrl}${ROUTE}`, requestBody(pair.right), { headers: requestHeaders(pair.right, bearerToken), tags: { profile: "contention" } }], + [ + "POST", + `${baseUrl}${ROUTE}`, + requestBody(pair.left), + governedSeparationRequestParams(requestHeaders(pair.left, bearerToken), "contention"), + ], + [ + "POST", + `${baseUrl}${ROUTE}`, + requestBody(pair.right), + governedSeparationRequestParams(requestHeaders(pair.right, bearerToken), "contention"), + ], ]); for (const response of responses) { contentionDuration.add(buyerPathElapsedMs(response.timings), { profile: "contention" }); latencySamples.add(1, { profile: "contention" }); } const parsed = responses.map((response) => ({ status: response.status, body: parseJson(response) })); @@ -174,4 +190,4 @@ export function handleSummary(data) { const rendered = `${JSON.stringify(payload, null, 2)}\n`; const path = __ENV.ORGMETRA_PERFORMANCE_SUMMARY_FILE || `employment-separation-performance-${selectedProfile}.json`; return { [path]: rendered, stdout: rendered }; -} \ No newline at end of file +} From 5d830693470a96af67b5f85f50ee76d13fc8e8cf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 07:04:27 +0900 Subject: [PATCH 256/269] test(perf): require HTTPS buyer evidence origin --- ...yment_separation_request_contract.test.mjs | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/performance/employment_separation_request_contract.test.mjs b/tests/performance/employment_separation_request_contract.test.mjs index 0a68961b1..f1c8e68d8 100644 --- a/tests/performance/employment_separation_request_contract.test.mjs +++ b/tests/performance/employment_separation_request_contract.test.mjs @@ -1,7 +1,10 @@ import assert from "node:assert/strict"; import test from "node:test"; -import { governedSeparationRequestParams } from "./employment_separation_request_contract.mjs"; +import { + governedSeparationRequestParams, + requireGovernedSeparationHttpsOrigin, +} from "./employment_separation_request_contract.mjs"; const headers = Object.freeze({ Authorization: "Bearer performance-token", @@ -12,6 +15,40 @@ const headers = Object.freeze({ "X-Tenant-Reference": "10000000-0000-4000-8000-000000000001", }); +test("commercial Employment-separation origin requires authenticated HTTPS", () => { + assert.equal( + requireGovernedSeparationHttpsOrigin("https://people.example.com"), + "https://people.example.com", + ); + assert.equal( + requireGovernedSeparationHttpsOrigin("https://people.example.com:8443/"), + "https://people.example.com:8443", + ); + assert.equal( + requireGovernedSeparationHttpsOrigin("https://127.0.0.1:9443"), + "https://127.0.0.1:9443", + ); +}); + +test("commercial Employment-separation origin rejects plaintext and caller-controlled URL components", () => { + for (const invalid of [ + "http://people.example.com", + "https://user:password@people.example.com", + "https://people.example.com/v1", + "https://people.example.com?tenant=other", + "https://people.example.com#fragment", + " https://people.example.com", + "https://people.example.com:0", + "https://people.example.com:65536", + ]) { + assert.throws( + () => requireGovernedSeparationHttpsOrigin(invalid), + /authenticated HTTPS origin/, + invalid, + ); + } +}); + test("governed request params disable redirects without changing the request headers", () => { const params = governedSeparationRequestParams(headers, "first_commit"); From 336792c0bb1c0e63cd41b9fca60ba73b568093ac Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 07:04:57 +0900 Subject: [PATCH 257/269] fix(perf): require authenticated HTTPS buyer origin --- ...employment_separation_request_contract.mjs | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/performance/employment_separation_request_contract.mjs b/tests/performance/employment_separation_request_contract.mjs index 613a80a7d..ebdcfb66f 100644 --- a/tests/performance/employment_separation_request_contract.mjs +++ b/tests/performance/employment_separation_request_contract.mjs @@ -1,9 +1,61 @@ const PERFORMANCE_PROFILES = new Set(["first_commit", "replay", "rejection", "contention"]); +const HTTPS_ORIGIN_PREFIX = "https://"; +const DNS_OR_IPV4_HOST_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?$/; +const BRACKETED_IP_LITERAL_PATTERN = /^\[[0-9A-Fa-f:.]+\]$/; function isPlainObject(value) { return value !== null && typeof value === "object" && !Array.isArray(value); } +function invalidHttpsOrigin() { + throw new Error("ORGMETRA_PERFORMANCE_BASE_URL must be an authenticated HTTPS origin"); +} + +function requireValidPort(value) { + if (!/^\d{1,5}$/.test(value)) invalidHttpsOrigin(); + const port = Number(value); + if (!Number.isSafeInteger(port) || port < 1 || port > 65535) invalidHttpsOrigin(); +} + +export function requireGovernedSeparationHttpsOrigin(value) { + if (typeof value !== "string" || value === "" || value !== value.trim()) invalidHttpsOrigin(); + if (!value.startsWith(HTTPS_ORIGIN_PREFIX)) invalidHttpsOrigin(); + + let authority = value.slice(HTTPS_ORIGIN_PREFIX.length); + const slash = authority.indexOf("/"); + if (slash !== -1) { + if (slash !== authority.length - 1 || authority.lastIndexOf("/") !== slash) invalidHttpsOrigin(); + authority = authority.slice(0, -1); + } + if ( + authority === "" + || authority.includes("@") + || authority.includes("?") + || authority.includes("#") + || /[\u0000-\u0020\u007f]/.test(authority) + ) invalidHttpsOrigin(); + + if (authority.startsWith("[")) { + const closingBracket = authority.indexOf("]"); + if (closingBracket < 2) invalidHttpsOrigin(); + const host = authority.slice(0, closingBracket + 1); + if (!BRACKETED_IP_LITERAL_PATTERN.test(host) || !host.includes(":")) invalidHttpsOrigin(); + const suffix = authority.slice(closingBracket + 1); + if (suffix !== "") { + if (!suffix.startsWith(":")) invalidHttpsOrigin(); + requireValidPort(suffix.slice(1)); + } + } else { + const colon = authority.lastIndexOf(":"); + if (colon !== authority.indexOf(":")) invalidHttpsOrigin(); + const host = colon === -1 ? authority : authority.slice(0, colon); + if (!DNS_OR_IPV4_HOST_PATTERN.test(host) || host.includes("..")) invalidHttpsOrigin(); + if (colon !== -1) requireValidPort(authority.slice(colon + 1)); + } + + return `${HTTPS_ORIGIN_PREFIX}${authority}`; +} + export function governedSeparationRequestParams(headers, profile) { if (!isPlainObject(headers)) { throw new Error("Employment-separation request headers must be a plain object"); From 822e591b3b111e5900daecefdd20ea160e50abbe Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 07:05:36 +0900 Subject: [PATCH 258/269] perf(people): bind buyer workload to HTTPS origin --- tests/performance/employment_separation_buyer_path.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index 3acb6c373..c90e0393e 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -13,7 +13,10 @@ import { requestHeaders, validatePerformanceFixture, } from "./employment_separation_fixture_contract.mjs"; -import { governedSeparationRequestParams } from "./employment_separation_request_contract.mjs"; +import { + governedSeparationRequestParams, + requireGovernedSeparationHttpsOrigin, +} from "./employment_separation_request_contract.mjs"; import { requirePinnedK6Runtime } from "./employment_separation_k6_runtime_contract.mjs"; import { normalizeEmploymentSeparationK6Summary } from "./employment_separation_k6_summary_contract.mjs"; import { @@ -43,7 +46,7 @@ const TREND_BY_PROFILE = Object.freeze({ contention: "employment_separation_contention_duration_ms", }); const fixturePath = __ENV.ORGMETRA_PERFORMANCE_DATA_FILE; -const baseUrl = (__ENV.ORGMETRA_PERFORMANCE_BASE_URL || "").replace(/\/$/, ""); +const baseUrl = requireGovernedSeparationHttpsOrigin(__ENV.ORGMETRA_PERFORMANCE_BASE_URL || ""); const bearerToken = __ENV.ORGMETRA_PERFORMANCE_BEARER_TOKEN || ""; const targetSha = (__ENV.ORGMETRA_PERFORMANCE_TARGET_SHA || "").toLowerCase(); const selectedProfile = requirePerformanceProfile(__ENV.ORGMETRA_PERFORMANCE_PROFILE || ""); @@ -56,7 +59,6 @@ const k6Runtime = requirePinnedK6Runtime({ }); if (!fixturePath) fail("ORGMETRA_PERFORMANCE_DATA_FILE is required"); -if (!baseUrl) fail("ORGMETRA_PERFORMANCE_BASE_URL is required"); if (!bearerToken) fail("ORGMETRA_PERFORMANCE_BEARER_TOKEN is required and must not be stored in the fixture"); if (!/^[0-9a-f]{40}$/.test(targetSha)) fail("ORGMETRA_PERFORMANCE_TARGET_SHA must be a full Git commit SHA"); From ad71be48b12197a2bbc1170381221f8d174ff1c1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 07:08:16 +0900 Subject: [PATCH 259/269] test(perf): forbid disabled TLS verification --- .../employment_separation_run_contract.test.mjs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index ef362d249..228b06772 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -8,6 +8,7 @@ import { arrivalRateScenarioForPerformanceProfile, requireDirectPerformanceClientNetwork, requirePerformanceProfile, + requireVerifiedTlsTransport, thresholdsForPerformanceProfile, validatePerformanceLoadModel, } from "./employment_separation_run_contract.mjs"; @@ -103,6 +104,14 @@ test("fails closed when the k6 client is routed through an ambient proxy", () => ); }); +test("fails closed when resolved k6 options disable TLS certificate verification", () => { + assert.equal(requireVerifiedTlsTransport(false), false); + assert.throws( + () => requireVerifiedTlsTransport(true), + /TLS certificate verification must remain enabled/, + ); +}); + test("uses exact scheduled completion rather than a zero-sample dropped-iteration threshold", () => { assert.deepEqual(thresholdsForPerformanceProfile("first_commit", 1000), { employment_separation_unexpected_response: ["rate==0"], From b5d20e8a8b9fe9b5761ac85f31fba85dbdcf587d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 07:08:33 +0900 Subject: [PATCH 260/269] fix(perf): fail closed on disabled TLS verification --- tests/performance/employment_separation_run_contract.mjs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index e2d56ef6a..47e451445 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -76,6 +76,13 @@ export function requireDirectPerformanceClientNetwork(environment) { return PERFORMANCE_CLIENT_NETWORK_TOPOLOGY; } +export function requireVerifiedTlsTransport(insecureSkipTlsVerify) { + if (insecureSkipTlsVerify !== false) { + throw new Error("TLS certificate verification must remain enabled for commercial timing acceptance"); + } + return insecureSkipTlsVerify; +} + export function validatePerformanceLoadModel(value, expectedIterations, profile) { if (value === null || typeof value !== "object" || Array.isArray(value)) { throw new Error("load_model must be an object"); From ea458c3ca81bf1e87ceb22b6251fa8452d0478a3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 07:09:07 +0900 Subject: [PATCH 261/269] fix(perf): accept only verified k6 TLS state --- tests/performance/employment_separation_run_contract.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.mjs b/tests/performance/employment_separation_run_contract.mjs index 47e451445..69bf08d0f 100644 --- a/tests/performance/employment_separation_run_contract.mjs +++ b/tests/performance/employment_separation_run_contract.mjs @@ -77,10 +77,10 @@ export function requireDirectPerformanceClientNetwork(environment) { } export function requireVerifiedTlsTransport(insecureSkipTlsVerify) { - if (insecureSkipTlsVerify !== false) { + if (![false, null, undefined].includes(insecureSkipTlsVerify)) { throw new Error("TLS certificate verification must remain enabled for commercial timing acceptance"); } - return insecureSkipTlsVerify; + return false; } export function validatePerformanceLoadModel(value, expectedIterations, profile) { From b87001c4b8b0154bcb259a2fac5dc5d4dc13108b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 07:09:32 +0900 Subject: [PATCH 262/269] perf(people): reject insecure TLS runtime override --- tests/performance/employment_separation_buyer_path.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/performance/employment_separation_buyer_path.js b/tests/performance/employment_separation_buyer_path.js index c90e0393e..41ef8cc65 100644 --- a/tests/performance/employment_separation_buyer_path.js +++ b/tests/performance/employment_separation_buyer_path.js @@ -32,6 +32,7 @@ import { arrivalRateScenarioForPerformanceProfile, requireDirectPerformanceClientNetwork, requirePerformanceProfile, + requireVerifiedTlsTransport, thresholdsForPerformanceProfile, } from "./employment_separation_run_contract.mjs"; import { buyerPathElapsedMs } from "./employment_separation_timing_contract.mjs"; @@ -100,6 +101,9 @@ function recordAt(profile) { if (index < 0 || index >= records.length) fail(`${profile} iteration ${index} is outside the fixture`); return records[index]; } +function requireCommercialTls() { + requireVerifiedTlsTransport(exec.test.options.insecureSkipTLSVerify); +} function parseJson(response) { if (!hasGovernedSeparationJsonMediaType(response.headers)) return null; if (!hasGovernedSeparationNoStorePolicy(response.headers)) return null; @@ -107,6 +111,7 @@ function parseJson(response) { catch (_) { return null; } } function post(command, profile) { + requireCommercialTls(); const headers = requestHeaders(command, bearerToken); return http.post( `${baseUrl}${ROUTE}`, @@ -136,6 +141,7 @@ export function rejection() { observe(response, rejectionDuration, "rejection", (result) => isGovernedSeparationConflict(result.status, parseJson(result))); } export function contention() { + requireCommercialTls(); const pair = recordAt("contention"); const responses = http.batch([ [ From 74f726d2e81ab7b15df4944387817059588045d1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 07:09:53 +0900 Subject: [PATCH 263/269] test(perf): cover resolved TLS option defaults --- .../employment_separation_run_contract.test.mjs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/performance/employment_separation_run_contract.test.mjs b/tests/performance/employment_separation_run_contract.test.mjs index 228b06772..34a2d8c86 100644 --- a/tests/performance/employment_separation_run_contract.test.mjs +++ b/tests/performance/employment_separation_run_contract.test.mjs @@ -105,11 +105,15 @@ test("fails closed when the k6 client is routed through an ambient proxy", () => }); test("fails closed when resolved k6 options disable TLS certificate verification", () => { - assert.equal(requireVerifiedTlsTransport(false), false); - assert.throws( - () => requireVerifiedTlsTransport(true), - /TLS certificate verification must remain enabled/, - ); + for (const safeDefault of [false, null, undefined]) { + assert.equal(requireVerifiedTlsTransport(safeDefault), false); + } + for (const unsafe of [true, "true", 1]) { + assert.throws( + () => requireVerifiedTlsTransport(unsafe), + /TLS certificate verification must remain enabled/, + ); + } }); test("uses exact scheduled completion rather than a zero-sample dropped-iteration threshold", () => { From 21f8528abbe3b7edee68b50c500aa5bf1d77cb3a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 08:05:52 +0900 Subject: [PATCH 264/269] test(perf): require deployed-candidate owner gap --- ...loyment_separation_acceptance_cli_digest.test.mjs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_cli_digest.test.mjs b/tests/performance/employment_separation_acceptance_cli_digest.test.mjs index 0a46d20f2..2aee8c315 100644 --- a/tests/performance/employment_separation_acceptance_cli_digest.test.mjs +++ b/tests/performance/employment_separation_acceptance_cli_digest.test.mjs @@ -5,7 +5,13 @@ import test from "node:test"; const acceptanceCheck = fileURLToPath(new URL("./employment_separation_acceptance_check.mjs", import.meta.url)); -const OWNER_GAP_PATTERN = /authenticated performance-evidence attestation.*ContextualWisdomLab\/.github#2162/; +const PERFORMANCE_ATTESTATION_GAP_PATTERN = /authenticated performance-evidence attestation.*ContextualWisdomLab\/.github#2162/; +const DEPLOYMENT_IDENTITY_GAP_PATTERN = /authenticated deployed-candidate evidence.*ContextualWisdomLab\/Orgmetra#395/; + +function assertCommercialOwnerGaps(stderr) { + assert.match(stderr, PERFORMANCE_ATTESTATION_GAP_PATTERN); + assert.match(stderr, DEPLOYMENT_IDENTITY_GAP_PATTERN); +} test("commercial acceptance fails closed before trusting a caller-supplied result digest", () => { const result = spawnSync( @@ -14,7 +20,7 @@ test("commercial acceptance fails closed before trusting a caller-supplied resul { encoding: "utf8" }, ); assert.notEqual(result.status, 0); - assert.match(result.stderr, OWNER_GAP_PATTERN); + assertCommercialOwnerGaps(result.stderr); }); test("commercial acceptance cannot be restored by substituting both result bytes and digest locally", () => { @@ -24,5 +30,5 @@ test("commercial acceptance cannot be restored by substituting both result bytes { encoding: "utf8" }, ); assert.notEqual(result.status, 0); - assert.match(result.stderr, OWNER_GAP_PATTERN); + assertCommercialOwnerGaps(result.stderr); }); From a5bf8abf51751a436e2cdc6cf694a798884413d5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 08:06:01 +0900 Subject: [PATCH 265/269] test(perf): add deployed-candidate evidence gate --- ...loyment_separation_deployment_evidence_gate.mjs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/performance/employment_separation_deployment_evidence_gate.mjs diff --git a/tests/performance/employment_separation_deployment_evidence_gate.mjs b/tests/performance/employment_separation_deployment_evidence_gate.mjs new file mode 100644 index 000000000..1271c4720 --- /dev/null +++ b/tests/performance/employment_separation_deployment_evidence_gate.mjs @@ -0,0 +1,14 @@ +export const AUTHENTICATED_DEPLOYMENT_EVIDENCE_OWNER = "ContextualWisdomLab/Orgmetra#395"; + +/** + * Keep commercial performance acceptance fail closed until the service that + * actually answered the timed requests is independently bound to the exact + * source candidate. A caller-authored observed_service_sha or deployment + * reference can be made internally consistent and later attested as bytes; + * neither proves which deployed workload served the HTTPS origin. + */ +export function requireAuthenticatedDeploymentEvidence() { + throw new Error( + `commercial acceptance requires authenticated deployed-candidate evidence from ${AUTHENTICATED_DEPLOYMENT_EVIDENCE_OWNER}; caller-supplied observed_service_sha and deployment references are structural evidence only`, + ); +} From a913c0d231cc1d9ed596a7749822b18c65c7fbd1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 08:06:15 +0900 Subject: [PATCH 266/269] fix(perf): separate deployment identity acceptance gate --- ...employment_separation_acceptance_check.mjs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index 8e594a60b..53229b015 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -1,15 +1,34 @@ import { readFile } from "node:fs/promises"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; +import { requireAuthenticatedDeploymentEvidence } from "./employment_separation_deployment_evidence_gate.mjs"; import { requireAuthenticatedPerformanceEvidence } from "./employment_separation_authenticated_evidence_gate.mjs"; import { validatePinnedK6AcceptanceEvidence } from "./employment_separation_k6_evidence_contract.mjs"; import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; +function requireCommercialOwnerBoundaries() { + const failures = []; + for (const gate of [ + requireAuthenticatedPerformanceEvidence, + requireAuthenticatedDeploymentEvidence, + ]) { + try { + gate(); + } catch (error) { + failures.push(error instanceof Error ? error.message : String(error)); + } + } + if (failures.length !== 0) { + throw new Error(failures.join("\n")); + } +} + async function main() { - // A caller-controlled digest is not an authentication boundary. Keep the - // commercial entry point fail closed until the organization-owned signer and - // verifier tracked by .github#2162 is released and consumed here. - requireAuthenticatedPerformanceEvidence(); + // Byte/provenance attestation and deployed-candidate identity are separate + // trust boundaries. Surface every unresolved owner gap before touching caller + // paths so resolving one authority cannot accidentally enable acceptance while + // the other remains self-asserted. + requireCommercialOwnerBoundaries(); const [resultPath, runtimeEvidencePath, fixturePath] = process.argv.slice(2); if (!resultPath || !runtimeEvidencePath || !fixturePath || process.argv.length !== 5) { From 3e8f44ad5a32cf607fc6a95e6cbfd27cf2235edc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 08:06:32 +0900 Subject: [PATCH 267/269] test(perf): require all commercial evidence authorities --- ...t_separation_commercial_owner_gate.test.mjs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/performance/employment_separation_commercial_owner_gate.test.mjs diff --git a/tests/performance/employment_separation_commercial_owner_gate.test.mjs b/tests/performance/employment_separation_commercial_owner_gate.test.mjs new file mode 100644 index 000000000..cea0ac4bb --- /dev/null +++ b/tests/performance/employment_separation_commercial_owner_gate.test.mjs @@ -0,0 +1,18 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { requireCommercialPerformanceAuthorities } from "./employment_separation_commercial_owner_gate.mjs"; + +const PERFORMANCE_ATTESTATION_GAP_PATTERN = /authenticated performance-evidence attestation.*ContextualWisdomLab\/.github#2162/; +const DEPLOYMENT_IDENTITY_GAP_PATTERN = /authenticated deployed-candidate evidence.*ContextualWisdomLab\/Orgmetra#395/; + +test("reports every unresolved commercial evidence authority in one fail-closed result", () => { + assert.throws( + () => requireCommercialPerformanceAuthorities(), + (error) => { + assert.match(error.message, PERFORMANCE_ATTESTATION_GAP_PATTERN); + assert.match(error.message, DEPLOYMENT_IDENTITY_GAP_PATTERN); + return true; + }, + ); +}); From 2b3e9502333d4295863674f7d3d4b30cdd3b8917 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 08:06:39 +0900 Subject: [PATCH 268/269] fix(perf): compose commercial evidence owner gates --- ...yment_separation_commercial_owner_gate.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/performance/employment_separation_commercial_owner_gate.mjs diff --git a/tests/performance/employment_separation_commercial_owner_gate.mjs b/tests/performance/employment_separation_commercial_owner_gate.mjs new file mode 100644 index 000000000..16d7bbc41 --- /dev/null +++ b/tests/performance/employment_separation_commercial_owner_gate.mjs @@ -0,0 +1,19 @@ +import { requireAuthenticatedDeploymentEvidence } from "./employment_separation_deployment_evidence_gate.mjs"; +import { requireAuthenticatedPerformanceEvidence } from "./employment_separation_authenticated_evidence_gate.mjs"; + +export function requireCommercialPerformanceAuthorities() { + const failures = []; + for (const gate of [ + requireAuthenticatedPerformanceEvidence, + requireAuthenticatedDeploymentEvidence, + ]) { + try { + gate(); + } catch (error) { + failures.push(error instanceof Error ? error.message : String(error)); + } + } + if (failures.length !== 0) { + throw new Error(failures.join("\n")); + } +} From 151a2269ef6fb21cf5984e6ced9f98bb286cf42a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 16 Sep 2026 08:06:47 +0900 Subject: [PATCH 269/269] refactor(perf): centralize commercial owner gates --- ...employment_separation_acceptance_check.mjs | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/tests/performance/employment_separation_acceptance_check.mjs b/tests/performance/employment_separation_acceptance_check.mjs index 53229b015..c68e9c8e1 100644 --- a/tests/performance/employment_separation_acceptance_check.mjs +++ b/tests/performance/employment_separation_acceptance_check.mjs @@ -1,34 +1,16 @@ import { readFile } from "node:fs/promises"; import { validateEmploymentSeparationAcceptance } from "./employment_separation_acceptance_contract.mjs"; -import { requireAuthenticatedDeploymentEvidence } from "./employment_separation_deployment_evidence_gate.mjs"; -import { requireAuthenticatedPerformanceEvidence } from "./employment_separation_authenticated_evidence_gate.mjs"; +import { requireCommercialPerformanceAuthorities } from "./employment_separation_commercial_owner_gate.mjs"; import { validatePinnedK6AcceptanceEvidence } from "./employment_separation_k6_evidence_contract.mjs"; import { parseRuntimeEvidenceArtifact } from "./employment_separation_runtime_evidence_artifact.mjs"; -function requireCommercialOwnerBoundaries() { - const failures = []; - for (const gate of [ - requireAuthenticatedPerformanceEvidence, - requireAuthenticatedDeploymentEvidence, - ]) { - try { - gate(); - } catch (error) { - failures.push(error instanceof Error ? error.message : String(error)); - } - } - if (failures.length !== 0) { - throw new Error(failures.join("\n")); - } -} - async function main() { // Byte/provenance attestation and deployed-candidate identity are separate // trust boundaries. Surface every unresolved owner gap before touching caller // paths so resolving one authority cannot accidentally enable acceptance while // the other remains self-asserted. - requireCommercialOwnerBoundaries(); + requireCommercialPerformanceAuthorities(); const [resultPath, runtimeEvidencePath, fixturePath] = process.argv.slice(2); if (!resultPath || !runtimeEvidencePath || !fixturePath || process.argv.length !== 5) {