Files
shockbot/entryPost.ts
T
David Blass d3b5340583 fix: audit batch — MCP timeouts, entryPost, vip_audit 404s, and 6 more (#824)
* fix: 9 unaddressed log-audit / run-audit findings

Co-authored-by: Cursor <cursoragent@cursor.com>

#815 entryPost stdlib-only imports; #823 MCP timeoutMs on checkout_pr/shell;
#816 FREE_FALLBACK → opencode/big-pickle; #822 chunk GraphQL nodes ≤100;
#817/#821 vip_audit 404 skip paths; #813 longer serializable retries;
#818 run-context handler-entered log; #805 audit severity template.

* fix: update footer test for big-pickle fallback slug

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: anneal round 1 — ghaCore getState casing, post-hook timeout

Match @actions/core STATE_ key semantics (no uppercasing), cap
postApiFetch at 30s, trim serializable retries to stay under GitHub's
10s webhook window, log Clerk failures in getUserTokenByGithubLogin.

Co-authored-by: Cursor <cursoragent@cursor.com>

* revert: drop run-context handler log (#818 deferred)

The #692 client-side fix is already on main; residual SyntaxError hits
are old action pins. Per-request log added noise without fixing anything.

Co-authored-by: Cursor <cursoragent@cursor.com>

* document per-issue Closes syntax for audit PRs

GitHub only auto-closes the first issue when numbers are comma-separated;
/audits and AGENTS.md now require Closes before each issue number.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: anneal round 2 — outreach privacy, alert resilience, vertex cleanup

Filter private repos from VIP authority output, harden console alert
lines against DB failures, drop spoofable changesets body check, and
unset GOOGLE_APPLICATION_CREDENTIALS after vertex credential cleanup.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor: drop codexHome re-export of detectCodexRefresh

Import detectCodexRefresh directly from codexRefreshDetect.ts everywhere;
rename the unit test file to match. codexHome.ts stays install-only.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: drop deprecated minimax-m2.5-free; add paid minimax-m2.5

Remove the deprecated free MiniMax promo from the catalog, docs, and
tests. BYOK fallback and picker copy stay on opencode/big-pickle. Add
opencode/minimax-m2.5 and openrouter/minimax-m2.5 for Zen BYOK and
Router. Pin #816 regressions with freeFallbackCatalog and runErrorRenderer
unit tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: hidden minimax-m2.5-free fallback for stored slugs

Re-add opencode/minimax-m2.5-free as a hidden fallback alias to big-pickle
so repos with the legacy slug still resolve as free. Drop live Zen API
experiment tests in freeFallbackCatalog.test.ts.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 16:48:25 +00:00

101 lines
3.8 KiB
JavaScript

#!/usr/bin/env node
//
// GitHub Actions `post:` entry point. Runs after the main step regardless of
// exit status (cancellation, timeout, unhandled error) — that's the contract
// we need for credential persistence: if OpenCode refreshed the Codex
// auth.json during the run, the refreshed token must land back in Pullfrog
// even when the main step died unexpectedly.
//
// THIS IS WHY `CODEX_AUTH_JSON` HAS TO LIVE IN PULLFROG'S OWN SECRET STORE,
// NOT IN GITHUB ACTIONS SECRETS. The refresh chain rotates on every use; this
// hook PUTs the rotated chain back to Pullfrog Postgres so the next run starts
// from a fresh token. GH Actions secrets are read-only at runtime — there is
// no API to write them back from inside a job — so a token stashed there
// silently goes stale on the first refresh and the next run fails. See
// wiki/codex-auth.md.
//
// Today's only job: detect a Codex auth refresh by diffing the on-disk
// auth.json against the original refresh token (saved to GH Actions state
// by action/agents/opencode_v2.ts — see also the legacy v1 file kept as
// reference at action/agents/opencode.ts), convert OpenCode's auth shape
// back to Codex CLI shape, and PUT it to /api/runtime/secret.
//
// Silent no-op when the main step didn't materialize Codex auth (no state
// saved). Best-effort: failures are logged but never throw — the workflow
// is already done, and a missed refresh write-back means the user re-runs
// `pullfrog auth codex` next time the chain breaks.
//
// Imports here MUST stay stdlib-only — GHA runs this file directly from the
// checked-out action repo, which has no node_modules for sha-pinned consumers.
import { existsSync, readFileSync } from "node:fs";
import { detectCodexRefresh } from "./utils/codexRefreshDetect.ts";
import * as core from "./utils/ghaCore.ts";
import { postApiFetch } from "./utils/postApiFetch.ts";
async function main(): Promise<void> {
const raw = core.getState("codex_writeback");
if (!raw) {
core.info("codex post-hook: no writeback state — skipping");
return;
}
let state: { apiToken: string; authPath: string; originalRefresh: string };
try {
state = JSON.parse(raw) as typeof state;
} catch (err) {
core.warning(`codex post-hook: malformed writeback state — ${err}`);
return;
}
if (!state.apiToken || !state.authPath || !state.originalRefresh) {
core.warning("codex post-hook: incomplete writeback state — skipping");
return;
}
if (!existsSync(state.authPath)) {
core.info(`codex post-hook: ${state.authPath} not found — nothing to write back`);
return;
}
let authFileContent: string;
try {
authFileContent = readFileSync(state.authPath, "utf8");
} catch (err) {
core.warning(`codex post-hook: cannot read ${state.authPath}${err}`);
return;
}
const refreshedCodexJson = detectCodexRefresh({
authFileContent,
originalRefresh: state.originalRefresh,
});
if (!refreshedCodexJson) {
core.info("codex post-hook: refresh chain unchanged — no writeback needed");
return;
}
try {
const response = await postApiFetch({
path: "/api/runtime/secret",
method: "PUT",
headers: {
authorization: `Bearer ${state.apiToken}`,
"content-type": "application/json",
},
body: JSON.stringify({ name: "CODEX_AUTH_JSON", value: refreshedCodexJson }),
});
if (!response.ok) {
const body = await response.text().catch(() => "");
core.warning(`codex post-hook: writeback returned ${response.status}: ${body}`);
return;
}
core.info("codex post-hook: refreshed CODEX_AUTH_JSON persisted to Pullfrog");
} catch (err) {
core.warning(`codex post-hook: writeback failed — ${err}`);
}
}
main().catch((err) => {
core.warning(`codex post-hook: unexpected error — ${err}`);
});