import { env } from "cloudflare:workers";
import { z } from "zod";
import { loadRepoById } from "../repos";
import { ZERO_SHA } from "../git/store";
import { MAX_COMMITS_PER_FETCH } from "../git/upload-pack";
import { processSarifUpload } from "./code-scanning";
import { scanDependencies } from "./dependencies";
import { scanPushForSecrets } from "./secret-scan";
import { verifyCommits } from "./signatures";
export const SECURITY_QUEUE = "gitfor-security";
const RETRY_SECONDS = 30;
const MAX_PUSH_SIGNATURES = 50;
const sha = z.string().regex(/^[0-9a-f]{40}$/);
const securityMessage = z.discriminatedUnion("kind", [
z.object({ kind: z.literal("secrets.push"), repoId: z.string(), ref: z.string(), before: z.string(), after: sha }),
z.object({ kind: z.literal("deps.scan"), repoId: z.string(), sha }),
z.object({
kind: z.literal("signatures.verify"),
repoId: z.string(),
shas: z.array(sha).max(MAX_COMMITS_PER_FETCH),
}),
z.object({ kind: z.literal("sarif.process"), repoId: z.string(), uploadId: z.string() }),
]);
export type SecurityMessage = z.infer<typeof securityMessage>;
export async function enqueueSecurity(messages: SecurityMessage[]): Promise<void> {
if (messages.length === 0) return;
await env.SECURITY_QUEUE.sendBatch(messages.map((body) => ({ body })));
}
const MANIFEST_HINT =
/(^|\/)(package(-lock)?\.json|npm-shrinkwrap\.json|bun\.lock|yarn\.lock|pnpm-lock\.yaml|requirements(-dev)?\.txt|pyproject\.toml|Pipfile\.lock|go\.mod|Cargo\.(toml|lock)|Gemfile\.lock|composer\.(json|lock))$/;
/** Fans a landed push out to bounded, retryable security jobs on the security queue. */
export async function queuePushSecurity(push: {
repoId: string;
ref: string;