feat(design): receipted fetch for OpenAI calls

design/src/receipted-fetch.ts wraps every api.openai.com call: a
content-free egress receipt (sink design-openai, sha256 of the JSON
body — hash only, never the body) is written BEFORE the send. Polarity
is FAIL-OPEN: user-facing generation must not die because an audit log
hiccuped, so a receipt failure warns on stderr and the call proceeds.
Streams pass through untouched (response bodies returned as-is;
non-string request bodies receipted as sha256:null rather than drained
to hash).

All ten call sites converted with per-command payload classes:
generate, variants (injected fetchFn passes through), iterate (both
threaded and fresh paths), evolve (image + screenshot analysis), check,
diff, design-to-code, memory.

Unit-tested with injected fetch: receipt-before-send ordering, stream
passthrough, and fail-open on an unwritable ledger.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit c0e5ff6639414ac2fd98e8ac3affb51401746b55)
This commit is contained in:
Garry Tan
2026-08-12 15:31:48 -07:00
parent a1282c78d4
commit 52288947ec
11 changed files with 218 additions and 11 deletions
+2 -1
View File
@@ -5,6 +5,7 @@
import fs from "fs";
import { requireApiKey } from "./auth";
import { receiptedFetch } from "./receipted-fetch";
export interface CheckResult {
pass: boolean;
@@ -22,7 +23,7 @@ export async function checkMockup(imagePath: string, brief: string): Promise<Che
const timeout = setTimeout(() => controller.abort(), 60_000);
try {
const response = await fetch("https://api.openai.com/v1/chat/completions", {
const response = await receiptedFetch("check-screenshot-request", "https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,