arcane-os 0.3.0 → 0.3.2

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 (153) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +86 -117
  3. package/bin/arcane-test.mjs +170 -46
  4. package/browser-runtime/ai/browser-speech-artifacts.mjs +887 -909
  5. package/browser-runtime/ai/browser-speech-providers.mjs +96 -152
  6. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
  7. package/browser-runtime/ai/browser-wasm.mjs +24 -35
  8. package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
  9. package/browser-runtime/ai/model-controller.mjs +584 -181
  10. package/browser-runtime/ai/speech-worker-client.mjs +8 -146
  11. package/browser-runtime/ai/speech-worker-runtime.mjs +643 -363
  12. package/browser-runtime/dom-event-instrumentation.mjs +55 -147
  13. package/browser-runtime/event-manager.mjs +239 -624
  14. package/package.json +5 -6
  15. package/runtime/arcane/components/app-bar.html +3 -15
  16. package/runtime/arcane/components/assistant-panel.html +10 -10
  17. package/runtime/arcane/components/calculator.html +1 -1
  18. package/runtime/arcane/components/chat.html +1359 -135
  19. package/runtime/arcane/components/conversation-view.html +2 -2
  20. package/runtime/arcane/components/document-inspector.html +11 -17
  21. package/runtime/arcane/components/file-manager.html +13 -56
  22. package/runtime/arcane/components/markdown-document.html +82 -281
  23. package/runtime/arcane/components/markdown-editor.html +7 -10
  24. package/runtime/arcane/components/media-embed.html +6 -6
  25. package/runtime/arcane/components/screen-capture.html +4 -4
  26. package/runtime/arcane/components/source-explanation.html +2 -2
  27. package/runtime/arcane/components/speech.html +112 -68
  28. package/runtime/arcane/components/terminal-workspace.html +4 -4
  29. package/runtime/arcane/components/theme-editor.html +1 -1
  30. package/runtime/arcane/components/unified-inbox.html +2 -2
  31. package/runtime/arcane/components/voice-transcription.html +31 -21
  32. package/runtime/arcane/entities/Calculation.js +2 -3
  33. package/runtime/arcane/entities/Chat.js +228 -43
  34. package/runtime/arcane/entities/Preference.js +3 -5
  35. package/runtime/arcane/entities/Weather.js +5 -5
  36. package/runtime/arcane/modules/AI.js +1050 -427
  37. package/runtime/arcane/modules/AIProviderRuntime.js +658 -363
  38. package/runtime/arcane/modules/AIResponseLength.js +9 -19
  39. package/runtime/arcane/modules/AIRuntimeState.js +109 -72
  40. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
  41. package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
  42. package/runtime/arcane/modules/CalculatorEngine.js +9 -9
  43. package/runtime/arcane/modules/CommunicationAppController.js +3 -7
  44. package/runtime/arcane/modules/ComponentContracts.js +30 -32
  45. package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
  46. package/runtime/arcane/modules/ConversationActionItems.js +26 -59
  47. package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
  48. package/runtime/arcane/modules/ConversationTimebox.js +27 -15
  49. package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
  50. package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
  51. package/runtime/arcane/modules/HTMLImport.js +54 -1
  52. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
  53. package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
  54. package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
  55. package/runtime/arcane/modules/MD.js +1 -45
  56. package/runtime/arcane/modules/Mail.js +51 -103
  57. package/runtime/arcane/modules/MailOutbox.mjs +95 -193
  58. package/runtime/arcane/modules/MailTransport.mjs +36 -57
  59. package/runtime/arcane/modules/ModelDefinition.js +22 -106
  60. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
  61. package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
  62. package/runtime/arcane/modules/PreferenceStore.js +102 -30
  63. package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
  64. package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
  65. package/runtime/arcane/modules/ScreenCapture.js +175 -128
  66. package/runtime/arcane/modules/SpeechPlayback.js +46 -149
  67. package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
  68. package/runtime/arcane/modules/ToolCallRouter.js +25 -12
  69. package/runtime/arcane/modules/YouTubeMedia.js +6 -5
  70. package/schemas/arcane-app-bundle.schema.json +13 -78
  71. package/schemas/arcane-app.schema.json +9 -25
  72. package/schemas/arcane-lock.schema.json +18 -151
  73. package/schemas/arcane-package.schema.json +2 -16
  74. package/schemas/native-build-plan.schema.json +119 -122
  75. package/src/app-descriptor.mjs +75 -132
  76. package/src/application-tests.mjs +200 -0
  77. package/src/cli/main.mjs +27 -46
  78. package/src/constants.mjs +3 -4
  79. package/src/dev-server.mjs +30 -324
  80. package/src/doctor.mjs +92 -154
  81. package/src/dom-event-instrumentation.mjs +55 -147
  82. package/src/errors.mjs +2 -3
  83. package/src/event-manager.mjs +239 -624
  84. package/src/event-queue.mjs +3 -3
  85. package/src/import-map.mjs +273 -1028
  86. package/src/index.mjs +14 -16
  87. package/src/installed-sdk-runtime.mjs +40 -62
  88. package/src/integrated-provider-loader.mjs +53 -382
  89. package/src/mail-api.mjs +0 -2
  90. package/src/mail-server.mjs +224 -580
  91. package/src/mail.mjs +4 -10
  92. package/src/native-plan.mjs +163 -598
  93. package/src/native-provider-loader.mjs +104 -1063
  94. package/src/packager/core.mjs +485 -3229
  95. package/src/process.mjs +5 -10
  96. package/src/release-bundle.mjs +292 -2405
  97. package/src/runtime.mjs +76 -396
  98. package/src/scaffold.mjs +30 -80
  99. package/src/sdk-browser-runtime.mjs +70 -626
  100. package/src/source-server.mjs +588 -0
  101. package/src/targets/index.mjs +78 -188
  102. package/src/templates/workspace-template.mjs +19 -135
  103. package/src/testing-loader.mjs +164 -0
  104. package/src/testing.mjs +1 -1
  105. package/src/toolchain.mjs +131 -544
  106. package/src/update-check.mjs +26 -64
  107. package/src/workspace-operation-lock.mjs +139 -430
  108. package/src/workspace-runtime.mjs +112 -779
  109. package/src/workspace.mjs +40 -302
  110. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
  111. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
  112. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
  113. package/browser-runtime/ai/internal/sha256.mjs +0 -166
  114. package/docs/architecture.md +0 -344
  115. package/docs/compatibility.md +0 -36
  116. package/docs/event-manager.md +0 -294
  117. package/docs/platform-targets.md +0 -108
  118. package/docs/publishing.md +0 -201
  119. package/docs/reference/README.md +0 -187
  120. package/docs/reference/ai/browser-speech-package-authority.json +0 -835
  121. package/docs/reference/ai/browser-speech.md +0 -1252
  122. package/docs/reference/ai/browser-wasm.md +0 -530
  123. package/docs/reference/arcane-ollama.md +0 -288
  124. package/docs/reference/availability-and-normalization.md +0 -183
  125. package/docs/reference/behavioral-testing.md +0 -133
  126. package/docs/reference/cli.md +0 -779
  127. package/docs/reference/core/README.md +0 -62
  128. package/docs/reference/core/arcane-ai-contracts.md +0 -907
  129. package/docs/reference/core/arcane-api.md +0 -601
  130. package/docs/reference/core/arcane-entities.md +0 -65
  131. package/docs/reference/core/arcane-events.md +0 -134
  132. package/docs/reference/core/ollama-module.md +0 -181
  133. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
  134. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
  135. package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
  136. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
  137. package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
  138. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
  139. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
  140. package/docs/reference/event-manager.md +0 -1511
  141. package/docs/reference/inventory/package-api.json +0 -3284
  142. package/docs/reference/inventory/runtime-components.json +0 -1011
  143. package/docs/reference/inventory/runtime-entities.json +0 -26
  144. package/docs/reference/inventory/runtime-modules.json +0 -1431
  145. package/docs/reference/mail.md +0 -316
  146. package/docs/reference/protocols.md +0 -677
  147. package/docs/reference/runtime-components.md +0 -1366
  148. package/docs/reference/runtime-entities.md +0 -303
  149. package/docs/reference/runtime-modules.md +0 -2960
  150. package/docs/reference/sdk-api.md +0 -6694
  151. package/docs/roadmap.md +0 -79
  152. package/docs/work-amplification.md +0 -129
  153. package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
