@smthrs/kernel 0.0.0-stage → 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +206 -0
- package/LICENSE +21 -0
- package/README.md +154 -2
- package/dist/cjs/CapabilitySet.d.ts +6 -0
- package/dist/cjs/CapabilitySet.d.ts.map +1 -0
- package/dist/cjs/CapabilitySet.js +19 -0
- package/dist/cjs/CapabilitySet.js.map +7 -0
- package/dist/cjs/ChildProcessEnvironment.d.ts +60 -0
- package/dist/cjs/ChildProcessEnvironment.d.ts.map +1 -0
- package/dist/cjs/ChildProcessEnvironment.js +61 -0
- package/dist/cjs/ChildProcessEnvironment.js.map +7 -0
- package/dist/cjs/ChildProcessSpawner.d.ts +100 -0
- package/dist/cjs/ChildProcessSpawner.d.ts.map +1 -0
- package/dist/cjs/ChildProcessSpawner.js +291 -0
- package/dist/cjs/ChildProcessSpawner.js.map +7 -0
- package/dist/cjs/CommandLine.d.ts +173 -0
- package/dist/cjs/CommandLine.d.ts.map +1 -0
- package/dist/cjs/CommandLine.js +54 -0
- package/dist/cjs/CommandLine.js.map +7 -0
- package/dist/cjs/ContainedSpawner.d.ts +135 -0
- package/dist/cjs/ContainedSpawner.d.ts.map +1 -0
- package/dist/cjs/ContainedSpawner.js +141 -0
- package/dist/cjs/ContainedSpawner.js.map +7 -0
- package/dist/cjs/FileSystem.d.ts +452 -0
- package/dist/cjs/FileSystem.d.ts.map +1 -0
- package/dist/cjs/FileSystem.js +890 -0
- package/dist/cjs/FileSystem.js.map +7 -0
- package/dist/cjs/FileSystemBatch.d.ts +94 -0
- package/dist/cjs/FileSystemBatch.d.ts.map +1 -0
- package/dist/cjs/FileSystemBatch.js +31 -0
- package/dist/cjs/FileSystemBatch.js.map +7 -0
- package/dist/cjs/GrantEvent.d.ts +240 -0
- package/dist/cjs/GrantEvent.d.ts.map +1 -0
- package/dist/cjs/GrantEvent.js +115 -0
- package/dist/cjs/GrantEvent.js.map +7 -0
- package/dist/cjs/GrantStore.d.ts +270 -0
- package/dist/cjs/GrantStore.d.ts.map +1 -0
- package/dist/cjs/GrantStore.js +857 -0
- package/dist/cjs/GrantStore.js.map +7 -0
- package/dist/cjs/HostError.d.ts +36 -0
- package/dist/cjs/HostError.d.ts.map +1 -0
- package/dist/cjs/HostError.js +17 -0
- package/dist/cjs/HostError.js.map +7 -0
- package/dist/cjs/HostServices.d.ts +101 -0
- package/dist/cjs/HostServices.d.ts.map +1 -0
- package/dist/cjs/HostServices.js +66 -0
- package/dist/cjs/HostServices.js.map +7 -0
- package/dist/cjs/HttpClient.d.ts +177 -0
- package/dist/cjs/HttpClient.d.ts.map +1 -0
- package/dist/cjs/HttpClient.js +217 -0
- package/dist/cjs/HttpClient.js.map +7 -0
- package/dist/cjs/Jj.d.ts +67 -0
- package/dist/cjs/Jj.d.ts.map +1 -0
- package/dist/cjs/Jj.js +118 -0
- package/dist/cjs/Jj.js.map +7 -0
- package/dist/cjs/JournalGrantStore.d.ts +65 -0
- package/dist/cjs/JournalGrantStore.d.ts.map +1 -0
- package/dist/cjs/JournalGrantStore.js +354 -0
- package/dist/cjs/JournalGrantStore.js.map +7 -0
- package/dist/cjs/Path.d.ts +37 -0
- package/dist/cjs/Path.d.ts.map +1 -0
- package/dist/cjs/Path.js +46 -0
- package/dist/cjs/Path.js.map +7 -0
- package/dist/cjs/ProcessConfinement.d.ts +55 -0
- package/dist/cjs/ProcessConfinement.d.ts.map +1 -0
- package/dist/cjs/ProcessConfinement.js +94 -0
- package/dist/cjs/ProcessConfinement.js.map +7 -0
- package/dist/cjs/ProcessLedger.d.ts +260 -0
- package/dist/cjs/ProcessLedger.d.ts.map +1 -0
- package/dist/cjs/ProcessLedger.js +190 -0
- package/dist/cjs/ProcessLedger.js.map +7 -0
- package/dist/cjs/Rooted.d.ts +53 -0
- package/dist/cjs/Rooted.d.ts.map +1 -0
- package/dist/cjs/Rooted.js +101 -0
- package/dist/cjs/Rooted.js.map +7 -0
- package/dist/cjs/Unreachable.d.ts +27 -0
- package/dist/cjs/Unreachable.d.ts.map +1 -0
- package/dist/cjs/Unreachable.js +43 -0
- package/dist/cjs/Unreachable.js.map +7 -0
- package/dist/cjs/Workspace.d.ts +62 -0
- package/dist/cjs/Workspace.d.ts.map +1 -0
- package/dist/cjs/Workspace.js +35 -0
- package/dist/cjs/Workspace.js.map +7 -0
- package/dist/cjs/index.d.ts +161 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +73 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/Containment.d.ts +24 -0
- package/dist/cjs/internal/Containment.d.ts.map +1 -0
- package/dist/cjs/internal/Containment.js +30 -0
- package/dist/cjs/internal/Containment.js.map +7 -0
- package/dist/cjs/internal/Pipeline.d.ts +18 -0
- package/dist/cjs/internal/Pipeline.d.ts.map +1 -0
- package/dist/cjs/internal/Pipeline.js +90 -0
- package/dist/cjs/internal/Pipeline.js.map +7 -0
- package/dist/cjs/internal/makeCapability.d.ts +16 -0
- package/dist/cjs/internal/makeCapability.d.ts.map +1 -0
- package/dist/cjs/internal/makeCapability.js +44 -0
- package/dist/cjs/internal/makeCapability.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/test/FileSystemBatchContract.d.ts +15 -0
- package/dist/cjs/test/FileSystemBatchContract.d.ts.map +1 -0
- package/dist/cjs/test/FileSystemBatchContract.js +76 -0
- package/dist/cjs/test/FileSystemBatchContract.js.map +7 -0
- package/dist/cjs/test/HostContract.d.ts +225 -0
- package/dist/cjs/test/HostContract.d.ts.map +1 -0
- package/dist/cjs/test/HostContract.js +489 -0
- package/dist/cjs/test/HostContract.js.map +7 -0
- package/dist/cjs/test/TestGrantStore.d.ts +31 -0
- package/dist/cjs/test/TestGrantStore.d.ts.map +1 -0
- package/dist/cjs/test/TestGrantStore.js +65 -0
- package/dist/cjs/test/TestGrantStore.js.map +7 -0
- package/dist/esm/CapabilitySet.d.ts +6 -0
- package/dist/esm/CapabilitySet.d.ts.map +1 -0
- package/dist/esm/CapabilitySet.js +6 -0
- package/dist/esm/CapabilitySet.js.map +1 -0
- package/dist/esm/ChildProcessEnvironment.d.ts +60 -0
- package/dist/esm/ChildProcessEnvironment.d.ts.map +1 -0
- package/dist/esm/ChildProcessEnvironment.js +91 -0
- package/dist/esm/ChildProcessEnvironment.js.map +1 -0
- package/dist/esm/ChildProcessSpawner.d.ts +100 -0
- package/dist/esm/ChildProcessSpawner.d.ts.map +1 -0
- package/dist/esm/ChildProcessSpawner.js +342 -0
- package/dist/esm/ChildProcessSpawner.js.map +1 -0
- package/dist/esm/CommandLine.d.ts +173 -0
- package/dist/esm/CommandLine.d.ts.map +1 -0
- package/dist/esm/CommandLine.js +195 -0
- package/dist/esm/CommandLine.js.map +1 -0
- package/dist/esm/ContainedSpawner.d.ts +135 -0
- package/dist/esm/ContainedSpawner.d.ts.map +1 -0
- package/dist/esm/ContainedSpawner.js +180 -0
- package/dist/esm/ContainedSpawner.js.map +1 -0
- package/dist/esm/FileSystem.d.ts +452 -0
- package/dist/esm/FileSystem.d.ts.map +1 -0
- package/dist/esm/FileSystem.js +989 -0
- package/dist/esm/FileSystem.js.map +1 -0
- package/dist/esm/FileSystemBatch.d.ts +94 -0
- package/dist/esm/FileSystemBatch.d.ts.map +1 -0
- package/dist/esm/FileSystemBatch.js +26 -0
- package/dist/esm/FileSystemBatch.js.map +1 -0
- package/dist/esm/GrantEvent.d.ts +240 -0
- package/dist/esm/GrantEvent.d.ts.map +1 -0
- package/dist/esm/GrantEvent.js +155 -0
- package/dist/esm/GrantEvent.js.map +1 -0
- package/dist/esm/GrantStore.d.ts +270 -0
- package/dist/esm/GrantStore.d.ts.map +1 -0
- package/dist/esm/GrantStore.js +951 -0
- package/dist/esm/GrantStore.js.map +1 -0
- package/dist/esm/HostError.d.ts +36 -0
- package/dist/esm/HostError.d.ts.map +1 -0
- package/dist/esm/HostError.js +20 -0
- package/dist/esm/HostError.js.map +1 -0
- package/dist/esm/HostServices.d.ts +101 -0
- package/dist/esm/HostServices.d.ts.map +1 -0
- package/dist/esm/HostServices.js +76 -0
- package/dist/esm/HostServices.js.map +1 -0
- package/dist/esm/HttpClient.d.ts +177 -0
- package/dist/esm/HttpClient.d.ts.map +1 -0
- package/dist/esm/HttpClient.js +299 -0
- package/dist/esm/HttpClient.js.map +1 -0
- package/dist/esm/Jj.d.ts +67 -0
- package/dist/esm/Jj.d.ts.map +1 -0
- package/dist/esm/Jj.js +111 -0
- package/dist/esm/Jj.js.map +1 -0
- package/dist/esm/JournalGrantStore.d.ts +65 -0
- package/dist/esm/JournalGrantStore.d.ts.map +1 -0
- package/dist/esm/JournalGrantStore.js +350 -0
- package/dist/esm/JournalGrantStore.js.map +1 -0
- package/dist/esm/Path.d.ts +37 -0
- package/dist/esm/Path.d.ts.map +1 -0
- package/dist/esm/Path.js +34 -0
- package/dist/esm/Path.js.map +1 -0
- package/dist/esm/ProcessConfinement.d.ts +55 -0
- package/dist/esm/ProcessConfinement.d.ts.map +1 -0
- package/dist/esm/ProcessConfinement.js +106 -0
- package/dist/esm/ProcessConfinement.js.map +1 -0
- package/dist/esm/ProcessLedger.d.ts +260 -0
- package/dist/esm/ProcessLedger.d.ts.map +1 -0
- package/dist/esm/ProcessLedger.js +283 -0
- package/dist/esm/ProcessLedger.js.map +1 -0
- package/dist/esm/Rooted.d.ts +53 -0
- package/dist/esm/Rooted.d.ts.map +1 -0
- package/dist/esm/Rooted.js +104 -0
- package/dist/esm/Rooted.js.map +1 -0
- package/dist/esm/Unreachable.d.ts +27 -0
- package/dist/esm/Unreachable.d.ts.map +1 -0
- package/dist/esm/Unreachable.js +26 -0
- package/dist/esm/Unreachable.js.map +1 -0
- package/dist/esm/Workspace.d.ts +62 -0
- package/dist/esm/Workspace.d.ts.map +1 -0
- package/dist/esm/Workspace.js +51 -0
- package/dist/esm/Workspace.js.map +1 -0
- package/dist/esm/index.d.ts +161 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +151 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/Containment.d.ts +24 -0
- package/dist/esm/internal/Containment.d.ts.map +1 -0
- package/dist/esm/internal/Containment.js +27 -0
- package/dist/esm/internal/Containment.js.map +1 -0
- package/dist/esm/internal/Pipeline.d.ts +18 -0
- package/dist/esm/internal/Pipeline.d.ts.map +1 -0
- package/dist/esm/internal/Pipeline.js +68 -0
- package/dist/esm/internal/Pipeline.js.map +1 -0
- package/dist/esm/internal/makeCapability.d.ts +16 -0
- package/dist/esm/internal/makeCapability.d.ts.map +1 -0
- package/dist/esm/internal/makeCapability.js +22 -0
- package/dist/esm/internal/makeCapability.js.map +1 -0
- package/dist/esm/test/FileSystemBatchContract.d.ts +15 -0
- package/dist/esm/test/FileSystemBatchContract.d.ts.map +1 -0
- package/dist/esm/test/FileSystemBatchContract.js +57 -0
- package/dist/esm/test/FileSystemBatchContract.js.map +1 -0
- package/dist/esm/test/HostContract.d.ts +225 -0
- package/dist/esm/test/HostContract.d.ts.map +1 -0
- package/dist/esm/test/HostContract.js +460 -0
- package/dist/esm/test/HostContract.js.map +1 -0
- package/dist/esm/test/TestGrantStore.d.ts +31 -0
- package/dist/esm/test/TestGrantStore.d.ts.map +1 -0
- package/dist/esm/test/TestGrantStore.js +57 -0
- package/dist/esm/test/TestGrantStore.js.map +1 -0
- package/docs/README.md +162 -0
- package/docs/api.md +1532 -0
- package/docs/concepts/decoration-in-place.md +117 -0
- package/docs/concepts/filesystem-batches.md +58 -0
- package/docs/concepts/filesystem-confinement.md +168 -0
- package/docs/concepts/grant-decisions.md +181 -0
- package/docs/concepts/process-containment.md +155 -0
- package/docs/contract.md +14 -0
- package/docs/guides/adapt-a-new-host-platform.md +148 -0
- package/docs/guides/answer-permission-requests.md +151 -0
- package/docs/guides/authorize-network-and-model-calls.md +118 -0
- package/docs/guides/contain-spawned-processes.md +118 -0
- package/docs/guides/guard-a-host-bundle.md +109 -0
- package/docs/guides/persist-grants-across-restarts.md +135 -0
- package/docs/guides/write-a-capability-policy.md +159 -0
- package/docs/installation.md +115 -0
- package/docs/quickstart.md +182 -0
- package/docs/testing.md +108 -0
- package/docs/troubleshooting.md +281 -0
- package/package.json +344 -3
- package/src/CapabilitySet.ts +6 -0
- package/src/ChildProcessEnvironment.ts +98 -0
- package/src/ChildProcessSpawner.ts +414 -0
- package/src/CommandLine.ts +250 -0
- package/src/ContainedSpawner.ts +284 -0
- package/src/FileSystem.ts +1655 -0
- package/src/FileSystemBatch.ts +90 -0
- package/src/GrantEvent.ts +174 -0
- package/src/GrantStore.ts +1345 -0
- package/src/HostError.ts +37 -0
- package/src/HostServices.ts +133 -0
- package/src/HttpClient.ts +406 -0
- package/src/Jj.ts +159 -0
- package/src/JournalGrantStore.ts +461 -0
- package/src/Path.ts +47 -0
- package/src/ProcessConfinement.ts +156 -0
- package/src/ProcessLedger.ts +423 -0
- package/src/Rooted.ts +128 -0
- package/src/Unreachable.ts +30 -0
- package/src/Workspace.ts +65 -0
- package/src/index.ts +181 -0
- package/src/internal/Containment.ts +37 -0
- package/src/internal/Pipeline.ts +85 -0
- package/src/internal/makeCapability.ts +26 -0
- package/src/test/FileSystemBatchContract.ts +59 -0
- package/src/test/HostContract.ts +785 -0
- 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
|
-
#
|
|
1
|
+
# @smthrs/kernel
|
|
2
2
|
|
|
3
|
-
|
|
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 @@
|
|
|
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
|
+
}
|