// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 // A delivery's project comes from the record, inside the delivery's organization (adapters/jobs.ts). The record's // workspace and project must exist in that organization before knowledge acts on them; one that names another // workspace's project, or one the organization does not have, is refused by name and nothing is enqueued. import { Container, type EventContext, newId, type OrgScope } from "@conusai-kit/core" import { createMemoryDataSource, DATA_SOURCE, JOB_QUEUE } from "@conusai-kit/data" import { projects, workspaces } from "@conusai-kit/tenancy" import { fakeJobQueue } from "@conusai-kit/testing" import { describe, expect, it } from "vitest" import { KNOWLEDGE_SUBSCRIPTIONS } from "../adapters/jobs.js" import { KNOWLEDGE_ENTITIES, KNOWLEDGE_SCOPE } from "../index.js" async function delivery(archivedAt: string | null = null) { const data = createMemoryDataSource({ entities: [workspaces, projects, ...KNOWLEDGE_ENTITIES] }) const orgId = newId() const org: OrgScope = { level: "org", actor: { userId: newId() }, orgId } const workspace = await data .forScope(org) .of(workspaces) .insert({ slug: "main", name: "Main", isDefault: true, visibility: "org" }) const other = await data .forScope(org) .of(workspaces) .insert({ slug: "other", name: "Other", isDefault: false, visibility: "org" }) const project = await data .forScope({ level: "workspace", actor: org.actor, orgId, workspaceId: workspace.id }) .of(projects) .insert({ slug: "site", name: "Site", moduleKey: "notes", archivedAt }) const queue = fakeJobQueue() const container = new Container() container.value(DATA_SOURCE, data) container.value(JOB_QUEUE, queue) // The relay's delivery: the organization's scope, with a system actor. container.value(KNOWLEDGE_SCOPE, org) const ctx = { container } as unknown as EventContext return { ctx, queue, orgId, workspaceId: workspace.id, otherWorkspaceId: other.id, projectId: project.id } } const indexRequested = KNOWLEDGE_SUBSCRIPTIONS[1] const request = (ids: { orgId: string; workspaceId: string; projectId: string }) => ({ name: "knowledge.DocumentIndexRequested", payload: { ...ids, documentId: newId(), collectionName: "contracts", fileId: newId() }, }) describe("a knowledge delivery acts only in a project of its organization", () => { it("enqueues the job in the record's project when it exists there", async () => { const { ctx, queue, orgId, workspaceId, projectId } = await delivery() await indexRequested?.handler(request({ orgId, workspaceId, projectId }) as never, ctx) expect(queue.of("knowledge.index")).toHaveLength(1) }) it("refuses, by name, a workspace the organization does not have", async () => { const { ctx, queue, orgId, projectId } = await delivery() const workspaceId = newId() await expect(indexRequested?.handler(request({ orgId, workspaceId, projectId }) as never, ctx)).rejects.toThrow( new RegExp(`workspace ${workspaceId}`), ) expect(queue.of("knowledge.index")).toEqual([]) }) it("refuses, by name, a project that is not in the record's workspace", async () => { const { ctx, queue, orgId, otherWorkspaceId, projectId } = await delivery() await expect( indexRequested?.handler(request({ orgId, workspaceId: otherWorkspaceId, projectId }) as never, ctx), ).rejects.toThrow(new RegExp(`project ${projectId}`)) expect(queue.of("knowledge.index")).toEqual([]) }) it("acts on a record of an archived project: an archive hides a project and does not end its work", async () => { // The kit's one rule (kit-tenancy suspension.ts): an archived project refuses a person's write, not work with // no person behind it. A deleted file's text must still leave the index, and an index request a member made // before the archive still completes. const { ctx, queue, orgId, workspaceId, projectId } = await delivery(new Date("2026-11-09T00:00:00Z").toISOString()) await indexRequested?.handler(request({ orgId, workspaceId, projectId }) as never, ctx) expect(queue.of("knowledge.index")).toHaveLength(1) }) })