dsh-env-manager-plugin 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +274 -250
  3. package/client.js +2581 -2581
  4. package/cordis.patch.yml +4 -4
  5. package/docs/00-project/current-state.md +32 -6
  6. package/docs/00-project/glossary.md +215 -215
  7. package/docs/00-project/project-brief.md +114 -114
  8. package/docs/00-project/roadmap.md +89 -89
  9. package/docs/01-architecture/DSH_Environment_Service_Memory_Skill_Brainstorm.md +493 -493
  10. package/docs/01-architecture/api-verification.md +416 -416
  11. package/docs/01-architecture/architecture-overview.md +222 -222
  12. package/docs/01-architecture/data-model.md +930 -930
  13. package/docs/01-architecture/decisions/ADR-0001-plugin-as-bundle.md +29 -29
  14. package/docs/01-architecture/decisions/ADR-0002-file-based-storage.md +25 -25
  15. package/docs/01-architecture/decisions/ADR-0003-skill-router-over-search.md +25 -25
  16. package/docs/01-architecture/decisions/ADR-0004-typescript-host-js-client.md +31 -31
  17. package/docs/01-architecture/decisions/ADR-0005-layered-rule-resolution.md +36 -36
  18. package/docs/01-architecture/decisions/ADR-0006-credentials-as-references.md +30 -30
  19. package/docs/01-architecture/decisions/ADR-0007-session-scoped-default-environment.md +28 -28
  20. package/docs/01-architecture/decisions/ADR-0008-memory-bridge-not-second-store.md +31 -31
  21. package/docs/01-architecture/decisions/ADR-0009-client-host-http-transport.md +87 -87
  22. package/docs/01-architecture/decisions/ADR-0010-environment-plane-model.md +87 -87
  23. package/docs/01-architecture/decisions/ADR-0011-k8s-node-execution-model.md +92 -92
  24. package/docs/01-architecture/design.md +666 -666
  25. package/docs/01-architecture/detailed-design.md +961 -961
  26. package/docs/01-architecture/implementation-plan.md +323 -323
  27. package/docs/01-architecture/module-boundaries.md +306 -306
  28. package/docs/01-architecture/security-model.md +227 -227
  29. package/docs/01-architecture/storage-contract.md +224 -224
  30. package/docs/01-architecture/tool-contract.md +438 -438
  31. package/docs/01-architecture/ui-design.md +587 -587
  32. package/docs/02-harness/agent-behavior.md +36 -36
  33. package/docs/02-harness/change-snapshot-policy.md +29 -29
  34. package/docs/02-harness/client-ui-integration.md +110 -110
  35. package/docs/02-harness/context-policy.md +43 -43
  36. package/docs/02-harness/harness-standard.md +91 -91
  37. package/docs/02-harness/task-execution-policy.md +26 -26
  38. package/docs/02-harness/verification-policy.md +97 -97
  39. package/docs/03-openspec/archive-rule.md +25 -25
  40. package/docs/03-openspec/bugfix-rule.md +30 -30
  41. package/docs/03-openspec/design-rule.md +33 -33
  42. package/docs/03-openspec/openspec-usage-guide.md +31 -31
  43. package/docs/03-openspec/proposal-rule.md +70 -70
  44. package/docs/03-openspec/spec-rule.md +33 -33
  45. package/docs/03-openspec/tasks-rule.md +31 -31
  46. package/docs/04-development/coding-style.md +67 -67
  47. package/docs/04-development/dependency-policy.md +43 -43
  48. package/docs/04-development/development-guide.md +85 -85
  49. package/docs/04-development/directory-convention.md +105 -105
  50. package/docs/04-development/local-run-guide.md +61 -55
  51. package/docs/04-development/testing-guide.md +102 -102
  52. package/docs/05-domain/deployment-template.md +76 -76
  53. package/docs/05-domain/environment-template.md +165 -165
  54. package/docs/05-domain/operation-binding-template.md +55 -55
  55. package/docs/05-domain/operation-record-template.md +55 -55
  56. package/docs/05-domain/prompt-template.md +90 -90
  57. package/docs/05-domain/rule-template.md +73 -73
  58. package/docs/05-domain/service-template.md +39 -39
  59. package/docs/06-operations/deployment-guide.md +54 -54
  60. package/docs/06-operations/release.md +198 -188
  61. package/docs/06-operations/security-policy.md +53 -53
  62. package/docs/06-operations/troubleshooting.md +141 -91
  63. package/docs/07-templates/adr-template.md +21 -21
  64. package/docs/07-templates/bugfix-template.md +11 -11
  65. package/docs/07-templates/case-template.md +15 -15
  66. package/docs/07-templates/design-template.md +29 -29
  67. package/docs/07-templates/proposal-template.md +19 -19
  68. package/docs/07-templates/spec-template.md +15 -15
  69. package/docs/07-templates/tasks-template.md +12 -12
  70. package/docs/99-archive/README.md +13 -13
  71. package/docs/README.md +142 -142
  72. package/icon.svg +4 -4
  73. package/index.js +31 -8
  74. package/lib/app/app.d.ts +1 -1
  75. package/lib/app/app.js +4 -1
  76. package/lib/app/app.js.map +1 -1
  77. package/lib/skill.js +37 -37
  78. package/locale/en.json +6 -6
  79. package/locale/zh.json +6 -6
  80. package/package.json +101 -99
  81. package/scripts/repair-profile.mjs +141 -0
