@descryy/mcp 0.6.0 → 0.7.1

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 (264) hide show
  1. package/dist/action-handshake.d.ts +8 -75
  2. package/dist/action-handshake.d.ts.map +1 -1
  3. package/dist/action-handshake.js +9 -79
  4. package/dist/action-handshake.js.map +1 -1
  5. package/dist/bin/descry-mcp.d.ts +4 -15
  6. package/dist/bin/descry-mcp.d.ts.map +1 -1
  7. package/dist/bin/descry-mcp.js +12 -42
  8. package/dist/bin/descry-mcp.js.map +1 -1
  9. package/dist/browser/driver.d.ts +121 -224
  10. package/dist/browser/driver.d.ts.map +1 -1
  11. package/dist/browser/driver.js +9 -55
  12. package/dist/browser/driver.js.map +1 -1
  13. package/dist/browser/evidence.d.ts +10 -43
  14. package/dist/browser/evidence.d.ts.map +1 -1
  15. package/dist/browser/evidence.js +20 -54
  16. package/dist/browser/evidence.js.map +1 -1
  17. package/dist/browser/fake-driver.d.ts +12 -19
  18. package/dist/browser/fake-driver.d.ts.map +1 -1
  19. package/dist/browser/fake-driver.js +31 -26
  20. package/dist/browser/fake-driver.js.map +1 -1
  21. package/dist/browser/graph-write.d.ts +4 -45
  22. package/dist/browser/graph-write.d.ts.map +1 -1
  23. package/dist/browser/graph-write.js +8 -53
  24. package/dist/browser/graph-write.js.map +1 -1
  25. package/dist/browser/playwright-driver.d.ts +7 -91
  26. package/dist/browser/playwright-driver.d.ts.map +1 -1
  27. package/dist/browser/playwright-driver.js +59 -197
  28. package/dist/browser/playwright-driver.js.map +1 -1
  29. package/dist/browser/provider.d.ts +5 -34
  30. package/dist/browser/provider.d.ts.map +1 -1
  31. package/dist/browser/provider.js +4 -24
  32. package/dist/browser/provider.js.map +1 -1
  33. package/dist/browser/registry.d.ts +26 -106
  34. package/dist/browser/registry.d.ts.map +1 -1
  35. package/dist/browser/registry.js +20 -77
  36. package/dist/browser/registry.js.map +1 -1
  37. package/dist/browser/scenario-provenance.d.ts +23 -0
  38. package/dist/browser/scenario-provenance.d.ts.map +1 -0
  39. package/dist/browser/scenario-provenance.js +59 -0
  40. package/dist/browser/scenario-provenance.js.map +1 -0
  41. package/dist/browser/scenario-resolve.d.ts +10 -44
  42. package/dist/browser/scenario-resolve.d.ts.map +1 -1
  43. package/dist/browser/scenario-resolve.js +10 -41
  44. package/dist/browser/scenario-resolve.js.map +1 -1
  45. package/dist/browser/scenario-runner.d.ts +12 -70
  46. package/dist/browser/scenario-runner.d.ts.map +1 -1
  47. package/dist/browser/scenario-runner.js +30 -90
  48. package/dist/browser/scenario-runner.js.map +1 -1
  49. package/dist/browser/stack-parser.d.ts +4 -28
  50. package/dist/browser/stack-parser.d.ts.map +1 -1
  51. package/dist/browser/stack-parser.js +12 -39
  52. package/dist/browser/stack-parser.js.map +1 -1
  53. package/dist/browser/tool-support.d.ts +20 -67
  54. package/dist/browser/tool-support.d.ts.map +1 -1
  55. package/dist/browser/tool-support.js +21 -65
  56. package/dist/browser/tool-support.js.map +1 -1
  57. package/dist/browser/url-scheme.d.ts +14 -0
  58. package/dist/browser/url-scheme.d.ts.map +1 -0
  59. package/dist/browser/url-scheme.js +38 -0
  60. package/dist/browser/url-scheme.js.map +1 -0
  61. package/dist/cancellation.d.ts +11 -46
  62. package/dist/cancellation.d.ts.map +1 -1
  63. package/dist/cancellation.js +11 -46
  64. package/dist/cancellation.js.map +1 -1
  65. package/dist/capped.d.ts +9 -33
  66. package/dist/capped.d.ts.map +1 -1
  67. package/dist/capped.js +7 -27
  68. package/dist/capped.js.map +1 -1
  69. package/dist/disclosure-ledger.d.ts +6 -30
  70. package/dist/disclosure-ledger.d.ts.map +1 -1
  71. package/dist/disclosure-ledger.js +4 -26
  72. package/dist/disclosure-ledger.js.map +1 -1
  73. package/dist/index.d.ts +10 -26
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +7 -17
  76. package/dist/index.js.map +1 -1
  77. package/dist/module-trust.d.ts +24 -0
  78. package/dist/module-trust.d.ts.map +1 -0
  79. package/dist/module-trust.js +60 -0
  80. package/dist/module-trust.js.map +1 -0
  81. package/dist/path-confinement.d.ts +31 -0
  82. package/dist/path-confinement.d.ts.map +1 -0
  83. package/dist/path-confinement.js +44 -0
  84. package/dist/path-confinement.js.map +1 -0
  85. package/dist/protocol.d.ts +10 -53
  86. package/dist/protocol.d.ts.map +1 -1
  87. package/dist/protocol.js +14 -60
  88. package/dist/protocol.js.map +1 -1
  89. package/dist/registry.d.ts +37 -58
  90. package/dist/registry.d.ts.map +1 -1
  91. package/dist/registry.js +88 -96
  92. package/dist/registry.js.map +1 -1
  93. package/dist/render.d.ts +89 -13
  94. package/dist/render.d.ts.map +1 -1
  95. package/dist/render.js +111 -16
  96. package/dist/render.js.map +1 -1
  97. package/dist/runtime-registry.d.ts +7 -66
  98. package/dist/runtime-registry.d.ts.map +1 -1
  99. package/dist/runtime-registry.js +39 -114
  100. package/dist/runtime-registry.js.map +1 -1
  101. package/dist/scenarios/index.d.ts +1 -1
  102. package/dist/scenarios/index.d.ts.map +1 -1
  103. package/dist/scenarios/index.js +1 -1
  104. package/dist/scenarios/index.js.map +1 -1
  105. package/dist/scenarios/parse.d.ts +4 -18
  106. package/dist/scenarios/parse.d.ts.map +1 -1
  107. package/dist/scenarios/parse.js +14 -34
  108. package/dist/scenarios/parse.js.map +1 -1
  109. package/dist/scenarios/scenario.d.ts +18 -74
  110. package/dist/scenarios/scenario.d.ts.map +1 -1
  111. package/dist/scenarios/scenario.js +7 -34
  112. package/dist/scenarios/scenario.js.map +1 -1
  113. package/dist/scenarios/storage.d.ts +11 -41
  114. package/dist/scenarios/storage.d.ts.map +1 -1
  115. package/dist/scenarios/storage.js +57 -47
  116. package/dist/scenarios/storage.js.map +1 -1
  117. package/dist/server.d.ts.map +1 -1
  118. package/dist/server.js +69 -19
  119. package/dist/server.js.map +1 -1
  120. package/dist/session.d.ts +90 -259
  121. package/dist/session.d.ts.map +1 -1
  122. package/dist/session.js +136 -250
  123. package/dist/session.js.map +1 -1
  124. package/dist/tools/analyze.d.ts +32 -118
  125. package/dist/tools/analyze.d.ts.map +1 -1
  126. package/dist/tools/analyze.js +65 -186
  127. package/dist/tools/analyze.js.map +1 -1
  128. package/dist/tools/browser-click.d.ts +3 -21
  129. package/dist/tools/browser-click.d.ts.map +1 -1
  130. package/dist/tools/browser-click.js +10 -31
  131. package/dist/tools/browser-click.js.map +1 -1
  132. package/dist/tools/browser-close-session.d.ts +4 -13
  133. package/dist/tools/browser-close-session.d.ts.map +1 -1
  134. package/dist/tools/browser-close-session.js +4 -13
  135. package/dist/tools/browser-close-session.js.map +1 -1
  136. package/dist/tools/browser-fill.d.ts +5 -36
  137. package/dist/tools/browser-fill.d.ts.map +1 -1
  138. package/dist/tools/browser-fill.js +9 -44
  139. package/dist/tools/browser-fill.js.map +1 -1
  140. package/dist/tools/browser-navigate.d.ts +6 -27
  141. package/dist/tools/browser-navigate.d.ts.map +1 -1
  142. package/dist/tools/browser-navigate.js +6 -23
  143. package/dist/tools/browser-navigate.js.map +1 -1
  144. package/dist/tools/browser-run-scenario.d.ts +5 -31
  145. package/dist/tools/browser-run-scenario.d.ts.map +1 -1
  146. package/dist/tools/browser-run-scenario.js +10 -46
  147. package/dist/tools/browser-run-scenario.js.map +1 -1
  148. package/dist/tools/browser-save-scenario.d.ts +3 -28
  149. package/dist/tools/browser-save-scenario.d.ts.map +1 -1
  150. package/dist/tools/browser-save-scenario.js +47 -84
  151. package/dist/tools/browser-save-scenario.js.map +1 -1
  152. package/dist/tools/browser-snapshot.d.ts +6 -39
  153. package/dist/tools/browser-snapshot.d.ts.map +1 -1
  154. package/dist/tools/browser-snapshot.js +4 -31
  155. package/dist/tools/browser-snapshot.js.map +1 -1
  156. package/dist/tools/browser-start-session.d.ts +4 -23
  157. package/dist/tools/browser-start-session.d.ts.map +1 -1
  158. package/dist/tools/browser-start-session.js +145 -56
  159. package/dist/tools/browser-start-session.js.map +1 -1
  160. package/dist/tools/browser-type.d.ts +5 -35
  161. package/dist/tools/browser-type.d.ts.map +1 -1
  162. package/dist/tools/browser-type.js +10 -45
  163. package/dist/tools/browser-type.js.map +1 -1
  164. package/dist/tools/contracts.d.ts +9 -86
  165. package/dist/tools/contracts.d.ts.map +1 -1
  166. package/dist/tools/contracts.js +24 -80
  167. package/dist/tools/contracts.js.map +1 -1
  168. package/dist/tools/cross-pr.d.ts +42 -30
  169. package/dist/tools/cross-pr.d.ts.map +1 -1
  170. package/dist/tools/cross-pr.js +81 -62
  171. package/dist/tools/cross-pr.js.map +1 -1
  172. package/dist/tools/git-diff.d.ts +18 -2
  173. package/dist/tools/git-diff.d.ts.map +1 -1
  174. package/dist/tools/git-diff.js +118 -26
  175. package/dist/tools/git-diff.js.map +1 -1
  176. package/dist/tools/git-history.d.ts +5 -16
  177. package/dist/tools/git-history.d.ts.map +1 -1
  178. package/dist/tools/git-history.js +3 -10
  179. package/dist/tools/git-history.js.map +1 -1
  180. package/dist/tools/history.d.ts +4 -33
  181. package/dist/tools/history.d.ts.map +1 -1
  182. package/dist/tools/history.js +6 -31
  183. package/dist/tools/history.js.map +1 -1
  184. package/dist/tools/impact.d.ts +7 -51
  185. package/dist/tools/impact.d.ts.map +1 -1
  186. package/dist/tools/impact.js +15 -67
  187. package/dist/tools/impact.js.map +1 -1
  188. package/dist/tools/index.d.ts +3 -8
  189. package/dist/tools/index.d.ts.map +1 -1
  190. package/dist/tools/index.js +3 -8
  191. package/dist/tools/index.js.map +1 -1
  192. package/dist/tools/kit.d.ts +66 -113
  193. package/dist/tools/kit.d.ts.map +1 -1
  194. package/dist/tools/kit.js +60 -28
  195. package/dist/tools/kit.js.map +1 -1
  196. package/dist/tools/link-workspace.d.ts +7 -45
  197. package/dist/tools/link-workspace.d.ts.map +1 -1
  198. package/dist/tools/link-workspace.js +10 -48
  199. package/dist/tools/link-workspace.js.map +1 -1
  200. package/dist/tools/lookup.d.ts +4 -14
  201. package/dist/tools/lookup.d.ts.map +1 -1
  202. package/dist/tools/lookup.js +4 -14
  203. package/dist/tools/lookup.js.map +1 -1
  204. package/dist/tools/mark-incident.d.ts +7 -54
  205. package/dist/tools/mark-incident.d.ts.map +1 -1
  206. package/dist/tools/mark-incident.js +15 -68
  207. package/dist/tools/mark-incident.js.map +1 -1
  208. package/dist/tools/observe-runtime.d.ts +27 -210
  209. package/dist/tools/observe-runtime.d.ts.map +1 -1
  210. package/dist/tools/observe-runtime.js +273 -434
  211. package/dist/tools/observe-runtime.js.map +1 -1
  212. package/dist/tools/observe-tests.d.ts +9 -100
  213. package/dist/tools/observe-tests.d.ts.map +1 -1
  214. package/dist/tools/observe-tests.js +74 -152
  215. package/dist/tools/observe-tests.js.map +1 -1
  216. package/dist/tools/pr-analysis.d.ts +18 -2
  217. package/dist/tools/pr-analysis.d.ts.map +1 -1
  218. package/dist/tools/pr-analysis.js +73 -23
  219. package/dist/tools/pr-analysis.js.map +1 -1
  220. package/dist/tools/pre-push.d.ts +74 -16
  221. package/dist/tools/pre-push.d.ts.map +1 -1
  222. package/dist/tools/pre-push.js +152 -51
  223. package/dist/tools/pre-push.js.map +1 -1
  224. package/dist/tools/propagation.d.ts +11 -53
  225. package/dist/tools/propagation.d.ts.map +1 -1
  226. package/dist/tools/propagation.js +17 -58
  227. package/dist/tools/propagation.js.map +1 -1
  228. package/dist/tools/questions.d.ts +13 -63
  229. package/dist/tools/questions.d.ts.map +1 -1
  230. package/dist/tools/questions.js +33 -105
  231. package/dist/tools/questions.js.map +1 -1
  232. package/dist/tools/refusal-fetch.d.ts +4 -40
  233. package/dist/tools/refusal-fetch.d.ts.map +1 -1
  234. package/dist/tools/refusal-fetch.js +4 -40
  235. package/dist/tools/refusal-fetch.js.map +1 -1
  236. package/dist/tools/runtime-incident.d.ts +4 -63
  237. package/dist/tools/runtime-incident.d.ts.map +1 -1
  238. package/dist/tools/runtime-incident.js +10 -87
  239. package/dist/tools/runtime-incident.js.map +1 -1
  240. package/dist/tools/scope.d.ts +7 -25
  241. package/dist/tools/scope.d.ts.map +1 -1
  242. package/dist/tools/scope.js +10 -29
  243. package/dist/tools/scope.js.map +1 -1
  244. package/dist/tools/similar-incidents.d.ts +11 -86
  245. package/dist/tools/similar-incidents.d.ts.map +1 -1
  246. package/dist/tools/similar-incidents.js +7 -71
  247. package/dist/tools/similar-incidents.js.map +1 -1
  248. package/dist/tools/validate.d.ts +29 -70
  249. package/dist/tools/validate.d.ts.map +1 -1
  250. package/dist/tools/validate.js +141 -85
  251. package/dist/tools/validate.js.map +1 -1
  252. package/dist/tools/verification-status.d.ts +9 -64
  253. package/dist/tools/verification-status.d.ts.map +1 -1
  254. package/dist/tools/verification-status.js +9 -62
  255. package/dist/tools/verification-status.js.map +1 -1
  256. package/dist/tools/verify-claim.d.ts +5 -52
  257. package/dist/tools/verify-claim.d.ts.map +1 -1
  258. package/dist/tools/verify-claim.js +6 -56
  259. package/dist/tools/verify-claim.js.map +1 -1
  260. package/dist/transport.d.ts +15 -52
  261. package/dist/transport.d.ts.map +1 -1
  262. package/dist/transport.js +16 -60
  263. package/dist/transport.js.map +1 -1
  264. package/package.json +40 -22
