@pulse-compute/cli 0.0.0 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/API.md +539 -0
  2. package/CHANGELOG.md +47 -0
  3. package/README.md +70 -1
  4. package/bin/pulse.js +15 -0
  5. package/bin/pulsewasm-extract.js +22 -0
  6. package/cli-spec.json +575 -0
  7. package/completions/_pulse +106 -0
  8. package/completions/pulse.bash +31 -0
  9. package/completions/pulse.fish +76 -0
  10. package/docs/README.md +77 -0
  11. package/docs/architecture/current-contracts.md +381 -0
  12. package/docs/architecture/overview.md +93 -0
  13. package/docs/architecture/vision.md +515 -0
  14. package/docs/concepts/bodies.md +186 -0
  15. package/docs/concepts/compilation-and-lowering.md +496 -0
  16. package/docs/concepts/contracts-and-providers.md +158 -0
  17. package/docs/concepts/effects-and-continuations.md +243 -0
  18. package/docs/concepts/entities-and-adapters.md +71 -0
  19. package/docs/concepts/package-owned-lowering.md +175 -0
  20. package/docs/concepts/targets-and-hosts.md +62 -0
  21. package/docs/contributing/README.md +38 -0
  22. package/docs/contributing/adding-core-provider.md +315 -0
  23. package/docs/contributing/adding-first-party-lowerer.md +327 -0
  24. package/docs/contributing/entities-lowering.md +91 -0
  25. package/docs/contributing/package-lowerer-contract.md +383 -0
  26. package/docs/contributing/pulse-aware-packages.md +149 -0
  27. package/docs/examples.md +112 -0
  28. package/docs/fixtures/inspect-fetch-composition.selected.json +181 -0
  29. package/docs/getting-started.md +128 -0
  30. package/docs/guides/compatibility-imports.md +60 -0
  31. package/docs/guides/deploying-fastly.md +188 -0
  32. package/docs/guides/deploying-node.md +143 -0
  33. package/docs/guides/events.md +233 -0
  34. package/docs/guides/fastly-capabilities.md +153 -0
  35. package/docs/guides/fetching-and-composition.md +101 -0
  36. package/docs/guides/grip.md +94 -0
  37. package/docs/guides/json-schemas.md +233 -0
  38. package/docs/guides/migrating-from-express.md +192 -0
  39. package/docs/guides/project-lifecycle.md +143 -0
  40. package/docs/guides/routing.md +184 -0
  41. package/docs/guides/troubleshooting.md +47 -0
  42. package/docs/maintainers/README.md +60 -0
  43. package/docs/maintainers/codex-maintainer.md +71 -0
  44. package/docs/maintainers/documentation-deployment.md +147 -0
  45. package/docs/maintainers/documentation-system.md +58 -0
  46. package/docs/maintainers/documentation-versioning.md +65 -0
  47. package/docs/maintainers/maintainer-charter.md +84 -0
  48. package/docs/maintainers/maintenance-policy.json +778 -0
  49. package/docs/maintainers/maintenance-policy.md +124 -0
  50. package/docs/maintainers/npm-publishing.md +154 -0
  51. package/docs/maintainers/plugin-readiness.json +19 -0
  52. package/docs/maintainers/plugin-readiness.md +31 -0
  53. package/docs/maintainers/public-site.md +158 -0
  54. package/docs/maintainers/release-acceptance.md +250 -0
  55. package/docs/maintainers/release-manifest.md +88 -0
  56. package/docs/maintainers/repository-setup.md +145 -0
  57. package/docs/maintainers/scope-policy.md +93 -0
  58. package/docs/maintainers/support-and-triage.md +74 -0
  59. package/docs/maintainers/testing.md +288 -0
  60. package/docs/packages/README.md +59 -0
  61. package/docs/packages/assets.md +85 -0
  62. package/docs/packages/cli.md +190 -0
  63. package/docs/packages/crypto.md +71 -0
  64. package/docs/packages/entities.md +129 -0
  65. package/docs/packages/grip.md +82 -0
  66. package/docs/packages/implementation-packages.md +113 -0
  67. package/docs/packages/jwt.md +55 -0
  68. package/docs/packages/provider-fastly.md +217 -0
  69. package/docs/packages/pulse.md +159 -0
  70. package/docs/packages/runtime.md +256 -0
  71. package/docs/preview-scope.md +142 -0
  72. package/docs/reference/README.md +33 -0
  73. package/docs/reference/cli-spec.json +575 -0
  74. package/docs/reference/cli.md +457 -0
  75. package/docs/reference/compatibility-matrix.md +169 -0
  76. package/docs/reference/diagnostics.md +1872 -0
  77. package/docs/reference/documentation-versions.json +14 -0
  78. package/docs/reference/environment.md +347 -0
  79. package/docs/reference/handler-authoring.md +264 -0
  80. package/docs/reference/project-config.md +554 -0
  81. package/docs/reference/project-config.schema.json +918 -0
  82. package/docs/reference/release-manifest.json +427 -0
  83. package/docs/reference/shell-completion.md +23 -0
  84. package/documentation-site.json +661 -0
  85. package/documentation-versions.json +14 -0
  86. package/examples/01-hello-json/.pulse/.gitignore +3 -0
  87. package/examples/01-hello-json/.pulse/config.ts +16 -0
  88. package/examples/01-hello-json/README.md +119 -0
  89. package/examples/01-hello-json/package.json +20 -0
  90. package/examples/01-hello-json/src/index.ts +9 -0
  91. package/examples/01-hello-json/tests/pulse.harness.ts +22 -0
  92. package/examples/01-hello-json/tsconfig.json +14 -0
  93. package/examples/02-request-schema/.pulse/.gitignore +3 -0
  94. package/examples/02-request-schema/.pulse/config.ts +17 -0
  95. package/examples/02-request-schema/README.md +145 -0
  96. package/examples/02-request-schema/package.json +20 -0
  97. package/examples/02-request-schema/src/index.ts +18 -0
  98. package/examples/02-request-schema/src/schemas.ts +20 -0
  99. package/examples/02-request-schema/tests/pulse.harness.ts +37 -0
  100. package/examples/02-request-schema/tsconfig.json +14 -0
  101. package/examples/03-fetch-composition/.pulse/.gitignore +3 -0
  102. package/examples/03-fetch-composition/.pulse/config.ts +31 -0
  103. package/examples/03-fetch-composition/README.md +210 -0
  104. package/examples/03-fetch-composition/package.json +20 -0
  105. package/examples/03-fetch-composition/src/index.ts +60 -0
  106. package/examples/03-fetch-composition/tests/pulse.harness.ts +47 -0
  107. package/examples/03-fetch-composition/tsconfig.json +14 -0
  108. package/examples/05-fastly-capabilities/.pulse/.gitignore +3 -0
  109. package/examples/05-fastly-capabilities/.pulse/config.ts +57 -0
  110. package/examples/05-fastly-capabilities/README.md +257 -0
  111. package/examples/05-fastly-capabilities/package.json +22 -0
  112. package/examples/05-fastly-capabilities/src/index.ts +55 -0
  113. package/examples/05-fastly-capabilities/tests/pulse.harness.ts +66 -0
  114. package/examples/05-fastly-capabilities/tsconfig.json +14 -0
  115. package/examples/07-opaque-proxy/.pulse/.gitignore +3 -0
  116. package/examples/07-opaque-proxy/.pulse/config.ts +38 -0
  117. package/examples/07-opaque-proxy/README.md +150 -0
  118. package/examples/07-opaque-proxy/package.json +21 -0
  119. package/examples/07-opaque-proxy/src/index.ts +9 -0
  120. package/examples/07-opaque-proxy/tests/pulse.harness.ts +25 -0
  121. package/examples/07-opaque-proxy/tsconfig.json +14 -0
  122. package/examples/09-router-lowering/.pulse/.gitignore +3 -0
  123. package/examples/09-router-lowering/.pulse/config.ts +22 -0
  124. package/examples/09-router-lowering/README.md +287 -0
  125. package/examples/09-router-lowering/package.json +22 -0
  126. package/examples/09-router-lowering/src/index.ts +65 -0
  127. package/examples/09-router-lowering/tests/pulse.harness.ts +91 -0
  128. package/examples/09-router-lowering/tsconfig.json +14 -0
  129. package/examples/10-entities-tools/.pulse/.gitignore +4 -0
  130. package/examples/10-entities-tools/.pulse/config.ts +23 -0
  131. package/examples/10-entities-tools/README.md +165 -0
  132. package/examples/10-entities-tools/package.json +21 -0
  133. package/examples/10-entities-tools/src/handlers.ts +15 -0
  134. package/examples/10-entities-tools/src/index.ts +31 -0
  135. package/examples/10-entities-tools/src/schemas.ts +18 -0
  136. package/examples/10-entities-tools/tests/pulse.harness.ts +40 -0
  137. package/examples/10-entities-tools/tools-facade.cjs +158 -0
  138. package/examples/10-entities-tools/tsconfig.json +14 -0
  139. package/examples/11-events/.pulse/.gitignore +4 -0
  140. package/examples/11-events/.pulse/config.ts +24 -0
  141. package/examples/11-events/README.md +194 -0
  142. package/examples/11-events/package.json +20 -0
  143. package/examples/11-events/src/index.ts +27 -0
  144. package/examples/11-events/src/schemas.ts +19 -0
  145. package/examples/11-events/tests/pulse.harness.ts +34 -0
  146. package/examples/11-events/tsconfig.json +15 -0
  147. package/examples/12-mcp-proxy/.pulse/.gitignore +3 -0
  148. package/examples/12-mcp-proxy/.pulse/config.ts +25 -0
  149. package/examples/12-mcp-proxy/README.md +149 -0
  150. package/examples/12-mcp-proxy/package.json +20 -0
  151. package/examples/12-mcp-proxy/src/index.ts +17 -0
  152. package/examples/12-mcp-proxy/tests/pulse.harness.ts +29 -0
  153. package/examples/12-mcp-proxy/tsconfig.json +14 -0
  154. package/examples/13-jwt-es256/.pulse/config.ts +19 -0
  155. package/examples/13-jwt-es256/README.md +195 -0
  156. package/examples/13-jwt-es256/package.json +21 -0
  157. package/examples/13-jwt-es256/src/index.ts +21 -0
  158. package/examples/13-jwt-es256/tests/pulse.harness.ts +54 -0
  159. package/examples/13-jwt-es256/tsconfig.json +14 -0
  160. package/examples/README.md +36 -0
  161. package/package.json +66 -6
  162. package/project-config.schema.json +918 -0
  163. package/release-manifest.json +427 -0
  164. package/src/command-spec.js +279 -0
  165. package/src/completion.js +113 -0
  166. package/src/diagnostics.js +350 -0
  167. package/src/documentation.js +45 -0
  168. package/src/index.d.ts +133 -0
  169. package/src/index.js +15 -0
  170. package/src/internal/command-executor.d.ts +29 -0
  171. package/src/internal/command-executor.js +143 -0
  172. package/src/internal/command-plan.d.ts +9 -0
  173. package/src/internal/command-plan.js +73 -0
  174. package/src/internal/command-reporter.d.ts +15 -0
  175. package/src/internal/command-reporter.js +133 -0
  176. package/src/internal/command-request.d.ts +35 -0
  177. package/src/internal/command-request.js +154 -0
  178. package/src/internal/node-http.js +54 -0
  179. package/src/internal/project-context.d.ts +66 -0
  180. package/src/internal/project-context.js +175 -0
  181. package/src/project-config-reference.js +4 -0
  182. package/src/project-config-schema.d.ts +23 -0
  183. package/src/project-config-schema.js +271 -0
  184. package/src/project-config.js +724 -0
  185. package/src/project-execution.js +2930 -0
  186. package/src/provider-drivers.js +3 -0
  187. package/src/target-support.js +3 -0
  188. package/src/typescript-module-loader.js +269 -0
  189. package/src/workflow.js +78 -0
  190. package/src/workspace.js +82 -0
