perf: batch retained-reader authorization reads (#16424)

Batch retained-reader project checks through the existing multi-actor read API. Share raw database reads within one call, retain actor-specific privacy and supplied membership data, and avoid loading large saved-run payloads for identity checks.

Keep current-reader writes, distinct saved-run policies, company root fences and later-call revocation checks. Add query-count and access-control regressions. All 255 affected cases and full repository typecheck/build pass. Hosted response-time acceptance remains separate.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip authored and GitHub committed 2026-10-15 07:33:03 -05:00
1 parent 7f9d3d1929
commit ea4aa185b0
4 files changed
+186 -10

No files matched your search

+4 -2
View File
@@ -755,7 +755,8 @@ function createAuthorizationService(db: Db | DbTransaction, readSnapshot?: ReadA
async function decideReadsForActors(actors: AuthorizationActor[], resources: ReadAuthorizationResource[]): Promise<AuthorizationDecision[][]> {
if (!actors.length) return [];
const snapshots: ReadAuthorizationSnapshot[] = actors.map(() => ({ issues: new Map(), projects: new Map(), memo: new Map() }));
const memo = new Map<string, Promise<unknown>>();
const snapshots: ReadAuthorizationSnapshot[] = actors.map(() => ({ issues: new Map(), projects: new Map(), memo }));
const batchActors: ResponsibleUserActorWithMemo[] = actors.map(actor => ({ ...actor, __responsibleUserSnapshotMemo: undefined }));
const privacyKey = (actor: AuthorizationActor) => JSON.stringify([actor.type, actor.agentId, actor.userId, actor.onBehalfOfUserId]);
const privacyActors = [...new Map(batchActors.map(actor => [privacyKey(actor), actor])).values()];
@@ -892,7 +893,8 @@ function createAuthorizationService(db: Db | DbTransaction, readSnapshot?: ReadA
return promise;
}
const promise = loadResponsibleUserSnapshot(input.companyId, input.userId);
const promise = batchRead(`responsible:${input.companyId}:${input.userId}`,
() => loadResponsibleUserSnapshot(input.companyId, input.userId));
actorWithMemo.__responsibleUserSnapshotMemo.set(key, promise);
void promise.catch(() => {
if (actorWithMemo.__responsibleUserSnapshotMemo?.get(key) === promise) {
@@ -29,6 +29,11 @@ type DbTransaction = Parameters<Parameters<Db["transaction"]>[0]>[0];
const controllerAcquisitionMessage = "New controller repository acquisition requires a trusted task. Existing verified public checkouts remain available.";
const lowTrustRepositoryMessage = "Low-trust repository reuse permits anonymous public URLs only; new acquisition is unavailable. Use an authorized configured source for private repositories.";
const rootReaderRunColumns = {
id: heartbeatRuns.id, companyId: heartbeatRuns.companyId, agentId: heartbeatRuns.agentId,
responsibleUserId: heartbeatRuns.responsibleUserId, nativeIssueId: heartbeatRuns.nativeIssueId, issueId: heartbeatRuns.issueId,
contextSnapshot: sql<Record<string, unknown>>`jsonb_build_object('issueId', ${heartbeatRuns.contextSnapshot}->'issueId', 'taskId', ${heartbeatRuns.contextSnapshot}->'taskId', 'executionPolicy', ${heartbeatRuns.contextSnapshot}->'executionPolicy')`,
};
function resolveAcquisitionSource(request: PrepareWorkspaceRepository["repository"], available: ProjectRepository[], anonymousOnly: boolean) {
if (anonymousOnly && request.kind === "catalog") throw forbidden(lowTrustRepositoryMessage);
@@ -180,8 +185,17 @@ async function assertRootProjectAccess(db: Db | DbTransaction, actor: Authorizat
}
}
async function assertRootProjectsReadAccessForActors(db: Db | DbTransaction, actors: AuthorizationActor[], companyId: string, projectIds: Set<string>) {
if (!actors.length || !projectIds.size) return;
const decisions = await authorizationService(db).decideReadsForActors(actors,
[...projectIds].map(projectId => ({ type: "project" as const, companyId, projectId })));
if (decisions.some(batch => batch.some(decision => !decision.allowed))) {
throw forbidden("Workspace source project is no longer accessible");
}
}
async function retainedRootReader(tx: DbTransaction, companyId: string, reader: Pick<typeof executionWorkspaceRepositoryAccess.$inferSelect, "scopeId" | "issueId" | "agentId" | "responsibleUserId">) {
const [run] = await tx.select().from(heartbeatRuns).where(and(eq(heartbeatRuns.id, reader.scopeId), eq(heartbeatRuns.companyId, companyId)));
const [run] = await tx.select(rootReaderRunColumns).from(heartbeatRuns).where(and(eq(heartbeatRuns.id, reader.scopeId), eq(heartbeatRuns.companyId, companyId)));
const [agent] = reader.agentId ? await tx.select({ id: agents.id }).from(agents).where(and(eq(agents.id, reader.agentId), eq(agents.companyId, companyId))) : [];
const [issue] = reader.issueId ? await tx.select().from(issues).where(and(eq(issues.id, reader.issueId), eq(issues.companyId, companyId))) : [];
if (!run || !agent || !issue || run.agentId !== reader.agentId || run.responsibleUserId !== reader.responsibleUserId
@@ -260,8 +274,8 @@ async function retainGitMetadataOwners(tx: DbTransaction, input: {
for (const reader of closure.overlappingEntries.filter(entry => entry.kind === "reader")) {
const { actor } = await retainedRootReader(tx, input.companyId, reader);
readerActors.push(actor);
await assertRootProjectAccess(tx, actor, input.companyId, projectIds);
}
await assertRootProjectsReadAccessForActors(tx, readerActors, input.companyId, projectIds);
await assertTaskWorkspacesReadAccessForActors(tx, readerActors, input.companyId, workspaceIds);
for (const [kind, ids] of [["source", workspaceIds], ["project_source", projectIds]] as const) {
for (const scopeId of ids) if (!closure.entries.some(entry => entry.kind === kind && entry.scopeId === scopeId)) {
@@ -356,8 +370,8 @@ export async function retainIsolatedWorkspaceSourceAccess(db: Db, input: {
const { actor, issue } = await retainedRootReader(tx, input.companyId, reader);
readerActors.push(actor);
await assertRootProjectTrust(tx, { companyId: input.companyId, actor, issueId: issue.id, projectIds: target.sourceProjectIds });
await assertRootProjectAccess(tx, actor, input.companyId, target.sourceProjectIds);
}
await assertRootProjectsReadAccessForActors(tx, readerActors, input.companyId, target.sourceProjectIds);
await assertTaskWorkspacesReadAccessForActors(tx, readerActors, input.companyId, target.sourceIds);
} catch (error) { failure ??= error; }
if (!failure && verifiedCopyProjectIds) {
@@ -385,7 +399,7 @@ async function assertRootProjectTrust(db: Db | DbTransaction, input: {
if (!restricted.length) return;
const incompatible = () => forbidden("Physical workspace source trust is incompatible with the task's execution policy");
const runId = input.actor.runId;
const [run] = runId ? await db.select().from(heartbeatRuns).where(and(eq(heartbeatRuns.id, runId), eq(heartbeatRuns.companyId, input.companyId))) : [];
const [run] = runId ? await db.select(rootReaderRunColumns).from(heartbeatRuns).where(and(eq(heartbeatRuns.id, runId), eq(heartbeatRuns.companyId, input.companyId))) : [];
const creation = !input.issueId && input.actor.type === "agent" && runId ? input.taskCreation : undefined;
const runIssueId = run?.nativeIssueId ?? run?.contextSnapshot?.issueId ?? run?.contextSnapshot?.taskId ?? run?.issueId;
const issueId = input.issueId ?? (creation && typeof runIssueId === "string" ? runIssueId : null);
@@ -471,7 +485,7 @@ export function executionWorkspaceRepositoryService(db: Db) {
const [project] = issue.projectId ? await reader.select().from(projects).where(and(eq(projects.id, issue.projectId), eq(projects.companyId, issue.companyId))) : [];
const [workspaceSourceProject] = workspace?.projectId ? await reader.select().from(projects).where(and(eq(projects.id, workspace.projectId), eq(projects.companyId, issue.companyId))) : [];
const runId = input.runId ?? issue.executionRunId;
const [run] = runId ? await reader.select().from(heartbeatRuns).where(and(eq(heartbeatRuns.id, runId), eq(heartbeatRuns.companyId, issue.companyId))) : [];
const [run] = runId ? await reader.select(rootReaderRunColumns).from(heartbeatRuns).where(and(eq(heartbeatRuns.id, runId), eq(heartbeatRuns.companyId, issue.companyId))) : [];
if (runId && (!run || (input.runId && run.agentId !== agentId) || (run.nativeIssueId ?? run.contextSnapshot?.issueId ?? run.contextSnapshot?.taskId ?? run.issueId) !== issue.id)) {
throw forbidden("Task repository run identity is unavailable");
}
@@ -545,12 +559,14 @@ export function executionWorkspaceRepositoryService(db: Db) {
const sourceProjects = sourceIds.size ? await tx.selectDistinct({ projectId: executionWorkspaces.projectId }).from(executionWorkspaces).where(and(
eq(executionWorkspaces.companyId, input.companyId), inArray(executionWorkspaces.id, [...sourceIds]))) : [];
const sourceActors: AuthorizationActor[] = [];
const projectReaders: AuthorizationActor[] = [];
for (const reader of readers) {
const { actor, issue } = await retainedRootReader(tx, input.companyId, reader);
await assertRootProjectTrust(tx, { companyId: input.companyId, projectIds: sourceProjectIds, actor, issueId: issue.id,
sourceWorkspaceId: input.reader?.runId === reader.scopeId ? input.sourceWorkspaceId : undefined });
await assertRootProjectAccess(tx, actor, input.companyId, sourceProjectIds,
input.reader?.runId === reader.scopeId ? { sharedProjectIds, issueId: issue.id } : undefined);
if (input.reader?.runId === reader.scopeId) {
await assertRootProjectAccess(tx, actor, input.companyId, sourceProjectIds, { sharedProjectIds, issueId: issue.id });
} else projectReaders.push(actor);
if (ownAdmissionOnly) {
const [ownSource] = await tx.select({ id: executionWorkspaces.id }).from(executionWorkspaces).where(and(
eq(executionWorkspaces.companyId, input.companyId), eq(executionWorkspaces.id, input.sourceWorkspaceId!),
@@ -566,6 +582,7 @@ export function executionWorkspaceRepositoryService(db: Db) {
}
}
}
await assertRootProjectsReadAccessForActors(tx, projectReaders, input.companyId, sourceProjectIds);
if (input.actor) {
if (!input.issueId) throw forbidden("Workspace write authorization requires a task");
await assertRootProjectTrust(tx, { ...input, projectIds: sourceProjectIds, actor: input.actor });
@@ -676,7 +693,7 @@ export function executionWorkspaceRepositoryService(db: Db) {
throw forbidden("Task repository publication binding is unavailable");
}
await requiresAnonymousAcquisition(tx, { issue, workspace, agentId: input.agentId, runId: input.runId });
const [run] = await tx.select().from(heartbeatRuns).where(and(eq(heartbeatRuns.id, input.runId), eq(heartbeatRuns.companyId, input.companyId)));
const [run] = await tx.select({ responsibleUserId: heartbeatRuns.responsibleUserId }).from(heartbeatRuns).where(and(eq(heartbeatRuns.id, input.runId), eq(heartbeatRuns.companyId, input.companyId)));
const { actor } = await retainedRootReader(tx, input.companyId, {
scopeId: input.runId, issueId: input.issueId, agentId: input.agentId, responsibleUserId: run?.responsibleUserId ?? null,
});