@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
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/GrantStore.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * In-memory capability grants with an attended Deferred request lifecycle.\n *\n * Governing design:\n * `docs/specs/Concepts/Permission Kernel.md` and\n * `docs/specs/Concepts/Trust Granularity.md`.\n *\n * @since 1.0.0-rc.0\n */\n\nimport {\n type Capability,\n Capability as CapabilityValue,\n CapabilityPattern,\n type EffectTier,\n format,\n matches,\n maxResourceLength,\n parsePattern,\n patternFromCapability,\n subsumes,\n tierOf\n} from \"@smthrs/capability/Capability\"\nimport {\n evaluate,\n GrantStoreError,\n type PermissionDenied,\n permissionDenied,\n type PermissionRequired,\n permissionRequired,\n Rule\n} from \"@smthrs/capability/Permission\"\nimport { digestSync } from \"@smthrs/crypto/Sha256\"\nimport { Cause, Context, Deferred, Effect, Layer, Option, Schema, type Scope, Semaphore } from \"effect\"\nimport { allows, type CapabilitySet, current, fromPatterns, intersect } from \"./CapabilitySet.ts\"\nimport { DeniedGrant, EnvelopeGrant, type GrantEvent, OnceGrant, RememberedGrant, RunGrant } from \"./GrantEvent.ts\"\nimport { Workspace } from \"./Workspace.ts\"\n\n/**\n * A capability request waiting for an attended reply.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface PendingRequest {\n readonly requestId: string\n readonly capability: Capability\n readonly tier: EffectTier\n readonly meta: Record<string, unknown>\n}\n\n/**\n * A resolution supplied by an attended permission surface.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type Resolution = \"once\" | \"run\" | \"remembered\" | \"deny\"\n\n/**\n * Scope and plan identity for a bulk envelope approval.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface EnvelopeGrantOptions {\n readonly planDigest: string\n readonly patterns: ReadonlyArray<CapabilityPattern>\n readonly scope?: \"run\" | \"remembered\" | undefined\n}\n\n/** A policy rule and the authority captured when it was granted.\n * @category models\n * @since 1.0.0-rc.1\n */\nexport interface PolicyRule {\n readonly rule: Rule\n readonly ceiling: Pick<CapabilitySet, \"groups\">\n}\n\n/** Atomic ordered policy snapshot, bounded by the calling fiber.\n * @category models\n * @since 1.0.0-rc.1\n */\nexport interface Policy {\n readonly groups: ReadonlyArray<ReadonlyArray<PolicyRule>>\n readonly ceiling: CapabilitySet\n}\n\n/** A conservative snapshot for services that expose no durable authority.\n * @category constructors\n * @since 1.0.0-rc.1\n */\nexport const emptyPolicy: Effect.Effect<Policy> = current.pipe(\n Effect.map((ceiling) => Object.freeze({ groups: Object.freeze([]), ceiling }))\n)\n\n/** Operations exposed by the grant store.\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface Service {\n readonly policy: Effect.Effect<Policy, GrantStoreError>\n readonly check: (\n capability: Capability,\n meta?: Record<string, unknown>\n ) => Effect.Effect<void, PermissionRequired | PermissionDenied | GrantStoreError>\n readonly reply: (\n requestId: string,\n resolution: Resolution,\n pattern?: CapabilityPattern\n ) => Effect.Effect<void, GrantStoreError>\n readonly list: Effect.Effect<ReadonlyArray<PendingRequest>>\n readonly grantEnvelope: (options: EnvelopeGrantOptions) => Effect.Effect<void, GrantStoreError>\n}\n\n/**\n * Service key for permission decisions and attended grant requests.\n *\n * @category services\n * @since 1.0.0-rc.0\n */\nexport class GrantStore extends Context.Service<GrantStore, Service>()(\"@smthrs/kernel/GrantStore\") {}\n\n/**\n * A hook that durably records a grant decision before it becomes active.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type Persist = (event: GrantEvent) => Effect.Effect<void, GrantStoreError>\n\n/**\n * Configuration for an in-memory grant store.\n *\n * A nested `rules` value is also accepted by the journal adapter: its first\n * ruleset is configured policy and subsequent rulesets are replayed remembered\n * grants.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface MakeOptions {\n readonly attended?: boolean | undefined\n readonly rules?: ReadonlyArray<Rule> | ReadonlyArray<ReadonlyArray<Rule>> | undefined\n /** Bare rules use the constructor ceiling; captured groups intersect it. */\n readonly runRules?:\n | ReadonlyArray<\n Rule | {\n readonly rule: Rule\n readonly ceiling: ReadonlyArray<ReadonlyArray<CapabilityPattern>>\n }\n >\n | undefined\n readonly envelope?: EnvelopeGrantOptions | undefined\n /**\n * {@link envelopeSignature} values of envelopes that are already durable \u2014\n * typically replayed from a journal. A construction or runtime envelope\n * matching a seeded signature still activates its rules but is not\n * persisted again.\n */\n readonly envelopeSignatures?: ReadonlyArray<string> | undefined\n readonly runId?: string | undefined\n readonly planDigest?: string | undefined\n readonly persist?: Persist | undefined\n}\n\ninterface PendingEntry extends PendingRequest {\n readonly ceiling: CapabilitySet\n readonly deferred: Deferred.Deferred<void, PermissionDenied>\n}\n\n/**\n * Maximum policy rules retained by one store.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumRules = 1_024\n/**\n * Maximum predicates in one approval envelope.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumEnvelopePatterns = 256\n/**\n * Maximum permission requests parked at once.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumPendingRequests = 1_024\n/**\n * Maximum nesting depth of permission metadata.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumMetadataDepth = 16\n/**\n * Maximum members across one permission metadata graph.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumMetadataMembers = 1_024\n/**\n * Maximum encoded bytes retained for one metadata value.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumMetadataBytes = 64 * 1024\n/**\n * Maximum encoded bytes persisted for one grant event.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumEventBytes = 256 * 1024\n/**\n * Maximum milliseconds one grant journal write may take before its reply or\n * envelope admission fails with `journal_failed`. Journal writes never hold\n * the store's mutation permit, so a slow write stalls only the admission that\n * issued it.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumPersistMillis = 30_000\n/**\n * Maximum length of a run, plan, request, or signature identity.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumIdentityLength = 4_096\n/**\n * Maximum capability resource length enforced by the capability vocabulary.\n * @category limits\n * @since 1.0.0-rc.0\n */\nexport const maximumCapabilityResourceLength = maxResourceLength\n\nconst encoder = new TextEncoder()\n\nconst isWellFormed = (value: string): boolean => {\n for (let index = 0; index < value.length; index += 1) {\n const unit = value.charCodeAt(index)\n if (unit >= 0xd800 && unit <= 0xdbff) {\n const next = value.charCodeAt(index + 1)\n if (!(next >= 0xdc00 && next <= 0xdfff)) return false\n index += 1\n } else if (unit >= 0xdc00 && unit <= 0xdfff) {\n return false\n }\n }\n return true\n}\n\nconst invalid = (message: string): GrantStoreError => new GrantStoreError({ code: \"invalid_resolution\", message })\n\nconst immutableFields = <A extends object, K extends keyof A>(\n value: A,\n fields: ReadonlyArray<K>\n): A => {\n for (const field of fields) {\n Object.defineProperty(value, field, {\n value: value[field],\n enumerable: true,\n writable: false,\n configurable: false\n })\n }\n return value\n}\n\nconst snapshotCapability = (capability: Capability): Capability =>\n immutableFields(\n new CapabilityValue({ action: capability.action, resource: capability.resource }),\n [\"action\", \"resource\"]\n )\n\nconst snapshotPattern = (pattern: CapabilityPattern): CapabilityPattern =>\n immutableFields(\n new CapabilityPattern({ action: pattern.action, resource: pattern.resource }),\n [\"action\", \"resource\"]\n )\n\nconst snapshotRule = (rule: Rule): Rule =>\n immutableFields(\n new Rule({ effect: rule.effect, pattern: snapshotPattern(rule.pattern) }),\n [\"effect\", \"pattern\"]\n )\n\nconst snapshotFailure = (what: string, cause: unknown): GrantStoreError =>\n cause instanceof GrantStoreError ? cause : invalid(`${what} is invalid`)\n\nconst attemptSnapshot = <A>(what: string, evaluate: () => A): Effect.Effect<A, GrantStoreError> =>\n Effect.try({\n try: evaluate,\n catch: (cause) => snapshotFailure(what, cause)\n })\n\ntype Json = null | boolean | number | string | ReadonlyArray<Json> | { readonly [key: string]: Json }\n\nconst metadataSnapshot = (input: Readonly<Record<string, unknown>>): Readonly<Record<string, Json>> => {\n let members = 0\n const active = new WeakSet<object>()\n\n const visit = (value: unknown, depth: number): Json => {\n if (depth > maximumMetadataDepth) throw invalid(`metadata exceeds depth ${maximumMetadataDepth}`)\n if (value === null || typeof value === \"boolean\") return value\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw invalid(\"metadata contains a non-finite number\")\n return value\n }\n if (typeof value === \"string\") {\n if (!isWellFormed(value)) throw invalid(\"metadata contains ill-formed text\")\n if (value.length > maximumMetadataBytes) throw invalid(`metadata exceeds ${maximumMetadataBytes} bytes`)\n return value\n }\n if (typeof value !== \"object\" || value === null) throw invalid(\"metadata must be JSON data\")\n if (active.has(value)) throw invalid(\"metadata must not contain cycles\")\n active.add(value)\n try {\n if (Array.isArray(value)) {\n const descriptors = Object.getOwnPropertyDescriptors(value)\n const snapshot: Array<Json> = []\n for (let index = 0; index < value.length; index += 1) {\n members += 1\n if (members > maximumMetadataMembers) {\n throw invalid(`metadata exceeds ${maximumMetadataMembers} members`)\n }\n const descriptor = descriptors[String(index)]\n if (descriptor === undefined || !(\"value\" in descriptor)) {\n throw invalid(\"metadata arrays must be dense data\")\n }\n snapshot.push(visit(descriptor.value, depth + 1))\n }\n return Object.freeze(snapshot)\n }\n\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype && prototype !== null) {\n throw invalid(\"metadata objects must be plain records\")\n }\n const snapshot: Record<string, Json> = Object.create(null)\n for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {\n if (!descriptor.enumerable) continue\n members += 1\n if (members > maximumMetadataMembers) {\n throw invalid(`metadata exceeds ${maximumMetadataMembers} members`)\n }\n if (!isWellFormed(key) || !(\"value\" in descriptor)) {\n throw invalid(\"metadata members must be well-formed data properties\")\n }\n if (descriptor.value !== undefined) snapshot[key] = visit(descriptor.value, depth + 1)\n }\n return Object.freeze(snapshot)\n } finally {\n active.delete(value)\n }\n }\n\n const snapshot = visit(input, 0)\n if (Array.isArray(snapshot) || snapshot === null || typeof snapshot !== \"object\") {\n throw invalid(\"metadata must be a record\")\n }\n const encoded = JSON.stringify(snapshot)\n if (encoder.encode(encoded).byteLength > maximumMetadataBytes) {\n throw invalid(`metadata exceeds ${maximumMetadataBytes} bytes`)\n }\n return snapshot as Readonly<Record<string, Json>>\n}\n\nconst validIdentity = (value: unknown): value is string | undefined =>\n value === undefined ||\n (typeof value === \"string\" &&\n value.length > 0 &&\n value.length <= maximumIdentityLength &&\n isWellFormed(value) &&\n !value.includes(\"\\0\"))\n\nconst prepareEnvelope = (\n input: EnvelopeGrantOptions,\n expectedPlanDigest: string | undefined,\n workspaceRoot: string\n): Effect.Effect<{\n readonly planDigest: string\n readonly scope: \"run\" | \"remembered\"\n readonly patterns: ReadonlyArray<CapabilityPattern>\n}, GrantStoreError> =>\n attemptSnapshot(\"grant envelope\", () => {\n if (!Array.isArray(input.patterns)) throw invalid(\"patterns must be an array\")\n if (input.patterns.length > maximumEnvelopePatterns) {\n throw invalid(`patterns exceed ${maximumEnvelopePatterns} entries`)\n }\n const patterns = canonicalEnvelopePatterns(input.patterns)\n // An empty envelope carries no authority. It is deliberately a no-op even\n // when replayed without the plan identity that authorized a non-empty one.\n if (patterns.length === 0) {\n return { planDigest: expectedPlanDigest ?? \"\", scope: \"run\" as const, patterns }\n }\n const scope = input.scope ?? \"run\"\n if (!isEnvelopeScope(scope)) throw invalid(\"scope must be run or remembered\")\n if (expectedPlanDigest === undefined) throw invalid(\"grant envelope requires a configured planDigest\")\n if (!validIdentity(input.planDigest)) throw invalid(\"planDigest is empty, malformed, or too long\")\n if (input.planDigest !== expectedPlanDigest) throw invalid(\"planDigest mismatch\")\n for (let index = 0; index < patterns.length; index += 1) {\n if (!isValidEnvelopePattern(patterns[index]!, workspaceRoot)) {\n throw invalid(`patterns[${index}] is outside the workspace envelope`)\n }\n }\n return { planDigest: input.planDigest, scope, patterns }\n })\n\n/**\n * Records the displayed capability for once/deny audit events, which are never\n * installed or replayed as authority.\n */\nconst exactPattern = (capability: Capability): CapabilityPattern =>\n new CapabilityPattern({\n action: capability.action,\n resource: capability.resource\n })\n\nconst hasResourceWildcard = (resource: string): boolean => resource.includes(\"*\") || resource.includes(\"?\")\n\nconst isResolution = (value: string): value is Resolution =>\n value === \"once\" || value === \"run\" || value === \"remembered\" || value === \"deny\"\n\nconst isEnvelopeScope = (value: string): value is \"run\" | \"remembered\" => value === \"run\" || value === \"remembered\"\n\n/**\n * Canonicalizes an envelope pattern list: duplicate predicates collapse to\n * their first occurrence and the survivors sort by their formatted identity.\n *\n * An envelope is a *set* of predicates, so two envelopes listing the same\n * predicates in a different order or multiplicity are the same approval. Every\n * envelope is canonicalized before it is persisted or compared, which makes\n * envelope idempotency structural rather than dependent on caller discipline.\n *\n * The ordering is the code-unit sort of `format(pattern)` \u2014 the one renderer\n * for capability identity. RFC 8785 canonical JSON (`@smthrs/canonical`)\n * was considered and does not fit: it canonicalizes object keys but preserves\n * array order as semantic, and the ordering that matters here is exactly the\n * pattern-array order.\n *\n * @category validation\n * @since 1.0.0-rc.0\n */\nexport const canonicalEnvelopePatterns = (\n patterns: ReadonlyArray<CapabilityPattern>\n): ReadonlyArray<CapabilityPattern> => {\n const byIdentity = new Map<string, CapabilityPattern>()\n for (const input of patterns) {\n const pattern = snapshotPattern(input)\n const identity = format(pattern)\n if (!byIdentity.has(identity)) {\n byIdentity.set(identity, pattern)\n }\n }\n return Object.freeze([...byIdentity.keys()].sort().map((identity) => byIdentity.get(identity)!))\n}\n\nconst envelopeEncoding = (\n planDigest: string,\n scope: \"run\" | \"remembered\",\n patterns: ReadonlyArray<CapabilityPattern>\n): string => JSON.stringify({ planDigest, scope, patterns: canonicalEnvelopePatterns(patterns).map(format) })\n\n/**\n * Computes the canonical identity of an envelope approval.\n *\n * Two envelopes with the same plan digest, scope, and predicate set produce\n * the same signature regardless of pattern order or repetition. The signature\n * is how the store, and journal replay above it, recognise an envelope that\n * is already durable. It is `sha256:` followed by 64 lowercase hex digits.\n *\n * @category validation\n * @since 1.0.0-rc.0\n */\nexport const envelopeSignature = (\n planDigest: string,\n scope: \"run\" | \"remembered\",\n patterns: ReadonlyArray<CapabilityPattern>\n): string => `sha256:${digestSync(envelopeEncoding(planDigest, scope, patterns))}`\n\nconst decodeLegacySignature = Schema.decodeUnknownResult(\n Schema.fromJsonString(Schema.Struct({\n planDigest: Schema.String,\n scope: Schema.Literals([\"run\", \"remembered\"]),\n patterns: Schema.Array(Schema.String).check(Schema.isMaxLength(maximumEnvelopePatterns))\n })),\n { onExcessProperty: \"error\" }\n)\n\n// v1 events contain predicates, not signatures, and replay hashes them afresh.\n// Also accept canonical full-JSON identities supplied by older seed callers.\nconst normalizeEnvelopeSignature = (value: string): string => {\n if (!value.startsWith(\"{\")) return value\n if (value.length > maximumEventBytes || encoder.encode(value).byteLength > maximumEventBytes) return value\n const decoded = decodeLegacySignature(value)\n if (decoded._tag === \"Failure\" || !validIdentity(decoded.success.planDigest)) return value\n const { planDigest, scope, patterns } = decoded.success\n const parsed = Option.all(patterns.map(parsePattern))\n if (Option.isNone(parsed) || envelopeEncoding(planDigest, scope, parsed.value) !== value) return value\n return envelopeSignature(planDigest, scope, parsed.value)\n}\n\n/**\n * Checks that a request-scoped grant cannot authorize a different action or a\n * more dangerous effect tier than the request displayed to the user. A\n * wildcard-bearing pattern identical to the resource is ambiguous because the\n * grammar has no escape, so its wildcard reading would silently widen access.\n *\n * @category validation\n * @since 1.0.0-rc.0\n */\nexport const isValidGrantPattern = (\n pattern: CapabilityPattern,\n capability: Capability,\n tier: EffectTier,\n workspaceRoot: string\n): boolean => {\n if (pattern.action !== capability.action || !matches(pattern, capability)) {\n return false\n }\n if (hasResourceWildcard(pattern.resource) && pattern.resource === capability.resource) {\n return false\n }\n if (tierOf(capability, { workspaceRoot }) !== tier) {\n return false\n }\n if (capability.action !== \"fs:write\") {\n return true\n }\n if (tier === \"irreversible\") {\n return !hasResourceWildcard(pattern.resource)\n }\n const workspacePattern = new CapabilityPattern({\n action: \"fs:write\",\n resource: `${workspaceRoot.replace(/[\\\\/]+$/, \"\")}/**`\n })\n return pattern.resource === workspaceRoot || subsumes(workspacePattern, pattern)\n}\n\n/**\n * Checks that a bulk envelope pattern preserves exact action and filesystem\n * effect-tier boundaries.\n *\n * @category validation\n * @since 1.0.0-rc.0\n */\nexport const isValidEnvelopePattern = (\n pattern: CapabilityPattern,\n workspaceRoot: string\n): boolean => {\n if (pattern.action.includes(\"*\")) {\n return false\n }\n if (pattern.action !== \"fs:write\" || !hasResourceWildcard(pattern.resource)) {\n return true\n }\n const workspacePattern = new CapabilityPattern({\n action: \"fs:write\",\n resource: `${workspaceRoot.replace(/[\\\\/]+$/, \"\")}/**`\n })\n return subsumes(workspacePattern, pattern)\n}\n\nconst normalizeRules = (\n rules: MakeOptions[\"rules\"]\n): {\n readonly configured: ReadonlyArray<Rule>\n readonly remembered: ReadonlyArray<Rule>\n} => {\n if (rules === undefined || rules.length === 0 || rules[0] === undefined) {\n return { configured: [], remembered: [] }\n }\n if (rules.length > maximumRules) throw invalid(`rules exceed ${maximumRules} entries`)\n if (Array.isArray(rules[0])) {\n const rulesets = rules as ReadonlyArray<ReadonlyArray<Rule>>\n let count = 0\n for (const ruleset of rulesets) {\n count += ruleset.length\n if (count > maximumRules) throw invalid(`rules exceed ${maximumRules} entries`)\n }\n return {\n configured: Object.freeze(rulesets[0]!.map(snapshotRule)),\n remembered: Object.freeze(rulesets.slice(1).flatMap((ruleset) => ruleset.map(snapshotRule)))\n }\n }\n return {\n configured: Object.freeze((rules as ReadonlyArray<Rule>).map(snapshotRule)),\n remembered: []\n }\n}\n\n/**\n * Builds an in-memory grant store.\n *\n * Attended stores suspend an asking fiber on a request-local `Deferred`.\n * Unattended stores fail immediately with `PermissionRequired`. The returned\n * service is scoped: closing its scope rejects every waiter and clears the\n * pending map.\n *\n * @category constructors\n * @since 1.0.0-rc.0\n */\nexport const make = (\n options: MakeOptions = {}\n): Effect.Effect<Service, GrantStoreError, Scope.Scope | Workspace> =>\n Effect.gen(function*() {\n const attended = options.attended ?? true\n const runId = options.runId\n const planDigest = options.planDigest\n if (!validIdentity(runId)) {\n return yield* Effect.fail(invalid(\"runId is empty, malformed, or too long\"))\n }\n if (!validIdentity(planDigest)) {\n return yield* Effect.fail(invalid(\"planDigest is empty, malformed, or too long\"))\n }\n const workspace = yield* Workspace\n const initialCeiling = yield* current\n const workspaceRoot = workspace.root\n const initial = yield* attemptSnapshot(\"rules\", () => normalizeRules(options.rules))\n const initialRunRules = yield* attemptSnapshot(\"runRules\", () => {\n const values = options.runRules ?? []\n if (values.length > maximumRules) throw invalid(`runRules exceed ${maximumRules} entries`)\n return values.map((value) =>\n \"rule\" in value\n ? {\n rule: snapshotRule(value.rule),\n ceiling: value.ceiling.reduce(\n (ceiling, group) => intersect(ceiling, fromPatterns(group)),\n initialCeiling\n )\n }\n : { rule: snapshotRule(value), ceiling: initialCeiling }\n )\n })\n if (initial.configured.length + initial.remembered.length + initialRunRules.length > maximumRules) {\n return yield* Effect.fail(invalid(`rules exceed ${maximumRules} entries`))\n }\n const configuredRules = initial.configured\n const envelopeRules: Array<Rule> = []\n const runRules = initialRunRules\n const rememberedRules = [...initial.remembered]\n const pending = new Map<string, PendingEntry>()\n const persist = options.persist ?? (() => Effect.void)\n const signatures = yield* attemptSnapshot(\"envelopeSignatures\", () => {\n const values = options.envelopeSignatures ?? []\n if (!Array.isArray(values) || values.length > maximumRules) {\n throw invalid(`envelopeSignatures exceed ${maximumRules} entries`)\n }\n return values.map((value, index) => {\n const signature = typeof value === \"string\" ? normalizeEnvelopeSignature(value) : value\n if (typeof signature !== \"string\" || !validIdentity(signature)) {\n throw invalid(`envelopeSignatures[${index}] is malformed or too long`)\n }\n return signature\n })\n })\n const grantedEnvelopes = new Set<string>(signatures)\n let nextRequestId = 1\n let closed = false\n const mutation = yield* Semaphore.make(1)\n\n const persistEvent = (event: GrantEvent): Effect.Effect<void, GrantStoreError> => {\n // Every event is constructed below exclusively from validated primitive\n // identities and immutable capability snapshots, so encoding cannot\n // observe caller objects or invoke a caller-defined `toJSON` hook.\n const bytes = encoder.encode(JSON.stringify(event)).byteLength\n return bytes > maximumEventBytes\n ? Effect.fail(invalid(`grant event exceeds ${maximumEventBytes} bytes`))\n : Effect.timeoutOrElse(persist(event), {\n duration: maximumPersistMillis,\n orElse: () =>\n Effect.fail(\n new GrantStoreError({\n code: \"journal_failed\",\n message: `grant journal write exceeded ${maximumPersistMillis}ms`\n })\n )\n })\n }\n\n const invalidRemembered = rememberedRules.findIndex((rule) =>\n rule.effect === \"allow\" && !isValidEnvelopePattern(rule.pattern, workspaceRoot)\n )\n if (invalidRemembered !== -1) {\n return yield* Effect.fail(invalid(`rememberedRules[${invalidRemembered}] is outside the workspace envelope`))\n }\n const invalidRun = runRules.findIndex(({ rule }) =>\n rule.effect === \"allow\" && !isValidEnvelopePattern(rule.pattern, workspaceRoot)\n )\n if (invalidRun !== -1) {\n return yield* Effect.fail(invalid(`runRules[${invalidRun}] is outside the workspace envelope`))\n }\n\n // Construction envelopes validate capacity before persistence or\n // activation. A seeded construction envelope may already have rules\n // installed by replay. Runtime admission is two-phase in grantEnvelope.\n const admitEnvelope = (\n envelope: Effect.Success<ReturnType<typeof prepareEnvelope>>\n ): Effect.Effect<boolean, GrantStoreError> =>\n Effect.gen(function*() {\n const { patterns, scope } = envelope\n if (patterns.length === 0) return false\n const signature = envelopeSignature(envelope.planDigest, scope, patterns)\n const durable = grantedEnvelopes.has(signature)\n const destination = scope === \"remembered\" ? rememberedRules : envelopeRules\n const replayed = scope === \"remembered\"\n ? rememberedRules\n : runRules.filter(({ ceiling }) => ceiling === initialCeiling).map(({ rule }) => rule)\n const existing = new Set<string>()\n for (const rule of replayed) {\n // Supplied rules can mask earlier grants. Only the trailing allow\n // rules (including journal replay) can replace a fresh activation.\n if (rule.effect === \"allow\") existing.add(format(rule.pattern))\n else existing.clear()\n }\n const incoming = durable ? patterns.filter((pattern) => !existing.has(format(pattern))) : patterns\n if (\n configuredRules.length + envelopeRules.length + runRules.length + rememberedRules.length +\n incoming.length > maximumRules\n ) {\n return yield* Effect.fail(invalid(`rules exceed ${maximumRules} entries`))\n }\n if (!durable && grantedEnvelopes.size >= maximumRules) {\n return yield* Effect.fail(invalid(`grant envelopes exceed ${maximumRules} entries`))\n }\n if (!durable) {\n yield* persistEvent(\n new EnvelopeGrant({\n eventType: \"flows.kernel.grant.envelope.v1\",\n runId: runId ?? \"\",\n planDigest: envelope.planDigest,\n patterns,\n scope\n })\n )\n grantedEnvelopes.add(signature)\n }\n for (const pattern of incoming) {\n destination.push(snapshotRule(new Rule({ effect: \"allow\", pattern })))\n }\n return true\n })\n\n if (options.envelope !== undefined) {\n const envelope = yield* prepareEnvelope(options.envelope, planDigest, workspaceRoot)\n yield* admitEnvelope(envelope)\n }\n\n const rulesets = (capability: Capability): ReadonlyArray<ReadonlyArray<Rule>> => [\n configuredRules,\n envelopeRules,\n runRules\n .filter(({ ceiling }) => allows(ceiling, capability))\n .map(({ rule }) => rule),\n rememberedRules\n ]\n\n yield* Effect.addFinalizer(() =>\n mutation.withPermit(\n Effect.gen(function*() {\n closed = true\n const entries = [...pending.values()]\n pending.clear()\n yield* Effect.forEach(\n entries,\n (entry) =>\n Deferred.fail(\n entry.deferred,\n permissionDenied(entry.capability, \"grant store closed\")\n ),\n { discard: true }\n )\n })\n )\n )\n\n const allocateRequest = (\n capability: Capability,\n tier: EffectTier,\n meta: Record<string, unknown>,\n ceiling: CapabilitySet\n ): Effect.Effect<PendingEntry, GrantStoreError> =>\n Effect.gen(function*() {\n if (pending.size >= maximumPendingRequests) {\n return yield* Effect.fail(invalid(`pending requests exceed ${maximumPendingRequests} entries`))\n }\n const requestId = `permission-${nextRequestId++}`\n const deferred = yield* Deferred.make<void, PermissionDenied>()\n const entry: PendingEntry = {\n requestId,\n capability,\n tier,\n meta,\n ceiling,\n deferred\n }\n pending.set(requestId, entry)\n return entry\n })\n\n const nextUnattendedRequestId = Effect.sync(() => `permission-${nextRequestId++}`)\n\n const check: Service[\"check\"] = Effect.fn(\"GrantStore.check\")((capability, meta = {}) =>\n Effect.uninterruptibleMask((restore) =>\n Effect.gen(function*() {\n const request = yield* attemptSnapshot(\"permission request\", () => ({\n capability: snapshotCapability(capability),\n meta: metadataSnapshot(meta)\n }))\n // The permit guards only in-memory state, so acquiring it is\n // interruptible: a cancelled caller is released instead of queueing\n // uninterruptibly. The critical section itself stays uninterruptible.\n const entry = yield* restore(mutation.take(1)).pipe(\n Effect.andThen(\n Effect.gen(function*() {\n if (closed) {\n return yield* Effect.fail(new GrantStoreError({ code: \"store_closed\" }))\n }\n const ceiling = yield* current\n if (!allows(ceiling, request.capability)) {\n return yield* Effect.fail(permissionDenied(request.capability, \"outside capability ceiling\"))\n }\n\n const decision = evaluate(rulesets(request.capability), request.capability)\n if (decision === \"allow\") {\n return undefined\n }\n if (decision === \"deny\") {\n return yield* Effect.fail(permissionDenied(request.capability, \"denied by permission policy\"))\n }\n\n const tier = tierOf(request.capability, { workspaceRoot })\n if (!attended) {\n const requestId = yield* nextUnattendedRequestId\n return yield* Effect.fail(\n permissionRequired({\n requestId,\n runId,\n capability: request.capability,\n tier,\n meta: request.meta\n })\n )\n }\n\n return yield* allocateRequest(\n request.capability,\n tier,\n request.meta,\n ceiling\n )\n }).pipe(Effect.ensuring(mutation.release(1)))\n )\n )\n if (entry === undefined) {\n return\n }\n return yield* restore(Deferred.await(entry.deferred)).pipe(\n Effect.ensuring(\n mutation.withPermit(\n Effect.sync(() => {\n pending.delete(entry.requestId)\n })\n )\n )\n )\n })\n )\n )\n\n const resolveCovered: Effect.Effect<void> = Effect.suspend(() =>\n Effect.forEach(\n [...pending.entries()],\n ([requestId, entry]) => {\n if (\n !allows(entry.ceiling, entry.capability) ||\n evaluate(rulesets(entry.capability), entry.capability) !== \"allow\"\n ) {\n return Effect.void\n }\n return Deferred.succeed(entry.deferred, undefined).pipe(\n Effect.andThen(\n Effect.sync(() => {\n pending.delete(requestId)\n })\n )\n )\n },\n { discard: true }\n ).pipe(Effect.asVoid)\n )\n\n // Requests and envelopes with a journal write in flight. The mutation\n // permit guards only in-memory state: a decision is planned under the\n // permit, persisted without it, then activated under it again.\n const resolving = new Set<string>()\n const granting = new Map<string, Deferred.Deferred<void, GrantStoreError>>()\n // Planned rules occupy capacity until their write fails or they activate.\n // Replies and envelopes share this count, guarded by the mutation permit.\n let reservedRules = 0\n\n type PlannedReply =\n | {\n readonly resolution: \"once\" | \"deny\"\n readonly entry: PendingEntry\n readonly event: GrantEvent\n }\n | {\n readonly resolution: \"run\" | \"remembered\"\n readonly entry: PendingEntry\n readonly rule: Rule\n readonly event: GrantEvent\n }\n\n const planReply = (\n requestId: string,\n resolution: Resolution,\n suppliedPattern: CapabilityPattern | undefined\n ): Effect.Effect<PlannedReply, GrantStoreError> =>\n Effect.gen(function*() {\n if (closed) {\n return yield* Effect.fail(new GrantStoreError({ code: \"store_closed\" }))\n }\n if (!isResolution(resolution)) {\n // A runtime-invalid resolution must fail the reply, not fall\n // through the switch below: silently succeeding would strand\n // the request's waiter on its Deferred forever. The request\n // stays pending so the caller can still answer it.\n return yield* Effect.fail(\n new GrantStoreError({\n code: \"invalid_resolution\",\n message: \"unknown grant resolution\"\n })\n )\n }\n const entry = pending.get(requestId)\n // A request whose decision is already being persisted is decided:\n // the losing reply fails fast instead of queueing behind the journal.\n if (entry === undefined || resolving.has(requestId)) {\n return yield* Effect.fail(new GrantStoreError({ code: \"request_not_found\" }))\n }\n const pattern = yield* attemptSnapshot(\"grant pattern\", () => {\n if (resolution === \"run\" || resolution === \"remembered\") {\n if (suppliedPattern !== undefined) return snapshotPattern(suppliedPattern)\n const derived = patternFromCapability(entry.capability)\n if (Option.isNone(derived)) {\n throw invalid(\n \"the requested resource contains glob metacharacters; supply an explicit grant pattern or resolve once\"\n )\n }\n return snapshotPattern(derived.value)\n }\n return snapshotPattern(exactPattern(entry.capability))\n })\n\n switch (resolution) {\n case \"once\": {\n resolving.add(requestId)\n return {\n resolution,\n entry,\n event: new OnceGrant({\n eventType: \"flows.kernel.grant.once.v1\",\n requestId,\n runId: runId ?? \"\",\n ...(planDigest === undefined ? {} : { planDigest }),\n capability: entry.capability,\n pattern,\n scope: \"once\",\n tier: entry.tier\n })\n }\n }\n case \"run\": {\n if (planDigest === undefined) {\n return yield* Effect.fail(\n new GrantStoreError({\n code: \"invalid_resolution\",\n message: \"run grants require a plan digest\"\n })\n )\n }\n if (!isValidGrantPattern(pattern, entry.capability, entry.tier, workspaceRoot)) {\n return yield* Effect.fail(invalid(\"grant pattern exceeds the requested authority\"))\n }\n if (\n configuredRules.length + envelopeRules.length + runRules.length + rememberedRules.length +\n reservedRules >=\n maximumRules\n ) {\n return yield* Effect.fail(invalid(`rules exceed ${maximumRules} entries`))\n }\n resolving.add(requestId)\n reservedRules += 1\n return {\n resolution,\n entry,\n rule: snapshotRule(new Rule({ effect: \"allow\", pattern })),\n event: new RunGrant({\n eventType: \"flows.kernel.grant.run.v2\",\n requestId,\n runId: runId ?? \"\",\n planDigest,\n capability: entry.capability,\n pattern,\n ceiling: entry.ceiling.groups,\n scope: \"run\",\n tier: entry.tier\n })\n }\n }\n case \"remembered\": {\n if (!isValidGrantPattern(pattern, entry.capability, entry.tier, workspaceRoot)) {\n return yield* Effect.fail(invalid(\"grant pattern exceeds the requested authority\"))\n }\n if (\n configuredRules.length + envelopeRules.length + runRules.length + rememberedRules.length +\n reservedRules >=\n maximumRules\n ) {\n return yield* Effect.fail(invalid(`rules exceed ${maximumRules} entries`))\n }\n resolving.add(requestId)\n reservedRules += 1\n return {\n resolution,\n entry,\n rule: snapshotRule(new Rule({ effect: \"allow\", pattern })),\n event: new RememberedGrant({\n eventType: \"flows.kernel.grant.remembered.v1\",\n requestId,\n runId: runId ?? \"\",\n ...(planDigest === undefined ? {} : { planDigest }),\n capability: entry.capability,\n pattern,\n scope: \"remembered\",\n tier: entry.tier\n })\n }\n }\n case \"deny\": {\n resolving.add(requestId)\n return {\n resolution,\n entry,\n event: new DeniedGrant({\n eventType: \"flows.kernel.grant.denied.v1\",\n requestId,\n runId: runId ?? \"\",\n ...(planDigest === undefined ? {} : { planDigest }),\n capability: entry.capability,\n pattern,\n scope: \"once\",\n tier: entry.tier\n })\n }\n }\n }\n })\n\n const activateReply = (requestId: string, planned: PlannedReply): Effect.Effect<void, GrantStoreError> =>\n Effect.gen(function*() {\n resolving.delete(requestId)\n if (planned.resolution === \"run\" || planned.resolution === \"remembered\") reservedRules -= 1\n if (closed) {\n return yield* Effect.fail(new GrantStoreError({ code: \"store_closed\" }))\n }\n const entry = pending.get(requestId)\n switch (planned.resolution) {\n case \"once\": {\n if (entry === undefined) {\n return yield* Effect.fail(new GrantStoreError({ code: \"request_not_found\" }))\n }\n yield* Deferred.succeed(entry.deferred, undefined)\n pending.delete(requestId)\n return\n }\n case \"deny\": {\n if (entry === undefined) {\n return yield* Effect.fail(new GrantStoreError({ code: \"request_not_found\" }))\n }\n yield* Deferred.fail(\n entry.deferred,\n permissionDenied(entry.capability, \"permission request denied\")\n )\n pending.delete(requestId)\n return\n }\n case \"run\": {\n // The decision is already durable, so the rule activates even\n // when the request's own waiter left while the journal wrote:\n // replay installs it on the next open and the live store must\n // not diverge from the journal. Capacity was validated before\n // persistence.\n runRules.push({ rule: planned.rule, ceiling: planned.entry.ceiling })\n yield* resolveCovered\n return\n }\n case \"remembered\": {\n rememberedRules.push(planned.rule)\n yield* resolveCovered\n return\n }\n }\n })\n\n const reply: Service[\"reply\"] = Effect.fn(\"GrantStore.reply\")((\n requestId,\n resolution,\n suppliedPattern\n ) =>\n Effect.uninterruptibleMask((restore) =>\n Effect.gen(function*() {\n const planned = yield* mutation.withPermit(planReply(requestId, resolution, suppliedPattern))\n // Journal IO never holds the permit: only this reply waits on it,\n // interruptibly, so the write deadline can fire and a cancelled\n // reply is released. A failed write clears the in-flight mark so\n // the request stays retryable.\n yield* restore(persistEvent(planned.event)).pipe(\n Effect.onError(() =>\n mutation.withPermit(\n Effect.sync(() => {\n resolving.delete(requestId)\n if (planned.resolution === \"run\" || planned.resolution === \"remembered\") reservedRules -= 1\n })\n )\n )\n )\n yield* mutation.withPermit(activateReply(requestId, planned))\n })\n )\n )\n\n const list: Service[\"list\"] = Effect.fn(\"GrantStore.list\")(() =>\n mutation.withPermit(\n Effect.sync(() =>\n // Every entry's meta is already the frozen snapshot taken at check\n // time; list copies the array and re-wraps identity without\n // re-walking or re-serializing the metadata graph.\n Object.freeze(Array.from(\n pending.values(),\n ({ requestId, capability, tier, meta }): PendingRequest =>\n Object.freeze({\n requestId,\n capability: snapshotCapability(capability),\n tier,\n meta\n })\n ))\n )\n )\n )()\n\n type EnvelopeAdmission =\n | { readonly _tag: \"Durable\" }\n | { readonly _tag: \"Wait\"; readonly completion: Deferred.Deferred<void, GrantStoreError> }\n | {\n readonly _tag: \"Fresh\"\n readonly signature: string\n readonly scope: \"run\" | \"remembered\"\n readonly patterns: ReadonlyArray<CapabilityPattern>\n readonly completion: Deferred.Deferred<void, GrantStoreError>\n readonly event: GrantEvent\n }\n\n const planEnvelope = (\n envelope: Effect.Success<ReturnType<typeof prepareEnvelope>>\n ): Effect.Effect<EnvelopeAdmission, GrantStoreError> =>\n Effect.gen(function*() {\n if (closed) {\n return yield* Effect.fail(new GrantStoreError({ code: \"store_closed\" }))\n }\n const { patterns, scope } = envelope\n const signature = envelopeSignature(envelope.planDigest, scope, patterns)\n if (grantedEnvelopes.has(signature)) return { _tag: \"Durable\" as const }\n // A concurrent admission of the same envelope is already persisting;\n // wait for its outcome rather than writing a duplicate record.\n const inFlight = granting.get(signature)\n if (inFlight !== undefined) return { _tag: \"Wait\" as const, completion: inFlight }\n if (\n configuredRules.length + envelopeRules.length + runRules.length + rememberedRules.length +\n reservedRules + patterns.length > maximumRules\n ) {\n return yield* Effect.fail(invalid(`rules exceed ${maximumRules} entries`))\n }\n if (grantedEnvelopes.size + granting.size >= maximumRules) {\n return yield* Effect.fail(invalid(`grant envelopes exceed ${maximumRules} entries`))\n }\n const completion = yield* Deferred.make<void, GrantStoreError>()\n granting.set(signature, completion)\n reservedRules += patterns.length\n return {\n _tag: \"Fresh\" as const,\n signature,\n scope,\n patterns,\n completion,\n event: new EnvelopeGrant({\n eventType: \"flows.kernel.grant.envelope.v1\",\n runId: runId ?? \"\",\n planDigest: envelope.planDigest,\n patterns,\n scope\n })\n }\n })\n\n const activateEnvelope = (\n planned: Extract<EnvelopeAdmission, { readonly _tag: \"Fresh\" }>\n ): Effect.Effect<void, GrantStoreError> =>\n Effect.gen(function*() {\n granting.delete(planned.signature)\n reservedRules -= planned.patterns.length\n if (closed) {\n return yield* Effect.fail(new GrantStoreError({ code: \"store_closed\" }))\n }\n // The decision is already durable, so its rules activate without\n // re-checking capacity: replay installs them on the next open and the\n // live store must not diverge from the journal.\n grantedEnvelopes.add(planned.signature)\n const destination = planned.scope === \"remembered\" ? rememberedRules : envelopeRules\n for (const pattern of planned.patterns) {\n destination.push(snapshotRule(new Rule({ effect: \"allow\", pattern })))\n }\n yield* resolveCovered\n })\n\n const grantEnvelope: Service[\"grantEnvelope\"] = Effect.fn(\"GrantStore.grantEnvelope\")((input) =>\n Effect.uninterruptibleMask((restore) => {\n const admit = (\n prepared: Effect.Success<ReturnType<typeof prepareEnvelope>>\n ): Effect.Effect<void, GrantStoreError> =>\n Effect.gen(function*() {\n const planned = yield* mutation.withPermit(planEnvelope(prepared))\n switch (planned._tag) {\n case \"Durable\":\n return\n case \"Wait\": {\n // The identical envelope is mid-flight elsewhere; adopt its\n // outcome. A failed write fails here too: re-planning would\n // turn one journal outage into an unbounded loop of writes.\n // An interrupted first admission decided nothing and can be\n // retried. Check this caller's cancellation before re-planning\n // so an interrupted duplicate cannot loop under the mask.\n return yield* restore(Deferred.await(planned.completion)).pipe(\n Effect.catchCause((cause) =>\n Cause.hasInterruptsOnly(cause)\n ? restore(Effect.void).pipe(Effect.andThen(admit(prepared)))\n : Effect.failCause(cause)\n )\n )\n }\n case \"Fresh\": {\n // Journal IO never holds the permit: only this admission\n // waits on it, interruptibly, so the write deadline can fire.\n // Concurrent duplicates are released with the same outcome.\n yield* restore(persistEvent(planned.event)).pipe(\n Effect.onError((cause) =>\n mutation.withPermit(\n Effect.gen(function*() {\n granting.delete(planned.signature)\n reservedRules -= planned.patterns.length\n yield* Deferred.failCause(planned.completion, cause)\n })\n )\n )\n )\n yield* mutation.withPermit(activateEnvelope(planned)).pipe(\n Effect.tap(() => Deferred.succeed(planned.completion, undefined)),\n Effect.onError((cause) => Deferred.failCause(planned.completion, cause))\n )\n return\n }\n }\n })\n return Effect.gen(function*() {\n const prepared = yield* prepareEnvelope(input, planDigest, workspaceRoot)\n if (prepared.patterns.length === 0) return\n yield* admit(prepared)\n })\n })\n )\n\n const policy: Service[\"policy\"] = mutation.withPermit(Effect.gen(function*() {\n if (closed) return yield* Effect.fail(new GrantStoreError({ code: \"store_closed\" }))\n const ceiling = yield* current\n const unbounded = (rules: ReadonlyArray<Rule>) =>\n rules.map((rule) =>\n Object.freeze({ rule: snapshotRule(rule), ceiling: Object.freeze({ groups: Object.freeze([]) }) })\n )\n return Object.freeze({\n ceiling,\n groups: Object.freeze([\n unbounded(configuredRules),\n unbounded(envelopeRules),\n runRules.map(({ rule, ceiling }) => Object.freeze({ rule: snapshotRule(rule), ceiling })),\n unbounded(rememberedRules)\n ].map((group) => Object.freeze(group)))\n })\n }))\n return GrantStore.of({ check, reply, list, grantEnvelope, policy })\n })\n\n/**\n * Provides a scoped in-memory grant store.\n *\n * @category layers\n * @since 1.0.0-rc.0\n */\nexport const layer = (\n options: MakeOptions = {}\n): Layer.Layer<GrantStore, GrantStoreError, Workspace> => Layer.effect(GrantStore, make(options))\n\n/**\n * An allow-all grant store.\n *\n * @category constructors\n * @since 1.0.0-rc.0\n */\nexport const makeNoop: Service = GrantStore.of({\n policy: current.pipe(Effect.map((ceiling) =>\n Object.freeze({\n ceiling,\n groups: Object.freeze([Object.freeze(([\"*\", \"net:private\"] as const).map((action) =>\n Object.freeze({\n rule: snapshotRule(new Rule({ effect: \"allow\", pattern: new CapabilityPattern({ action, resource: \"**\" }) })),\n ceiling: Object.freeze({ groups: Object.freeze([]) })\n })\n ))])\n })\n )),\n check: Effect.fn(\"GrantStore.check\")(() => Effect.void),\n reply: Effect.fn(\"GrantStore.reply\")(() => Effect.void),\n list: Effect.fn(\"GrantStore.list\")(() => Effect.succeed([]))(),\n grantEnvelope: Effect.fn(\"GrantStore.grantEnvelope\")(() => Effect.void)\n})\n\n/**\n * Provides the allow-all grant store.\n *\n * @category layers\n * @since 1.0.0-rc.0\n */\nexport const layerNoop: Layer.Layer<GrantStore> = Layer.succeed(GrantStore)(makeNoop)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["CapabilityValue", "evaluate", "snapshot", "ceiling"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0-rc.0
|
|
3
|
+
*
|
|
4
|
+
* Host domain errors, shaped after `effect/PlatformError`.
|
|
5
|
+
*
|
|
6
|
+
* Effect's platform errors carry normalized operation data — a stable `_tag`
|
|
7
|
+
* reason, the `module` and `method` that failed, a human `description`, and the
|
|
8
|
+
* original `cause` — and are constructed through small helpers rather than
|
|
9
|
+
* `new`. We mirror that exactly, with two deliberate deviations:
|
|
10
|
+
*
|
|
11
|
+
* - the normalized reason lives in a `code` field rather than a nested
|
|
12
|
+
* `reason._tag`, because ours is a small closed set per service; and
|
|
13
|
+
* - the classes are `Schema.TaggedError`, not `Data.TaggedError`, because
|
|
14
|
+
* Host failures cross the durability boundary and must round-trip.
|
|
15
|
+
*
|
|
16
|
+
* Codes are a STABLE public contract: callers branch on them, step keys digest
|
|
17
|
+
* them, UIs map them to remediation. Never repurpose a code — add one.
|
|
18
|
+
*/
|
|
19
|
+
import type { JjError } from "@smthrs/jj";
|
|
20
|
+
/**
|
|
21
|
+
* Every failure the Host surface is allowed to surface.
|
|
22
|
+
*
|
|
23
|
+
* `JjError` is declared by `@smthrs/jj` beside its contract; it is named here
|
|
24
|
+
* because that service is still part of the closed Host surface
|
|
25
|
+
* (`HostServices.ts`). This is a type union, not a re-export — import the
|
|
26
|
+
* error itself from its package.
|
|
27
|
+
*
|
|
28
|
+
* Running a command is absent on purpose: process execution is Effect's
|
|
29
|
+
* `ChildProcessSpawner`, so it fails with `PlatformError` like the rest of
|
|
30
|
+
* `effect`'s platform surface.
|
|
31
|
+
*
|
|
32
|
+
* @category models
|
|
33
|
+
* @since 1.0.0-rc.0
|
|
34
|
+
*/
|
|
35
|
+
export type HostError = JjError;
|
|
36
|
+
//# sourceMappingURL=HostError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HostError.d.ts","sourceRoot":"","sources":["../../src/HostError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEzC;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var HostError_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(HostError_exports);
|
|
17
|
+
//# sourceMappingURL=HostError.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/HostError.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * @since 1.0.0-rc.0\n *\n * Host domain errors, shaped after `effect/PlatformError`.\n *\n * Effect's platform errors carry normalized operation data \u2014 a stable `_tag`\n * reason, the `module` and `method` that failed, a human `description`, and the\n * original `cause` \u2014 and are constructed through small helpers rather than\n * `new`. We mirror that exactly, with two deliberate deviations:\n *\n * - the normalized reason lives in a `code` field rather than a nested\n * `reason._tag`, because ours is a small closed set per service; and\n * - the classes are `Schema.TaggedError`, not `Data.TaggedError`, because\n * Host failures cross the durability boundary and must round-trip.\n *\n * Codes are a STABLE public contract: callers branch on them, step keys digest\n * them, UIs map them to remediation. Never repurpose a code \u2014 add one.\n */\n\nimport type { JjError } from \"@smthrs/jj\"\n\n/**\n * Every failure the Host surface is allowed to surface.\n *\n * `JjError` is declared by `@smthrs/jj` beside its contract; it is named here\n * because that service is still part of the closed Host surface\n * (`HostServices.ts`). This is a type union, not a re-export \u2014 import the\n * error itself from its package.\n *\n * Running a command is absent on purpose: process execution is Effect's\n * `ChildProcessSpawner`, so it fails with `PlatformError` like the rest of\n * `effect`'s platform surface.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type HostError = JjError\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed Host service list.
|
|
3
|
+
*
|
|
4
|
+
* One list, one set of tags. The kernel decorates each slot **in place** — a
|
|
5
|
+
* middleware `Layer` over the very tag the platform adapter provides — so
|
|
6
|
+
* there is no second, "protected" tag to keep in slot-order sync with this
|
|
7
|
+
* one, and no cast to force a guarded implementation onto a narrower error
|
|
8
|
+
* contract.
|
|
9
|
+
*
|
|
10
|
+
* Governing design:
|
|
11
|
+
* `docs/specs/Concepts/Permission Kernel.md`,
|
|
12
|
+
* `docs/specs/Concepts/Trust Granularity.md`, and
|
|
13
|
+
* `docs/specs/Concepts/Host Adapters.md`.
|
|
14
|
+
*
|
|
15
|
+
* @since 1.0.0-rc.0
|
|
16
|
+
*/
|
|
17
|
+
import { Jj as JjPort } from "@smthrs/jj";
|
|
18
|
+
import { FileSystem as EffectFileSystem, Layer, Path as EffectPath } from "effect";
|
|
19
|
+
import { HttpClient as HttpClientPort } from "effect/unstable/http/HttpClient";
|
|
20
|
+
import { ChildProcessSpawner as ChildProcessSpawnerPort } from "effect/unstable/process/ChildProcessSpawner";
|
|
21
|
+
/**
|
|
22
|
+
* The CLOSED LIST of platform ports the kernel protects.
|
|
23
|
+
* Optional filesystem batches belong to the existing FileSystem slot. The
|
|
24
|
+
* decorator grants each member separately and exposes no additional tag or
|
|
25
|
+
* unguarded executor to consumers; host slot identities remain unchanged.
|
|
26
|
+
*
|
|
27
|
+
* Everything that touches the outside world enters Smithers through exactly one
|
|
28
|
+
* of these tags — there is no ambient `node:fs`, no bare `spawn`, no global
|
|
29
|
+
* `Date.now()`. Two things depend on that closure:
|
|
30
|
+
*
|
|
31
|
+
* 1. The capability kernel wraps precisely this list. A service that is not
|
|
32
|
+
* here cannot be attenuated, denied, or audited, so it must not exist.
|
|
33
|
+
* 2. Step keys digest this list as their `layers` component. Which platform
|
|
34
|
+
* implementations were in scope is part of a step's identity, so a replay
|
|
35
|
+
* under different layers is a different step rather than a silent lie.
|
|
36
|
+
*
|
|
37
|
+
* Each slot's guarded implementation replaces the raw one under the same tag,
|
|
38
|
+
* so a consumer that never heard of the kernel still cannot bypass it. Where
|
|
39
|
+
* Effect owns the tag (`FileSystem`, `Path`, `ChildProcessSpawner`,
|
|
40
|
+
* `HttpClient`) the error channel stays Effect's own — `PlatformError`, or
|
|
41
|
+
* `HttpClientError` for the network — and permission failures are projected
|
|
42
|
+
* into it by `Permission.toPlatformError` and `HttpClient.toHttpClientError`;
|
|
43
|
+
* where Smithers owns the service (`Jj`) the interface names the kernel's
|
|
44
|
+
* failures directly.
|
|
45
|
+
*
|
|
46
|
+
* `Path` is intentionally retained as an explicit decision: it checks nothing
|
|
47
|
+
* and resolves relative paths against `Workspace.root`.
|
|
48
|
+
* Network access is Effect's own `HttpClient`: there is no Smithers transport
|
|
49
|
+
* port beneath it, because a raw port would be a second way to reach the
|
|
50
|
+
* network whose contract never mentions permission.
|
|
51
|
+
*
|
|
52
|
+
* `Clock` and `Random` are Effect core built-ins: already port-shaped, already
|
|
53
|
+
* swappable via `Effect.provideService`, and never decorated here — a `Clock`
|
|
54
|
+
* or a `Random` carries no host authority to guard, so they are not ours to
|
|
55
|
+
* define. `ChildProcessSpawner` is the same story one layer out: process spawning is
|
|
56
|
+
* `effect/unstable/process`, and the slot holds Effect's tag rather than a
|
|
57
|
+
* Smithers wrapper around it.
|
|
58
|
+
*
|
|
59
|
+
* @category models
|
|
60
|
+
* @since 1.0.0-rc.0
|
|
61
|
+
*/
|
|
62
|
+
export type HostService = EffectFileSystem.FileSystem | EffectPath.Path | ChildProcessSpawnerPort | JjPort | HttpClientPort;
|
|
63
|
+
/**
|
|
64
|
+
* The Host tags consumed by the kernel at runtime, decorated in place by
|
|
65
|
+
* {@link layer}, and digested by the step-key planner.
|
|
66
|
+
*
|
|
67
|
+
* @category models
|
|
68
|
+
* @since 1.0.0-rc.0
|
|
69
|
+
*/
|
|
70
|
+
export declare const HostServiceTags: readonly [import("effect/Context").Service<EffectFileSystem.FileSystem, EffectFileSystem.FileSystem>, import("effect/Context").Service<EffectPath.Path, EffectPath.Path>, typeof ChildProcessSpawnerPort, import("effect/Context").Service<JjPort, JjPort>, import("effect/Context").Service<HttpClientPort, HttpClientPort>];
|
|
71
|
+
/**
|
|
72
|
+
* Stable slot identifiers shared by host composition, kernel attenuation, and
|
|
73
|
+
* step-layer resolution.
|
|
74
|
+
*
|
|
75
|
+
* Each id is the tag key of its slot's service — Effect's own key for the
|
|
76
|
+
* services Effect ships, the defining module's path for ours. The ids are
|
|
77
|
+
* digested into step keys, so a rename invalidates every cached step naming
|
|
78
|
+
* the slot; rename only when the service itself changes, as when `Shell` was
|
|
79
|
+
* replaced by Effect's `ChildProcessSpawner`.
|
|
80
|
+
*
|
|
81
|
+
* @category models
|
|
82
|
+
* @since 1.0.0-rc.0
|
|
83
|
+
*/
|
|
84
|
+
export declare const HostServiceIds: readonly ["effect/FileSystem", "effect/Path", "effect/process/ChildProcessSpawner", "@smthrs/jj/Jj", "effect/HttpClient"];
|
|
85
|
+
/**
|
|
86
|
+
* Builds the full protected Host surface over a host platform bundle and a
|
|
87
|
+
* `GrantStore`. `Workspace` remains a requirement so the exact same root
|
|
88
|
+
* service can be supplied to both the grant store and filesystem decorators.
|
|
89
|
+
*
|
|
90
|
+
* Every member both requires and provides its own slot's tag: provide this
|
|
91
|
+
* layer over a raw platform bundle and the guarded implementation shadows the
|
|
92
|
+
* raw one for everything downstream. There is no exception and no second tag
|
|
93
|
+
* list — `HttpClient` decorates Effect's network tag exactly the way
|
|
94
|
+
* `FileSystem` decorates Effect's filesystem tag. The host supplies
|
|
95
|
+
* `ProcessConfinement` for approved processes; absence refuses spawning.
|
|
96
|
+
*
|
|
97
|
+
* @category layers
|
|
98
|
+
* @since 1.0.0-rc.0
|
|
99
|
+
*/
|
|
100
|
+
export declare const layer: Layer.Layer<ChildProcessSpawnerPort | EffectPath.Path | EffectFileSystem.FileSystem | JjPort | HttpClientPort, import("effect/PlatformError").PlatformError, ChildProcessSpawnerPort | import("./Workspace.ts").Workspace | import("./GrantStore.ts").GrantStore | EffectPath.Path | EffectFileSystem.FileSystem | JjPort | HttpClientPort>;
|
|
101
|
+
//# sourceMappingURL=HostServices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HostServices.d.ts","sourceRoot":"","sources":["../../src/HostServices.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,UAAU,IAAI,gBAAgB,EAAE,KAAK,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,QAAQ,CAAA;AAClF,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAC9E,OAAO,EAAE,mBAAmB,IAAI,uBAAuB,EAAE,MAAM,6CAA6C,CAAA;AAO5G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,MAAM,WAAW,GACnB,gBAAgB,CAAC,UAAU,GAC3B,UAAU,CAAC,IAAI,GACf,uBAAuB,GACvB,MAAM,GACN,cAAc,CAAA;AAElB;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,+TAMlB,CAAA;AAEV;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,2HAMjB,CAAA;AAEV;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,KAAK,6UAMjB,CAAA"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var HostServices_exports = {};
|
|
30
|
+
__export(HostServices_exports, {
|
|
31
|
+
HostServiceIds: () => HostServiceIds,
|
|
32
|
+
HostServiceTags: () => HostServiceTags,
|
|
33
|
+
layer: () => layer
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(HostServices_exports);
|
|
36
|
+
var import_jj = require("@smthrs/jj");
|
|
37
|
+
var import_effect = require("effect");
|
|
38
|
+
var import_HttpClient = require("effect/unstable/http/HttpClient");
|
|
39
|
+
var import_ChildProcessSpawner = require("effect/unstable/process/ChildProcessSpawner");
|
|
40
|
+
var ChildProcessSpawner = __toESM(require("./ChildProcessSpawner.js"), 1);
|
|
41
|
+
var FileSystem = __toESM(require("./FileSystem.js"), 1);
|
|
42
|
+
var HttpClient = __toESM(require("./HttpClient.js"), 1);
|
|
43
|
+
var Jj = __toESM(require("./Jj.js"), 1);
|
|
44
|
+
var Path = __toESM(require("./Path.js"), 1);
|
|
45
|
+
const HostServiceTags = [
|
|
46
|
+
import_effect.FileSystem.FileSystem,
|
|
47
|
+
import_effect.Path.Path,
|
|
48
|
+
import_ChildProcessSpawner.ChildProcessSpawner,
|
|
49
|
+
import_jj.Jj,
|
|
50
|
+
import_HttpClient.HttpClient
|
|
51
|
+
];
|
|
52
|
+
const HostServiceIds = [
|
|
53
|
+
"effect/FileSystem",
|
|
54
|
+
"effect/Path",
|
|
55
|
+
"effect/process/ChildProcessSpawner",
|
|
56
|
+
"@smthrs/jj/Jj",
|
|
57
|
+
"effect/HttpClient"
|
|
58
|
+
];
|
|
59
|
+
const layer = import_effect.Layer.mergeAll(
|
|
60
|
+
FileSystem.layer,
|
|
61
|
+
Path.layer,
|
|
62
|
+
ChildProcessSpawner.layer,
|
|
63
|
+
Jj.layer,
|
|
64
|
+
HttpClient.layer
|
|
65
|
+
);
|
|
66
|
+
//# sourceMappingURL=HostServices.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/HostServices.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The closed Host service list.\n *\n * One list, one set of tags. The kernel decorates each slot **in place** \u2014 a\n * middleware `Layer` over the very tag the platform adapter provides \u2014 so\n * there is no second, \"protected\" tag to keep in slot-order sync with this\n * one, and no cast to force a guarded implementation onto a narrower error\n * contract.\n *\n * Governing design:\n * `docs/specs/Concepts/Permission Kernel.md`,\n * `docs/specs/Concepts/Trust Granularity.md`, and\n * `docs/specs/Concepts/Host Adapters.md`.\n *\n * @since 1.0.0-rc.0\n */\n\nimport { Jj as JjPort } from \"@smthrs/jj\"\nimport { FileSystem as EffectFileSystem, Layer, Path as EffectPath } from \"effect\"\nimport { HttpClient as HttpClientPort } from \"effect/unstable/http/HttpClient\"\nimport { ChildProcessSpawner as ChildProcessSpawnerPort } from \"effect/unstable/process/ChildProcessSpawner\"\nimport * as ChildProcessSpawner from \"./ChildProcessSpawner.ts\"\nimport * as FileSystem from \"./FileSystem.ts\"\nimport * as HttpClient from \"./HttpClient.ts\"\nimport * as Jj from \"./Jj.ts\"\nimport * as Path from \"./Path.ts\"\n\n/**\n * The CLOSED LIST of platform ports the kernel protects.\n * Optional filesystem batches belong to the existing FileSystem slot. The\n * decorator grants each member separately and exposes no additional tag or\n * unguarded executor to consumers; host slot identities remain unchanged.\n *\n * Everything that touches the outside world enters Smithers through exactly one\n * of these tags \u2014 there is no ambient `node:fs`, no bare `spawn`, no global\n * `Date.now()`. Two things depend on that closure:\n *\n * 1. The capability kernel wraps precisely this list. A service that is not\n * here cannot be attenuated, denied, or audited, so it must not exist.\n * 2. Step keys digest this list as their `layers` component. Which platform\n * implementations were in scope is part of a step's identity, so a replay\n * under different layers is a different step rather than a silent lie.\n *\n * Each slot's guarded implementation replaces the raw one under the same tag,\n * so a consumer that never heard of the kernel still cannot bypass it. Where\n * Effect owns the tag (`FileSystem`, `Path`, `ChildProcessSpawner`,\n * `HttpClient`) the error channel stays Effect's own \u2014 `PlatformError`, or\n * `HttpClientError` for the network \u2014 and permission failures are projected\n * into it by `Permission.toPlatformError` and `HttpClient.toHttpClientError`;\n * where Smithers owns the service (`Jj`) the interface names the kernel's\n * failures directly.\n *\n * `Path` is intentionally retained as an explicit decision: it checks nothing\n * and resolves relative paths against `Workspace.root`.\n * Network access is Effect's own `HttpClient`: there is no Smithers transport\n * port beneath it, because a raw port would be a second way to reach the\n * network whose contract never mentions permission.\n *\n * `Clock` and `Random` are Effect core built-ins: already port-shaped, already\n * swappable via `Effect.provideService`, and never decorated here \u2014 a `Clock`\n * or a `Random` carries no host authority to guard, so they are not ours to\n * define. `ChildProcessSpawner` is the same story one layer out: process spawning is\n * `effect/unstable/process`, and the slot holds Effect's tag rather than a\n * Smithers wrapper around it.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type HostService =\n | EffectFileSystem.FileSystem\n | EffectPath.Path\n | ChildProcessSpawnerPort\n | JjPort\n | HttpClientPort\n\n/**\n * The Host tags consumed by the kernel at runtime, decorated in place by\n * {@link layer}, and digested by the step-key planner.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport const HostServiceTags = [\n EffectFileSystem.FileSystem,\n EffectPath.Path,\n ChildProcessSpawnerPort,\n JjPort,\n HttpClientPort\n] as const\n\n/**\n * Stable slot identifiers shared by host composition, kernel attenuation, and\n * step-layer resolution.\n *\n * Each id is the tag key of its slot's service \u2014 Effect's own key for the\n * services Effect ships, the defining module's path for ours. The ids are\n * digested into step keys, so a rename invalidates every cached step naming\n * the slot; rename only when the service itself changes, as when `Shell` was\n * replaced by Effect's `ChildProcessSpawner`.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport const HostServiceIds = [\n \"effect/FileSystem\",\n \"effect/Path\",\n \"effect/process/ChildProcessSpawner\",\n \"@smthrs/jj/Jj\",\n \"effect/HttpClient\"\n] as const\n\n/**\n * Builds the full protected Host surface over a host platform bundle and a\n * `GrantStore`. `Workspace` remains a requirement so the exact same root\n * service can be supplied to both the grant store and filesystem decorators.\n *\n * Every member both requires and provides its own slot's tag: provide this\n * layer over a raw platform bundle and the guarded implementation shadows the\n * raw one for everything downstream. There is no exception and no second tag\n * list \u2014 `HttpClient` decorates Effect's network tag exactly the way\n * `FileSystem` decorates Effect's filesystem tag. The host supplies\n * `ProcessConfinement` for approved processes; absence refuses spawning.\n *\n * @category layers\n * @since 1.0.0-rc.0\n */\nexport const layer = Layer.mergeAll(\n FileSystem.layer,\n Path.layer,\n ChildProcessSpawner.layer,\n Jj.layer,\n HttpClient.layer\n)\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,gBAA6B;AAC7B,oBAA0E;AAC1E,wBAA6C;AAC7C,iCAA+D;AAC/D,0BAAqC;AACrC,iBAA4B;AAC5B,iBAA4B;AAC5B,SAAoB;AACpB,WAAsB;AAyDf,MAAM,kBAAkB;AAAA,EAC7B,cAAAA,WAAiB;AAAA,EACjB,cAAAC,KAAW;AAAA,EACX,2BAAAC;AAAA,EACA,UAAAC;AAAA,EACA,kBAAAC;AACF;AAeO,MAAM,iBAAiB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAiBO,MAAM,QAAQ,oBAAM;AAAA,EACzB,WAAW;AAAA,EACX,KAAK;AAAA,EACL,oBAAoB;AAAA,EACpB,GAAG;AAAA,EACH,WAAW;AACb;",
|
|
6
|
+
"names": ["EffectFileSystem", "EffectPath", "ChildProcessSpawnerPort", "JjPort", "HttpClientPort"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission-aware outgoing HTTP requests.
|
|
3
|
+
*
|
|
4
|
+
* There is no kernel `HttpClient` interface and no kernel `HttpClient` tag.
|
|
5
|
+
* Effect owns both, and its tag fixes the error channel to `HttpClientError`,
|
|
6
|
+
* so this module is only the middleware: a `Layer` over Effect's own tag that
|
|
7
|
+
* reads the raw client out of context and returns a guarded one in its place.
|
|
8
|
+
* Permission failures are projected into `HttpClientError` by
|
|
9
|
+
* {@link toHttpClientError}, which keeps the structured kernel failure on the
|
|
10
|
+
* transport reason's `cause` so {@link fromHttpClientError} can hand it back.
|
|
11
|
+
*
|
|
12
|
+
* **Redirects.** A redirect is a second network destination, so it needs a
|
|
13
|
+
* second grant check. Two halves guarantee that:
|
|
14
|
+
*
|
|
15
|
+
* 1. The client below this layer must **not** follow redirects on its own.
|
|
16
|
+
* That is a precondition on the host: Undici without a redirect
|
|
17
|
+
* interceptor, or Effect's fetch layer with `redirect: "manual"`. This
|
|
18
|
+
* layer also forces `RequestInit { redirect: "manual" }` over the ambient
|
|
19
|
+
* value for every request it executes, so a plain `FetchHttpClient.layer`,
|
|
20
|
+
* which follows redirects by default, cannot walk to another origin below
|
|
21
|
+
* the guard either. A custom client that ignores `RequestInit` must meet
|
|
22
|
+
* the precondition itself.
|
|
23
|
+
* 2. This layer composes Effect's own `HttpClient.followRedirects` *above*
|
|
24
|
+
* the guard. That combinator re-enters `postprocess` for every hop, and
|
|
25
|
+
* `postprocess` is the guarded one, so hop *n* is checked exactly like hop
|
|
26
|
+
* zero and an authorized origin cannot lend its grant to another.
|
|
27
|
+
* A caller that sets `FetchHttpClient.RequestInit.redirect` to `manual`
|
|
28
|
+
* receives one guarded hop and owns any further redirect requests itself.
|
|
29
|
+
*
|
|
30
|
+
* Governing design:
|
|
31
|
+
* `docs/specs/Concepts/Permission Kernel.md`,
|
|
32
|
+
* `docs/specs/Concepts/Effect Taxonomy.md`, and
|
|
33
|
+
* `docs/specs/Concepts/Host Adapters.md`.
|
|
34
|
+
*
|
|
35
|
+
* @since 1.0.0-rc.0
|
|
36
|
+
*/
|
|
37
|
+
import { type PermissionError, type PermissionErrorPayload } from "@smthrs/capability/Permission";
|
|
38
|
+
import { Context, Effect, Layer, Option } from "effect";
|
|
39
|
+
import * as EffectHttpClient from "effect/unstable/http/HttpClient";
|
|
40
|
+
import * as HttpClientError from "effect/unstable/http/HttpClientError";
|
|
41
|
+
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest";
|
|
42
|
+
import { GrantStore } from "./GrantStore.ts";
|
|
43
|
+
/**
|
|
44
|
+
* Effect's own outgoing HTTP client tag, unchanged. Re-exported so the kernel
|
|
45
|
+
* namespace stays one-stop; it is the *same* tag, never a second one.
|
|
46
|
+
*
|
|
47
|
+
* @category services
|
|
48
|
+
* @since 1.0.0-rc.0
|
|
49
|
+
*/
|
|
50
|
+
export { HttpClient } from "effect/unstable/http/HttpClient";
|
|
51
|
+
/**
|
|
52
|
+
* Constructs a client from a low-level request runner, keeping Effect's own
|
|
53
|
+
* URL construction, tracing, header redaction, and interruption behavior.
|
|
54
|
+
*
|
|
55
|
+
* @category constructors
|
|
56
|
+
* @since 1.0.0-rc.0
|
|
57
|
+
*/
|
|
58
|
+
export { make } from "effect/unstable/http/HttpClient";
|
|
59
|
+
/**
|
|
60
|
+
* The model identity an outgoing request is made on behalf of, if any.
|
|
61
|
+
*
|
|
62
|
+
* A model call is not a general `net:*` effect: the same host answers many
|
|
63
|
+
* models, and a grant for one must not be a grant for the rest. Effect's tag
|
|
64
|
+
* has no room for an extra method, so the intent rides on a `Context`
|
|
65
|
+
* reference instead — set it with {@link withModelCall} and the decorator asks
|
|
66
|
+
* for `model:call` rather than `net:get`/`net:post`.
|
|
67
|
+
*
|
|
68
|
+
* @category references
|
|
69
|
+
* @since 1.0.0-rc.0
|
|
70
|
+
*/
|
|
71
|
+
export declare const ModelCall: Context.Reference<string | undefined>;
|
|
72
|
+
/**
|
|
73
|
+
* Runs `effect` with every outgoing request in it checked as a `model:call` on
|
|
74
|
+
* `modelId` instead of as plain network access.
|
|
75
|
+
*
|
|
76
|
+
* @category references
|
|
77
|
+
* @since 1.0.0-rc.0
|
|
78
|
+
*/
|
|
79
|
+
export declare const withModelCall: (modelId: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
80
|
+
/**
|
|
81
|
+
* Projects a permission failure into the error channel Effect's `HttpClient`
|
|
82
|
+
* tag fixes.
|
|
83
|
+
*
|
|
84
|
+
* Nothing is lost: the reason is always a `TransportError` — the request did
|
|
85
|
+
* not leave the host because the capability kernel refused, suspended, or
|
|
86
|
+
* could not decide it — `description` carries the human rendering from
|
|
87
|
+
* `Permission.formatError`, and `cause` carries the structured failure itself,
|
|
88
|
+
* so {@link fromHttpClientError} hands the attended surface back the original
|
|
89
|
+
* `capability`, `tier`, `requestId`, and `reason`.
|
|
90
|
+
*
|
|
91
|
+
* @category constructors
|
|
92
|
+
* @since 1.0.0-rc.0
|
|
93
|
+
*/
|
|
94
|
+
export declare const toHttpClientError: (options: {
|
|
95
|
+
readonly request: HttpClientRequest.HttpClientRequest;
|
|
96
|
+
readonly error: PermissionError;
|
|
97
|
+
}) => HttpClientError.HttpClientError;
|
|
98
|
+
/**
|
|
99
|
+
* Recovers the structured permission failure a {@link toHttpClientError}
|
|
100
|
+
* projection carries, so an attended surface can still reply to the request
|
|
101
|
+
* and an unattended report can still name the capability.
|
|
102
|
+
*
|
|
103
|
+
* Recovery validates data fields and the transport reason tag, not origin or
|
|
104
|
+
* class operations. Establish producer or request identity separately across
|
|
105
|
+
* a trust boundary.
|
|
106
|
+
*
|
|
107
|
+
* @category refinements
|
|
108
|
+
* @since 1.0.0-rc.0
|
|
109
|
+
*/
|
|
110
|
+
export declare const fromHttpClientError: (error: HttpClientError.HttpClientError) => Option.Option<PermissionErrorPayload>;
|
|
111
|
+
/**
|
|
112
|
+
* Constructs an unavailable HTTP client stub.
|
|
113
|
+
*
|
|
114
|
+
* Every request reports the missing host as a `TransportError` naming the
|
|
115
|
+
* request, so an unconfigured capability answers rather than vanishing.
|
|
116
|
+
*
|
|
117
|
+
* @category constructors
|
|
118
|
+
* @since 1.0.0-rc.0
|
|
119
|
+
*/
|
|
120
|
+
export declare const makeNoop: () => EffectHttpClient.HttpClient;
|
|
121
|
+
/**
|
|
122
|
+
* Provides an unavailable HTTP client stub.
|
|
123
|
+
*
|
|
124
|
+
* @category layers
|
|
125
|
+
* @since 1.0.0-rc.0
|
|
126
|
+
*/
|
|
127
|
+
export declare const layerNoop: () => Layer.Layer<EffectHttpClient.HttpClient>;
|
|
128
|
+
/**
|
|
129
|
+
* Authorizes a request before a caller performs network preflight work such as
|
|
130
|
+
* DNS. The guarded transport consumes the same admission once, so a one-shot
|
|
131
|
+
* grant is not spent twice. Admissions match both store identity and the exact
|
|
132
|
+
* capability; redirects and retries require their own authorization.
|
|
133
|
+
*
|
|
134
|
+
* @category authorization
|
|
135
|
+
* @since 1.0.0
|
|
136
|
+
*/
|
|
137
|
+
export declare const authorizePreflight: <A, E, R>(request: HttpClientRequest.HttpClientRequest, effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | HttpClientError.HttpClientError, R | GrantStore>;
|
|
138
|
+
/**
|
|
139
|
+
* Decorates the HTTP client in place with a `net:get`/`net:post`/`model:call`
|
|
140
|
+
* capability check, then follows redirects *through* that check.
|
|
141
|
+
*
|
|
142
|
+
* The layer provides the tag it also requires: compose it over a host client
|
|
143
|
+
* layer with `Layer.provide` and a consumer that never heard of the kernel is
|
|
144
|
+
* guarded too. Because every hop re-enters the guarded `postprocess`, an
|
|
145
|
+
* authorized first URL that redirects to an unauthorized one is denied at the
|
|
146
|
+
* second hop instead of being fetched.
|
|
147
|
+
*
|
|
148
|
+
* @category layers
|
|
149
|
+
* @since 1.0.0-rc.0
|
|
150
|
+
*/
|
|
151
|
+
export declare const layer: Layer.Layer<EffectHttpClient.HttpClient, never, EffectHttpClient.HttpClient | GrantStore>;
|
|
152
|
+
/**
|
|
153
|
+
* Address snapshot authorized for one web request. Host transports must reject
|
|
154
|
+
* a different origin and use only these addresses for every connection attempt.
|
|
155
|
+
* Ordinary model traffic leaves this reference unset.
|
|
156
|
+
* @category references
|
|
157
|
+
* @since 1.0.0
|
|
158
|
+
*/
|
|
159
|
+
export declare const Destination: Context.Reference<{
|
|
160
|
+
readonly origin: string;
|
|
161
|
+
readonly addresses: ReadonlyArray<string>;
|
|
162
|
+
} | undefined>;
|
|
163
|
+
/**
|
|
164
|
+
* Marks a trusted transport that enforces Destination on every connection.
|
|
165
|
+
* The assertion belongs to this client instance, not ambient context. A
|
|
166
|
+
* replacement client must establish its own transport guarantee.
|
|
167
|
+
* @category constructors
|
|
168
|
+
* @since 1.0.0
|
|
169
|
+
*/
|
|
170
|
+
export declare const withDestinationPinning: <A extends EffectHttpClient.HttpClient>(client: A) => A;
|
|
171
|
+
/**
|
|
172
|
+
* Whether this exact client implements the Destination transport contract.
|
|
173
|
+
* @category predicates
|
|
174
|
+
* @since 1.0.0
|
|
175
|
+
*/
|
|
176
|
+
export declare const supportsDestinationPinning: (client: EffectHttpClient.HttpClient) => boolean;
|
|
177
|
+
//# sourceMappingURL=HttpClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpClient.d.ts","sourceRoot":"","sources":["../../src/HttpClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAIvD,OAAO,KAAK,gBAAgB,MAAM,iCAAiC,CAAA;AACnE,OAAO,KAAK,eAAe,MAAM,sCAAsC,CAAA;AACvE,OAAO,KAAK,iBAAiB,MAAM,wCAAwC,CAAA;AAE3E,OAAO,EAAE,UAAU,EAAgC,MAAM,iBAAiB,CAAA;AAyD1E;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D;;;;;;GAMG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAA;AAEtD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAG3D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAC/D,CAAA;AAEnD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS;IACzC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,iBAAiB,CAAA;IACrD,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;CAChC,KAAG,eAAe,CAAC,eAOhB,CAAA;AAEJ;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,eAAe,CAAC,eAAe,KACrC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAGpB,CAAA;AAEnB;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,QAAO,gBAAgB,CAAC,UAU1C,CAAA;AAEH;;;;;GAKG;AACH,eAAO,MAAM,SAAS,QAAO,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CACZ,CAAA;AA6CxD;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EACxC,SAAS,iBAAiB,CAAC,iBAAiB,EAC5C,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,eAAe,EAAE,CAAC,GAAG,UAAU,CAQnE,CAAA;AAYJ;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAC7B,gBAAgB,CAAC,UAAU,EAC3B,KAAK,EACL,gBAAgB,CAAC,UAAU,GAAG,UAAU,CAiDzC,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW;qBAEH,MAAM;wBACH,aAAa,CAAC,MAAM,CAAC;cAEgC,CAAA;AAI7E;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,GAAI,CAAC,SAAS,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,KAAG,CAGzF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,gBAAgB,CAAC,UAAU,KAAG,OAAoC,CAAA"}
|