@@ -1,227 +1,227 @@
1
- # Security Model (V1)
2
-
3
- Status: normative for V1.
4
-
5
- The plugin manages internal network topology and may describe production systems. This document defines the security boundaries and the controls required by V1.
6
-
7
- Related: [AGENTS.md](../../AGENTS.md) §3, [security-policy.md](../06-operations/security-policy.md), [design.md](./design.md) §12, [data-model.md](./data-model.md).
8
-
9
- ---
10
-
11
- ## 1. Assets
12
-
13
- | Asset | Sensitivity | Where it lives |
14
- |---|---|---|
15
- | Hostnames, IPs, internal URLs | medium | registry YAML |
16
- | Service Git URLs | low–medium | registry YAML |
17
- | Deployment topology | medium | registry YAML |
18
- | Credential references | low | registry YAML |
19
- | Credential values | high | DSH credential service / external vault — **never here** |
20
- | Operation history | medium | memory plugin (P1) |
21
- | Skill bindings and policies | high (execution routing) | registry YAML |
22
-
23
- ---
24
-
25
- ## 2. Trust boundaries
26
-
27
- ```text
28
- Browser (Client half) ──HTTP──▶ Host transport ──▶ app ──files──▶ plugin data dir
29
- │
30
- Agent/model ──tools──▶ Host tools ────┤
31
- ├──describe──▶ DSH credential service
32
- ├──request───▶ DSH approval service
33
- └──lookup────▶ DSH Skill registry
34
- ```
35
-
36
- Two untrusted input paths exist: the model through tools, and the browser page through
37
- the local HTTP route. Registry content is user-maintained and semi-trusted. The DSH
38
- credential service is the only component allowed to hold secret values.
39
-
40
- ---
41
-
42
- ## 3. Credential handling
43
-
44
- ### 3.1 Rules
45
-
46
- 1. Registry records store only `credentialRef` strings.
47
- 2. The Host calls `ctx.credentials.describe(ref)` and keeps only `{ configured, source?, writable }`.
48
- 3. The Host never calls `ctx.credentials.resolve(ref)` and never forwards a resolved value to a tool result, diagnostic or log.
49
- 4. Tool and HTTP outputs contain `{ ref, configured, source }` only.
50
- 5. `credentialRef` values are validated against the credential reference pattern if one exists; otherwise a conservative pattern (`^[A-Za-z0-9._:/-]{1,200}$`) is applied.
51
- 6. Host accounts and login records follow the same rule: `Host.accounts[].credentialRef` is a
52
- reference, and `LoginRecord` stores username, time, source and result only. A web login
53
- `loginUrl` is configuration, not a secret; it must be an absolute `http(s)` URL. Password,
54
- private-key, token and session-recording fields are not part of the schema.
55
- 7. The guided environment form may collect a password transiently. It sends the value
56
- once to `credential`; the Host calls `ctx.credentials.set(ref, value)` and returns only
57
- `{ ref, configured }`. The value is never written to YAML, never logged and never
58
- returned. The Host still never calls `resolve`.
59
- 8. Credential writes are restricted to refs matching
60
- `env-manager/<environmentId>/<accountId>` so the form cannot overwrite an ambient
61
- credential such as `OPENAI_API_KEY`.
62
-
63
- ### 3.2 Threat: exfiltration through tool output
64
-
65
- Mitigation: a single formatting layer for tool results strips any field named `value`, `secret`, `password`, `token`, `privateKey` and similar, even if a future module accidentally adds one. This is defense in depth, not a replacement for rule 3.
66
-
67
- ### 3.3 Threat: credential reference confusion
68
-
69
- A user may point a production deployment at a test credential. V1 cannot detect this; the result reports `configured: true` without revealing which secret it is. Operational review is required; this is documented as a residual risk.
70
-
71
- ### 3.4 Threat: password exposure while adding or editing a node or account
72
-
73
- The add/edit node form and the add/edit account form optionally hold a login password in the
74
- browser input and send it in the same-origin JSON request. Shell creation and batch import
75
- collect no password.
76
- Mitigations:
77
-
78
- - the route is localhost-only, requires the custom request header, validates origin and
79
- sends `cache-control: no-store`;
80
- - the Host forwards the value directly to `ctx.credentials.set` and does not log the
81
- request body or the value;
82
- - the response contains only the ref and `configured`, never the value;
83
- - the generated YAML is checked by tests to contain the ref only.
84
-
85
- A compromised same-origin page could still submit a credential write while the user is
86
- present; this is accepted for a local single-user tool and documented as a residual risk.
87
- Credential deletion is restricted to the same `env-manager/` namespace.
88
-
89
- ### 3.5 Command access is metadata, not authorization
90
-
91
- `Host.access` records that `ssh`, `kubectl` or `docker` exists on a machine; it does not
92
- grant permission to run anything. V1 has no remote execution path, so a declared method
93
- cannot be used to open a shell, call Kubernetes or run `docker exec` through this plugin.
94
- A future execution adapter must still apply the operation binding's approval policy,
95
- production checks and credential resolution. `Host.kind` and `Cluster.topology` are also
96
- descriptive: they do not prove cluster membership or command availability. Do not treat a
97
- `pod-host` badge as permission to run `docker exec` on a Pod.
98
-
99
- ---
100
-
101
- ## 4. Approval and production policy
102
-
103
- ### 4.1 Operation routing
104
-
105
- - `policy.requiresApproval` defaults to `true` for write operations.
106
- - `policy.allowProduction` defaults to `false`.
107
- - When `environmentCategory === 'production'` and `allowProduction !== true`, the router fails with `POLICY_DENIED`.
108
- - The router does not execute anything; it returns the policy for the executing Skill.
109
-
110
- ### 4.2 Management writes
111
-
112
- Tool writes (`env_save` / `env_delete`) request approval through `ctx.approval` when the write affects a production environment:
113
-
114
- - creating/updating an environment with `category: production`;
115
- - creating/updating a deployment or operation binding whose environment is production;
116
- - deleting any environment, deployment or binding that resolves to production.
117
-
118
- Denied approval returns `POLICY_DENIED`; nothing is written. An approval outcome other
119
- than `allowed-once` (`rejected`, `cancelled`, `unavailable`) denies.
120
-
121
- UI writes (`record.save` / `record.remove`) run with actor `'ui'`:
122
-
123
- - production saves are denied unless `writePolicy.allowUiProductionWrites` is true;
124
- - delete requires `confirm: true` and a second, explicit confirmation in the panel;
125
- - the UI never sends an approval request (it has no agent); it is policy-gated instead.
126
-
127
- ### 4.3 Local HTTP route
128
-
129
- `POST /env-manager/api` is reachable only with:
130
-
131
- - `x-env-manager-request: 1`;
132
- - `Content-Type: application/json`;
133
- - an `Origin` equal to `ctx.webServer.getOrigin()` when the header is present;
134
- - a body no larger than 2 MiB.
135
-
136
- No CORS headers are sent, so a cross-origin page cannot preflight the custom header.
137
- The route reads no cookie and no credential. It returns only registry data that a
138
- `env_get`/`env_list` call could also return, plus derived context.
139
-
140
- ### 4.4 Threat: approval bypass
141
-
142
- A caller could edit YAML files directly, outside the tools. V1 cannot prevent this; file access is governed by the DSH sandbox and OS permissions. The design documents this as a deliberate boundary: the plugin is a context manager, not a policy enforcement point for the filesystem.
143
-
144
- ---
145
-
146
- ## 5. Rule template safety
147
-
148
- Controls:
149
-
150
- 1. Interpolation only — no function calls, operators, conditionals or shell.
151
- 2. No environment variable access unless a future ADR explicitly allows named variables.
152
- 3. Undefined references are errors.
153
- 4. Cyclic references are errors with the cycle path.
154
- 5. Resolved paths are rejected if any segment is `..`.
155
- 6. Resolved values are not executed, only returned.
156
- 7. Template syntax is restricted to `${identifier(.identifier)*}` with a 2048-character
157
- cap; anything else is `RULE_TEMPLATE_INVALID`.
158
-
159
- Threat: a malicious rule profile could point at sensitive directories to make the Agent read them later. Mitigation: the plugin never reads the resolved paths itself in V1; it only returns them. Future adapters that read paths must add their own path allowlist.
160
-
161
- ---
162
-
163
- ## 6. Data minimization and redaction
164
-
165
- Before emitting diagnostics, logs or P1 operation records:
166
-
167
- - Replace values matching common secret patterns: `password=`, `token=`, `Authorization:`, private key blocks, `kubeconfig` blocks.
168
- - Truncate command output and error text to a bounded length.
169
- - Keep only opaque evidence references, not raw evidence.
170
-
171
- The redaction function is shared and unit-tested.
172
-
173
- ---
174
-
175
- ## 7. Scope isolation
176
-
177
- - Registry data is profile-global and read-only for sessions.
178
- - Session default environment is per session; one session cannot change another's.
179
- - Tools accept explicit ids and do not implicitly broaden scope.
180
- - P1 memory queries always carry environment/service/deployment scope; a single-environment result must not be presented as a global rule.
181
-
182
- ---
183
-
184
- ## 8. Fail-safe behavior
185
-
186
- | Condition | Behavior |
187
- |---|---|
188
- | Two same-level bindings | `BINDING_CONFLICT`, no selection |
189
- | Skill missing or mismatched | `SKILL_UNAVAILABLE`, no fallback |
190
- | Skill registry unreachable | resolve with `available: 'unknown'` + warning |
191
- | Production without `allowProduction` | `POLICY_DENIED` |
192
- | Missing credential | `configured: false`, warning; operation still resolves |
193
- | Broken reference | error from `env_validate`, skipped on read |
194
- | Invalid record | skipped on read with diagnostic |
195
- | Approval denied | `POLICY_DENIED`, no write |
196
- | UI production write without `allowUiProductionWrites` | `POLICY_DENIED`, no write |
197
- | Missing transport header or foreign origin | `FORBIDDEN`, no routing |
198
- | Body over 2 MiB | 413, no parsing |
199
- | Record cap exceeded | `RECORD_LIMIT_EXCEEDED`, no write |
200
-
201
- ---
202
-
203
- ## 9. Audit
204
-
205
- V1 does not maintain an audit log of its own. P1 operation records become the audit trail through the memory bridge.
206
-
207
- Requirements for P1:
208
-
209
- - every write-class operation record includes `sessionId`, target ids, outcome and evidence refs;
210
- - summaries are redacted;
211
- - records are append-only from the plugin's perspective;
212
- - evidence retention is bounded.
213
-
214
- ---
215
-
216
- ## 10. Residual risks
217
-
218
- 1. YAML editing outside the plugin bypasses approval.
219
- 2. Credential reference swaps are undetectable without a vault policy.
220
- 3. A correct Skill binding can still be used for an unsafe action; policy is necessary but not sufficient.
221
- 4. Internal hostnames/IPs in registry files may leak if the repository or data directory is shared carelessly. Registry data must not be committed to Git.
222
- 5. Operation history in P1 may capture sensitive command text if redaction is incomplete.
223
- 6. The local HTTP route trusts the page origin and a custom header; a script running in
224
- the DSH page (extension, devtools) can call it. It can read registry data the user
225
- can already see, and write only as the `ui` actor under §4.2.
226
- 7. `ctx.fs.watch` is not used in V1, so an external edit is picked up on the next
227
- request rather than immediately; a stale resolve cannot outlive one request.
1
+ # Security Model (V1)
2
+
3
+ Status: normative for V1.
4
+
5
+ The plugin manages internal network topology and may describe production systems. This document defines the security boundaries and the controls required by V1.
6
+
7
+ Related: [AGENTS.md](../../AGENTS.md) §3, [security-policy.md](../06-operations/security-policy.md), [design.md](./design.md) §12, [data-model.md](./data-model.md).
8
+
9
+ ---
10
+
11
+ ## 1. Assets
12
+
13
+ | Asset | Sensitivity | Where it lives |
14
+ |---|---|---|
15
+ | Hostnames, IPs, internal URLs | medium | registry YAML |
16
+ | Service Git URLs | low–medium | registry YAML |
17
+ | Deployment topology | medium | registry YAML |
18
+ | Credential references | low | registry YAML |
19
+ | Credential values | high | DSH credential service / external vault — **never here** |
20
+ | Operation history | medium | memory plugin (P1) |
21
+ | Skill bindings and policies | high (execution routing) | registry YAML |
22
+
23
+ ---
24
+
25
+ ## 2. Trust boundaries
26
+
27
+ ```text
28
+ Browser (Client half) ──HTTP──▶ Host transport ──▶ app ──files──▶ plugin data dir
29
+ │
30
+ Agent/model ──tools──▶ Host tools ────┤
31
+ ├──describe──▶ DSH credential service
32
+ ├──request───▶ DSH approval service
33
+ └──lookup────▶ DSH Skill registry
34
+ ```
35
+
36
+ Two untrusted input paths exist: the model through tools, and the browser page through
37
+ the local HTTP route. Registry content is user-maintained and semi-trusted. The DSH
38
+ credential service is the only component allowed to hold secret values.
39
+
40
+ ---
41
+
42
+ ## 3. Credential handling
43
+
44
+ ### 3.1 Rules
45
+
46
+ 1. Registry records store only `credentialRef` strings.
47
+ 2. The Host calls `ctx.credentials.describe(ref)` and keeps only `{ configured, source?, writable }`.
48
+ 3. The Host never calls `ctx.credentials.resolve(ref)` and never forwards a resolved value to a tool result, diagnostic or log.
49
+ 4. Tool and HTTP outputs contain `{ ref, configured, source }` only.
50
+ 5. `credentialRef` values are validated against the credential reference pattern if one exists; otherwise a conservative pattern (`^[A-Za-z0-9._:/-]{1,200}$`) is applied.
51
+ 6. Host accounts and login records follow the same rule: `Host.accounts[].credentialRef` is a
52
+ reference, and `LoginRecord` stores username, time, source and result only. A web login
53
+ `loginUrl` is configuration, not a secret; it must be an absolute `http(s)` URL. Password,
54
+ private-key, token and session-recording fields are not part of the schema.
55
+ 7. The guided environment form may collect a password transiently. It sends the value
56
+ once to `credential`; the Host calls `ctx.credentials.set(ref, value)` and returns only
57
+ `{ ref, configured }`. The value is never written to YAML, never logged and never
58
+ returned. The Host still never calls `resolve`.
59
+ 8. Credential writes are restricted to refs matching
60
+ `env-manager/<environmentId>/<accountId>` so the form cannot overwrite an ambient
61
+ credential such as `OPENAI_API_KEY`.
62
+
63
+ ### 3.2 Threat: exfiltration through tool output
64
+
65
+ Mitigation: a single formatting layer for tool results strips any field named `value`, `secret`, `password`, `token`, `privateKey` and similar, even if a future module accidentally adds one. This is defense in depth, not a replacement for rule 3.
66
+
67
+ ### 3.3 Threat: credential reference confusion
68
+
69
+ A user may point a production deployment at a test credential. V1 cannot detect this; the result reports `configured: true` without revealing which secret it is. Operational review is required; this is documented as a residual risk.
70
+
71
+ ### 3.4 Threat: password exposure while adding or editing a node or account
72
+
73
+ The add/edit node form and the add/edit account form optionally hold a login password in the
74
+ browser input and send it in the same-origin JSON request. Shell creation and batch import
75
+ collect no password.
76
+ Mitigations:
77
+
78
+ - the route is localhost-only, requires the custom request header, validates origin and
79
+ sends `cache-control: no-store`;
80
+ - the Host forwards the value directly to `ctx.credentials.set` and does not log the
81
+ request body or the value;
82
+ - the response contains only the ref and `configured`, never the value;
83
+ - the generated YAML is checked by tests to contain the ref only.
84
+
85
+ A compromised same-origin page could still submit a credential write while the user is
86
+ present; this is accepted for a local single-user tool and documented as a residual risk.
87
+ Credential deletion is restricted to the same `env-manager/` namespace.
88
+
89
+ ### 3.5 Command access is metadata, not authorization
90
+
91
+ `Host.access` records that `ssh`, `kubectl` or `docker` exists on a machine; it does not
92
+ grant permission to run anything. V1 has no remote execution path, so a declared method
93
+ cannot be used to open a shell, call Kubernetes or run `docker exec` through this plugin.
94
+ A future execution adapter must still apply the operation binding's approval policy,
95
+ production checks and credential resolution. `Host.kind` and `Cluster.topology` are also
96
+ descriptive: they do not prove cluster membership or command availability. Do not treat a
97
+ `pod-host` badge as permission to run `docker exec` on a Pod.
98
+
99
+ ---
100
+
101
+ ## 4. Approval and production policy
102
+
103
+ ### 4.1 Operation routing
104
+
105
+ - `policy.requiresApproval` defaults to `true` for write operations.
106
+ - `policy.allowProduction` defaults to `false`.
107
+ - When `environmentCategory === 'production'` and `allowProduction !== true`, the router fails with `POLICY_DENIED`.
108
+ - The router does not execute anything; it returns the policy for the executing Skill.
109
+
110
+ ### 4.2 Management writes
111
+
112
+ Tool writes (`env_save` / `env_delete`) request approval through `ctx.approval` when the write affects a production environment:
113
+
114
+ - creating/updating an environment with `category: production`;
115
+ - creating/updating a deployment or operation binding whose environment is production;
116
+ - deleting any environment, deployment or binding that resolves to production.
117
+
118
+ Denied approval returns `POLICY_DENIED`; nothing is written. An approval outcome other
119
+ than `allowed-once` (`rejected`, `cancelled`, `unavailable`) denies.
120
+
121
+ UI writes (`record.save` / `record.remove`) run with actor `'ui'`:
122
+
123
+ - production saves are denied unless `writePolicy.allowUiProductionWrites` is true;
124
+ - delete requires `confirm: true` and a second, explicit confirmation in the panel;
125
+ - the UI never sends an approval request (it has no agent); it is policy-gated instead.
126
+
127
+ ### 4.3 Local HTTP route
128
+
129
+ `POST /env-manager/api` is reachable only with:
130
+
131
+ - `x-env-manager-request: 1`;
132
+ - `Content-Type: application/json`;
133
+ - an `Origin` equal to `ctx.webServer.getOrigin()` when the header is present;
134
+ - a body no larger than 2 MiB.
135
+
136
+ No CORS headers are sent, so a cross-origin page cannot preflight the custom header.
137
+ The route reads no cookie and no credential. It returns only registry data that a
138
+ `env_get`/`env_list` call could also return, plus derived context.
139
+
140
+ ### 4.4 Threat: approval bypass
141
+
142
+ A caller could edit YAML files directly, outside the tools. V1 cannot prevent this; file access is governed by the DSH sandbox and OS permissions. The design documents this as a deliberate boundary: the plugin is a context manager, not a policy enforcement point for the filesystem.
143
+
144
+ ---
145
+
146
+ ## 5. Rule template safety
147
+
148
+ Controls:
149
+
150
+ 1. Interpolation only — no function calls, operators, conditionals or shell.
151
+ 2. No environment variable access unless a future ADR explicitly allows named variables.
152
+ 3. Undefined references are errors.
153
+ 4. Cyclic references are errors with the cycle path.
154
+ 5. Resolved paths are rejected if any segment is `..`.
155
+ 6. Resolved values are not executed, only returned.
156
+ 7. Template syntax is restricted to `${identifier(.identifier)*}` with a 2048-character
157
+ cap; anything else is `RULE_TEMPLATE_INVALID`.
158
+
159
+ Threat: a malicious rule profile could point at sensitive directories to make the Agent read them later. Mitigation: the plugin never reads the resolved paths itself in V1; it only returns them. Future adapters that read paths must add their own path allowlist.
160
+
161
+ ---
162
+
163
+ ## 6. Data minimization and redaction
164
+
165
+ Before emitting diagnostics, logs or P1 operation records:
166
+
167
+ - Replace values matching common secret patterns: `password=`, `token=`, `Authorization:`, private key blocks, `kubeconfig` blocks.
168
+ - Truncate command output and error text to a bounded length.
169
+ - Keep only opaque evidence references, not raw evidence.
170
+
171
+ The redaction function is shared and unit-tested.
172
+
173
+ ---
174
+
175
+ ## 7. Scope isolation
176
+
177
+ - Registry data is profile-global and read-only for sessions.
178
+ - Session default environment is per session; one session cannot change another's.
179
+ - Tools accept explicit ids and do not implicitly broaden scope.
180
+ - P1 memory queries always carry environment/service/deployment scope; a single-environment result must not be presented as a global rule.
181
+
182
+ ---
183
+
184
+ ## 8. Fail-safe behavior
185
+
186
+ | Condition | Behavior |
187
+ |---|---|
188
+ | Two same-level bindings | `BINDING_CONFLICT`, no selection |
189
+ | Skill missing or mismatched | `SKILL_UNAVAILABLE`, no fallback |
190
+ | Skill registry unreachable | resolve with `available: 'unknown'` + warning |
191
+ | Production without `allowProduction` | `POLICY_DENIED` |
192
+ | Missing credential | `configured: false`, warning; operation still resolves |
193
+ | Broken reference | error from `env_validate`, skipped on read |
194
+ | Invalid record | skipped on read with diagnostic |
195
+ | Approval denied | `POLICY_DENIED`, no write |
196
+ | UI production write without `allowUiProductionWrites` | `POLICY_DENIED`, no write |
197
+ | Missing transport header or foreign origin | `FORBIDDEN`, no routing |
198
+ | Body over 2 MiB | 413, no parsing |
199
+ | Record cap exceeded | `RECORD_LIMIT_EXCEEDED`, no write |
200
+
201
+ ---
202
+
203
+ ## 9. Audit
204
+
205
+ V1 does not maintain an audit log of its own. P1 operation records become the audit trail through the memory bridge.
206
+
207
+ Requirements for P1:
208
+
209
+ - every write-class operation record includes `sessionId`, target ids, outcome and evidence refs;
210
+ - summaries are redacted;
211
+ - records are append-only from the plugin's perspective;
212
+ - evidence retention is bounded.
213
+
214
+ ---
215
+
216
+ ## 10. Residual risks
217
+
218
+ 1. YAML editing outside the plugin bypasses approval.
219
+ 2. Credential reference swaps are undetectable without a vault policy.
220
+ 3. A correct Skill binding can still be used for an unsafe action; policy is necessary but not sufficient.
221
+ 4. Internal hostnames/IPs in registry files may leak if the repository or data directory is shared carelessly. Registry data must not be committed to Git.
222
+ 5. Operation history in P1 may capture sensitive command text if redaction is incomplete.
223
+ 6. The local HTTP route trusts the page origin and a custom header; a script running in
224
+ the DSH page (extension, devtools) can call it. It can read registry data the user
225
+ can already see, and write only as the `ui` actor under §4.2.
226
+ 7. `ctx.fs.watch` is not used in V1, so an external edit is picked up on the next
227
+ request rather than immediately; a stale resolve cannot outlive one request.