@@ -1,46 +1,16 @@
1
- /**
2
- * What a tool does when the caller has already gone.
3
- *
4
- * `notifications/cancelled` makes the *server* stop waiting and suppress the
5
- * response. It cannot make the work stop, and for the tools that hold
6
- * something real — a browser, an application, a test runner — the work
7
- * continuing after the reply is discarded is the whole problem: a Chromium
8
- * nothing will ever close, an application still being driven, a scenario
9
- * still clicking through a live system on behalf of a caller who cancelled.
10
- *
11
- * So `ctx.signal` is checked at the points where a tool is about to *start*
12
- * something, and whatever the tool already started is released. Three rules
13
- * hold everywhere it is used:
14
- *
15
- * 1. **Release what this call started, and nothing else.** A cancelled verb
16
- * does not close the session `browser_start_session` opened, and a
17
- * cancelled run does not kill a process it merely attached to. Cancellation
18
- * stops the work it was asked to stop; tearing down a caller's own state
19
- * because one call was cancelled is a second failure, not a cleanup.
20
- * 2. **Keep the evidence.** Nothing witnessed before the cancellation is
21
- * thrown away. Evidence captured and then dropped is worse than evidence
22
- * never captured, because nothing discloses it.
23
- * 3. **Never let a cancelled run render as a clean one.** A check that stopped
24
- * a third of the way through has not passed, and the reply says so even
25
- * though nobody is expected to read it — the reply is suppressed only when
26
- * the cancellation arrived over the wire, and this same path is reachable
27
- * when a signal is aborted for any other reason.
28
- *
29
- * The state is `refused`: cancellation is a fact about Descry — it stopped
30
- * looking — and never a fact about the user's code. `empty` would say the run
31
- * looked and found nothing, which is the one thing it must not say.
32
- */
1
+ /** What a tool does when the caller has already gone. `notifications/cancelled` stops the
2
+ * server from waiting, not the work itself — a browser or process would keep running
3
+ * unless released. Three rules: release only what this call started (never a caller's own
4
+ * state), keep evidence already witnessed, never render a cancelled run as clean. State is
5
+ * `refused` (a fact about Descry stopping) not `empty` (which would falsely say it looked and found nothing). */
33
6
  /** The reply state for a call that stopped because its signal was aborted. */
