@pulse-compute/wasm-guest-link 1.0.0-beta.4 → 1.0.0-beta.6
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 +2 -2
- package/package.json +3 -3
- package/src/constants.js +36 -9
- package/src/contracts.js +19 -20
- package/src/materialize.js +6 -6
- package/src/pipeline.js +1 -1
- package/src/stage.js +2 -2
package/README.md
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
> **Supported entry points:** `None for application authors.`<br>
|
|
8
8
|
> **Stability:** Internal first-party prebuilt guest-link interface synchronized with the compiler; no application-author or third-party guest compatibility guarantee.<br>
|
|
9
9
|
> **npm:** [`@pulse-compute/wasm-guest-link`](https://www.npmjs.com/package/@pulse-compute/wasm-guest-link)<br>
|
|
10
|
-
> **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.
|
|
10
|
+
> **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.6/packages/implementation-packages/)
|
|
11
11
|
>
|
|
12
|
-
> 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.6` package policy.
|
|
13
13
|
<!-- pulse-package-status:end -->
|
|
14
14
|
|
|
15
15
|
Internal Pulse implementation package for connecting validated first-party core
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pulse-compute/wasm-guest-link",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.6",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Internal first-party guest-unit validation, materialization, core Wasm composition, optimization, and final audit for Pulse.",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"./toolchain": "./src/toolchain.js"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@pulse-compute/wasm-contracts": "1.0.0-beta.
|
|
17
|
+
"@pulse-compute/wasm-contracts": "1.0.0-beta.6",
|
|
18
18
|
"binaryen": "129.0.0-nightly.20260428"
|
|
19
19
|
},
|
|
20
20
|
"publishConfig": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"url": "git+https://github.com/pulse-compute/pulse.git",
|
|
32
32
|
"directory": "wasm/packages/wasm-guest-link"
|
|
33
33
|
},
|
|
34
|
-
"homepage": "https://pulsecompute.io/v1.0.0-beta.
|
|
34
|
+
"homepage": "https://pulsecompute.io/v1.0.0-beta.6/packages/implementation-packages/",
|
|
35
35
|
"bugs": {
|
|
36
36
|
"url": "https://github.com/pulse-compute/pulse/issues"
|
|
37
37
|
}
|
package/src/constants.js
CHANGED
|
@@ -99,27 +99,28 @@ const es256GuestUnit = Object.freeze({
|
|
|
99
99
|
id: 'pulse.crypto.es256.rustcrypto-p256.v1',
|
|
100
100
|
module: 'pulse_crypto_es256',
|
|
101
101
|
owner: '@pulse-compute/crypto',
|
|
102
|
-
packageVersion: '1.0.0-beta.
|
|
103
|
-
abi: 'pulse.crypto.es256.verify.
|
|
102
|
+
packageVersion: '1.0.0-beta.6',
|
|
103
|
+
abi: 'pulse.crypto.es256-rs256.verify-and-sign.v3',
|
|
104
104
|
artifact: Object.freeze({
|
|
105
105
|
file: 'prebuilt/es256-verifier.wasm',
|
|
106
|
-
bytes:
|
|
107
|
-
sha256: '
|
|
106
|
+
bytes: 36378,
|
|
107
|
+
sha256: 'b1d09f10fddf7587cb9e87f959fa908457e076e207db078fc101390c70e4aecf'
|
|
108
108
|
}),
|
|
109
109
|
source: Object.freeze({
|
|
110
110
|
directory: 'source',
|
|
111
|
-
treeSha256: '
|
|
111
|
+
treeSha256: '581fa765f228bd1a3ab6a40ee3cbb35a9d7a101e2839d32e36ececc94b66a741'
|
|
112
112
|
}),
|
|
113
113
|
toolchain: Object.freeze({
|
|
114
114
|
rustc: '1.97.1 (8bab26f4f 2026-07-14)',
|
|
115
115
|
cargo: '1.97.1 (c980f4866 2026-06-30)',
|
|
116
|
+
zig: '0.13.0',
|
|
116
117
|
binaryen: binaryenVersion
|
|
117
118
|
}),
|
|
118
119
|
provenance: Object.freeze({
|
|
119
|
-
cargoLockSha256: '
|
|
120
|
-
reconstructionCommandIdentity: 'pulse.crypto.es256.
|
|
120
|
+
cargoLockSha256: 'd5ecc12c9c846468686974aaed841156cc82ab8f876fec4d40b2baa29dff1551',
|
|
121
|
+
reconstructionCommandIdentity: 'pulse.crypto.es256-rs256.build.v3',
|
|
121
122
|
buildScript: 'build.cjs',
|
|
122
|
-
buildScriptSha256: '
|
|
123
|
+
buildScriptSha256: '85d99761b442ec3ea11af6496206f475c14e6c419b5aa89bbedc730d8b61e95d',
|
|
123
124
|
optimizationPosture: 'native-size',
|
|
124
125
|
binaryenWasmOptSha256: '1304eb38ad315a0d70d8427757f641c110d972468c126af645ef800b09c26e56',
|
|
125
126
|
g0SourceDecision: '../../../../wasm/.test-results/jwt-g0/es256-source-decision.json',
|
|
@@ -147,6 +148,31 @@ const optimizationPostures = Object.freeze({
|
|
|
147
148
|
])
|
|
148
149
|
});
|
|
149
150
|
|
|
151
|
+
// Keep the pinned prebuilt recipe above unchanged. Composed final modules use
|
|
152
|
+
// these bounded, layout-preserving passes before the existing final audit.
|
|
153
|
+
const finalOptimizationPostures = Object.freeze({
|
|
154
|
+
'native-default': Object.freeze([
|
|
155
|
+
'--mvp-features',
|
|
156
|
+
'--merge-similar-functions',
|
|
157
|
+
'--one-caller-inline-max-function-size=64',
|
|
158
|
+
'--flexible-inline-max-function-size=0',
|
|
159
|
+
'--inline-max-combined-binary-size=1024',
|
|
160
|
+
'-Oz',
|
|
161
|
+
'--skip-pass=memory-packing',
|
|
162
|
+
'--strip-debug'
|
|
163
|
+
]),
|
|
164
|
+
'native-size': Object.freeze([
|
|
165
|
+
'--mvp-features',
|
|
166
|
+
'--merge-similar-functions',
|
|
167
|
+
'--one-caller-inline-max-function-size=64',
|
|
168
|
+
'--flexible-inline-max-function-size=0',
|
|
169
|
+
'--inline-max-combined-binary-size=1024',
|
|
170
|
+
'-Oz',
|
|
171
|
+
'--skip-pass=memory-packing',
|
|
172
|
+
'--strip-debug'
|
|
173
|
+
])
|
|
174
|
+
});
|
|
175
|
+
|
|
150
176
|
module.exports = Object.freeze({
|
|
151
177
|
versions,
|
|
152
178
|
binaryenVersion,
|
|
@@ -155,5 +181,6 @@ module.exports = Object.freeze({
|
|
|
155
181
|
memoryAbiV2,
|
|
156
182
|
es256FrameV2,
|
|
157
183
|
es256GuestUnit,
|
|
158
|
-
optimizationPostures
|
|
184
|
+
optimizationPostures,
|
|
185
|
+
finalOptimizationPostures
|
|
159
186
|
});
|
package/src/contracts.js
CHANGED
|
@@ -8,7 +8,7 @@ const {
|
|
|
8
8
|
memoryAbiV2,
|
|
9
9
|
es256FrameV2,
|
|
10
10
|
es256GuestUnit,
|
|
11
|
-
|
|
11
|
+
finalOptimizationPostures
|
|
12
12
|
} = require('./constants.js');
|
|
13
13
|
const { fail } = require('./errors.js');
|
|
14
14
|
const { assertRelativePath } = require('./files.js');
|
|
@@ -198,7 +198,12 @@ function manifestRelativePath(value, field) {
|
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
function exactValue(value, expected, field, code = diagnosticCodes.invalid) {
|
|
201
|
-
|
|
201
|
+
// JSON object member order is not part of the contract. The compiler writes
|
|
202
|
+
// sorted artifact JSON; retain array order and exact values when reloading it.
|
|
203
|
+
const canonical = item => JSON.stringify(item, (_key, nested) => plainObject(nested)
|
|
204
|
+
? Object.fromEntries(Object.keys(nested).sort().map(key => [key, nested[key]]))
|
|
205
|
+
: nested);
|
|
206
|
+
if (canonical(value) !== canonical(expected)) {
|
|
202
207
|
fail(code, `${field} does not match the reviewed ES256 guest contract.`, { expected, actual: value });
|
|
203
208
|
}
|
|
204
209
|
return value;
|
|
@@ -409,7 +414,7 @@ function normalizeGuestUnitManifestV2(input) {
|
|
|
409
414
|
);
|
|
410
415
|
|
|
411
416
|
exactKeys(input.toolchain, ['kind', 'target', 'locked', 'versions'], [], 'guest unit v2 toolchain');
|
|
412
|
-
exactKeys(input.toolchain.versions, ['rustc', 'cargo', 'binaryen'], [], 'guest unit v2 toolchain.versions');
|
|
417
|
+
exactKeys(input.toolchain.versions, ['rustc', 'cargo', 'zig', 'binaryen'], [], 'guest unit v2 toolchain.versions');
|
|
413
418
|
const toolchain = Object.freeze({
|
|
414
419
|
kind: string(input.toolchain.kind, 'guest unit v2 toolchain.kind'),
|
|
415
420
|
target: string(input.toolchain.target, 'guest unit v2 toolchain.target'),
|
|
@@ -417,6 +422,7 @@ function normalizeGuestUnitManifestV2(input) {
|
|
|
417
422
|
versions: Object.freeze({
|
|
418
423
|
rustc: string(input.toolchain.versions.rustc, 'guest unit v2 rustc version'),
|
|
419
424
|
cargo: string(input.toolchain.versions.cargo, 'guest unit v2 cargo version'),
|
|
425
|
+
zig: string(input.toolchain.versions.zig, 'guest unit v2 Zig version'),
|
|
420
426
|
binaryen: string(input.toolchain.versions.binaryen, 'guest unit v2 Binaryen version')
|
|
421
427
|
})
|
|
422
428
|
});
|
|
@@ -449,17 +455,10 @@ function normalizeGuestUnitManifestV2(input) {
|
|
|
449
455
|
})
|
|
450
456
|
})]);
|
|
451
457
|
exactValue(imports, expectedImports, 'guest unit v2 imports', diagnosticCodes.importMismatch);
|
|
452
|
-
const expectedExports = Object.freeze([Object.freeze({
|
|
453
|
-
name: es256FrameV2.
|
|
454
|
-
|
|
455
|
-
parameters: es256FrameV2.parameters,
|
|
456
|
-
results: es256FrameV2.results,
|
|
457
|
-
role: 'abi'
|
|
458
|
-
})]);
|
|
458
|
+
const expectedExports = Object.freeze(['pulse_crypto_es256_sign', 'pulse_crypto_es256_verify', 'pulse_crypto_rs256_sign', 'pulse_crypto_rs256_verify'].map(name => Object.freeze({
|
|
459
|
+
name, kind: 'function', parameters: es256FrameV2.parameters, results: es256FrameV2.results, role: 'abi'
|
|
460
|
+
})));
|
|
459
461
|
exactValue(exports, expectedExports, 'guest unit v2 exports', diagnosticCodes.exportMismatch);
|
|
460
|
-
if (exports.filter((entry) => entry.role === 'abi').length !== 1) {
|
|
461
|
-
fail(diagnosticCodes.abiMismatch, 'Guest unit v2 must declare exactly one ABI function export.');
|
|
462
|
-
}
|
|
463
462
|
|
|
464
463
|
exactKeys(input.memory, ['identity', 'import', 'owner'], [], 'guest unit v2 memory');
|
|
465
464
|
exactValue(input.memory, {
|
|
@@ -715,10 +714,10 @@ function normalizeGuestUnitPlanV1(input) {
|
|
|
715
714
|
const directory = assertRelativePath(input.materialization.directory, 'guest unit plan materialization.directory');
|
|
716
715
|
if (
|
|
717
716
|
workspace !== '.pulse/guests'
|
|
718
|
-
|| directory !== `${workspace}/${unit.id}/${unit.artifactSha256}`
|
|
717
|
+
|| directory !== `${workspace}/${unit.id}/${unit.artifactSha256}/${unit.manifestSha256}`
|
|
719
718
|
|| input.materialization.artifact !== 'unit.wasm'
|
|
720
719
|
|| input.materialization.manifest !== 'unit.json'
|
|
721
|
-
|| input.materialization.contentAddress !== 'artifact-sha256'
|
|
720
|
+
|| input.materialization.contentAddress !== 'artifact-and-manifest-sha256'
|
|
722
721
|
|| input.materialization.generated !== true
|
|
723
722
|
|| input.materialization.authoritative !== false
|
|
724
723
|
) {
|
|
@@ -762,7 +761,7 @@ function normalizeGuestUnitPlanV1(input) {
|
|
|
762
761
|
directory,
|
|
763
762
|
artifact: 'unit.wasm',
|
|
764
763
|
manifest: 'unit.json',
|
|
765
|
-
contentAddress: 'artifact-sha256',
|
|
764
|
+
contentAddress: 'artifact-and-manifest-sha256',
|
|
766
765
|
generated: true,
|
|
767
766
|
authoritative: false
|
|
768
767
|
}),
|
|
@@ -921,10 +920,10 @@ function normalizeGuestUnitPlanV2(input) {
|
|
|
921
920
|
);
|
|
922
921
|
if (
|
|
923
922
|
workspace !== '.pulse/guests'
|
|
924
|
-
|| directory !== `${workspace}/${unit.id}/${unit.artifact.sha256}`
|
|
923
|
+
|| directory !== `${workspace}/${unit.id}/${unit.artifact.sha256}/${unit.manifestSha256}`
|
|
925
924
|
|| input.materialization.artifact !== 'unit.wasm'
|
|
926
925
|
|| input.materialization.manifest !== 'unit.json'
|
|
927
|
-
|| input.materialization.contentAddress !== 'artifact-sha256'
|
|
926
|
+
|| input.materialization.contentAddress !== 'artifact-and-manifest-sha256'
|
|
928
927
|
|| input.materialization.generated !== true
|
|
929
928
|
|| input.materialization.authoritative !== false
|
|
930
929
|
) {
|
|
@@ -1003,7 +1002,7 @@ function normalizeGuestUnitPlanV2(input) {
|
|
|
1003
1002
|
directory,
|
|
1004
1003
|
artifact: 'unit.wasm',
|
|
1005
1004
|
manifest: 'unit.json',
|
|
1006
|
-
contentAddress: 'artifact-sha256',
|
|
1005
|
+
contentAddress: 'artifact-and-manifest-sha256',
|
|
1007
1006
|
generated: true,
|
|
1008
1007
|
authoritative: false
|
|
1009
1008
|
}),
|
|
@@ -1128,7 +1127,7 @@ function assertPlanMatchesManifest(plan, manifest) {
|
|
|
1128
1127
|
}
|
|
1129
1128
|
|
|
1130
1129
|
function optimizationArguments(posture) {
|
|
1131
|
-
const args =
|
|
1130
|
+
const args = finalOptimizationPostures[posture];
|
|
1132
1131
|
if (!args) fail(diagnosticCodes.optimizationFailed, `Unsupported guest-link optimization posture ${posture}.`);
|
|
1133
1132
|
return args;
|
|
1134
1133
|
}
|
package/src/materialize.js
CHANGED
|
@@ -127,12 +127,12 @@ function assertGuestBinary(manifest, inspection) {
|
|
|
127
127
|
type: 'i32',
|
|
128
128
|
initializer: { instruction: 'i32.const', value: contract.layout.rustStack.endExclusive }
|
|
129
129
|
})
|
|
130
|
-
|| inspection.instructions.globalSet !==
|
|
131
|
-
|| inspection.instructions.store !==
|
|
130
|
+
|| inspection.instructions.globalSet !== 104
|
|
131
|
+
|| inspection.instructions.store !== 823
|
|
132
132
|
) {
|
|
133
133
|
fail(
|
|
134
134
|
diagnosticCodes.memoryMismatch,
|
|
135
|
-
`Guest unit ${manifest.id} binary does not match the reviewed stack
|
|
135
|
+
`Guest unit ${manifest.id} binary does not match the reviewed stack and bounded-signature-output posture.`
|
|
136
136
|
);
|
|
137
137
|
}
|
|
138
138
|
}
|
|
@@ -156,9 +156,9 @@ function assertGuestBinary(manifest, inspection) {
|
|
|
156
156
|
}))) !== JSON.stringify([{
|
|
157
157
|
memoryIndex: 0,
|
|
158
158
|
offset: 131072,
|
|
159
|
-
endExclusive:
|
|
160
|
-
bytes:
|
|
161
|
-
sha256: '
|
|
159
|
+
endExclusive: 131722,
|
|
160
|
+
bytes: 650,
|
|
161
|
+
sha256: 'a33fcc685d2bb0bbbaa4678207d5c4ab2698f41ed7694be4fe0ba590e93d98ce'
|
|
162
162
|
}])
|
|
163
163
|
) {
|
|
164
164
|
fail(diagnosticCodes.memoryMismatch, `Guest unit ${manifest.id} static data does not match the reviewed layout.`);
|
package/src/pipeline.js
CHANGED
|
@@ -208,7 +208,7 @@ function assertPrimaryAndOwner(plan, manifest, primary, owner) {
|
|
|
208
208
|
kind: entry.kind,
|
|
209
209
|
type: { parameters: entry.parameters, results: entry.results }
|
|
210
210
|
}));
|
|
211
|
-
if (!equal(guestImports.map(surfaceImport), expectedGuestImports)) {
|
|
211
|
+
if (!equal(sortedSurface(guestImports.map(surfaceImport)), sortedSurface(expectedGuestImports))) {
|
|
212
212
|
fail(diagnosticCodes.abiMismatch, 'Primary guest imports do not exactly match the selected guest ABI.');
|
|
213
213
|
}
|
|
214
214
|
const memoryImports = primary.imports.filter((entry) => entry.kind === 'memory');
|
package/src/stage.js
CHANGED
|
@@ -364,10 +364,10 @@ function makeGuestUnitPlan(selection, resolved, facts, primaryBytes) {
|
|
|
364
364
|
targetPolicy,
|
|
365
365
|
materialization: {
|
|
366
366
|
workspace: '.pulse/guests',
|
|
367
|
-
directory: `.pulse/guests/${manifest.id}/${manifest.artifact.sha256}`,
|
|
367
|
+
directory: `.pulse/guests/${manifest.id}/${manifest.artifact.sha256}/${resolved.manifestSha256}`,
|
|
368
368
|
artifact: 'unit.wasm',
|
|
369
369
|
manifest: 'unit.json',
|
|
370
|
-
contentAddress: 'artifact-sha256',
|
|
370
|
+
contentAddress: 'artifact-and-manifest-sha256',
|
|
371
371
|
generated: true,
|
|
372
372
|
authoritative: false
|
|
373
373
|
},
|