@pulse-compute/cli 1.0.0-beta.1 → 1.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +37 -4
- package/CHANGELOG.md +30 -0
- package/README.md +4 -3
- package/cli-spec.json +1 -1
- package/docs/README.md +1 -1
- package/docs/architecture/current-contracts.md +108 -7
- package/docs/concepts/compilation-and-lowering.md +1 -1
- package/docs/concepts/contracts-and-providers.md +2 -2
- package/docs/concepts/effects-and-continuations.md +57 -0
- package/docs/concepts/package-owned-lowering.md +1 -1
- package/docs/concepts/targets-and-hosts.md +10 -2
- package/docs/contributing/adding-core-provider.md +1 -1
- package/docs/contributing/adding-first-party-lowerer.md +1 -1
- package/docs/contributing/package-lowerer-contract.md +2 -2
- package/docs/guides/migrating-from-express.md +3 -3
- package/docs/guides/routing.md +19 -1
- package/docs/maintainers/documentation-deployment.md +4 -4
- package/docs/maintainers/documentation-versioning.md +1 -1
- package/docs/maintainers/maintainer-charter.md +17 -1
- package/docs/maintainers/maintenance-policy.json +34 -3
- package/docs/maintainers/maintenance-policy.md +3 -3
- package/docs/maintainers/npm-publishing.md +34 -6
- package/docs/maintainers/plugin-readiness.json +1 -1
- package/docs/maintainers/plugin-readiness.md +1 -1
- package/docs/maintainers/release-acceptance.md +51 -8
- package/docs/maintainers/release-manifest.md +23 -22
- package/docs/maintainers/scope-policy.md +13 -1
- package/docs/maintainers/testing.md +47 -1
- package/docs/packages/README.md +25 -24
- package/docs/packages/assets.md +1 -1
- package/docs/packages/crypto.md +8 -1
- package/docs/packages/entities.md +1 -1
- package/docs/packages/grip.md +1 -1
- package/docs/packages/implementation-packages.md +10 -1
- package/docs/packages/jwt.md +1 -1
- package/docs/packages/provider-fastly.md +29 -3
- package/docs/packages/pulse.md +1 -1
- package/docs/packages/runtime.md +10 -1
- package/docs/packages/s3.md +101 -0
- package/docs/preview-scope.md +2 -2
- package/docs/reference/cli-spec.json +1 -1
- package/docs/reference/cli.md +1 -1
- package/docs/reference/compatibility-matrix.md +2 -2
- package/docs/reference/diagnostics.md +5 -5
- package/docs/reference/documentation-versions.json +19 -3
- package/docs/reference/handler-authoring.md +1 -1
- package/docs/reference/project-config.md +33 -5
- package/docs/reference/project-config.schema.json +70 -7
- package/docs/reference/release-manifest.json +37 -23
- package/documentation-site.json +8 -1
- package/documentation-versions.json +19 -3
- package/examples/01-hello-json/README.md +1 -1
- package/examples/01-hello-json/package.json +2 -2
- package/examples/02-request-schema/README.md +1 -1
- package/examples/02-request-schema/package.json +2 -2
- package/examples/03-fetch-composition/README.md +1 -1
- package/examples/03-fetch-composition/package.json +2 -2
- package/examples/05-fastly-capabilities/README.md +2 -2
- package/examples/05-fastly-capabilities/package.json +4 -4
- package/examples/07-opaque-proxy/README.md +2 -2
- package/examples/07-opaque-proxy/package.json +3 -3
- package/examples/09-router-lowering/README.md +1 -1
- package/examples/09-router-lowering/package.json +3 -3
- package/examples/10-entities-tools/package.json +3 -3
- package/examples/11-events/README.md +1 -1
- package/examples/11-events/package.json +2 -2
- package/examples/12-mcp-proxy/README.md +1 -1
- package/examples/12-mcp-proxy/package.json +2 -2
- package/examples/13-jwt-es256/README.md +1 -1
- package/examples/13-jwt-es256/package.json +3 -3
- package/package.json +7 -7
- package/project-config.schema.json +70 -7
- package/release-manifest.json +37 -23
- package/src/documentation.js +1 -1
- package/src/project-config-schema.js +3 -3
- package/src/project-execution.js +64 -30
package/API.md
CHANGED
|
@@ -30,7 +30,7 @@ process, provider SDK, or global network surface behind it.
|
|
|
30
30
|
| [`ctx.emit`](#ctxemit) | HTTP and event handlers | One-way, schema-bound event acceptance effect. |
|
|
31
31
|
| [`ctx.log`](#ctxlog) | HTTP and event handlers | Synchronous thresholded logging. |
|
|
32
32
|
| [`ctx.config`, `ctx.secret`](#config-and-secrets) | HTTP and event handlers | Explicit configured binding reads. |
|
|
33
|
-
| [`ctx.kv(name)`](#kv) | HTTP and event handlers | Bound
|
|
33
|
+
| [`ctx.kv(name)`](#kv) | HTTP and event handlers | Bound reads, writes, and conditional KV effects (Node reference). |
|
|
34
34
|
| [`ctx.json`, `ctx.text`, `ctx.response`](#response-builders) | HTTP handlers and middleware | Synchronous response construction. |
|
|
35
35
|
| `ctx.event` | Event handlers only | Exact event type and immutable validated payload. |
|
|
36
36
|
|
|
@@ -83,7 +83,7 @@ app.mount('/api', api)
|
|
|
83
83
|
export default app
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
`Router` is a compile-time marker. Canonical v2 supports `get`, `head`, `post`, exact paths, named parameters, a trailing wildcard, static mounts, global/path-scoped/mounted middleware, route fallthrough, and error middleware. `ctx.param(name)` returns the matched named parameter inside route handlers.
|
|
86
|
+
`Router` is a compile-time marker. Canonical v2 supports `get`, `head`, `post`, `put`, `patch`, `delete`, exact paths, named parameters, a trailing wildcard, static mounts, global/path-scoped/mounted middleware, route fallthrough, and error middleware. `Pulse` inherits these registrations. `ctx.param(name)` returns the matched named parameter inside route handlers.
|
|
87
87
|
|
|
88
88
|
`next()` is a terminal control transfer. `return next()` advances the normal Router cursor and permanently ends the current handler scope. `return next(error)` enters or advances the error lane. There is no onion-style downstream return or post-`next()` resume. Normal and error exhaustion produce compiler-owned 404 and 500 responses respectively.
|
|
89
89
|
|
|
@@ -400,7 +400,7 @@ const value = await sessions.get('current')
|
|
|
400
400
|
if (value !== undefined) await sessions.put('last', value)
|
|
401
401
|
```
|
|
402
402
|
|
|
403
|
-
The
|
|
403
|
+
The existing `get` and `put` operations remain available. Store names and keys are
|
|
404
404
|
provider-neutral logical bindings. Values are bounded, detached, deeply frozen
|
|
405
405
|
JSON-compatible trees; accessors, symbols, sparse arrays, repeated references,
|
|
406
406
|
cycles, class instances, nonfinite numbers, and nested `undefined` are rejected.
|
|
@@ -408,6 +408,39 @@ cycles, class instances, nonfinite numbers, and nested `undefined` are rejected.
|
|
|
408
408
|
and cross-request lifetime remain provider capabilities rather than properties
|
|
409
409
|
of the common API.
|
|
410
410
|
|
|
411
|
+
The Node reference on JavaScript and Native, and the Fastly Native adapter,
|
|
412
|
+
realize these operations through direct await or keyed `ctx.parallel`:
|
|
413
|
+
|
|
414
|
+
| Method | Result |
|
|
415
|
+
| --- | --- |
|
|
416
|
+
| `getVersioned(key)` | `found` with one observed `value` and opaque `generation`, `not-found`, or `failed` with a reason. |
|
|
417
|
+
| `insertIfAbsent(key, value)` | Atomically creates an absent key. |
|
|
418
|
+
| `compareAndSwap(key, generation, value)` | Atomically replaces the value only when its current generation matches. |
|
|
419
|
+
|
|
420
|
+
Conditional writes return `stored`, `conflict`, `not-stored` with a reason, or
|
|
421
|
+
`unknown` with a reason. `unknown` may have committed; Pulse never automatically
|
|
422
|
+
retries or rebases. A write acknowledgement carries no new generation. An absent
|
|
423
|
+
CAS conflicts. A read may be stale, but its value and token describe the same
|
|
424
|
+
observation. Tokens are bounded opaque strings, never JavaScript numbers or
|
|
425
|
+
application revision counters.
|
|
426
|
+
|
|
427
|
+
Namespaces must be literal bindings; keys, generations, and candidates are runtime
|
|
428
|
+
data. Candidates are snapshotted at admission. Keys are exact Unicode scalar
|
|
429
|
+
strings of 1–1,024 UTF-8 bytes without C0/C1 controls; tokens are 1–256 visible
|
|
430
|
+
ASCII bytes. Values retain the 65,536-byte JSON, depth-64 and 10,000-entry bounds.
|
|
431
|
+
The host owns the ten-second operation deadline, shortened by a request deadline.
|
|
432
|
+
Timeouts before dispatch are `not-stored`; unconfirmed writes after dispatch are
|
|
433
|
+
`unknown`. Request cancellation follows the existing managed lifecycle and
|
|
434
|
+
never implies rollback.
|
|
435
|
+
|
|
436
|
+
The Node realization is an explicit in-memory reference instance, not a durable
|
|
437
|
+
storage guarantee. Fastly Native uses lossless 64-bit generation metadata and
|
|
438
|
+
conditional host operations with bounded readiness and body acquisition. Deployed
|
|
439
|
+
cross-location acceptance remains a separate gate. The Fastly JavaScript SDK is
|
|
440
|
+
incomplete capability mapping and does not define or block
|
|
441
|
+
Pulse's contract. Conditional wire values use the strict
|
|
442
|
+
`{"__pulseKv":1,"value":...}` envelope; legacy raw JSON requires explicit migration.
|
|
443
|
+
|
|
411
444
|
## Explicit JSON schemas
|
|
412
445
|
|
|
413
446
|
<!-- pulse-doc-source: examples/02-request-schema/.pulse/config.ts -->
|
|
@@ -454,7 +487,7 @@ Older `/pulsewasm` imports are compatibility-only and are isolated in the
|
|
|
454
487
|
|
|
455
488
|
## Entities API
|
|
456
489
|
|
|
457
|
-
`@pulse-compute/entities` is part of the synchronized `1.0.0-beta.
|
|
490
|
+
`@pulse-compute/entities` is part of the synchronized `1.0.0-beta.3` package
|
|
458
491
|
set. The application surface has two runtime values:
|
|
459
492
|
|
|
460
493
|
```ts
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
Pulse follows semantic versioning for public releases. The repository begins its public history with the `1.0.0-beta.1` prerelease.
|
|
4
4
|
|
|
5
|
+
## 1.0.0-beta.3 — Beta (2026-09-14)
|
|
6
|
+
|
|
7
|
+
- Fix CLI storage execution on Node Native, Node JavaScript and the Fastly Native local fixture host, including S3 response streams, bindings and conditional KV.
|
|
8
|
+
- Keep the last working Native application available when a development reload fails.
|
|
9
|
+
- Allow bounded npm registry propagation time and publish future releases directly under the `latest` npm tag while retaining the Beta release label.
|
|
10
|
+
|
|
11
|
+
## 1.0.0-beta.2 — Beta (2026-09-13)
|
|
12
|
+
|
|
13
|
+
This candidate synchronizes the 19-package release catalog and prepares the
|
|
14
|
+
next npm `beta` release:
|
|
15
|
+
|
|
16
|
+
- adds bounded S3-compatible object storage in `@pulse-compute/s3`, backed by
|
|
17
|
+
the Crypto hashing and signing primitives; the Assets contract stays intact;
|
|
18
|
+
- adds conditional KV operations and opaque generation tokens, with explicit
|
|
19
|
+
conflict handling and no non-atomic emulation;
|
|
20
|
+
- propagates explicit JavaScript targets through project analysis, retaining
|
|
21
|
+
resolved static third-party imports and ordinary awaited calls while
|
|
22
|
+
checking Native eligibility independently;
|
|
23
|
+
- clarifies maintainer ownership, target boundaries, evidence requirements,
|
|
24
|
+
and human release authority;
|
|
25
|
+
- links public and internal package listings to npm and preserves the exact
|
|
26
|
+
published beta.1 documentation snapshot alongside the beta.2 documentation.
|
|
27
|
+
|
|
28
|
+
Conditional KV acceptance remains gated separately from the aggregate seal:
|
|
29
|
+
Viceroy 0.21.0 creates a missing key for an existing-generation CAS, contrary to
|
|
30
|
+
the required conflict behavior, and deployed Pulse cross-location acceptance
|
|
31
|
+
is still pending. The standalone live Fastly probe confirms missing-key
|
|
32
|
+
rejection but does not satisfy those Pulse acceptance gates. See
|
|
33
|
+
[`wasm/test/kv/K4.md`](https://github.com/pulse-compute/pulse/blob/16444cc5e116498e1fdf5f1e4815b4b8c3c74349/wasm/test/kv/K4.md) for the evidence and release boundary.
|
|
34
|
+
|
|
5
35
|
## 1.0.0-beta.1 — Beta (2026-08-01)
|
|
6
36
|
|
|
7
37
|
The first public Beta establishes a native-first Pulse application contract
|
package/README.md
CHANGED
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
> **Install directly:** Yes. Install the package globally or as a project development dependency.<br>
|
|
7
7
|
> **Supported entry points:** `pulse binary`, `@pulse-compute/cli`, `@pulse-compute/cli/workflow`, `@pulse-compute/cli/project-config`, `@pulse-compute/cli/project-execution`, `@pulse-compute/cli/project-config-schema`, `@pulse-compute/cli/diagnostics`, `@pulse-compute/cli/project-config.schema.json`, `@pulse-compute/cli/cli-spec.json`, `@pulse-compute/cli/release-manifest.json`, `@pulse-compute/cli/documentation-versions.json`, `@pulse-compute/cli/documentation-site.json`<br>
|
|
8
8
|
> **Stability:** Supported Beta workflow and project-configuration contract.<br>
|
|
9
|
-
> **
|
|
9
|
+
> **npm:** [`@pulse-compute/cli`](https://www.npmjs.com/package/@pulse-compute/cli)<br>
|
|
10
|
+
> **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.3/packages/cli/)
|
|
10
11
|
>
|
|
11
|
-
> This release-status block is generated from the synchronized `Pulse 1.0.0-beta.
|
|
12
|
+
> This release-status block is generated from the synchronized `Pulse 1.0.0-beta.3` package policy.
|
|
12
13
|
<!-- pulse-package-status:end -->
|
|
13
14
|
|
|
14
15
|
The public CLI and conventional `@pulse-compute/pulse` application root are
|
|
15
|
-
both part of the synchronized `1.0.0-beta.
|
|
16
|
+
both part of the synchronized `1.0.0-beta.3` release set. Validate the generated
|
|
16
17
|
workflow from the repository or the exact packed acceptance set:
|
|
17
18
|
|
|
18
19
|
```bash
|
package/cli-spec.json
CHANGED
package/docs/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Pulse documentation
|
|
2
2
|
|
|
3
|
-
Pulse documentation is organized in layers so you can stop when you have enough detail. The `1.0.0-beta.
|
|
3
|
+
Pulse documentation is organized in layers so you can stop when you have enough detail. The `1.0.0-beta.3` candidate uses async-shaped managed handlers, trusted Pulse effects, a conventional `.pulse/config.ts` workspace, and the `pulse` CLI. The synchronized 18-package release catalog remains the authority for npm availability and support tiers.
|
|
4
4
|
|
|
5
5
|
## 1. Start and ship a first project
|
|
6
6
|
|
|
@@ -52,6 +52,14 @@ their own topology while normalizing handler bodies into the same canonical IR.
|
|
|
52
52
|
Provider realization begins only after the complete reachable program and its
|
|
53
53
|
capability requirements are known.
|
|
54
54
|
|
|
55
|
+
HTTP Router authoring supports static `get`, `head`, `post`, `put`, `patch`,
|
|
56
|
+
and `delete` registrations, inherited by `Pulse`. The owned Router API registry
|
|
57
|
+
defines compiler admission; topology and lifecycle method catalogs derive from
|
|
58
|
+
that registry. Each verb uses the existing route entry, exact-method dispatch,
|
|
59
|
+
terminal transfer and 404/500 exhaustion contracts. This expands ingress
|
|
60
|
+
registration without changing outgoing fetch methods or the effect/continuation
|
|
61
|
+
ABI.
|
|
62
|
+
|
|
55
63
|
The compiler also recognizes root-only `Pulse.on(type, { schema }, handler)`
|
|
56
64
|
declarations as a separate static event topology. Event types and schema IDs
|
|
57
65
|
must be literal, schema IDs must resolve through the project registry, each
|
|
@@ -115,10 +123,10 @@ See [Compilation and lowering](../concepts/compilation-and-lowering.md) and the
|
|
|
115
123
|
|
|
116
124
|
## Execution ownership
|
|
117
125
|
|
|
118
|
-
|
|
119
|
-
host operations enter the program as canonical capabilities
|
|
120
|
-
operations.
|
|
121
|
-
namespaces
|
|
126
|
+
Pulse-provided host authority is explicit. Fetch, config, secrets, KV, GRIP,
|
|
127
|
+
assets, and future host operations enter the program as canonical capabilities
|
|
128
|
+
or package operations. Pulse does not expose provider SDK objects, ambient
|
|
129
|
+
process state, or hidden host namespaces through the handler context.
|
|
122
130
|
|
|
123
131
|
Native execution erases managed async notation into explicit effects and
|
|
124
132
|
single-use continuations. JavaScript targets execute the same application
|
|
@@ -133,6 +141,19 @@ authority but do
|
|
|
133
141
|
not expose a Request, Response, route parameters, Router transfer, middleware,
|
|
134
142
|
or response builders.
|
|
135
143
|
|
|
144
|
+
Conditional KV is owned by the portable runtime authoring/host contract.
|
|
145
|
+
`kv.getVersioned`, `kv.insertIfAbsent`, and `kv.compareAndSwap` lower through the
|
|
146
|
+
ordinary effect and continuation machinery, including Native value handles.
|
|
147
|
+
The Node reference supplies one explicit local key authority; provider
|
|
148
|
+
preparation and the send boundary remain distinct so unconfirmed writes preserve
|
|
149
|
+
`unknown`. The Native host imports the existing workspace runtime owner rather
|
|
150
|
+
than duplicating its validation, snapshots, limits, or outcome normalization.
|
|
151
|
+
The Fastly Native provider realizes conditional KV directly through its host ABI,
|
|
152
|
+
with lossless generations, conditional options, bounded metadata/body reads and
|
|
153
|
+
readiness deadlines. Its AssemblyScript limits come from the runtime owner; the
|
|
154
|
+
shared corpus checks its wire and outcome semantics. Fastly JavaScript remains
|
|
155
|
+
incomplete capability mapping. Deployed acceptance remains a separate gate. See [conditional KV](../concepts/effects-and-continuations.md#conditional-kv).
|
|
156
|
+
|
|
136
157
|
`ctx.parallel({ ... })` is the explicit cross-target concurrency form. Router
|
|
137
158
|
`next()` and `next(error)` are terminal cursor transfers, not onion-style calls:
|
|
138
159
|
no application code resumes after the transfer. Normal exhaustion produces
|
|
@@ -161,6 +182,25 @@ A generally available target can reject an ineligible project. A passing local
|
|
|
161
182
|
runtime does not claim that an external deployment, binding, service, or
|
|
162
183
|
provider control plane is healthy.
|
|
163
184
|
|
|
185
|
+
The selected target reaches project linking and handler validation explicitly.
|
|
186
|
+
For `javascript`, resolved static package imports and project-relative helper
|
|
187
|
+
imports remain source-runtime boundaries; they do not acquire Native lowerer
|
|
188
|
+
authority. Canonical application topology, schemas, effect-await rules, graph
|
|
189
|
+
containment and entry lifecycle checks still apply. An ordinary imported async
|
|
190
|
+
call may be awaited in a JavaScript handler. Native compilation continues to
|
|
191
|
+
reject unsupported imports and awaits, including when graph eligibility is
|
|
192
|
+
requested in record-only mode.
|
|
193
|
+
|
|
194
|
+
JavaScript compilation returns canonical inspection metadata without an
|
|
195
|
+
executable normalized generator. The provider's graph-backed loader and source
|
|
196
|
+
packager execute the original module closure with its JavaScript async semantics.
|
|
197
|
+
Inspection describes recognized Pulse effects; it does not infer effects inside
|
|
198
|
+
ordinary dependency implementations or certify their isolation. An ordinary
|
|
199
|
+
JavaScript import gains no compiler/lowerer authority or Native guest sandbox
|
|
200
|
+
guarantee. Native inspection compiles the source
|
|
201
|
+
independently under Native rules. Its failure is advisory for a selected
|
|
202
|
+
JavaScript target; `pulse compile` still requires a real Native compilation.
|
|
203
|
+
|
|
164
204
|
Provider packages own descriptors, configuration normalization, local
|
|
165
205
|
execution, target generation, source packaging, deployment bindings, and target
|
|
166
206
|
support policy. The compiler owns the neutral bootstrap, contract validation,
|
|
@@ -198,6 +238,18 @@ guest-link packaging authorization have already been checked. It does not
|
|
|
198
238
|
contain a TypeScript AST/service, compiler cache, builder, mutable manifest,
|
|
199
239
|
compiled-program object, raw target option bag, or alternate target.
|
|
200
240
|
|
|
241
|
+
CLI Native test/dev execution that needs guest crypto or conditional KV uses
|
|
242
|
+
an optional provider-owned `prepareNativeExecution` driver hook. It receives the
|
|
243
|
+
same immutable, validated invocation with action `execute-native` and returns a
|
|
244
|
+
local request executor. The CLI never substitutes another provider's host.
|
|
245
|
+
Node executes the compiled neutral Wasm with its provider adapter. Fastly
|
|
246
|
+
realizes its own Native artifact and runs the existing fixture ABI, including
|
|
247
|
+
the conditional-KV authority. Its result identifies the artifact hash and fixture
|
|
248
|
+
kind; unavailable effect telemetry is reported as such. This does not establish
|
|
249
|
+
Viceroy or deployed Fastly acceptance. S3 fixtures preserve raw response streams
|
|
250
|
+
inside the provider transport while ordinary fetch retains its opaque response
|
|
251
|
+
contract. Dev retains a last-good Native executor if recompilation fails.
|
|
252
|
+
|
|
201
253
|
Native realization and JavaScript source packaging are normalized into
|
|
202
254
|
versioned, data-only results before the CLI consumes them. Provider packaging
|
|
203
255
|
must report the same artifact identity authorized by the final guest audit.
|
|
@@ -295,7 +347,7 @@ without moving package semantics into the compiler or widening the trust model.
|
|
|
295
347
|
|
|
296
348
|
## JWT verification
|
|
297
349
|
|
|
298
|
-
The synchronized `1.0.0-beta.
|
|
350
|
+
The synchronized `1.0.0-beta.3` JWT/crypto packages compose
|
|
299
351
|
`@pulse-compute/jwt` over the lower-level, provider-neutral verification
|
|
300
352
|
contract owned by `@pulse-compute/crypto`. The executable algorithm set is
|
|
301
353
|
HS256 and ES256. Crypto verifies a MAC or signature over caller-supplied bytes
|
|
@@ -312,7 +364,7 @@ objects do not merge. An empty declaration enables no algorithms. An unknown,
|
|
|
312
364
|
missing, unavailable, or failed realization stops with a normalized diagnostic
|
|
313
365
|
and never authorizes fallback.
|
|
314
366
|
|
|
315
|
-
JavaScript targets select `runtime-builtin` and use Web Crypto with explicit
|
|
367
|
+
For JWT verification, JavaScript targets select `runtime-builtin` and use Web Crypto with explicit
|
|
316
368
|
HMAC/SHA-256 or ECDSA/P-256/SHA-256 parameters. The crypto boundary receives a
|
|
317
369
|
normalized 64-byte P-256 point; its JavaScript adapter validates that point and
|
|
318
370
|
constructs the runtime-private JWK used for import. Native HS256 selects
|
|
@@ -321,6 +373,41 @@ primary module, while Native ES256 selects the audited
|
|
|
321
373
|
`guest-linked:pulse-es256-rustcrypto-p256` unit. Neither algorithm retries a
|
|
322
374
|
different realization.
|
|
323
375
|
|
|
376
|
+
S3 operations require exact `SHA-256` and `HMAC-SHA256` selection. Native
|
|
377
|
+
composes the same Crypto-owned source once; Node JavaScript explicitly selects
|
|
378
|
+
Crypto's `runtime-builtin` Web Crypto byte realization through the trusted
|
|
379
|
+
`@pulse-compute/crypto/provider` export. Both return 32-byte results, cap data
|
|
380
|
+
at 32 KiB and HMAC keys at 8 KiB, and snapshot and wipe staging inputs. Native
|
|
381
|
+
also checks guest memory ranges. JWT verification retains its separate limits.
|
|
382
|
+
No target probes or falls back to a different realization.
|
|
383
|
+
|
|
384
|
+
The supported-extension `@pulse-compute/s3` package owns `head`, `getText` and `putText`,
|
|
385
|
+
literal binding/options authority, runtime key/text lowering, SigV4 composition
|
|
386
|
+
and bounded results. Node and Fastly own fixed endpoint/bucket/region mappings,
|
|
387
|
+
credential lookup, deadlines and transport. Fastly requires a static backend.
|
|
388
|
+
Reads and writes bypass cache, disable decompression and redirects, preserve
|
|
389
|
+
exact bytes and do not retry. PUT distinguishes pre-dispatch failure and
|
|
390
|
+
complete rejection (`not-stored`) from unconfirmed dispatched writes (`unknown`).
|
|
391
|
+
Only a complete 200 acknowledgement with a bounded empty body yields `stored`;
|
|
392
|
+
its digest describes sent bytes, not durability. Request cancellation retains
|
|
393
|
+
existing lifecycle behavior and does not fabricate a typed S3 outcome. Fastly
|
|
394
|
+
pending requests lack a cancel ABI; invocation termination owns their release.
|
|
395
|
+
|
|
396
|
+
One canonical consumer exercises Node Native, Node JavaScript and Fastly Native
|
|
397
|
+
PUT/HEAD/GET, integrity, bounded acknowledgements and cancellation. Fastly Native
|
|
398
|
+
runs compiled Wasm against a host ABI fixture. This is local evidence, not live
|
|
399
|
+
Object Storage proof. Fastly JavaScript remains ineligible: its SDK projects raw
|
|
400
|
+
response headers, losing multiplicity and aggregate-size evidence required by
|
|
401
|
+
O1. The provider-specific limitation is documented in `wasm/test/s3/O3.md` and
|
|
402
|
+
does not gate supported targets. O4 adds S3 to the synchronized release package
|
|
403
|
+
set and repeats the three-target read/write corpus against isolated exact
|
|
404
|
+
tarballs, including package-owned lowering. These are local candidate checks;
|
|
405
|
+
live origin acceptance follows T2. Assets alignment remains separate.
|
|
406
|
+
|
|
407
|
+
Package redaction declarations survive Handler IR projection into the Native
|
|
408
|
+
plan. Native host effect traces omit declared private payloads and results;
|
|
409
|
+
applications still control their own response and logging use of returned data.
|
|
410
|
+
|
|
324
411
|
All four target classes—Node JavaScript, Fastly JavaScript, Node Native, and
|
|
325
412
|
Fastly Native—execute the same HS256 semantics. ES256 adds exact default and
|
|
326
413
|
size-oriented Native artifact cells, producing a six-cell 38-case matrix:
|
|
@@ -341,7 +428,7 @@ publish, promote, deploy, or activate the release.
|
|
|
341
428
|
|
|
342
429
|
## Support, release, and authority
|
|
343
430
|
|
|
344
|
-
Pulse `1.0.0-beta.
|
|
431
|
+
Pulse `1.0.0-beta.3` is a Beta intended for the `beta` channel.
|
|
345
432
|
Documented, evidence-backed behavior is intentional, but public surfaces may
|
|
346
433
|
change deliberately before a compatibility-bearing release. Unsupported
|
|
347
434
|
behavior fails explicitly, historical and implementation subpaths gain no
|
|
@@ -361,6 +448,20 @@ architecture, merge, repository-setting, and release authority. Codex may
|
|
|
361
448
|
analyze, review, reproduce, and prepare bounded patches; deterministic checks
|
|
362
449
|
remain authoritative even when Codex is unavailable.
|
|
363
450
|
|
|
451
|
+
A protected-path match requires a boundary declaration and review; it does not
|
|
452
|
+
establish that the patch changes that boundary's semantics. Human direction
|
|
453
|
+
already supplied for a bounded task covers its necessary implementation, tests,
|
|
454
|
+
canonical documentation, regeneration and PR preparation. The PR records that
|
|
455
|
+
direction and any remaining decision. A new semantic or authority change beyond
|
|
456
|
+
the authorized scope requires new direction. Implementation approval does not
|
|
457
|
+
transfer merge, publication, deployment or self-approval authority.
|
|
458
|
+
|
|
459
|
+
Validation claims distinguish injected hosts, local Compute engines, standalone
|
|
460
|
+
live probes and deployed Pulse artifacts. SDK capability mappings and observed
|
|
461
|
+
provider discrepancies do not redefine Pulse's contract. Required acceptance
|
|
462
|
+
gates remain separate from the aggregate release command; their status and any
|
|
463
|
+
human-directed policy changes must be explicit before claiming release readiness.
|
|
464
|
+
|
|
364
465
|
See the [maintainer charter](../maintainers/maintainer-charter.md),
|
|
365
466
|
[release acceptance](../maintainers/release-acceptance.md),
|
|
366
467
|
[npm publishing](../maintainers/npm-publishing.md), and
|
|
@@ -408,7 +408,7 @@ generic loader handles reachable-graph discovery and trusted invocation. Older
|
|
|
408
408
|
`/pulsewasm` imports are isolated in the
|
|
409
409
|
[compatibility migration guide](../guides/compatibility-imports.md).
|
|
410
410
|
|
|
411
|
-
In Pulse `1.0.0-beta.
|
|
411
|
+
In Pulse `1.0.0-beta.3`, package-owned builders must declare `compiler.trust: 'first-party'` and ship in the synchronized release set. This is an internal contributor mechanism, not a general third-party plugin API. See [Add a first-party package-owned lowerer](../contributing/adding-first-party-lowerer.md).
|
|
412
412
|
|
|
413
413
|
## Provider lowering is a second contract
|
|
414
414
|
|
|
@@ -38,7 +38,7 @@ GRIP uses the same split. `isWebSocket`, `subscribe`, and `handoff` are pure HTT
|
|
|
38
38
|
|
|
39
39
|
## Provider selection
|
|
40
40
|
|
|
41
|
-
Pulse `1.0.0-beta.
|
|
41
|
+
Pulse `1.0.0-beta.3` has three provider driver identifiers:
|
|
42
42
|
|
|
43
43
|
| Provider | Local execution | Deployable build | Purpose |
|
|
44
44
|
|---|---:|---:|---|
|
|
@@ -96,7 +96,7 @@ For Fastly, `pulse build` additionally emits a real Compute target. The explicit
|
|
|
96
96
|
|
|
97
97
|
## Current extension boundary
|
|
98
98
|
|
|
99
|
-
There is no automatic provider plugin registry in `1.0.0-beta.
|
|
99
|
+
There is no automatic provider plugin registry in `1.0.0-beta.3`. Configuration
|
|
100
100
|
selects a bare host ID, internal `none`, or an exact scoped project-installed
|
|
101
101
|
package name. Bare IDs resolve by the `@pulse-compute/provider-<id>` convention.
|
|
102
102
|
A package is loadable only when selected and when it exports the versioned
|
|
@@ -241,3 +241,60 @@ pulse test ./my-app --json
|
|
|
241
241
|
- [Fetching and composing data](../guides/fetching-and-composition.md)
|
|
242
242
|
- [Project configuration](../reference/project-config.md)
|
|
243
243
|
- [Troubleshooting](../guides/troubleshooting.md)
|
|
244
|
+
|
|
245
|
+
## Conditional KV
|
|
246
|
+
|
|
247
|
+
`ctx.kv<T>('name')` exposes `getVersioned(key)`, `insertIfAbsent(key, value)`, and
|
|
248
|
+
`compareAndSwap(key, generation, value)` as direct awaited or keyed parallel
|
|
249
|
+
effects. The Node reference implements the contract for JavaScript and compiled
|
|
250
|
+
Native control flow. Fastly Native implements it through direct KV hostcalls;
|
|
251
|
+
Fastly JavaScript conditional KV remains explicitly incomplete.
|
|
252
|
+
|
|
253
|
+
The condition and mutation are atomic at one key's authority. A versioned read
|
|
254
|
+
returns a value and an opaque generation from the same observation, which may be
|
|
255
|
+
stale. Generations are strings, not numbers, hashes or application versions.
|
|
256
|
+
Create conflicts when present; CAS conflicts when absent or when its token is
|
|
257
|
+
stale. Equal-byte replacement is still a write and changes its generation.
|
|
258
|
+
Existing unconditional `get` and `put` remain available.
|
|
259
|
+
|
|
260
|
+
A write returns `stored`, `conflict`, `not-stored` with a bounded reason, or
|
|
261
|
+
`unknown` with a bounded reason. Unknown may have committed. A complete explicit
|
|
262
|
+
provider rejection establishes no write; an exception from a send primitive
|
|
263
|
+
does not. Pulse does not retry, reread-and-rebase, or invent a generation from a
|
|
264
|
+
write acknowledgement. A subsequent missing or stale read cannot resolve an
|
|
265
|
+
ambiguous write by itself.
|
|
266
|
+
|
|
267
|
+
Admission detaches and freezes the candidate before provider preparation. The
|
|
268
|
+
host's monotonic ten-second deadline starts at admission and is shortened by an
|
|
269
|
+
owning request deadline. Preparation may resolve bindings and stage data but
|
|
270
|
+
cannot send. Entry into the returned provider primitive marks dispatch even if
|
|
271
|
+
it throws synchronously. Timeout before that boundary is `not-stored`; timeout
|
|
272
|
+
or transport loss after it is `unknown`. Cancellation suppresses delivery to an
|
|
273
|
+
inactive execution and records whether dispatch occurred; it promises no rollback.
|
|
274
|
+
|
|
275
|
+
Exact keys are bounded Unicode scalar strings; generations are bounded visible
|
|
276
|
+
ASCII strings. Values retain the portable KV JSON limits. Conditional storage
|
|
277
|
+
uses a strict UTF-8 JSON envelope with exactly `__pulseKv: 1` and `value`, rejecting
|
|
278
|
+
duplicate members, invalid values, and oversized bodies. The wrapper is not
|
|
279
|
+
recursively unwrapped. Legacy raw JSON requires explicit migration. Keys, tokens,
|
|
280
|
+
and values are omitted or redacted from runtime evidence and managed errors;
|
|
281
|
+
application responses are not silently rewritten.
|
|
282
|
+
|
|
283
|
+
Node reference instances retain nonreused generation identities for their own
|
|
284
|
+
lifetime. Host code can explicitly reuse one reference across requests and target
|
|
285
|
+
runners; independent instances isolate their state. Deterministic identities,
|
|
286
|
+
clocks, and failure hooks belong to host evidence, not handler authority. This
|
|
287
|
+
local model does not establish durability, global visibility, cross-key
|
|
288
|
+
transactions, or a portable physical-delete/recreate guarantee. Fastly SDK
|
|
289
|
+
limitations cannot redefine this contract or gate other targets.
|
|
290
|
+
|
|
291
|
+
Fastly Native preserves all 64 generation bits in an opaque string. ADD and
|
|
292
|
+
generation-conditioned overwrite remain distinct operations, including an explicit
|
|
293
|
+
condition for zero bits. The adapter stages the complete envelope before dispatch,
|
|
294
|
+
uses monotonic deadlines and readiness selection before pending waits and body
|
|
295
|
+
reads, and closes acquired bodies. It accepts up to 65,560 wire bytes, including
|
|
296
|
+
wrapper overhead. Provider key restrictions return `invalid-key` without changing
|
|
297
|
+
the key. Pending KV operations have no cancellation hostcall; an expired operation
|
|
298
|
+
is abandoned to invocation teardown and may still commit. Host termination never
|
|
299
|
+
resumes an inactive handler. Local Wasm evidence is separate from K4's deployed
|
|
300
|
+
cross-location acceptance.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Package-owned lowering lets a synchronized Pulse package extend the canonical compiler with narrow, statically recognized operations while keeping domain rules out of compiler core.
|
|
4
4
|
|
|
5
|
-
The synchronized `1.0.0-beta.
|
|
5
|
+
The synchronized `1.0.0-beta.3` release uses this pattern for Assets, GRIP,
|
|
6
6
|
JWT, and Entities.
|
|
7
7
|
It is a **trusted first-party synchronization mechanism**, not a public
|
|
8
8
|
registry that executes arbitrary npm compiler plugins.
|
|
@@ -6,9 +6,17 @@ branches on. The release distinguishes current execution proof from forward
|
|
|
6
6
|
host work so architectural direction does not become an accidental support
|
|
7
7
|
claim.
|
|
8
8
|
|
|
9
|
+
An explicit JavaScript profile can retain resolved static package imports and
|
|
10
|
+
project-relative helpers, including awaited calls into ordinary JavaScript
|
|
11
|
+
dependencies. Pulse checks the canonical application surface and packages its
|
|
12
|
+
original source graph. Native eligibility is reported separately and does not
|
|
13
|
+
block JavaScript execution. Unsupported dynamic module boundaries and missing
|
|
14
|
+
`await` on Pulse effects still fail validation. `pulse compile` continues to
|
|
15
|
+
require Native-compatible source; use `pulse build` for a JavaScript package.
|
|
16
|
+
|
|
9
17
|
## Current Beta targets
|
|
10
18
|
|
|
11
|
-
`1.0.0-beta.
|
|
19
|
+
`1.0.0-beta.3` exercises four explicit modes through one conformance corpus:
|
|
12
20
|
|
|
13
21
|
| Host | Target | Current release status | Build shape |
|
|
14
22
|
|---|---|---|---|
|
|
@@ -37,7 +45,7 @@ adapter, lifecycle, conformance evidence, and package claim.
|
|
|
37
45
|
The [ESP32 reference host](https://github.com/pulsecompute/pulse-esp32-host)
|
|
38
46
|
tests whether the event/effect/continuation model remains useful without a
|
|
39
47
|
JavaScript fallback, abundant memory, or an HTTP-centered lifecycle. It is a
|
|
40
|
-
boundary witness, not a `1.0.0-beta.
|
|
48
|
+
boundary witness, not a `1.0.0-beta.3` provider or compatibility promise. The
|
|
41
49
|
[architecture vision](../architecture/vision.md#esp32-as-a-boundary-witness)
|
|
42
50
|
describes the intended host-owned interrupt queue and non-reentrant Wasm entry.
|
|
43
51
|
|
|
@@ -75,7 +75,7 @@ Descriptors are normalized by the shared provider contract. A conceptual descrip
|
|
|
75
75
|
```js
|
|
76
76
|
const EXAMPLE_PROVIDER_DESCRIPTOR = createProviderDescriptor({
|
|
77
77
|
id: 'example',
|
|
78
|
-
providerVersion: '1.0.0-beta.
|
|
78
|
+
providerVersion: '1.0.0-beta.3',
|
|
79
79
|
package: '@pulse-compute/provider-example',
|
|
80
80
|
runtime: 'pulse.canonical-example-runtime.v1',
|
|
81
81
|
buildTarget: 'example-edge',
|
|
@@ -11,7 +11,7 @@ Start with [Pulse-aware package authoring](./pulse-aware-packages.md) to decide
|
|
|
11
11
|
whether the package needs Native lowering at all. Ordinary target-compatible
|
|
12
12
|
JavaScript packages do not require a compiler builder.
|
|
13
13
|
|
|
14
|
-
> **Scope and trust boundary:** Pulse `1.0.0-beta.
|
|
14
|
+
> **Scope and trust boundary:** Pulse `1.0.0-beta.3` executes package-owned compiler builders only when their manifest declares `compiler.trust: 'first-party'` and the package is part of the synchronized release set. This is a core-repository contributor workflow, **not an external plugin** interface or a supported third-party plugin API. An external package cannot self-register arbitrary compiler code.
|
|
15
15
|
|
|
16
16
|
A package-owned lowerer lets one release package define a narrow TypeScript facade and keep its domain-specific static validation outside compiler core. GRIP is the clearest current example; assets is the second implementation proving that the generic loader is not GRIP-specific.
|
|
17
17
|
|
|
@@ -8,7 +8,7 @@ pulse-doc-meta:end -->
|
|
|
8
8
|
# Package lowerer contract reference
|
|
9
9
|
|
|
10
10
|
This reference describes the internal first-party lowerer protocol used by the
|
|
11
|
-
synchronized `1.0.0-beta.
|
|
11
|
+
synchronized `1.0.0-beta.3` release. It documents current repository
|
|
12
12
|
interfaces; it is not a third-party plugin compatibility promise. Package
|
|
13
13
|
availability remains owned by the release catalog.
|
|
14
14
|
|
|
@@ -370,7 +370,7 @@ Package lowerer code must not choose `node.*`, `fastly.*`, backend names, store
|
|
|
370
370
|
|
|
371
371
|
## Compatibility status
|
|
372
372
|
|
|
373
|
-
This protocol is synchronized inside the `1.0.0-beta.
|
|
373
|
+
This protocol is synchronized inside the `1.0.0-beta.3` release set. It can change with compiler implementation needs. Only explicitly documented application facades carry the package support promise.
|
|
374
374
|
|
|
375
375
|
A public external lowerer API would require a new contract that addresses trust, sandboxing, provenance, protocol negotiation, resource limits, lifecycle support, and semver compatibility.
|
|
376
376
|
|
|
@@ -117,12 +117,12 @@ normal lane ends as `404 Not Found`; an unhandled error lane ends as
|
|
|
117
117
|
|
|
118
118
|
The Beta Router supports:
|
|
119
119
|
|
|
120
|
-
- `use`, `get`, `head`, `post`, `mount`, and `error`;
|
|
120
|
+
- `use`, `get`, `head`, `post`, `put`, `patch`, `delete`, `mount`, and `error`;
|
|
121
121
|
- exact paths, named `:parameters`, and a trailing `*` wildcard;
|
|
122
122
|
- statically declared, acyclic mounted routers;
|
|
123
123
|
- first-match order and explicit route fallthrough.
|
|
124
124
|
|
|
125
|
-
It does not support `
|
|
125
|
+
It does not support `options`, `trace`, `connect`, regular-expression routes,
|
|
126
126
|
runtime route registration, Express Router plugins, or hidden server lifecycle
|
|
127
127
|
hooks. Keep an unsupported endpoint on its existing service or redesign it
|
|
128
128
|
before moving that endpoint into Pulse; selecting a JavaScript target does not
|
|
@@ -165,7 +165,7 @@ Pulse never changes targets or falls back automatically.
|
|
|
165
165
|
|
|
166
166
|
1. Inventory routes, methods, middleware order, error paths, body parsing, and
|
|
167
167
|
ambient host dependencies.
|
|
168
|
-
2. Move one supported `GET`, `HEAD`, or `
|
|
168
|
+
2. Move one supported `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, or `DELETE` route to a statically declared
|
|
169
169
|
`Pulse` application.
|
|
170
170
|
3. Replace response mutation with returned `ctx.json`, `ctx.text`, or
|
|
171
171
|
`ctx.response` results.
|
package/docs/guides/routing.md
CHANGED
|
@@ -76,7 +76,7 @@ export default app
|
|
|
76
76
|
|
|
77
77
|
- `new Router()` with a default-exported root router;
|
|
78
78
|
- `use(handler)` and `use(path, handler)` middleware;
|
|
79
|
-
- `get`, `head`, and `
|
|
79
|
+
- `get`, `head`, `post`, `put`, `patch`, and `delete` registrations;
|
|
80
80
|
- exact paths, named `:parameters`, and a trailing `*` wildcard;
|
|
81
81
|
- static acyclic `mount` composition;
|
|
82
82
|
- named or inline async-shaped route handlers using `(ctx)` or `(ctx, next)`;
|
|
@@ -87,6 +87,24 @@ export default app
|
|
|
87
87
|
|
|
88
88
|
Every Router handler uses the normal canonical context. Fetches, schemas, config, secrets, KV, opaque responses, and trusted package effects lower into the same native execution plan as single-handler authoring.
|
|
89
89
|
|
|
90
|
+
`Pulse` inherits the same route registration methods. Each registration matches
|
|
91
|
+
its exact HTTP method; a method mismatch advances the route cursor and normal
|
|
92
|
+
exhaustion remains `404`. There is no automatic `OPTIONS` or `405` response.
|
|
93
|
+
Ingress route methods do not widen the separate outbound `ctx.fetch` contract.
|
|
94
|
+
|
|
95
|
+
The `catalog-router-parity` conformance task exercises the original Catalog
|
|
96
|
+
consumer probe and all 14 of its PUT/PATCH/DELETE operations with their existing
|
|
97
|
+
methods and paths. Its shared cases check mounted parameters, request text,
|
|
98
|
+
middleware state, exact method misses, registration order, terminal fallthrough,
|
|
99
|
+
404 exhaustion and handled errors on Node/Fastly JavaScript and Native. Native
|
|
100
|
+
lanes execute compiled Wasm; Fastly evidence uses local provider emulation and
|
|
101
|
+
the target ABI mock host, not a deployed service. The fixtures establish routing
|
|
102
|
+
acceptance only; they do not implement Catalog persistence or authorization.
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
node wasm/scripts/run-wasm-tests.cjs --task catalog-router-parity --no-report
|
|
106
|
+
```
|
|
107
|
+
|
|
90
108
|
## `next()` is a terminal transfer
|
|
91
109
|
|
|
92
110
|
`next()` is not an onion-style callback. It is a compiler-visible control transfer:
|
|
@@ -31,7 +31,7 @@ GitHub Pages deployment is no longer part of the repository workflow. The releas
|
|
|
31
31
|
|
|
32
32
|
## Object classes
|
|
33
33
|
|
|
34
|
-
The `1.0.0-beta.
|
|
34
|
+
The `1.0.0-beta.3` layout is:
|
|
35
35
|
|
|
36
36
|
```text
|
|
37
37
|
<bucket>/pulse/
|
|
@@ -41,8 +41,8 @@ The `1.0.0-beta.1` layout is:
|
|
|
41
41
|
versions.json mutable
|
|
42
42
|
site-manifest.json mutable
|
|
43
43
|
public-site-manifest.json mutable
|
|
44
|
-
v1.0.0-beta.
|
|
45
|
-
deployments/v1.0.0-beta.
|
|
44
|
+
v1.0.0-beta.3/** immutable
|
|
45
|
+
deployments/v1.0.0-beta.3.json immutable receipt
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
The exact-version tree is the archival release. Root and `latest` are convenience surfaces promoted only after exact-version verification and matching npm package verification.
|
|
@@ -72,7 +72,7 @@ npm run docs:deployment:prepare
|
|
|
72
72
|
npm run docs:deployment:verify
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
`.pulse-documentation-deployment/documentation-deployment-manifest.json` records every object key, local source, byte length, SHA-256, content type, cache class, mutability, source commit, public documentation route, and independent storage prefix. Its deterministic deployment receipt records the complete generated-site digest and the exact-version object inventory and tree digest for `deployments/v1.0.0-beta.
|
|
75
|
+
`.pulse-documentation-deployment/documentation-deployment-manifest.json` records every object key, local source, byte length, SHA-256, content type, cache class, mutability, source commit, public documentation route, and independent storage prefix. Its deterministic deployment receipt records the complete generated-site digest and the exact-version object inventory and tree digest for `deployments/v1.0.0-beta.3.json`. Candidate verification rejects any root or site file outside that sealed inventory.
|
|
76
76
|
|
|
77
77
|
A local adapter exercised by `npm run publication:check` proves:
|
|
78
78
|
|
|
@@ -26,7 +26,7 @@ The homepage and exact current documentation load the same assets under `/v<vers
|
|
|
26
26
|
The canonical URL for this release begins with:
|
|
27
27
|
|
|
28
28
|
```text
|
|
29
|
-
https://pulsecompute.io/v1.0.0-beta.
|
|
29
|
+
https://pulsecompute.io/v1.0.0-beta.3/
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Diagnostics, package status blocks, and package metadata use exact-version URLs. This prevents a diagnostic emitted by an older CLI from silently opening instructions for a newer contract.
|