@@ -1,1252 +0,0 @@
1
- # Browser speech providers
2
-
3
- `arcane-os/ai/browser-speech` is the browser-only, event-neutral SDK boundary
4
- for caller-supplied Whisper speech-to-text and Kokoro text-to-speech runtimes.
5
- It supplies immutable artifact-graph validation, DBOPFS admission, role Workers,
6
- provider/2 adapters, audio normalization, cancellation, and cleanup. It does
7
- not ship or select runtime modules, model weights, voice bytes, a default
8
- catalog, credentials, a native provider, or a cloud fallback.
9
- The package contains no speech runtime, model, or voice payload and
10
- never downloads one before explicit `load()`.
11
-
12
- Use this entrypoint when an application deliberately owns every browser-local
13
- speech choice. Higher-level selection, startup policy, shared state, and event
14
- projection belong to the application runtime; this package exposes only
15
- promises, `AbortSignal`, and the caller's progress callback.
16
-
17
- ## Availability
18
-
19
- | Host | Availability | Notes |
20
- | --- | --- | --- |
21
- | Browser | Shipped | Requires DBOPFS/OPFS, Web Locks, Workers, Fetch, Blob/File, and object URLs. Authenticated graphs additionally require `MessageChannel`; shared Blob/File STT requests require the browser audio decoder. |
22
- | Native WebView | Conditional | Available only when the WebView exposes the same browser APIs and the application admits every artifact. It does not invoke Core speech. |
23
- | Node | Importable, execution unavailable | The ESM subpath can be imported, but the SDK supplies no Node speech storage, Worker, or audio-decoder host. |
24
- | Cloud | Not provided | A cloud speech adapter may separately implement `arcane-ai-provider/2`; this package never selects it. |
25
-
26
- Whisper `stt` and Kokoro `tts` each own an independent provider lifecycle. A
27
- failure or cancellation in either role does not disable LLM use and never
28
- authorizes a different local, native, Core, or cloud provider.
29
-
30
- ## Public exports
31
-
32
- ```javascript
33
- import {
34
- BROWSER_SPEECH_ARTIFACT_GRAPH_PROTOCOL,
35
- BROWSER_SPEECH_ARTIFACT_PROTOCOL,
36
- createBrowserKokoroProvider,
37
- createBrowserSpeechArtifactGraph,
38
- createBrowserSpeechAuthority,
39
- createBrowserWhisperProvider,
40
- createDbopfsSpeechArtifactStore
41
- } from 'arcane-os/ai/browser-speech';
42
- ```
43
-
44
- The entrypoint exports exactly those seven names. Importing it downloads no
45
- artifact, opens no cache, creates no Worker, and publishes no event.
46
-
47
- ## Protocol and enum registry
48
-
49
- | Subject | Exact value or closed set |
50
- | --- | --- |
51
- | Artifact-store protocol | `arcane-ai-browser-speech-artifacts/1` |
52
- | Authenticated artifact-graph protocol | `arcane-ai-browser-speech-artifact-graph/1` |
53
- | Graph `kind` and prepared `runtime.moduleGraph` | `browser-speech-authenticated-artifact-graph` |
54
- | Legacy prepared `runtime.moduleGraph` | `self-contained` |
55
- | Legacy authority protocol | `arcane-ai-model-authority/1` |
56
- | Provider protocol | `arcane-ai-provider/2` |
57
- | Worker protocol | `arcane-ai-speech-worker/1` |
58
- | Worker error-envelope protocol | `arcane-ai-speech-worker-error/1` |
59
- | Nested artifact module-Worker protocol | `arcane-ai-browser-speech-artifact-module-worker/1` |
60
- | Nested module-Worker rejection event | `artifact-module-worker-bootstrap-rejected` |
61
- | Runtime graph-guard protocol | `arcane-ai-browser-speech-artifact-graph-runtime/1` |
62
- | Roles | `stt`, `tts` |
63
- | Role operations | `transcribe` for `stt`; `synthesize` for `tts` |
64
- | Public Worker operations | `load`, `use`, `status`, `unload`, `dispose` |
65
- | Worker transport-only control operation | `cancel` |
66
- | TTS response format | `wav` |
67
- | Runtime adapters | `transformers-whisper` for `stt`; `kokoro-js` for `tts` |
68
- | ONNX namespace identifiers | `transformers-env-backends-onnx-wasm` for `stt`; `kokoro-env-wasm-paths` for `tts` |
69
- | Edge policies | `artifact-targets-admitted`, `inactive-runtime-branch-rejected` |
70
- | Import target matches | `exact-runtime-specifier`, `materialized-module-url`; module-Worker targets additionally admit `self-module-url` |
71
- | Transform kinds | `function-return-this-to-global-this`, `typed-array-constructor` |
72
- | Graph descriptor status | `artifact-graph-descriptor-verified` |
73
- | Graph admission | `artifact-graph-network-dbopfs-verified`, `artifact-graph-dbopfs-cache-verified`, `artifact-graph-offline-dbopfs-cache-verified` |
74
-
75
- These values are exact, case-sensitive public contract values. Unknown values
76
- fail closed; a newer-looking value is not treated as compatible.
77
-
78
- ## `createBrowserSpeechArtifactGraph()`
79
-
80
- This is the operational authority for a real auxiliary ESM/WASM/model/voice
81
- closure. It creates one frozen, caller-selected graph and computes its SHA-256
82
- identity from a canonical JSON projection. The inventory is dynamic and has no
83
- fixed file or edge count; every declared member must still belong to the one
84
- complete reachable closure.
85
-
86
- The top-level shape is:
87
-
88
- ```text
89
- createBrowserSpeechArtifactGraph({
90
- kind?,
91
- identitySha256?,
92
- providerId?,
93
- role,
94
- model: { ... },
95
- runtime: { ... },
96
- files: [fileDescriptor, ...],
97
- edges: {
98
- staticImports: [...],
99
- dynamicImports: [...],
100
- moduleWorkers: [...],
101
- fetches: [...],
102
- cacheOpens: [...]
103
- },
104
- transforms: [...]
105
- })
106
- ```
107
-
108
- ### Top-level and model fields
109
-
110
- | Field | Contract |
111
- | --- | --- |
112
- | `kind` | Omit it or use exactly `browser-speech-authenticated-artifact-graph`. |
113
- | `identitySha256` | Optional 64-character lowercase SHA-256 assertion. If supplied, it must equal the SDK's canonical descriptor digest. The returned graph always contains the computed value. |
114
- | `providerId` | `null`/omitted, or one trimmed 1–128 character identity. A non-null value must equal the provider constructor's `id`. |
115
- | `role` | Exactly `stt` or `tts`. |
116
- | `model.id` | Trimmed 1–128 character caller-owned model identity. |
117
- | `model.repository` | Trimmed 1–128 character logical repository identity. The SDK passes it to the admitted adapter but does not resolve it independently. |
118
- | `model.revision` | Trimmed 1–128 character immutable revision. Every model and voice file must use this same revision. |
119
- | `model.dtype` | Trimmed 1–128 character caller-owned dtype. There is no SDK-selected graph default. |
120
- | `model.inputSampleRate` | Required positive safe integer for `stt`; caller-owned. STT must not declare voices. |
121
- | `model.outputSampleRate` | Required positive safe integer for `tts`; caller-owned. |
122
- | `model.defaultVoice` | Required for `tts`; must name one declared `voices[].id`. |
123
- | `model.voices` | Required nonempty TTS array of unique `{id,path}` records. Every path must name one unique `voice-style-binary`, and every such file must be in this inventory. |
124
-
125
- ### Runtime fields
126
-
127
- | Field | Contract |
128
- | --- | --- |
129
- | `runtime.adapter` | `transformers-whisper` for `stt`; `kokoro-js` for `tts`. |
130
- | `runtime.version` / `runtime.revision` | Trimmed 1–128 character caller-pinned identities. The sole entrypoint file revision must equal `runtime.revision`. |
131
- | `runtime.entrypoint` | Canonical path of the sole `runtime-entrypoint-javascript`. `runtime.entry` is accepted as an input alias; the normalized graph exposes `runtime.entry`. |
132
- | `runtime.onnxWasm.namespace` | `transformers-env-backends-onnx-wasm` for STT or `kokoro-env-wasm-paths` for TTS. |
133
- | `runtime.onnxWasm.mjsPath` | Path of a declared `runtime-auxiliary-javascript`. |
134
- | `runtime.onnxWasm.wasmPath` | Path of a declared `runtime-wasm-binary`. |
135
- | `runtime.onnxWasm.numThreads` | Optional positive safe integer for Transformers STT only. Kokoro does not expose a verified thread setting and rejects this field with reason `kokoro-env-num-threads-field-not-exposed`. No hardware-derived default is chosen. |
136
- | `runtime.negativeRuntimeRequestUrls` | Optional unique absolute HTTPS routes that a declared fetch edge may intentionally resolve as a local `404`. They may not overlap a positive source or runtime route and must be referenced by an edge. |
137
-
138
- ### File descriptor
139
-
140
- Every `files[]` entry contains all of these fields:
141
-
142
- ```text
143
- {
144
- kind,
145
- path,
146
- sourceUrl,
147
- revision,
148
- license,
149
- mediaType,
150
- sourceMediaType?,
151
- bytes,
152
- sha256,
153
- runtimeRequestUrls?,
154
- redirectFinalOrigins?
155
- }
156
- ```
157
-
158
- | Field | Contract |
159
- | --- | --- |
160
- | `kind` | One exact kind from the table below. |
161
- | `path` | Nonempty NFC-normalized relative path. Leading/trailing slash, backslash, empty/`.`/`..` segment, percent escape, query/fragment delimiter, control character, duplicate spelling, or case-folded collision is rejected. |
162
- | `sourceUrl` | Immutable starting HTTPS or same-origin authority without credentials or fragment. The pathname must not name `main`, `master`, `latest`, `refs/heads/main`, `refs/heads/master`, `resolve/main`, or `resolve/master`, or an `@latest`/`@next` channel. The URL must contain the declared revision or SHA-256 and remains authoritative even when redirect following is opted in. `url` is accepted as an input alias. |
163
- | `revision` | Nonempty 1–128 character immutable file revision. Runtime entry revision equals the runtime revision; all model/voice revisions equal the model revision. |
164
- | `license` | Nonempty declaration up to 256 characters. It is part of graph identity and the DBOPFS manifest authority, but it is only a declaration: it is not provenance, a composite notice, corresponding-source evidence, or a license inferred from bytes. The caller remains responsible for complete immutable license/notice evidence. |
165
- | `mediaType` | Exact lowercase `type/subtype` without parameters. JavaScript is `application/javascript` or `text/javascript`; WASM is `application/wasm`; `*-json` kinds are `application/json`. |
166
- | `sourceMediaType` | Optional exact lowercase `type/subtype` without parameters for the cold HTTP response. It defaults to `mediaType`; when different, it is exposed in the normalized descriptor and graph identity while `mediaType` remains the authenticated materialized Blob type. |
167
- | `bytes` | Positive safe integer; always required and always verified for graphs. |
168
- | `sha256` | Exactly 64 lowercase hexadecimal characters; always required and always verified for graphs. |
169
- | `runtimeRequestUrls` | Optional unique absolute HTTPS aliases used only inside the authenticated Worker. An alias may describe a third-party runtime's hard-coded mutable request, but it is never a download authority: the Worker maps it to this already verified local file. |
170
- | `redirectFinalOrigins` | Optional nonempty array that opts this file into Fetch redirect following. Every member must canonicalize to a unique HTTPS origin with no credentials, path, query, or fragment. The normalized array is lexically sorted, frozen, and graph-identity-bound. Omit the field for redirect rejection; an empty array is rejected. |
171
-
172
- The closed file kinds are:
173
-
174
- | Runtime kinds | Model/data kinds |
175
- | --- | --- |
176
- | `runtime-entrypoint-javascript` | `model-configuration-json` |
177
- | `runtime-auxiliary-javascript` | `model-generation-configuration-json` |
178
- | `runtime-wasm-binary` | `model-onnx-binary` |
179
- | `runtime-opaque-data` | `model-onnx-external-data` |
180
- | | `model-preprocessor-json` |
181
- | | `model-tokenizer-json` |
182
- | | `model-opaque-data` |
183
- | | `voice-style-binary` |
184
-
185
- Paths and immutable source URLs are globally unique within a graph. Positive
186
- runtime request aliases are also unique and cannot overlap a source URL or a
187
- negative route. Every non-entry file must be reachable from the declared ONNX
188
- pair, TTS voice inventory, or one exact edge; unreachable files and routes are
189
- rejected rather than silently retained.
190
-
191
- ### Edge and transform descriptors
192
-
193
- Edge `occurrence` values are positive, one-based occurrences in the named
194
- `modulePath`. A declaration must match the scanner's exact source occurrence;
195
- missing, duplicate, extra, occurrence-mismatched, or undeclared runtime edges
196
- fail closed. Descriptor collections are canonically sorted for graph identity,
197
- so caller array order is not semantic.
198
-
199
- | Collection | Exact record |
200
- | --- | --- |
201
- | `edges.staticImports` | `{modulePath,occurrence,specifier,targetPath}`. The literal specifier and declared JavaScript target must match. |
202
- | `edges.dynamicImports` | `{modulePath,occurrence,edgePolicy,targets}`. Each target is `{match,targetPath,exactSpecifier?}`. `exactSpecifier` is required only for `exact-runtime-specifier`. |
203
- | `edges.moduleWorkers` | Same shape as dynamic imports; `self-module-url` is additionally available and must target the declaring module. Only module Workers are admitted. |
204
- | `edges.fetches` | `{modulePath,occurrence,edgePolicy,methods:["GET"],targetPaths,negativeRuntimeRequestUrls,allowMaterializedUrls}`. `methods` defaults to the same one-element `GET` array; the two target arrays default empty; `allowMaterializedUrls` is `true` only when explicitly set and otherwise normalizes to `false`. No other method is admitted, and a fetch target cannot be JavaScript. |
205
- | `edges.cacheOpens` | `{modulePath,occurrence,edgePolicy,cacheName,targetPaths}`. `artifact-targets-admitted` requires at least one exact non-JavaScript file path; `inactive-runtime-branch-rejected` requires none. The returned cache can read only those files. |
206
- | `transforms` | `{kind,modulePath,occurrence}`. `function-return-this-to-global-this` replaces the one audited `Function("return this")()` pattern. `typed-array-constructor` rewrites only a scanner-recognized typed-array `.constructor(...)` call and later proves the receiver uses an intrinsic typed-array prototype. |
207
-
208
- An omitted `edgePolicy` normalizes to `artifact-targets-admitted`, which
209
- requires a declared target. An
210
- `inactive-runtime-branch-rejected` edge has no target and proves only that the
211
- branch must remain inactive; execution of that occurrence rejects. The source
212
- scanner rejects undeclared imports, fetches, Workers, executable-string
213
- construction or constructor access, Cache Storage access outside a direct
214
- declared `caches.open(...)`, computed capability access, ambiguous tokens, and
215
- unmatched transforms. It also reserves the SDK guard name so artifact code
216
- cannot address the guard directly. Static import cycles are rejected so
217
- materialization order remains deterministic; runtime isolation separately
218
- denies every raw transport listed below.
219
-
220
- The returned graph is deeply frozen and has exactly
221
- `{protocol,kind,providerId,role,model,runtime,files,edges,transforms,identitySha256,artifactGraphStatus}`.
222
- The status is `artifact-graph-descriptor-verified`. Its computed identity binds
223
- every preceding descriptor field, including paths, revisions, licenses,
224
- runtime aliases, edge policy, and transform occurrences; the status itself is
225
- the result of that computation rather than identity input.
226
-
227
- ## `createDbopfsSpeechArtifactStore()`
228
-
229
- ```text
230
- createDbopfsSpeechArtifactStore({
231
- dbopfs,
232
- tableName = 'arcane_ai_browser_speech',
233
- fetchImpl = null,
234
- objectUrlFactory = null
235
- } = {})
236
- ```
237
-
238
- The frozen store exposes `{protocol,tableName,prepare,remove}`. It accepts both
239
- the authenticated graph above and an SDK-created legacy authority.
240
- `objectUrlFactory` remains a legacy compatibility seam. Graph preparation
241
- ignores it and uses module-captured native Blob URL creation, revocation, and
242
- fetch so a caller cannot substitute the executable materialization boundary.
243
-
244
- For a graph, `prepare(graph,{signal,onProgress,offline=false,security})` follows
245
- the shared model-security flag and requires explicit `secure:true`. The graph is
246
- the opt-in strict path: it enables byte-length, SHA-256, and undeclared-
247
- capability enforcement. Ordinary warn-first operation uses the direct
248
- `model`/`runtime` authority described below and does not construct or admit an
249
- artifact graph.
250
-
251
- ### Cold admission
252
-
253
- 1. Acquire the exact authority's exclusive Web Lock.
254
- 2. Delete incomplete prior state.
255
- 3. Fetch only each declared immutable `sourceUrl` using `credentials:"omit"`,
256
- `cache:"no-store"`, `mode:"cors"`, and `referrerPolicy:"no-referrer"`.
257
- The default is `redirect:"error"`; only a file with declared
258
- `redirectFinalOrigins` uses `redirect:"follow"`.
259
- 4. Without a followed redirect, require the response URL to remain exactly the
260
- immutable `sourceUrl`. After a followed redirect, require a readable final
261
- HTTPS URL without credentials or a fragment and require its canonical origin
262
- to occur in that file's declared final-origin inventory.
263
- 5. Require the response Content-Type to equal `sourceMediaType` (which defaults
264
- to `mediaType`), then stream exact byte-length and SHA-256 verification into
265
- DBOPFS.
266
- 6. Reopen and rehash every persisted file.
267
- 7. Decode and scan every runtime JavaScript file and prove exact edge/transform
268
- closure.
269
- 8. Persist `arcane.ai.browser-speech.authenticated-artifact-graph.v1` only
270
- after every file and the complete runtime graph pass.
271
-
272
- The returned admission is
273
- `artifact-graph-network-dbopfs-verified`. A failure before manifest completion
274
- removes the graph's incomplete records.
275
-
276
- `redirectFinalOrigins` admits only a final origin, not a final path, query, or
277
- signed/expiring URL. The browser may follow such an implementation-specific
278
- final URL, but that URL is neither persisted nor accepted as source, revision,
279
- signature, graph identity, or future download authority. Trust remains bound to
280
- the immutable starting `sourceUrl` and the exact authenticated length and
281
- SHA-256 of the received bytes.
282
-
283
- Browser Fetch exposes the final CORS response, not an inspectable list of every
284
- intermediate redirect hop. The SDK therefore cannot authenticate intermediate
285
- hop origins or headers. CORS must succeed for the browser-managed chain, and
286
- the SDK can enforce only the immutable start, the declared final HTTPS origin,
287
- the final response metadata, and the end-to-end bytes. A caller that requires
288
- every hop to be independently pinned must use a direct immutable source rather
289
- than this redirect opt-in.
290
-
291
- ### Warm and offline admission
292
-
293
- A warm prepare requires the exact manifest authority and file count, reopens
294
- every DBOPFS record, checks the manifest's observed bytes and declared SHA-256,
295
- rehashes every file, and rescans the runtime graph before returning
296
- `artifact-graph-dbopfs-cache-verified`.
297
-
298
- `offline:true` runs the same cache verification and never calls the source
299
- fetch function. It returns
300
- `artifact-graph-offline-dbopfs-cache-verified`, or rejects with code
301
- `ARCANE_AI_ARTIFACT_GRAPH_OFFLINE_CACHE_MISS` and reason
302
- `artifact-graph-offline-cache-miss`. There is no network repair, runtime CDN,
303
- private Cache Storage fallback, or partial-cache admission.
304
-
305
- The manifest authority binds each file's `sourceMediaType` and
306
- `redirectFinalOrigins` through the graph identity. A valid warm or offline
307
- admission does not resolve the starting URL again, follow a redirect, or reuse a
308
- prior final URL; it authenticates only the complete cached bytes and graph.
309
-
310
- After every cold, warm, or offline admission, the store materializes a fresh
311
- set of unique native `blob:` URLs. Each URL is fetched back with omitted
312
- credentials and redirect rejection, and its exact URL identity, media type,
313
- byte length, and SHA-256 are compared with the Blob that was created. Only then
314
- does the SDK apply the already-scanned deterministic module rewrites. A fresh
315
- cryptographically random 32-byte lowercase-hex guard capability binds every
316
- rewritten dynamic import, fetch, cache-open, child-Worker, and typed-array call
317
- for that materialization. The capability is ephemeral: it is neither supplied
318
- by the caller nor persisted in the manifest or graph identity.
319
-
320
- Successful graph preparation returns:
321
-
322
- ```text
323
- {
324
- cache, // the exact graph admission value
325
- artifactGraphId,
326
- artifactGraphAdmission,
327
- runtime: {
328
- ...normalizedRuntime,
329
- files, edges, transforms,
330
- guardCapability,
331
- artifactGraphId,
332
- artifactGraphAdmission
333
- },
334
- model: {...normalizedModel, files},
335
- release
336
- }
337
- ```
338
-
339
- `release()` revokes the materialized object URLs after Worker termination. It
340
- does not delete the caller-owned DBOPFS cache. `remove(graph)` is the explicit
341
- cache-deletion operation.
342
-
343
- ## Authenticated Worker host
344
-
345
- Graph loading creates one dedicated Worker for the selected role. Its first
346
- load envelope transfers a new private `MessagePort`; all graph responses,
347
- progress, cancellation settlement, and later operations stay on that port.
348
- Graph loading rejects if `MessageChannel`/`MessagePort` is unavailable, if a
349
- legacy global transport was already selected, or if the Worker receives a graph
350
- load without the private port. The published single-module compatibility path
351
- continues to use the original Worker-global message transport.
352
-
353
- Before importing the entrypoint, the graph Worker installs these fail-closed
354
- boundaries:
355
-
356
- - exact graph routes map declared source URLs, runtime aliases, and materialized
357
- URLs to already authenticated object URLs;
358
- - the ephemeral guard capability must match at every rewritten call;
359
- - global `fetch` rejects unless the scanned source was rewritten to one
360
- declared fetch edge;
361
- - global Cache Storage `open` and `match` reject unless the scanned
362
- `caches.open(...)` was rewritten to one exact declared cache-open edge; its
363
- returned read-only cache serves only `targetPaths`, while `put`, `add`, and
364
- `addAll` reject, so DBOPFS remains the sole durable store;
365
- - a `typed-array-constructor` rewrite returns only the intrinsic constructor of
366
- a verified typed-array receiver; an own or non-intrinsic `constructor`
367
- rejects;
368
- - the `Function`, `AsyncFunction`, `GeneratorFunction`, and
369
- `AsyncGeneratorFunction` prototype constructor escape is replaced before
370
- import, and string callbacks to `setTimeout` or `setInterval` reject;
371
- - `indexedDB` and `navigator.storage`/OPFS are made unavailable;
372
- - raw `BroadcastChannel`, `EventSource`, `Function`, `RTCPeerConnection`,
373
- `ShadowRealm`, `SharedWorker`, `WebSocket`, `WebSocketStream`, `WebTransport`,
374
- `Worker`, `XMLHttpRequest`, `eval`, and `importScripts` capabilities are
375
- denied; and
376
- - an admitted child module Worker is created through the SDK's role Worker,
377
- receives the authenticated graph configuration, installs the same guard, and
378
- imports only its declared materialized target.
379
-
380
- An immutable `sourceUrl` may be an explicitly caller-selected HTTPS origin,
381
- but runtime execution cannot escalate to that or another network origin. Its
382
- declared request is answered from authenticated local object bytes, and any
383
- other request or import edge rejects.
384
-
385
- ### ONNX Runtime Web configuration
386
-
387
- The Worker accepts only the two mechanically verified namespace shapes:
388
-
389
- - Kokoro: `namespace.env.wasmPaths = {mjs,wasm}`. No Kokoro cache setting or
390
- thread setting is invented. A missing property rejects as
391
- `kokoro-env-wasm-paths-unavailable`; a property that rejects or does not
392
- retain the exact assignment rejects as
393
- `kokoro-env-wasm-paths-assignment-rejected`.
394
- - Transformers: `namespace.env.backends.onnx.wasm.wasmPaths = {mjs,wasm}`.
395
- The Worker also requires the verified outer `env` fields, sets
396
- `allowLocalModels:false`, `allowRemoteModels:true`, `useBrowserCache:false`,
397
- and `useFSCache:false`. With no admitted `cacheOpens` edge named exactly
398
- `transformers-cache`, it assigns `useCustomCache:false` and `customCache:null`.
399
- With exactly one such edge it assigns `useCustomCache:true` and the
400
- target-limited read-only graph facade; more than one rejects as ambiguous.
401
- Only a caller-declared STT `numThreads` is assigned. The
402
- `allowRemoteModels` value permits the audited library code path to issue its
403
- declared request; the graph guard still prevents network access and serves
404
- only exact local graph routes.
405
-
406
- For Transformers, the exact missing-field reasons are
407
- `transformers-env-backends-onnx-wasm-unavailable`,
408
- `transformers-env-allow-local-models-unavailable`,
409
- `transformers-env-allow-remote-models-unavailable`,
410
- `transformers-env-browser-cache-unavailable`,
411
- `transformers-env-fs-cache-unavailable`,
412
- `transformers-env-custom-cache-toggle-unavailable`, and
413
- `transformers-env-custom-cache-unavailable`. The corresponding exact
414
- assignment-rejection reasons are
415
- `transformers-env-allow-local-models-assignment-rejected`,
416
- `transformers-env-allow-remote-models-assignment-rejected`,
417
- `transformers-env-browser-cache-assignment-rejected`,
418
- `transformers-env-fs-cache-assignment-rejected`,
419
- `transformers-env-custom-cache-toggle-assignment-rejected`, and
420
- `transformers-env-custom-cache-assignment-rejected`. The optional, creatable
421
- ONNX fields fail assignment as
422
- `transformers-env-wasm-paths-assignment-rejected` or
423
- `transformers-env-num-threads-assignment-rejected`; their defensive
424
- unavailable reasons are `transformers-env-wasm-paths-unavailable` and
425
- `transformers-env-num-threads-unavailable`. Every case rejects with
426
- `ARCANE_AI_PROVIDER_UNAVAILABLE`; the Worker never guesses a different
427
- namespace shape.
428
-
429
- Kokoro's audited bundle hard-codes a mutable
430
- `.../resolve/main/voices/${voice}.bin` request and opens `kokoro-voices` Cache
431
- Storage. That URL is never accepted as `sourceUrl`. An operational graph must
432
- declare the exact resolved voice file as an immutable authenticated source,
433
- bind the hard-coded URL only as that file's `runtimeRequestUrls` alias, and
434
- declare the exact `cacheOpens` occurrence with `cacheName:"kokoro-voices"` and
435
- the caller-owned voice paths. Every scanned fetch occurrence still requires its
436
- own explicit admitted or inactive policy. The Worker satisfies the cache read
437
- from verified local voice bytes; it never opens Kokoro's private durable cache.
438
- If the graph does not prove those exact edges, Kokoro fails closed before the
439
- mutable request can reach the network.
440
-
441
- That graph closure is an optional caller-owned secure/offline configuration,
442
- not the public runtime's default and not a publication gate. In warn-first mode
443
- the SDK loads the caller-selected version-pinned upstream package and provider
444
- assets from their publishers. The SDK neither republishes those bytes nor
445
- requires their optional provenance or legal metadata before the provider can
446
- operate. When `secure:true` is selected, incomplete graph metadata rejects that
447
- specific secure load without disabling ordinary warn-first operation.
448
-
449
- ## Providers
450
-
451
- ```text
452
- createBrowserWhisperProvider({
453
- id = 'arcane-browser-whisper',
454
- localOnly = true,
455
- graph?,
456
- model?, runtime?,
457
- store,
458
- offline = false,
459
- appSecurity,
460
- security
461
- } = {})
462
-
463
- createBrowserKokoroProvider({
464
- id = 'arcane-browser-kokoro',
465
- localOnly = true,
466
- graph?,
467
- model?, runtime?,
468
- store,
469
- offline = false,
470
- appSecurity,
471
- security
472
- } = {})
473
- ```
474
-
475
- `graph` is mutually exclusive with the legacy `model`/`runtime` options and may
476
- load only when effective security explicitly selects `secure:true`. Both
477
- constructors require an SDK-created DBOPFS speech store and return one frozen
478
- `arcane-ai-provider/2` object:
479
-
480
- ```text
481
- {
482
- protocol, role, id, localOnly,
483
- catalog, inspect, status, load, request, unload, dispose
484
- }
485
- ```
486
-
487
- `localOnly` must remain `true`. `offline:true` makes every later explicit load
488
- use strict offline graph/cache admission; it does not trigger a load itself.
489
-
490
- `catalog()` exposes only the caller's selected model/runtime/files. A graph
491
- catalog also reports `artifactGraphId`, caller dtype, exact sample rate, and the
492
- caller voice inventory. Its one exact catalog record is
493
- `{id,providerId,role,localOnly,defaultVoice?,repository,revision,dtype?,runtime,files,artifactGraphId?,voices?,speech}`;
494
- the `speech` record is `{inputSampleRate}` for STT or
495
- `{outputSampleRate,responseFormats:["wav"],defaultResponseFormat:"wav"}` for
496
- TTS.
497
-
498
- `inspect()` admits only the exact provider/model/local selection and, when
499
- supplied, the matching role. A successful graph inspection returns
500
- `{available:true,authority}`. Its frozen authority has exactly
501
- `{protocol,admitted,graph,artifactGraphProtocol,providerId,role,modelId,repository,revision,dtype,defaultVoice,voices,inputSampleRate,outputSampleRate,runtime,files,security,artifactGraphId}`;
502
- `protocol` is `arcane-ai-model-authority/1` and `artifactGraphId` is the graph
503
- identity. An unavailable record uses
504
- `ARCANE_AI_MODEL_AUTHORITY_REQUIRED` and the exact role-specific reason
505
- `stt-provider-inspection-selection-authority-mismatch` or
506
- `tts-provider-inspection-selection-authority-mismatch`. `load()` is explicit;
507
- construction, catalog, status, and inspection never start a download or Worker.
508
-
509
- ### Whisper STT
510
-
511
- The provider-native operation is:
512
-
513
- ```javascript
514
- const result = await whisper.request({
515
- role: 'stt',
516
- operation: 'transcribe',
517
- signal,
518
- payload: {
519
- audio: pcmFloat32,
520
- sampleRate: graph.model.inputSampleRate
521
- }
522
- });
523
- ```
524
-
525
- The native payload is exact `Float32Array` mono PCM at the graph's
526
- caller-selected input sample rate. The result is `{text}`. The shared AI
527
- payload `{audio:Blob|File,mimeType,model}` verifies the exact model, uses the
528
- browser decoder to normalize to that same rate, and then enters the same Worker
529
- operation. Multi-channel decoded audio is averaged to one mono `Float32Array`.
530
- Cancellation during Blob/audio decoding rejects with
531
- `ARCANE_AI_REQUEST_ABORTED` / `stt-transcription-cancelled` while the already
532
- loaded Worker remains ready.
533
-
534
- ### Kokoro TTS
535
-
536
- ```javascript
537
- const result = await kokoro.request({
538
- role: 'tts',
539
- operation: 'synthesize',
540
- signal,
541
- payload: {
542
- text: 'Hello from Arcane.',
543
- voice: 'caller-voice-id',
544
- speed: 1
545
- }
546
- });
547
- ```
548
-
549
- `voice` must belong to the graph's caller-declared inventory; omission uses
550
- only that graph's `model.defaultVoice`. `speed` must be greater than zero and at
551
- most four. The provider-native result is
552
- `{audio:Float32Array,sampleRate,voice}` at the caller-selected output sample
553
- rate. The shared AI payload `{model,input,responseFormat,voice?,speed?}` accepts
554
- only `responseFormat:"wav"` and returns frozen
555
- `{audio:Uint8Array,contentType:"audio/wav"}` containing mono signed 16-bit PCM
556
- at the caller-selected output rate. No saved voice from another route is
557
- substituted.
558
-
559
- ## Lifecycle, progress, cancellation, and cleanup
560
-
561
- Provider `status()` returns:
562
-
563
- ```text
564
- {
565
- role,
566
- providerId,
567
- modelId,
568
- state,
569
- lifecycleStatus,
570
- lifecycleReason,
571
- activeOperation,
572
- loaded,
573
- busy,
574
- generation,
575
- errorCode,
576
- cache,
577
- artifactGraphId,
578
- artifactGraphAdmission
579
- }
580
- ```
581
-
582
- The provider states are exactly `unloaded`, `loading`, `ready`, `unloading`,
583
- `error`, and `disposed`. `lifecycleStatus` is therefore exactly one of
584
- `stt-provider-unloaded`, `stt-provider-loading`, `stt-provider-ready`,
585
- `stt-provider-unloading`, `stt-provider-error`, `stt-provider-disposed`,
586
- `tts-provider-unloaded`, `tts-provider-loading`, `tts-provider-ready`,
587
- `tts-provider-unloading`, `tts-provider-error`, or `tts-provider-disposed`.
588
-
589
- `activeOperation` is `null` or one of `stt-provider-load`,
590
- `tts-provider-load`, `stt-provider-transcription`, `tts-provider-synthesis`,
591
- `stt-provider-unload`, `tts-provider-unload`, `stt-provider-dispose`, and
592
- `tts-provider-dispose`.
593
-
594
- `loaded` is true only for `ready`. `busy` reports an active transcription or
595
- synthesis request; load, unload, and dispose remain visible through `state` and
596
- `activeOperation`. `cache` is `null`, a graph admission value, or the legacy
597
- `installed`/`cached` value. Graph identity and admission are otherwise `null`.
598
-
599
- Provider-owned lifecycle reasons are:
600
-
601
- - creation and load: `stt-provider-created`, `tts-provider-created`,
602
- `stt-load-started`, `tts-load-started`, `stt-load-completed`,
603
- `tts-load-completed`, `stt-load-cancelled`, `tts-load-cancelled`,
604
- `stt-provider-load-rejected`, `tts-provider-load-rejected`,
605
- `stt-load-rejected-during-unload`,
606
- `tts-load-rejected-during-unload`,
607
- `stt-load-superseded-by-security-change`,
608
- `tts-load-superseded-by-security-change`,
609
- `stt-load-superseded-by-unload`, `tts-load-superseded-by-unload`,
610
- `stt-load-progress-callback-threw`, and
611
- `tts-load-progress-callback-threw`;
612
- - use: `stt-transcription-started`, `stt-transcription-completed`,
613
- `stt-transcription-cancelled`,
614
- `stt-transcription-engine-operation-rejected`,
615
- `tts-synthesis-started`, `tts-synthesis-completed`,
616
- `tts-synthesis-cancelled`, `tts-synthesis-engine-operation-rejected`,
617
- `stt-transcription-superseded-by-unload`, and
618
- `tts-synthesis-superseded-by-unload`;
619
- - teardown: `stt-unload-started`, `tts-unload-started`,
620
- `stt-unload-completed`, `tts-unload-completed`, `stt-dispose-started`,
621
- `tts-dispose-started`, `stt-dispose-completed`, `tts-dispose-completed`,
622
- `stt-worker-terminated-by-unload`, `tts-worker-terminated-by-unload`,
623
- `stt-worker-terminated`, and `tts-worker-terminated`; and
624
- - Worker failure: `stt-worker-crashed`, `tts-worker-crashed`,
625
- `stt-worker-message-rejected`, `tts-worker-message-rejected`,
626
- `stt-worker-private-message-rejected`,
627
- `tts-worker-private-message-rejected`,
628
- `stt-worker-progress-envelope-rejected`,
629
- `tts-worker-progress-envelope-rejected`,
630
- `stt-worker-response-envelope-shape-rejected`,
631
- `tts-worker-response-envelope-shape-rejected`,
632
- `stt-worker-error-envelope-rejected`, `tts-worker-error-envelope-rejected`,
633
- `stt-worker-protocol-mismatch`, and
634
- `tts-worker-protocol-mismatch`.
635
-
636
- When an active load or use fails with one of the stable reasons below, the
637
- provider preserves that exact reason as `lifecycleReason`; it does not collapse
638
- the boundary to a generic failure label.
639
-
640
- Worker statuses use exactly `stt-worker-unloaded`, `stt-worker-ready`,
641
- `stt-worker-disposed`, `tts-worker-unloaded`, `tts-worker-ready`, and
642
- `tts-worker-disposed`. The nested bootstrap status is exactly
643
- `stt-artifact-module-worker-awaiting-initialization` or
644
- `tts-artifact-module-worker-awaiting-initialization`.
645
-
646
- Worker `activeOperation` is `null`, `stt-load`, `tts-load`,
647
- `stt-transcription`, `tts-synthesis`, `stt-status`, `tts-status`, `stt-unload`,
648
- `tts-unload`, `stt-dispose`, or `tts-dispose`. Its own lifecycle starts with
649
- `stt-worker-created` or `tts-worker-created`. Load uses exactly
650
- `stt-load-started`, `stt-load-completed`, `stt-load-cancelled`,
651
- `stt-worker-runtime-configuration-rejected`,
652
- `stt-worker-runtime-import-rejected`, `stt-worker-model-load-rejected`,
653
- `tts-load-started`, `tts-load-completed`, `tts-load-cancelled`,
654
- `tts-worker-runtime-configuration-rejected`,
655
- `tts-worker-runtime-import-rejected`, and
656
- `tts-worker-model-load-rejected`. Use uses exactly
657
- `stt-transcription-started`, `stt-transcription-completed`,
658
- `stt-transcription-cancelled`, `stt-transcription-engine-operation-rejected`,
659
- `tts-synthesis-started`, `tts-synthesis-completed`,
660
- `tts-synthesis-cancelled`, and `tts-synthesis-engine-operation-rejected`; a stable underlying
661
- reason replaces only the matching failure fallback. Orderly Worker teardown
662
- additionally uses `stt-unload-completed`,
663
- `tts-unload-completed`, `stt-worker-engine-dispose-rejected`,
664
- `tts-worker-engine-dispose-rejected`, `stt-dispose-unloaded-worker`,
665
- `tts-dispose-unloaded-worker`, `stt-dispose-completed`, and
666
- `tts-dispose-completed`. A Worker protocol cancel result is
667
- `stt-cancel-target-not-active` or `tts-cancel-target-not-active` when its target
668
- is already settled; otherwise it names the exact cancelled load, transcription,
669
- synthesis, status, unload, or dispose operation.
670
-
671
- The Worker client admits only `load`, `use`, `status`, `unload`, and `dispose`.
672
- The transport host additionally admits only its internal `cancel` control
673
- message. Any other `op` rejects as `ARCANE_AI_INVALID_REQUEST` with
674
- message `The speech worker operation is not part of its protocol.` and reason
675
- `stt-worker-operation-unknown` or `tts-worker-operation-unknown` before it can
676
- enter active-operation, cancellation, or serialized-error naming.
677
-
678
- Progress records have exactly `{phase,completed,total,unit,heartbeat}`. They do
679
- not add a `role` field; Worker phase names carry the role and the provider
680
- forwards the same provider-neutral record. Graph store phases are exactly
681
- `artifact-graph-network-download`,
682
- `artifact-graph-dbopfs-persisted-rehash`, and
683
- `artifact-graph-dbopfs-cache-rehash`. Worker phases are
684
- `stt-runtime-import-started`, `tts-runtime-import-started`,
685
- `stt-model-load-started`, `tts-model-load-started`,
686
- `stt-model-load-progress`, `tts-model-load-progress`,
687
- `stt-provider-ready`, and `tts-provider-ready`.
688
-
689
- `load(context)` requires the exact role/selection and a `progress` function.
690
- Compatible concurrent loads coalesce behind one underlying preparation/Worker
691
- operation while each caller keeps its own progress callback and cancellation
692
- observation. Cancelling or throwing from the last observer aborts that shared
693
- load; one observer cannot cancel another observer that remains attached. A
694
- security change unloads and reloads; graph verification itself can never be
695
- weakened. `request(context)` admits one role operation at a time and otherwise
696
- rejects with `ARCANE_AI_PROVIDER_BUSY`.
697
-
698
- An `AbortSignal` before or during graph preparation/load rejects that exact
699
- operation. Once a Worker request has started, cancellation terminates the whole
700
- role Worker, rejects every pending operation, closes private ports, terminates
701
- nested Workers, discards that isolated Worker's guards and runtime settings,
702
- revokes object URLs, and returns the provider to `unloaded`; a later request
703
- requires explicit load. `unload()` uses the same destructive boundary for
704
- active load/use before
705
- releasing state. `dispose()` completes unload and permanently enters
706
- `disposed`. Cancelling an `unload()` or `dispose()` caller rejects only that
707
- caller's wait with the corresponding stable reason; the already-started shared
708
- teardown continues to its terminal state. Late results are generation-checked
709
- and cannot settle a superseded operation.
710
-
711
- The provider owns no listener registry or event source. Applications may
712
- project its promises, status, and progress records into the one SDK event/state
713
- authority, and DOM components may project presentation/intent events, but this
714
- package creates no `EventPubSub`, exposes no public `EventTarget` lifecycle
715
- source, and owns no competing listener registry or event bus.
716
-
717
- The provider also has no implicit mute flag. A higher-level shared state owner
718
- can implement mute by awaiting the role's explicit `unload()` and unmute by
719
- performing an explicit `load()`; it projects the returned status and progress
720
- without inventing a second provider, listener registry, or background load.
721
-
722
- ## Stable errors and reasons
723
-
724
- Operational graph, provider, client, and Worker rejections expose a stable
725
- `code` and a concise `reason` naming the failed operation or boundary.
726
- `ARCANE_AI_REQUEST_ABORTED` errors use `name:"AbortError"`; an arbitrary
727
- caller `AbortSignal.reason` is retained only as `cause` and cannot replace the
728
- stable public reason. Immediate JavaScript API-shape misuse can instead throw a
729
- plain `TypeError` before an operation exists.
730
-
731
- ### Compatibility and provider codes
732
-
733
- Worker failures cross the private port only in the exact envelope
734
- `{protocol:"arcane-ai-speech-worker-error/1",code,message,reason}`. Its own-key
735
- set must be exactly `code,message,protocol,reason`, every field must be a data
736
- property rather than an accessor, `protocol` and `message` must match the
737
- registered code, and the finite registered code/reason pair must match the
738
- pending role and operation. A missing field, extra string or symbol key,
739
- foreign value, accessor, or cross-role/cross-operation pairing is rejected and
740
- the role Worker is terminated; arbitrary third-party error fields never become
741
- public authority.
742
-
743
- | Code | Exact caller-visible reasons |
744
- | --- | --- |
745
- | `ARCANE_AI_MODEL_AUTHORITY_REQUIRED` | `stt-provider-inspection-selection-authority-mismatch`, `tts-provider-inspection-selection-authority-mismatch`, `stt-load-selection-authority-mismatch`, `tts-load-selection-authority-mismatch`, `stt-provider-request-selection-authority-mismatch`, `tts-provider-request-selection-authority-mismatch`, `stt-provider-unload-selection-authority-mismatch`, `tts-provider-unload-selection-authority-mismatch`, `stt-provider-dispose-selection-authority-mismatch`, `tts-provider-dispose-selection-authority-mismatch`, `stt-transcription-model-authority-missing`, `stt-transcription-model-authority-mismatch`, `tts-synthesis-model-authority-missing`, `tts-synthesis-model-authority-mismatch`, `tts-synthesis-voice-not-declared` |
746
- | `ARCANE_AI_INVALID_REQUEST` | The exact context/payload and Worker reasons enumerated immediately below this table. |
747
- | `ARCANE_AI_NOT_READY` | `stt-provider-request-not-ready`, `tts-provider-request-not-ready`, `stt-transcription-rejected-before-load`, `tts-synthesis-rejected-before-load` |
748
- | `ARCANE_AI_PROVIDER_BUSY` | `stt-provider-request-already-active`, `tts-provider-request-already-active` |
749
- | `ARCANE_AI_PROVIDER_DISPOSED` | `stt-provider-load-rejected-after-dispose`, `tts-provider-load-rejected-after-dispose`, `stt-load-rejected-after-dispose`, `tts-load-rejected-after-dispose` |
750
- | `ARCANE_AI_REQUEST_ABORTED` | `stt-provider-inspection-cancelled`, `tts-provider-inspection-cancelled`, `stt-load-cancelled`, `tts-load-cancelled`, `stt-transcription-cancelled`, `tts-synthesis-cancelled`, `stt-unload-cancelled`, `tts-unload-cancelled`, `stt-dispose-cancelled`, `tts-dispose-cancelled`, `stt-status-cancelled`, `tts-status-cancelled`, `artifact-graph-preparation-cancelled` |
751
- | `ARCANE_AI_OPERATION_SUPERSEDED` | `stt-load-rejected-during-unload`, `tts-load-rejected-during-unload`, `stt-load-superseded-by-security-change`, `tts-load-superseded-by-security-change`, `stt-load-superseded-by-unload`, `tts-load-superseded-by-unload`, `stt-transcription-superseded-by-unload`, `tts-synthesis-superseded-by-unload`, `stt-worker-terminated-by-unload`, `tts-worker-terminated-by-unload`, `stt-worker-terminated`, `tts-worker-terminated`, `stt-worker-already-terminated`, `tts-worker-already-terminated` |
752
- | `ARCANE_AI_AUDIO_DECODE_UNAVAILABLE` | `stt-browser-offline-audio-context-unavailable`, `stt-browser-offline-audio-context-construction-rejected`, `stt-browser-audio-decode-method-unavailable` |
753
- | `ARCANE_AI_AUDIO_DECODE_FAILED` | `stt-browser-audio-decode-operation-rejected`, `stt-browser-decoded-audio-not-object`, `stt-browser-decoded-audio-sample-rate-mismatch`, `stt-browser-decoded-audio-frame-length-not-safe-integer`, `stt-browser-decoded-audio-empty`, `stt-browser-decoded-audio-channel-count-not-safe-integer`, `stt-browser-decoded-audio-channel-count-zero`, `stt-browser-decoded-audio-get-channel-data-not-function`, `stt-browser-decoded-audio-channel-read-rejected`, `stt-browser-decoded-audio-channel-not-float32-array`, `stt-browser-decoded-audio-channel-length-mismatch`, `stt-browser-decoded-audio-sample-non-finite` |
754
- | `ARCANE_AI_UNSUPPORTED_RESPONSE_FORMAT` | `tts-synthesis-response-format-not-wav` |
755
- | `ARCANE_AI_INVALID_PROVIDER_RESULT` | `stt-transcription-result-text-not-string`, `tts-synthesis-result-not-object`, `tts-synthesis-result-audio-not-float32-array`, `tts-synthesis-result-sample-rate-mismatch`, `tts-synthesis-result-audio-empty`, `tts-synthesis-result-wav-byte-length-overflow`, `tts-synthesis-pcm-result-not-float32array`, `tts-synthesis-pcm-sample-non-finite` |
756
- | `ARCANE_AI_PROVIDER_LOAD_FAILED` | `stt-provider-load-rejected`, `tts-provider-load-rejected` |
757
- | `ARCANE_AI_PROVIDER_REQUEST_FAILED` | `stt-worker-runtime-configuration-rejected`, `tts-worker-runtime-configuration-rejected`, `stt-worker-runtime-import-rejected`, `tts-worker-runtime-import-rejected`, `stt-worker-model-load-rejected`, `tts-worker-model-load-rejected`, `stt-transcription-engine-operation-rejected`, `tts-synthesis-engine-operation-rejected`, `stt-worker-engine-dispose-rejected`, `tts-worker-engine-dispose-rejected`, `stt-worker-dispose-rejected`, `tts-worker-dispose-rejected`, `stt-worker-status-rejected`, `tts-worker-status-rejected` |
758
- | `ARCANE_AI_PROVIDER_UNAVAILABLE` | `speech-worker-fetch-unavailable`, `artifact-graph-fetch-constructor-unavailable`, `artifact-graph-negative-response-constructor-unavailable`, `artifact-graph-module-worker-constructor-unavailable`, `artifact-graph-onnx-wasm-pair-not-materialized`, `transformers-env-backends-onnx-wasm-unavailable`, `transformers-env-allow-local-models-unavailable`, `transformers-env-allow-local-models-assignment-rejected`, `transformers-env-allow-remote-models-unavailable`, `transformers-env-allow-remote-models-assignment-rejected`, `transformers-env-browser-cache-unavailable`, `transformers-env-browser-cache-assignment-rejected`, `transformers-env-fs-cache-unavailable`, `transformers-env-fs-cache-assignment-rejected`, `transformers-env-custom-cache-toggle-unavailable`, `transformers-env-custom-cache-toggle-assignment-rejected`, `transformers-env-custom-cache-unavailable`, `transformers-env-custom-cache-assignment-rejected`, `transformers-env-wasm-paths-unavailable`, `transformers-env-wasm-paths-assignment-rejected`, `transformers-env-num-threads-unavailable`, `transformers-env-num-threads-assignment-rejected`, `transformers-whisper-pipeline-export-missing`, `stt-transcription-method-unavailable`, `kokoro-env-wasm-paths-unavailable`, `kokoro-env-wasm-paths-assignment-rejected`, `kokoro-tts-constructor-export-missing`, `tts-synthesis-method-unavailable` |
759
- | `ARCANE_AI_LOAD_PROGRESS_CALLBACK_THREW` | `stt-load-progress-callback-threw`, `tts-load-progress-callback-threw` at the public provider observer boundary |
760
- | `ARCANE_AI_PROGRESS_CALLBACK_THREW` | `stt-load-progress-callback-threw`, `tts-load-progress-callback-threw` at the internal Worker-client callback boundary |
761
- | `ARCANE_AI_ADAPTER_PROTOCOL_MISMATCH` | `stt-worker-client-authority-mismatch`, `tts-worker-client-authority-mismatch`, `stt-worker-protocol-mismatch`, `tts-worker-protocol-mismatch`, `artifact-graph-private-message-port-established-too-late`, `stt-worker-runtime-transport-mode-mismatch`, `tts-worker-runtime-transport-mode-mismatch` |
762
- | `ARCANE_AI_WORKER_CRASHED` | `stt-worker-crashed`, `tts-worker-crashed` |
763
- | `ARCANE_AI_WORKER_MESSAGE_ERROR` | `stt-worker-message-rejected`, `tts-worker-message-rejected`, `stt-worker-private-message-rejected`, `tts-worker-private-message-rejected`, `stt-worker-progress-envelope-rejected`, `tts-worker-progress-envelope-rejected`, `stt-worker-response-envelope-shape-rejected`, `tts-worker-response-envelope-shape-rejected`, `stt-worker-error-envelope-rejected`, `tts-worker-error-envelope-rejected`, `stt-load-message-rejected`, `tts-load-message-rejected`, `stt-transcription-message-rejected`, `tts-synthesis-message-rejected`, `stt-status-message-rejected`, `tts-status-message-rejected`, `stt-unload-message-rejected`, `tts-unload-message-rejected`, `stt-dispose-message-rejected`, `tts-dispose-message-rejected`, `artifact-graph-private-message-channel-unavailable`, `artifact-graph-private-message-port-unavailable`, `artifact-graph-module-worker-error-envelope-rejected`, `artifact-graph-module-worker-initialization-message-rejected` |
764
- | `ARCANE_AI_WORKER_MESSAGE_REJECTED` | `stt-worker-error-envelope-rejected`, `tts-worker-error-envelope-rejected` when the provider rejects a foreign or missing SDK error brand |
765
- | `ARCANE_AI_UNDECLARED_ARTIFACT` | `speech-worker-artifact-request-method-rejected`, `speech-worker-artifact-request-undeclared`, `speech-worker-cache-open-rejected`, `speech-worker-cache-match-rejected`, `artifact-graph-cache-write-rejected`, `artifact-graph-runtime-request-url-malformed` |
766
- | `ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID` | The exact Worker graph-configuration reasons enumerated below. |
767
- | `ARCANE_AI_ARTIFACT_GRAPH_FETCH_EDGE_UNDECLARED` | `artifact-graph-fetch-edge-undeclared`, `artifact-graph-fetch-edge-undeclared-inactive-runtime-branch-entered`, `artifact-graph-fetch-method-undeclared`, `artifact-graph-fetch-target-undeclared`, `artifact-graph-fetch-guard-bypassed` |
768
- | `ARCANE_AI_ARTIFACT_GRAPH_IMPORT_EDGE_UNDECLARED` | `artifact-graph-dynamic-import-edge-undeclared`, `artifact-graph-dynamic-import-edge-undeclared-inactive-runtime-branch-entered`, `artifact-graph-dynamic-import-target-undeclared` |
769
- | `ARCANE_AI_ARTIFACT_GRAPH_CACHE_EDGE_UNDECLARED` | `artifact-graph-cache-open-edge-undeclared`, `artifact-graph-cache-open-edge-undeclared-inactive-runtime-branch-entered`, `artifact-graph-cache-name-mismatch`, `artifact-graph-cache-read-target-undeclared`, `artifact-graph-cache-open-guard-bypassed`, `artifact-graph-cache-match-guard-bypassed` |
770
- | `ARCANE_AI_ARTIFACT_GRAPH_WORKER_EDGE_UNDECLARED` | `artifact-graph-module-worker-edge-undeclared`, `artifact-graph-module-worker-edge-undeclared-inactive-runtime-branch-entered`, `artifact-graph-module-worker-target-undeclared`, `artifact-graph-module-worker-type-mismatch` |
771
- | `ARCANE_AI_ARTIFACT_GRAPH_ISOLATION_UNAVAILABLE` | The exact guard, typed-array, dynamic-code, timer, storage, and denied-capability reasons enumerated below. |
772
-
773
- The exact provider context reasons under `ARCANE_AI_INVALID_REQUEST` are:
774
-
775
- | Boundary | Exact reasons |
776
- | --- | --- |
777
- | Context is not an object | `stt-provider-inspection-context-not-object`, `tts-provider-inspection-context-not-object`, `stt-provider-load-context-not-object`, `tts-provider-load-context-not-object`, `stt-provider-request-context-not-object`, `tts-provider-request-context-not-object`, `stt-provider-unload-context-not-object`, `tts-provider-unload-context-not-object`, `stt-provider-dispose-context-not-object`, `tts-provider-dispose-context-not-object` |
778
- | Role does not match | `stt-provider-inspection-role-mismatch`, `tts-provider-inspection-role-mismatch`, `stt-provider-load-role-mismatch`, `tts-provider-load-role-mismatch`, `stt-provider-request-role-mismatch`, `tts-provider-request-role-mismatch`, `stt-provider-unload-role-mismatch`, `tts-provider-unload-role-mismatch`, `stt-provider-dispose-role-mismatch`, `tts-provider-dispose-role-mismatch` |
779
- | Signal is not an `AbortSignal` | `stt-provider-inspection-signal-not-abort-signal`, `tts-provider-inspection-signal-not-abort-signal`, `stt-provider-load-signal-not-abort-signal`, `tts-provider-load-signal-not-abort-signal`, `stt-provider-request-signal-not-abort-signal`, `tts-provider-request-signal-not-abort-signal`, `stt-provider-unload-signal-not-abort-signal`, `tts-provider-unload-signal-not-abort-signal`, `stt-provider-dispose-signal-not-abort-signal`, `tts-provider-dispose-signal-not-abort-signal` |
780
- | Lifecycle context property read rejects | `stt-provider-unload-context-read-rejected`, `tts-provider-unload-context-read-rejected`, `stt-provider-dispose-context-read-rejected`, `tts-provider-dispose-context-read-rejected` |
781
-
782
- The other exact provider request reasons under `ARCANE_AI_INVALID_REQUEST` are
783
- `stt-load-progress-callback-not-function`,
784
- `tts-load-progress-callback-not-function`, `stt-provider-operation-mismatch`,
785
- `tts-provider-operation-mismatch`, `stt-transcription-payload-not-object`,
786
- `tts-synthesis-payload-not-object`, and these eight structural payload reasons:
787
- `stt-transcription-payload-not-plain-object`,
788
- `stt-transcription-payload-field-unknown`,
789
- `stt-transcription-payload-accessor-rejected`,
790
- `stt-transcription-payload-required-field-missing`,
791
- `tts-synthesis-payload-not-plain-object`,
792
- `tts-synthesis-payload-field-unknown`,
793
- `tts-synthesis-payload-accessor-rejected`, and
794
- `tts-synthesis-payload-required-field-missing`.
795
-
796
- The remaining exact provider input reasons are
797
- `stt-transcription-blob-constructor-unavailable`,
798
- `stt-transcription-audio-not-blob-or-file`,
799
- `stt-transcription-audio-blob-empty`,
800
- `stt-transcription-mime-type-not-string`,
801
- `stt-transcription-mime-type-malformed`,
802
- `stt-transcription-audio-blob-mime-type-not-string`,
803
- `stt-transcription-audio-blob-mime-type-malformed`,
804
- `stt-transcription-audio-blob-mime-type-mismatch`,
805
- `stt-transcription-audio-not-float32-array`,
806
- `stt-transcription-pcm-input-empty`,
807
- `stt-transcription-sample-rate-mismatch`,
808
- `stt-transcription-pcm-sample-non-finite`, `tts-synthesis-text-empty`,
809
- `tts-synthesis-voice-empty`, and `tts-synthesis-speed-out-of-range`.
810
-
811
- The exact Worker configuration/input reasons under
812
- `ARCANE_AI_INVALID_REQUEST` are `speech-worker-configuration-missing`,
813
- `speech-worker-runtime-selection-mismatch`, `speech-worker-model-id-empty`,
814
- `speech-worker-model-repository-empty`, `speech-worker-model-revision-empty`,
815
- `speech-worker-model-dtype-empty`, `speech-worker-runtime-entry-empty`,
816
- `speech-worker-materialized-files-missing`,
817
- `speech-runtime-entrypoint-not-materialized`,
818
- `speech-model-sample-rate-not-positive-safe-integer`,
819
- `tts-default-voice-empty`, `artifact-graph-materialized-file-not-object`,
820
- `artifact-graph-materialized-path-empty`,
821
- `artifact-graph-materialized-source-url-empty`,
822
- `artifact-graph-materialized-module-url-empty`,
823
- `artifact-graph-materialized-media-type-empty`,
824
- `artifact-graph-runtime-request-routes-not-array`,
825
- `artifact-graph-materialized-path-ambiguous`,
826
- `artifact-graph-entrypoint-not-materialized`,
827
- `stt-worker-message-envelope-shape-rejected`,
828
- `tts-worker-message-envelope-shape-rejected`,
829
- `stt-worker-operation-unknown`, `tts-worker-operation-unknown`,
830
- `stt-transcription-audio-not-float32array`,
831
- `stt-transcription-sample-rate-mismatch`, `tts-synthesis-text-empty`,
832
- `tts-synthesis-voice-empty`, `tts-synthesis-voice-not-declared`, and
833
- `tts-synthesis-speed-out-of-range`.
834
-
835
- The exact `ARCANE_AI_ARTIFACT_GRAPH_CONFIGURATION_INVALID` reasons are
836
- `artifact-graph-worker-configuration-incomplete`,
837
- `artifact-graph-onnx-wasm-configuration-mismatch`,
838
- `artifact-graph-kokoro-voice-inventory-missing`,
839
- `artifact-graph-negative-request-routes-not-array`,
840
- `artifact-graph-runtime-request-route-ambiguous`,
841
- `artifact-graph-module-worker-target-not-materialized`,
842
- `artifact-graph-transform-kind-not-admitted`,
843
- `artifact-graph-transform-module-path-empty`,
844
- `artifact-graph-transform-occurrence-not-positive-safe-integer`,
845
- `artifact-graph-transform-identity-ambiguous`,
846
- `artifact-graph-typed-array-constructor-transform-undeclared`,
847
- `artifact-graph-transformers-cache-edge-ambiguous`,
848
- `kokoro-env-num-threads-field-not-exposed`, and
849
- `transformers-env-num-threads-not-positive-safe-integer`. For each exact edge
850
- subject `cache-open`, `dynamic-import`, `fetch`, and `module-worker`, that code
851
- also admits the six exact endings `edges-not-array`, `edge-not-object`,
852
- `edge-module-path-empty`, `edge-occurrence-not-positive-safe-integer`,
853
- `edge-policy-not-admitted`, and `edge-identity-ambiguous`, joined as
854
- `artifact-graph-{subject}-{ending}`.
855
-
856
- `browser-speech-provider-error-reason-unmapped` is a fail-closed internal
857
- sentinel for a provider error constructed without a mapped reason. No current
858
- public operation deliberately selects it.
859
-
860
- The published legacy authority/store code-to-reason pairs remain:
861
-
862
- | Code | Exact compatibility reason |
863
- | --- | --- |
864
- | `ARCANE_AI_REQUEST_ABORTED` | `browser-speech-artifact-preparation-cancelled` |
865
- | `ARCANE_AI_STORAGE_BUSY` | `browser-speech-artifact-dbopfs-write-lock-unavailable` |
866
- | `ARCANE_AI_STORAGE_UNAVAILABLE` | `browser-speech-artifact-dbopfs-table-unavailable` |
867
- | `ARCANE_AI_STORAGE_DELETE_FAILED` | `browser-speech-artifact-dbopfs-delete-rejected` |
868
- | `ARCANE_AI_STORAGE_READ_FAILED` | `browser-speech-artifact-dbopfs-read-rejected` |
869
- | `ARCANE_AI_ARTIFACT_SOURCE_INVALID` | `browser-speech-artifact-source-body-unreadable` |
870
- | `ARCANE_AI_RUNTIME_MODULE_GRAPH_UNDECLARED` | `browser-speech-runtime-module-graph-undeclared` |
871
- | `ARCANE_AI_ARTIFACT_SOURCE_UNAVAILABLE` | `browser-speech-artifact-fetch-unavailable` |
872
- | `ARCANE_AI_ARTIFACT_DOWNLOAD_FAILED` | `browser-speech-artifact-fetch-rejected` |
873
- | `ARCANE_AI_ARTIFACT_SOURCE_CHANGED` | `browser-speech-artifact-source-redirected` |
874
- | `ARCANE_AI_ARTIFACT_SIZE_MISMATCH` | `browser-speech-artifact-byte-length-mismatch` |
875
- | `ARCANE_AI_ARTIFACT_DIGEST_MISMATCH` | `browser-speech-artifact-sha256-mismatch` |
876
- | `ARCANE_AI_ARTIFACT_CACHE_REJECTED` | `browser-speech-artifact-dbopfs-cache-rejected` |
877
- | `ARCANE_AI_ARTIFACT_OFFLINE_MISS` | `browser-speech-artifact-offline-cache-miss` |
878
-
879
- ### Graph reason/code rule
880
-
881
- Graph construction and store errors use
882
- `code = "ARCANE_AI_" + reason.toUpperCase().replaceAll("-", "_")`. The
883
- following closed reason groups therefore define their exact matching codes.
884
-
885
- The redirect and source-response descriptor/runtime pairs are exactly:
886
-
887
- | Reason | Code |
888
- | --- | --- |
889
- | `artifact-graph-file-source-media-type-missing` | `ARCANE_AI_ARTIFACT_GRAPH_FILE_SOURCE_MEDIA_TYPE_MISSING` |
890
- | `artifact-graph-file-source-media-type-format-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_FILE_SOURCE_MEDIA_TYPE_FORMAT_MISMATCH` |
891
- | `artifact-graph-source-redirect-final-origins-not-array` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGINS_NOT_ARRAY` |
892
- | `artifact-graph-source-redirect-final-origin-inventory-empty` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_INVENTORY_EMPTY` |
893
- | `artifact-graph-source-redirect-final-origin-text-required` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_TEXT_REQUIRED` |
894
- | `artifact-graph-source-redirect-final-origin-whitespace-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_WHITESPACE_REJECTED` |
895
- | `artifact-graph-source-redirect-final-origin-not-absolute` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_NOT_ABSOLUTE` |
896
- | `artifact-graph-source-redirect-final-origin-protocol-not-https` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_PROTOCOL_NOT_HTTPS` |
897
- | `artifact-graph-source-redirect-final-origin-credentials-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_CREDENTIALS_REJECTED` |
898
- | `artifact-graph-source-redirect-final-origin-path-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_PATH_REJECTED` |
899
- | `artifact-graph-source-redirect-final-origin-query-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_QUERY_REJECTED` |
900
- | `artifact-graph-source-redirect-final-origin-fragment-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_FRAGMENT_REJECTED` |
901
- | `artifact-graph-source-redirect-final-origin-duplicate` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_DUPLICATE` |
902
- | `artifact-graph-source-response-url-unreadable` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_UNREADABLE` |
903
- | `artifact-graph-source-redirected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECTED` |
904
- | `artifact-graph-source-response-url-protocol-not-https` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_PROTOCOL_NOT_HTTPS` |
905
- | `artifact-graph-source-response-url-credentials-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_CREDENTIALS_REJECTED` |
906
- | `artifact-graph-source-response-url-fragment-rejected` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_FRAGMENT_REJECTED` |
907
- | `artifact-graph-source-redirect-final-origin-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_REDIRECT_FINAL_ORIGIN_MISMATCH` |
908
- | `artifact-graph-source-response-url-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_SOURCE_RESPONSE_URL_MISMATCH` |
909
-
910
- When an explicit `sourceMediaType` differs from `mediaType`, a cold response
911
- mismatch uses the exact file-kind-specific pair below. When the two fields are
912
- equal, the existing `*-media-type-mismatch` pair applies instead.
913
-
914
- | Reason | Code |
915
- | --- | --- |
916
- | `artifact-graph-entrypoint-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_ENTRYPOINT_SOURCE_MEDIA_TYPE_MISMATCH` |
917
- | `artifact-graph-runtime-auxiliary-javascript-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_RUNTIME_AUXILIARY_JAVASCRIPT_SOURCE_MEDIA_TYPE_MISMATCH` |
918
- | `artifact-graph-runtime-wasm-binary-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_RUNTIME_WASM_BINARY_SOURCE_MEDIA_TYPE_MISMATCH` |
919
- | `artifact-graph-runtime-opaque-data-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_RUNTIME_OPAQUE_DATA_SOURCE_MEDIA_TYPE_MISMATCH` |
920
- | `artifact-graph-model-configuration-json-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_CONFIGURATION_JSON_SOURCE_MEDIA_TYPE_MISMATCH` |
921
- | `artifact-graph-model-generation-configuration-json-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_GENERATION_CONFIGURATION_JSON_SOURCE_MEDIA_TYPE_MISMATCH` |
922
- | `artifact-graph-model-onnx-binary-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_ONNX_BINARY_SOURCE_MEDIA_TYPE_MISMATCH` |
923
- | `artifact-graph-model-onnx-external-data-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_ONNX_EXTERNAL_DATA_SOURCE_MEDIA_TYPE_MISMATCH` |
924
- | `artifact-graph-model-opaque-data-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_OPAQUE_DATA_SOURCE_MEDIA_TYPE_MISMATCH` |
925
- | `artifact-graph-model-preprocessor-json-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_PREPROCESSOR_JSON_SOURCE_MEDIA_TYPE_MISMATCH` |
926
- | `artifact-graph-model-tokenizer-json-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_MODEL_TOKENIZER_JSON_SOURCE_MEDIA_TYPE_MISMATCH` |
927
- | `artifact-graph-voice-style-binary-source-media-type-mismatch` | `ARCANE_AI_ARTIFACT_GRAPH_VOICE_STYLE_BINARY_SOURCE_MEDIA_TYPE_MISMATCH` |
928
-
929
- Descriptor and identity reasons:
930
-
931
- - `artifact-graph-kind-mismatch`, `artifact-graph-role-not-stt-or-tts`,
932
- `artifact-graph-provider-id-missing`,
933
- `artifact-graph-provider-id-length-exceeded`,
934
- `artifact-graph-model-descriptor-missing`,
935
- `artifact-graph-runtime-descriptor-missing`,
936
- `artifact-graph-file-inventory-missing`,
937
- `artifact-graph-file-descriptor-not-object`,
938
- `artifact-graph-file-kind-missing`,
939
- `artifact-graph-file-kind-not-admitted`,
940
- `artifact-graph-file-path-missing`,
941
- `artifact-graph-file-path-noncanonical`,
942
- `artifact-graph-file-revision-missing`,
943
- `artifact-graph-file-revision-length-exceeded`,
944
- `artifact-graph-file-byte-length-positive-safe-integer-required`,
945
- `artifact-graph-file-sha256-missing`,
946
- `artifact-graph-file-sha256-format-mismatch`,
947
- `artifact-graph-file-license-missing`,
948
- `artifact-graph-file-license-whitespace-rejected`,
949
- `artifact-graph-file-license-not-nfc`,
950
- `artifact-graph-file-license-control-character-rejected`,
951
- `artifact-graph-file-license-length-exceeded`,
952
- `artifact-graph-file-media-type-missing`,
953
- `artifact-graph-file-media-type-format-mismatch`,
954
- `artifact-graph-file-source-media-type-missing`,
955
- `artifact-graph-file-source-media-type-format-mismatch`,
956
- `artifact-graph-file-identity-ambiguous`,
957
- `artifact-graph-source-url-missing`,
958
- `artifact-graph-source-url-mutable`,
959
- `artifact-graph-source-revision-unbound`,
960
- `artifact-graph-source-redirect-final-origins-not-array`,
961
- `artifact-graph-source-redirect-final-origin-inventory-empty`,
962
- `artifact-graph-source-redirect-final-origin-text-required`,
963
- `artifact-graph-source-redirect-final-origin-whitespace-rejected`,
964
- `artifact-graph-source-redirect-final-origin-not-absolute`,
965
- `artifact-graph-source-redirect-final-origin-protocol-not-https`,
966
- `artifact-graph-source-redirect-final-origin-credentials-rejected`,
967
- `artifact-graph-source-redirect-final-origin-path-rejected`,
968
- `artifact-graph-source-redirect-final-origin-query-rejected`,
969
- `artifact-graph-source-redirect-final-origin-fragment-rejected`,
970
- `artifact-graph-source-redirect-final-origin-duplicate`,
971
- `artifact-graph-javascript-media-type-mismatch`,
972
- `artifact-graph-wasm-media-type-mismatch`,
973
- `artifact-graph-json-media-type-mismatch`,
974
- `artifact-graph-entrypoint-path-missing`,
975
- `artifact-graph-entrypoint-path-noncanonical`,
976
- `artifact-graph-entrypoint-file-kind-mismatch`,
977
- `artifact-graph-entrypoint-count-mismatch`,
978
- `artifact-graph-entrypoint-revision-mismatch`,
979
- `artifact-graph-runtime-adapter-missing`,
980
- `artifact-graph-runtime-adapter-role-mismatch`,
981
- `artifact-graph-runtime-version-missing`,
982
- `artifact-graph-runtime-version-length-exceeded`,
983
- `artifact-graph-runtime-revision-missing`,
984
- `artifact-graph-runtime-revision-length-exceeded`,
985
- `artifact-graph-onnx-wasm-descriptor-missing`,
986
- `artifact-graph-onnx-wasm-namespace-missing`,
987
- `artifact-graph-onnx-wasm-namespace-role-mismatch`,
988
- `artifact-graph-onnx-wasm-file-kind-mismatch`,
989
- `artifact-graph-onnx-wasm-num-threads-positive-safe-integer-required`,
990
- `artifact-graph-negative-runtime-routes-not-array`,
991
- `artifact-graph-negative-runtime-route-duplicate`,
992
- `artifact-graph-negative-runtime-route-ambiguous`,
993
- `artifact-graph-model-id-missing`,
994
- `artifact-graph-model-id-length-exceeded`,
995
- `artifact-graph-model-repository-missing`,
996
- `artifact-graph-model-repository-length-exceeded`,
997
- `artifact-graph-model-revision-missing`,
998
- `artifact-graph-model-revision-length-exceeded`,
999
- `artifact-graph-model-dtype-missing`,
1000
- `artifact-graph-model-dtype-length-exceeded`,
1001
- `artifact-graph-sample-rate-missing`,
1002
- `artifact-graph-sample-rate-positive-safe-integer-required`,
1003
- `artifact-graph-default-voice-missing`,
1004
- `artifact-graph-default-voice-length-exceeded`,
1005
- `artifact-graph-default-voice-undeclared`,
1006
- `artifact-graph-stt-voice-authority-declared`,
1007
- `artifact-graph-stt-voice-file-declared`,
1008
- `artifact-graph-voice-inventory-missing`,
1009
- `artifact-graph-voice-descriptor-not-object`,
1010
- `artifact-graph-voice-id-missing`,
1011
- `artifact-graph-voice-id-length-exceeded`,
1012
- `artifact-graph-voice-file-kind-mismatch`,
1013
- `artifact-graph-voice-inventory-ambiguous`,
1014
- `artifact-graph-voice-file-undeclared`,
1015
- `artifact-graph-model-file-inventory-missing`,
1016
- `artifact-graph-model-file-revision-mismatch`,
1017
- `artifact-graph-file-unreachable`,
1018
- `artifact-graph-runtime-request-routes-not-array`,
1019
- `artifact-graph-runtime-request-url-text-required`,
1020
- `artifact-graph-runtime-request-url-not-absolute`,
1021
- `artifact-graph-runtime-request-url-protocol-not-https`,
1022
- `artifact-graph-runtime-request-url-credentials-rejected`,
1023
- `artifact-graph-runtime-request-url-fragment-rejected`,
1024
- `artifact-graph-runtime-request-route-duplicate`,
1025
- `artifact-graph-runtime-request-route-ambiguous`,
1026
- `artifact-graph-runtime-request-route-unreachable`,
1027
- `artifact-graph-negative-runtime-route-unreachable`,
1028
- `artifact-graph-identity-sha256-text-required`,
1029
- `artifact-graph-identity-sha256-format-mismatch`, and
1030
- `artifact-graph-identity-sha256-mismatch`.
1031
-
1032
- The lower-level field helpers retain the exact reasons
1033
- `artifact-graph-field-text-required`, `artifact-graph-identifier-missing`,
1034
- `artifact-graph-identifier-length-exceeded`, and
1035
- `artifact-graph-positive-safe-integer-required`. A Kokoro thread declaration
1036
- raises `kokoro-env-num-threads-field-not-exposed` at graph construction; the
1037
- Worker retains that same reason under its defensive graph-configuration
1038
- boundary if construction is bypassed.
1039
-
1040
- Edge and transform reasons:
1041
-
1042
- - `artifact-graph-edges-not-object`, `artifact-graph-edge-kind-not-admitted`,
1043
- `artifact-graph-edge-list-not-array`,
1044
- `artifact-graph-edge-not-object`, `artifact-graph-edge-module-path-missing`,
1045
- `artifact-graph-edge-module-path-noncanonical`,
1046
- `artifact-graph-edge-module-path-not-runtime-javascript`,
1047
- `artifact-graph-edge-occurrence-positive-safe-integer-required`,
1048
- `artifact-graph-edge-occurrence-duplicate`,
1049
- `artifact-graph-edge-policy-not-admitted`,
1050
- `artifact-graph-edge-targets-not-array`,
1051
- `artifact-graph-edge-target-not-object`,
1052
- `artifact-graph-edge-target-match-missing`,
1053
- `artifact-graph-edge-target-match-not-admitted`,
1054
- `artifact-graph-edge-target-path-missing`,
1055
- `artifact-graph-edge-target-path-noncanonical`,
1056
- `artifact-graph-edge-target-path-undeclared`,
1057
- `artifact-graph-edge-target-specifier-missing`,
1058
- `artifact-graph-edge-target-duplicate`,
1059
- `artifact-graph-static-import-specifier-missing`,
1060
- `artifact-graph-dynamic-import-policy-target-mismatch`,
1061
- `artifact-graph-module-worker-policy-target-mismatch`,
1062
- `artifact-graph-module-worker-self-target-mismatch`,
1063
- `artifact-graph-fetch-method-not-get`,
1064
- `artifact-graph-fetch-targets-not-array`,
1065
- `artifact-graph-fetch-target-duplicate`,
1066
- `artifact-graph-fetch-javascript-target-rejected`,
1067
- `artifact-graph-fetch-negative-routes-not-array`,
1068
- `artifact-graph-fetch-negative-route-undeclared`,
1069
- `artifact-graph-fetch-targets-incomplete`,
1070
- `artifact-graph-fetch-policy-target-mismatch`,
1071
- `artifact-graph-cache-name-missing`,
1072
- `artifact-graph-cache-targets-not-array`,
1073
- `artifact-graph-cache-target-duplicate`,
1074
- `artifact-graph-cache-javascript-target-rejected`,
1075
- `artifact-graph-cache-policy-target-mismatch`,
1076
- `artifact-graph-transforms-not-array`,
1077
- `artifact-graph-transform-not-object`,
1078
- `artifact-graph-transform-kind-not-admitted`, and
1079
- `artifact-graph-transform-occurrence-duplicate`.
1080
-
1081
- Runtime scan and materialization reasons:
1082
-
1083
- - `artifact-graph-runtime-javascript-file-missing`,
1084
- `artifact-graph-runtime-javascript-utf8-decode-rejected`,
1085
- `artifact-graph-javascript-block-comment-unterminated`,
1086
- `artifact-graph-javascript-escape-unterminated`,
1087
- `artifact-graph-javascript-hexadecimal-escape-malformed`,
1088
- `artifact-graph-javascript-unicode-code-point-escape-malformed`,
1089
- `artifact-graph-javascript-unicode-code-point-out-of-range`,
1090
- `artifact-graph-javascript-unicode-escape-malformed`,
1091
- `artifact-graph-javascript-quoted-string-line-break-rejected`,
1092
- `artifact-graph-javascript-quoted-string-unterminated`,
1093
- `artifact-graph-javascript-regexp-line-break-rejected`,
1094
- `artifact-graph-javascript-regexp-unterminated`,
1095
- `artifact-graph-javascript-template-expression-unterminated`,
1096
- `artifact-graph-javascript-template-literal-unterminated`,
1097
- `artifact-graph-javascript-escaped-identifier-rejected`,
1098
- `artifact-graph-runtime-fetch-direct-call-required`,
1099
- `artifact-graph-runtime-fetch-receiver-not-global`,
1100
- `artifact-graph-runtime-cache-open-direct-call-required`,
1101
- `artifact-graph-runtime-cache-open-receiver-not-global`,
1102
- `artifact-graph-runtime-worker-constructor-call-required`,
1103
- `artifact-graph-runtime-worker-receiver-not-global`,
1104
- `artifact-graph-runtime-guard-reference-reserved`,
1105
- `artifact-graph-runtime-dynamic-code-undeclared`,
1106
- `artifact-graph-runtime-computed-dynamic-code-undeclared`,
1107
- `artifact-graph-runtime-constructor-dynamic-code-undeclared`,
1108
- `artifact-graph-runtime-edge-undeclared`,
1109
- `artifact-graph-runtime-edge-declaration-unmatched`,
1110
- `artifact-graph-runtime-edge-occurrence-noncanonical`,
1111
- `artifact-graph-static-import-specifier-mismatch`,
1112
- `artifact-graph-static-import-specifier-unresolved`,
1113
- `artifact-graph-static-import-target-unmaterialized`,
1114
- `artifact-graph-runtime-static-import-cycle`,
1115
- `artifact-graph-module-transform-overlap`,
1116
- `artifact-graph-guard-capability-unavailable`,
1117
- `artifact-graph-object-url-platform-unavailable`,
1118
- `artifact-graph-object-url-scheme-not-blob`,
1119
- `artifact-graph-object-url-identity-ambiguous`,
1120
- `artifact-graph-object-url-readback-unavailable`,
1121
- `artifact-graph-object-url-readback-http-status-rejected`,
1122
- `artifact-graph-object-url-readback-identity-mismatch`,
1123
- `artifact-graph-object-url-media-type-mismatch`,
1124
- `artifact-graph-object-url-byte-length-mismatch`, and
1125
- `artifact-graph-object-url-sha256-mismatch`.
1126
-
1127
- Source, cache, and security reasons:
1128
-
1129
- - `artifact-graph-load-security-contract-rejected`,
1130
- `artifact-graph-source-fetch-rejected`,
1131
- `artifact-graph-source-http-response-rejected`,
1132
- `artifact-graph-source-redirected`,
1133
- `artifact-graph-source-response-url-unreadable`,
1134
- `artifact-graph-source-response-url-protocol-not-https`,
1135
- `artifact-graph-source-response-url-credentials-rejected`,
1136
- `artifact-graph-source-response-url-fragment-rejected`,
1137
- `artifact-graph-source-redirect-final-origin-mismatch`,
1138
- `artifact-graph-source-response-url-mismatch`,
1139
- `artifact-graph-offline-cache-miss`, and
1140
- `artifact-graph-preparation-cancelled`.
1141
-
1142
- For an exact file verification failure, `reason` is
1143
- `artifact-graph-{subject}-{boundary}`. `{subject}` is `entrypoint` for
1144
- `runtime-entrypoint-javascript`; otherwise it is the exact file kind from the
1145
- closed kind table. `{boundary}` is one of `media-type-mismatch`,
1146
- `source-media-type-mismatch`, `byte-length-mismatch`, `sha256-mismatch`,
1147
- `dbopfs-persisted-byte-length-mismatch`, or
1148
- `dbopfs-persisted-sha256-mismatch`. `source-media-type-mismatch` occurs only
1149
- when an explicit `sourceMediaType` differs from `mediaType`; otherwise a source
1150
- Content-Type mismatch uses `media-type-mismatch`. This expansion produces the
1151
- exact public code by the rule above; for example,
1152
- `artifact-graph-entrypoint-sha256-mismatch` becomes
1153
- `ARCANE_AI_ARTIFACT_GRAPH_ENTRYPOINT_SHA256_MISMATCH`.
1154
-
1155
- The other exact isolation reasons are
1156
- `artifact-graph-private-message-port-missing`,
1157
- `artifact-graph-guard-global-collision`,
1158
- `artifact-graph-guard-global-definition-rejected`,
1159
- `artifact-graph-guard-capability-mismatch`,
1160
- `artifact-graph-fetch-isolation-unavailable`,
1161
- `artifact-graph-cache-isolation-unavailable`,
1162
- `speech-worker-fetch-isolation-unavailable`,
1163
- `speech-worker-cache-isolation-unavailable`,
1164
- `artifact-graph-typed-array-validation-unavailable`,
1165
- `artifact-graph-typed-array-constructor-receiver-not-typed-array`,
1166
- `artifact-graph-typed-array-constructor-intrinsic-mismatch`,
1167
- `artifact-graph-dynamic-code-constructor-rejected`,
1168
- `artifact-graph-dynamic-code-constructor-isolation-unavailable`,
1169
- `artifact-graph-setinterval-isolation-unavailable`,
1170
- `artifact-graph-settimeout-isolation-unavailable`,
1171
- `artifact-graph-setinterval-string-callback-rejected`,
1172
- `artifact-graph-settimeout-string-callback-rejected`,
1173
- `artifact-graph-indexeddb-isolation-unavailable`, and
1174
- `artifact-graph-opfs-isolation-unavailable`.
1175
-
1176
- The denied-capability Worker reasons are
1177
- `artifact-graph-{capability}-capability-undeclared` and
1178
- `artifact-graph-{capability}-isolation-unavailable`, where `{capability}` is
1179
- exactly `broadcastchannel`, `eventsource`, `function`, `rtcpeerconnection`,
1180
- `shadowrealm`, `sharedworker`, `websocket`, `websocketstream`, `webtransport`,
1181
- `worker`, `xmlhttprequest`, `eval`, or `importscripts`.
1182
-
1183
- ## `createBrowserSpeechAuthority()` upstream package mode
1184
-
1185
- `BROWSER_SPEECH_ARTIFACT_PROTOCOL` remains exactly
1186
- `arcane-ai-browser-speech-artifacts/1`, and
1187
- `createBrowserSpeechAuthority({providerId,role,model,runtime,security})`
1188
- loads a caller-selected browser bundle from npm or another upstream package
1189
- authority. The SDK stores only the downloaded application-selected entrypoint;
1190
- the runtime uses its normal provider fetch and browser cache behavior. Its
1191
- optional byte/SHA checks still resolve independently from SDK default to app,
1192
- provider, and load scopes. Its cache values remain `installed` and `cached`,
1193
- and its offline miss remains `ARCANE_AI_ARTIFACT_OFFLINE_MISS`.
1194
-
1195
- The model descriptor is
1196
- `{id,repository,revision,defaultVoice?,files?}`; `defaultVoice` is required only
1197
- for `tts`. In default warn-first mode `files` may be omitted so the selected
1198
- provider downloads its own model and voice assets. The runtime descriptor is
1199
- `{adapter,version,revision,entry,wasmPaths?,files}` and its adapter is exactly
1200
- `transformers-whisper` for `stt` or `kokoro-js` for `tts`. Every legacy file is
1201
- `{path,url,bytes?,sha256?,mediaType?}` with a normalized relative path, a
1202
- unique immutable URL containing the descriptor revision or SHA-256 identity,
1203
- and optional positive byte length and SHA-256. Legacy SHA input is normalized
1204
- to lowercase before validation and projection. `runtime.entry` must
1205
- name the one `text/javascript` `.js` or `.mjs` runtime file. The frozen result
1206
- is
1207
- `{protocol,providerId,modelId,admitted,role,repository,revision,defaultVoice,runtime,files,security}`.
1208
-
1209
- `runtime.wasmPaths` may name a version-pinned upstream npm CDN directory in
1210
- warn-first mode. `secure:true` rejects remote `wasmPaths`, requires explicit
1211
- model files, applies the closed-module scan, and replaces ordinary fetch/cache
1212
- access with the admitted file map. The authenticated artifact graph remains an
1213
- advanced strict-control option; it is not required for normal speech use.
1214
-
1215
- ## Security and ownership summary
1216
-
1217
- - The SDK redistributes no speech runtime, model, voice, third-party license,
1218
- or corresponding-source payload. Explicit `load()` resolves them from the
1219
- caller-selected npm/package/provider authorities.
1220
- - Default direct-authority operation is warn-first and preserves ordinary
1221
- upstream fetch/cache behavior. An artifact graph is admitted only when
1222
- `secure:true` explicitly opts into strict graph/file verification and
1223
- capability isolation.
1224
- - Every graph byte is caller-selected, immutable, exact-length, SHA-256 bound,
1225
- revision bound, media-type bound, license-declaration bound, and reachable
1226
- through one closed graph identity.
1227
- - Redirects are rejected by default. An undeclared redirect, an undeclared or
1228
- non-HTTPS final origin, a mutable starting source authority, an ambiguous
1229
- path/route, an undeclared code/data edge, a raw network transport, a cache
1230
- write, or an incomplete offline closure fails closed.
1231
- - DBOPFS is the sole durable artifact store; the Worker sees only authenticated
1232
- local object bytes and an exact read-only cache facade.
1233
- - Runtime/model/sample-rate/default-voice/voice inventory and optional
1234
- Transformers thread count remain caller authority. No hardware heuristic,
1235
- hidden fallback, startup download, native/Core call, or cloud retry is added.
1236
- - A completion manifest and SHA-256 prove consistency with the caller's graph;
1237
- they are not independent publisher authenticity or complete license evidence.
1238
- - The component resolution record is
1239
- `browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json`; the detailed
1240
- package/model audit is `docs/reference/ai/browser-speech-package-authority.json`.
1241
- - Upstream publishers remain responsible for their distributed package and
1242
- provider assets. Applications own selected model/voice policy and integration
1243
- with the one shared SDK state/event owner.
1244
-
1245
- ## Related
1246
-
1247
- - [Normalized AI](../README.md#normalized-ai)
1248
- - [Browser-WASM LLM](browser-wasm.md)
1249
- - [AIProviderRuntime.js](../runtime-modules.md#aiproviderruntimejs)
1250
- - [AIRuntimeState.js](../runtime-modules.md#airuntimestatejs)
1251
- - [Availability and normalization](../availability-and-normalization.md)
1252
- - [Protocol architecture](../protocols.md#portable-ai-provider-runtime)