@@ -0,0 +1,918 @@
1
+ {
2
+ "schemaVersion": "pulse.project-config-schema-bundle.v1",
3
+ "releaseVersion": "1.0.0-beta.1",
4
+ "project": {
5
+ "schemaVersion": "pulse.project-config-schema.v1",
6
+ "discovery": [
7
+ ".pulse/config.ts"
8
+ ],
9
+ "precedence": [
10
+ "Discovery starts at the positional directory or the current working directory and searches upward for .pulse/config.ts.",
11
+ "Profile precedence is --profile, PULSE_PROFILE, then pulse.defaultProfile.",
12
+ "A selected-profile crypto declaration replaces pulse.crypto completely; array and object forms never merge.",
13
+ "Command-line output, host, port, and watch values override the corresponding active-profile field for that command. Entry, provider, and target remain project-configured.",
14
+ "Dedicated harness case inputs replace development inputs for that case; they do not configure deployment resources.",
15
+ "Provider deployment bindings come from the configured provider object; handler source never receives provider SDK objects."
16
+ ],
17
+ "sections": [
18
+ {
19
+ "id": "project",
20
+ "title": "Project and provider selection",
21
+ "description": "Select the canonical entry, provider, and build output."
22
+ },
23
+ {
24
+ "id": "crypto",
25
+ "title": "Cryptographic requirements",
26
+ "description": "Declare exact algorithms for the global or selected profile and resolve one target realization without fallback. This surface is part of the synchronized 1.0.0-beta.1 package set."
27
+ },
28
+ {
29
+ "id": "schemas",
30
+ "title": "JSON schema policy",
31
+ "description": "Configure bounded schema-body policy. Conventional projects declare registry identity only through pulse.schema."
32
+ },
33
+ {
34
+ "id": "dev",
35
+ "title": "Local development",
36
+ "description": "Configure the foreground local server and local-only provider inputs."
37
+ },
38
+ {
39
+ "description": "Options passed to fastly(...) from @pulse-compute/provider-fastly.",
40
+ "id": "fastly",
41
+ "title": "Fastly provider options"
42
+ }
43
+ ],
44
+ "fields": [
45
+ {
46
+ "required": false,
47
+ "default": "`./src/index.ts`",
48
+ "allowed": "—",
49
+ "precedence": "`pulse.entry` in `.pulse/config.ts`.",
50
+ "security": "Must resolve to an existing file.",
51
+ "diagnostics": [
52
+ "PULSE_ENTRY_NOT_FOUND"
53
+ ],
54
+ "section": "project",
55
+ "path": "entry",
56
+ "type": "string",
57
+ "scope": "all project commands",
58
+ "description": "Project-relative TypeScript handler entry."
59
+ },
60
+ {
61
+ "required": false,
62
+ "default": "`node`",
63
+ "allowed": "`node`, `fastly`, `none`, another bare host id, or an exact scoped package name",
64
+ "precedence": "Bare host ids resolve to `@pulse-compute/provider-<id>`; scoped package names are loaded exactly from the project.",
65
+ "security": "Package loading is explicit and limited to the selected package `./toolchain` export; there is no scanning or fallback discovery.",
66
+ "diagnostics": [
67
+ "PULSE_PROVIDER_PACKAGE_NOT_FOUND",
68
+ "PULSE_PROVIDER_TOOLCHAIN_LOAD_FAILED",
69
+ "PULSE_PROVIDER_TOOLCHAIN_INVALID",
70
+ "PULSE_PROVIDER_UNSUPPORTED",
71
+ "PULSE_PROVIDER_COMPILE_ONLY",
72
+ "PULSE_TEST_PROVIDER_REQUIRED",
73
+ "PULSE_DEV_PROVIDER_UNSUPPORTED"
74
+ ],
75
+ "section": "project",
76
+ "path": "provider",
77
+ "type": "'node' | 'fastly' | 'none' | scoped package name | provider configuration",
78
+ "scope": "compile/build/dev/test",
79
+ "description": "Selects provider validation, local conformance, and build realization through the provider package toolchain contract."
80
+ },
81
+ {
82
+ "required": false,
83
+ "default": "`./dist`",
84
+ "allowed": "—",
85
+ "precedence": "`--out` overrides this field for the current command.",
86
+ "security": "Must remain a real child of the project root; absolute, parent-traversal, and symbolic-link traversal outside the project root is rejected.",
87
+ "diagnostics": [
88
+ "PULSE_BUILD_OUT_UNSAFE"
89
+ ],
90
+ "section": "project",
91
+ "path": "outDir",
92
+ "type": "string",
93
+ "scope": "compile/build",
94
+ "description": "Project-relative artifact output directory."
95
+ },
96
+ {
97
+ "required": false,
98
+ "default": "`info`",
99
+ "allowed": "`off`, `error`, `warn`, `info`, `debug`",
100
+ "precedence": "Selected-profile `reporting`, then `pulse.reporting`, then `info`.",
101
+ "security": "Known request-owned secret values are redacted before provider emission.",
102
+ "diagnostics": [
103
+ "PULSE_REPORTING_LEVEL_UNSUPPORTED"
104
+ ],
105
+ "section": "project",
106
+ "path": "reporting",
107
+ "type": "'off' | 'error' | 'warn' | 'info' | 'debug'",
108
+ "scope": "compile/build/dev/test",
109
+ "description": "Resolved synchronous logging threshold after the flat profile override is applied."
110
+ },
111
+ {
112
+ "required": false,
113
+ "default": "implicit no-crypto declaration",
114
+ "allowed": "`HS256`, `ES256`; exact pins `runtime-builtin`, `guest-source:pulse-hmac-as`, and `guest-linked:pulse-es256-rustcrypto-p256`",
115
+ "precedence": "Used only when the selected profile omits `crypto`.",
116
+ "security": "Keys and verification bytes are not configuration values. Target selection is deterministic and never probes or falls back.",
117
+ "diagnostics": [
118
+ "PULSE_CRYPTO_CONFIG_SHAPE_INVALID",
119
+ "PULSE_CRYPTO_ALGORITHM_DUPLICATE",
120
+ "PULSE_CRYPTO_ALGORITHM_UNKNOWN",
121
+ "PULSE_CRYPTO_REALIZATION_UNKNOWN"
122
+ ],
123
+ "section": "crypto",
124
+ "path": "pulse.crypto",
125
+ "type": "readonly ('HS256' | 'ES256')[] | { readonly HS256?: { readonly realization?: PulseCryptoRealization }; readonly ES256?: { readonly realization?: PulseCryptoRealization } }",
126
+ "scope": "global crypto requirement default",
127
+ "description": "Declares the complete global algorithm set. Array entries are canonical algorithm names; object entries may pin one exact known realization."
128
+ },
129
+ {
130
+ "required": false,
131
+ "default": "inherit `pulse.crypto` when absent",
132
+ "allowed": "`[]` and `{}` explicitly select no crypto; otherwise `HS256` and/or `ES256`",
133
+ "precedence": "Selected-profile declaration replaces `pulse.crypto`; absence inherits it.",
134
+ "security": "Every declared algorithm must resolve for the selected target before lowering. A failed exact realization cannot select another backend.",
135
+ "diagnostics": [
136
+ "PULSE_CRYPTO_CONFIG_REQUIRED",
137
+ "PULSE_CRYPTO_REALIZATION_PIN_INVALID",
138
+ "PULSE_CRYPTO_REALIZATION_UNAVAILABLE"
139
+ ],
140
+ "section": "crypto",
141
+ "path": "<profile>.crypto",
142
+ "type": "readonly ('HS256' | 'ES256')[] | { readonly HS256?: { readonly realization?: PulseCryptoRealization }; readonly ES256?: { readonly realization?: PulseCryptoRealization } }",
143
+ "scope": "selected profile",
144
+ "description": "Replaces the complete global crypto declaration for the selected profile. Arrays and objects never merge with `pulse.crypto`."
145
+ },
146
+ {
147
+ "required": false,
148
+ "default": "`{}`",
149
+ "allowed": "—",
150
+ "precedence": "Configuration value.",
151
+ "security": "Structured bodies are bounded before decoding.",
152
+ "diagnostics": [
153
+ "PULSE_SCHEMA_COMPILE_FAILED"
154
+ ],
155
+ "section": "schemas",
156
+ "path": "schemas",
157
+ "type": "PulseSchemaConfig",
158
+ "scope": "compile/dev/test/build",
159
+ "description": "Sets schema body limits and content-type policy. Schema identities come from the module selected by pulse.schema."
160
+ },
161
+ {
162
+ "required": false,
163
+ "default": "`accept-json-or-missing`",
164
+ "allowed": "`accept-json-or-missing`, `require-json`",
165
+ "precedence": "Configuration value.",
166
+ "security": "No special handling.",
167
+ "diagnostics": [
168
+ "PULSE_SCHEMA_CONTENT_TYPE_POLICY_INVALID",
169
+ "PULSE_SCHEMA_DECODE"
170
+ ],
171
+ "section": "schemas",
172
+ "path": "schemas.contentTypePolicy",
173
+ "type": "'accept-json-or-missing' | 'require-json'",
174
+ "scope": "request and fetched-body schema decode",
175
+ "description": "Controls whether a JSON content type is mandatory."
176
+ },
177
+ {
178
+ "required": false,
179
+ "default": "`65_536`",
180
+ "allowed": "—",
181
+ "precedence": "Configuration value.",
182
+ "security": "Raise deliberately; this is a memory and request-amplification boundary.",
183
+ "diagnostics": [
184
+ "PULSE_SCHEMA_BODY_LIMIT_INVALID",
185
+ "PULSE_BODY_TOO_LARGE"
186
+ ],
187
+ "section": "schemas",
188
+ "path": "schemas.maxBytes",
189
+ "type": "positive safe integer",
190
+ "scope": "structured schema decode",
191
+ "description": "Maximum buffered bytes accepted by schema decoding."
192
+ },
193
+ {
194
+ "required": false,
195
+ "default": "`{}`",
196
+ "allowed": "—",
197
+ "precedence": "Configuration value.",
198
+ "security": "No special handling.",
199
+ "diagnostics": [],
200
+ "section": "dev",
201
+ "path": "dev",
202
+ "type": "object",
203
+ "scope": "pulse dev and local conformance",
204
+ "description": "Development listener and local fixture inputs."
205
+ },
206
+ {
207
+ "required": false,
208
+ "default": "`127.0.0.1`",
209
+ "allowed": "—",
210
+ "precedence": "`--host` overrides this field.",
211
+ "security": "Binding a non-loopback address exposes the local development server.",
212
+ "diagnostics": [
213
+ "PULSE_DEV_HOST_INVALID"
214
+ ],
215
+ "section": "dev",
216
+ "path": "dev.host",
217
+ "type": "string",
218
+ "scope": "pulse dev",
219
+ "description": "Listener host."
220
+ },
221
+ {
222
+ "required": false,
223
+ "default": "`8787`",
224
+ "allowed": "`0`–`65535`; `0` requests an ephemeral port",
225
+ "precedence": "`--port` overrides this field.",
226
+ "security": "No special handling.",
227
+ "diagnostics": [
228
+ "PULSE_DEV_PORT_INVALID"
229
+ ],
230
+ "section": "dev",
231
+ "path": "dev.port",
232
+ "type": "integer",
233
+ "scope": "pulse dev",
234
+ "description": "Listener port."
235
+ },
236
+ {
237
+ "required": false,
238
+ "default": "`true`",
239
+ "allowed": "—",
240
+ "precedence": "`--watch` or `--no-watch` overrides this field.",
241
+ "security": "Configuration-file changes still require a restart.",
242
+ "diagnostics": [],
243
+ "section": "dev",
244
+ "path": "dev.watch",
245
+ "type": "boolean",
246
+ "scope": "pulse dev",
247
+ "description": "Watches the entry and schema dependency graph."
248
+ },
249
+ {
250
+ "required": false,
251
+ "default": "`65_536`",
252
+ "allowed": "—",
253
+ "precedence": "Configuration value.",
254
+ "security": "Raise deliberately; this is a memory and request-amplification boundary.",
255
+ "diagnostics": [
256
+ "PULSE_DEV_BODY_LIMIT_INVALID",
257
+ "PULSE_REQUEST_BODY_TOO_LARGE"
258
+ ],
259
+ "section": "dev",
260
+ "path": "dev.maxBodyBytes",
261
+ "type": "positive safe integer",
262
+ "scope": "incoming local requests",
263
+ "description": "Maximum request body accepted by the local development server."
264
+ },
265
+ {
266
+ "required": false,
267
+ "default": "selected provider default",
268
+ "allowed": "—",
269
+ "precedence": "This explicit field overrides the selected provider local default.",
270
+ "security": "Keep disabled for deterministic or untrusted test inputs.",
271
+ "diagnostics": [
272
+ "PULSE_FETCH_IMPLEMENTATION_UNAVAILABLE",
273
+ "PULSE_FETCH_NETWORK"
274
+ ],
275
+ "section": "dev",
276
+ "path": "dev.networkFetch",
277
+ "type": "boolean",
278
+ "scope": "local fetch realization",
279
+ "description": "Allows unmatched local fetches to use the network."
280
+ },
281
+ {
282
+ "required": false,
283
+ "default": "`{}`",
284
+ "allowed": "—",
285
+ "precedence": "Configuration value.",
286
+ "security": "Development input only; it does not configure deployed provider stores.",
287
+ "diagnostics": [],
288
+ "section": "dev",
289
+ "path": "dev.config",
290
+ "type": "Readonly<Record<string, string>>",
291
+ "scope": "local config capability",
292
+ "description": "Local configuration-store values."
293
+ },
294
+ {
295
+ "required": false,
296
+ "default": "`{}`",
297
+ "allowed": "—",
298
+ "precedence": "Configuration value.",
299
+ "security": "Raw values are omitted from project JSON, diagnostics, and runtime error details; do not commit real production secrets.",
300
+ "diagnostics": [],
301
+ "section": "dev",
302
+ "path": "dev.secrets",
303
+ "type": "Readonly<Record<string, string>>",
304
+ "scope": "local secret capability",
305
+ "description": "Local secret-store values."
306
+ },
307
+ {
308
+ "required": false,
309
+ "default": "`{}`",
310
+ "allowed": "—",
311
+ "precedence": "Configuration value.",
312
+ "security": "Development input only; it is not deployed.",
313
+ "diagnostics": [],
314
+ "section": "dev",
315
+ "path": "dev.kv",
316
+ "type": "Readonly<Record<string, Readonly<Record<string, unknown>>>>",
317
+ "scope": "local KV capability",
318
+ "description": "Local KV stores keyed by configured logical store name."
319
+ },
320
+ {
321
+ "required": false,
322
+ "default": "`{}`",
323
+ "allowed": "—",
324
+ "precedence": "Configuration value.",
325
+ "security": "Prefer fixtures for deterministic tests and offline development.",
326
+ "diagnostics": [],
327
+ "section": "dev",
328
+ "path": "dev.fetches",
329
+ "type": "Readonly<Record<string, unknown>>",
330
+ "scope": "local fetch capability",
331
+ "description": "Deterministic fetch fixtures resolved before optional live network fetch."
332
+ },
333
+ {
334
+ "required": false,
335
+ "default": "`pulse_config`",
336
+ "allowed": "—",
337
+ "precedence": "Configuration value.",
338
+ "security": "No special handling.",
339
+ "diagnostics": [],
340
+ "description": "Fastly Config Store resource name.",
341
+ "path": "fastly.configStore",
342
+ "scope": "Fastly config capability",
343
+ "section": "fastly",
344
+ "type": "string"
345
+ },
346
+ {
347
+ "required": false,
348
+ "default": "`pulse_secrets`",
349
+ "allowed": "—",
350
+ "precedence": "Configuration value.",
351
+ "security": "The name is build metadata; secret values are never embedded by this option.",
352
+ "diagnostics": [],
353
+ "description": "Fastly Secret Store resource name.",
354
+ "path": "fastly.secretStore",
355
+ "scope": "Fastly secret capability",
356
+ "section": "fastly",
357
+ "type": "string"
358
+ },
359
+ {
360
+ "required": false,
361
+ "default": "`{}`",
362
+ "allowed": "—",
363
+ "precedence": "Configuration value.",
364
+ "security": "No special handling.",
365
+ "diagnostics": [
366
+ "PULSE_FASTLY_KV_BINDINGS_INVALID"
367
+ ],
368
+ "description": "Maps logical ctx.kv names to Fastly KV Store resource names.",
369
+ "path": "fastly.kv",
370
+ "scope": "Fastly KV capability",
371
+ "section": "fastly",
372
+ "type": "Readonly<Record<string, string>>"
373
+ },
374
+ {
375
+ "required": false,
376
+ "default": "`{}`",
377
+ "allowed": "—",
378
+ "precedence": "Configuration value.",
379
+ "security": "Prefer explicit backends over dynamic origin authority.",
380
+ "diagnostics": [
381
+ "PULSE_FASTLY_BACKEND_BINDINGS_INVALID",
382
+ "PULSE_FASTLY_BACKEND_REQUIRED"
383
+ ],
384
+ "description": "Maps static absolute origin URLs to named Fastly backends.",
385
+ "path": "fastly.backends",
386
+ "scope": "Fastly fetch capability",
387
+ "section": "fastly",
388
+ "type": "Readonly<Record<string, string>>"
389
+ },
390
+ {
391
+ "required": false,
392
+ "default": "`false`",
393
+ "allowed": "—",
394
+ "precedence": "Configuration value.",
395
+ "security": "Opt in deliberately because it broadens outbound authority.",
396
+ "diagnostics": [
397
+ "PULSE_FASTLY_BACKEND_REQUIRED"
398
+ ],
399
+ "description": "Allows undeclared outbound origins to use dynamic backends.",
400
+ "path": "fastly.dynamicBackends",
401
+ "scope": "Fastly fetch capability",
402
+ "section": "fastly",
403
+ "type": "boolean"
404
+ },
405
+ {
406
+ "required": false,
407
+ "default": "omitted",
408
+ "allowed": "—",
409
+ "precedence": "Configuration value.",
410
+ "security": "No special handling.",
411
+ "diagnostics": [],
412
+ "description": "Provider-owned bindings used by package-owned GRIP compatibility and canonical broadcast effects.",
413
+ "path": "fastly.grip",
414
+ "scope": "Fastly GRIP capability",
415
+ "section": "fastly",
416
+ "type": "object"
417
+ },
418
+ {
419
+ "required": false,
420
+ "default": "omitted",
421
+ "allowed": "—",
422
+ "precedence": "Configuration value.",
423
+ "security": "No special handling.",
424
+ "diagnostics": [
425
+ "PULSE_FASTLY_GRIP_FANOUT_BACKEND_REQUIRED"
426
+ ],
427
+ "description": "Named Fastly Fanout backend.",
428
+ "path": "fastly.grip.fanoutBackend",
429
+ "scope": "GRIP hold",
430
+ "section": "fastly",
431
+ "type": "string"
432
+ },
433
+ {
434
+ "required": false,
435
+ "default": "omitted",
436
+ "allowed": "—",
437
+ "precedence": "Configuration value.",
438
+ "security": "No special handling.",
439
+ "diagnostics": [
440
+ "PULSE_FASTLY_GRIP_PUBLISH_BINDING_REQUIRED"
441
+ ],
442
+ "description": "Provider-owned absolute publish/control endpoint; distinct from public gateway and ingress URLs.",
443
+ "path": "fastly.grip.publishEndpoint",
444
+ "scope": "GRIP broadcast",
445
+ "section": "fastly",
446
+ "type": "string"
447
+ },
448
+ {
449
+ "required": false,
450
+ "default": "omitted",
451
+ "allowed": "—",
452
+ "precedence": "Configuration value.",
453
+ "security": "No special handling.",
454
+ "diagnostics": [
455
+ "PULSE_FASTLY_GRIP_PUBLISH_BINDING_REQUIRED"
456
+ ],
457
+ "description": "Absolute publish endpoint URL.",
458
+ "path": "fastly.grip.publishUrl",
459
+ "scope": "GRIP publish",
460
+ "section": "fastly",
461
+ "type": "string"
462
+ },
463
+ {
464
+ "required": false,
465
+ "default": "omitted",
466
+ "allowed": "—",
467
+ "precedence": "Configuration value.",
468
+ "security": "No special handling.",
469
+ "diagnostics": [
470
+ "PULSE_FASTLY_GRIP_PUBLISH_BINDING_REQUIRED"
471
+ ],
472
+ "description": "Named backend for the provider publish endpoint.",
473
+ "path": "fastly.grip.publishBackend",
474
+ "scope": "GRIP broadcast/publish",
475
+ "section": "fastly",
476
+ "type": "string"
477
+ },
478
+ {
479
+ "required": false,
480
+ "default": "omitted",
481
+ "allowed": "—",
482
+ "precedence": "Configuration value.",
483
+ "security": "Store the value in Fastly Secret Store and configure only secretRef.",
484
+ "diagnostics": [],
485
+ "description": "Authentication metadata containing references only; no credential value is accepted here.",
486
+ "path": "fastly.grip.authentication",
487
+ "scope": "GRIP broadcast authentication",
488
+ "section": "fastly",
489
+ "type": "object"
490
+ },
491
+ {
492
+ "required": false,
493
+ "default": "`bearer`",
494
+ "allowed": "—",
495
+ "precedence": "Configuration value.",
496
+ "security": "No special handling.",
497
+ "diagnostics": [
498
+ "PULSE_FASTLY_NATIVE_GRIP_AUTH_SCHEME_UNSUPPORTED"
499
+ ],
500
+ "description": "Provider authentication scheme.",
501
+ "path": "fastly.grip.authentication.scheme",
502
+ "scope": "GRIP broadcast authentication",
503
+ "section": "fastly",
504
+ "type": "'bearer'"
505
+ },
506
+ {
507
+ "required": false,
508
+ "default": "omitted",
509
+ "allowed": "—",
510
+ "precedence": "Configuration value.",
511
+ "security": "The secret value is resolved only at request execution and is redacted from traces.",
512
+ "diagnostics": [
513
+ "PULSE_FASTLY_NATIVE_GRIP_SECRET_REFERENCE_MISSING"
514
+ ],
515
+ "description": "Named Fastly Secret Store key used for the bearer token.",
516
+ "path": "fastly.grip.authentication.secretRef",
517
+ "scope": "GRIP broadcast authentication",
518
+ "section": "fastly",
519
+ "type": "string"
520
+ },
521
+ {
522
+ "required": false,
523
+ "default": "`true`",
524
+ "allowed": "—",
525
+ "precedence": "Configuration value.",
526
+ "security": "No special handling.",
527
+ "diagnostics": [],
528
+ "description": "Enables the direct host-owned hold response realization.",
529
+ "path": "fastly.grip.directHold",
530
+ "scope": "GRIP hold",
531
+ "section": "fastly",
532
+ "type": "boolean"
533
+ },
534
+ {
535
+ "required": false,
536
+ "default": "`pulse-app`",
537
+ "allowed": "—",
538
+ "precedence": "Configuration value.",
539
+ "security": "No special handling.",
540
+ "diagnostics": [],
541
+ "description": "Generated Fastly package name.",
542
+ "path": "fastly.name",
543
+ "scope": "Fastly package metadata",
544
+ "section": "fastly",
545
+ "type": "string"
546
+ },
547
+ {
548
+ "required": false,
549
+ "default": "`Pulse application`",
550
+ "allowed": "—",
551
+ "precedence": "Configuration value.",
552
+ "security": "No special handling.",
553
+ "diagnostics": [],
554
+ "description": "Generated Fastly package description.",
555
+ "path": "fastly.description",
556
+ "scope": "Fastly package metadata",
557
+ "section": "fastly",
558
+ "type": "string"
559
+ },
560
+ {
561
+ "required": false,
562
+ "default": "`[]`",
563
+ "allowed": "—",
564
+ "precedence": "Configuration value.",
565
+ "security": "No special handling.",
566
+ "diagnostics": [],
567
+ "description": "Generated Fastly package authors.",
568
+ "path": "fastly.authors",
569
+ "scope": "Fastly package metadata",
570
+ "section": "fastly",
571
+ "type": "readonly string[]"
572
+ },
573
+ {
574
+ "required": false,
575
+ "default": "`{}`",
576
+ "allowed": "—",
577
+ "precedence": "Configuration value.",
578
+ "security": "No special handling.",
579
+ "diagnostics": [],
580
+ "description": "Local-only behavior; it does not alter the deployed target.",
581
+ "path": "fastly.local",
582
+ "scope": "local Fastly conformance",
583
+ "section": "fastly",
584
+ "type": "object"
585
+ },
586
+ {
587
+ "required": false,
588
+ "default": "`false`",
589
+ "allowed": "—",
590
+ "precedence": "`dev.networkFetch` overrides this value when explicitly set.",
591
+ "security": "Keep disabled for deterministic tests and offline development.",
592
+ "diagnostics": [],
593
+ "description": "Allows unmatched local Fastly fetches to use the network.",
594
+ "path": "fastly.local.networkFetch",
595
+ "scope": "local Fastly fetch realization",
596
+ "section": "fastly",
597
+ "type": "boolean"
598
+ }
599
+ ],
600
+ "runtimeRules": {
601
+ "entry": {
602
+ "kind": "string",
603
+ "default": "./src/index.ts",
604
+ "nonEmpty": true
605
+ },
606
+ "provider": {
607
+ "kind": "provider-package",
608
+ "default": "node",
609
+ "builtinValues": [
610
+ "node",
611
+ "fastly",
612
+ "none"
613
+ ]
614
+ },
615
+ "outDir": {
616
+ "kind": "string",
617
+ "default": "./dist",
618
+ "nonEmpty": true
619
+ },
620
+ "reporting": {
621
+ "kind": "enum",
622
+ "default": "info",
623
+ "values": [
624
+ "off",
625
+ "error",
626
+ "warn",
627
+ "info",
628
+ "debug"
629
+ ]
630
+ },
631
+ "crypto": {
632
+ "kind": "crypto-configuration",
633
+ "optional": true
634
+ },
635
+ "schemas.contentTypePolicy": {
636
+ "kind": "enum",
637
+ "default": "accept-json-or-missing",
638
+ "values": [
639
+ "accept-json-or-missing",
640
+ "require-json"
641
+ ]
642
+ },
643
+ "schemas.maxBytes": {
644
+ "kind": "positive-safe-integer",
645
+ "default": 65536
646
+ },
647
+ "dev.host": {
648
+ "kind": "string",
649
+ "default": "127.0.0.1",
650
+ "nonEmpty": true
651
+ },
652
+ "dev.port": {
653
+ "kind": "integer",
654
+ "default": 8787,
655
+ "minimum": 0,
656
+ "maximum": 65535
657
+ },
658
+ "dev.watch": {
659
+ "kind": "boolean",
660
+ "default": true
661
+ },
662
+ "dev.maxBodyBytes": {
663
+ "kind": "positive-safe-integer",
664
+ "default": 65536
665
+ },
666
+ "harness.maxBodyBytes": {
667
+ "kind": "positive-safe-integer",
668
+ "optional": true
669
+ },
670
+ "harness.continuationTtlMs": {
671
+ "kind": "non-negative-safe-integer",
672
+ "optional": true
673
+ }
674
+ },
675
+ "jsonSchema": {
676
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
677
+ "$id": "urn:pulse:project-config:v1",
678
+ "title": "Pulse project configuration",
679
+ "type": "object",
680
+ "additionalProperties": false,
681
+ "properties": {
682
+ "entry": {
683
+ "type": "string",
684
+ "minLength": 1,
685
+ "default": "./src/index.ts"
686
+ },
687
+ "provider": {
688
+ "oneOf": [
689
+ {
690
+ "type": "string",
691
+ "minLength": 1
692
+ },
693
+ {
694
+ "type": "object",
695
+ "required": [
696
+ "kind"
697
+ ],
698
+ "properties": {
699
+ "kind": {
700
+ "type": "string",
701
+ "minLength": 1
702
+ }
703
+ },
704
+ "additionalProperties": true
705
+ }
706
+ ],
707
+ "default": "node"
708
+ },
709
+ "outDir": {
710
+ "type": "string",
711
+ "minLength": 1,
712
+ "default": "./dist"
713
+ },
714
+ "reporting": {
715
+ "enum": [
716
+ "off",
717
+ "error",
718
+ "warn",
719
+ "info",
720
+ "debug"
721
+ ],
722
+ "default": "info"
723
+ },
724
+ "crypto": {
725
+ "oneOf": [
726
+ {
727
+ "type": "array",
728
+ "uniqueItems": true,
729
+ "items": {
730
+ "enum": [
731
+ "HS256",
732
+ "ES256"
733
+ ]
734
+ }
735
+ },
736
+ {
737
+ "type": "object",
738
+ "additionalProperties": false,
739
+ "properties": {
740
+ "HS256": {
741
+ "type": "object",
742
+ "additionalProperties": false,
743
+ "properties": {
744
+ "realization": {
745
+ "enum": [
746
+ "runtime-builtin",
747
+ "guest-source:pulse-hmac-as",
748
+ "guest-linked:pulse-es256-rustcrypto-p256"
749
+ ]
750
+ }
751
+ }
752
+ },
753
+ "ES256": {
754
+ "type": "object",
755
+ "additionalProperties": false,
756
+ "properties": {
757
+ "realization": {
758
+ "enum": [
759
+ "runtime-builtin",
760
+ "guest-source:pulse-hmac-as",
761
+ "guest-linked:pulse-es256-rustcrypto-p256"
762
+ ]
763
+ }
764
+ }
765
+ }
766
+ }
767
+ }
768
+ ]
769
+ },
770
+ "schemas": {
771
+ "type": "object",
772
+ "additionalProperties": false,
773
+ "properties": {
774
+ "contentTypePolicy": {
775
+ "enum": [
776
+ "accept-json-or-missing",
777
+ "require-json"
778
+ ],
779
+ "default": "accept-json-or-missing"
780
+ },
781
+ "maxBytes": {
782
+ "type": "integer",
783
+ "minimum": 1,
784
+ "maximum": 9007199254740991,
785
+ "default": 65536
786
+ }
787
+ }
788
+ },
789
+ "dev": {
790
+ "type": "object",
791
+ "additionalProperties": false,
792
+ "properties": {
793
+ "host": {
794
+ "type": "string",
795
+ "minLength": 1,
796
+ "default": "127.0.0.1"
797
+ },
798
+ "port": {
799
+ "type": "integer",
800
+ "minimum": 0,
801
+ "maximum": 65535,
802
+ "default": 8787
803
+ },
804
+ "watch": {
805
+ "type": "boolean",
806
+ "default": true
807
+ },
808
+ "maxBodyBytes": {
809
+ "type": "integer",
810
+ "minimum": 1,
811
+ "maximum": 9007199254740991,
812
+ "default": 65536
813
+ },
814
+ "networkFetch": {
815
+ "type": "boolean"
816
+ },
817
+ "config": {
818
+ "type": "object",
819
+ "additionalProperties": {
820
+ "type": "string"
821
+ }
822
+ },
823
+ "secrets": {
824
+ "type": "object",
825
+ "additionalProperties": {
826
+ "type": "string"
827
+ }
828
+ },
829
+ "kv": {
830
+ "type": "object",
831
+ "additionalProperties": {
832
+ "type": "object"
833
+ }
834
+ },
835
+ "fetches": {
836
+ "type": "object"
837
+ }
838
+ }
839
+ }
840
+ }
841
+ }
842
+ },
843
+ "providers": {
844
+ "fastly": {
845
+ "schemaVersion": "pulse.provider-fastly-config-schema.v1",
846
+ "fields": {
847
+ "fastly.configStore": {
848
+ "kind": "string",
849
+ "default": "pulse_config"
850
+ },
851
+ "fastly.secretStore": {
852
+ "kind": "string",
853
+ "default": "pulse_secrets"
854
+ },
855
+ "fastly.kv": {
856
+ "kind": "string-map",
857
+ "default": {}
858
+ },
859
+ "fastly.backends": {
860
+ "kind": "string-map",
861
+ "default": {}
862
+ },
863
+ "fastly.dynamicBackends": {
864
+ "kind": "boolean",
865
+ "default": false
866
+ },
867
+ "fastly.grip": {
868
+ "kind": "object"
869
+ },
870
+ "fastly.grip.fanoutBackend": {
871
+ "kind": "optional-string"
872
+ },
873
+ "fastly.grip.publishEndpoint": {
874
+ "kind": "optional-string"
875
+ },
876
+ "fastly.grip.publishUrl": {
877
+ "kind": "optional-string"
878
+ },
879
+ "fastly.grip.publishBackend": {
880
+ "kind": "optional-string"
881
+ },
882
+ "fastly.grip.authentication": {
883
+ "kind": "object"
884
+ },
885
+ "fastly.grip.authentication.scheme": {
886
+ "kind": "optional-string"
887
+ },
888
+ "fastly.grip.authentication.secretRef": {
889
+ "kind": "optional-string"
890
+ },
891
+ "fastly.grip.directHold": {
892
+ "kind": "boolean",
893
+ "default": true
894
+ },
895
+ "fastly.name": {
896
+ "kind": "string",
897
+ "default": "pulse-app"
898
+ },
899
+ "fastly.description": {
900
+ "kind": "string",
901
+ "default": "Pulse application"
902
+ },
903
+ "fastly.authors": {
904
+ "kind": "string-array",
905
+ "default": []
906
+ },
907
+ "fastly.local": {
908
+ "kind": "object",
909
+ "default": {}
910
+ },
911
+ "fastly.local.networkFetch": {
912
+ "kind": "boolean",
913
+ "default": false
914
+ }
915
+ }
916
+ }
917
+ }
918
+ }