feat(memory-wiki): scope vault path to instanceId (Phase D2.1)#13
Merged
Conversation
Adds an optional `instanceId` field to OpenClawConfig. Validates 1-128 chars matching `[A-Za-z0-9_-]+` so the value can serve as a filesystem-safe path component. When set, downstream features (memory-wiki vault path, cloud-mirror state file, health snapshot, shard directory layout) scope per-instance resources to this id. When unset, single-user Tier A defaults apply. This is the foundation PR for Phase D2.1 (per-instance harness hardening); subsequent PRs surface the field on health, scope the memory-wiki vault, and update the cloud-mirror daemon. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Threads `instanceId` from `OpenClawConfig` into the memory-wiki
config resolver so each Bench instance gets its own vault directory:
Tier A (no instanceId): ~/.openclaw/wiki/main/
Tier B/C (instanceId): ~/.openclaw/wiki/{instanceId}/
Validates the id with a local copy of the same regex used by the
core config schema (`/^[A-Za-z0-9_-]{1,128}$/`) — kept local because
the memory-wiki extension doesn't import from `src/config/*` and the
constraint must stay filesystem-safe regardless. Path-traversal
inputs (`"../evil"`, `"has/slash"`, `""`) fall back to `main/` rather
than scoping into a malicious dir.
Explicit `vault.path` overrides still win, so existing single-user
deployments that set a custom vault path are unaffected.
Depends on PR #11.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This was referenced Apr 28, 2026
Surfaced by Codex Anvil (PR #13 smoke 20260428T080050Z): 1. `cli-metadata.test.ts` asserted the old one-arg call to `resolveMemoryWikiConfig`, but the entry now passes `{ instanceId }` as a second arg. Updated assertion + added `instanceId: "bench-prod-01"` to the test's `appConfig` fixture so it proves the threading works end-to-end. 2. README, `docs/plugins/memory-wiki.md`, and the plugin manifest `openclaw.plugin.json` all hardcoded `vault.path: "~/.openclaw/wiki/main"` in copy-paste examples. A user copying that into Tier B/C config would silently override the new instance-scoped default. Updated: - examples comment-out `path:` and document the new default. - manifest help text describes the `~/.openclaw/wiki/{instanceId}` default + override semantics. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
LightDriverCS
added a commit
that referenced
this pull request
Apr 28, 2026
Phase D2.1 foundation. Adds optional top-level instanceId to OpenClawConfig with strict regex /^[A-Za-z0-9_-]{1,128}$/ for filesystem-safe per-instance scoping. Stack of #12 (health), #13 (memory-wiki vault), #14 (cloud-mirror) follows.
Codex Anvil (gpt-5.5 xhigh) verdict: PASS. 54 tests pass; pnpm config:schema:check + pnpm config:docs:check both green. Repair patch from first smoke (regenerate config-baseline.sha256) applied as second commit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Threads
instanceIdfromOpenClawConfiginto the memory-wiki config resolver so each Bench instance gets its own vault directory:~/.openclaw/wiki/main/~/.openclaw/wiki/{instanceId}/Explicit
vault.pathoverrides still win, so existing single-user deployments that set a custom vault path are unaffected.Why
Phase D2.1 — per-instance harnesses (Tier B local, Tier C cloud) need filesystem isolation between vaults so multi-tenant signals never co-mingle. The vault dir is the most security-relevant place to scope; the cloud-mirror state file (PR D) follows.
Changes
extensions/memory-wiki/src/config.ts:INSTANCE_ID_PATTERN+normalizeInstanceId()— local copy of the same regex used bysrc/config/zod-schema.ts(kept local because memory-wiki doesn't import fromsrc/config/*).resolveDefaultMemoryWikiVaultPath(homedir, instanceId?)— appends{instanceId}ormain.resolveMemoryWikiConfig(config, { homedir, instanceId })— accepts the new option.extensions/memory-wiki/index.ts+cli-metadata.ts+src/cli.ts: threadappConfig.instanceIdthrough to the resolver.extensions/memory-wiki/src/config.test.ts: 7 new tests (vault scoping happy paths + path-traversal/empty/slash fallback tomain/).Path-traversal hardening
Inputs like
"../evil","has/slash","", or anything not matching[A-Za-z0-9_-]{1,128}fall back tomain/rather than scoping into a malicious dir. Verified by tests.Stacked PR
Stacked on #11. Once #11 merges, GitHub auto-rebases this onto
main. Orthogonal to #10 (canon-kind indexing).Test plan
pnpm vitest run extensions/memory-wiki/src/config.test.ts— 11 tests pass🤖 Generated with Claude Code
Anvil Handoff
appConfig.instanceIdintoresolveMemoryWikiConfigandresolveDefaultMemoryWikiVaultPath. Vault becomes~/.openclaw/wiki/{instanceId}/; falls back tomain/when unset or invalid. Path-traversal inputs (../evil,has/slash,"", anything not matching the regex) safely fall back tomain/. Stacked on feat(config): top-level instanceId field (Phase D2.1 foundation) #11. Orthogonal to open feat(memory-wiki): index canon/ directory in bridge #10 (canon-kind indexing) — verified zero file overlap.extensions/memory-wiki/cli-metadata.ts,extensions/memory-wiki/index.ts,extensions/memory-wiki/src/cli.ts,extensions/memory-wiki/src/config.ts,extensions/memory-wiki/src/config.test.tspnpm vitest run extensions/memory-wiki/src/config.test.ts→ 11 passed (7 new covering vault scoping happy paths + path-traversal fallback). Pre-commit green.~/.openclaw/wiki/main/will keep using it (sinceinstanceIddefaults unset); flippinginstanceIdlater creates a freshwiki/{instanceId}/and orphans the previous content. (2)INSTANCE_ID_PATTERNregex is a local copy of the one in feat(config): top-level instanceId field (Phase D2.1 foundation) #11'szod-schema.ts— drift risk. (3) Explicitvault.pathconfig override beats the newinstanceIdscoping; the documented precedence isn't surfaced inschema.help.ts.resolveMemoryWikiConfigto confirmappConfig.instanceIdis threaded everywhere (the PR touchescli-metadata.ts,index.ts,src/cli.ts— anywhere else?). Verify the path-traversal test set covers all variants the regex would reject (Unicode, leading.,null,Symbol()). Check whether thevault.pathoverride +instanceIdinteraction needs documentation inschema.help.ts.