import { waitUntil } from "cloudflare:workers";
import { all, batch, stmt } from "./db";
import { adjustOpenCounter } from "./issue-counters";
import { repoDb } from "./scoped-db";
import { pullBaseRepoIds } from "./pull-scope";
import { loadUserById, toViewer } from "./auth";
import { pullHeadAccessible } from "./git/bridge-policy";
import { dropHiddenRefsForRepo, dropPullRefsForIssue, requestHiddenRefCleanup } from "./git/pull-bridge";
import { CAPS } from "./limits";
import { addIssueEvent } from "./pulls";
import type { PullRow } from "./pulls";
import { hasPermission, loadRepoById, repoPermission } from "./repos";
import type { RepoRow, Viewer } from "~/lib/types";
import { issuesChanged } from "./repo-state";
type GuardedPull = Pick<PullRow, "issue_id" | "repo_id" | "head_repo_id" | "author_id" | "state">;
/** Closes a pull request because its author can no longer read one of its repositories. */
async function closeForRevokedAccess(pull: GuardedPull): Promise<void> {
const now = Date.now();
const closed = await repoDb(pull.repo_id).run(
"UPDATE issues SET state = 'closed', closed_at = ?, closed_by = NULL, updated_at = ? WHERE id = ? AND state = 'open'",
now,
now,
pull.issue_id,
);
if (closed.meta.changes > 0) {
await adjustOpenCounter({ id: pull.issue_id, repo_id: pull.repo_id, is_pull: 1 }, -1);
}
issuesChanged(pull.repo_id, [pull.issue_id]);
await addIssueEvent(pull, null, "closed", { reason: "access_revoked" });
waitUntil(dropPullRefsForIssue(pull.repo_id, pull.issue_id));
}
/**
* Whether a fork pull request may still synchronize, bridge or run CI: the author must currently read
* both repositories and the head must be a live fork of the base. When that stopped being true the pull
* request is closed and its hidden refs dropped, so revoked readers stop receiving (and feeding) history.
*/
export async function ensurePullHeadAccessible(pull: GuardedPull): Promise<boolean> {