@smthrs/kernel 0.0.0-stage → 1.0.0-rc.3

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 (267) hide show
  1. package/CHANGELOG.md +206 -0
  2. package/LICENSE +21 -0
  3. package/README.md +154 -2
  4. package/dist/cjs/CapabilitySet.d.ts +6 -0
  5. package/dist/cjs/CapabilitySet.d.ts.map +1 -0
  6. package/dist/cjs/CapabilitySet.js +19 -0
  7. package/dist/cjs/CapabilitySet.js.map +7 -0
  8. package/dist/cjs/ChildProcessEnvironment.d.ts +60 -0
  9. package/dist/cjs/ChildProcessEnvironment.d.ts.map +1 -0
  10. package/dist/cjs/ChildProcessEnvironment.js +61 -0
  11. package/dist/cjs/ChildProcessEnvironment.js.map +7 -0
  12. package/dist/cjs/ChildProcessSpawner.d.ts +100 -0
  13. package/dist/cjs/ChildProcessSpawner.d.ts.map +1 -0
  14. package/dist/cjs/ChildProcessSpawner.js +291 -0
  15. package/dist/cjs/ChildProcessSpawner.js.map +7 -0
  16. package/dist/cjs/CommandLine.d.ts +173 -0
  17. package/dist/cjs/CommandLine.d.ts.map +1 -0
  18. package/dist/cjs/CommandLine.js +54 -0
  19. package/dist/cjs/CommandLine.js.map +7 -0
  20. package/dist/cjs/ContainedSpawner.d.ts +135 -0
  21. package/dist/cjs/ContainedSpawner.d.ts.map +1 -0
  22. package/dist/cjs/ContainedSpawner.js +141 -0
  23. package/dist/cjs/ContainedSpawner.js.map +7 -0
  24. package/dist/cjs/FileSystem.d.ts +452 -0
  25. package/dist/cjs/FileSystem.d.ts.map +1 -0
  26. package/dist/cjs/FileSystem.js +890 -0
  27. package/dist/cjs/FileSystem.js.map +7 -0
  28. package/dist/cjs/FileSystemBatch.d.ts +94 -0
  29. package/dist/cjs/FileSystemBatch.d.ts.map +1 -0
  30. package/dist/cjs/FileSystemBatch.js +31 -0
  31. package/dist/cjs/FileSystemBatch.js.map +7 -0
  32. package/dist/cjs/GrantEvent.d.ts +240 -0
  33. package/dist/cjs/GrantEvent.d.ts.map +1 -0
  34. package/dist/cjs/GrantEvent.js +115 -0
  35. package/dist/cjs/GrantEvent.js.map +7 -0
  36. package/dist/cjs/GrantStore.d.ts +270 -0
  37. package/dist/cjs/GrantStore.d.ts.map +1 -0
  38. package/dist/cjs/GrantStore.js +857 -0
  39. package/dist/cjs/GrantStore.js.map +7 -0
  40. package/dist/cjs/HostError.d.ts +36 -0
  41. package/dist/cjs/HostError.d.ts.map +1 -0
  42. package/dist/cjs/HostError.js +17 -0
  43. package/dist/cjs/HostError.js.map +7 -0
  44. package/dist/cjs/HostServices.d.ts +101 -0
  45. package/dist/cjs/HostServices.d.ts.map +1 -0
  46. package/dist/cjs/HostServices.js +66 -0
  47. package/dist/cjs/HostServices.js.map +7 -0
  48. package/dist/cjs/HttpClient.d.ts +177 -0
  49. package/dist/cjs/HttpClient.d.ts.map +1 -0
  50. package/dist/cjs/HttpClient.js +217 -0
  51. package/dist/cjs/HttpClient.js.map +7 -0
  52. package/dist/cjs/Jj.d.ts +67 -0
  53. package/dist/cjs/Jj.d.ts.map +1 -0
  54. package/dist/cjs/Jj.js +118 -0
  55. package/dist/cjs/Jj.js.map +7 -0
  56. package/dist/cjs/JournalGrantStore.d.ts +65 -0
  57. package/dist/cjs/JournalGrantStore.d.ts.map +1 -0
  58. package/dist/cjs/JournalGrantStore.js +354 -0
  59. package/dist/cjs/JournalGrantStore.js.map +7 -0
  60. package/dist/cjs/Path.d.ts +37 -0
  61. package/dist/cjs/Path.d.ts.map +1 -0
  62. package/dist/cjs/Path.js +46 -0
  63. package/dist/cjs/Path.js.map +7 -0
  64. package/dist/cjs/ProcessConfinement.d.ts +55 -0
  65. package/dist/cjs/ProcessConfinement.d.ts.map +1 -0
  66. package/dist/cjs/ProcessConfinement.js +94 -0
  67. package/dist/cjs/ProcessConfinement.js.map +7 -0
  68. package/dist/cjs/ProcessLedger.d.ts +260 -0
  69. package/dist/cjs/ProcessLedger.d.ts.map +1 -0
  70. package/dist/cjs/ProcessLedger.js +190 -0
  71. package/dist/cjs/ProcessLedger.js.map +7 -0
  72. package/dist/cjs/Rooted.d.ts +53 -0
  73. package/dist/cjs/Rooted.d.ts.map +1 -0
  74. package/dist/cjs/Rooted.js +101 -0
  75. package/dist/cjs/Rooted.js.map +7 -0
  76. package/dist/cjs/Unreachable.d.ts +27 -0
  77. package/dist/cjs/Unreachable.d.ts.map +1 -0
  78. package/dist/cjs/Unreachable.js +43 -0
  79. package/dist/cjs/Unreachable.js.map +7 -0
  80. package/dist/cjs/Workspace.d.ts +62 -0
  81. package/dist/cjs/Workspace.d.ts.map +1 -0
  82. package/dist/cjs/Workspace.js +35 -0
  83. package/dist/cjs/Workspace.js.map +7 -0
  84. package/dist/cjs/index.d.ts +161 -0
  85. package/dist/cjs/index.d.ts.map +1 -0
  86. package/dist/cjs/index.js +73 -0
  87. package/dist/cjs/index.js.map +7 -0
  88. package/dist/cjs/internal/Containment.d.ts +24 -0
  89. package/dist/cjs/internal/Containment.d.ts.map +1 -0
  90. package/dist/cjs/internal/Containment.js +30 -0
  91. package/dist/cjs/internal/Containment.js.map +7 -0
  92. package/dist/cjs/internal/Pipeline.d.ts +18 -0
  93. package/dist/cjs/internal/Pipeline.d.ts.map +1 -0
  94. package/dist/cjs/internal/Pipeline.js +90 -0
  95. package/dist/cjs/internal/Pipeline.js.map +7 -0
  96. package/dist/cjs/internal/makeCapability.d.ts +16 -0
  97. package/dist/cjs/internal/makeCapability.d.ts.map +1 -0
  98. package/dist/cjs/internal/makeCapability.js +44 -0
  99. package/dist/cjs/internal/makeCapability.js.map +7 -0
  100. package/dist/cjs/package.json +1 -0
  101. package/dist/cjs/test/FileSystemBatchContract.d.ts +15 -0
  102. package/dist/cjs/test/FileSystemBatchContract.d.ts.map +1 -0
  103. package/dist/cjs/test/FileSystemBatchContract.js +76 -0
  104. package/dist/cjs/test/FileSystemBatchContract.js.map +7 -0
  105. package/dist/cjs/test/HostContract.d.ts +225 -0
  106. package/dist/cjs/test/HostContract.d.ts.map +1 -0
  107. package/dist/cjs/test/HostContract.js +489 -0
  108. package/dist/cjs/test/HostContract.js.map +7 -0
  109. package/dist/cjs/test/TestGrantStore.d.ts +31 -0
  110. package/dist/cjs/test/TestGrantStore.d.ts.map +1 -0
  111. package/dist/cjs/test/TestGrantStore.js +65 -0
  112. package/dist/cjs/test/TestGrantStore.js.map +7 -0
  113. package/dist/esm/CapabilitySet.d.ts +6 -0
  114. package/dist/esm/CapabilitySet.d.ts.map +1 -0
  115. package/dist/esm/CapabilitySet.js +6 -0
  116. package/dist/esm/CapabilitySet.js.map +1 -0
  117. package/dist/esm/ChildProcessEnvironment.d.ts +60 -0
  118. package/dist/esm/ChildProcessEnvironment.d.ts.map +1 -0
  119. package/dist/esm/ChildProcessEnvironment.js +91 -0
  120. package/dist/esm/ChildProcessEnvironment.js.map +1 -0
  121. package/dist/esm/ChildProcessSpawner.d.ts +100 -0
  122. package/dist/esm/ChildProcessSpawner.d.ts.map +1 -0
  123. package/dist/esm/ChildProcessSpawner.js +342 -0
  124. package/dist/esm/ChildProcessSpawner.js.map +1 -0
  125. package/dist/esm/CommandLine.d.ts +173 -0
  126. package/dist/esm/CommandLine.d.ts.map +1 -0
  127. package/dist/esm/CommandLine.js +195 -0
  128. package/dist/esm/CommandLine.js.map +1 -0
  129. package/dist/esm/ContainedSpawner.d.ts +135 -0
  130. package/dist/esm/ContainedSpawner.d.ts.map +1 -0
  131. package/dist/esm/ContainedSpawner.js +180 -0
  132. package/dist/esm/ContainedSpawner.js.map +1 -0
  133. package/dist/esm/FileSystem.d.ts +452 -0
  134. package/dist/esm/FileSystem.d.ts.map +1 -0
  135. package/dist/esm/FileSystem.js +989 -0
  136. package/dist/esm/FileSystem.js.map +1 -0
  137. package/dist/esm/FileSystemBatch.d.ts +94 -0
  138. package/dist/esm/FileSystemBatch.d.ts.map +1 -0
  139. package/dist/esm/FileSystemBatch.js +26 -0
  140. package/dist/esm/FileSystemBatch.js.map +1 -0
  141. package/dist/esm/GrantEvent.d.ts +240 -0
  142. package/dist/esm/GrantEvent.d.ts.map +1 -0
  143. package/dist/esm/GrantEvent.js +155 -0
  144. package/dist/esm/GrantEvent.js.map +1 -0
  145. package/dist/esm/GrantStore.d.ts +270 -0
  146. package/dist/esm/GrantStore.d.ts.map +1 -0
  147. package/dist/esm/GrantStore.js +951 -0
  148. package/dist/esm/GrantStore.js.map +1 -0
  149. package/dist/esm/HostError.d.ts +36 -0
  150. package/dist/esm/HostError.d.ts.map +1 -0
  151. package/dist/esm/HostError.js +20 -0
  152. package/dist/esm/HostError.js.map +1 -0
  153. package/dist/esm/HostServices.d.ts +101 -0
  154. package/dist/esm/HostServices.d.ts.map +1 -0
  155. package/dist/esm/HostServices.js +76 -0
  156. package/dist/esm/HostServices.js.map +1 -0
  157. package/dist/esm/HttpClient.d.ts +177 -0
  158. package/dist/esm/HttpClient.d.ts.map +1 -0
  159. package/dist/esm/HttpClient.js +299 -0
  160. package/dist/esm/HttpClient.js.map +1 -0
  161. package/dist/esm/Jj.d.ts +67 -0
  162. package/dist/esm/Jj.d.ts.map +1 -0
  163. package/dist/esm/Jj.js +111 -0
  164. package/dist/esm/Jj.js.map +1 -0
  165. package/dist/esm/JournalGrantStore.d.ts +65 -0
  166. package/dist/esm/JournalGrantStore.d.ts.map +1 -0
  167. package/dist/esm/JournalGrantStore.js +350 -0
  168. package/dist/esm/JournalGrantStore.js.map +1 -0
  169. package/dist/esm/Path.d.ts +37 -0
  170. package/dist/esm/Path.d.ts.map +1 -0
  171. package/dist/esm/Path.js +34 -0
  172. package/dist/esm/Path.js.map +1 -0
  173. package/dist/esm/ProcessConfinement.d.ts +55 -0
  174. package/dist/esm/ProcessConfinement.d.ts.map +1 -0
  175. package/dist/esm/ProcessConfinement.js +106 -0
  176. package/dist/esm/ProcessConfinement.js.map +1 -0
  177. package/dist/esm/ProcessLedger.d.ts +260 -0
  178. package/dist/esm/ProcessLedger.d.ts.map +1 -0
  179. package/dist/esm/ProcessLedger.js +283 -0
  180. package/dist/esm/ProcessLedger.js.map +1 -0
  181. package/dist/esm/Rooted.d.ts +53 -0
  182. package/dist/esm/Rooted.d.ts.map +1 -0
  183. package/dist/esm/Rooted.js +104 -0
  184. package/dist/esm/Rooted.js.map +1 -0
  185. package/dist/esm/Unreachable.d.ts +27 -0
  186. package/dist/esm/Unreachable.d.ts.map +1 -0
  187. package/dist/esm/Unreachable.js +26 -0
  188. package/dist/esm/Unreachable.js.map +1 -0
  189. package/dist/esm/Workspace.d.ts +62 -0
  190. package/dist/esm/Workspace.d.ts.map +1 -0
  191. package/dist/esm/Workspace.js +51 -0
  192. package/dist/esm/Workspace.js.map +1 -0
  193. package/dist/esm/index.d.ts +161 -0
  194. package/dist/esm/index.d.ts.map +1 -0
  195. package/dist/esm/index.js +151 -0
  196. package/dist/esm/index.js.map +1 -0
  197. package/dist/esm/internal/Containment.d.ts +24 -0
  198. package/dist/esm/internal/Containment.d.ts.map +1 -0
  199. package/dist/esm/internal/Containment.js +27 -0
  200. package/dist/esm/internal/Containment.js.map +1 -0
  201. package/dist/esm/internal/Pipeline.d.ts +18 -0
  202. package/dist/esm/internal/Pipeline.d.ts.map +1 -0
  203. package/dist/esm/internal/Pipeline.js +68 -0
  204. package/dist/esm/internal/Pipeline.js.map +1 -0
  205. package/dist/esm/internal/makeCapability.d.ts +16 -0
  206. package/dist/esm/internal/makeCapability.d.ts.map +1 -0
  207. package/dist/esm/internal/makeCapability.js +22 -0
  208. package/dist/esm/internal/makeCapability.js.map +1 -0
  209. package/dist/esm/test/FileSystemBatchContract.d.ts +15 -0
  210. package/dist/esm/test/FileSystemBatchContract.d.ts.map +1 -0
  211. package/dist/esm/test/FileSystemBatchContract.js +57 -0
  212. package/dist/esm/test/FileSystemBatchContract.js.map +1 -0
  213. package/dist/esm/test/HostContract.d.ts +225 -0
  214. package/dist/esm/test/HostContract.d.ts.map +1 -0
  215. package/dist/esm/test/HostContract.js +460 -0
  216. package/dist/esm/test/HostContract.js.map +1 -0
  217. package/dist/esm/test/TestGrantStore.d.ts +31 -0
  218. package/dist/esm/test/TestGrantStore.d.ts.map +1 -0
  219. package/dist/esm/test/TestGrantStore.js +57 -0
  220. package/dist/esm/test/TestGrantStore.js.map +1 -0
  221. package/docs/README.md +162 -0
  222. package/docs/api.md +1532 -0
  223. package/docs/concepts/decoration-in-place.md +117 -0
  224. package/docs/concepts/filesystem-batches.md +58 -0
  225. package/docs/concepts/filesystem-confinement.md +168 -0
  226. package/docs/concepts/grant-decisions.md +181 -0
  227. package/docs/concepts/process-containment.md +155 -0
  228. package/docs/contract.md +14 -0
  229. package/docs/guides/adapt-a-new-host-platform.md +148 -0
  230. package/docs/guides/answer-permission-requests.md +151 -0
  231. package/docs/guides/authorize-network-and-model-calls.md +118 -0
  232. package/docs/guides/contain-spawned-processes.md +118 -0
  233. package/docs/guides/guard-a-host-bundle.md +109 -0
  234. package/docs/guides/persist-grants-across-restarts.md +135 -0
  235. package/docs/guides/write-a-capability-policy.md +159 -0
  236. package/docs/installation.md +115 -0
  237. package/docs/quickstart.md +182 -0
  238. package/docs/testing.md +108 -0
  239. package/docs/troubleshooting.md +281 -0
  240. package/package.json +344 -3
  241. package/src/CapabilitySet.ts +6 -0
  242. package/src/ChildProcessEnvironment.ts +98 -0
  243. package/src/ChildProcessSpawner.ts +414 -0
  244. package/src/CommandLine.ts +250 -0
  245. package/src/ContainedSpawner.ts +284 -0
  246. package/src/FileSystem.ts +1655 -0
  247. package/src/FileSystemBatch.ts +90 -0
  248. package/src/GrantEvent.ts +174 -0
  249. package/src/GrantStore.ts +1345 -0
  250. package/src/HostError.ts +37 -0
  251. package/src/HostServices.ts +133 -0
  252. package/src/HttpClient.ts +406 -0
  253. package/src/Jj.ts +159 -0
  254. package/src/JournalGrantStore.ts +461 -0
  255. package/src/Path.ts +47 -0
  256. package/src/ProcessConfinement.ts +156 -0
  257. package/src/ProcessLedger.ts +423 -0
  258. package/src/Rooted.ts +128 -0
  259. package/src/Unreachable.ts +30 -0
  260. package/src/Workspace.ts +65 -0
  261. package/src/index.ts +181 -0
  262. package/src/internal/Containment.ts +37 -0
  263. package/src/internal/Pipeline.ts +85 -0
  264. package/src/internal/makeCapability.ts +26 -0
  265. package/src/test/FileSystemBatchContract.ts +59 -0
  266. package/src/test/HostContract.ts +785 -0
  267. package/src/test/TestGrantStore.ts +73 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,206 @@
