import { env } from "cloudflare:workers";
import { first, run } from "../db";
import { repoDb, stmt } from "../scoped-db";
import { forgetLocator, locate, registerLocator } from "../scoped-db/locators";
import { randomToken, sha256Hex } from "../crypto";
import { credentialFromRequest } from "../auth";
import { publicUrl } from "../events/emit";
import { allows, restrictPermissions } from "./permissions";
import type { TokenPermissions } from "./permissions";
import { isUntrustedRun } from "./jobs";
import type { JobExecution } from "./jobs";
import type { Permission } from "~/lib/types";
export const JOB_TOKEN_PREFIX = "gitfor_job";
const TOKEN_GRACE_MS = 10 * 60 * 1000;
export const JOB_TOKEN_MARKER_TTL_MS = 24 * 60 * 60 * 1000;
export type JobTokenRow = {
token_hash: string;
job_id: string;
repo_id: string;
permissions: string;
expires_at: number;
};
export type JobTokenAccess = { jobId: string; repoId: string; permissions: TokenPermissions };
/** Mints the job's `GITHUB_TOKEN` equivalent; it is revoked when the job completes and expires after its timeout. */
export async function mintJobToken(execution: JobExecution): Promise<string> {
const token = randomToken(JOB_TOKEN_PREFIX);
const forked = isUntrustedRun(execution);
const permissions = forked ? restrictPermissions(execution.spec.permissions) : execution.spec.permissions;
const hash = await sha256Hex(token);
await repoDb(execution.repo.id).run(
"INSERT INTO job_tokens (token_hash, job_id, repo_id, permissions, expires_at) VALUES (?, ?, ?, ?, ?)",
hash,
execution.job.id,
execution.repo.id,
JSON.stringify(permissions),
Date.now() + execution.spec.timeoutMinutes * 60 * 1000 + TOKEN_GRACE_MS,