dsh-plugin-inspector 0.8.0 → 0.9.0

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.
package/README.md CHANGED
@@ -79,6 +79,20 @@ Findings are tiered by how much you should trust them:
79
79
 
80
80
  [Every check, by tier →](https://charlotten7.github.io/dsh-plugin-inspector/checks.html)
81
81
 
82
+ ## What it deliberately does not flag
83
+
84
+ A `critical` is only worth reading if it is rare, so the two tables that decide one — the core rows
85
+ A2 treats as security-relevant, and the capability seams A23, B1 and B15 do — are kept small on a
86
+ stated rule: a row is in when disabling it **fails open** or **silently removes evidence**. A row
87
+ that fails closed when removed is out, however security-adjacent its name reads, and so is one whose
88
+ absence takes a feature away and grants nothing.
89
+
90
+ The rows checked against that rule and kept out are named with their reasons, so you can tell "we
91
+ checked and it does not qualify" from "we never looked". Excluded is not unreported: disabling any
92
+ core row is still an A3 finding.
93
+
94
+ [What is deliberately not a finding →](https://charlotten7.github.io/dsh-plugin-inspector/checks.html#what-is-deliberately-not-a-finding)
95
+
82
96
  ## The ceiling
83
97
 
84
98
  **This is not a malware scanner and it cannot be one.** Capability is decidable from source;
package/lib/knowledge.js CHANGED
@@ -203,7 +203,16 @@ export const CORE_ROW_IDS = new Set(CORE_ROWS.keys());
203
203
  * Disabling or reconfiguring one of these from a third-party patch layer is
204
204
  * the highest-value finding this tool produces, and it is plain YAML.
205
205
  *
206
- * Each entry names what stops holding when the row stops running.
206
+ * Each entry names what stops holding when the row stops running. Membership
207
+ * needs one of two properties: disabling the row **fails open**, so the agent
208
+ * may afterwards do something it could not before, or it **removes evidence**
209
+ * without saying so, leaving nothing to reconstruct what the agent did. A row
210
+ * that fails closed on removal, or whose absence only takes a feature away, is
211
+ * not a member however security-adjacent its name reads.
212
+ *
213
+ * The rows examined against that rule and kept out are listed with their
214
+ * reasons under "What is deliberately not a finding" in `docs/checks.md`, so a
215
+ * reader can tell a considered exclusion from a row nobody looked at.
207
216
  */
208
217
  export const SECURITY_ROW_IDS = new Map([
209
218
  ['approval', 'user approval prompts for tool calls'],
@@ -244,7 +253,12 @@ export const SEAM_KEYS = new Set([
244
253
  'webhookRuntime', 'webServer', 'workflowEngine', 'workspaceController', 'workspaceRegistry',
245
254
  ]);
246
255
  /**
247
- * The subset of {@link SEAM_KEYS} whose replacement removes a constraint.
256
+ * The subset of {@link SEAM_KEYS} whose replacement either removes a constraint
257
+ * or takes over the record by which one could be checked afterwards. Most
258
+ * members are the first kind — `approval`, `sandbox`, `credentials`. The set
259
+ * already holds two of the second, `sessionPersistence` and `sessionTelemetry`,
260
+ * and each entry below says which kind it is rather than borrowing the other's
261
+ * sentence.
248
262
  *
249
263
  * `authorization` is the registry of flows that obtain a credential through a
250
264
  * conversation with the user, so providing it means owning that conversation.
@@ -296,6 +310,31 @@ export const SEAM_KEYS = new Set([
296
310
  * (`@deepseek-ai/dsh-webhook/lib/types/session.js:94`, `:117`, `:120`).
297
311
  * Providing it picks the approval and sandbox preset for an agent started by
298
312
  * a remote delivery with no user present.
313
+ * - `inspector` is the second kind, and the only member graded from the
314
+ * catalogue rather than from an implementation. The catalogue declares it as
315
+ * the façade over the realm's source publisher, with `publish(topic, payload,
316
+ * monotonicMs?)` and a read-only `CordisRuntimeTreeReader`
317
+ * (`@deepseek-ai/dsh-tool-cordis/lib/index.js:1558`, the two method
318
+ * signatures at `:1562` and `:1579`). Providing it
319
+ * takes no decision away from anyone: nothing is gated on an observation, and
320
+ * on that ground the key does not belong beside `approval`. What it takes is
321
+ * the position observations pass through. A substituted publisher chooses
322
+ * which topics reach the carrier and what payload each one carries, so it can
323
+ * withhold the record of something that happened or publish one for something
324
+ * that did not, and a consumer downstream cannot tell either from a quiet
325
+ * system. That is the property this set already recognises in
326
+ * `sessionPersistence` and `sessionTelemetry`.
327
+ *
328
+ * No implementation exists to displace. In `0.1.2-rc.1` the key is declared
329
+ * once and used nowhere: `'inspector'` as a string literal occurs exactly
330
+ * once across the 224 `@deepseek-ai` packages in the installed tree — that
331
+ * catalogue entry — no file reads `ctx.inspector`, and `InspectorJsonValue`
332
+ * and `CordisRuntimeTreeReader` appear only in that same bundle. So a package
333
+ * providing `inspector` in this release displaces nothing and reaches nothing
334
+ * it could not reach under a name of its own. This entry grades what the
335
+ * catalogue says the key is for, not code that runs today, and it is the one
336
+ * entry a release that ships a publisher or a consumer should settle again
337
+ * against them.
299
338
  *
300
339
  * Excluded:
301
340
  * - `workspaceController` forwards `request.path` to
@@ -327,20 +366,12 @@ export const SEAM_KEYS = new Set([
327
366
  * field colliding with the base request, so `messages`, `tools` and `model`
328
367
  * are not writable through it. The constraint is in the adapter, not the
329
368
  * registry the substitution replaces.
330
- * - `inspector` is declared by the catalogue and implemented by no shipped
331
- * package: in `0.1.2-rc.1` the key, `InspectorJsonValue` and
332
- * `CordisRuntimeTreeReader` occur only in
333
- * `@deepseek-ai/dsh-tool-cordis/lib/index.js`, and nothing provides or reads
334
- * `ctx.inspector`. No composed row enforces anything through it, so a
335
- * substitution displaces nothing. This is the one entry decided from the
336
- * catalogue rather than from an implementation; a release that ships one is a
337
- * reason to decide it again.
338
369
  */
339
370
  export const SECURITY_SEAM_KEYS = new Set([
340
371
  'approval', 'authorization', 'sandbox', 'sandboxPolicy', 'permissionPresets', 'credentials',
341
372
  'credentialsController', 'settingsController', 'sessionController', 'webhookRuntime',
342
- 'subprocess', 'shell', 'fs', 'tools', 'agentLoop', 'sessionPersistence', 'sessionTelemetry',
343
- 'invariants',
373
+ 'subprocess', 'shell', 'fs', 'tools', 'agentLoop', 'inspector', 'sessionPersistence',
374
+ 'sessionTelemetry', 'invariants',
344
375
  ]);
345
376
  /**
346
377
  * Waterfall events, from `EVENT_API` in the api-catalog. A listener on one of
@@ -60,7 +60,16 @@ export declare const CORE_ROW_IDS: ReadonlySet<string>;
60
60
  * Disabling or reconfiguring one of these from a third-party patch layer is
61
61
  * the highest-value finding this tool produces, and it is plain YAML.
62
62
  *
63
- * Each entry names what stops holding when the row stops running.
63
+ * Each entry names what stops holding when the row stops running. Membership
64
+ * needs one of two properties: disabling the row **fails open**, so the agent
65
+ * may afterwards do something it could not before, or it **removes evidence**
66
+ * without saying so, leaving nothing to reconstruct what the agent did. A row
67
+ * that fails closed on removal, or whose absence only takes a feature away, is
68
+ * not a member however security-adjacent its name reads.
69
+ *
70
+ * The rows examined against that rule and kept out are listed with their
71
+ * reasons under "What is deliberately not a finding" in `docs/checks.md`, so a
72
+ * reader can tell a considered exclusion from a row nobody looked at.
64
73
  */
65
74
  export declare const SECURITY_ROW_IDS: ReadonlyMap<string, string>;
66
75
  /**
@@ -71,7 +80,12 @@ export declare const SECURITY_ROW_IDS: ReadonlyMap<string, string>;
71
80
  */
72
81
  export declare const SEAM_KEYS: ReadonlySet<string>;
73
82
  /**
74
- * The subset of {@link SEAM_KEYS} whose replacement removes a constraint.
83
+ * The subset of {@link SEAM_KEYS} whose replacement either removes a constraint
84
+ * or takes over the record by which one could be checked afterwards. Most
85
+ * members are the first kind — `approval`, `sandbox`, `credentials`. The set
86
+ * already holds two of the second, `sessionPersistence` and `sessionTelemetry`,
87
+ * and each entry below says which kind it is rather than borrowing the other's
88
+ * sentence.
75
89
  *
76
90
  * `authorization` is the registry of flows that obtain a credential through a
77
91
  * conversation with the user, so providing it means owning that conversation.
@@ -123,6 +137,31 @@ export declare const SEAM_KEYS: ReadonlySet<string>;
123
137
  * (`@deepseek-ai/dsh-webhook/lib/types/session.js:94`, `:117`, `:120`).
124
138
  * Providing it picks the approval and sandbox preset for an agent started by
125
139
  * a remote delivery with no user present.
140
+ * - `inspector` is the second kind, and the only member graded from the
141
+ * catalogue rather than from an implementation. The catalogue declares it as
142
+ * the façade over the realm's source publisher, with `publish(topic, payload,
143
+ * monotonicMs?)` and a read-only `CordisRuntimeTreeReader`
144
+ * (`@deepseek-ai/dsh-tool-cordis/lib/index.js:1558`, the two method
145
+ * signatures at `:1562` and `:1579`). Providing it
146
+ * takes no decision away from anyone: nothing is gated on an observation, and
147
+ * on that ground the key does not belong beside `approval`. What it takes is
148
+ * the position observations pass through. A substituted publisher chooses
149
+ * which topics reach the carrier and what payload each one carries, so it can
150
+ * withhold the record of something that happened or publish one for something
151
+ * that did not, and a consumer downstream cannot tell either from a quiet
152
+ * system. That is the property this set already recognises in
153
+ * `sessionPersistence` and `sessionTelemetry`.
154
+ *
155
+ * No implementation exists to displace. In `0.1.2-rc.1` the key is declared
156
+ * once and used nowhere: `'inspector'` as a string literal occurs exactly
157
+ * once across the 224 `@deepseek-ai` packages in the installed tree — that
158
+ * catalogue entry — no file reads `ctx.inspector`, and `InspectorJsonValue`
159
+ * and `CordisRuntimeTreeReader` appear only in that same bundle. So a package
160
+ * providing `inspector` in this release displaces nothing and reaches nothing
161
+ * it could not reach under a name of its own. This entry grades what the
162
+ * catalogue says the key is for, not code that runs today, and it is the one
163
+ * entry a release that ships a publisher or a consumer should settle again
164
+ * against them.
126
165
  *
127
166
  * Excluded:
128
167
  * - `workspaceController` forwards `request.path` to
@@ -154,14 +193,6 @@ export declare const SEAM_KEYS: ReadonlySet<string>;
154
193
  * field colliding with the base request, so `messages`, `tools` and `model`
155
194
  * are not writable through it. The constraint is in the adapter, not the
156
195
  * registry the substitution replaces.
157
- * - `inspector` is declared by the catalogue and implemented by no shipped
158
- * package: in `0.1.2-rc.1` the key, `InspectorJsonValue` and
159
- * `CordisRuntimeTreeReader` occur only in
160
- * `@deepseek-ai/dsh-tool-cordis/lib/index.js`, and nothing provides or reads
161
- * `ctx.inspector`. No composed row enforces anything through it, so a
162
- * substitution displaces nothing. This is the one entry decided from the
163
- * catalogue rather than from an implementation; a release that ships one is a
164
- * reason to decide it again.
165
196
  */
166
197
  export declare const SECURITY_SEAM_KEYS: ReadonlySet<string>;
167
198
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-inspector",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Know what a DeepSeek Harness plugin does before you install it — static pre-install analysis of a plugin directory or tarball",
5
5
  "license": "MIT",
6
6
  "author": "Ivan Tyshchenko",