1
+ # @smthrs/kernel
2
+
3
+ ## [Unreleased]
4
+
5
+ ### Added
6
+
7
+ - `FileSystem.confined(fileSystem, root)` returns a filesystem view whose every
8
+ path operation is one descriptor-relative, no-follow request against `root`,
9
+ pinned by canonical path and `device:inode` identity, without a grant check.
10
+ Engine machinery uses it so its own writes cannot be redirected by a symlink
11
+ swap. It refuses a plain path-based host with `PermissionDenied`, returns an
12
+ isolated volume or the guarded `FileSystem.layer` service for the same root
13
+ as it is, and refuses operations that are not one atomic request.
14
+ `isConfinable` and `requireConfinable` check a host at composition time.
15
+ - `@smthrs/kernel/Rooted` binds unguarded `FileSystem`, `Path` and
16
+ `ChildProcessSpawner` services to one root directory. `Rooted.spawner` keeps
17
+ a contained spawner's containment mark. It replaces the TUI's private copy.
18
+
19
+ ### Changed
20
+
21
+ - `ChildProcessSpawner.layer` and `Path.layer` now require `Workspace`. A
22
+ command with no or a relative `cwd` runs in `Workspace.root`, and relative
23
+ paths resolve there, instead of in `process.cwd()`. The grant check sees the
24
+ resolved directory.
25
+
26
+ ### Fixed
27
+
28
+ - `HttpClient.layer` honors a caller's explicit `RequestInit { redirect: "manual" }`
29
+ by returning one authorized hop. Callers can own their redirect loop and hop
30
+ limit without a second loop following redirects underneath them. Default
31
+ redirect following and authorization on every hop are preserved.
32
+ - `HttpClient.layer` forces `RequestInit { redirect: "manual" }` below its
33
+ guard, so composing it over a plain `FetchHttpClient.layer`, which follows
34
+ redirects by default, can no longer fetch a redirect target without a grant
35
+ check.
36
+ - `JournalGrantStore` no longer tells an operator to compact a full policy
37
+ journal. Replay never reads a checkpoint, so compaction broke every later
38
+ construction; the message now says to start a new `policyRunId`.
39
+ - The internal `@slop` review markers no longer ship in the published
40
+ declarations. Every export they marked already carries its prose.
41
+
42
+ ## [1.0.0-rc.0] - 2026-08-31
43
+
44
+ ### Changed
45
+
46
+ - **`HttpTransport` is gone; network access is Effect's own `HttpClient`**
47
+ (maintainer directive, 2026-08-10). `@smthrs/kernel/HttpTransport` — the
48
+ raw one-hop port — is deleted, and `HttpClient` is now middleware over
49
+ `effect/unstable/http`'s `HttpClient` tag rather than a kernel-owned service
50
+ projected off that port. The kernel declares no HTTP interface, no HTTP tag,
51
+ and no `executeModel` method: it re-exports Effect's tag and `make`, and adds
52
+ `layer`, a `TransportError`-reporting `makeNoop` / `layerNoop` stub, and the
53
+ `toHttpClientError` / `fromHttpClientError` projection.
54
+ - A `model:call` check is requested with the new `ModelCall` context
55
+ reference, set by `HttpClient.withModelCall(modelId)` around the request,
56
+ in place of the removed `executeModel` method.
57
+ - Permission failures now ride in `HttpClientError`, the channel Effect's tag
58
+ fixes: reason `TransportError`, `description` the one-line rendering, and
59
+ `cause` the structured `PermissionRequired` / `PermissionDenied` /
60
+ `GrantStoreError`. `HttpClient.fromHttpClientError` reads it back.
61
+ - **Redirects.** The old port existed so a redirect could not bypass
62
+ enforcement. The invariant is preserved with Effect alone: host bundles
63
+ provide a client that never follows a redirect on its own (fetch with
64
+ `RequestInit { redirect: "manual" }`, Undici with no redirect interceptor),
65
+ and the decorator composes Effect's own `HttpClient.followRedirects`
66
+ _above_ the guard, so each hop re-enters the guarded `postprocess` and is
67
+ authorized independently.
68
+ - `HostServices` slot 5 is now Effect's `HttpClient` tag and its
69
+ `HostServiceIds` entry changes from `@smthrs/kernel/HttpTransport` to
70
+ `effect/HttpClient`. **This changes step-key identity**: every cached step
71
+ that named the network slot is invalidated, which is the intent.
72
+
73
+ - **One tag per protected service** (maintainer directive, 2026-08-10).
74
+ Enforcement is now middleware over the service's _own_ tag —
75
+ `Layer.effect(Tag, Effect.gen(function*() { const raw = yield* Tag; … }))`
76
+ composed over the platform layer with `Layer.provide` — instead of a widened
77
+ redeclaration of the interface behind a second tag plus an
78
+ `as unknown as` cast to force the guarded implementation back onto the raw
79
+ one. Those widened service-interface casts are gone; narrow casts remain for
80
+ the atomic filesystem extension, process and journal identities, and
81
+ validated immutable snapshots.
82
+ - `FileSystem` and `ChildProcessSpawner` no longer export a kernel
83
+ interface, tag, `make`, `makeNoop`, or `layerNoop` for the service itself;
84
+ Effect's are the ones to use. `FileSystem` keeps `canonicalResource` and
85
+ `layer`; `ChildProcessSpawner` keeps `layer` plus a `NotFound`-reporting
86
+ `makeNoop` / `layerNoop` stub, and re-exports Effect's tag and `make`.
87
+ - `Jj` no longer redeclares `@smthrs/jj`'s interface. It re-exports that
88
+ package's tag, `make`, `makeNoop`, and `layerNoop`, and adds `layer`.
89
+ - `HostServices` collapses to one closed list: `ProtectedHostService` and
90
+ `ProtectedHostServiceTags` are gone. `HostServiceIds` is unchanged — the
91
+ service identities did not change, only the plumbing.
92
+ - Permission failures on Effect-owned services are projected into the native
93
+ `PlatformError` channel by the new `Permission.toPlatformError`: the reason
94
+ is the normalized `PermissionDenied` system-error tag, `description` is the
95
+ one-line rendering of the failure, and `cause` carries the structured
96
+ `PermissionRequired` / `PermissionDenied` / `GrantStoreError`.
97
+ `Permission.fromPlatformError` reads it back, so the attended surface and
98
+ unattended reporting lose nothing.
99
+ - `Capability` and `Permission` moved to the new leaf package
100
+ `@smthrs/capability` and are re-exported from the root barrel unchanged;
101
+ only the deep imports move (`@smthrs/kernel/Capability` →
102
+ `@smthrs/capability/Capability`, same for `Permission`). The split exists
103
+ so `@smthrs/jj` can
104
+ declare the permission failures its guarded interface adds without depending
105
+ on the kernel that already depends on it. Every schema id is frozen and
106
+ unchanged (`@smthrs/kernel/Capability`, `@smthrs/kernel/PermissionDenied`, …)
107
+ because they round-trip through the grant journal.
108
+ - Attended suspension on a `Deferred`, unattended fail-fast, and terminal
109
+ denial keep their existing `GrantStore` behavior.
110
+ - **HTTP capability resources now make non-`https` schemes explicit.** GET and
111
+ HEAD use `net:get` and every other method uses `net:post`. An `https:` URL
112
+ uses its lowercased host as the resource; every other scheme uses
113
+ `<scheme>//<lowercased host>`. `model:call` follows the same rule before
114
+ appending `/<model id>`, so a grant for an HTTPS host no longer admits a
115
+ cleartext downgrade.
116
+ - **The 1,024-envelope ceiling now covers the construction envelope.**
117
+ `GrantStore.make` refuses a new construction envelope, rather than persisting
118
+ it, once the replayed signatures already fill the ceiling — the bound
119
+ `grantEnvelope` has always applied at reply time. A durable history can
120
+ therefore never outgrow what a later construction will replay.
121
+ `JournalGrantStore` reports an already-grown history with a message naming
122
+ the policy run and both signature counts, the way it already reports an
123
+ oversized replayed rule set, instead of the bare
124
+ `envelopeSignatures exceed 1024 entries`.
125
+
126
+ ### Added
127
+
128
+ - Added `ContainedSpawner`, process middleware that applies the
129
+ `SIGTERM`-then-`SIGKILL` deadline to every command and records each child in
130
+ `ProcessLedger` until its spawn scope closes.
131
+ - Added `ProcessLedger` with durable and in-memory layers, the
132
+ `SpawnedEventType`, `ExitedEventType`, `ReapedEventType`, and
133
+ `SkippedEventType` wire constants, and replay of process records abandoned
134
+ by a dead host incarnation.
135
+ - Added the atomic-host filesystem extension:
136
+ `withAtomicFileSystem` installs a descriptor-relative, no-follow executor,
137
+ `withIsolatedFileSystem` attests a whole isolated browser or test volume, and
138
+ guarded filesystem operations fail closed when a host declares neither.
139
+ - Added `canonicalEnvelopePatterns` and `envelopeSignature` so envelope
140
+ approvals have one deduplicated, order-independent durable identity.
141
+ - Added `CommandLine`, which renders an `effect/unstable/process` `Command` back
142
+ to a POSIX command line. One renderer, two callers: the `proc:spawn`
143
+ capability resource and the interpreter or remote sandbox that executes the
144
+ line, so a grant and the thing it authorizes cannot drift apart. `shell: true`
145
+ keeps shell syntax verbatim, while a custom shell path is named explicitly in
146
+ the rendered invocation and therefore in the permission resource.
147
+ - Added `ChildProcessSpawner`, the permission decorator over Effect's own
148
+ spawner. The check is suspended inside `spawn`, so building a `Command` or a
149
+ stream neither asks permission nor starts a process; the derived helpers
150
+ (`exitCode`, `string`, `lines`, `stream*`) are rebuilt from the guarded
151
+ `spawn` so none can route around it; and `layer` double-publishes onto
152
+ Effect's tag, so a `Command` run as a plain `Effect` is checked too.
153
+ - Absorbed the dissolved `@smthrs/host`: `HostError`, the
154
+ closed `HostServices` list, the shared contract suite (now
155
+ `@smthrs/kernel/test/contract`), and the deterministic `TestHost` bundle
156
+ (`@smthrs/kernel/test/TestHost`, Node-only) live here.
157
+
158
+ ### Fixed
159
+
160
+ - A spawn whose ledger record fails is now signalled and removed from
161
+ `ProcessLedger.live` before the failed spawn returns.
162
+ - `withIsolatedFileSystem` refuses a filesystem that already carries a
163
+ descriptor-relative executor instead of silently replacing it with a
164
+ path-delegating one.
165
+ - Replayed remembered rules are deduplicated, and a policy journal past the
166
+ 1,024-rule ceiling now fails with the policy run id and the configured,
167
+ replayed, and total rule counts.
168
+ - Made capability sets, grant inputs/results, Host request descriptions, and
169
+ byte buffers immutable snapshots rather than aliases to caller-owned state.
170
+ - Added finite GrantStore policy, envelope, pending-request, metadata, event,
171
+ and identity limits with field-specific typed failures.
172
+ - Added complete Host conformance matrices, observable child liveness, exact
173
+ refused-operation codes, and clean packed-consumer coverage for the public
174
+ test contract.
175
+
176
+ ### Removed
177
+
178
+ - Removed the `Pty` decorator, and with it the `flows/host/Pty` slot from the
179
+ closed list, `PtyError` from `HostError`, and the `@smthrs/pty` package from
180
+ the workspace. The contract had no production consumer and its Node
181
+ implementation was piped stdio, not a pseudo-terminal. Interactive-terminal
182
+ support belongs to a higher-level harness extension, not the closed Host
183
+ surface — see D13 in `docs/pages/design-decisions.md` and
184
+ `docs/specs/Concepts/No Pty In Core.md`.
185
+ - Removed the `Shell` decorator and the raw `Shell` port. Process execution is
186
+ `effect/unstable/process`; the closed list's third slot now holds Effect's own
187
+ tag and its id is `effect/process/ChildProcessSpawner`. That id change is
188
+ deliberate and invalidates cached steps that ran a command: the service
189
+ really is different, so the step really is different.
190
+ - Removed `ShellError`, `ShellErrorCode`, and `shellError` from `HostError`. A
191
+ spawn fails with `PlatformError`, like the rest of `effect`'s platform
192
+ surface.
193
+
194
+ ## [0.1.0] - 2026-08-05
195
+
196
+ ### Added
197
+
198
+ - Added the effect-aware capability model, monotone attenuation, journaled grant store, and mandatory decoration of the original Host and Effect service tags.
199
+ - Added tier-preserving grant validation, canonical filesystem confinement, single-hop HTTP transport enforcement, browser-bundle coverage, and dual ESM/CJS package artifacts.
200
+
201
+ ### Fixed
202
+
203
+ - Switched Host integration to its current public service subpaths and made the browser root entrypoint Node-free.
204
+ - Corrected configured-policy last-match-wins evaluation, journaled one-call grants, and resumed every pending waiter covered by run grants.
205
+ - Added plan-digest-bound run and remembered envelopes, same-run grant replay, trusted journal envelope validation, and duplicate-free resume.
206
+ - Preserved grant-store lifecycle failures in the typed stable-code channel and emitted identity-safe non-bundled CJS modules.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 William Cory and the Smithers Flows contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,155 @@
1
- # Temporary Holding Version
1
+ # @smthrs/kernel
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Release candidate scope, host requirements and compatibility review are defined in the [library support policy](https://github.com/smithersai/smithers/blob/main/RELEASE_SUPPORT.md).
4
+
5
+ This package declares `effect` as an exact
6
+ `4.0.0-rc.115` peer dependency. Keep the application on that version so
7
+ all Smithers packages share one Effect runtime.
8
+
9
+ **Documentation:** https://kernel.smithers.sh
10
+
11
+ A capability kernel for [Effect](https://effect.website) hosts. It puts a
12
+ permission check in front of every side effect a program can reach: the five
13
+ service tags a host provides, `FileSystem`, `Path`, `ChildProcessSpawner`,
14
+ `HttpClient`, and `Jj`, are decorated in place, so each operation is named as a
15
+ capability, checked against a grant store, and refused with a typed error when
16
+ nobody authorized it.
17
+
18
+ Decorating in place is the point. A protected second service only guards the
19
+ callers who agreed to use it, and the first dependency that reaches for the
20
+ ordinary `FileSystem` tag walks straight past it. Once this layer is composed,
21
+ the guarded implementation is what the tag resolves to, so there is no
22
+ unguarded one left to reach for. Code that calls `fs.readFileString` is checked
23
+ without ever mentioning permission.
24
+
25
+ ## Install
26
+
27
+ `@smthrs/kernel` is not on npm at 1.0.0-rc.0. Its source lives in the
28
+ [smithers repository](https://github.com/smithersai/smithers), and the
29
+ [installation page](https://kernel.smithers.sh/installation/) covers how to
30
+ depend on it from a checkout, the import forms, and the two test helpers.
31
+
32
+ It needs Node.js 26.4.0 or later and `effect` 4.0.0-rc.115. It carries no
33
+ platform implementations of its own, so a composition that reaches a real
34
+ machine also adds a bundle such as
35
+ [`@smthrs/platform-node`](https://platform-node.smithers.sh).
36
+
37
+ ## Refuse an operation nobody authorized
38
+
39
+ This program composes the kernel over the deterministic host from
40
+ `@smthrs/testing/TestHost`. Add `"@smthrs/testing": "workspace:*"` to the
41
+ consuming package's devDependencies before running it. The policy allows reads
42
+ under the workspace and says nothing about writes:
43
+
44
+ ```ts
45
+ import { Capability, GrantStore, HostServices, Permission, Workspace } from "@smthrs/kernel"
46
+ import * as TestHost from "@smthrs/testing/TestHost"
47
+ import { Effect, FileSystem, Layer } from "effect"
48
+
49
+ const rules = [
50
+ new Permission.Rule({
51
+ effect: "allow",
52
+ pattern: new Capability.CapabilityPattern({ action: "fs:read", resource: "/workspace/**" })
53
+ })
54
+ ]
55
+
56
+ const guarded = HostServices.layer.pipe(
57
+ Layer.provide(Layer.orDie(GrantStore.layer({ attended: false, rules }))),
58
+ Layer.provideMerge(TestHost.layer({ files: { "/workspace/README.md": "# hello" } })),
59
+ Layer.provide(Workspace.layer("/workspace"))
60
+ )
61
+
62
+ /** Ordinary Effect code. Nothing here knows a kernel exists. */
63
+ const program = Effect.gen(function*() {
64
+ const fs = yield* FileSystem.FileSystem
65
+ const readme = yield* fs.readFileString("/workspace/README.md")
66
+ yield* fs.writeFileString("/workspace/out.txt", readme)
67
+ })
68
+
69
+ Effect.runPromise(program.pipe(Effect.provide(guarded), Effect.scoped))
70
+ ```
71
+
72
+ The read returns `"# hello"`. The write never reaches the filesystem. Effect
73
+ fixes that method's error channel to `PlatformError`, so the kernel projects
74
+ its refusal into one and keeps the structured original on the cause, where
75
+ `Permission.fromPlatformError` reads it back as a `PermissionRequired` naming
76
+ `fs:write` on `/workspace/out.txt`.
77
+
78
+ `permission_required`, not `permission_denied`: no rule matched, silence is not
79
+ consent, and this store has nobody to ask. Build the store with
80
+ `attended: true` instead and the same write parks on a request an operator can
81
+ answer, then resumes the operation it was authorized for. The
82
+ [quickstart](https://kernel.smithers.sh/quickstart/) runs both halves.
83
+
84
+ ## What a yes or no answer leaves open
85
+
86
+ - **Confinement.** A path is authorized as a canonical resource and the
87
+ operation runs through a pinned directory descriptor, so a symlink or a
88
+ rename between the decision and the call cannot redirect it. A host that
89
+ cannot address the real filesystem attests whole-volume isolation instead; a
90
+ path-only adapter is unsupported and fails closed.
91
+ - **Containment.** A cancelled run signals its children, escalates to
92
+ `SIGKILL` on a deadline, and records each child in a durable ledger, so a
93
+ host that dies leaves orphan records its successor can reap.
94
+ - **A ceiling that only narrows.** `CapabilitySet.attenuate` bounds what a
95
+ fiber may ask for, and no public operation widens it again.
96
+ - **Grants that outlive the process.** A decision is written to a journal
97
+ before it takes effect, so a permission a person chose to remember is still
98
+ in force after a restart.
99
+
100
+ ## Public API
101
+
102
+ The root entry point exports these namespaces, and each is also importable from
103
+ `@smthrs/kernel/<Module>`. Every export, with its signature and its bounds, is
104
+ on the [API reference](https://kernel.smithers.sh/reference/api/).
105
+
106
+ | Namespace | What it is |
107
+ | --------------------- | ------------------------------------------------------------------------------------------------------------ |
108
+ | `Capability` | The vocabulary a decision is made in: actions, exact capabilities, patterns, matching, and effect tiers. |
109
+ | `Permission` | The typed failure contract, plus policy rules and their evaluation. |
110
+ | `CapabilitySet` | The authority ceiling. `attenuate` narrows it; no public operation widens it again. |
111
+ | `GrantStore` | The service that decides: check a capability, park a request, reply to it, and the bounds every value obeys. |
112
+ | `JournalGrantStore` | A grant store that replays and persists its decisions through `Journal`. |
113
+ | `GrantEvent` | The durable grant vocabulary: once, remembered, run, denied, and envelope grants, with their schema. |
114
+ | `HostServices` | The closed list of five host slots, and the aggregate layer that decorates all of them in place. |
115
+ | `FileSystem` | The guarded filesystem, its canonical resources, and the confinement a host attaches at its boundary. |
116
+ | `HttpClient` | The guarded HTTP client: `net:get`, `net:post`, `model:call`, and every redirect hop rechecked. |
117
+ | `ChildProcessSpawner` | The guarded spawner over Effect's own tag. |
118
+ | `ContainedSpawner` | A `SIGTERM`-then-`SIGKILL` deadline on every child, and a ledger entry released when its scope closes. |
119
+ | `ProcessConfinement` | Host confinement for approved processes, derived conservatively from effective grants and ceilings. |
120
+ | `ProcessLedger` | The durable record of spawned processes, and the `orphans` a dead host leaves its successor to reap. |
121
+ | `CommandLine` | The one renderer shared by the `proc:spawn` capability resource and the interpreters that run the line. |
122
+ | `Jj` | The guarded [Jujutsu](https://jj-vcs.github.io) repository port over `@smthrs/jj`'s own tag. |
123
+ | `Path` | Effect's `Path`, passed through unchecked by decision. |
124
+ | `Workspace` | The root that filesystem capability resources are resolved against. |
125
+
126
+ `ChildProcessEnvironment` builds a replacement environment from bootstrap names plus explicit declarations, withholding credential-shaped ambient values.
127
+
128
+ `Capability` and `Permission` are re-exports; their modules live in
129
+ [`@smthrs/capability`](https://capability.smithers.sh).
130
+
131
+ Two test helpers ship in the package's export map, not as dev-only files:
132
+ `@smthrs/kernel/test/TestGrantStore` for allow, deny, and scripted grant-store
133
+ doubles and `@smthrs/kernel/test/contract` for `runHostContract`, the behavioral
134
+ contract every host bundle must satisfy (`test/HostContract` is an alias).
135
+ The contract is Node-only. The
136
+ deterministic host bundle lives at `@smthrs/testing/TestHost` so the kernel does
137
+ not depend back on a platform implementation.
138
+
139
+ ## Documentation
140
+
141
+ - [Overview](https://kernel.smithers.sh)
142
+ - [Quickstart](https://kernel.smithers.sh/quickstart/)
143
+ - [Guard a host bundle](https://kernel.smithers.sh/guides/guard-a-host-bundle/)
144
+ - [Write a capability policy](https://kernel.smithers.sh/guides/write-a-capability-policy/)
145
+ - [Decoration in place](https://kernel.smithers.sh/concepts/decoration-in-place/)
146
+ - [API reference](https://kernel.smithers.sh/reference/api/)
147
+ - [Troubleshooting](https://kernel.smithers.sh/troubleshooting/), which lists
148
+ every refusal this package raises, what it means, and what to change.
149
+
150
+ `@smthrs/kernel` is one package of the Smithers durable flow engine, which
151
+ ships whole as [`@smthrs/flows`](https://flows.smithers.sh).
152
+
153
+ ## License
154
+
155
+ MIT. See [LICENSE](./LICENSE).
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The shared monotone authority implementation used by declarations and guards.
3
+ * @since 1.0.0
4
+ */
5
+ export * from "@smthrs/capability/CapabilitySet";
6
+ //# sourceMappingURL=CapabilitySet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CapabilitySet.d.ts","sourceRoot":"","sources":["../../src/CapabilitySet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,kCAAkC,CAAA"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
15
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
16
+ var CapabilitySet_exports = {};
17
+ module.exports = __toCommonJS(CapabilitySet_exports);
18
+ __reExport(CapabilitySet_exports, require("@smthrs/capability/CapabilitySet"), module.exports);
19
+ //# sourceMappingURL=CapabilitySet.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/CapabilitySet.ts"],
4
+ "sourcesContent": ["/**\n * The shared monotone authority implementation used by declarations and guards.\n * @since 1.0.0\n */\n\nexport * from \"@smthrs/capability/CapabilitySet\"\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;AAAA;AAAA;AAKA,kCAAc,6CALd;",
6
+ "names": []
7
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Least-authority environment construction for child processes.
3
+ *
4
+ * @since 1.0.0-rc.0
5
+ */
6
+ /**
7
+ * Credential-bearing field names shared with the model request boundary.
8
+ *
9
+ * `token`, `key` (optionally followed by a separated `id`), and `pat` are
10
+ * anchored to complete or separator-delimited suffixes so names such as
11
+ * `TOKEN_COUNT` and `KEYBOARD` remain ordinary diagnostics. Keeping this rule
12
+ * below the model and process layers gives request validation and child
13
+ * spawning one definition of a sensitive name.
14
+ *
15
+ * @category constants
16
+ * @since 1.0.0-rc.0
17
+ */
18
+ export declare const credentialNamePattern: RegExp;
19
+ /**
20
+ * Reports whether a field name conventionally carries credentials.
21
+ *
22
+ * @category predicates
23
+ * @since 1.0.0-rc.0
24
+ */
25
+ export declare const isCredentialName: (name: string) => boolean;
26
+ /**
27
+ * Ambient variables a child may inherit for executable lookup, identity,
28
+ * locale, terminal behavior, temporary files, and its shell.
29
+ *
30
+ * Locale category variables are admitted separately by their `LC_` prefix.
31
+ *
32
+ * @category constants
33
+ * @since 1.0.0-rc.0
34
+ */
35
+ export declare const inheritedNames: ReadonlyArray<string>;
36
+ /**
37
+ * Reports whether a variable belongs to the bootstrap set {@link make}
38
+ * inherits: one of {@link inheritedNames} or a locale `LC_` category,
39
+ * compared case-insensitively.
40
+ *
41
+ * @category predicates
42
+ * @since 1.0.0-rc.1
43
+ */
44
+ export declare const isInheritedName: (name: string) => boolean;
45
+ /**
46
+ * Selects the bootstrap allowlist from an ambient environment and overlays
47
+ * caller-declared names.
48
+ *
49
+ * Sensitive-looking ambient names are withheld even if a future bootstrap
50
+ * list grows to include one. A caller declaration is applied last because it
51
+ * is the explicit authority for that child; an `undefined` declaration
52
+ * removes an inherited name. The returned null-prototype record is always
53
+ * suitable as a replacement environment and never asks the spawner to merge
54
+ * the rest of the host process environment.
55
+ *
56
+ * @category constructors
57
+ * @since 1.0.0-rc.0
58
+ */
59
+ export declare const make: (ambient: Readonly<Record<string, string | undefined>>, declared?: Readonly<Record<string, string | undefined>>) => Record<string, string>;
60
+ //# sourceMappingURL=ChildProcessEnvironment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChildProcessEnvironment.d.ts","sourceRoot":"","sources":["../../src/ChildProcessEnvironment.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,QACoR,CAAA;AAEtT;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,OAA2C,CAAA;AAE3F;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,MAAM,CAQ/C,CAAA;AAIF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,OAG9C,CAAA;AASD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,IAAI,GACf,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACrD,WAAU,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAM,KAC1D,MAAM,CAAC,MAAM,EAAE,MAAM,CAUvB,CAAA"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var ChildProcessEnvironment_exports = {};
20
+ __export(ChildProcessEnvironment_exports, {
21
+ credentialNamePattern: () => credentialNamePattern,
22
+ inheritedNames: () => inheritedNames,
23
+ isCredentialName: () => isCredentialName,
24
+ isInheritedName: () => isInheritedName,
25
+ make: () => make
26
+ });
27
+ module.exports = __toCommonJS(ChildProcessEnvironment_exports);
28
+ const credentialNamePattern = /authorization|api[-_]?key|access[-_]?token|refresh[-_]?token|id[-_]?token|auth[-_]?token|api[-_]?token|session[-_]?token|bearer|(?:^|[-_])token$|(?:^|[-_])key(?:[-_]id)?$|(?:^|[-_])pat$|secret|credential|password|passphrase|passwd|signature|x-amz-signature|cookie|set[-_]?cookie|chatgpt[-_]?account[-_]?id/i;
29
+ const isCredentialName = (name) => credentialNamePattern.test(name);
30
+ const inheritedNames = Object.freeze([
31
+ "PATH",
32
+ "HOME",
33
+ "USER",
34
+ "LANG",
35
+ "TERM",
36
+ "TMPDIR",
37
+ "SHELL"
38
+ ]);
39
+ const inherited = new Set(inheritedNames);
40
+ const isInheritedName = (name) => {
41
+ const canonical = name.toUpperCase();
42
+ return inherited.has(canonical) || canonical.startsWith("LC_");
43
+ };
44
+ const remove = (environment, name) => {
45
+ const canonical = name.toUpperCase();
46
+ for (const present of Object.keys(environment)) {
47
+ if (present.toUpperCase() === canonical) delete environment[present];
48
+ }
49
+ };
50
+ const make = (ambient, declared = {}) => {
51
+ const environment = /* @__PURE__ */ Object.create(null);
52
+ for (const [name, value] of Object.entries(ambient)) {
53
+ if (value !== void 0 && isInheritedName(name) && !isCredentialName(name)) environment[name] = value;
54
+ }
55
+ for (const [name, value] of Object.entries(declared)) {
56
+ remove(environment, name);
57
+ if (value !== void 0) environment[name] = value;
58
+ }
59
+ return environment;
60
+ };
61
+ //# sourceMappingURL=ChildProcessEnvironment.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ChildProcessEnvironment.ts"],
4
+ "sourcesContent": ["/**\n * Least-authority environment construction for child processes.\n *\n * @since 1.0.0-rc.0\n */\n\n/**\n * Credential-bearing field names shared with the model request boundary.\n *\n * `token`, `key` (optionally followed by a separated `id`), and `pat` are\n * anchored to complete or separator-delimited suffixes so names such as\n * `TOKEN_COUNT` and `KEYBOARD` remain ordinary diagnostics. Keeping this rule\n * below the model and process layers gives request validation and child\n * spawning one definition of a sensitive name.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const credentialNamePattern =\n /authorization|api[-_]?key|access[-_]?token|refresh[-_]?token|id[-_]?token|auth[-_]?token|api[-_]?token|session[-_]?token|bearer|(?:^|[-_])token$|(?:^|[-_])key(?:[-_]id)?$|(?:^|[-_])pat$|secret|credential|password|passphrase|passwd|signature|x-amz-signature|cookie|set[-_]?cookie|chatgpt[-_]?account[-_]?id/i\n\n/**\n * Reports whether a field name conventionally carries credentials.\n *\n * @category predicates\n * @since 1.0.0-rc.0\n */\nexport const isCredentialName = (name: string): boolean => credentialNamePattern.test(name)\n\n/**\n * Ambient variables a child may inherit for executable lookup, identity,\n * locale, terminal behavior, temporary files, and its shell.\n *\n * Locale category variables are admitted separately by their `LC_` prefix.\n *\n * @category constants\n * @since 1.0.0-rc.0\n */\nexport const inheritedNames: ReadonlyArray<string> = Object.freeze([\n \"PATH\",\n \"HOME\",\n \"USER\",\n \"LANG\",\n \"TERM\",\n \"TMPDIR\",\n \"SHELL\"\n])\n\nconst inherited = new Set(inheritedNames)\n\n/**\n * Reports whether a variable belongs to the bootstrap set {@link make}\n * inherits: one of {@link inheritedNames} or a locale `LC_` category,\n * compared case-insensitively.\n *\n * @category predicates\n * @since 1.0.0-rc.1\n */\nexport const isInheritedName = (name: string): boolean => {\n const canonical = name.toUpperCase()\n return inherited.has(canonical) || canonical.startsWith(\"LC_\")\n}\n\nconst remove = (environment: Record<string, string>, name: string): void => {\n const canonical = name.toUpperCase()\n for (const present of Object.keys(environment)) {\n if (present.toUpperCase() === canonical) delete environment[present]\n }\n}\n\n/**\n * Selects the bootstrap allowlist from an ambient environment and overlays\n * caller-declared names.\n *\n * Sensitive-looking ambient names are withheld even if a future bootstrap\n * list grows to include one. A caller declaration is applied last because it\n * is the explicit authority for that child; an `undefined` declaration\n * removes an inherited name. The returned null-prototype record is always\n * suitable as a replacement environment and never asks the spawner to merge\n * the rest of the host process environment.\n *\n * @category constructors\n * @since 1.0.0-rc.0\n */\nexport const make = (\n ambient: Readonly<Record<string, string | undefined>>,\n declared: Readonly<Record<string, string | undefined>> = {}\n): Record<string, string> => {\n const environment = Object.create(null) as Record<string, string>\n for (const [name, value] of Object.entries(ambient)) {\n if (value !== undefined && isInheritedName(name) && !isCredentialName(name)) environment[name] = value\n }\n for (const [name, value] of Object.entries(declared)) {\n remove(environment, name)\n if (value !== undefined) environment[name] = value\n }\n return environment\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBO,MAAM,wBACX;AAQK,MAAM,mBAAmB,CAAC,SAA0B,sBAAsB,KAAK,IAAI;AAWnF,MAAM,iBAAwC,OAAO,OAAO;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,MAAM,YAAY,IAAI,IAAI,cAAc;AAUjC,MAAM,kBAAkB,CAAC,SAA0B;AACxD,QAAM,YAAY,KAAK,YAAY;AACnC,SAAO,UAAU,IAAI,SAAS,KAAK,UAAU,WAAW,KAAK;AAC/D;AAEA,MAAM,SAAS,CAAC,aAAqC,SAAuB;AAC1E,QAAM,YAAY,KAAK,YAAY;AACnC,aAAW,WAAW,OAAO,KAAK,WAAW,GAAG;AAC9C,QAAI,QAAQ,YAAY,MAAM,UAAW,QAAO,YAAY,OAAO;AAAA,EACrE;AACF;AAgBO,MAAM,OAAO,CAClB,SACA,WAAyD,CAAC,MAC/B;AAC3B,QAAM,cAAc,uBAAO,OAAO,IAAI;AACtC,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AACnD,QAAI,UAAU,UAAa,gBAAgB,IAAI,KAAK,CAAC,iBAAiB,IAAI,EAAG,aAAY,IAAI,IAAI;AAAA,EACnG;AACA,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACpD,WAAO,aAAa,IAAI;AACxB,QAAI,UAAU,OAAW,aAAY,IAAI,IAAI;AAAA,EAC/C;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }