v1.87.0.0 feat: add verified CSO audits and replayable repair bundles (#2852)

* feat(cso): add verified audits and replayable repair bundles

* fix(cso): harden qualification and setup boundaries

* fix(cso): assemble security canaries at runtime

* fix(cso): bound release proof and maintenance work

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): require complete evaluation reports

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): replay expired snapshots from supplied source

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test(cso): synchronize DNS cancellation assertion

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore(ship): exempt repository owner from liveness proof

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* test(cso): make recheck retention overlap deterministic

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore: bump version and changelog (v1.85.0.0)

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): pass native release gates

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore: move release to v1.86.0.0

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): resolve rechecks by finding

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* chore: move release to v1.87.0.0

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): pass macOS and Windows release gates

Normalize BSD wc output, compare Windows paths by filesystem identity, preserve portable snapshot race coverage, and narrow POSIX-only Windows fixtures.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(cso): harden native verification gates

* fix(cso): refine Windows native diagnostics

* test(cso): isolate Windows Git startup failure

* test(cso): stabilize Windows native diagnostics

* fix(cso): support hardened Git on Windows

* fix(cso): close final verification gaps

* test(cso): bound cold Docker fixture setup

* fix(cso): restore cross-platform free-suite gates

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
This commit is contained in:
Garry Tan
2026-09-14 15:14:58 -07:00
committed by GitHub
co-authored by OpenAI Codex
parent 9f81911136
commit 4a3c6a8a3c
160 changed files with 24697 additions and 2288 deletions
+148
View File
@@ -0,0 +1,148 @@
import { createHash } from 'node:crypto';
export type ProducerHost = 'claude' | 'codex' | 'gemini';
export type ProducerVersion = 'v2' | 'v3';
export type ProducerMode = 'daily' | 'comprehensive';
export type ProducerStack = 'node' | 'bun' | 'python' | 'rails';
export type ProducerVariant = 'vulnerable' | 'fixed';
export interface ProducerCell {
id: string;
caseId: string;
stack: ProducerStack;
variant: ProducerVariant;
version: ProducerVersion;
mode: ProducerMode;
repetition: 1 | 2 | 3;
model: string;
host: ProducerHost;
budgetSeconds: number;
sourceHash: string;
skillHash: string;
}
export interface ProducerSourceEntry {
path: string;
sha256: string;
bytes: number;
}
/**
* This control file is consumed before a producing agent starts. It must never
* be placed inside the application repository or retained on the producer.
*/
export interface ProducerInput {
schemaVersion: 1;
cell: ProducerCell;
/** Exact canonical portable payload: root SKILL.md plus its manifest-listed sections. */
skill: string;
source: ProducerSourceEntry[];
}
export interface ProducerArtifactIdentity {
sha256: string;
bytes: number;
}
export interface ProducerInstallationIdentity {
schemaVersion: 1;
producer: ProducerArtifactIdentity;
launcher: ProducerArtifactIdentity;
core: ProducerArtifactIdentity;
watchdog: ProducerArtifactIdentity;
/** The adjacent manifest is exactly `<coreSha256>\n`; bind both its bytes and declaration. */
generation: {
coreSha256: string;
manifest: ProducerArtifactIdentity;
};
embeddedCatalogs: {
runtimeRevision: string;
runtimeBuildRevision: string;
runtimeSha256: string;
scannerRevision: string;
scannerSha256: string;
};
identityHash: string;
}
export interface ProducerProviderIdentity {
schemaVersion: 1;
family: 'claude' | 'gpt' | 'gemini';
policyRevision: string;
executable: ProducerArtifactIdentity;
argsPrefix: string[];
version: string;
identityHash: string;
}
export interface ProducerArtifactInventory {
schemaVersion: 1;
root: 'security/cso';
/** Sorted safe paths relative to root within the retained helper home. */
entries: ProducerSourceEntry[];
totalBytes: number;
identityHash: string;
}
export interface ProducerReceipt {
schemaVersion: 1;
cell: ProducerCell;
inputHash: string;
installationIdentity: ProducerInstallationIdentity;
providerIdentity: ProducerProviderIdentity;
artifacts: ProducerArtifactInventory;
startedAt: string;
finishedAt: string;
status: 'succeeded' | 'failed';
requestedModel: string;
modelUsed: string;
/** Provider-reported when it differs; otherwise the exact CLI model pin. */
modelIdentitySource: 'provider_reported' | 'requested_pin';
durationMs: number;
firstUsefulResultMs: null;
toolCalls: number;
output: string;
outputHash: string;
usage: {
/** CLI/provider-reported tokens. Null means the adapter did not report usage. */
inputTokens: number | null;
outputTokens: number | null;
cachedTokens: number | null;
/** Pricing-table estimate, not a host-billed amount. */
estimatedCostUSD: number | null;
};
error?: { code: string; reason: string };
receiptHash: string;
}
/** Compact trusted index; raw output remains in the separately retained receipt. */
export type ProducerReceiptIndex = Omit<ProducerReceipt, 'output' | 'error'> & {
error?: { code: string };
};
export const sha256 = (value: string | Buffer): string => createHash('sha256').update(value).digest('hex');
export function producerInputHash(input: ProducerInput): string {
return sha256(JSON.stringify(input));
}
export function producerReceiptHash(receipt: Omit<ProducerReceipt, 'receiptHash'>): string {
return sha256(JSON.stringify(receipt));
}
export function producerInstallationIdentityHash(identity: Omit<ProducerInstallationIdentity, 'identityHash'>): string {
if (!identity.generation || !identity.generation.manifest || identity.generation.coreSha256 !== identity.core.sha256 ||
identity.generation.manifest.bytes !== 65 ||
identity.generation.manifest.sha256 !== sha256(`${identity.generation.coreSha256}\n`)) {
throw new Error('INVALID_PRODUCER_GENERATION_IDENTITY');
}
return sha256(JSON.stringify(identity));
}
export function producerProviderIdentityHash(identity: Omit<ProducerProviderIdentity, 'identityHash'>): string {
return sha256(JSON.stringify(identity));
}
export function producerArtifactInventoryHash(inventory: Omit<ProducerArtifactInventory, 'identityHash'>): string {
return sha256(JSON.stringify(inventory));
}