Files
IdentityDB/docs/plans/2026-05-11-identitydb-space-isolation.md

6.1 KiB
Raw Permalink Blame History

IdentityDB Space Isolation Implementation Plan

For Hermes: Use the writing-plans and test-driven-development skills. Implement this feature in small TDD steps with meaningful commits.

Goal: Add first-class memory spaces so callers can keep unrelated topic/fact graphs isolated from each other while still using one physical database.

Architecture: Introduce a spaces table plus space_id scoping on the canonical topic/fact records that define graph ownership. Treat the unnamed/default behavior as a built-in default space so existing API usage keeps working, while allowing any write/query path to target a named space explicitly.

Tech Stack: TypeScript, Bun, Vitest, Kysely, SQLite/PostgreSQL/MySQL/MariaDB-compatible schema primitives.


Requirements

  1. A caller must be able to write memory into independent spaces such as A and B.
  2. Topic lookups, alias resolution, hierarchy traversal, connected-topic queries, fact queries, ingestion, and semantic search must only see data from the requested space.
  3. Existing callers that do not specify a space must continue to work inside a built-in default space.
  4. Space names must be normalized/canonicalized similarly to topics.
  5. Documentation must explain both the isolation model and the default-space compatibility behavior.

Task 1: Add failing tests for schema-level space support

Objective: Define the storage contract for spaces and per-space uniqueness before implementation.

Files:

  • Modify: tests/migrations.test.ts

Step 1: Write failing tests

  • Assert that initialization creates a spaces table.
  • Assert that topics, facts, and topic_aliases now include space_id.
  • Assert that spaces includes id, name, normalized_name, description, metadata, created_at, updated_at.

Step 2: Run red test

  • Run: bun run test tests/migrations.test.ts
  • Expect: failure because the schema does not yet contain space support.

Step 3: Commit later with implementation

  • Do not commit yet; continue only after implementation turns the test green.

Task 2: Add failing behavioral tests for isolated spaces

Objective: Lock in the public API behavior for separate memory spaces.

Files:

  • Modify: tests/identity-db.test.ts
  • Modify: tests/queries.test.ts
  • Modify: tests/semantic-search.test.ts
  • Optionally create: tests/spaces.test.ts if separation makes the scenarios clearer.

Step 1: Write failing tests

  • Verify the same topic name can exist in two spaces without deduplicating together.
  • Verify facts added in spaceName: 'A' are invisible from spaceName: 'B'.
  • Verify alias resolution only resolves inside the same space.
  • Verify hierarchy parent/child traversal only stays within the same space.
  • Verify semantic search and duplicate-aware ingestion only search within the same space.
  • Verify callers that omit spaceName still operate in the default space.

Step 2: Run red tests

  • Run the most targeted files first, then the whole suite slice.
  • Example: bun run test tests/identity-db.test.ts tests/queries.test.ts tests/semantic-search.test.ts
  • Expect: failure due to missing API fields and missing isolation logic.

Task 3: Implement schema and type support

Objective: Add the underlying data model required for spaces.

Files:

  • Modify: src/core/schema.ts
  • Modify: src/types/domain.ts
  • Modify: src/types/database.ts
  • Modify: src/core/migrations.ts

Implementation notes:

  • Add SPACES_TABLE and SPACE_COLUMNS constants.
  • Add SpaceRecord domain type.
  • Add spaces to IdentityDatabaseSchema.
  • Create the spaces table.
  • Add space_id columns to topics, facts, and topic_aliases.
  • Make topic uniqueness per-space, not global.
  • Make alias uniqueness per-space, not global.
  • Seed or upsert a built-in default space during initialization via normal application flow, not hard-coded SQL assumptions.

Verification:

  • Re-run: bun run test tests/migrations.test.ts
  • Expect: green.

Task 4: Implement space-aware API contracts and query helpers

Objective: Thread spaceName through the high-level API and low-level query layer.

Files:

  • Modify: src/types/api.ts
  • Modify: src/ingestion/types.ts
  • Modify: src/queries/topics.ts
  • Modify: src/queries/facts.ts
  • Modify: src/core/identity-db.ts
  • Modify: src/index.ts if new exported types are added

Implementation notes:

  • Add public Space and UpsertSpaceInput types if needed.
  • Add optional spaceName on write/query inputs where the caller targets a graph.
  • Add helpers to resolve or create the requested space inside transactions.
  • Ensure all existing topic lookup helpers filter by space_id.
  • Ensure semantic search candidates are restricted to facts in the requested space.
  • Preserve existing no-space API calls by mapping them to default.

Verification:

  • Re-run the failing behavior tests.
  • Expect: green for the new targeted tests.

Task 5: Refine ergonomics and update documentation

Objective: Make the feature understandable and safe to use.

Files:

  • Modify: README.md
  • Optionally modify: wiki docs later if requested

Implementation notes:

  • Document the default space behavior.
  • Add examples for spaceName: 'A' and spaceName: 'B'.
  • Explain that spaces are hard isolation boundaries for topic/fact traversal and semantic retrieval.

Verification:

  • Run: bun run test && bun run check && bun run build
  • Confirm docs/examples align with the final public API.

Suggested commit boundaries

  1. docs: add IdentityDB space isolation plan
  2. test: specify isolated memory spaces
  3. feat: add space-aware memory graph isolation
  4. docs: document space-scoped memory usage

Acceptance checklist

  • spaces table exists.
  • Topics with the same normalized name can exist in different spaces.
  • Facts from one space do not appear in another spaces queries.
  • Alias and hierarchy traversal are space-aware.
  • Semantic search and duplicate detection are space-aware.
  • Existing callers still work via the default space.
  • Full test/build/typecheck suite passes.