@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,149 @@
1
+ # MCP-shaped HTTP proxy
2
+
3
+ Forwards one JSON-RPC-shaped HTTP request to an upstream endpoint and returns
4
+ the upstream response without inspecting it. This is intentionally not a full
5
+ MCP server: it has no SSE, sessions, discovery, tools catalog, authorization,
6
+ or protocol lifecycle state.
7
+
8
+ Pulse does not expose an opaque incoming-body handle. The request body crosses
9
+ one bounded `ctx.req.text()` materialization seam before the outbound POST. The
10
+ upstream response remains provider-owned and opaque.
11
+
12
+ ## Workflow
13
+
14
+ ```bash
15
+ pulse doctor
16
+ pulse inspect
17
+ pulse test
18
+ pulse dev
19
+ pulse build
20
+ ```
21
+
22
+ The documented test result below is executed by the documentation gate.
23
+
24
+ <!-- pulse-doc-run {"project":"examples/12-mcp-proxy","args":["test","--json"]} -->
25
+ ```bash
26
+ pulse test --json
27
+ ```
28
+ ```json
29
+ {
30
+ "status": "passed",
31
+ "provider": "node",
32
+ "summary": {
33
+ "total": 1,
34
+ "passed": 1,
35
+ "failed": 0
36
+ },
37
+ "cases": [
38
+ {
39
+ "name": "json-rpc-pass-through",
40
+ "status": "passed",
41
+ "response": {
42
+ "status": 200
43
+ }
44
+ }
45
+ ]
46
+ }
47
+ ```
48
+
49
+ ## Wasm size
50
+
51
+ | Artifact | Default build | `--experimental-native-size` | Reduction |
52
+ |---|---:|---:|---:|
53
+ | `canonical-native.wasm` | 2.5 KiB (2,589 bytes) | 2.4 KiB (2,418 bytes) | 6.6% |
54
+
55
+ The executable documentation gate rebuilds and measures both variants on
56
+ `1.0.0-beta.1`. These are uncompressed on-disk sizes, not transfer sizes or
57
+ platform limits.
58
+
59
+ ## Handler
60
+
61
+ <!-- pulse-doc-source: examples/12-mcp-proxy/src/index.ts -->
62
+ ```ts
63
+ import { Pulse } from '@pulse-compute/pulse'
64
+
65
+ const app = new Pulse({ auto: true })
66
+
67
+ app.post('/mcp', async (ctx) => {
68
+ const body = await ctx.req.text()
69
+ return ctx.fetch('https://mcp.example.test/rpc', {
70
+ method: 'POST',
71
+ headers: {
72
+ accept: 'application/json',
73
+ 'content-type': 'application/json',
74
+ },
75
+ body,
76
+ })
77
+ })
78
+
79
+ export default app
80
+ ```
81
+ <!-- /pulse-doc-source -->
82
+
83
+ ## Project config
84
+
85
+ <!-- pulse-doc-source: examples/12-mcp-proxy/.pulse/config.ts -->
86
+ ```ts
87
+ import { defineConfig } from '@pulse-compute/pulse'
88
+
89
+ export default defineConfig((_scope) => ({
90
+ pulse: {
91
+ entry: 'src/index.ts',
92
+ tests: 'tests/pulse.harness.ts',
93
+ defaultProfile: 'local',
94
+ strict: true,
95
+ },
96
+ local: {
97
+ host: 'node',
98
+ target: 'native',
99
+ outDir: 'dist',
100
+ dev: {
101
+ fetches: {
102
+ 'POST https://mcp.example.test/rpc': {
103
+ opaque: true,
104
+ status: 200,
105
+ headers: [['content-type', 'application/json']],
106
+ chunks: ['{"jsonrpc":"2.0","result":{},"id":1}'],
107
+ },
108
+ },
109
+ },
110
+ },
111
+ }))
112
+ ```
113
+ <!-- /pulse-doc-source -->
114
+
115
+ ## Test harness
116
+
117
+ <!-- pulse-doc-source: examples/12-mcp-proxy/tests/pulse.harness.ts -->
118
+ ```ts
119
+ export default {
120
+ cases: [
121
+ {
122
+ name: 'json-rpc-pass-through',
123
+ request: {
124
+ method: 'POST',
125
+ path: '/mcp',
126
+ headers: { 'content-type': 'application/json' },
127
+ body: JSON.stringify({
128
+ jsonrpc: '2.0',
129
+ method: 'tools/list',
130
+ id: 1,
131
+ }),
132
+ },
133
+ fetches: {
134
+ 'POST https://mcp.example.test/rpc': {
135
+ opaque: true,
136
+ status: 200,
137
+ headers: [['content-type', 'application/json']],
138
+ chunks: ['{"jsonrpc":"2.0","result":{},"id":1}'],
139
+ },
140
+ },
141
+ expect: {
142
+ status: 200,
143
+ bodyClass: 'opaque',
144
+ },
145
+ },
146
+ ],
147
+ }
148
+ ```
149
+ <!-- /pulse-doc-source -->
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@pulse-examples/12-mcp-proxy",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "doctor": "pulse doctor",
8
+ "inspect": "pulse inspect",
9
+ "test": "pulse test",
10
+ "dev": "pulse dev",
11
+ "build": "pulse build"
12
+ },
13
+ "dependencies": {
14
+ "@pulse-compute/pulse": "1.0.0-beta.1"
15
+ },
16
+ "devDependencies": {
17
+ "@pulse-compute/cli": "1.0.0-beta.1",
18
+ "typescript": "5.9.3"
19
+ }
20
+ }
@@ -0,0 +1,17 @@
1
+ import { Pulse } from '@pulse-compute/pulse'
2
+
3
+ const app = new Pulse({ auto: true })
4
+
5
+ app.post('/mcp', async (ctx) => {
6
+ const body = await ctx.req.text()
7
+ return ctx.fetch('https://mcp.example.test/rpc', {
8
+ method: 'POST',
9
+ headers: {
10
+ accept: 'application/json',
11
+ 'content-type': 'application/json',
12
+ },
13
+ body,
14
+ })
15
+ })
16
+
17
+ export default app
@@ -0,0 +1,29 @@
1
+ export default {
2
+ cases: [
3
+ {
4
+ name: 'json-rpc-pass-through',
5
+ request: {
6
+ method: 'POST',
7
+ path: '/mcp',
8
+ headers: { 'content-type': 'application/json' },
9
+ body: JSON.stringify({
10
+ jsonrpc: '2.0',
11
+ method: 'tools/list',
12
+ id: 1,
13
+ }),
14
+ },
15
+ fetches: {
16
+ 'POST https://mcp.example.test/rpc': {
17
+ opaque: true,
18
+ status: 200,
19
+ headers: [['content-type', 'application/json']],
20
+ chunks: ['{"jsonrpc":"2.0","result":{},"id":1}'],
21
+ },
22
+ },
23
+ expect: {
24
+ status: 200,
25
+ bodyClass: 'opaque',
26
+ },
27
+ },
28
+ ],
29
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "noEmit": true
8
+ },
9
+ "include": [
10
+ "src/**/*.ts",
11
+ ".pulse/**/*.ts",
12
+ "tests/**/*.ts"
13
+ ]
14
+ }
@@ -0,0 +1,19 @@
1
+ import { defineConfig } from '@pulse-compute/pulse'
2
+
3
+ export default defineConfig((_scope) => ({
4
+ pulse: {
5
+ entry: 'src/index.ts',
6
+ tests: 'tests/pulse.harness.ts',
7
+ defaultProfile: 'node-native',
8
+ strict: true,
9
+ },
10
+ 'node-native': {
11
+ host: 'node',
12
+ target: 'native',
13
+ outDir: 'dist-node-native',
14
+ crypto: {
15
+ ES256: { realization: 'guest-linked:pulse-es256-rustcrypto-p256' },
16
+ },
17
+ dev: { host: '127.0.0.1', port: 8787, networkFetch: false },
18
+ },
19
+ }))
@@ -0,0 +1,195 @@
1
+ # ES256 bearer verification
2
+
3
+ This Node example verifies one bearer JWT with an inline public P-256 JWK.
4
+ The Native profile links the released RustCrypto verifier explicitly and does
5
+ not probe for a fallback realization.
6
+
7
+ The deterministic harness covers a valid token, a one-byte signature mutation,
8
+ and a token whose declared algorithm is outside the allowlist. The fixture
9
+ contains only a public verification key; no private signing material is part of
10
+ the application or build output.
11
+
12
+ ## Workflow
13
+
14
+ ```bash
15
+ pulse doctor
16
+ pulse inspect
17
+ pulse test
18
+ pulse dev
19
+ pulse build
20
+ ```
21
+
22
+ The documented result below is executed against the exact linked Native
23
+ artifact by the documentation gate.
24
+
25
+ <!-- pulse-doc-run {"project":"examples/13-jwt-es256","args":["test","--json"],"timeoutMs":240000} -->
26
+ ```bash
27
+ pulse test --json
28
+ ```
29
+ ```json
30
+ {
31
+ "status": "passed",
32
+ "provider": "node",
33
+ "summary": {
34
+ "total": 3,
35
+ "passed": 3,
36
+ "failed": 0
37
+ },
38
+ "cases": [
39
+ {
40
+ "name": "valid ES256 bearer",
41
+ "status": "passed",
42
+ "response": {
43
+ "status": 200
44
+ }
45
+ },
46
+ {
47
+ "name": "wrong ES256 signature",
48
+ "status": "passed",
49
+ "expectedError": {
50
+ "code": "PULSE_JWT_SIGNATURE_INVALID"
51
+ }
52
+ },
53
+ {
54
+ "name": "disallowed algorithm",
55
+ "status": "passed",
56
+ "expectedError": {
57
+ "code": "PULSE_JWT_ALGORITHM_NOT_ALLOWED"
58
+ }
59
+ }
60
+ ]
61
+ }
62
+ ```
63
+
64
+ ## Wasm size
65
+
66
+ | Artifact | Default build | `--experimental-native-size` | Reduction |
67
+ |---|---:|---:|---:|
68
+ | Application input | 2.7 KiB (2,759 bytes) | 2.5 KiB (2,577 bytes) | 6.6% |
69
+ | ES256 guest input | 20.5 KiB (21,009 bytes) | 20.5 KiB (21,009 bytes) | 0.0% |
70
+ | Final linked `canonical-native.wasm` | 23.1 KiB (23,647 bytes) | 22.9 KiB (23,461 bytes) | 0.8% |
71
+
72
+ The executable documentation gate rebuilds and measures both variants on
73
+ `1.0.0-beta.1`. These are uncompressed on-disk sizes, not transfer sizes or
74
+ platform limits. The first two rows are the exact primary and guest inputs
75
+ recorded by `guest-link-report.json`; the last row is the validated output of
76
+ the deterministic static link. Linked output is not the arithmetic sum of its
77
+ inputs because the linker composes and deduplicates the modules.
78
+
79
+ ## Application
80
+
81
+ <!-- pulse-doc-source: examples/13-jwt-es256/src/index.ts -->
82
+ ```ts
83
+ import { jwt } from '@pulse-compute/jwt'
84
+
85
+ export default async function handler(ctx) {
86
+ const verified = await jwt.verify(ctx, jwt.bearer(ctx.req), {
87
+ algorithms: ['ES256'],
88
+ key: {
89
+ type: 'jwk',
90
+ key: {
91
+ kty: 'EC',
92
+ crv: 'P-256',
93
+ x: 'YP7UuiVanTHJYet0xjVtaMBJuJI7Yfps5mliLmDyn7Y',
94
+ y: 'eQP-EAi4vJmkGunpVii8ZPLxsgwtfp9Rd6PClNRGIpk',
95
+ alg: 'ES256',
96
+ use: 'sig',
97
+ key_ops: ['verify'],
98
+ kid: 'g3-key',
99
+ },
100
+ },
101
+ })
102
+ return ctx.text(verified.claims.sub + ':' + verified.protectedHeader.alg)
103
+ }
104
+ ```
105
+ <!-- /pulse-doc-source -->
106
+
107
+ ## Project config
108
+
109
+ <!-- pulse-doc-source: examples/13-jwt-es256/.pulse/config.ts -->
110
+ ```ts
111
+ import { defineConfig } from '@pulse-compute/pulse'
112
+
113
+ export default defineConfig((_scope) => ({
114
+ pulse: {
115
+ entry: 'src/index.ts',
116
+ tests: 'tests/pulse.harness.ts',
117
+ defaultProfile: 'node-native',
118
+ strict: true,
119
+ },
120
+ 'node-native': {
121
+ host: 'node',
122
+ target: 'native',
123
+ outDir: 'dist-node-native',
124
+ crypto: {
125
+ ES256: { realization: 'guest-linked:pulse-es256-rustcrypto-p256' },
126
+ },
127
+ dev: { host: '127.0.0.1', port: 8787, networkFetch: false },
128
+ },
129
+ }))
130
+ ```
131
+ <!-- /pulse-doc-source -->
132
+
133
+ ## Test harness
134
+
135
+ <!-- pulse-doc-source: examples/13-jwt-es256/tests/pulse.harness.ts -->
136
+ ```ts
137
+ const valid =
138
+ 'eyJ0eXAiOiJKV1QiLCJraWQiOiJnMy1rZXkiLCJhbGciOiJFUzI1NiJ9.' +
139
+ 'eyJzdWIiOiJnMy1zZW5zaXRpdmUtc3ViamVjdCIsImlhdCI6MTk5OTk5OTk5MCwi' +
140
+ 'ZXhwIjoyMDAwMDAwMDYwLCJyb2xlcyI6WyJtZW1iZXIiXX0.' +
141
+ 'LgxFHy8spsAvPR5FgmnHS1MnVWEr7rAOVtS-PMSrwnabWfD3tEmOam2km7ZCLiX2' +
142
+ 'l2a_0ycVMIy6VMk95_ZOkQ'
143
+
144
+ const wrongSignature =
145
+ 'eyJ0eXAiOiJKV1QiLCJraWQiOiJnMy1rZXkiLCJhbGciOiJFUzI1NiJ9.' +
146
+ 'eyJzdWIiOiJnMy1zZW5zaXRpdmUtc3ViamVjdCIsImlhdCI6MTk5OTk5OTk5MCwi' +
147
+ 'ZXhwIjoyMDAwMDAwMDYwLCJyb2xlcyI6WyJtZW1iZXIiXX0.' +
148
+ 'rgxFHy8spsAvPR5FgmnHS1MnVWEr7rAOVtS-PMSrwnabWfD3tEmOam2km7ZCLiX2' +
149
+ 'l2a_0ycVMIy6VMk95_ZOkQ'
150
+
151
+ const disallowedAlgorithm =
152
+ 'eyJ0eXAiOiJKV1QiLCJraWQiOiJnMy1rZXkiLCJhbGciOiJIUzI1NiJ9.' +
153
+ 'eyJzdWIiOiJnMy1zZW5zaXRpdmUtc3ViamVjdCIsImlhdCI6MTk5OTk5OTk5MCwi' +
154
+ 'ZXhwIjoyMDAwMDAwMDYwLCJyb2xlcyI6WyJtZW1iZXIiXX0.' +
155
+ 'LgxFHy8spsAvPR5FgmnHS1MnVWEr7rAOVtS-PMSrwnabWfD3tEmOam2km7ZCLiX2' +
156
+ 'l2a_0ycVMIy6VMk95_ZOkQ'
157
+
158
+ function authorization(token: string) {
159
+ return { authorization: `Bearer ${token}` }
160
+ }
161
+
162
+ export default { cases: [
163
+ {
164
+ name: 'valid ES256 bearer',
165
+ request: { method: 'GET', path: '/verify', headers: authorization(valid) },
166
+ expect: { status: 200, text: 'g3-sensitive-subject:ES256' },
167
+ },
168
+ {
169
+ name: 'wrong ES256 signature',
170
+ request: {
171
+ method: 'GET',
172
+ path: '/verify',
173
+ headers: authorization(wrongSignature),
174
+ },
175
+ expect: {
176
+ error: { name: 'JwtError', code: 'PULSE_JWT_SIGNATURE_INVALID' },
177
+ },
178
+ },
179
+ {
180
+ name: 'disallowed algorithm',
181
+ request: {
182
+ method: 'GET',
183
+ path: '/verify',
184
+ headers: authorization(disallowedAlgorithm),
185
+ },
186
+ expect: {
187
+ error: { name: 'JwtError', code: 'PULSE_JWT_ALGORITHM_NOT_ALLOWED' },
188
+ },
189
+ },
190
+ ] }
191
+ ```
192
+ <!-- /pulse-doc-source -->
193
+
194
+ See [JWT](../../docs/packages/jwt.md) for the full verification policy and
195
+ supported key sources.
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@pulse-examples/13-jwt-es256",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "doctor": "pulse doctor",
8
+ "inspect": "pulse inspect",
9
+ "test": "pulse test",
10
+ "dev": "pulse dev",
11
+ "build": "pulse build"
12
+ },
13
+ "dependencies": {
14
+ "@pulse-compute/jwt": "1.0.0-beta.1",
15
+ "@pulse-compute/pulse": "1.0.0-beta.1"
16
+ },
17
+ "devDependencies": {
18
+ "@pulse-compute/cli": "1.0.0-beta.1",
19
+ "typescript": "5.9.3"
20
+ }
21
+ }
@@ -0,0 +1,21 @@
1
+ import { jwt } from '@pulse-compute/jwt'
2
+
3
+ export default async function handler(ctx) {
4
+ const verified = await jwt.verify(ctx, jwt.bearer(ctx.req), {
5
+ algorithms: ['ES256'],
6
+ key: {
7
+ type: 'jwk',
8
+ key: {
9
+ kty: 'EC',
10
+ crv: 'P-256',
11
+ x: 'YP7UuiVanTHJYet0xjVtaMBJuJI7Yfps5mliLmDyn7Y',
12
+ y: 'eQP-EAi4vJmkGunpVii8ZPLxsgwtfp9Rd6PClNRGIpk',
13
+ alg: 'ES256',
14
+ use: 'sig',
15
+ key_ops: ['verify'],
16
+ kid: 'g3-key',
17
+ },
18
+ },
19
+ })
20
+ return ctx.text(verified.claims.sub + ':' + verified.protectedHeader.alg)
21
+ }
@@ -0,0 +1,54 @@
1
+ const valid =
2
+ 'eyJ0eXAiOiJKV1QiLCJraWQiOiJnMy1rZXkiLCJhbGciOiJFUzI1NiJ9.' +
3
+ 'eyJzdWIiOiJnMy1zZW5zaXRpdmUtc3ViamVjdCIsImlhdCI6MTk5OTk5OTk5MCwi' +
4
+ 'ZXhwIjoyMDAwMDAwMDYwLCJyb2xlcyI6WyJtZW1iZXIiXX0.' +
5
+ 'LgxFHy8spsAvPR5FgmnHS1MnVWEr7rAOVtS-PMSrwnabWfD3tEmOam2km7ZCLiX2' +
6
+ 'l2a_0ycVMIy6VMk95_ZOkQ'
7
+
8
+ const wrongSignature =
9
+ 'eyJ0eXAiOiJKV1QiLCJraWQiOiJnMy1rZXkiLCJhbGciOiJFUzI1NiJ9.' +
10
+ 'eyJzdWIiOiJnMy1zZW5zaXRpdmUtc3ViamVjdCIsImlhdCI6MTk5OTk5OTk5MCwi' +
11
+ 'ZXhwIjoyMDAwMDAwMDYwLCJyb2xlcyI6WyJtZW1iZXIiXX0.' +
12
+ 'rgxFHy8spsAvPR5FgmnHS1MnVWEr7rAOVtS-PMSrwnabWfD3tEmOam2km7ZCLiX2' +
13
+ 'l2a_0ycVMIy6VMk95_ZOkQ'
14
+
15
+ const disallowedAlgorithm =
16
+ 'eyJ0eXAiOiJKV1QiLCJraWQiOiJnMy1rZXkiLCJhbGciOiJIUzI1NiJ9.' +
17
+ 'eyJzdWIiOiJnMy1zZW5zaXRpdmUtc3ViamVjdCIsImlhdCI6MTk5OTk5OTk5MCwi' +
18
+ 'ZXhwIjoyMDAwMDAwMDYwLCJyb2xlcyI6WyJtZW1iZXIiXX0.' +
19
+ 'LgxFHy8spsAvPR5FgmnHS1MnVWEr7rAOVtS-PMSrwnabWfD3tEmOam2km7ZCLiX2' +
20
+ 'l2a_0ycVMIy6VMk95_ZOkQ'
21
+
22
+ function authorization(token: string) {
23
+ return { authorization: `Bearer ${token}` }
24
+ }
25
+
26
+ export default { cases: [
27
+ {
28
+ name: 'valid ES256 bearer',
29
+ request: { method: 'GET', path: '/verify', headers: authorization(valid) },
30
+ expect: { status: 200, text: 'g3-sensitive-subject:ES256' },
31
+ },
32
+ {
33
+ name: 'wrong ES256 signature',
34
+ request: {
35
+ method: 'GET',
36
+ path: '/verify',
37
+ headers: authorization(wrongSignature),
38
+ },
39
+ expect: {
40
+ error: { name: 'JwtError', code: 'PULSE_JWT_SIGNATURE_INVALID' },
41
+ },
42
+ },
43
+ {
44
+ name: 'disallowed algorithm',
45
+ request: {
46
+ method: 'GET',
47
+ path: '/verify',
48
+ headers: authorization(disallowedAlgorithm),
49
+ },
50
+ expect: {
51
+ error: { name: 'JwtError', code: 'PULSE_JWT_ALGORITHM_NOT_ALLOWED' },
52
+ },
53
+ },
54
+ ] }
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "noEmit": true
8
+ },
9
+ "include": [
10
+ "src/**/*.ts",
11
+ ".pulse/**/*.ts",
12
+ "tests/**/*.ts"
13
+ ]
14
+ }
@@ -0,0 +1,36 @@
1
+ # Pulse canonical examples
2
+
3
+ These are complete canonical projects using the conventional
4
+ `.pulse/config.ts` workspace, dedicated deterministic test harnesses,
5
+ async-shaped managed handlers, and the same `pulse` commands as a user
6
+ application. Examples 01, 02, 03, 05, 07, 11, and 12 use the project-level
7
+ `@pulse-compute/pulse` application root. Example 09 retains
8
+ `@pulse-compute/runtime` and `Router` as the explicit low-level authoring path.
9
+ Example 10 uses `@pulse-compute/entities` with an external tools facade.
10
+
11
+ For every example except 10, enter the example directory and run:
12
+
13
+ ```bash
14
+ pulse doctor
15
+ pulse inspect
16
+ pulse test
17
+ pulse dev
18
+ pulse build
19
+ ```
20
+
21
+ From this source checkout, the equivalent root command is:
22
+
23
+ ```bash
24
+ pnpm pulse -- doctor examples/01-hello-json
25
+ ```
26
+
27
+ See [`../docs/examples.md`](../docs/examples.md) for the capability index.
28
+
29
+ Example 10 documents its focused entity workflow. Its gate executes
30
+ catalog discovery, governed JavaScript calls, and Native artifact compilation
31
+ without claiming that the ordinary project lifecycle integration is complete.
32
+ Example 11 runs mixed HTTP and event cases on Node JavaScript or Node Native.
33
+ Its development server remains HTTP-only; event input is available through the
34
+ bounded test/reference adapter rather than a public listener.
35
+ Example 12 is only an HTTP/JSON-RPC proxy shape: it does not claim MCP protocol
36
+ ownership, discovery, SSE, or session behavior.
package/package.json CHANGED
@@ -1,15 +1,75 @@
1
1
  {
2
2
  "name": "@pulse-compute/cli",
3
- "version": "0.0.0",
4
- "description": "Inert namespace bootstrap for Pulse.",
3
+ "version": "1.0.0-beta.1",
5
4
  "license": "Apache-2.0",
5
+ "description": "Pulse project CLI, configuration loader, and end-to-end workflow driver.",
6
+ "type": "commonjs",
7
+ "main": "./src/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./src/index.d.ts",
11
+ "require": "./src/index.js",
12
+ "default": "./src/index.js"
13
+ },
14
+ "./workflow": "./src/workflow.js",
15
+ "./project-config": "./src/project-config.js",
16
+ "./project-execution": "./src/project-execution.js",
17
+ "./diagnostics": "./src/diagnostics.js",
18
+ "./project-config-schema": {
19
+ "types": "./src/project-config-schema.d.ts",
20
+ "require": "./src/project-config-schema.js",
21
+ "default": "./src/project-config-schema.js"
22
+ },
23
+ "./project-config.schema.json": "./project-config.schema.json",
24
+ "./cli-spec.json": "./cli-spec.json",
25
+ "./release-manifest.json": "./release-manifest.json",
26
+ "./documentation-versions.json": "./documentation-versions.json",
27
+ "./documentation-site.json": "./documentation-site.json"
28
+ },
29
+ "dependencies": {
30
+ "@pulse-compute/wasm-build-support": "1.0.0-beta.1",
31
+ "@pulse-compute/wasm-compiler": "1.0.0-beta.1",
32
+ "@pulse-compute/wasm-contracts": "1.0.0-beta.1",
33
+ "@pulse-compute/wasm-host-runtime": "1.0.0-beta.1",
34
+ "@pulse-compute/wasm-schema-json": "1.0.0-beta.1",
35
+ "typescript": "5.9.3"
36
+ },
37
+ "bin": {
38
+ "pulsewasm-extract": "./bin/pulsewasm-extract.js",
39
+ "pulsewasm": "./bin/pulsewasm-extract.js",
40
+ "pulse": "./bin/pulse.js"
41
+ },
42
+ "types": "./src/index.d.ts",
43
+ "engines": {
44
+ "node": "^22.14.0 || ^24.0.0"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
6
49
  "files": [
50
+ "bin",
51
+ "src",
7
52
  "README.md",
53
+ "docs",
54
+ "examples",
55
+ "API.md",
56
+ "completions",
57
+ "cli-spec.json",
58
+ "project-config.schema.json",
59
+ "release-manifest.json",
60
+ "documentation-versions.json",
61
+ "documentation-site.json",
62
+ "CHANGELOG.md",
8
63
  "LICENSE",
9
64
  "NOTICE"
10
65
  ],
11
- "publishConfig": {
12
- "access": "public",
13
- "tag": "bootstrap"
66
+ "repository": {
67
+ "type": "git",
68
+ "url": "git+https://github.com/pulse-compute/pulse.git",
69
+ "directory": "wasm/packages/cli"
70
+ },
71
+ "homepage": "https://pulsecompute.io/v1.0.0-beta.1/packages/cli/",
72
+ "bugs": {
73
+ "url": "https://github.com/pulse-compute/pulse/issues"
14
74
  }
15
- }
75
+ }