@ai-switch/tauri-plugin-runtime 0.1.0

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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +327 -0
  3. package/THIRD_PARTY_NOTICES.md +210 -0
  4. package/dist/bridge/handshake.d.ts +11 -0
  5. package/dist/bridge/json-codec.d.ts +4 -0
  6. package/dist/bridge/rpc-peer.d.ts +7 -0
  7. package/dist/bridge/rpc-types.d.ts +20 -0
  8. package/dist/chunk-CFQSUF5W.js +1794 -0
  9. package/dist/chunk-JSBRDJBE.js +30 -0
  10. package/dist/chunk-K5YWIJN6.js +389 -0
  11. package/dist/chunk-PW7XHHWG.js +403 -0
  12. package/dist/chunk-RKQEK7DY.js +13879 -0
  13. package/dist/chunk-WT62GTMC.js +18 -0
  14. package/dist/chunk-YI6NQ6WR.js +513 -0
  15. package/dist/host/event-router.d.ts +19 -0
  16. package/dist/host/file-handles.d.ts +15 -0
  17. package/dist/host/host.d.ts +2 -0
  18. package/dist/host/index.d.ts +4 -0
  19. package/dist/host/index.js +791 -0
  20. package/dist/host/policy.d.ts +7 -0
  21. package/dist/host/requests.d.ts +13 -0
  22. package/dist/host/types.d.ts +19 -0
  23. package/dist/host/view.d.ts +18 -0
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.js +9 -0
  26. package/dist/node/buffer.d.ts +7 -0
  27. package/dist/node/buffer.js +8 -0
  28. package/dist/node/events.d.ts +12 -0
  29. package/dist/node/events.js +458 -0
  30. package/dist/node/fs/backend.d.ts +8 -0
  31. package/dist/node/fs/callback-types.d.ts +43 -0
  32. package/dist/node/fs/callbacks.d.ts +3 -0
  33. package/dist/node/fs/client.d.ts +3 -0
  34. package/dist/node/fs/errors.d.ts +5 -0
  35. package/dist/node/fs/lifecycle.d.ts +11 -0
  36. package/dist/node/fs/options.d.ts +7 -0
  37. package/dist/node/fs/promises.d.ts +33 -0
  38. package/dist/node/fs/promises.js +30 -0
  39. package/dist/node/fs/transfer.d.ts +7 -0
  40. package/dist/node/fs/types.d.ts +86 -0
  41. package/dist/node/fs.d.ts +36 -0
  42. package/dist/node/fs.js +92 -0
  43. package/dist/node/path.d.ts +20 -0
  44. package/dist/node/path.js +434 -0
  45. package/dist/plugin/client.d.ts +4 -0
  46. package/dist/plugin/connection.d.ts +6 -0
  47. package/dist/plugin/errors.d.ts +3 -0
  48. package/dist/plugin/index.d.ts +6 -0
  49. package/dist/plugin/index.js +12 -0
  50. package/dist/plugin/types.d.ts +28 -0
  51. package/dist/protocol/capabilities.d.ts +8 -0
  52. package/dist/protocol/errors.d.ts +14 -0
  53. package/dist/protocol/generated/capabilities.generated.d.ts +56 -0
  54. package/dist/protocol/generated/fs.generated.d.ts +178 -0
  55. package/dist/protocol/generated/host-event.generated.d.ts +17 -0
  56. package/dist/protocol/generated/manifest.generated.d.ts +64 -0
  57. package/dist/protocol/generated/session.generated.d.ts +93 -0
  58. package/dist/protocol/generated/types.generated.d.ts +6 -0
  59. package/dist/protocol/generated/validators.generated.d.mts +24 -0
  60. package/dist/protocol/generated/wire.generated.d.ts +63 -0
  61. package/dist/protocol/index.d.ts +18 -0
  62. package/dist/protocol/index.js +746 -0
  63. package/dist/protocol/json-safety.d.ts +3 -0
  64. package/dist/protocol/limits.d.ts +11 -0
  65. package/dist/protocol/manifest.d.ts +5 -0
  66. package/dist/protocol/path-policy.d.ts +2 -0
  67. package/dist/protocol/schema/capabilities.schema.json +301 -0
  68. package/dist/protocol/schema/fs.schema.json +900 -0
  69. package/dist/protocol/schema/host-event.schema.json +116 -0
  70. package/dist/protocol/schema/manifest.schema.json +60 -0
  71. package/dist/protocol/schema/session.schema.json +145 -0
  72. package/dist/protocol/schema/wire.schema.json +358 -0
  73. package/dist/protocol/session.d.ts +3 -0
  74. package/dist/protocol/types.d.ts +27 -0
  75. package/dist/protocol/validation.d.ts +2 -0
  76. package/dist/protocol/wire.d.ts +16 -0
  77. package/package.json +95 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xyito
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # @ai-switch/tauri-plugin-runtime
2
+
3
+ Host-neutral contracts for APLG plugins. The package does not depend on Tauri,
4
+ React, Vue, or AI Switch application source code.
5
+
6
+ ## Implementation status
7
+
8
+ The R1/R2 implementation slices provide manifest, wire, session and standard
9
+ capability schemas, generated TypeScript declarations and ahead-of-time
10
+ validators, safe JSON validation, portable archive/virtual path policies,
11
+ capability negotiation, safe error envelopes, and version constants.
12
+
13
+ R3/R4 add a bounded MessagePort RPC layer and the public `/plugin` client,
14
+ including lazy bootstrap, two-way acknowledgement, capability calls,
15
+ subscriptions, storage/dialog wrappers, and connection lifecycle handling.
16
+ R5 adds the generic `/host` mounting API with scoped identity, event routing,
17
+ reconnect handling and bounded cleanup. R6 adds pure-JavaScript path, Buffer and
18
+ EventEmitter entry points. R7 adds asynchronous filesystem clients and callback
19
+ wrappers with bounded transfer handling. R8 adds clean builds, package boundary
20
+ checks, a framework-free storage-only host example, and real external npm
21
+ tarball installation tests in Chromium and WebKit. Real Rust capability providers and
22
+ installation/release integration are **not implemented yet**. The package has
23
+ not been published to npm. Do not interpret a valid manifest as authorization
24
+ to access files, the network, or the host application.
25
+
26
+ ## 发布与 CI
27
+
28
+ 两个 npm 包由 `.github/workflows/tauri-plugin-runtime.yml` 协调。普通 PR/main push 只执行两包 typecheck/test/build/pack、`verify-pair` 与发布计划测试;只有 `tauri-plugin-runtime-v*` tag 才进入受保护 environment `aplg-npm-release` 的发布 job。
29
+
30
+ 发布 job 使用 npm trusted publishing(OIDC),不保存明文 token;按 `@ai-switch/tauri-plugin-runtime` → `@ai-switch/tauri-plugin-devkit` 顺序以 `latest` 发布。npm 的 OIDC 只认证 `npm publish`,因此不再有独立的候选 tag 与提升步骤;第二包失败时第一包已发布,重跑会按 integrity 幂等跳过,不宣称事务性。实际发布必须由用户显式授权;本地脚本默认 dry-run。
31
+
32
+ 候选 dist-tag 不会隔离按版本范围安装,使用者应使用锁文件或精确版本。包发布本身不代表签名、安装授权或 plugin-store 审核已完成。
33
+
34
+ ## Protocol entry
35
+
36
+ ```ts
37
+ import {
38
+ validateManifest,
39
+ parseManifest,
40
+ manifestSchema,
41
+ normalizeArchivePath,
42
+ validateVirtualPath,
43
+ validateWireMessage,
44
+ validateHostEvent,
45
+ validateSessionDescriptor,
46
+ validateCapabilityRequest,
47
+ validateCapabilityResult,
48
+ } from "@ai-switch/tauri-plugin-runtime/protocol";
49
+ ```
50
+
51
+ - `validateManifest(value)` returns `{ ok, value }` or structured diagnostics.
52
+ - `parseManifest(value)` throws an error with `code: E_MANIFEST_INVALID` on failure.
53
+ - `normalizeArchivePath(path)` validates a portable relative POSIX archive path;
54
+ it never accesses the filesystem or silently rewrites input.
55
+ - `validateVirtualPath(path)` accepts only `/app`, `/data`, and
56
+ `/mounts/<grantId>` roots. It does not grant real filesystem access.
57
+ - `manifestSchema` is the draft-07 structural schema. Semantic version, path,
58
+ duplicate ID, origin and safe-JSON rules also require `validateManifest`.
59
+
60
+ - `validateWireMessage` rejects unknown operations, plugin-supplied identity
61
+ fields, malformed replies, unsafe JSON and oversized UTF-8 envelopes.
62
+ - `validateHostEvent` validates the separate identity-bearing host event shape.
63
+ - `validateSessionDescriptor` checks manifest identity, capability declarations,
64
+ standard method completeness, API versions, asset URL safety and limits.
65
+ An allowed asset URL still needs the concrete host's origin/IPC policy.
66
+ - `validateCapabilityRequest` / `validateCapabilityResult` validate v1
67
+ `aplg.storage`, `aplg.dialog` and `aplg.fs` DTOs. They reject unknown standard
68
+ methods; extension capabilities require their own provider-side validation.
69
+ - `AplgError` and `toErrorPayload` serialize deliberately public errors without
70
+ blindly copying native Error stacks or real filesystem paths. Construct
71
+ AplgError only from messages/details that are safe to show to plugins.
72
+
73
+ File DTO checks enforce canonical base64, bounded offsets/chunks and virtual
74
+ paths. The JS filesystem client now tracks transfers over the capability bridge,
75
+ but it does **not** execute OS filesystem operations or grant permissions. Those
76
+ remain the responsibility of an authenticated capability provider.
77
+
78
+ Shared cross-language inputs live in `fixtures/aplg/protocol-v1/`. Generated
79
+ schemas define structural contracts; semantic validation and backend grant
80
+ checks remain necessary in every consumer.
81
+ The implementation version is `0.1.0`; the wire identifier is `aplg/1`, the
82
+ plugin API version is `1.0.0`, and `manifestVersion` is `1`. These are separate
83
+ version domains.
84
+
85
+ ## Plugin entry
86
+
87
+ ```ts
88
+ import { aplg, connectPlugin } from "@ai-switch/tauri-plugin-runtime/plugin";
89
+
90
+ await connectPlugin(); // Also called lazily by aplg.ready().
91
+ if (aplg.capabilities.supports("aplg.storage", "^1.0.0")) {
92
+ await aplg.storage.set("note", "hello");
93
+ }
94
+ ```
95
+
96
+ A real host must declare and authorize the requested capabilities. Imports do
97
+ not create a connection or touch browser globals. Calling `connectPlugin()` on
98
+ a standalone page or without bootstrap context fails explicitly; it never
99
+ falls back to a privileged mock host. Concurrent initial calls share one
100
+ handshake. The client requires the exact parent window/origin, nonce, one port,
101
+ and a parent acknowledgement before resolving readiness.
102
+
103
+ Session information is a frozen public snapshot, not a host credential. The
104
+ client rejects unavailable methods and malformed standard requests/results.
105
+ Subscriptions are bounded, duplicate/old sequence events are ignored, and
106
+ connection changes let callers re-read state after a gap or reconnect; events
107
+ are not replayed automatically. Closing the view or losing the peer invalidates
108
+ pending work, subscriptions and capability discovery.
109
+
110
+ RPC frames are bounded JSON strings. Cancellation and timeouts settle locally
111
+ and send best-effort cancellation to the peer; they cannot undo side effects.
112
+ Duplicate request detection remembers the most recent 1024 IDs, not unlimited
113
+ history or durable idempotency across sessions.
114
+
115
+ Browser tests cover both the low-level handshake fixture and the real generic
116
+ host API with an in-memory backend. They demonstrate Chromium iframe/CSP behavior,
117
+ not Tauri IPC isolation, actual Rust file access, or WebKit compatibility.
118
+ ## Host entry
119
+
120
+ ```ts
121
+ import { createPluginHost } from "@ai-switch/tauri-plugin-runtime/host";
122
+ import type { HostTransport } from "@ai-switch/tauri-plugin-runtime/host";
123
+
124
+ async function mountPlugin(transport: HostTransport, container: HTMLElement) {
125
+ const host = createPluginHost({ transport });
126
+ const view = await host.mount({ pluginId: "io.github.example.notes", container });
127
+ return async () => { await view.dispose(); await host.dispose(); };
128
+ }
129
+ ```
130
+
131
+ The application supplies an authenticated `HostTransport`; it is not handed to
132
+ plugin code. Mounting subscribes to host events before opening a backend session,
133
+ validates the descriptor, binds it to one sandboxed iframe/port, and resolves only
134
+ after the plugin handshake. By default assets must use the host page's origin;
135
+ other HTTPS/loopback origins require an explicit `allowedAssetOrigins` list.
136
+
137
+ Each view gets its own backend request IDs and stable logical subscription IDs.
138
+ A reconnect only restores active subscriptions; it never repeats a completed
139
+ write. Backend sequence numbers are mapped into the logical subscription's
140
+ monotonic sequence, while stale backend IDs and foreign sessions are ignored.
141
+
142
+ Timeouts, container removal, document reload, remote session closure and explicit
143
+ disposal all invalidate the view. Late session/subscription results are released,
144
+ and cleanup is bounded even if a transport operation never resolves. The backend
145
+ must still authorize every call and enforce grants, resource limits and asset
146
+ access. Dedicated asset serving, CSP headers and Tauri IPC restrictions remain
147
+ the embedding application's responsibility; an iframe is not an OS sandbox.
148
+ ## Pure JavaScript Node subset
149
+
150
+ ```ts
151
+ import path from "@ai-switch/tauri-plugin-runtime/node/path";
152
+ import { Buffer } from "@ai-switch/tauri-plugin-runtime/node/buffer";
153
+ import EventEmitter from "@ai-switch/tauri-plugin-runtime/node/events";
154
+
155
+ const filename = path.resolve("notes", "example.txt"); // /data/notes/example.txt
156
+ const bytes = Buffer.from("hello", "utf8");
157
+ const events = new EventEmitter();
158
+ events.once("saved", (name: string) => console.log(name));
159
+ events.emit("saved", filename);
160
+ ```
161
+
162
+ These modules are local JS operations: importing them does not connect to a
163
+ host, grant file access, or install `Buffer`, `process`, or `require` globals.
164
+ `node:path`/`node:buffer`/`node:events` build aliases belong to the later devkit;
165
+ use the explicit package subpaths until that toolchain is implemented.
166
+
167
+ - **Path:** only `join`, `resolve`, `normalize`, `dirname`, `basename`, `extname`,
168
+ `relative`, and `isAbsolute`. Semantics are POSIX on every host. Both `resolve`
169
+ and `relative` use `/data` as the virtual working directory, never the OS cwd.
170
+ String operations can produce a path outside the allowed virtual roots; the
171
+ actual filesystem capability must reject it. No `win32`, `parse`, or `format`.
172
+ - **Buffer:** uses the browser `buffer@6.0.3` implementation, including byte
173
+ arrays, UTF-8/base64 conversion, concatenation and Buffer-returning subarrays.
174
+ It is not Node's native/global Buffer. Compatibility is limited to the pinned
175
+ implementation and verified behavior, not every modern Node Buffer overload.
176
+ - **EventEmitter:** only `on`, `once`, `off`, `emit`, and `removeAllListeners`,
177
+ with string/symbol events, synchronous delivery, original-listener removal,
178
+ and `this` bound to the public emitter. Listener exceptions propagate, as in
179
+ Node. No promise helpers, prepend API or listener-limit configuration is exposed.
180
+ Removing an event's listeners is not cancellation of work they already started.
181
+
182
+ Type tests cover source and built package exports without installing Node globals.
183
+ Browser tests load the actual built ESM files while trapping access to Node globals,
184
+ including inside an opaque sandboxed iframe; these are not source-alias-only tests.
185
+ The upstream path dependency retains an unreachable `process.cwd()` fallback in
186
+ its bundle, but every exposed resolving path supplies an explicit absolute root.
187
+ ## Asynchronous filesystem client
188
+
189
+ ```ts
190
+ import fs from "@ai-switch/tauri-plugin-runtime/node/fs";
191
+ import fsp from "@ai-switch/tauri-plugin-runtime/node/fs/promises";
192
+
193
+ await fsp.writeFile("/data/note.txt", "hello", "utf8");
194
+ const text = await fs.promises.readFile("/data/note.txt", "utf8");
195
+ fs.readFile("/data/note.txt", (error, data) => {
196
+ if (error) { console.error(error.code); return; }
197
+ console.log(data.toString("utf8"));
198
+ });
199
+ ```
200
+
201
+ The plugin must declare and be granted compatible `aplg.fs` capability. These
202
+ imports do not call Node's real filesystem, create an implicit browser filesystem,
203
+ or auto-connect on module import. `fs.promises`, the default promises export and
204
+ its named methods share one lazy client and one concurrency queue.
205
+
206
+ Supported operations are `readFile`, `writeFile`, `appendFile`, `readdir`, `stat`,
207
+ `mkdir`, `rename`, `copyFile` and `rm`, plus their callback forms. Only absolute
208
+ virtual string paths are accepted. UTF-8 reads return strings; omitted/null
209
+ encoding returns the browser Buffer. Writes accept strings/Uint8Array and flags
210
+ `w`/`wx`; append uses `a`/`ax`. Unknown options, streams, file descriptors, URLs,
211
+ watch APIs and arbitrary encodings are rejected. Synchronous methods throw
212
+ `ERR_APLG_SYNC_IO_UNSUPPORTED`, not promises.
213
+
214
+ - A file is limited to **8 MiB**, chunks to **256 KiB**, and active transfers to
215
+ **two** (or smaller negotiated host limits). The queue is bounded at 64 operations.
216
+ - The client snapshots input byte buffers, checks chunk offsets/lengths/base64 and
217
+ byte acknowledgements, and commits only after the complete transfer is staged.
218
+ - A 30-second per-request/queue timeout and connection-close handling prevent
219
+ unbounded waits. Cleanup has its own bounded best-effort abort; uncertain
220
+ cleanup blocks new transfer admission rather than pretending capacity is free.
221
+ - Host-side handle ownership also protects replies that arrive after a plugin
222
+ request timed out. Reconnect confirms interrupted handle cleanup before
223
+ resuming; unconfirmed opens fail closed. These are not a substitute for backend
224
+ resource ownership and authorization.
225
+ - Timeouts/cancellation do not undo an already committed write or other external
226
+ side effect. Non-idempotent operations, especially append, are never retried
227
+ automatically. `force` does not bypass permissions and rename cannot cross grants.
228
+ - Stats and directory entries expose immutable snapshots of the supported subset,
229
+ not the full native Node Stats/Dirent APIs. Errors contain safe virtual paths,
230
+ syscall names and known codes, never blindly copied backend stacks or credentials.
231
+
232
+ The in-memory filesystem implementation is test-only and is not exported. Tests
233
+ include real Node filesystem differential cases in an isolated temporary directory
234
+ and actual built ESM imports in sandboxed browser views. The Rust provider and
235
+ its symlink/junction, OS permissions, quotas and transactional staging still need
236
+ separate implementation and verification. Standard `node:fs` import aliases are
237
+ part of the later devkit, not automatically installed by this runtime.
238
+ ## Development
239
+
240
+ Node `^22.12.0 || ^24.0.0 || >=26.0.0` and pnpm `10.12.4` are required.
241
+
242
+ ```sh
243
+ pnpm install --frozen-lockfile
244
+ pnpm --dir packages/tauri-plugin-runtime generate
245
+ pnpm --dir packages/tauri-plugin-runtime check:generated
246
+ pnpm --dir packages/tauri-plugin-runtime typecheck
247
+ pnpm --dir packages/tauri-plugin-runtime test
248
+ pnpm --dir packages/tauri-plugin-runtime build
249
+ pnpm --dir packages/tauri-plugin-runtime test:types
250
+ pnpm --dir packages/tauri-plugin-runtime test:types:public
251
+ pnpm --dir packages/tauri-plugin-runtime run test:package
252
+ pnpm --dir packages/tauri-plugin-runtime exec playwright install chromium webkit
253
+ pnpm --dir packages/tauri-plugin-runtime test:browser
254
+ pnpm --dir packages/tauri-plugin-runtime verify:tarball
255
+ ```
256
+
257
+ JSON schemas under `src/protocol/schema/` are the authoritative structural
258
+ contract. Generated TypeScript and ESM validators are committed and verified
259
+ without invoking runtime code generation in the browser. Validation does not
260
+ need `eval`, `new Function`, a Node `require`, or browser globals on import.
261
+
262
+ Only implemented entry points are exported: root version/types, `/protocol`,
263
+ `/plugin`, `/host`, `/node/path`, `/node/buffer`, `/node/events`, `/node/fs`, and
264
+ `/node/fs/promises`. The root export contains only version constants and public
265
+ TypeScript types; it does not aggregate host or Node clients. Consumers need an
266
+ ESM-capable bundler and TypeScript `Bundler`/`NodeNext` resolution. CJS `require`
267
+ and deep internal paths are not public APIs.
268
+
269
+ ## Independent package verification
270
+
271
+ `verify:tarball` builds and packs a real `.tgz`, then creates a new consumer under
272
+ `os.tmpdir()` **outside the source checkout**. It installs with npm and disabled
273
+ lifecycle scripts, verifies all nine public ESM entries and the fs singleton in
274
+ Node without DOM globals, compiles public types without Node globals, and builds
275
+ the plain-host example with its own Vite 8. The consumer's runtime and build/test
276
+ tools must resolve from its own node_modules, never a workspace link or source
277
+ alias. The npm package file list and installed bytes are compared before testing.
278
+
279
+ The same consumer runs the packaged browser suite against two loopback-only
280
+ origins with a no-inline/no-eval CSP and an opaque iframe. Tests cover storage
281
+ roundtrips, safe text rendering, cleanup/remount, unavailable filesystem access,
282
+ origin separation and a narrow viewport. Both Chromium and WebKit must be
283
+ installed; missing browsers fail, not silently skip. On Linux, install browser
284
+ system dependencies first (`playwright install --with-deps chromium webkit`).
285
+
286
+ The verifier stops its owned child processes/servers and checks the temporary
287
+ directory's canonical parent, identity and ownership marker before removal in
288
+ `finally`. Its bounded subprocess tests also cover failure, interruption and
289
+ descendant termination. Forced OS termination/power loss cannot promise cleanup.
290
+ Run builds and validation commands sequentially: they intentionally share the
291
+ single generated dist directory. `test` now builds first so the example tests also
292
+ work on a fresh checkout.
293
+
294
+ Package hygiene checks inspect **parsed** JS/declaration imports, the esbuild
295
+ input graph and installed transitive production dependencies. They reject real
296
+ Node builtins, app/framework/Tauri imports, workspace/file dependencies, runtime
297
+ install hooks, unresolved or stale chunks, source maps, unexpected packed files,
298
+ known source-root paths and common secret/key material. This is a conservative
299
+ release boundary check, **not** a general malware scanner or authorization layer.
300
+ Every build clears only the validated package-local dist directory before the
301
+ single multi-entry ESM build, retaining shared client state across subpaths.
302
+
303
+ Current artifacts contain 77 files (16 JS files), approximately **120 KiB gzip
304
+ npm tarball / 983 KiB unpacked**. Exact bytes are reported each run and change with
305
+ documentation. The four direct registry dependencies remain `buffer@6.0.3`,
306
+ `events@3.3.0`, `path-browserify@1.0.1`, `semver@7.8.5`; the installed production
307
+ graph also includes `base64-js@1.5.1` and `ieee754@1.2.1`. They are not claimed to
308
+ be zero dependencies: browser JS is bundled, while public Buffer declarations
309
+ still use its upstream package. See third-party notices for bundled code.
310
+
311
+ Local verification has run on **Windows, Node 22.22.2**, with both browsers.
312
+ Linux execution is still outstanding: the available Ubuntu and Podman WSL
313
+ registrations could not mount their missing VHDs. Portable scripts and a POSIX
314
+ signal-target unit test are not evidence of Linux execution. The Windows/Ubuntu
315
+ Node 22/24 CI matrix belongs to the later coordinated runtime/devkit D9 workflow;
316
+ no remote workflow or publication has been triggered by this task.
317
+
318
+ The Chinese walkthrough is in `examples/aplg-plain-host/README.md` in the source
319
+ repository. Its Transport offers **memory-only, view-scoped storage**, no fake
320
+ filesystem and no OS/network permission grants. The example and verification tools
321
+ are deliberately not in the published tarball. Rust providers, production
322
+ Tauri/Web adapters, native plugins, installation/signing and store release
323
+ workflows are separate work. The runtime has **not been published to npm**.
324
+
325
+ ## License
326
+
327
+ MIT. See [LICENSE](LICENSE) and [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
@@ -0,0 +1,210 @@
1
+ # Third-party notices
2
+
3
+ The built ESM output includes code from the following packages under their listed licenses.
4
+ The JSON Schema compiler remains a development-only dependency. Its generated
5
+ standalone validators include the runtime helpers listed below; compiler code is
6
+ not installed or executed in the browser. Build/test tools (TypeScript, Vite,
7
+ esbuild, Vitest and Playwright) and the plain-host example are not shipped.
8
+ These notices are included in every npm tarball; bundling and ESM splitting do
9
+ not remove the obligations of the original licenses.
10
+
11
+ ## node-semver 7.8.5
12
+
13
+ The ISC License
14
+
15
+ Copyright (c) Isaac Z. Schlueter and Contributors
16
+
17
+ Permission to use, copy, modify, and/or distribute this software for any
18
+ purpose with or without fee is hereby granted, provided that the above
19
+ copyright notice and this permission notice appear in all copies.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
22
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
23
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
24
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
26
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
27
+ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28
+
29
+
30
+ ## Ajv 8.20.0 runtime helpers
31
+
32
+ The MIT License (MIT)
33
+
34
+ Copyright (c) 2015-2021 Evgeny Poberezkin
35
+
36
+ Permission is hereby granted, free of charge, to any person obtaining a copy
37
+ of this software and associated documentation files (the "Software"), to deal
38
+ in the Software without restriction, including without limitation the rights
39
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40
+ copies of the Software, and to permit persons to whom the Software is
41
+ furnished to do so, subject to the following conditions:
42
+
43
+ The above copyright notice and this permission notice shall be included in all
44
+ copies or substantial portions of the Software.
45
+
46
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52
+ SOFTWARE.
53
+
54
+
55
+
56
+ ## fast-deep-equal runtime helper
57
+
58
+ MIT License
59
+
60
+ Copyright (c) 2017 Evgeny Poberezkin
61
+
62
+ Permission is hereby granted, free of charge, to any person obtaining a copy
63
+ of this software and associated documentation files (the "Software"), to deal
64
+ in the Software without restriction, including without limitation the rights
65
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66
+ copies of the Software, and to permit persons to whom the Software is
67
+ furnished to do so, subject to the following conditions:
68
+
69
+ The above copyright notice and this permission notice shall be included in all
70
+ copies or substantial portions of the Software.
71
+
72
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
78
+ SOFTWARE.
79
+
80
+ ## buffer 6.0.3
81
+
82
+ The MIT License (MIT)
83
+
84
+ Copyright (c) Feross Aboukhadijeh, and other contributors.
85
+
86
+ Permission is hereby granted, free of charge, to any person obtaining a copy
87
+ of this software and associated documentation files (the "Software"), to deal
88
+ in the Software without restriction, including without limitation the rights
89
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
90
+ copies of the Software, and to permit persons to whom the Software is
91
+ furnished to do so, subject to the following conditions:
92
+
93
+ The above copyright notice and this permission notice shall be included in
94
+ all copies or substantial portions of the Software.
95
+
96
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
97
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
98
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
99
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
100
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
101
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
102
+ THE SOFTWARE.
103
+
104
+ ## events 3.3.0
105
+
106
+ MIT
107
+
108
+ Copyright Joyent, Inc. and other Node contributors.
109
+
110
+ Permission is hereby granted, free of charge, to any person obtaining a
111
+ copy of this software and associated documentation files (the
112
+ "Software"), to deal in the Software without restriction, including
113
+ without limitation the rights to use, copy, modify, merge, publish,
114
+ distribute, sublicense, and/or sell copies of the Software, and to permit
115
+ persons to whom the Software is furnished to do so, subject to the
116
+ following conditions:
117
+
118
+ The above copyright notice and this permission notice shall be included
119
+ in all copies or substantial portions of the Software.
120
+
121
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
122
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
123
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
124
+ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
125
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
126
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
127
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
128
+
129
+ ## path-browserify 1.0.1
130
+
131
+ MIT License
132
+
133
+ Copyright (c) 2013 James Halliday
134
+
135
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
136
+ this software and associated documentation files (the "Software"), to deal in
137
+ the Software without restriction, including without limitation the rights to
138
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
139
+ the Software, and to permit persons to whom the Software is furnished to do so,
140
+ subject to the following conditions:
141
+
142
+ The above copyright notice and this permission notice shall be included in all
143
+ copies or substantial portions of the Software.
144
+
145
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
146
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
147
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
148
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
149
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
150
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
151
+
152
+ ## base64-js 1.5.1 (Buffer dependency)
153
+
154
+ The MIT License (MIT)
155
+
156
+ Copyright (c) 2014 Jameson Little
157
+
158
+ Permission is hereby granted, free of charge, to any person obtaining a copy
159
+ of this software and associated documentation files (the "Software"), to deal
160
+ in the Software without restriction, including without limitation the rights
161
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
162
+ copies of the Software, and to permit persons to whom the Software is
163
+ furnished to do so, subject to the following conditions:
164
+
165
+ The above copyright notice and this permission notice shall be included in
166
+ all copies or substantial portions of the Software.
167
+
168
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
169
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
170
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
171
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
172
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
173
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
174
+ THE SOFTWARE.
175
+
176
+ ## ieee754 1.2.1 (Buffer dependency)
177
+
178
+ Copyright 2008 Fair Oaks Labs, Inc.
179
+
180
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
181
+
182
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
183
+
184
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
185
+
186
+ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
187
+
188
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
189
+
190
+ ### Node.js-derived path implementation notice
191
+
192
+ 'path' module extracted from Node.js v8.11.1 (only the posix part)
193
+ transplited with Babel
194
+ Copyright Joyent, Inc. and other Node contributors.
195
+ Permission is hereby granted, free of charge, to any person obtaining a
196
+ copy of this software and associated documentation files (the
197
+ "Software"), to deal in the Software without restriction, including
198
+ without limitation the rights to use, copy, modify, merge, publish,
199
+ distribute, sublicense, and/or sell copies of the Software, and to permit
200
+ persons to whom the Software is furnished to do so, subject to the
201
+ following conditions:
202
+ The above copyright notice and this permission notice shall be included
203
+ in all copies or substantial portions of the Software.
204
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
205
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
206
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
207
+ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
208
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
209
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
210
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,11 @@
1
+ import type { SessionInfo } from "../protocol/wire.js";
2
+ export interface BootstrapHint {
3
+ nonce: string;
4
+ parentOrigin: string;
5
+ originalHash: string;
6
+ }
7
+ export declare function appendBootstrapHint(assetUrl: string, nonce: string, parentOrigin: string): string;
8
+ export declare function readBootstrapHint(href: string): BootstrapHint;
9
+ /** Validate public info through the existing session contract, never a second schema. */
10
+ export declare function validatePublicSessionInfo(input: unknown): SessionInfo;
11
+ export declare function validateConnectMessage(value: unknown, nonce: string): SessionInfo;
@@ -0,0 +1,4 @@
1
+ import type { WireMessage } from "../protocol/generated/types.generated.js";
2
+ export declare function checkedByteLimit(value: number): number;
3
+ export declare function encodeWireMessage(value: unknown, maxBytes?: number): string;
4
+ export declare function decodeWireMessage(frame: unknown, maxBytes?: number): WireMessage;
@@ -0,0 +1,7 @@
1
+ import type { RpcPeer } from "./rpc-types.js";
2
+ export type { CallOptions, IncomingRequest, PortEvent, RpcPeer } from "./rpc-types.js";
3
+ export declare function createRpcPeer(port: MessagePort, options?: {
4
+ timeoutMs?: number;
5
+ maxInflight?: number;
6
+ maxBytes?: number;
7
+ }): RpcPeer;
@@ -0,0 +1,20 @@
1
+ import type { JsonObject, JsonValue } from "../protocol/types.js";
2
+ import type { PluginOperation, PluginRequest, Unsubscribe } from "../protocol/wire.js";
3
+ import type { WireMessage } from "../protocol/generated/types.generated.js";
4
+ export interface CallOptions {
5
+ signal?: AbortSignal;
6
+ timeoutMs?: number;
7
+ }
8
+ export type IncomingRequest = PluginRequest & {
9
+ signal: AbortSignal;
10
+ };
11
+ export type PortEvent = Extract<WireMessage, {
12
+ kind: "event" | "connection";
13
+ }>;
14
+ export interface RpcPeer {
15
+ request(operation: PluginOperation, args: JsonObject, options?: CallOptions): Promise<JsonValue>;
16
+ onRequest(handler: (request: IncomingRequest) => Promise<JsonValue>): Unsubscribe;
17
+ onEvent(handler: (event: PortEvent) => void): Unsubscribe;
18
+ sendEvent(event: PortEvent): void;
19
+ close(reason?: Error): void;
20
+ }