// The archive use cases over a recording port: what each asks the service, with no client and no network. import type { ProjectScope } from "@conusai-kit/core" import { createMemoryDataSource } from "@conusai-kit/data" import { DEFAULT_FILES_POLICY, files } from "@conusai-kit/files" import { fakeObjectStore } from "@conusai-kit/testing" import { describe, expect, it } from "vitest" import { addVersion, listDocuments, registerDocument, requestKey, versionFacts } from "../core/archive.js" import { type ArchiveService, archiveReadsOf } from "../core/ports.js" const scope: ProjectScope = { 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 receipt = { documentId: "doc_1", revision: "1" } function recording() { const asked: Array<[string, unknown]> = [] const service: ArchiveService = { listDocuments: async (query) => { asked.push(["listDocuments", query]) return { rows: [] } }, getDocument: async () => { throw new Error("not asked") }, listVersions: async () => ({ rows: [] }), listRetentionClasses: async () => ({ rows: [] }), listDisposalDue: async () => ({ rows: [] }), registerDocument: async (input) => { asked.push(["registerDocument", input]) return receipt }, addVersion: async (input) => { asked.push(["addVersion", input]) return receipt }, setLegalHold: async () => receipt, disposeDocument: async () => receipt, createRetentionClass: async () => undefined, } return { service, asked } } async function storedFile() { const data = createMemoryDataSource({ entities: [files] }) const deps = { data, store: fakeObjectStore(), policy: DEFAULT_FILES_POLICY } const row = await data .forScope(scope) .of(files) .insert({ status: "stored", storageKey: "files/w/p/f", filename: "record.pdf", contentType: "application/pdf", size: 1234, sha256: "a".repeat(64), uploadedBy: scope.actor.userId, storedAt: "2026-11-02T10:00:00.000Z", uploadId: null, declaredSize: null, partSize: null, deletingAt: null, }) return { deps, fileId: row.id } } describe("the archive use cases", () => { it("list documents with a trimmed search and the module's page size", async () => { const { service, asked } = recording() await listDocuments(service, { q: " invoice " }) await listDocuments(service, { q: " " }) expect(asked).toEqual([ ["listDocuments", { q: "invoice", limit: 50 }], ["listDocuments", { limit: 50 }], ]) }) it("take a version's facts from the stored file, with an opaque Blob reference", async () => { const { deps, fileId } = await storedFile() expect(await versionFacts(deps, scope, fileId)).toEqual({ sha256: "a".repeat(64), mediaType: "application/pdf", size: 1234, blobRef: `conusai://blob/files/${fileId}`, }) }) it("register a document with the project's request key and a trimmed title, and no kind unless asked", async () => { const { deps, fileId } = await storedFile() const { service, asked } = recording() await registerDocument(service, deps, scope, { title: " Signed contract ", kind: " ", retentionClass: "contracts", fileId, requestId: "r1", }) expect(asked).toEqual([ [ "registerDocument", { title: "Signed contract", retentionClass: "contracts", version: await versionFacts(deps, scope, fileId), key: requestKey(scope, "r1"), }, ], ]) }) it("add a version over the revision the page read", async () => { const { deps, fileId } = await storedFile() const { service, asked } = recording() await addVersion(service, deps, scope, { documentId: "doc_1", revision: "4", fileId, requestId: "r2" }) expect(asked[0]?.[1]).toMatchObject({ documentId: "doc_1", revision: "4", key: requestKey(scope, "r2") }) }) it("refuse a file this project does not hold before the service is asked", async () => { const { deps } = await storedFile() const { service, asked } = recording() await expect( registerDocument(service, deps, scope, { title: "Someone else's", retentionClass: "contracts", fileId: "01900000-0000-7000-0000-0000000000ff", requestId: "r3", }), ).rejects.toMatchObject({ problem: { status: 404 } }) expect(asked).toEqual([]) }) it("hand a read handler a view without a single write", () => { expect(Object.keys(archiveReadsOf(recording().service)).sort()).toEqual([ "getDocument", "listDisposalDue", "listDocuments", "listRetentionClasses", "listVersions", ]) }) })