@ai-ecoverse/slicc-vault 1.12.2 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -183,6 +183,7 @@ iframe.contentWindow.postMessage({ type: 'slicc-vault', v: 1, op: 'hello', role:
183
183
  | `lock` | — | `{}`; drops the key everywhere when the lock is on |
184
184
  | `dismissBackupReminder` | — | `{ backupReminder }`; the reminder becomes `dismissed` for this namespace |
185
185
  | `policy` | `files` | the attested policy files, below (Policy) |
186
+ | `endpoints` | `model?`: https base URLs, or `{ name, url }`, a custom base URL for the `model` record `name`; `mcp?`: as the agent's; `remove?`: `{ model?: (url \| { name, url })[], mcp?: { server, url }[] }` | `{ ok: true }`; the user's own registrations, trusted (Model and MCP endpoints). The whole request is checked first and applied in one transaction, so an `EINVAL` anywhere changes nothing. `unpin?`: names of `mcp` records to unpin (needs the vault unlocked). `remove` takes back the page's own entries, never the agent's; removing the model record drops its custom URLs too. A `{ name, url }` needs a live `model` record of that name, and a plain `https:` URL on 443 without `*` or `{…}` and not under a page-registered MCP server, else `EINVAL` |
186
187
  | `forward` | `head`, `body?`, `owner`, `exit`, `rawTraits`, with a `MessagePort` transferred alongside | the injected head, below (Forward) |
187
188
  | `materializeConsume` | `ticket`, `stamp`, `path`, `resolved`, `argv`, `cwd`, `interpreters`, `trusted` | the values for the child's environment, below (Exec) |
188
189
  | `sessionMaterialize` | `stamp`, `session`, `host`, `port`, `protocol`, `position`, `verified`, `handshakeAt`, `exit`, `verifiedBy?`, `anchor?`, then `placeholders` (and `head` for http1) at every position but `scram-sha-256`, which takes `scram` and no `placeholders` | `{ values }` for a kernel-verified TLS session, below (Sessions) |
@@ -359,13 +360,27 @@ The candidates are the placeholders that would pass the per-placeholder checks a
359
360
  ## Model and MCP endpoints
360
361
 
361
362
  The vault never injects a secret into a model or MCP endpoint, whatever a rule says.
362
- - **The built-in list** is generated at build time (`scripts/endpoints.mjs`, into the gitignored `src/endpoints.json`) from every provider base URL in pi-ai's catalog (`@earendil-works/pi-ai`, pinned in `devDependencies`, the version slicc-agent runs), plus `bedrock-runtime.*` and `bedrock-runtime-fips.*.amazonaws.com`, Vertex AI's global `aiplatform.googleapis.com` (`google-vertex`), Azure OpenAI, AI services and Cognitive Services' OpenAI path (`*.openai.azure.com`, `*.services.ai.azure.com`, `*.cognitiveservices.azure.com/openai`, so Speech, Translator and the other Cognitive Services stay usable by rules), Adobe's LLM proxy, and the model base URLs pi-ai has retired but that still serve models (`opencode.ai/zen`, `api.kimi.com/coding`): the refused set never shrinks when pi-ai drops a URL, though no key goes there. `*` is exactly one label. The published package's `piAi` field in `package.json` names the pi-ai version the vault was built against, so slicc-agent can check that both run the same catalog; Renovate bumps it with the pin, labelled `pi-ai-lockstep` and never automerged. Each entry is a host (with `*` for one label) and a path prefix (`*` for one segment, from templated segments).
363
- - **Registered endpoints:** the agent's `endpoints` op adds model base URLs and MCP servers for its namespace. They only ever add.
363
+ - **The built-in list** is generated at build time (`scripts/endpoints.mjs`, into the gitignored `src/endpoints.json`) from every provider base URL in pi-ai's catalog (`@earendil-works/pi-ai`, pinned in `devDependencies`, the version slicc-agent runs), plus `bedrock-runtime.*` and `bedrock-runtime-fips.*.amazonaws.com`, Vertex AI's global `aiplatform.googleapis.com` (`google-vertex`), Azure OpenAI, AI services and Cognitive Services' OpenAI path (`*.openai.azure.com`, `*.services.ai.azure.com`, `*.cognitiveservices.azure.com/openai`, so Speech, Translator and the other Cognitive Services stay usable by rules), Adobe's LLM proxy (for the provider `adobe`), and the model base URLs pi-ai has retired but that still serve models (`opencode.ai/zen`, `api.kimi.com/coding`): the refused set never shrinks when pi-ai drops a URL, though no key goes there. `*` is exactly one label. The published package's `piAi` field in `package.json` names the pi-ai version the vault was built against, so slicc-agent can check that both run the same catalog; Renovate bumps it with the pin, labelled `pi-ai-lockstep` and never automerged. Each entry is a host (with `*` for one label) and a path prefix (`*` for one segment, from templated segments).
364
+ - **Registered endpoints** only ever add, per namespace, and who registers them decides what they do:
365
+ - **The page's `endpoints` op** (bios and spectrum, for what the user typed in Settings) adds model base URLs, a custom base URL for one model record as `{ name, url }` (an Azure APIM gateway or a Cloudflare gateway the owner typed for that account, say), and MCP servers. These are trusted: they join the refused set below. A `{ name, url }` is the only way a key reaches a URL outside the built-in list, and only that record's key: another record of the same provider never goes there. The vault stores the record's provider with it, and drops it when the record is removed.
366
+ - **The agent's `endpoints` op** adds MCP servers, which only say where the agent's own `mcp` credentials may go (below). The vault never sets an agent-supplied `tokenUrl` for a server name a typed-in token is bound to. Once the page has registered a server name, every agent entry under that name is ignored, stored or new: the agent can't add to its `names`, set its `tokenUrl`, or register it at another URL. Its model base URLs and `{ provider, url }` entries are kept as URLs only: they never let a key go anywhere, and never refuse a secret rule. So a compromised agent worker can neither send a provider's key to a URL of its choosing nor make a user's secret rules inert by registering their host.
367
+ - **Upgrade,** once per namespace, at the first hello the vault can scrub at, or before the first MCP credential is used after an unlock, (a namespace that registers anything for the first time after the upgrade has nothing to migrate):
368
+ - the `{ provider, url }` entries earlier versions let an agent register are deleted, and never used meanwhile. Those a built-in base URL of that provider doesn't already cover (so not the Adobe proxy every agent registered) are listed as `purged: [{ provider, host }]`;
369
+ - the agent-registered URLs of servers that typed-in `mcp` records are bound to (by `server`) are **adopted** into the page's servers, listed as `adopted: [{ server, host }]`, so existing setups keep working and the agent can't retarget them later. Typed-in tokens that are removed but restorable count too. Only the server's one concrete agent URL is adopted, bare (no `names`, no `tokenUrl`). A server name with no such URL (none, several, a `*` pattern, or one overlapping a page custom model URL) is held instead: none is adopted, and its tokens never pin on first use either, until the page registers the server. The decision uses only what was registered before the upgrade: agent registrations that arrive before the migration has run are kept aside and added only afterwards;
370
+ - one `endpoints` audit entry holds both lists, scrubbed and with hosts only (never paths or queries, where a value could hide); none is written when both are empty.
371
+ - **The refused set** is the built-in list and the page's registrations, never the agent's.
364
372
  - **At policy parse:** a rule that can reach only refused URLs (its domain matches, and the endpoint has no path prefix or every path of the rule lies under it), and an `smtp` or `pg` session rule whose domain matches any endpoint's host, is dropped and listed in `list.refused` with the reason `NAME: host is a model or MCP endpoint; the vault never injects there`. Other rules on the same host stay.
365
373
  - **At request time:** `forward` refuses any URL under the refused set, before rules: `403 host is a model or MCP endpoint; the vault never injects there`.
366
- - **Kernel programs calling a registered MCP server (§3.16.1):** a `forward` whose URL lies under a registered MCP server isn't refused but handled for that server only. Only `mcp` records the server lists in `names` are filled in; a `secret`, `grant` or `model` placeholder is refused ("secrets are never sent to model or MCP endpoints"). The reply carries `body`, the request body scrubbed over every value, which bios sends instead of its own copy; the response is scrubbed as above; each call is audited as `mcp` with `server`, uid and tag.
374
+ - **Which MCP credential goes where (§3.16.1):** an `mcp` record is filled only on a server it belongs to, by where it came from:
375
+ - **page-sealed** (Settings, `seal`, import): on an `https:` URL under the server URL the **page** registered for its server name (never at a `tokenUrl`). Until slicc-agent hands those URLs to the page, one without a page server is **pinned on first use** (§3.16.1, TOFU): on the agent's `mcp` path at its first fill, on a kernel `forward` at the first 2xx relayed through the vault. The pin is that agent server's URL (origin and path prefix; an agent server URL with a `*` pattern never pins, so the token isn't filled there), kept as the record's `url`, and audited as `endpoints { pinned: { name, server, host } }` (`name` is the record's); afterwards the agent's registrations for that server never count. A page registration for the server overrides the pin; once the page has dropped its registration for a server, the server is held, so its tokens never pin to an agent URL again until the page registers it. The page's `endpoints { unpin: [name] }` clears a pin (audited as `endpoints { unpinned: { name, server, host } }`), so the next use pins again;
376
+ - **the agent's sign-ins** (`grant`, source `oauth:mcp`): on any registered `https:` URL of that server, since the agent already held the token;
377
+ - **kernel bridge tokens** (§3.16.3, with their `url`): only on that URL;
378
+ - **never** on a kernel loopback URL unless it is a bridge token, and never on a URL under a built-in or page-registered model endpoint.
379
+ - **Kernel programs calling a registered MCP server:** a `forward` that carries no `secret` placeholder and whose URL lies under a registered MCP server isn't refused but handled for that server only, a page server winning over an agent one on the same URL. Only `mcp` records bound to that server (by `server`, or listed in its `names`) and held as above are filled in; a `grant` or `model` placeholder is refused. A request that carries a `secret` placeholder is a secret request, whatever the agent registered: the refused set and the rules decide, so an agent's MCP registration can't make a user's rule inert, and a secret never goes over a kernel loopback `http:` URL ("credentials are sent only over https on port 443"). The reply carries `body`, the request body scrubbed over every value, which bios sends instead of its own copy; the response is scrubbed as above; each call is audited as `mcp` with `server`, uid and tag.
367
380
  - **`http://<port>.kernel.localhost/<path>`** (port 1–65535, never 9222, no explicit port) is the one `http:` form an MCP server may have (§3.16.3). Everything else must be `https:` on 443.
368
381
 
382
+ **Owner changes and requests in flight.** The vault re-reads the endpoints, the records and the scrub version as a last step before it hands a prepared head (agent `model`/`mcp`) or a forwarded one (kernel `forward`) back, so an owner change that has committed by then refuses it. Otherwise, a request prepared before an owner change (the page removing, rotating, unpinning or re-registering something) may complete under the earlier state; the next request sees the change. This applies only to the owner's own changes: what the agent or a kernel program registers or sends never widens a binding, whatever the timing.
383
+
369
384
  ## The agent's ops
370
385
 
371
386
  | op | fields | reply |
@@ -376,7 +391,7 @@ The vault never injects a secret into a model or MCP endpoint, whatever a rule s
376
391
  | `idle` | `stream` | `{ chunk }`: a held tail under 16 bytes, after `idleMs` without input |
377
392
  | `end` | `stream` | `{ chunk, hits }`: the rest, and the stream is gone |
378
393
  | `drop` | `stream` | `{}` |
379
- | `endpoints` | `model?`: https base URLs, or `{ provider, url }` for a provider's custom base URL; `mcp?`: `{ server, url, names?, tokenUrl? }` or a URL string | `{ ok: true }`; registrations only add: a server's first `tokenUrl` stays, for every URL it registers. New entries re-check the policy and push `changed` |
394
+ | `endpoints` | `model?`: https base URLs, or `{ provider, url }` (kept as its `url` only, below); `mcp?`: `{ server, url, names?, tokenUrl? }` or a URL string | `{ ok: true }`; registrations only add: a server's first `tokenUrl` stays, for every URL it registers. New entries re-check the policy and push `changed`. An agent's registrations never let a model key go anywhere and never refuse a secret rule (Model and MCP endpoints) |
380
395
  | `model` | `provider?`, `request`: `{ method, url, headers: [name, value][], body?: string \| bytes }` | `{ request, hits, version }`, the request prepared for the agent's transport, below |
381
396
  | `mcp` | `server`, `request` (the same shape) | `{ request, hits, version }`, below |
382
397
  | `records` | — | `{ records: [{ kind, name, placeholder, state, provider?, server?, expiresAt?, settings? }] }`: the namespace's `model` and `mcp` records that aren't removed, `state` being `ready`, `expired` or `refreshing` (expired with a refresh source), and `settings` scrubbed over every value (an entry whose name holds a value is dropped; so is a record whose name, provider or server holds one, and an `expiresAt` whose digits are a value). Never a value, a `secret` or a `grant`; the records are read and scrubbed under one scrub version (retried, then `EAGAIN` while values keep changing); `EACCES` while the vault is locked before its first unlock |
@@ -387,7 +402,7 @@ The vault never injects a secret into a model or MCP endpoint, whatever a rule s
387
402
  - **The head carries no value:** checked with the scrubber from before and after any refresh or rotation during the request, a raw value (in any form the scrubber knows) in the method, the URL, a header name or a header value is `EACCES` ("the request head carries a value; send its placeholder instead").
388
403
  - **The body** (a string or bytes, at most 32 MiB of UTF-8) is scrubbed over every value of the namespace (S4), with both of those scrubbers, so neither a token refreshed for this request nor a value rotated meanwhile slips through and keeps its type; placeholders in it are left alone. The URL must be `https:`, or for `mcp` the kernel loopback `http://<port>.kernel.localhost/…` (port 9222 refused) under that server's own loopback registration; anything else is `EACCES` ("model and MCP requests go out over https only").
389
404
  - **The credential goes in by placeholder.** The worker sets a provider's API key (or `mcp.json`'s `${NAME}`) to the record's placeholder from `records`, and the vault replaces it with the value **only in the headers and the URL** (URL-encoded there), never in the body. Every placeholder of the namespace in the headers or URL must belong to the target, else `EACCES` ("NAME isn't a credential of TARGET; secrets are never sent to model or MCP endpoints"): for `model`, a `model` record of that `provider`; for `mcp`, an `mcp` record bound to that `server` or listed in its `names`; a bridge token sealed by a program only when the server's registration has exactly its `url` and the request is under that `url` itself (never at the server's `tokenUrl`). A `secret` or `grant` is never filled in, nor a credential whose value contains or equals another record's value in any form the scrubber knows except a 16-character fragment (`EACCES`). Every string in the replies of `model`/`mcp` (outside the prepared head), `records`, `grant` and `refresh`, and every error message, is scrubbed over every value, and a number whose digits are a value is left out.
390
- - **Its own URLs only.** `model` fills a key only under that provider's built-in base URL (pi-ai's catalog, generated with the provider ids) or a `{ provider, url }` registered with `endpoints`; `mcp` only under that server's registered URL (same scheme and port), at exactly its `tokenUrl`, or at its kernel loopback URL. Elsewhere a filled placeholder is `EACCES` ("NAME is sent only to TARGET's own endpoints"). A request without such a placeholder is only scrubbed, wherever it goes over `https:`, so OAuth discovery and client registration work.
405
+ - **Its own URLs only.** `model` fills a key only under that provider's built-in base URL (pi-ai's catalog, generated with the provider ids) or a `{ name, url }` the page registered for that very record with `endpoints` (never the agent); `mcp` only under that server's registered URL (same scheme and port) or at exactly its `tokenUrl`, by the rules of Model and MCP endpoints (a page-sealed credential only where the page registered the server, a bridge token only at its loopback URL). Elsewhere a filled placeholder is `EACCES` ("NAME is sent only to TARGET's own endpoints"). A request without such a placeholder is only scrubbed, wherever it goes over `https:`, so OAuth discovery and client registration work.
391
406
  - **`provider` is optional:** without it, the provider is the one of the single `model` placeholder in the headers and URL; with none or several, nothing is filled.
392
407
  - **An expired record** with a refresh source is refreshed first, once per prepared request however often its placeholder appears, through `egress` (`EACCES` "NAME expired; refreshing" if that fails); one without is `EACCES` "NAME expired". A removed record is `EACCES`. A locked vault before its first unlock is `EACCES` ("unlock the vault to continue").
393
408
  - **Consistency:** if the namespace's values change while a request is prepared by more than the one change each of its own refreshes makes, it's `EAGAIN` ("prepare the request again"), and a credential that a refresh rebinds to another provider or server is `EACCES`; `grant`'s kept fields also have the returned tokens replaced by their placeholders directly, and its record names and `expiresAt` are scrubbed against a value stored meanwhile.
@@ -460,10 +475,11 @@ The npm package `@ai-ecoverse/slicc-vault` holds only TypeScript types, built fr
460
475
  - **`Rule`**: `domain` is an exact lower-case host; `header` a lower-case header name; **empty `methods` or `paths` mean any**. A rule with `protocol` (`http1`, `smtp`, `pg`) is a session rule, with its `port` and, for smtp and pg, its `position`; show it as "PROTOCOL on host:port". `anchors`, `pins` and `roots` are its trust anchors (Policy).
461
476
  - **`exec`**: `false` means the value is never revealed to a program; `any`, `argv` (with `execArgv`, the allowed argv prefixes) and `shell` are the `[exec]` modes under which `fnox exec` may hand it to a program.
462
477
  - **`exits`** is present only when `/etc/slicc/secrets-policy.toml` restricts that secret; absent means every exit (`page`, `proxy`, `tailscale`, `device:<id>`).
478
+ - **`url` and `pinned` in `list`** (`mcp` records): the URL a credential is bound to, the full URL scrubbed over every value, and `pinned: true` when that binding is a first-use pin (§3.16.1) rather than a kernel bridge's. A page registration for the server overrides a pin, so compare it with the page's own registrations.
463
479
  - **Bindings in `list`:** read under one scrub version (retried, then `EAGAIN`), `provider`, `server` and `settings` are scrubbed over every value (a setting whose name holds one is dropped), and left out while the vault is locked before its first unlock.
464
480
  - **`kind`**: `secret` (a credential programs use through rules), **`grant`** (a sign-in's refresh token, never injected; show it as "Sign-in"), `model` (a model provider key), `mcp` (an MCP server credential). `provider` and `account` name the service and the signed-in account where one is known; a `model` record always has its `provider`, an `mcp` record may have its `server`, and either may carry non-secret `settings`.
465
- - **Who did it:** `uid` and `tag` are the kernel stamp for entries a program or the agent caused (`/dev/sealed` seals, `forward`, `mcp`, `materialize`, `session`). Every entry from a page-role op (`put`, `seal`, `remove`, `restore`, `import`, `policy`) and from the vault itself (`refresh`) has `uid: null, tag: null`, older entries included. Spectrum shows page ops as "by you", `refresh` as "automatically", and `policy` entries with no "by …".
466
- - **`AuditEntry`**: `forward` is a use of a value in a request, with the exit that carried it; `mcp` a kernel program's call to a registered MCP server; `session` a value handed to the kernel for a verified TLS session (show it as "Sent over PROTOCOL to host", with "trusted by public roots" or "trusted by its pinned anchor" from `verifiedBy`, and nothing when an older entry has no `verifiedBy`); **`materialize` is shown as "Revealed to a program"**; `seal`, `remove`, `restore` and `policy` (with its `changes`) record changes. Every entry has a `seq` for paging.
481
+ - **Who did it:** `uid` and `tag` are the kernel stamp for entries a program or the agent caused (`/dev/sealed` seals, `forward`, `mcp`, `materialize`, `session`). Every entry from a page-role op (`put`, `seal`, `remove`, `restore`, `import`, `policy`) and from the vault itself (`refresh`, `endpoints`) has `uid: null, tag: null`, older entries included. Spectrum shows page ops as "by you", `refresh` and `endpoints` as "automatically", and `policy` entries with no "by …".
482
+ - **`AuditEntry`**: `endpoints` is vault-originated: the upgrade's `purged` (show it as "Removed custom model URLs an agent set") and `adopted` ("Kept the MCP servers your tokens use"), a `pinned` MCP token ("pinned to <host>", with an Unpin action) and an `unpinned` one; `forward` is a use of a value in a request, with the exit that carried it; `mcp` a kernel program's call to a registered MCP server; `session` a value handed to the kernel for a verified TLS session (show it as "Sent over PROTOCOL to host", with "trusted by public roots" or "trusted by its pinned anchor" from `verifiedBy`, and nothing when an older entry has no `verifiedBy`); **`materialize` is shown as "Revealed to a program"**; `seal`, `remove`, `restore` and `policy` (with its `changes`) record changes. Every entry has a `seq` for paging.
467
483
  - **`SessionTarget`**: a `sessionMaterialize` request's protocol, position and what goes with it: `placeholders` (and `head` for http1) for every position but `scram-sha-256`, which takes `scram` (a `ScramExchange`) and no `placeholders`.
468
484
  - **`VaultList.refused`** lists rules the vault dropped because they name a model or MCP endpoint.
469
485
  - **`PendingRequest.prompt`** is untrusted, agent-written text of at most 200 characters.
@@ -88,6 +88,8 @@ export interface SecretView {
88
88
  provider?: string;
89
89
  account?: string;
90
90
  server?: string;
91
+ url?: string;
92
+ pinned?: true;
91
93
  settings?: Record<string, string>;
92
94
  domains: string[];
93
95
  rules: Rule[];
@@ -221,7 +223,33 @@ export interface PolicyEntry {
221
223
  changes: PolicyChange[];
222
224
  warning?: string;
223
225
  }
224
- export type AuditEntry = ForwardEntry | SessionEntry | McpEntry | RevealEntry | SealEntry | RemoveEntry | RefreshEntry | PolicyEntry;
226
+ export interface EndpointsEntry {
227
+ type: 'endpoints';
228
+ seq: number;
229
+ id: string;
230
+ at: EpochMs;
231
+ uid: null;
232
+ tag: null;
233
+ purged?: {
234
+ provider: string;
235
+ host: string;
236
+ }[];
237
+ adopted?: {
238
+ server: string;
239
+ host: string;
240
+ }[];
241
+ pinned?: {
242
+ name: string;
243
+ server: string;
244
+ host: string;
245
+ };
246
+ unpinned?: {
247
+ name: string;
248
+ server: string;
249
+ host: string;
250
+ };
251
+ }
252
+ export type AuditEntry = EndpointsEntry | ForwardEntry | SessionEntry | McpEntry | RevealEntry | SealEntry | RemoveEntry | RefreshEntry | PolicyEntry;
225
253
  export interface RefreshEntry extends AuditBase {
226
254
  type: 'refresh';
227
255
  grant: string;
@@ -471,6 +499,24 @@ export type Op = {
471
499
  } | {
472
500
  op: 'policy';
473
501
  files: Attestation[];
502
+ } | {
503
+ op: 'endpoints';
504
+ model?: (string | {
505
+ name: string;
506
+ url: string;
507
+ })[];
508
+ mcp?: (string | McpServerEntry)[];
509
+ remove?: {
510
+ model?: (string | {
511
+ name: string;
512
+ url: string;
513
+ })[];
514
+ mcp?: {
515
+ server: string;
516
+ url: string;
517
+ }[];
518
+ };
519
+ unpin?: string[];
474
520
  } | {
475
521
  op: 'forward';
476
522
  head: RequestHead;
@@ -638,6 +684,9 @@ export type OpReply = {
638
684
  } | ({
639
685
  op: 'policy';
640
686
  } & PolicyResult) | {
687
+ op: 'endpoints';
688
+ ok: true;
689
+ } | {
641
690
  op: 'refresh';
642
691
  state: 'refreshed' | 'requested';
643
692
  expiresAt?: EpochMs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-vault",
3
- "version": "1.12.2",
3
+ "version": "1.13.0",
4
4
  "description": "The separate-origin vault at vault.sliccy.ai: sealed secrets, OAuth tokens, and model and MCP credentials for SLICC seven, used only by its injector",
5
5
  "piAi": "1.3.0",
6
6
  "type": "module",
@@ -48,7 +48,7 @@
48
48
  },
49
49
  "devDependencies": {
50
50
  "@ai-ecoverse/jerk-oauth": "1.0.0",
51
- "@ai-ecoverse/slicc-kernel": "1.128.0",
51
+ "@ai-ecoverse/slicc-kernel": "1.129.0",
52
52
  "@ai-ecoverse/slicc-scrub": "1.0.0",
53
53
  "@ai-ecoverse/slicc-shared-web": "1.24.2",
54
54
  "@ai-ecoverse/wasm-bash": "5.3.0-20",
@@ -63,7 +63,7 @@
63
63
  "fake-indexeddb": "6.2.5",
64
64
  "happy-dom": "20.14.6",
65
65
  "hash-wasm": "4.12.0",
66
- "js-yaml": "4.3.2",
66
+ "js-yaml": "5.5.0",
67
67
  "kdbxweb": "2.1.1",
68
68
  "lefthook": "2.2.1",
69
69
  "monocart-coverage-reports": "2.13.2",