spell-runtime 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -7
- package/README.txt +90 -7
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +70 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/server.d.ts +19 -0
- package/dist/api/server.js +868 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/ui.d.ts +2 -0
- package/dist/api/ui.js +474 -0
- package/dist/api/ui.js.map +1 -0
- package/dist/bundle/install.js +9 -0
- package/dist/bundle/install.js.map +1 -1
- package/dist/cli/index.js +93 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/contract/buttonRegistry.d.ts +21 -0
- package/dist/contract/buttonRegistry.js +103 -0
- package/dist/contract/buttonRegistry.js.map +1 -0
- package/dist/logging/executionLog.js +3 -1
- package/dist/logging/executionLog.js.map +1 -1
- package/dist/runner/cast.js +43 -3
- package/dist/runner/cast.js.map +1 -1
- package/dist/runner/dockerRunner.d.ts +9 -0
- package/dist/runner/dockerRunner.js +121 -0
- package/dist/runner/dockerRunner.js.map +1 -0
- package/dist/runner/spell-runner.d.ts +11 -0
- package/dist/runner/spell-runner.js +144 -0
- package/dist/runner/spell-runner.js.map +1 -0
- package/dist/signature/bundleDigest.d.ts +6 -0
- package/dist/signature/bundleDigest.js +89 -0
- package/dist/signature/bundleDigest.js.map +1 -0
- package/dist/signature/signatureFile.d.ts +12 -0
- package/dist/signature/signatureFile.js +79 -0
- package/dist/signature/signatureFile.js.map +1 -0
- package/dist/signature/signing.d.ts +27 -0
- package/dist/signature/signing.js +87 -0
- package/dist/signature/signing.js.map +1 -0
- package/dist/signature/trustStore.d.ts +20 -0
- package/dist/signature/trustStore.js +173 -0
- package/dist/signature/trustStore.js.map +1 -0
- package/dist/signature/verify.d.ts +12 -0
- package/dist/signature/verify.js +119 -0
- package/dist/signature/verify.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/util/paths.d.ts +2 -0
- package/dist/util/paths.js +9 -0
- package/dist/util/paths.js.map +1 -1
- package/dist/util/platform.d.ts +2 -0
- package/dist/util/platform.js +38 -0
- package/dist/util/platform.js.map +1 -1
- package/dist/util/redact.d.ts +2 -0
- package/dist/util/redact.js +66 -0
- package/dist/util/redact.js.map +1 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -46,7 +46,12 @@ npm run smoke:npx
|
|
|
46
46
|
- `spell install <local-path>`
|
|
47
47
|
- `spell list`
|
|
48
48
|
- `spell inspect <id> [--version x.y.z]`
|
|
49
|
-
- `spell cast <id> [--version x.y.z] [-p key=value ...] [--input input.json] [--dry-run] [--yes] [--allow-billing] [--verbose] [--profile <name>]`
|
|
49
|
+
- `spell cast <id> [--version x.y.z] [-p key=value ...] [--input input.json] [--dry-run] [--yes] [--allow-billing] [--require-signature] [--verbose] [--profile <name>]`
|
|
50
|
+
- `spell sign keygen <publisher> [--key-id default] [--out-dir .spell-keys]`
|
|
51
|
+
- `spell sign bundle <local-path> --private-key <file> [--key-id default] [--publisher <name>]`
|
|
52
|
+
- `spell trust add <publisher> <public-key> [--key-id default]`
|
|
53
|
+
- `spell trust list`
|
|
54
|
+
- `spell trust remove <publisher>`
|
|
50
55
|
- `spell log <execution-id>`
|
|
51
56
|
|
|
52
57
|
## Storage Layout
|
|
@@ -72,6 +77,7 @@ Consistency rule:
|
|
|
72
77
|
- bundle resolution by id (and optional version)
|
|
73
78
|
- input assembly (`--input` + `-p` overrides)
|
|
74
79
|
- JSON Schema validation by Ajv
|
|
80
|
+
- optional signature verification (`--require-signature`)
|
|
75
81
|
- platform guard
|
|
76
82
|
- risk guard (`high`/`critical` requires `--yes`)
|
|
77
83
|
- billing guard (`billing.enabled` requires `--allow-billing`)
|
|
@@ -82,14 +88,17 @@ If `--dry-run` is set, command exits after summary and validation.
|
|
|
82
88
|
|
|
83
89
|
## Runtime Model
|
|
84
90
|
|
|
85
|
-
v1 supports
|
|
91
|
+
v1 supports:
|
|
86
92
|
|
|
87
93
|
- host: steps run in order, shell/http supported.
|
|
88
|
-
- docker:
|
|
94
|
+
- docker: steps run in a linux container via "runner-in-image".
|
|
89
95
|
|
|
90
|
-
|
|
96
|
+
Docker mode (v1) details:
|
|
91
97
|
|
|
92
|
-
- docker
|
|
98
|
+
- `runtime.execution=docker` requires `runtime.docker_image`.
|
|
99
|
+
- the image must provide `spell-runner` on `PATH` (this repo publishes it as a second npm bin).
|
|
100
|
+
- the bundle is mounted read-only at `/spell`; the runner copies it into a writable temp workdir before executing steps.
|
|
101
|
+
- environment variables passed from host -> container are restricted to connector tokens only (`CONNECTOR_<NAME>_TOKEN`). If your spell needs `{{ENV.*}}` for other values, provide them inside the image (or extend the runtime later).
|
|
93
102
|
|
|
94
103
|
## Windows Policy
|
|
95
104
|
|
|
@@ -111,11 +120,38 @@ Use these `effect.type` words where possible:
|
|
|
111
120
|
## v1 Limitations (Intentionally Not Implemented)
|
|
112
121
|
|
|
113
122
|
- name search or ambiguous resolution (id only)
|
|
114
|
-
- registry/marketplace/
|
|
123
|
+
- registry/marketplace/license verification
|
|
115
124
|
- real billing execution (Stripe)
|
|
116
125
|
- DAG/parallel/rollback/self-healing
|
|
117
126
|
- advanced templating language (only `{{INPUT.*}}` and `{{ENV.*}}`)
|
|
118
|
-
- docker
|
|
127
|
+
- docker env passthrough beyond connector tokens
|
|
128
|
+
|
|
129
|
+
## Signature (Sign + Verify)
|
|
130
|
+
|
|
131
|
+
If a bundle contains `spell.sig.json`, you can require signature verification at execution time:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
spell cast <id> --require-signature ...
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Signing flow:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
spell sign keygen samples --key-id default --out-dir .spell-keys
|
|
141
|
+
spell trust add samples <public_key_base64url> --key-id default
|
|
142
|
+
spell sign bundle ./examples/spells/call-webhook --private-key .spell-keys/samples__default.private.pem --key-id default
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Trust store:
|
|
146
|
+
|
|
147
|
+
- `spell trust add <publisher> <public-key>`
|
|
148
|
+
- `spell trust list`
|
|
149
|
+
- `spell trust remove <publisher>`
|
|
150
|
+
|
|
151
|
+
Notes:
|
|
152
|
+
|
|
153
|
+
- publisher is derived from the spell id prefix before the first `/` (example: `samples/call-webhook` -> `samples`).
|
|
154
|
+
- public key format is ed25519 `spki` DER encoded as base64url.
|
|
119
155
|
|
|
120
156
|
## Example Flow
|
|
121
157
|
|
|
@@ -128,9 +164,75 @@ spell cast fixtures/hello-host -p name=world
|
|
|
128
164
|
spell log <execution-id>
|
|
129
165
|
```
|
|
130
166
|
|
|
167
|
+
## Real-Use Sample Spells
|
|
168
|
+
|
|
169
|
+
These are product-facing examples (separate from test fixtures):
|
|
170
|
+
|
|
171
|
+
- `/Users/koichinishizuka/spell-runtime/examples/spells/call-webhook`
|
|
172
|
+
- `/Users/koichinishizuka/spell-runtime/examples/spells/repo-ops`
|
|
173
|
+
- `/Users/koichinishizuka/spell-runtime/examples/spells/publish-site`
|
|
174
|
+
|
|
175
|
+
Quick try:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
spell install ./examples/spells/call-webhook
|
|
179
|
+
spell inspect samples/call-webhook
|
|
180
|
+
spell cast samples/call-webhook --dry-run -p event=deploy -p source=manual -p payload='{"service":"web"}'
|
|
181
|
+
```
|
|
182
|
+
|
|
131
183
|
## UI Connection Spec
|
|
132
184
|
|
|
133
185
|
- Decision-complete button integration spec:
|
|
134
186
|
- `/Users/koichinishizuka/spell-runtime/docs/ui-connection-spec-v1.md`
|
|
135
187
|
- Sample button registry:
|
|
136
188
|
- `/Users/koichinishizuka/spell-runtime/examples/button-registry.v1.json`
|
|
189
|
+
- Button registry schema:
|
|
190
|
+
- `/Users/koichinishizuka/spell-runtime/examples/button-registry.v1.schema.json`
|
|
191
|
+
- Registry optional policy:
|
|
192
|
+
- `require_signature` (when true, Execution API adds `--require-signature`)
|
|
193
|
+
|
|
194
|
+
## Runtime Decision Log
|
|
195
|
+
|
|
196
|
+
- `/Users/koichinishizuka/spell-runtime/docs/runtime-decisions-v1.md`
|
|
197
|
+
|
|
198
|
+
## Execution API (Async)
|
|
199
|
+
|
|
200
|
+
Start API server:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
npm run api:dev
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
By default it listens on `:8787` and reads:
|
|
207
|
+
- button registry: `./examples/button-registry.v1.json`
|
|
208
|
+
- limits:
|
|
209
|
+
- request body: `64KB`
|
|
210
|
+
- execution timeout: `60s`
|
|
211
|
+
- in-flight executions: `4`
|
|
212
|
+
- execution index persistence: `~/.spell/logs/index.json`
|
|
213
|
+
- routes:
|
|
214
|
+
- `GET /` (minimal Receipts UI)
|
|
215
|
+
- `GET /ui/app.js` (UI client script)
|
|
216
|
+
- `GET /api/buttons`
|
|
217
|
+
- `GET /api/spell-executions` (`status`, `button_id`, `limit` query supported)
|
|
218
|
+
- `POST /api/spell-executions`
|
|
219
|
+
- `GET /api/spell-executions/:execution_id`
|
|
220
|
+
|
|
221
|
+
Optional environment variables:
|
|
222
|
+
- `SPELL_API_PORT`
|
|
223
|
+
- `SPELL_BUTTON_REGISTRY_PATH`
|
|
224
|
+
- `SPELL_API_AUTH_KEYS` (comma-separated `role=token` entries; when set, `/api/*` requires auth and derives `actor_role` from token)
|
|
225
|
+
- `SPELL_API_AUTH_TOKENS` (legacy: comma-separated tokens; when set, `/api/*` requires auth but does not bind role)
|
|
226
|
+
- `SPELL_API_BODY_LIMIT_BYTES`
|
|
227
|
+
- `SPELL_API_EXECUTION_TIMEOUT_MS`
|
|
228
|
+
- `SPELL_API_RATE_LIMIT_WINDOW_MS`
|
|
229
|
+
- `SPELL_API_RATE_LIMIT_MAX_REQUESTS`
|
|
230
|
+
- `SPELL_API_MAX_CONCURRENT_EXECUTIONS`
|
|
231
|
+
- `SPELL_API_LOG_RETENTION_DAYS` (default `14`, `0` disables age-based pruning)
|
|
232
|
+
- `SPELL_API_LOG_MAX_FILES` (default `500`, `0` disables count-based pruning)
|
|
233
|
+
|
|
234
|
+
Security note:
|
|
235
|
+
- execution logs redact secret-like keys (`token`, `authorization`, `apiKey`, etc.)
|
|
236
|
+
- environment-derived secret values are masked in persisted logs
|
|
237
|
+
- when auth is enabled, pass `Authorization: Bearer <token>` (or `x-api-key`) for `/api` routes
|
|
238
|
+
- do not set both `SPELL_API_AUTH_KEYS` and `SPELL_API_AUTH_TOKENS` at the same time
|
package/README.txt
CHANGED
|
@@ -33,7 +33,12 @@ Manual npx (local package):
|
|
|
33
33
|
- spell install <local-path>
|
|
34
34
|
- spell list
|
|
35
35
|
- spell inspect <id> [--version x.y.z]
|
|
36
|
-
- spell cast <id> [--version x.y.z] [-p key=value ...] [--input input.json] [--dry-run] [--yes] [--allow-billing] [--verbose] [--profile <name>]
|
|
36
|
+
- spell cast <id> [--version x.y.z] [-p key=value ...] [--input input.json] [--dry-run] [--yes] [--allow-billing] [--require-signature] [--verbose] [--profile <name>]
|
|
37
|
+
- spell sign keygen <publisher> [--key-id default] [--out-dir .spell-keys]
|
|
38
|
+
- spell sign bundle <local-path> --private-key <file> [--key-id default] [--publisher <name>]
|
|
39
|
+
- spell trust add <publisher> <public-key> [--key-id default]
|
|
40
|
+
- spell trust list
|
|
41
|
+
- spell trust remove <publisher>
|
|
37
42
|
- spell log <execution-id>
|
|
38
43
|
|
|
39
44
|
3. Storage layout
|
|
@@ -54,6 +59,7 @@ Cast performs these checks before execution:
|
|
|
54
59
|
- Bundle resolution by id (and optional version)
|
|
55
60
|
- Input assembly (--input + -p overrides)
|
|
56
61
|
- JSON Schema validation by Ajv
|
|
62
|
+
- Optional signature verification (--require-signature)
|
|
57
63
|
- Platform guard
|
|
58
64
|
- Risk guard (high/critical requires --yes)
|
|
59
65
|
- Billing guard (billing.enabled requires --allow-billing)
|
|
@@ -63,12 +69,15 @@ Cast performs these checks before execution:
|
|
|
63
69
|
If --dry-run is set, command exits after summary and validation.
|
|
64
70
|
|
|
65
71
|
5. Runtime model
|
|
66
|
-
v1 supports
|
|
72
|
+
v1 supports:
|
|
67
73
|
- host: steps run in order, shell/http supported.
|
|
68
|
-
- docker:
|
|
74
|
+
- docker: steps run in a linux container via "runner-in-image".
|
|
69
75
|
|
|
70
|
-
|
|
71
|
-
- docker
|
|
76
|
+
Docker mode (v1) details:
|
|
77
|
+
- runtime.execution=docker requires runtime.docker_image.
|
|
78
|
+
- the image must provide spell-runner on PATH (this repo publishes it as a second npm bin).
|
|
79
|
+
- the bundle is mounted read-only at /spell; the runner copies it into a writable temp workdir before executing steps.
|
|
80
|
+
- env vars passed from host -> container are restricted to connector tokens only (CONNECTOR_<NAME>_TOKEN). If your spell needs {{ENV.*}} for other values, provide them inside the image (or extend the runtime later).
|
|
72
81
|
|
|
73
82
|
6. Windows policy
|
|
74
83
|
- host mode does not assume bash/sh.
|
|
@@ -86,11 +95,29 @@ Use these effect.type words where possible:
|
|
|
86
95
|
|
|
87
96
|
8. v1 limitations (intentionally not implemented)
|
|
88
97
|
- name search or ambiguous resolution (id only)
|
|
89
|
-
- registry/marketplace/
|
|
98
|
+
- registry/marketplace/license verification
|
|
90
99
|
- real billing execution (Stripe)
|
|
91
100
|
- DAG/parallel/rollback/self-healing
|
|
92
101
|
- advanced templating language (only {{INPUT.*}} and {{ENV.*}})
|
|
93
|
-
- docker
|
|
102
|
+
- docker env passthrough beyond connector tokens
|
|
103
|
+
|
|
104
|
+
8.1 Signature (sign + verify)
|
|
105
|
+
If a bundle contains spell.sig.json, you can require signature verification at execution time:
|
|
106
|
+
spell cast <id> --require-signature ...
|
|
107
|
+
|
|
108
|
+
Signing flow:
|
|
109
|
+
spell sign keygen samples --key-id default --out-dir .spell-keys
|
|
110
|
+
spell trust add samples <public_key_base64url> --key-id default
|
|
111
|
+
spell sign bundle ./examples/spells/call-webhook --private-key .spell-keys/samples__default.private.pem --key-id default
|
|
112
|
+
|
|
113
|
+
Trust store:
|
|
114
|
+
- spell trust add <publisher> <public-key>
|
|
115
|
+
- spell trust list
|
|
116
|
+
- spell trust remove <publisher>
|
|
117
|
+
|
|
118
|
+
Notes:
|
|
119
|
+
- publisher is derived from the spell id prefix before the first / (example: samples/call-webhook -> samples).
|
|
120
|
+
- public key format is ed25519 spki DER encoded as base64url.
|
|
94
121
|
|
|
95
122
|
9. Example flow
|
|
96
123
|
1) Install a local fixture
|
|
@@ -116,6 +143,10 @@ Use these effect.type words where possible:
|
|
|
116
143
|
/Users/koichinishizuka/spell-runtime/docs/ui-connection-spec-v1.md
|
|
117
144
|
- Sample button registry:
|
|
118
145
|
/Users/koichinishizuka/spell-runtime/examples/button-registry.v1.json
|
|
146
|
+
- Button registry schema:
|
|
147
|
+
/Users/koichinishizuka/spell-runtime/examples/button-registry.v1.schema.json
|
|
148
|
+
- Registry optional policy:
|
|
149
|
+
require_signature (when true, Execution API adds --require-signature)
|
|
119
150
|
|
|
120
151
|
11. Install from npm
|
|
121
152
|
Global install:
|
|
@@ -124,3 +155,55 @@ Global install:
|
|
|
124
155
|
|
|
125
156
|
Run with npx:
|
|
126
157
|
npx --yes --package spell-runtime spell --help
|
|
158
|
+
|
|
159
|
+
12. Real-use sample spells
|
|
160
|
+
- /Users/koichinishizuka/spell-runtime/examples/spells/call-webhook
|
|
161
|
+
- /Users/koichinishizuka/spell-runtime/examples/spells/repo-ops
|
|
162
|
+
- /Users/koichinishizuka/spell-runtime/examples/spells/publish-site
|
|
163
|
+
|
|
164
|
+
Quick try:
|
|
165
|
+
spell install ./examples/spells/call-webhook
|
|
166
|
+
spell inspect samples/call-webhook
|
|
167
|
+
spell cast samples/call-webhook --dry-run -p event=deploy -p source=manual -p payload='{"service":"web"}'
|
|
168
|
+
|
|
169
|
+
13. Runtime decision log
|
|
170
|
+
- /Users/koichinishizuka/spell-runtime/docs/runtime-decisions-v1.md
|
|
171
|
+
|
|
172
|
+
14. Execution API (async)
|
|
173
|
+
Start:
|
|
174
|
+
npm run api:dev
|
|
175
|
+
|
|
176
|
+
Defaults:
|
|
177
|
+
- listens on :8787
|
|
178
|
+
- reads registry: ./examples/button-registry.v1.json
|
|
179
|
+
- limits:
|
|
180
|
+
- request body: 64KB
|
|
181
|
+
- execution timeout: 60s
|
|
182
|
+
- in-flight executions: 4
|
|
183
|
+
- execution index persistence: ~/.spell/logs/index.json
|
|
184
|
+
- routes:
|
|
185
|
+
GET /
|
|
186
|
+
GET /ui/app.js
|
|
187
|
+
GET /api/buttons
|
|
188
|
+
GET /api/spell-executions (status/button_id/limit query supported)
|
|
189
|
+
POST /api/spell-executions
|
|
190
|
+
GET /api/spell-executions/:execution_id
|
|
191
|
+
|
|
192
|
+
Optional environment variables:
|
|
193
|
+
- SPELL_API_PORT
|
|
194
|
+
- SPELL_BUTTON_REGISTRY_PATH
|
|
195
|
+
- SPELL_API_AUTH_KEYS (comma-separated role=token entries; when set, /api/* requires auth and derives actor_role from token)
|
|
196
|
+
- SPELL_API_AUTH_TOKENS (legacy: comma-separated tokens; when set, /api/* requires auth but does not bind role)
|
|
197
|
+
- SPELL_API_BODY_LIMIT_BYTES
|
|
198
|
+
- SPELL_API_EXECUTION_TIMEOUT_MS
|
|
199
|
+
- SPELL_API_RATE_LIMIT_WINDOW_MS
|
|
200
|
+
- SPELL_API_RATE_LIMIT_MAX_REQUESTS
|
|
201
|
+
- SPELL_API_MAX_CONCURRENT_EXECUTIONS
|
|
202
|
+
- SPELL_API_LOG_RETENTION_DAYS (default 14, 0 disables age-based pruning)
|
|
203
|
+
- SPELL_API_LOG_MAX_FILES (default 500, 0 disables count-based pruning)
|
|
204
|
+
|
|
205
|
+
Security note:
|
|
206
|
+
- execution logs redact secret-like keys (token, authorization, apiKey, etc.)
|
|
207
|
+
- environment-derived secret values are masked in persisted logs
|
|
208
|
+
- when auth is enabled, pass Authorization: Bearer <token> (or x-api-key) for /api routes
|
|
209
|
+
- do not set both SPELL_API_AUTH_KEYS and SPELL_API_AUTH_TOKENS at the same time
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const server_1 = require("./server");
|
|
4
|
+
async function main() {
|
|
5
|
+
const port = readIntegerEnv("SPELL_API_PORT", 1, 8787);
|
|
6
|
+
const registryPath = process.env.SPELL_BUTTON_REGISTRY_PATH;
|
|
7
|
+
const requestBodyLimitBytes = readOptionalIntegerEnv("SPELL_API_BODY_LIMIT_BYTES", 1);
|
|
8
|
+
const executionTimeoutMs = readOptionalIntegerEnv("SPELL_API_EXECUTION_TIMEOUT_MS", 1);
|
|
9
|
+
const rateLimitWindowMs = readOptionalIntegerEnv("SPELL_API_RATE_LIMIT_WINDOW_MS", 1);
|
|
10
|
+
const rateLimitMaxRequests = readOptionalIntegerEnv("SPELL_API_RATE_LIMIT_MAX_REQUESTS", 1);
|
|
11
|
+
const maxConcurrentExecutions = readOptionalIntegerEnv("SPELL_API_MAX_CONCURRENT_EXECUTIONS", 0);
|
|
12
|
+
const authTokens = readOptionalCsvEnv("SPELL_API_AUTH_TOKENS");
|
|
13
|
+
const authKeys = readOptionalCsvEnv("SPELL_API_AUTH_KEYS");
|
|
14
|
+
const logRetentionDays = readOptionalIntegerEnv("SPELL_API_LOG_RETENTION_DAYS", 0);
|
|
15
|
+
const logMaxFiles = readOptionalIntegerEnv("SPELL_API_LOG_MAX_FILES", 0);
|
|
16
|
+
const started = await (0, server_1.startExecutionApiServer)({
|
|
17
|
+
port,
|
|
18
|
+
registryPath,
|
|
19
|
+
requestBodyLimitBytes,
|
|
20
|
+
executionTimeoutMs,
|
|
21
|
+
rateLimitWindowMs,
|
|
22
|
+
rateLimitMaxRequests,
|
|
23
|
+
maxConcurrentExecutions,
|
|
24
|
+
authTokens,
|
|
25
|
+
authKeys,
|
|
26
|
+
logRetentionDays,
|
|
27
|
+
logMaxFiles
|
|
28
|
+
});
|
|
29
|
+
process.stdout.write(`spell execution api listening on :${started.port}\n`);
|
|
30
|
+
}
|
|
31
|
+
main().catch((error) => {
|
|
32
|
+
process.stderr.write(`${error.message}\n`);
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
});
|
|
35
|
+
function readOptionalIntegerEnv(name, min) {
|
|
36
|
+
const raw = process.env[name];
|
|
37
|
+
if (raw === undefined || raw.trim() === "") {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
return readInteger(name, raw, min);
|
|
41
|
+
}
|
|
42
|
+
function readIntegerEnv(name, min, fallback) {
|
|
43
|
+
const raw = process.env[name];
|
|
44
|
+
if (raw === undefined || raw.trim() === "") {
|
|
45
|
+
return fallback;
|
|
46
|
+
}
|
|
47
|
+
return readInteger(name, raw, min);
|
|
48
|
+
}
|
|
49
|
+
function readInteger(name, raw, min) {
|
|
50
|
+
const num = Number(raw);
|
|
51
|
+
if (!Number.isInteger(num) || num < min) {
|
|
52
|
+
throw new Error(`${name} must be an integer >= ${min}`);
|
|
53
|
+
}
|
|
54
|
+
return num;
|
|
55
|
+
}
|
|
56
|
+
function readOptionalCsvEnv(name) {
|
|
57
|
+
const raw = process.env[name];
|
|
58
|
+
if (raw === undefined || raw.trim() === "") {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const values = raw
|
|
62
|
+
.split(",")
|
|
63
|
+
.map((entry) => entry.trim())
|
|
64
|
+
.filter((entry) => entry.length > 0);
|
|
65
|
+
if (values.length === 0) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
return values;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ExecutionApiServerOptions {
|
|
2
|
+
port?: number;
|
|
3
|
+
registryPath?: string;
|
|
4
|
+
requestBodyLimitBytes?: number;
|
|
5
|
+
executionTimeoutMs?: number;
|
|
6
|
+
rateLimitWindowMs?: number;
|
|
7
|
+
rateLimitMaxRequests?: number;
|
|
8
|
+
maxConcurrentExecutions?: number;
|
|
9
|
+
authTokens?: string[];
|
|
10
|
+
authKeys?: string[];
|
|
11
|
+
logRetentionDays?: number;
|
|
12
|
+
logMaxFiles?: number;
|
|
13
|
+
}
|
|
14
|
+
interface StartExecutionApiServerResult {
|
|
15
|
+
port: number;
|
|
16
|
+
close: () => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare function startExecutionApiServer(options?: ExecutionApiServerOptions): Promise<StartExecutionApiServerResult>;
|
|
19
|
+
export {};
|