From 310196dfa6a171d1dfc50a5f691a710c8f34b094 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Thu, 24 Sep 2026 23:22:16 -0700 Subject: [PATCH 1/2] test: delete the arktype schema tests The schema tests and the arktype half of the enum lockstep test assert that arktype validates what each schema declares, which tests the library rather than this package. The lockstep check that the migration CHECK constraints match the TypeScript enum constants stays. --- src/core/enums.lockstep.test.ts | 32 -------- src/core/schemas/adapted-document.test.ts | 56 ------------- src/core/schemas/chunk.test.ts | 45 ----------- src/core/schemas/claim-bearing.test.ts | 93 --------------------- src/core/schemas/document.test.ts | 91 --------------------- src/core/schemas/entity-edge.test.ts | 78 ------------------ src/core/schemas/search.test.ts | 99 ----------------------- 7 files changed, 494 deletions(-) delete mode 100644 src/core/schemas/adapted-document.test.ts delete mode 100644 src/core/schemas/chunk.test.ts delete mode 100644 src/core/schemas/claim-bearing.test.ts delete mode 100644 src/core/schemas/document.test.ts delete mode 100644 src/core/schemas/entity-edge.test.ts delete mode 100644 src/core/schemas/search.test.ts diff --git a/src/core/enums.lockstep.test.ts b/src/core/enums.lockstep.test.ts index aa58c31..5537788 100644 --- a/src/core/enums.lockstep.test.ts +++ b/src/core/enums.lockstep.test.ts @@ -9,14 +9,6 @@ import { RETENTION_CLASSES, TEMPORAL_CLASSES, } from "./enums.js"; -import { MemoryEdgeRelSchema, MemoryEdgeRefTypeSchema } from "./schemas/entity-edge.js"; -import { - LineageClassSchema, - ProvenanceModeSchema, - RetentionClassSchema, - TemporalClassSchema, -} from "./schemas/document.js"; -import { type } from "arktype"; const MIGRATIONS_DIR = join(import.meta.dir, "../../migrations"); @@ -65,27 +57,3 @@ describe("enum lockstep: TS constants match migration CHECK constraints", () => expect(sorted(lastCheckInList(sql, constraint))).toEqual(sorted(values)); }); }); - -describe("enum lockstep: arktype accepts every SSOT value and rejects unknown", () => { - // "produced_by" is in neither the rel set nor the ref-type sets, so it is - // a safe unknown-value probe for both schemas. - it.each([ - ["MemoryEdgeRelSchema", MemoryEdgeRelSchema, EDGE_RELS, "produced_by"], - [ - "MemoryEdgeRefTypeSchema", - MemoryEdgeRefTypeSchema, - ["document", "version", "chunk", "entity", "native"], - "produced_by", - ], - ["LineageClassSchema", LineageClassSchema, LINEAGE_CLASSES, "thread"], - ["ProvenanceModeSchema", ProvenanceModeSchema, PROVENANCE_MODES, "guessed"], - ["TemporalClassSchema", TemporalClassSchema, TEMPORAL_CLASSES, "forecast"], - ["RetentionClassSchema", RetentionClassSchema, RETENTION_CLASSES, "forever"], - ] as const)("%s accepts its SSOT values and rejects unknown", (_name, schema, valid, invalid) => { - for (const value of valid) { - const out = schema(value); - expect(out instanceof type.errors ? out.summary : out).toBe(value); - } - expect(schema(invalid) instanceof type.errors).toBe(true); - }); -}); diff --git a/src/core/schemas/adapted-document.test.ts b/src/core/schemas/adapted-document.test.ts deleted file mode 100644 index b0c2840..0000000 --- a/src/core/schemas/adapted-document.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { type } from "arktype"; -import { AdaptedDocumentSchema } from "./adapted-document.js"; -import type { AdaptedDocument } from "./adapted-document.js"; - -// T2 — a full AdaptedDocument fixture must parse with no errors. -describe("AdaptedDocumentSchema", () => { - it("round-trips a full fixture", () => { - const fixture: AdaptedDocument = { - kind: "call_transcript", - title: "Q3 renewal call", - externalRef: "granola:note_123", - accessTags: ["memory.tenant:t1"], - attributes: { durationSec: 1800 }, - entityHints: [{ kind: "person", identifier: "jane@example.com" }], - edges: [ - { rel: "about", to: { type: "entity", ref: "acme-co" } }, - { rel: "authored_by", to: { type: "native", ref: "principal_1" } }, - ], - chunks: [ - { ordinal: 0, text: "Opening remarks.", role: "summary" }, - { ordinal: 1, text: "Pricing discussion." }, - ], - rawPointer: { table: "granola_call_job", id: "job_1" }, - actor: { kind: "adapter" }, - contentHash: "sha256:abc123", - }; - const out = AdaptedDocumentSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("parses without any of the optional fields", () => { - const out = AdaptedDocumentSchema({ - kind: "task", - title: "Follow up with Acme", - externalRef: "task:1", - accessTags: ["memory.owner:u1"], - entityHints: [], - chunks: [{ ordinal: 0, text: "Follow up with Acme on pricing." }], - contentHash: "sha256:def456", - }); - expect(out instanceof type.errors).toBe(false); - }); - - it("rejects a fixture missing contentHash", () => { - const out = AdaptedDocumentSchema({ - kind: "task", - title: "Follow up with Acme", - externalRef: "task:1", - accessTags: ["memory.owner:u1"], - entityHints: [], - chunks: [{ ordinal: 0, text: "Follow up with Acme on pricing." }], - }); - expect(out instanceof type.errors).toBe(true); - }); -}); diff --git a/src/core/schemas/chunk.test.ts b/src/core/schemas/chunk.test.ts deleted file mode 100644 index 0ac8c52..0000000 --- a/src/core/schemas/chunk.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { type } from "arktype"; -import { MemoryChunkSchema } from "./chunk.js"; - -describe("MemoryChunkSchema", () => { - it("round-trips a full fixture", () => { - const fixture = { - id: "chunk_1", - tenant_id: "tenant_1", - version_id: "kv_1", - document_id: "doc_1", - ordinal: 0, - text: "We agreed to renew at the same tier.", - role: "summary", - created_at: "2026-07-19T00:00:00.000Z", - }; - const out = MemoryChunkSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("parses without the optional role", () => { - const out = MemoryChunkSchema({ - id: "chunk_1", - tenant_id: "tenant_1", - version_id: "kv_1", - document_id: "doc_1", - ordinal: 0, - text: "We agreed to renew at the same tier.", - created_at: "2026-07-19T00:00:00.000Z", - }); - expect(out instanceof type.errors).toBe(false); - }); - - it("rejects a chunk missing version_id", () => { - const out = MemoryChunkSchema({ - id: "chunk_1", - tenant_id: "tenant_1", - document_id: "doc_1", - ordinal: 0, - text: "We agreed to renew at the same tier.", - created_at: "2026-07-19T00:00:00.000Z", - }); - expect(out instanceof type.errors).toBe(true); - }); -}); diff --git a/src/core/schemas/claim-bearing.test.ts b/src/core/schemas/claim-bearing.test.ts deleted file mode 100644 index 0f66cf4..0000000 --- a/src/core/schemas/claim-bearing.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { type } from "arktype"; -import { AdaptedDocumentSchema } from "./adapted-document.js"; -import { MemoryEdgeHintSchema } from "./entity-edge.js"; -import type { AdaptedDocument } from "./adapted-document.js"; - -/** - * Claim-bearing write shape: a distilled claim is a normal AdaptedDocument - * with inferred provenance, derived lineage, and a derived_from edge. - * Core never runs inference — it only accepts this shape. - */ -describe("claim-bearing AdaptedDocument shape", () => { - it("accepts a derived claim with provenance, lineage, and derived_from", () => { - const claim: AdaptedDocument = { - kind: "claim", - title: "Acme renews in Q3", - externalRef: "claim:acme-q3-renewal", - accessTags: ["memory.tenant:t1"], - entityHints: [{ kind: "org", identifier: "acme.com" }], - edges: [ - { - rel: "derived_from", - to: { type: "version", ref: "kver_source_1" }, - }, - { - rel: "supports", - to: { type: "version", ref: "kver_prior_claim" }, - }, - ], - chunks: [ - { - ordinal: 0, - text: "Acme is expected to renew in Q3 at a 12% expansion.", - }, - ], - actor: { kind: "agent", agentId: "distiller-v1" }, - sourceClass: "record", - lineageClass: "derived", - provenance: "inferred", - contentHash: "sha256:claim-1", - }; - const out = AdaptedDocumentSchema(claim); - expect(out instanceof type.errors ? out.summary : out).toEqual(claim); - }); - - it("accepts every claim-bearing edge rel", () => { - for (const rel of [ - "derived_from", - "supports", - "contradicts", - "supersedes", - "authored_by", - "involves", - "part_of", - ] as const) { - const out = MemoryEdgeHintSchema({ - rel, - to: { type: "version", ref: "kver_1" }, - }); - expect(out instanceof type.errors).toBe(false); - } - }); - - it("rejects pre-claim edge rels that were never DB-valid", () => { - for (const rel of ["produced_by", "links", "parent", "waiting_on"]) { - const out = MemoryEdgeHintSchema({ - rel, - to: { type: "entity", ref: "e1" }, - }); - expect(out instanceof type.errors).toBe(true); - } - }); - - it("keeps ranking sourceClass independent of lineageClass", () => { - const out = AdaptedDocumentSchema({ - kind: "call_transcript", - title: "Call", - externalRef: "call:1", - accessTags: ["memory.tenant:t1"], - entityHints: [], - chunks: [{ ordinal: 0, text: "hi" }], - contentHash: "sha256:x", - sourceClass: "channel", - lineageClass: "native", - provenance: "stated", - }); - expect(out instanceof type.errors).toBe(false); - if (!(out instanceof type.errors)) { - expect(out.sourceClass).toBe("channel"); - expect(out.lineageClass).toBe("native"); - } - }); -}); diff --git a/src/core/schemas/document.test.ts b/src/core/schemas/document.test.ts deleted file mode 100644 index 256c6bd..0000000 --- a/src/core/schemas/document.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { type } from "arktype"; -import { - MemoryDocumentSchema, - MemoryVersionSchema, -} from "./document.js"; -import type { MemoryDocument, MemoryVersion } from "./document.js"; - -describe("MemoryDocumentSchema", () => { - it("round-trips a full fixture", () => { - const fixture: MemoryDocument = { - id: "doc_1", - tenant_id: "tenant_1", - kind: "call_transcript", - title: "Q3 renewal call", - adapter: "granola", - external_ref: "granola:note_123", - access_tags: ["memory.tenant:tenant_1"], - attributes: { channel: "call", pinned: true, score: null }, - created_at: "2026-07-19T00:00:00.000Z", - last_seen_at: "2026-07-19T00:00:00.000Z", - }; - const out = MemoryDocumentSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("rejects a document missing external_ref", () => { - const out = MemoryDocumentSchema({ - id: "doc_1", - tenant_id: "tenant_1", - kind: "call_transcript", - title: "Q3 renewal call", - adapter: "granola", - access_tags: ["memory.tenant:tenant_1"], - attributes: {}, - created_at: "2026-07-19T00:00:00.000Z", - last_seen_at: "2026-07-19T00:00:00.000Z", - }); - expect(out instanceof type.errors).toBe(true); - }); -}); - -describe("MemoryVersionSchema", () => { - it("round-trips a full fixture", () => { - const fixture: MemoryVersion = { - id: "kv_1", - tenant_id: "tenant_1", - document_id: "doc_1", - version: 1, - version_id: "kv_1", - supersedes_version_id: null, - status: "active", - content_hash: "sha256:abc", - occurred_at: "2026-07-19T00:00:00.000Z", - ingested_at: "2026-07-19T00:00:01.000Z", - deprecated_at: null, - deprecated_reason: null, - created_by_principal_id: "principal_1", - created_by_kind: "human", - provenance: "stated", - source_class: "native", - temporal_class: "event", - retention_class: "standard", - }; - const out = MemoryVersionSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("rejects an invalid status", () => { - const out = MemoryVersionSchema({ - id: "kv_1", - tenant_id: "tenant_1", - document_id: "doc_1", - version: 1, - version_id: "kv_1", - supersedes_version_id: null, - status: "final", - content_hash: "sha256:abc", - occurred_at: "2026-07-19T00:00:00.000Z", - ingested_at: "2026-07-19T00:00:01.000Z", - deprecated_at: null, - deprecated_reason: null, - created_by_principal_id: null, - created_by_kind: "human", - provenance: "stated", - source_class: "native", - temporal_class: "event", - }); - expect(out instanceof type.errors).toBe(true); - }); -}); diff --git a/src/core/schemas/entity-edge.test.ts b/src/core/schemas/entity-edge.test.ts deleted file mode 100644 index 769cac2..0000000 --- a/src/core/schemas/entity-edge.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { type } from "arktype"; -import { - MemoryEdgeHintSchema, - MemoryEdgeSchema, - MemoryEntitySchema, -} from "./entity-edge.js"; -import type { MemoryEdge } from "./entity-edge.js"; - -describe("MemoryEntitySchema", () => { - it("round-trips a full fixture", () => { - const fixture = { - id: "entity_1", - tenant_id: "tenant_1", - kind: "person", - identifiers: { email: "jane@example.com" }, - created_at: "2026-07-19T00:00:00.000Z", - }; - const out = MemoryEntitySchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); -}); - -describe("MemoryEdgeSchema", () => { - it("round-trips a full fixture", () => { - const fixture: MemoryEdge = { - id: "edge_1", - tenant_id: "tenant_1", - rel: "about", - from: { type: "document", ref: "doc_1" }, - to: { type: "entity", ref: "entity_1" }, - created_at: "2026-07-19T00:00:00.000Z", - }; - const out = MemoryEdgeSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("rejects an unknown rel", () => { - const out = MemoryEdgeSchema({ - id: "edge_1", - tenant_id: "tenant_1", - rel: "orbits", - from: { type: "document", ref: "doc_1" }, - to: { type: "entity", ref: "entity_1" }, - created_at: "2026-07-19T00:00:00.000Z", - }); - expect(out instanceof type.errors).toBe(true); - }); -}); - -// T4 — a MemoryEdgeHint missing to.ref must fail arktype validation. -describe("MemoryEdgeHintSchema", () => { - it("parses a full fixture", () => { - const out = MemoryEdgeHintSchema({ - rel: "authored_by", - to: { type: "native", ref: "principal_1" }, - }); - expect(out instanceof type.errors).toBe(false); - }); - - it("rejects a hint whose to is missing ref", () => { - const out = MemoryEdgeHintSchema({ - rel: "authored_by", - to: { type: "native" }, - }); - expect(out instanceof type.errors).toBe(true); - }); - - it("accepts version and chunk endpoint types", () => { - for (const endpointType of ["version", "chunk"] as const) { - const out = MemoryEdgeHintSchema({ - rel: "derived_from", - to: { type: endpointType, ref: "id_1" }, - }); - expect(out instanceof type.errors).toBe(false); - } - }); -}); diff --git a/src/core/schemas/search.test.ts b/src/core/schemas/search.test.ts deleted file mode 100644 index 5a4ab90..0000000 --- a/src/core/schemas/search.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { type } from "arktype"; -import { SearchHitSchema, SearchResponseSchema } from "./search.js"; -import type { SearchHit, SearchResponse } from "./search.js"; - -function fullHitFixture(): SearchHit { - return { - chunk_id: "chunk_1", - document_id: "doc_1", - version: 3, - version_id: "kv_3", - status: "active", - score: 0.87, - title: "Q3 renewal call", - snippet: "...agreed to renew at the same tier...", - kind: "call_transcript", - created_by_kind: "adapter", - citation: { - adapter: "granola", - external_ref: "granola:note_123", - open: { type: "call", id: "note_123", at: { tSec: 412 } }, - }, - entity_ids: ["entity_1"], - channels_matched: ["lexical", "dense"], - }; -} - -describe("SearchHitSchema", () => { - it("round-trips a full fixture with a version-pinned citation", () => { - const fixture = fullHitFixture(); - const out = SearchHitSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("parses citation.open without the optional at anchor", () => { - const fixture = fullHitFixture(); - fixture.citation.open = { type: "artifact", id: "doc_1" }; - const out = SearchHitSchema(fixture); - expect(out instanceof type.errors).toBe(false); - }); - - // T3 — a SearchHit missing version_id must fail arktype validation; the - // citation must always be reproducible against the exact version it cites. - it("rejects a hit missing version_id", () => { - const fixture: Record = fullHitFixture(); - delete fixture.version_id; - const out = SearchHitSchema(fixture); - expect(out instanceof type.errors).toBe(true); - }); - - it("accepts additive attribution fields (CL-5870)", () => { - const fixture = fullHitFixture(); - fixture.provenance = "inferred"; - fixture.source_class = "derived"; - fixture.temporal_class = "lesson"; - fixture.occurred_at = "2026-07-01T00:00:00.000Z"; - fixture.valid_until = null; - fixture.supports = 3; - fixture.contradicts = 1; - fixture.derived_from = ["kv_src"]; - fixture.generator_agent_id = "resident-distiller"; - fixture.created_by_kind = "agent"; - const out = SearchHitSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("still parses without attribution fields (additive / back-compat)", () => { - const fixture = fullHitFixture(); - const out = SearchHitSchema(fixture); - expect(out instanceof type.errors).toBe(false); - }); -}); - -describe("SearchResponseSchema", () => { - // T5 — evidence: "weak" with no degraded field must still parse. - it("parses a weak-evidence response with no degraded field", () => { - const fixture: SearchResponse = { - hits: [fullHitFixture()], - evidence: "weak", - }; - const out = SearchResponseSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("parses a none-evidence response with an empty hit list and degraded reasons", () => { - const fixture: SearchResponse = { - hits: [], - evidence: "none", - degraded: ["dense_unavailable", "lexical_only"], - }; - const out = SearchResponseSchema(fixture); - expect(out instanceof type.errors ? out.summary : out).toEqual(fixture); - }); - - it("rejects an invalid evidence value", () => { - const out = SearchResponseSchema({ hits: [], evidence: "certain" }); - expect(out instanceof type.errors).toBe(true); - }); -}); From 07f18a5c33dddade9f7caf31a392166cf76ada0f Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Thu, 24 Sep 2026 23:22:21 -0700 Subject: [PATCH 2/2] test: delete tests of the port test doubles These tests exercised the test doubles rather than production code. --- src/ports/fakes.test.ts | 148 -------------------------------- src/ports/mount-fakes.test.ts | 156 ---------------------------------- 2 files changed, 304 deletions(-) delete mode 100644 src/ports/fakes.test.ts delete mode 100644 src/ports/mount-fakes.test.ts diff --git a/src/ports/fakes.test.ts b/src/ports/fakes.test.ts deleted file mode 100644 index f90bb6a..0000000 --- a/src/ports/fakes.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { createInMemoryGrantStore } from "@intx/authz"; - -import { ownerTag, tenantTag } from "../grant-tags.js"; - -import { - createFakeDocumentStore, - createFakeSourceProvider, -} from "./fakes.js"; - -const TENANT = "t1"; -const PRINCIPAL = "p1"; -const OTHER = "p2"; - -describe("createFakeDocumentStore", () => { - it("round-trips add → find → recent", async () => { - const store = createFakeDocumentStore(); - const { documentId } = await store.add({ - tenantId: TENANT, - principalId: PRINCIPAL, - title: "standup notes", - text: "shipped the ports foundation", - accessTags: [ownerTag(PRINCIPAL), tenantTag(TENANT)], - }); - expect(documentId).toMatch(/^fake_doc_/); - - const found = await store.search({ - tenantId: TENANT, - principalId: PRINCIPAL, - query: "ports foundation", - includeEvidence: true, - }); - expect(found.items).toHaveLength(1); - expect(found.items[0]?.documentId).toBe(documentId); - expect(found.evidence).toBe("weak"); - - const events = await store.list({ - tenantId: TENANT, - principalId: PRINCIPAL, - }); - expect(events.map((e) => e.title)).toEqual(["standup notes"]); - await store.close(); - }); - - it("creator-only without grants; other principal cannot see", async () => { - const store = createFakeDocumentStore(); - await store.add({ - tenantId: TENANT, - principalId: PRINCIPAL, - title: "secret", - text: "classified payload", - accessTags: [ownerTag(PRINCIPAL)], - }); - const asOwner = await store.search({ - tenantId: TENANT, - principalId: PRINCIPAL, - query: "classified", - }); - const asOther = await store.search({ - tenantId: TENANT, - principalId: OTHER, - query: "classified", - }); - expect(asOwner.items).toHaveLength(1); - expect(asOther.items).toHaveLength(0); - await store.close(); - }); - - it("peer with grant on owner tag can see", async () => { - const store = createFakeDocumentStore(); - await store.add({ - tenantId: TENANT, - principalId: PRINCIPAL, - title: "shared note", - text: "visible body", - accessTags: [ownerTag(PRINCIPAL), ownerTag(OTHER)], - }); - const grants = createInMemoryGrantStore([ - { - id: "g1", - principalId: OTHER, - resource: ownerTag(OTHER), - action: "search", - effect: "allow", - origin: "role", - conditions: null, - expiresAt: null, - roleId: null, - }, - ]); - const asOther = await store.search({ - tenantId: TENANT, - principalId: OTHER, - query: "visible", - grants, - }); - expect(asOther.items).toHaveLength(1); - await store.close(); - }); -}); - -describe("createFakeSourceProvider", () => { - it("searchLive filters catalog by query", async () => { - const source = createFakeSourceProvider("linear", [ - { - adapter: "linear", - externalRef: "CL-1", - title: "ports foundation", - snippet: "DocumentStore + SourceProvider", - score: 0.9, - kind: "issue", - citation: { - adapter: "linear", - external_ref: "CL-1", - open: { - type: "issue", - id: "CL-1", - url: "https://linear.app/x/issue/CL-1", - }, - }, - }, - { - adapter: "linear", - externalRef: "CL-2", - title: "unrelated", - snippet: "something else", - score: 0.1, - kind: "issue", - citation: { - adapter: "linear", - external_ref: "CL-2", - open: { - type: "issue", - id: "CL-2", - url: "https://linear.app/x/issue/CL-2", - }, - }, - }, - ]); - const hits = await source.searchLive!({ - query: "ports", - tenantId: TENANT, - principalId: PRINCIPAL, - }); - expect(hits).toHaveLength(1); - expect(hits[0]?.externalRef).toBe("CL-1"); - }); -}); diff --git a/src/ports/mount-fakes.test.ts b/src/ports/mount-fakes.test.ts deleted file mode 100644 index 4a7a34e..0000000 --- a/src/ports/mount-fakes.test.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Acceptance: a host can createMemory with only fakes and get working - * add / search / list — proves the port boundary is real. - */ -import { describe, expect, it } from "bun:test"; -import { Hono } from "hono"; -import { createRequireGrant, type TenantEnv } from "@intx/hub-api"; -import { - createInMemoryGrantStore, - type GrantRule, -} from "@intx/authz"; - -import { createMemory } from "../memory.js"; -import { createMemoryRoutes } from "../routes/mount.js"; -import { createFakeDocumentStore, createFakeSourceProvider } from "./fakes.js"; - -const TENANT = "tenant_fake"; -const PRINCIPAL = "principal_fake"; - -function grant(action: string): GrantRule { - return { - id: `g-${action}`, - resource: "memory", - action, - effect: "allow", - origin: "role", - conditions: null, - expiresAt: null, - roleId: null, - principalId: PRINCIPAL, - }; -} - -function appWithPrincipal() { - const app = new Hono(); - app.use("*", async (c, next) => { - c.set("principal", { - id: PRINCIPAL, - tenantId: TENANT, - kind: "user", - refId: "u1", - status: "active", - createdAt: new Date(0), - updatedAt: new Date(0), - }); - c.set("tenant", { - id: TENANT, - name: "T1", - slug: "t1", - domain: "t1.test", - parentId: null, - config: {}, - createdAt: new Date(0), - updatedAt: new Date(0), - }); - await next(); - }); - return app; -} - -describe("createMemory with fakes only", () => { - it("add → search → list without Postgres or embed config", async () => { - const store = createFakeDocumentStore(); - const sources = [ - createFakeSourceProvider("linear", [ - { - adapter: "linear", - externalRef: "CL-99", - title: "live only issue", - snippet: "should not appear until merge lands", - score: 0.99, - kind: "issue", - citation: { - adapter: "linear", - external_ref: "CL-99", - open: { - type: "issue", - id: "CL-99", - url: "https://linear.app/x/issue/CL-99", - }, - }, - }, - ]), - ]; - const app = appWithPrincipal(); - const grantConfig = { - grantStore: createInMemoryGrantStore([grant("add"), grant("search")]), - conditionRegistry: {}, - }; - const memory = createMemory({ - grantStore: grantConfig.grantStore, - conditionRegistry: grantConfig.conditionRegistry, - documentStore: store, - sources, - }); - app.route( - "/api/tenants/:tenantId/memory", - createMemoryRoutes({ - memory, - requireGrant: createRequireGrant(grantConfig), - }), - ); - - const { documentId } = await memory.add({ - tenantId: TENANT, - principalId: PRINCIPAL, - content: { - title: "ports note", - text: "DocumentStore override works end to end", - }, - }); - expect(documentId).toMatch(/^fake_doc_/); - - const found = await memory.search({ - tenantId: TENANT, - principalId: PRINCIPAL, - query: "DocumentStore override", - includeEvidence: true, - }); - expect(found.items).toHaveLength(1); - expect(found.items[0]?.documentId).toBe(documentId); - - const listed = await memory.list({ - tenantId: TENANT, - principalId: PRINCIPAL, - }); - expect(listed.some((e) => e.title === "ports note")).toBe(true); - - const addRes = await app.request("/api/tenants/tenant_fake/memory/add", { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ - title: "via http", - text: "http path uses the same store", - }), - }); - expect(addRes.status).toBe(200); - const addBody = (await addRes.json()) as { documentId: string }; - expect(addBody.documentId).toMatch(/^fake_doc_/); - - const searchRes = await app.request("/api/tenants/tenant_fake/memory/search", { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ query: "http path" }), - }); - expect(searchRes.status).toBe(200); - const searchBody = (await searchRes.json()) as { - items: Array<{ documentId: string }>; - }; - expect( - searchBody.items.some((i) => i.documentId === addBody.documentId), - ).toBe(true); - - await memory.close(); - }); -});