34
7
  export const CANCELLED_STATE = "refused";
35
8
  export function cancellationHeadline(what) {
36
9
  return `The call was cancelled; ${what}.`;
37
10
  }
38
- /**
39
- * @param stopped What this call stopped doing, in the caller's terms.
40
- * @param released What it tore down, when it had started something. Omitted
41
- * when there was nothing to release — claiming a teardown that did not happen
42
- * is the same class of false statement as hiding one that did.
43
- */
11
+ /** @param stopped What this call stopped doing, in the caller's terms.
12
+ * @param released What it tore down, if anything — omitted when nothing was released;
13
+ * claiming a teardown that didn't happen is as false as hiding one that did. */
44
14
  export function cancellationNotes(stopped, released) {
45
15
  return [
46
16
  `This call was cancelled before it finished. ${stopped} Nothing here is a finding about your ` +
@@ -48,14 +18,9 @@ export function cancellationNotes(stopped, released) {
48
18
  ...(released === undefined ? [] : [released]),
49
19
  ];
50
20
  }
51
- /**
52
- * A promise that settles when the signal aborts, and a way to stop listening.
53
- *
54
- * The disposal half is the point. `Promise.race` leaves the losing promise
55
- * pending forever, so a listener added per call and never removed accumulates
56
- * on a signal that outlives the call — the standard leak this shape exists to
57
- * avoid. Callers race and then dispose in a `finally`.
58
- */
21
+ /** A promise that settles when the signal aborts, plus a way to stop listening.
22
+ * `Promise.race` leaves the loser pending forever, so an unremoved listener leaks on a
23
+ * signal that outlives the call — callers race then dispose in a `finally`. */
59
24
  export function whenAborted(signal) {
60
25
  if (signal.aborted)
61
26
  return { promise: Promise.resolve(), dispose: () => { } };
@@ -1 +1 @@
1
- {"version":3,"file":"cancellation.js","sourceRoot":"","sources":["../src/cancellation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,eAAe,GAAG,SAAkB,CAAC;AAElD,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,OAAO,2BAA2B,IAAI,GAAG,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,QAAiB;IAClE,OAAO;QACL,+CAA+C,OAAO,wCAAwC;YAC5F,oDAAoD;QACtD,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAE7E,IAAI,OAAO,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC5C,OAAO,GAAG,GAAG,EAAE;YACb,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IACH,OAAO;QACL,OAAO;QACP,OAAO,EAAE,GAAG,EAAE;YACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cancellation.js","sourceRoot":"","sources":["../src/cancellation.ts"],"names":[],"mappings":"AAAA;;;;kHAIkH;AAElH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,eAAe,GAAG,SAAkB,CAAC;AAElD,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,OAAO,2BAA2B,IAAI,GAAG,CAAC;AAC5C,CAAC;AAED;;iFAEiF;AACjF,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,QAAiB;IAClE,OAAO;QACL,+CAA+C,OAAO,wCAAwC;YAC5F,oDAAoD;QACtD,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED;;gFAEgF;AAChF,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAE7E,IAAI,OAAO,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC5C,OAAO,GAAG,GAAG,EAAE;YACb,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IACH,OAAO;QACL,OAAO;QACP,OAAO,EAAE,GAAG,EAAE;YACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/capped.d.ts CHANGED
@@ -1,41 +1,17 @@
1
- /**
2
- * `capped(items, limit) → { shown, detail }` — B6's fix, part 2.
3
- *
4
- * `render.ts`'s envelope carries a `truncated` field precisely so a caller
5
- * does not have to guess whether a short list is short because that is all
6
- * there was, or because the reply was cut. Before this helper existed, three
7
- * tools computed that cut three different ways: one sliced and remembered to
8
- * report `shown`/`total` by hand, one sliced and forgot, one never sliced at
9
- * all but discarded rows anyway. Two of the three left `render.ts` with
10
- * nothing to report and it filled the gap with a sentinel
11
- * (`{shown:-1,total:-1}`) that is worse than reporting nothing, because it
12
- * passes a presence check and then poisons arithmetic.
13
- *
14
- * This is the fix: the slice and the fact that a slice happened are computed
15
- * together, in one call, so a tool cannot hold one without the other. A tool
16
- * that caps a list calls this instead of `.slice(0, limit)`, and then has a
17
- * `detail` sitting right next to `shown` with nothing further to remember.
18
- */
1
+ /** `capped(items, limit) → { shown, detail }`, B6's fix. Three tools used to compute a list cut
2
+ * three different ways; two left `render.ts` filling the gap with a `{shown:-1,total:-1}`
3
+ * sentinel — worse than nothing, since it passes a presence check and poisons arithmetic. Now the
4
+ * slice and the fact it happened are computed together, so a tool can't hold one without the other. */
19
5
  import type { TruncationDetail } from "./render.ts";
20
6
  export interface Capped<T> {
21
7
  /** The first `limit` items, in their original order. */
22
8
  readonly shown: readonly T[];
23
- /**
24
- * `null` when nothing was withheld — `shown` already holds everything
25
- * `items` had. Non-null exactly when `shown.length < items.length`, and
26
- * carries the same `{shown, total}` shape `render.ts` puts on the wire, so
27
- * a tool can pass it straight through as `truncatedDetail`.
28
- */
9
+ /** `null` when nothing was withheld; otherwise the same `{shown, total}` shape `render.ts` puts
10
+ * on the wire, so a tool can pass it straight through as `truncatedDetail`. */
29
11
  readonly detail: TruncationDetail | null;
30
12
  }
31
- /**
32
- * Slice `items` to `limit` and report what that cost in the same call.
33
- *
34
- * A negative or fractional `limit` is treated as zero rather than thrown —
35
- * the callers here already validate `limit` as a positive integer at the
36
- * schema boundary (`optionalInteger(..., 1)`), so a non-positive value
37
- * reaching this function is defensive, not an expected input to reject
38
- * loudly.
39
- */
13
+ /** Slices `items` to `limit` and reports the cost in the same call. A negative/fractional `limit`
14
+ * is treated as zero rather than thrown — defensive only, callers already validate at the schema
15
+ * boundary. */
40
16
  export declare function capped<T>(items: readonly T[], limit: number): Capped<T>;
41
17
  //# sourceMappingURL=capped.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capped.d.ts","sourceRoot":"","sources":["../src/capped.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,MAAM,CAAC,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAKvE"}
1
+ {"version":3,"file":"capped.d.ts","sourceRoot":"","sources":["../src/capped.ts"],"names":[],"mappings":"AAAA;;;wGAGwG;AAExG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,MAAM,CAAC,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAC7B;oFACgF;IAChF,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC1C;AAED;;gBAEgB;AAChB,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAKvE"}
package/dist/capped.js CHANGED
@@ -1,30 +1,10 @@
1
- /**
2
- * `capped(items, limit) → { shown, detail }` — B6's fix, part 2.
3
- *
4
- * `render.ts`'s envelope carries a `truncated` field precisely so a caller
5
- * does not have to guess whether a short list is short because that is all
6
- * there was, or because the reply was cut. Before this helper existed, three
7
- * tools computed that cut three different ways: one sliced and remembered to
8
- * report `shown`/`total` by hand, one sliced and forgot, one never sliced at
9
- * all but discarded rows anyway. Two of the three left `render.ts` with
10
- * nothing to report and it filled the gap with a sentinel
11
- * (`{shown:-1,total:-1}`) that is worse than reporting nothing, because it
12
- * passes a presence check and then poisons arithmetic.
13
- *
14
- * This is the fix: the slice and the fact that a slice happened are computed
15
- * together, in one call, so a tool cannot hold one without the other. A tool
16
- * that caps a list calls this instead of `.slice(0, limit)`, and then has a
17
- * `detail` sitting right next to `shown` with nothing further to remember.
18
- */
19
- /**
20
- * Slice `items` to `limit` and report what that cost in the same call.
21
- *
22
- * A negative or fractional `limit` is treated as zero rather than thrown —
23
- * the callers here already validate `limit` as a positive integer at the
24
- * schema boundary (`optionalInteger(..., 1)`), so a non-positive value
25
- * reaching this function is defensive, not an expected input to reject
26
- * loudly.
27
- */
1
+ /** `capped(items, limit) → { shown, detail }`, B6's fix. Three tools used to compute a list cut
2
+ * three different ways; two left `render.ts` filling the gap with a `{shown:-1,total:-1}`
3
+ * sentinel — worse than nothing, since it passes a presence check and poisons arithmetic. Now the
4
+ * slice and the fact it happened are computed together, so a tool can't hold one without the other. */
5
+ /** Slices `items` to `limit` and reports the cost in the same call. A negative/fractional `limit`
6
+ * is treated as zero rather than thrown — defensive only, callers already validate at the schema
7
+ * boundary. */
28
8
  export function capped(items, limit) {
29
9
  const bound = Number.isFinite(limit) && limit > 0 ? Math.floor(limit) : 0;
30
10
  const shown = items.slice(0, bound);
@@ -1 +1 @@
1
- {"version":3,"file":"capped.js","sourceRoot":"","sources":["../src/capped.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAgBH;;;;;;;;GAQG;AACH,MAAM,UAAU,MAAM,CAAI,KAAmB,EAAE,KAAa;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;AACrF,CAAC"}
1
+ {"version":3,"file":"capped.js","sourceRoot":"","sources":["../src/capped.ts"],"names":[],"mappings":"AAAA;;;wGAGwG;AAYxG;;gBAEgB;AAChB,MAAM,UAAU,MAAM,CAAI,KAAmB,EAAE,KAAa;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;AACrF,CAAC"}
@@ -1,35 +1,11 @@
1
1
  /**
2
- * Which standing disclosures this connection has already been given in full.
3
- *
4
- * The tax it removes was measured, not supposed: the R0/class-C reliability
5
- * sentence is 354 characters — ~88 tokens — and appeared byte-for-byte
6
- * identical on the large majority of one session's thirty-odd tool calls.
7
- * Nothing about it was wrong; it was simply the same paragraph, re-billed to
8
- * the caller's context window every call, and the loop this server is built
9
- * for (edit, re-check, edit again) is the one that pays it most.
10
- *
11
- * ## What the ledger is allowed to shorten, and what it is not
12
- *
13
- * Only the *argument* for a cap. The floor and the class it caps to stay on
14
- * every reply, first or fiftieth, in `graph.resolutionFloor` /
15
- * `graph.reliabilityCap` and in the short disclosure itself. Rule 7 is about
16
- * what reaches the user, and a reply that stopped naming its own cap after
17
- * the first call would be a reply that silently does less.
18
- *
19
- * ## Per connection, deliberately not per process
20
- *
21
- * "Already disclosed" is a fact about one conversation. A ledger shared across
22
- * connections would let the *second* client's first call inherit the first
23
- * client's history — that client would receive the short form of a sentence it
24
- * has never seen, which is the exact failure this is supposed to avoid, only
25
- * harder to notice. So one ledger is created per `createMcpServer`, and it
26
- * lives as long as that server does.
27
- */
2
+ * Tracks disclosures this connection has already seen in full. Measured: the
3
+ * R0/class-C sentence is ~354 chars (~88 tokens), repeated on most of a 30-call
4
+ * session. Only the *argument* shortens — floor/cap stay on every reply (rule 7).
5
+ * Per connection, not per process — a second client can't inherit the first's history. */
28
6
  export interface DisclosureLedger {
29
- /**
30
- * `true` the first time this key is seen on this connection, `false` after.
31
- * Records the sighting — calling it is what marks the key as disclosed.
32
- */
7
+ /** `true` the first time this key is seen on this connection, `false` after —
8
+ * calling it is what marks the key as disclosed. */
33
9
  firstSighting(key: string): boolean;
34
10
  /** Keys disclosed in full so far. For tests and diagnostics. */
35
11
  disclosed(): readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"disclosure-ledger.d.ts","sourceRoot":"","sources":["../src/disclosure-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,gEAAgE;IAChE,SAAS,IAAI,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,wBAAgB,sBAAsB,IAAI,gBAAgB,CAUzD"}
1
+ {"version":3,"file":"disclosure-ledger.d.ts","sourceRoot":"","sources":["../src/disclosure-ledger.ts"],"names":[],"mappings":"AAAA;;;;0FAI0F;AAE1F,MAAM,WAAW,gBAAgB;IAC/B;yDACqD;IACrD,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,gEAAgE;IAChE,SAAS,IAAI,SAAS,MAAM,EAAE,CAAC;CAChC;AAED,wBAAgB,sBAAsB,IAAI,gBAAgB,CAUzD"}
@@ -1,30 +1,8 @@
1
1
  /**
2
- * Which standing disclosures this connection has already been given in full.
3
- *
4
- * The tax it removes was measured, not supposed: the R0/class-C reliability
5
- * sentence is 354 characters — ~88 tokens — and appeared byte-for-byte
6
- * identical on the large majority of one session's thirty-odd tool calls.
7
- * Nothing about it was wrong; it was simply the same paragraph, re-billed to
8
- * the caller's context window every call, and the loop this server is built
9
- * for (edit, re-check, edit again) is the one that pays it most.
10
- *
11
- * ## What the ledger is allowed to shorten, and what it is not
12
- *
13
- * Only the *argument* for a cap. The floor and the class it caps to stay on
14
- * every reply, first or fiftieth, in `graph.resolutionFloor` /
15
- * `graph.reliabilityCap` and in the short disclosure itself. Rule 7 is about
16
- * what reaches the user, and a reply that stopped naming its own cap after
17
- * the first call would be a reply that silently does less.
18
- *
19
- * ## Per connection, deliberately not per process
20
- *
21
- * "Already disclosed" is a fact about one conversation. A ledger shared across
22
- * connections would let the *second* client's first call inherit the first
23
- * client's history — that client would receive the short form of a sentence it
24
- * has never seen, which is the exact failure this is supposed to avoid, only
25
- * harder to notice. So one ledger is created per `createMcpServer`, and it
26
- * lives as long as that server does.
27
- */
2
+ * Tracks disclosures this connection has already seen in full. Measured: the
3
+ * R0/class-C sentence is ~354 chars (~88 tokens), repeated on most of a 30-call
4
+ * session. Only the *argument* shortens — floor/cap stay on every reply (rule 7).
5
+ * Per connection, not per process — a second client can't inherit the first's history. */
28
6
  export function createDisclosureLedger() {
29
7
  const seen = new Set();
30
8
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"disclosure-ledger.js","sourceRoot":"","sources":["../src/disclosure-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAYH,MAAM,UAAU,sBAAsB;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO;QACL,aAAa,CAAC,GAAG;YACf,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;YAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QACD,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;KAC3B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"disclosure-ledger.js","sourceRoot":"","sources":["../src/disclosure-ledger.ts"],"names":[],"mappings":"AAAA;;;;0FAI0F;AAU1F,MAAM,UAAU,sBAAsB;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO;QACL,aAAa,CAAC,GAAG;YACf,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;YAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QACD,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;KAC3B,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,6 @@
1
- /**
2
- * `@descryy/mcp` — the agent-facing front door.
3
- *
4
- * A thin wrapper over the query layer, as DEC-002 requires: every consumer goes
5
- * through here and **nothing touches storage directly**. That is why the tools
6
- * hold a `Session` and not a driver.
7
- */
1
+ /** `@descryy/mcp` — the agent-facing front door. A thin wrapper over the query layer
2
+ * (DEC-002): every consumer goes through here and nothing touches storage directly —
3
+ * which is why tools hold a `Session`, not a driver. */
8
4
  export { createMcpServer } from "./server.ts";
9
5
  export type { McpServer, McpServerOptions } from "./server.ts";
10
6
  export { Session, loadConfig, writeConfig, writeSources, ConfigError, CONFIG_RELATIVE_PATH, DEFAULT_GRAPH_RELATIVE_PATH, } from "./session.ts";
@@ -15,29 +11,17 @@ export { renderAnswer, renderFailed, renderHandshake, renderTimedOut, renderTool
15
11
  export type { AnswerEnvelope, CallToolResult, Provenance, ResultState, ToolAnswer, ToolTier, TruncationDetail, } from "./render.ts";
16
12
  export { TOOLS, TOOLS_BY_NAME, ToolInputError, resolveOneNode } from "./tools/index.ts";
17
13
  export type { BriefNode, NodeCandidates, Progress, ToolContext, ToolDefinition, } from "./tools/index.ts";
18
- /**
19
- * The shape each tool puts in `AnswerEnvelope.data`.
20
- *
21
- * `data` is `unknown` in the envelope by design — it differs per tool — but
22
- * "read the handler" is not a contract, and an AI caller cannot rely on a
23
- * shape nobody wrote down. Each of these describes what its tool returns
24
- * **today**; where a tool's payload is genuinely conditional the type is a
25
- * union that says so rather than a widening to `unknown`.
26
- */
14
+ /** The shape each tool puts in `AnswerEnvelope.data`. `data` is `unknown` in the envelope
15
+ * by design, but an AI caller can't rely on an unwritten shape — each type here describes
16
+ * what its tool returns today; genuinely conditional payloads are unions, not `unknown`. */
27
17
  export type { AffectedRef, AnalyzeData, BlockedCheck, CoChangedFile, ConfigDependencyReport, ContractPathFinding, ContractShapeMismatchReport, ContractShapeStatus, ContractsData, CrossPrData, CrossPrEmptyDiff, CrossPrGitFailure, CrossPrReport, EnvFindingReport, HiddenDependencyCheck, HiddenDependencyFinding, HistoryData, HistoryFile, HistoryFileResolved, HistoryFileUnresolved, HistoryReport, ImpactData, ImpactReport, ImpactedNode, LinkWorkspaceData, MarkIncidentData, LinkedRepo, OverlapCheck, OverlapReportChecked, PrAnalysisData, PrAnalysisEmptyDiff, PrAnalysisGitFailure, PrAnalysisLists, PrAnalysisRange, PrAnalysisReport, PrAnalysisUnresolved, PropagationData, PropagationReport, QuestionsData, ReachedNode, RelatedNode, ScopeData, ScopeNotSeeded, ScopeReport, ScopeTierCount, ScopedNodeReport, SimilarIncidentReport, SimilarIncidentSignalReport, SimilarIncidentsData, SourceRun, SupersededCheck, TracedPath, ValidateData, } from "./tools/index.ts";
28
18
  export { serveStdio, guardStdout, createLineReader } from "./transport.ts";
29
19
  export type { Transport, StdioOptions } from "./transport.ts";
30
20
  export { PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, negotiateVersion, parseMessage, ProtocolError, } from "./protocol.ts";
31
21
  export type { RpcRequest, RpcNotification, RpcResponse, RpcMessage, RpcId } from "./protocol.ts";
32
- /**
33
- * The scenario format — storage, schema and the refusals.
34
- *
35
- * Re-exported here because `descry check` reads saved scenarios through this
36
- * module and must not reach past the package boundary to do it. A CLI that
37
- * imported `./scenarios/storage.ts` by relative path would be a second reader
38
- * of the format, free to drift from this one the day the schema changes; the
39
- * whole argument for a format module is that there is exactly one.
40
- */
41
- export { SCENARIO_SCHEMA_VERSION, isUnverifying, parseScenario, serializeScenario, scenariosDirectory, scenarioPath, listScenarios, readScenario, writeScenario, } from "./scenarios/index.ts";
22
+ /** The scenario format — storage, schema, refusals. Re-exported here so `descry check`
23
+ * doesn't reach past the package boundary — a second reader importing the relative path
24
+ * could drift from this one the day the schema changes. */
25
+ export { SCENARIO_SCHEMA_VERSION, isUnverifying, parseScenario, serializeScenario, scenariosDirectory, scenarioPath, listScenarios, ScenarioListError, readScenario, writeScenario, } from "./scenarios/index.ts";
42
26
  export type { Scenario, ScenarioStep, ScenarioAssertion, ScenarioAssertionKind, ScenarioActionKind, ScenarioParseResult, TargetDescriptor, } from "./scenarios/index.ts";
43
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EACL,OAAO,EACP,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE9E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEjG,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,cAAc,EACd,UAAU,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACxF,YAAY,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;GAQG;AACH,YAAY,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,mBAAmB,EACnB,2BAA2B,EAC3B,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,WAAW,EACX,SAAS,EACT,cAAc,EACd,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,oBAAoB,EACpB,SAAS,EACT,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEjG;;;;;;;;GAQG;AACH,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;yDAEyD;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EACL,OAAO,EACP,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE9E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEjG,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,cAAc,EACd,UAAU,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACxF,YAAY,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B;;6FAE6F;AAC7F,YAAY,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,mBAAmB,EACnB,2BAA2B,EAC3B,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,WAAW,EACX,SAAS,EACT,cAAc,EACd,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,2BAA2B,EAC3B,oBAAoB,EACpB,SAAS,EACT,eAAe,EACf,UAAU,EACV,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEjG;;4DAE4D;AAC5D,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,6 @@
1
- /**
2
- * `@descryy/mcp` — the agent-facing front door.
3
- *
4
- * A thin wrapper over the query layer, as DEC-002 requires: every consumer goes
5
- * through here and **nothing touches storage directly**. That is why the tools
6
- * hold a `Session` and not a driver.
7
- */
1
+ /** `@descryy/mcp` — the agent-facing front door. A thin wrapper over the query layer
2
+ * (DEC-002): every consumer goes through here and nothing touches storage directly —
3
+ * which is why tools hold a `Session`, not a driver. */
8
4
  export { createMcpServer } from "./server.js";
9
5
  export { Session, loadConfig, writeConfig, writeSources, ConfigError, CONFIG_RELATIVE_PATH, DEFAULT_GRAPH_RELATIVE_PATH, } from "./session.js";
10
6
  export { loadSources, detectSources, normaliseSpec } from "./registry.js";
@@ -12,14 +8,8 @@ export { renderAnswer, renderFailed, renderHandshake, renderTimedOut, renderTool
12
8
  export { TOOLS, TOOLS_BY_NAME, ToolInputError, resolveOneNode } from "./tools/index.js";
13
9
  export { serveStdio, guardStdout, createLineReader } from "./transport.js";
14
10
  export { PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, negotiateVersion, parseMessage, ProtocolError, } from "./protocol.js";
15
- /**
16
- * The scenario format — storage, schema and the refusals.
17
- *
18
- * Re-exported here because `descry check` reads saved scenarios through this
19
- * module and must not reach past the package boundary to do it. A CLI that
20
- * imported `./scenarios/storage.ts` by relative path would be a second reader
21
- * of the format, free to drift from this one the day the schema changes; the
22
- * whole argument for a format module is that there is exactly one.
23
- */
24
- export { SCENARIO_SCHEMA_VERSION, isUnverifying, parseScenario, serializeScenario, scenariosDirectory, scenarioPath, listScenarios, readScenario, writeScenario, } from "./scenarios/index.js";
11
+ /** The scenario format — storage, schema, refusals. Re-exported here so `descry check`
12
+ * doesn't reach past the package boundary — a second reader importing the relative path
13
+ * could drift from this one the day the schema changes. */
14
+ export { SCENARIO_SCHEMA_VERSION, isUnverifying, parseScenario, serializeScenario, scenariosDirectory, scenarioPath, listScenarios, ScenarioListError, readScenario, writeScenario, } from "./scenarios/index.js";
25
15
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EACL,OAAO,EACP,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,UAAU,GACX,MAAM,aAAa,CAAC;AAWrB,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA0ExF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG3E,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC;AAGvB;;;;;;;;GAQG;AACH,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,GACd,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;yDAEyD;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EACL,OAAO,EACP,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG1E,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,UAAU,GACX,MAAM,aAAa,CAAC;AAWrB,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAoExF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAG3E,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,gBAAgB,EAChB,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC;AAGvB;;4DAE4D;AAC5D,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,aAAa,GACd,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Gates `import()` of caller-named specifiers (A-F1/A-F2, three ungated call sites). Refuses path-like specifiers (exact bytes, no install step) by default.
3
+ * Also refuses a bare specifier resolved into the scanned repo's own git-tracked `node_modules` (real `npm install` leaves it untracked) — a repo can otherwise ship a payload merely by being cloned.
4
+ * Escape hatches: `DESCRY_ALLOW_PATH_ADAPTER_MODULES=1`, `DESCRY_ALLOW_TRACKED_NODE_MODULES=1` (server env only, never repo-set).
5
+ */
6
+ export declare const ALLOW_PATH_MODULES_ENV_VAR = "DESCRY_ALLOW_PATH_ADAPTER_MODULES";
7
+ export declare const ALLOW_TRACKED_NODE_MODULES_ENV_VAR = "DESCRY_ALLOW_TRACKED_NODE_MODULES";
8
+ export type ModuleTrustDecision = {
9
+ readonly allowed: true;
10
+ } | {
11
+ readonly allowed: false;
12
+ readonly reason: string;
13
+ };
14
+ /** Path-like: relative/absolute/drive-absolute/home-relative path, or any URL-scheme specifier (`file:`, `http:`, `data:`, …) — names exact bytes, not an installed package. Everything else resolves normally. */
15
+ export declare function isPathLikeSpecifier(specifier: string): boolean;
16
+ /** Decides if `specifier` may be `import()`-ed; never throws — each call site turns a refusal into its own existing failure channel (`SourceLoadFailure`, etc.). */
17
+ export declare function checkModuleTrust(specifier: string): ModuleTrustDecision;
18
+ /** Follow-up to `checkModuleTrust`: refuses a bare specifier resolved into the scanned repo's own git-tracked `node_modules` (real `npm install` leaves it untracked) — closes a payload-via-commit gap. A `null` git-tracked check (no `.git`) is allowed, not refused: the exploit needs a clone, and a non-git directory is a real workflow this check has no history to verify either way. */
19
+ export declare function checkRepoResolvedModuleTrust(options: {
20
+ readonly specifier: string;
21
+ readonly repoPath: string;
22
+ readonly resolvedAbsolutePath: string;
23
+ }): Promise<ModuleTrustDecision>;
24
+ //# sourceMappingURL=module-trust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-trust.d.ts","sourceRoot":"","sources":["../src/module-trust.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,eAAO,MAAM,0BAA0B,sCAAsC,CAAC;AAC9E,eAAO,MAAM,kCAAkC,sCAAsC,CAAC;AAEtF,MAAM,MAAM,mBAAmB,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpH,mNAAmN;AACnN,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAK9D;AAOD,oKAAoK;AACpK,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,mBAAmB,CAYvE;AAOD,kYAAkY;AAClY,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;CACvC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAiB/B"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Gates `import()` of caller-named specifiers (A-F1/A-F2, three ungated call sites). Refuses path-like specifiers (exact bytes, no install step) by default.
3
+ * Also refuses a bare specifier resolved into the scanned repo's own git-tracked `node_modules` (real `npm install` leaves it untracked) — a repo can otherwise ship a payload merely by being cloned.
4
+ * Escape hatches: `DESCRY_ALLOW_PATH_ADAPTER_MODULES=1`, `DESCRY_ALLOW_TRACKED_NODE_MODULES=1` (server env only, never repo-set).
5
+ */
6
+ import { isPathTrackedByGit } from "@descryy/core";
7
+ export const ALLOW_PATH_MODULES_ENV_VAR = "DESCRY_ALLOW_PATH_ADAPTER_MODULES";
8
+ export const ALLOW_TRACKED_NODE_MODULES_ENV_VAR = "DESCRY_ALLOW_TRACKED_NODE_MODULES";
9
+ /** Path-like: relative/absolute/drive-absolute/home-relative path, or any URL-scheme specifier (`file:`, `http:`, `data:`, …) — names exact bytes, not an installed package. Everything else resolves normally. */
10
+ export function isPathLikeSpecifier(specifier) {
11
+ if (specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("~"))
12
+ return true;
13
+ if (/^[a-zA-Z]:[\\/]/.test(specifier))
14
+ return true;
15
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(specifier))
16
+ return true;
17
+ return false;
18
+ }
19
+ function pathModulesAllowed() {
20
+ const value = process.env[ALLOW_PATH_MODULES_ENV_VAR];
21
+ return value === "1" || value === "true";
22
+ }
23
+ /** Decides if `specifier` may be `import()`-ed; never throws — each call site turns a refusal into its own existing failure channel (`SourceLoadFailure`, etc.). */
24
+ export function checkModuleTrust(specifier) {
25
+ if (!isPathLikeSpecifier(specifier))
26
+ return { allowed: true };
27
+ if (pathModulesAllowed())
28
+ return { allowed: true };
29
+ return {
30
+ allowed: false,
31
+ reason: `"${specifier}" names a file path or URL rather than an installed package. Loading one executes ` +
32
+ "arbitrary code with no further confirmation, and this specifier can come from a scanned repository's " +
33
+ "own configuration or from a tool call — neither is necessarily something the operator running this " +
34
+ `server chose. Refused by default; set ${ALLOW_PATH_MODULES_ENV_VAR}=1 in this server's own environment ` +
35
+ "to allow it, and only do that for adapters and configuration you, the operator, trust.",
36
+ };
37
+ }
38
+ function trackedNodeModulesAllowed() {
39
+ const value = process.env[ALLOW_TRACKED_NODE_MODULES_ENV_VAR];
40
+ return value === "1" || value === "true";
41
+ }
42
+ /** Follow-up to `checkModuleTrust`: refuses a bare specifier resolved into the scanned repo's own git-tracked `node_modules` (real `npm install` leaves it untracked) — closes a payload-via-commit gap. A `null` git-tracked check (no `.git`) is allowed, not refused: the exploit needs a clone, and a non-git directory is a real workflow this check has no history to verify either way. */
43
+ export async function checkRepoResolvedModuleTrust(options) {
44
+ if (trackedNodeModulesAllowed())
45
+ return { allowed: true };
46
+ const tracked = await isPathTrackedByGit(options.repoPath, options.resolvedAbsolutePath);
47
+ if (tracked !== true)
48
+ return { allowed: true };
49
+ return {
50
+ allowed: false,
51
+ reason: `"${options.specifier}" resolved to ${options.resolvedAbsolutePath}, inside ${options.repoPath}'s own ` +
52
+ "node_modules — but that file is committed to this repository's own git history, not installed by a " +
53
+ "package manager (a real `npm install` leaves node_modules untracked, almost universally). A " +
54
+ "repository that commits its own node_modules can deliver arbitrary code to anyone who merely clones " +
55
+ `it, with no npm install step at all. Refused by default; set ${ALLOW_TRACKED_NODE_MODULES_ENV_VAR}=1 ` +
56
+ "in this server's own environment to allow it, and only do that for a repository whose committed " +
57
+ "node_modules you, the operator, trust.",
58
+ };
59
+ }
60
+ //# sourceMappingURL=module-trust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-trust.js","sourceRoot":"","sources":["../src/module-trust.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,CAAC,MAAM,0BAA0B,GAAG,mCAAmC,CAAC;AAC9E,MAAM,CAAC,MAAM,kCAAkC,GAAG,mCAAmC,CAAC;AAItF,mNAAmN;AACnN,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACrG,IAAI,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,2BAA2B,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACtD,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,MAAM,CAAC;AAC3C,CAAC;AAED,oKAAoK;AACpK,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC9D,IAAI,kBAAkB,EAAE;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACnD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM,EACJ,IAAI,SAAS,oFAAoF;YACjG,uGAAuG;YACvG,qGAAqG;YACrG,yCAAyC,0BAA0B,sCAAsC;YACzG,wFAAwF;KAC3F,CAAC;AACJ,CAAC;AAED,SAAS,yBAAyB;IAChC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAC9D,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,MAAM,CAAC;AAC3C,CAAC;AAED,kYAAkY;AAClY,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,OAIlD;IACC,IAAI,yBAAyB,EAAE;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAE1D,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACzF,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAE/C,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM,EACJ,IAAI,OAAO,CAAC,SAAS,iBAAiB,OAAO,CAAC,oBAAoB,YAAY,OAAO,CAAC,QAAQ,SAAS;YACvG,qGAAqG;YACrG,8FAA8F;YAC9F,sGAAsG;YACtG,gEAAgE,kCAAkC,KAAK;YACvG,kGAAkG;YAClG,wCAAwC;KAC3C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Confines a caller-named path to a set of roots, with a disclosed, operator-set
3
+ * escape hatch (A-F6). Generalizes two `observe-runtime.ts` call sites with no such
4
+ * check: `evidencePath` (relative joined onto repo root with no re-check — `..`
5
+ * escaped it) and `attach.logFilePath` (read in full every poll, unchecked). */
6
+ export type PathConfinementDecision = {
7
+ readonly allowed: true;
8
+ readonly resolved: string;
9
+ } | {
10
+ readonly allowed: false;
11
+ readonly reason: string;
12
+ };
13
+ export interface PathConfinementOptions {
14
+ /** The path as configured, absolute or relative. Relative is resolved against `process.cwd()` — callers that mean "relative to the repo" must join it themselves before calling this. */
15
+ readonly candidate: string;
16
+ /** Confined when the resolved candidate is under any of these. */
17
+ readonly allowedRoots: readonly string[];
18
+ /** Set to `"1"` or `"true"` in this server's own environment to bypass confinement. */
19
+ readonly envVar: string;
20
+ /** What the value is, for the refusal message — e.g. `"evidencePath"`. */
21
+ readonly what: string;
22
+ }
23
+ export declare function checkPathConfinement(options: PathConfinementOptions): PathConfinementDecision;
24
+ export type SensitivePathDecision = {
25
+ readonly sensitive: false;
26
+ } | {
27
+ readonly sensitive: true;
28
+ readonly reason: string;
29
+ };
30
+ export declare function checkNotSensitivePath(candidate: string, envVar: string): SensitivePathDecision;
31
+ //# sourceMappingURL=path-confinement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-confinement.d.ts","sourceRoot":"","sources":["../src/path-confinement.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAIhF,MAAM,MAAM,uBAAuB,GAC/B;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAOzD,MAAM,WAAW,sBAAsB;IACrC,yLAAyL;IACzL,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,uFAAuF;IACvF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,sBAAsB,GAAG,uBAAuB,CAe7F;AAQD,MAAM,MAAM,qBAAqB,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1H,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,qBAAqB,CAY9F"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Confines a caller-named path to a set of roots, with a disclosed, operator-set
3
+ * escape hatch (A-F6). Generalizes two `observe-runtime.ts` call sites with no such
4
+ * check: `evidencePath` (relative joined onto repo root with no re-check — `..`
5
+ * escaped it) and `attach.logFilePath` (read in full every poll, unchecked). */
6
+ import { resolve, sep } from "node:path";
7
+ function isWithin(resolvedCandidate, root) {
8
+ const resolvedRoot = resolve(root);
9
+ return resolvedCandidate === resolvedRoot || resolvedCandidate.startsWith(resolvedRoot + sep);
10
+ }
11
+ export function checkPathConfinement(options) {
12
+ const resolved = resolve(options.candidate);
13
+ if (options.allowedRoots.some((root) => isWithin(resolved, root))) {
14
+ return { allowed: true, resolved };
15
+ }
16
+ if (process.env[options.envVar] === "1" || process.env[options.envVar] === "true") {
17
+ return { allowed: true, resolved };
18
+ }
19
+ return {
20
+ allowed: false,
21
+ reason: `"${options.candidate}" (${options.what}) resolves to ${resolved}, outside ` +
22
+ `${options.allowedRoots.length === 1 ? "" : "every one of "}${options.allowedRoots.join(", ")}. ` +
23
+ `Refused by default; set ${options.envVar}=1 in this server's own environment to allow it.`,
24
+ };
25
+ }
26
+ /** Name-based blocklist for logFilePath (can't root-confine — logs live anywhere),
27
+ * narrowed to the exploit's shape (`~/.ssh/id_rsa`). NOT primary defence: `redact()`
28
+ * unconditionally scans every byte first — this only stops the read itself. */
29
+ const SENSITIVE_PATH_SEGMENT = /(^|[/\\])(\.ssh|\.aws|\.gnupg|\.kube|\.netrc|\.npmrc|\.git-credentials|\.pgpass|shadow|id_rsa|id_dsa|id_ecdsa|id_ed25519|\.env(\..+)?|[^/\\]+\.pem|[^/\\]+\.key)($|[/\\])/i;
30
+ export function checkNotSensitivePath(candidate, envVar) {
31
+ const resolved = resolve(candidate);
32
+ if (!SENSITIVE_PATH_SEGMENT.test(resolved))
33
+ return { sensitive: false };
34
+ if (process.env[envVar] === "1" || process.env[envVar] === "true")
35
+ return { sensitive: false };
36
+ return {
37
+ sensitive: true,
38
+ reason: `"${candidate}" names a file shape that is never an application log (an SSH/cloud/credential ` +
39
+ `location) — refusing to read it as one. This is a narrow, name-based check, not a guarantee that ` +
40
+ `every sensitive path is caught; set ${envVar}=1 in this server's own environment if this path ` +
41
+ "genuinely is your application's log.",
42
+ };
43
+ }
44
+ //# sourceMappingURL=path-confinement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-confinement.js","sourceRoot":"","sources":["../src/path-confinement.ts"],"names":[],"mappings":"AAAA;;;;gFAIgF;AAEhF,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAMzC,SAAS,QAAQ,CAAC,iBAAyB,EAAE,IAAY;IACvD,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,iBAAiB,KAAK,YAAY,IAAI,iBAAiB,CAAC,UAAU,CAAC,YAAY,GAAG,GAAG,CAAC,CAAC;AAChG,CAAC;AAaD,MAAM,UAAU,oBAAoB,CAAC,OAA+B;IAClE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,MAAM,EAAE,CAAC;QAClF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM,EACJ,IAAI,OAAO,CAAC,SAAS,MAAM,OAAO,CAAC,IAAI,iBAAiB,QAAQ,YAAY;YAC5E,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YACjG,2BAA2B,OAAO,CAAC,MAAM,kDAAkD;KAC9F,CAAC;AACJ,CAAC;AAED;;gFAEgF;AAChF,MAAM,sBAAsB,GAC1B,4KAA4K,CAAC;AAI/K,MAAM,UAAU,qBAAqB,CAAC,SAAiB,EAAE,MAAc;IACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACxE,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,MAAM;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC/F,OAAO;QACL,SAAS,EAAE,IAAI;QACf,MAAM,EACJ,IAAI,SAAS,iFAAiF;YAC9F,mGAAmG;YACnG,uCAAuC,MAAM,mDAAmD;YAChG,sCAAsC;KACzC,CAAC;AACJ,CAAC"}