diff --git a/knowledge-fs/packages/api/src/durable-deletion-handlers.test.ts b/knowledge-fs/packages/api/src/durable-deletion-handlers.test.ts index a1821df29e3..1ec40c524a4 100644 --- a/knowledge-fs/packages/api/src/durable-deletion-handlers.test.ts +++ b/knowledge-fs/packages/api/src/durable-deletion-handlers.test.ts @@ -13,6 +13,7 @@ const SPACE_ID = "018f0d60-7a49-7cc2-9c1b-5b36f18f2c42"; const SOURCE_ID = "018f0d60-7a49-7cc2-9c1b-5b36f18f2c43"; const DOCUMENT_ID = "018f0d60-7a49-7cc2-9c1b-5b36f18f2c44"; const JOB_ID = "018f0d60-7a49-7cc2-9c1b-5b36f18f2c45"; +const CAPABILITY_GRANT_ID = "018f0d60-7a49-7cc2-9c1b-5b36f18f2c46"; const NOW = "2026-07-14T12:00:00.000Z"; describe("durable deletion handlers", () => { @@ -116,6 +117,7 @@ describe("durable deletion handlers", () => { ); expect(service.requestDocumentDeletion).not.toHaveBeenCalled(); await expect(bulkOperations.get({ id: JOB_ID, tenantId: "tenant-1" })).resolves.toMatchObject({ + capabilityGrantId: CAPABILITY_GRANT_ID, items: [expect.objectContaining({ deletionJobId: JOB_ID, documentId: DOCUMENT_ID })], type: "document_delete", }); @@ -145,6 +147,7 @@ describe("durable deletion handlers", () => { }), ); await expect(bulkOperations.get({ id: JOB_ID, tenantId: "tenant-1" })).resolves.toMatchObject({ + capabilityGrantId: CAPABILITY_GRANT_ID, items: [expect.objectContaining({ deletionJobId: JOB_ID, documentId: DOCUMENT_ID })], type: "document_delete", }); @@ -204,6 +207,12 @@ function testApp( const app = createKnowledgeGatewayApp(); app.use("*", async (context, next) => { context.set("callerKind", callerKind); + if (callerKind === "interactive") { + context.set("capabilityV2Grant", { + contentScopeIds: [], + grantId: CAPABILITY_GRANT_ID, + } as never); + } context.set("subject", { scopes: ["knowledge-spaces:read", "knowledge-spaces:write"], subjectId: "owner-1", diff --git a/knowledge-fs/packages/api/src/durable-deletion-handlers.ts b/knowledge-fs/packages/api/src/durable-deletion-handlers.ts index f4b4d7cd387..16be7c1b144 100644 --- a/knowledge-fs/packages/api/src/durable-deletion-handlers.ts +++ b/knowledge-fs/packages/api/src/durable-deletion-handlers.ts @@ -194,6 +194,7 @@ export function registerDurableDeletionHandlers({ knowledgeSpaceId: params.id, requestedBySubjectId: subject.subjectId, tenantId: subject.tenantId, + ...(principal.capability ? { capabilityGrantId: principal.capability.grantId } : {}), }); context.header("Location", `/knowledge-spaces/${params.id}/background-tasks`); return context.json(accepted, 202); @@ -238,8 +239,9 @@ export function registerDurableDeletionHandlers({ const body = context.req.valid("json") as DeleteLogicalDocumentBody; const headers = context.req.valid("header") as DurableDeletionIdempotencyHeaders; try { + const principal = deletionPrincipal(context); const accepted = await service.requestLogicalDocumentDeletion({ - ...deletionPrincipal(context), + ...principal, documentId: params.documentId, expectedRevision: body.expectedRevision, idempotencyKey: headers["idempotency-key"], @@ -253,6 +255,7 @@ export function registerDurableDeletionHandlers({ knowledgeSpaceId: params.id, requestedBySubjectId: subject.subjectId, tenantId: subject.tenantId, + ...(principal.capability ? { capabilityGrantId: principal.capability.grantId } : {}), }); context.header("Location", accepted.statusUrl); return context.json(accepted, 202); @@ -301,6 +304,7 @@ export function registerDurableDeletionHandlers({ } async function ensureLogicalDeletionBackgroundTask(input: { + readonly capabilityGrantId?: string | undefined; readonly bulkOperations: BulkOperationRepository; readonly id: string; readonly items: readonly { @@ -315,6 +319,7 @@ async function ensureLogicalDeletionBackgroundTask(input: { const existing = await input.bulkOperations.get({ id: input.id, tenantId: input.tenantId }); if (existing) return; await input.bulkOperations.create({ + ...(input.capabilityGrantId ? { capabilityGrantId: input.capabilityGrantId } : {}), id: input.id, items: input.items.map((item) => ({ ...item, status: "queued" as const })), knowledgeSpaceId: input.knowledgeSpaceId,