@pulse-compute/wasm-contracts 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/README.md +3 -2
- package/package.json +4 -3
- package/src/crypto/contracts.js +12 -2
- package/src/definitions/router-api.js +3 -0
- package/src/diagnostics.js +1 -1
- package/src/handler/ctx-contract.js +1 -1
- package/src/handler/lifecycle-authoring-alignment.js +5 -1
- package/src/handler/surface-contract.js +7 -0
- package/src/provider/canonical-provider.js +4 -0
- package/src/provider/toolchain.js +6 -1
- package/src/s3/contracts.js +12 -0
package/README.md
CHANGED
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
> **Install directly:** Provider toolchain authors may install it for the versioned bootstrap contract; application projects receive it transitively.<br>
|
|
7
7
|
> **Supported entry points:** `@pulse-compute/wasm-contracts/provider/toolchain`<br>
|
|
8
8
|
> **Stability:** The provider toolchain contract is versioned and supported for the Beta; other protocol and proof interfaces remain internal.<br>
|
|
9
|
-
> **
|
|
9
|
+
> **npm:** [`@pulse-compute/wasm-contracts`](https://www.npmjs.com/package/@pulse-compute/wasm-contracts)<br>
|
|
10
|
+
> **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.3/packages/implementation-packages/)
|
|
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
|
This package owns stable data contracts shared by the compiler, runtime, and providers.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pulse-compute/wasm-contracts",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": "^22.14.0 || ^24.0.0"
|
|
@@ -109,7 +109,8 @@
|
|
|
109
109
|
"./project/javascript-application": "./src/project/javascript-application.js",
|
|
110
110
|
"./project/target-support-evidence": "./src/project/target-support-evidence.js",
|
|
111
111
|
"./project/javascript-core-capabilities": "./src/project/javascript-core-capabilities.js",
|
|
112
|
-
"./project/native-optimization": "./src/project/native-optimization.js"
|
|
112
|
+
"./project/native-optimization": "./src/project/native-optimization.js",
|
|
113
|
+
"./s3/contracts": "./src/s3/contracts.js"
|
|
113
114
|
},
|
|
114
115
|
"publishConfig": {
|
|
115
116
|
"access": "public"
|
|
@@ -125,7 +126,7 @@
|
|
|
125
126
|
"url": "git+https://github.com/pulse-compute/pulse.git",
|
|
126
127
|
"directory": "wasm/packages/contracts"
|
|
127
128
|
},
|
|
128
|
-
"homepage": "https://pulsecompute.io/v1.0.0-beta.
|
|
129
|
+
"homepage": "https://pulsecompute.io/v1.0.0-beta.3/packages/implementation-packages/",
|
|
129
130
|
"bugs": {
|
|
130
131
|
"url": "https://github.com/pulse-compute/pulse/issues"
|
|
131
132
|
}
|
package/src/crypto/contracts.js
CHANGED
|
@@ -23,8 +23,18 @@ const CRYPTO_VERIFICATION_STATUSES = Object.freeze([
|
|
|
23
23
|
'realization-failure'
|
|
24
24
|
]);
|
|
25
25
|
|
|
26
|
-
const CRYPTO_ALGORITHMS = Object.freeze(['HS256', 'ES256']);
|
|
26
|
+
const CRYPTO_ALGORITHMS = Object.freeze(['HS256', 'ES256', 'SHA-256', 'HMAC-SHA256']);
|
|
27
27
|
const CRYPTO_REALIZATIONS = Object.freeze([
|
|
28
|
+
...['SHA-256', 'HMAC-SHA256'].map((algorithm) => Object.freeze({
|
|
29
|
+
id: 'runtime-builtin', kind: 'runtime-builtin', algorithm, targets: Object.freeze(['javascript']),
|
|
30
|
+
implementation: algorithm === 'SHA-256' ? 'webcrypto.subtle.sha-256-bytes.v1' : 'webcrypto.subtle.hmac-sha-256-bytes.v1'
|
|
31
|
+
})),
|
|
32
|
+
...['SHA-256', 'HMAC-SHA256'].map((algorithm) => Object.freeze({
|
|
33
|
+
id: 'guest-source:pulse-hmac-as', kind: 'guest-source', backend: 'pulse-hmac-as',
|
|
34
|
+
implementation: CRYPTO_GUEST_SOURCE_IMPLEMENTATION, algorithm, targets: Object.freeze(['native']),
|
|
35
|
+
source: Object.freeze({ package: '@pulse-compute/crypto', export: './pulsewasm-native',
|
|
36
|
+
contractVersion: 'pulse.crypto-guest-source.v1', contribution: 'pulse-hmac-as' })
|
|
37
|
+
})),
|
|
28
38
|
Object.freeze({
|
|
29
39
|
id: 'runtime-builtin',
|
|
30
40
|
kind: 'runtime-builtin',
|
|
@@ -586,7 +596,7 @@ function planCryptoRealizations(input = {}) {
|
|
|
586
596
|
algorithm: configured.algorithm,
|
|
587
597
|
primitive: configured.algorithm === 'ES256'
|
|
588
598
|
? Object.freeze({ kind: 'ecdsa', curve: 'P-256', hash: 'SHA-256' })
|
|
589
|
-
: Object.freeze({ kind: 'hmac', hash: 'SHA-256' }),
|
|
599
|
+
: Object.freeze({ kind: configured.algorithm === 'SHA-256' ? 'digest' : 'hmac', hash: 'SHA-256' }),
|
|
590
600
|
requestedBy: requirement ? requirement.requestedBy : Object.freeze([]),
|
|
591
601
|
semanticOwner: requirements.semanticOwner,
|
|
592
602
|
realization,
|
|
@@ -34,6 +34,9 @@ const ROUTER_API_DEFINITIONS = Object.freeze([
|
|
|
34
34
|
createHttpRouteDefinition('get', 'GET'),
|
|
35
35
|
createHttpRouteDefinition('head', 'HEAD'),
|
|
36
36
|
createHttpRouteDefinition('post', 'POST'),
|
|
37
|
+
createHttpRouteDefinition('put', 'PUT'),
|
|
38
|
+
createHttpRouteDefinition('patch', 'PATCH'),
|
|
39
|
+
createHttpRouteDefinition('delete', 'DELETE'),
|
|
37
40
|
Object.freeze({
|
|
38
41
|
name: 'mount',
|
|
39
42
|
kind: 'mount',
|
package/src/diagnostics.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
|
|
5
|
-
const PACKAGE_VERSION = 'pulsewasm-route-extractor@1.0.0-beta.
|
|
5
|
+
const PACKAGE_VERSION = 'pulsewasm-route-extractor@1.0.0-beta.3';
|
|
6
6
|
const DIAGNOSTICS_VERSION = 'pulsewasm.diagnostics.v1';
|
|
7
7
|
|
|
8
8
|
function stableFileName(fileName, cwd) {
|
|
@@ -8,7 +8,7 @@ const CTX_SURFACE_IDS = Object.freeze([
|
|
|
8
8
|
'ctx.param','ctx.req.method','ctx.req.url','ctx.req.path','ctx.req.header','ctx.req.headers',
|
|
9
9
|
'ctx.state.get','ctx.state.set','ctx.json','ctx.text','ctx.response','ctx.req.text','ctx.req.json.schema',
|
|
10
10
|
'ctx.req.json.generic','ctx.fetch.projected','ctx.fetch.opaque-return','ctx.config.get','ctx.secret.get',
|
|
11
|
-
'ctx.kv.get','ctx.kv.put','ctx.emit','package.operation'
|
|
11
|
+
'ctx.kv.get','ctx.kv.put','ctx.kv.getVersioned','ctx.kv.insertIfAbsent','ctx.kv.compareAndSwap','ctx.emit','package.operation'
|
|
12
12
|
]);
|
|
13
13
|
const surfaceById = new Map(HANDLER_SURFACE_DEFINITIONS.map((entry) => [entry.id, entry]));
|
|
14
14
|
const CTX_SURFACES = Object.freeze(CTX_SURFACE_IDS.map((id) => {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { ROUTER_API_DEFINITIONS } = require('../definitions/router-api.js');
|
|
4
|
+
|
|
3
5
|
const LIFECYCLE_AUTHORING_ALIGNMENT_VERSION = 'pulsewasm.lifecycle-authoring-alignment.v1';
|
|
4
6
|
const LIFECYCLE_AUTHORING_ALIGNMENT_PHASE = '52';
|
|
5
7
|
const LIFECYCLE_AUTHORING_ALIGNMENT_ARTIFACT = 'lifecycle-authoring-alignment.json';
|
|
@@ -19,7 +21,9 @@ const LIFECYCLE_AUTHORING_ALIGNMENT_POLICY = Object.freeze({
|
|
|
19
21
|
purpose: 'make the beta lowerable authoring subset explicit and fail fast when route methods and package-owned lowerable effect methods diverge',
|
|
20
22
|
productionCompletenessRequired: false,
|
|
21
23
|
simpleUserFunctionLoweringIntentional: true,
|
|
22
|
-
routerMethods: Object.freeze(
|
|
24
|
+
routerMethods: Object.freeze(ROUTER_API_DEFINITIONS
|
|
25
|
+
.filter((definition) => definition.kind === 'route')
|
|
26
|
+
.map((definition) => definition.method)),
|
|
23
27
|
packageEffectAlignment: Object.freeze({
|
|
24
28
|
assets: Object.freeze({
|
|
25
29
|
rule: 'assets.lookup method must match the owning router route method when route metadata is available',
|
|
@@ -348,6 +348,13 @@ const HANDLER_SURFACE_DEFINITIONS = Object.freeze([
|
|
|
348
348
|
nativeBehavior: 'emit-kv-put-effect',
|
|
349
349
|
status: 'supported'
|
|
350
350
|
}),
|
|
351
|
+
...['getVersioned', 'insertIfAbsent', 'compareAndSwap'].map((method) => surface({
|
|
352
|
+
id: `ctx.kv.${method}`, class: 'effect', canonicalOperation: `effect.kv.${method}`,
|
|
353
|
+
publicForms: [`ctx.kv<T>('namespace').${method}(${method === 'getVersioned' ? 'key' : method === 'compareAndSwap' ? 'key, generation, value' : 'key, value'})`],
|
|
354
|
+
awaitPolicy: 'required-when-consumed', validPositions: ['await-expression', 'parallel-member'],
|
|
355
|
+
targetSupport: { javascript: true, native: true }, nativeBehavior: 'emit-conditional-kv-effect-and-continuation',
|
|
356
|
+
redaction: 'key-generation-value-required', status: 'supported'
|
|
357
|
+
})),
|
|
351
358
|
surface({
|
|
352
359
|
id: 'ctx.emit',
|
|
353
360
|
class: 'effect',
|
|
@@ -13,6 +13,7 @@ const CANONICAL_PROVIDER_CAPABILITIES = Object.freeze([
|
|
|
13
13
|
'secret.get',
|
|
14
14
|
'kv.get',
|
|
15
15
|
'kv.put',
|
|
16
|
+
'kv.getVersioned', 'kv.insertIfAbsent', 'kv.compareAndSwap',
|
|
16
17
|
'event.ingress',
|
|
17
18
|
'event.emit',
|
|
18
19
|
'assets.lookup',
|
|
@@ -21,6 +22,9 @@ const CANONICAL_PROVIDER_CAPABILITIES = Object.freeze([
|
|
|
21
22
|
'grip.publish',
|
|
22
23
|
'grip.broadcast',
|
|
23
24
|
'jwt.verify',
|
|
25
|
+
's3.head',
|
|
26
|
+
's3.getText',
|
|
27
|
+
's3.putText',
|
|
24
28
|
'opaque.pass-through'
|
|
25
29
|
]);
|
|
26
30
|
|
|
@@ -51,6 +51,7 @@ const DRIVER_FIELDS = Object.freeze([
|
|
|
51
51
|
'events',
|
|
52
52
|
'targets',
|
|
53
53
|
'execute',
|
|
54
|
+
'prepareNativeExecution',
|
|
54
55
|
'createLoweringPlan',
|
|
55
56
|
'inspectRealization',
|
|
56
57
|
'writeTarget',
|
|
@@ -366,6 +367,9 @@ function defineProviderDriver(input, expected = {}) {
|
|
|
366
367
|
if ((targets.native && (targets.native.commands.test || targets.native.commands.dev)) && typeof input.execute !== 'function') {
|
|
367
368
|
throw new TypeError(`Pulse provider driver ${id} is missing execute().`);
|
|
368
369
|
}
|
|
370
|
+
if (input.prepareNativeExecution !== undefined && typeof input.prepareNativeExecution !== 'function') {
|
|
371
|
+
throw new TypeError(`Pulse provider driver ${id} prepareNativeExecution must be a function.`);
|
|
372
|
+
}
|
|
369
373
|
const descriptor = input.descriptor === undefined ? undefined : normalizeDescriptor(input.descriptor);
|
|
370
374
|
if (descriptor && descriptor.id !== id) throw new TypeError(`Pulse provider driver ${id} descriptor identity does not match.`);
|
|
371
375
|
const javascript = normalizeJavascriptDriver(input.javascript, targets.javascript);
|
|
@@ -392,6 +396,7 @@ function defineProviderDriver(input, expected = {}) {
|
|
|
392
396
|
events,
|
|
393
397
|
targets,
|
|
394
398
|
execute: input.execute,
|
|
399
|
+
prepareNativeExecution: input.prepareNativeExecution,
|
|
395
400
|
createLoweringPlan: input.createLoweringPlan,
|
|
396
401
|
inspectRealization: input.inspectRealization,
|
|
397
402
|
writeTarget: input.writeTarget,
|
|
@@ -622,7 +627,7 @@ function createProviderTargetInvocation(input) {
|
|
|
622
627
|
throw new TypeError(`Pulse provider target invocation version must be ${PROVIDER_TARGET_INVOCATION_VERSION}.`);
|
|
623
628
|
}
|
|
624
629
|
const action = nonEmpty(input.action, 'invocation action');
|
|
625
|
-
if (!['inspect-native', 'write-native', 'write-javascript'].includes(action)) {
|
|
630
|
+
if (!['inspect-native', 'write-native', 'write-javascript', 'execute-native'].includes(action)) {
|
|
626
631
|
throw new TypeError(`Pulse provider target invocation action ${action} is unsupported.`);
|
|
627
632
|
}
|
|
628
633
|
const target = action.endsWith('javascript') ? 'javascript' : 'native';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const S3_CONTRACT_ID = 'pulse.s3';
|
|
4
|
+
const S3_PACKAGE = '@pulse-compute/s3';
|
|
5
|
+
const S3_LOWERING_PLAN_VERSION = 'pulse.s3-lowering-plan.v1';
|
|
6
|
+
const S3_LIMITS = Object.freeze({ keyBytes: 1024, textBytes: 32768, metadataBytes: 1024, headerBytes: 16384, envelopeBytes: 262144 });
|
|
7
|
+
const S3_OPERATIONS = Object.freeze(Object.fromEntries(['head', 'getText', 'putText'].map((name) => [name, Object.freeze({
|
|
8
|
+
kind: `s3.${name}`, capability: `s3.${name}`, result: name === 'head' ? 's3-head-result' : name === 'getText' ? 's3-get-text-result' : 's3-put-text-result'
|
|
9
|
+
})])));
|
|
10
|
+
const S3_PROVIDER_REQUIREMENTS = Object.freeze(['s3.head', 's3.getText', 's3.putText', 'secret.get', 'time.wall-clock']);
|
|
11
|
+
const S3_CRYPTO_ALGORITHMS = Object.freeze(['SHA-256', 'HMAC-SHA256']);
|
|
12
|
+
module.exports = Object.freeze({ S3_CONTRACT_ID, S3_PACKAGE, S3_LOWERING_PLAN_VERSION, S3_LIMITS, S3_OPERATIONS, S3_PROVIDER_REQUIREMENTS, S3_CRYPTO_ALGORITHMS });
|