// Every knowledge procedure a page calls, run as the kernel runs it: `createCaller` hands a handler the // container of its kind, and that container refuses a port above the kind. `knowledge.status` backs the // knowledge page and `knowledge.settings.get` the organization's settings page, so a handler that reaches // for an effect port from a read is a 500 `kind_violation` on those pages on every real stack. The ports // stay effects: what changes is what each handler asks for. import { Container, type ProcedureKind, type TenantScope } from "@conusai-kit/core" import { createMemoryDataSource, DATA_SOURCE, OBJECT_STORE } from "@conusai-kit/data" import { files } from "@conusai-kit/files" import { fakeObjectStore } from "@conusai-kit/testing" import { describe, expect, it, vi } from "vitest" import { knowledgeStatusImpl, settingsDisableDocumentAiImpl, settingsEnableDocumentAiImpl, settingsGetImpl, } from "../adapters/procedures.js" import { platformKnowledgeReadiness } from "../adapters/readiness.js" import { KNOWLEDGE_ENTITIES } from "../contract/index.js" import { type DocumentAiPlatform, KNOWLEDGE_ENABLEMENT, KNOWLEDGE_READINESS, KNOWLEDGE_SEARCH, type KnowledgeScope, } from "../core/ports.js" const scope: TenantScope & KnowledgeScope = { level: "project", actor: { userId: "01900000-0000-7000-0000-000000000009" }, orgId: "01900000-0000-7000-0000-000000000001", workspaceId: "01900000-0000-7000-0000-000000000002", projectId: "01900000-0000-7000-0000-000000000003", } const projectInput = { org: "acme", workspace: "general", project: "demo" } const orgInput = { org: "acme" } const processContainer = () => { const container = new Container() container.value(DATA_SOURCE, createMemoryDataSource({ entities: [...KNOWLEDGE_ENTITIES, files] })) container.value(OBJECT_STORE, fakeObjectStore()) return container } /** A handler as the kernel calls it (`createCaller`): with the container of its procedure's kind. */ const run = ( impl: { readonly kind: ProcedureKind; readonly handler: (call: never) => unknown }, input: unknown, container: Container, ) => impl.handler({ input, ctx: { container: container.restrict(impl.kind), scope } } as never) const neverBuilt = () => vi.fn((): never => { throw new Error("a port above this procedure's kind was built") }) const platform: DocumentAiPlatform = { checkEligibility: async () => ({ ok: true }), indexingQuota: async () => 1000, } describe("the ports that leave the process", () => { it("stay refused to a read and a write", () => { const container = processContainer() container.value(KNOWLEDGE_ENABLEMENT, platform) container.register(KNOWLEDGE_SEARCH, neverBuilt()) for (const kind of ["read", "write"] as const) { expect(() => container.restrict(kind).resolve(KNOWLEDGE_SEARCH)).toThrow(/cannot resolve knowledge.search/) expect(() => container.restrict(kind).resolve(KNOWLEDGE_ENABLEMENT)).toThrow( /cannot resolve knowledge.enablement/, ) } }) }) describe("the knowledge page's knowledge.status", () => { it("answers through a read handler's container, and never builds the search service", async () => { const container = processContainer() const search = neverBuilt() container.register(KNOWLEDGE_SEARCH, search) await expect(run(knowledgeStatusImpl, projectInput, container)).resolves.toMatchObject({ documents: { queued: 0, indexing: 0, indexed: 0, failed: 0, cancelled: 0 }, }) expect(search).not.toHaveBeenCalled() }) }) describe("the settings page's knowledge.settings", () => { it("get answers through a read handler's container, without the enablement platform", async () => { const container = processContainer() const enablement = neverBuilt() container.register(KNOWLEDGE_ENABLEMENT, enablement) await expect(run(settingsGetImpl, orgInput, container)).resolves.toEqual({ enabled: false, backend: null, }) expect(enablement).not.toHaveBeenCalled() }) it("enable reaches the platform and stores the configuration", async () => { const container = processContainer() container.value(KNOWLEDGE_ENABLEMENT, platform) await expect(run(settingsEnableDocumentAiImpl, orgInput, container)).resolves.toEqual({ enabled: true, backend: "platform", }) await expect(run(settingsGetImpl, orgInput, container)).resolves.toEqual({ enabled: true, backend: "platform" }) }) it("disable only flips the stored flag, without the enablement platform", async () => { const container = processContainer() const enablement = neverBuilt() container.register(KNOWLEDGE_ENABLEMENT, enablement) await expect(run(settingsDisableDocumentAiImpl, orgInput, container)).resolves.toEqual({ enabled: false }) expect(enablement).not.toHaveBeenCalled() }) }) describe("what knowledge.status says of the backend", () => { it("says what the bound readiness says, and asks it with the request's scope", async () => { const container = processContainer() const readiness = vi.fn(async () => ({ state: "degraded" as const, reasons: ["the index is behind"] })) container.value(KNOWLEDGE_READINESS, { readiness }) await expect(run(knowledgeStatusImpl, projectInput, container)).resolves.toMatchObject({ service: { state: "degraded", reasons: ["the index is behind"] }, }) expect(readiness).toHaveBeenCalledWith(scope) }) it("says the backend is not bound in a process that has none", async () => { await expect(run(knowledgeStatusImpl, projectInput, processContainer())).resolves.toMatchObject({ service: { state: "unavailable", reasons: ["the knowledge search service is not bound in this process"] }, }) }) it("reports the managed service failing to answer as unavailable, not as an error page", async () => { const container = processContainer() const client = { readiness: vi.fn(async () => Promise.reject(new Error("no answer\nstack"))) } container.value(KNOWLEDGE_READINESS, platformKnowledgeReadiness(client as never)) await expect(run(knowledgeStatusImpl, projectInput, container)).resolves.toMatchObject({ service: { state: "unavailable", reasons: [], refusal: "runtime_unavailable" }, }) }) })