docs: add IdentityDB space isolation plan

This commit is contained in:
2026-05-11 14:28:08 +09:00
parent 283f91ed91
commit b908bc0bd9

View File

@@ -0,0 +1,157 @@
# 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.