6.1 KiB
IdentityDB Space Isolation Implementation Plan
For Hermes: Use the
writing-plansandtest-driven-developmentskills. 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
- A caller must be able to write memory into independent spaces such as
AandB. - Topic lookups, alias resolution, hierarchy traversal, connected-topic queries, fact queries, ingestion, and semantic search must only see data from the requested space.
- Existing callers that do not specify a space must continue to work inside a built-in
defaultspace. - Space names must be normalized/canonicalized similarly to topics.
- 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
spacestable. - Assert that
topics,facts, andtopic_aliasesnow includespace_id. - Assert that
spacesincludesid,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.tsif 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 fromspaceName: '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
spaceNamestill operate in thedefaultspace.
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_TABLEandSPACE_COLUMNSconstants. - Add
SpaceRecorddomain type. - Add
spacestoIdentityDatabaseSchema. - Create the
spacestable. - Add
space_idcolumns totopics,facts, andtopic_aliases. - Make topic uniqueness per-space, not global.
- Make alias uniqueness per-space, not global.
- Seed or upsert a built-in
defaultspace 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.tsif new exported types are added
Implementation notes:
- Add public
SpaceandUpsertSpaceInputtypes if needed. - Add optional
spaceNameon 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'andspaceName: '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
docs: add IdentityDB space isolation plantest: specify isolated memory spacesfeat: add space-aware memory graph isolationdocs: document space-scoped memory usage
Acceptance checklist
spacestable exists.- Topics with the same normalized name can exist in different spaces.
- Facts from one space do not appear in another space’s queries.
- Alias and hierarchy traversal are space-aware.
- Semantic search and duplicate detection are space-aware.
- Existing callers still work via the
defaultspace. - Full test/build/typecheck suite passes.