@ai-ecoverse/slicc-vault 1.2.0 → 1.3.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 +57 -8
- package/dist/types/contract.d.ts +110 -2
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
The separate-origin vault at `vault.sliccy.ai`. It holds the sealed secrets, OAuth tokens, and model and MCP credentials of SLICC seven, so that no value ever reaches the model provider. The design is `secrets-tokens-design.md` (revision 4) in slicc-agent-plan. This README is the spec of what is built.
|
|
4
4
|
|
|
5
|
-
- **Built:** the key store, records, origin namespacing, auto-unlock with an optional passkey or passphrase lock, the embedding API with its `page` and `agent` roles, the page's `put`, `seal`, `remove`, `restore`, `cancel` and `lock`, the scrub state, the lock button and its popup, the attested policy (rules, `[exec]`, `[exits]`, `[limits]`), and the vault side of the `/dev/sealed` ops `seal`, `placeholder`, `list`, `test`, `request`, `status`, `cancel` and `materialize`.
|
|
6
|
-
- **Not built yet:**
|
|
5
|
+
- **Built:** the key store, records, origin namespacing, auto-unlock with an optional passkey or passphrase lock, the embedding API with its `page` and `agent` roles, the page's `put`, `seal`, `remove`, `restore`, `cancel` and `lock`, the scrub state, the lock button and its popup, the attested policy (rules, `[exec]`, `[exits]`, `[limits]`), the injector and `forward` with the response scrub (S1), the agent's `redact`, `redactStream` and `endpoints` (S3), the model and MCP refusal, and the vault side of the `/dev/sealed` ops `seal`, `placeholder`, `list`, `test`, `request`, `status`, `cancel` and `materialize`.
|
|
6
|
+
- **Not built yet:** exec (`materialize`), `import` and `export`, and the agent's `model`, `mcp`, `records`, `grant` and `refresh`. They answer as described below.
|
|
7
|
+
- **The vault has no network stack.** It never fetches anything but its own `config.json` and `embedders.json`: bios sends every request the vault prepares.
|
|
7
8
|
|
|
8
9
|
## Documents and hosting
|
|
9
10
|
|
|
@@ -139,7 +140,7 @@ Accepted policy is kept per namespace in IndexedDB, and loaded when an embedder
|
|
|
139
140
|
`scrub { needed, version, ready }` tells bios and the agent whether output must pass the vault's scrubber before it reaches the model. It's per namespace:
|
|
140
141
|
- `needed` is false only when the namespace holds no plaintext at all: no record of any kind or state, removed ones included until they're purged.
|
|
141
142
|
- `version` counts every change to the namespace's set of values: each seal, rotation, removal, restore and purge.
|
|
142
|
-
- `ready` is false only when values exist
|
|
143
|
+
- `ready` is false only when values exist, the vault is locked, and this frame has no compiled scrubber for the namespace: a reload with the lock on, before unlock. The scrubber (`@ai-ecoverse/slicc-scrub`, over every value of the namespace, records of every kind and state) is compiled whenever the frame holds the key and the set of values changed, and is kept in memory for the frame's life, so locking stops value use but never scrubbing.
|
|
143
144
|
|
|
144
145
|
It's in `status`, in `placeholders` replies and in every `placeholders` push. After `put` and `seal`, the push with the new pair goes out **before** the reply.
|
|
145
146
|
|
|
@@ -158,12 +159,13 @@ iframe.contentWindow.postMessage({ type: 'slicc-vault', v: 1, op: 'hello', role:
|
|
|
158
159
|
- The frame answers only when the message comes from its own parent window, from an allowed origin, matching `location.ancestorOrigins[0]` when the browser exposes it. Anything else gets no answer at all.
|
|
159
160
|
- On `port2` it answers `{ v: 1, op: 'welcome', role, status }`, or `{ v: 1, op: 'refused', error }` for another protocol version or an unknown role.
|
|
160
161
|
- Everything after that goes over the port. The namespace and the role are fixed by the hello. Requests are `{ v: 1, id, op, ...fields }`; replies are `{ v: 1, id, op, ...fields }` or `{ v: 1, id, error: { code, message } }`. Each port is answered in order (FIFO).
|
|
161
|
-
- **Roles:** `page` (the default) is bios and spectrum. bios may hand spectrum a page port of its own, or relay; the messages are the same. `agent` is the port bios hands the agent worker: it may use only `redact`, `redactStream`, `push`, `end`, `drop`, `
|
|
162
|
+
- **Roles:** `page` (the default) is bios and spectrum. bios may hand spectrum a page port of its own, or relay; the messages are the same. `agent` is the port bios hands the agent worker: it may use only `redact`, `redactStream`, `push`, `idle`, `end`, `drop`, `endpoints`, `model`, `mcp`, `records`, `grant` and `refresh` (the last five `ENOTSUP` in this version), and anything else is `EACCES`. The agent port gets no events. Its ops are below (The agent's ops).
|
|
163
|
+
- **Values:** only `forward` puts a value into the page, inside the head it returns, and only where an accepted rule allows it. No other op, event or reply carries one, and nothing on the agent port ever does.
|
|
162
164
|
|
|
163
165
|
| op (page role) | fields | reply |
|
|
164
166
|
|---|---|---|
|
|
165
167
|
| `sealed` | `req` (the `/dev/sealed` request object, or its JSON text), `stamp` (`{ pid, ppid, uid, gid, tag }` from the kernel) | `{ reply }`, the §3.7 reply, below |
|
|
166
|
-
| `status` | — | `{ status: { version, protocol, origin, locked, lock, scrub, waiting, exportedAt, backupReminder } }` |
|
|
168
|
+
| `status` | — | `{ status: { version, protocol, origin, locked, lock, scrub, waiting, exportedAt, backupReminder, policy } }` |
|
|
167
169
|
| `placeholders` | — | `{ placeholders, scrub }`: every placeholder of a record that isn't removed, active and inert, sorted |
|
|
168
170
|
| `list` | — | `{ list: { secrets, refused, audit, auditMore, exits } }` for Settings › Secrets |
|
|
169
171
|
| `audit` | `before?` (a `seq`), `limit?` (1–1000, default 100) | `{ audit, more, next? }`, newest first; pass `next` as `before` for the next page |
|
|
@@ -174,6 +176,7 @@ iframe.contentWindow.postMessage({ type: 'slicc-vault', v: 1, op: 'hello', role:
|
|
|
174
176
|
| `lock` | — | `{}`; drops the key everywhere when the lock is on |
|
|
175
177
|
| `dismissBackupReminder` | — | `{ backupReminder }`; the reminder becomes `dismissed` for this namespace |
|
|
176
178
|
| `policy` | `files` | the attested policy files, below (Policy) |
|
|
179
|
+
| `forward` | `head`, `body?`, `owner`, `exit`, `rawTraits`, with a `MessagePort` transferred alongside | the injected head, below (Forward) |
|
|
177
180
|
| `import`, `export`, anything else | | `ENOTSUP` |
|
|
178
181
|
|
|
179
182
|
`put` and `seal` need the vault unlocked. They answer `EACCES` with a message starting `vault is locked` otherwise.
|
|
@@ -194,7 +197,7 @@ bios relays each kernel request unchanged as the `sealed` op, with the kernel's
|
|
|
194
197
|
| `seal` | `name`, `value` | `{ placeholder, state }`. A new name creates a `process` record. An existing one is rotated and keeps its placeholder, but only when its value came from a process; a value from Settings, jerk, OAuth or an import is replaced only by uid 0, and anyone else gets `EEXIST` |
|
|
195
198
|
| `placeholder` | `name` | `{ placeholder, state }`, including `removed`; `ENOENT` when there's no record |
|
|
196
199
|
| `list` | — | `{ secrets: [{ name, placeholder, state, exec, rules, expiresAt? }] }`, records of kind `secret` that aren't removed, with their rules and `[exec]` mode |
|
|
197
|
-
| `test` | `name`, `url`, `method
|
|
200
|
+
| `test` | `name`, `url`, `method?` (`GET`), `header?` (`authorization`), `exit?` (`page`) | `{ verdict: 'inject' \| 'refuse', reason }`: the injector's verdict for `Bearer <placeholder>` in that header, without sending anything; `ENOENT` for an unknown name |
|
|
198
201
|
| `request` | `kind: "value"`, `name`, `prompt?` (≤ 200 characters) | `{ state: "pending", id }` |
|
|
199
202
|
| `request` | `kind: "oauth"`, `provider`, `oauth` (an object) | the same |
|
|
200
203
|
| `request` | `kind: "jerk-seal"`, `provider` | the same |
|
|
@@ -205,6 +208,52 @@ bios relays each kernel request unchanged as the `sealed` op, with the kernel's
|
|
|
205
208
|
- **Requests** expire 300 s after they're made. Each uid has at most one pending request per namespace; a second one is `EAGAIN`. `status` and `cancel` see only the caller's own requests (uid 0 sees all), and others get `ENOENT`.
|
|
206
209
|
- A value request shows up in `status.waiting` and is answered by the page's `put` with its `request` id, or ended by `cancel`. `oauth` and `jerk-seal` requests can only be cancelled in this version.
|
|
207
210
|
|
|
211
|
+
## Forward
|
|
212
|
+
|
|
213
|
+
bios's exit router asks the vault to inject a request the kernel forwarded (an owner-bearing request that carries a placeholder), then sends it itself:
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
const channel = new MessageChannel();
|
|
217
|
+
port.postMessage({ v: 1, id, op: 'forward', head, body, owner, exit, rawTraits }, [channel.port2]);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
- `head` is `{ method, url, headers: [name, value][] }`; `owner` the kernel's `{ pid, ppid, uid, gid, tag }`; `exit` the exit bios chose (`page`, `proxy`, `tailscale` or `device:<name>`); `rawTraits` that exit's `{ manualRedirects?, encodedBodies? }`. `body` (bytes or a string) is needed only for MCP requests (below); for every other request it stays in bios, because bodies are never injected.
|
|
221
|
+
- **The reply** is `{ head }`, the same head with the values filled in, or `{ refused: { status, reason } }`: `403` with a one-line reason, or `502` for an exit with encoded bodies. A refused request must not be sent anywhere. Malformed fields are `EINVAL`.
|
|
222
|
+
- **The response** goes back over `channel.port1`, scrubbed: bios posts `{ op: 'response', status, statusText, url, redirected?, headers }`, then any number of `{ op: 'body', chunk: Uint8Array }`, then `{ op: 'end' }` or `{ op: 'error', message }`. The vault answers with the same messages, with `statusText`, `url`, every header name and value, the body and the error scrubbed over every value of the namespace. A value in its raw form comes back as its placeholder, anything else as `[redacted:NAME]`. The body is scrubbed as a stream; after 250 ms without input, a held tail shorter than 16 bytes is let through.
|
|
223
|
+
|
|
224
|
+
**The injector**, fnox's proxy semantics:
|
|
225
|
+
- **Hosts** are compared lower-cased, without a trailing dot, in rules, the refusal list and MCP servers alike.
|
|
226
|
+
- **Refused before anything is sent:** a placeholder in the URL or in a header name; credentials in the URL; a scheme other than `https:` or a port other than 443 (except §3.16.3's kernel servers, below); an ambiguous path (`.`/`..` segments, `\`, `%2e`, `%2f`, `%5c`, `%25`, checked on the raw URL); an exit with encoded bodies; no placeholder of this vault at all; a record that is removed, expired ("NAME expired; refreshing") or not a `secret`; a locked vault; no rule (in `/etc/fnox/config.toml`) whose exact domain, header, method and path allow it; an exit the secret's `[exits]` line doesn't list; the same placeholder twice in one header value; a header other than `authorization` on an exit that follows redirects (`manualRedirects` false); CR, LF or NUL after substitution.
|
|
227
|
+
- **Paths** in rules are globs: `*` stays within a segment, `**` crosses segments, `?` is one character.
|
|
228
|
+
- **Injected:** each placeholder is replaced inside the rule's header value, so `Bearer …` and `token …` templates work. In `Authorization: Basic`, the credential is decoded, the user and password parts substituted (a substituted user may not contain `:`), and re-encoded. A Basic value that holds a placeholder but isn't valid base64 of UTF-8 is refused.
|
|
229
|
+
- **Audited:** each injection adds a `forward` audit entry `{ name, domain, method, path, rule, exit, uid, tag }` and sets the record's `usedAt`. Never headers, bodies or values.
|
|
230
|
+
|
|
231
|
+
## Model and MCP endpoints
|
|
232
|
+
|
|
233
|
+
The vault never injects a secret into a model or MCP endpoint, whatever a rule says.
|
|
234
|
+
- **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`), plus `bedrock-runtime.*` and `bedrock-runtime-fips.*.amazonaws.com`, Azure OpenAI and AI services, and Adobe's LLM proxy. Each entry is a host (with `*` for one label) and a path prefix (`*` for one segment, from templated segments).
|
|
235
|
+
- **Registered endpoints:** the agent's `endpoints` op adds model base URLs and MCP servers for its namespace. They only ever add.
|
|
236
|
+
- **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) 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.
|
|
237
|
+
- **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`.
|
|
238
|
+
- **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.
|
|
239
|
+
- **`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.
|
|
240
|
+
|
|
241
|
+
## The agent's ops
|
|
242
|
+
|
|
243
|
+
| op | fields | reply |
|
|
244
|
+
|---|---|---|
|
|
245
|
+
| `redact` | `texts`: strings and `Uint8Array`s | `{ texts, hits, version }`: each text scrubbed, in the same order and type; `hits` totals `{ name, form, count }` |
|
|
246
|
+
| `redactStream` | `stream` (an id) | `{ stream, idleMs, version }`; at most 64 streams per port (`EAGAIN`) |
|
|
247
|
+
| `push` | `stream`, `chunk` (bytes) | `{ chunk }`: what can be released, scrubbed |
|
|
248
|
+
| `idle` | `stream` | `{ chunk }`: a held tail under 16 bytes, after `idleMs` without input |
|
|
249
|
+
| `end` | `stream` | `{ chunk, hits }`: the rest, and the stream is gone |
|
|
250
|
+
| `drop` | `stream` | `{}` |
|
|
251
|
+
| `endpoints` | `model?`: https base URLs; `mcp?`: `{ server, url, names? }` or a URL string | `{ ok: true }`; new entries re-check the policy and push `changed` |
|
|
252
|
+
|
|
253
|
+
A stream is compiled against the namespace's values when it opens. If a value is added, rotated or removed while it's open, its next `push`, `idle` or `end` answers `EAGAIN` and the stream is gone: open it again and push the output from its start.
|
|
254
|
+
|
|
255
|
+
`redact` and `redactStream` need a compiled scrubber: with the lock on, before the first unlock since the frame loaded, they answer `EACCES` ("unlock the vault to continue"). They never return a value: matches are replaced, everything else passes through.
|
|
256
|
+
|
|
208
257
|
## The button (`button.html`)
|
|
209
258
|
|
|
210
259
|
A popup needs a click inside a vault document, so the way into the lock popup is this button. The embedder loads `https://vault.sliccy.ai/button.html` in an iframe and, after `load`, posts:
|
|
@@ -262,8 +311,8 @@ The npm package `@ai-ecoverse/slicc-vault` holds only TypeScript types, built fr
|
|
|
262
311
|
- **`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.
|
|
263
312
|
- **`exits`** is present only when `/etc/slicc/secrets-policy.toml` restricts that secret; absent means every exit (`page`, `proxy`, `tailscale`, `device:<id>`).
|
|
264
313
|
- **`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.
|
|
265
|
-
- **`AuditEntry`**: `forward` is a use of a value in a request, with the exit that carried it; **`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.
|
|
266
|
-
- **`VaultList.refused`** lists rules the vault dropped because they name a model or MCP endpoint
|
|
314
|
+
- **`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; **`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.
|
|
315
|
+
- **`VaultList.refused`** lists rules the vault dropped because they name a model or MCP endpoint.
|
|
267
316
|
- **`PendingRequest.prompt`** is untrusted, agent-written text of at most 200 characters.
|
|
268
317
|
- **`ExitPolicyView`** is read-only: the secrets `/etc/slicc/secrets-policy.toml` restricts to certain exits.
|
|
269
318
|
|
package/dist/types/contract.d.ts
CHANGED
|
@@ -121,6 +121,14 @@ export interface ForwardEntry extends AuditBase {
|
|
|
121
121
|
rule: Rule;
|
|
122
122
|
exit: ExitName;
|
|
123
123
|
}
|
|
124
|
+
export interface McpEntry extends AuditBase {
|
|
125
|
+
type: 'mcp';
|
|
126
|
+
server: string;
|
|
127
|
+
domain: string;
|
|
128
|
+
method: string;
|
|
129
|
+
path: string;
|
|
130
|
+
exit: ExitName;
|
|
131
|
+
}
|
|
124
132
|
export interface RevealEntry extends AuditBase {
|
|
125
133
|
type: 'materialize';
|
|
126
134
|
exec: ExecMode;
|
|
@@ -152,7 +160,51 @@ export interface PolicyEntry {
|
|
|
152
160
|
changes: PolicyChange[];
|
|
153
161
|
warning?: string;
|
|
154
162
|
}
|
|
155
|
-
export type AuditEntry = ForwardEntry | RevealEntry | SealEntry | RemoveEntry | PolicyEntry;
|
|
163
|
+
export type AuditEntry = ForwardEntry | McpEntry | RevealEntry | SealEntry | RemoveEntry | PolicyEntry;
|
|
164
|
+
export interface RequestHead {
|
|
165
|
+
method: string;
|
|
166
|
+
url: string;
|
|
167
|
+
headers: [string, string][];
|
|
168
|
+
}
|
|
169
|
+
export interface RawTraits {
|
|
170
|
+
manualRedirects?: boolean;
|
|
171
|
+
encodedBodies?: boolean;
|
|
172
|
+
}
|
|
173
|
+
export type ForwardResult = {
|
|
174
|
+
head: RequestHead;
|
|
175
|
+
body?: Uint8Array;
|
|
176
|
+
} | {
|
|
177
|
+
refused: {
|
|
178
|
+
status: number;
|
|
179
|
+
reason: string;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
export type ResponsePart = {
|
|
183
|
+
op: 'response';
|
|
184
|
+
status: number;
|
|
185
|
+
statusText: string;
|
|
186
|
+
url: string;
|
|
187
|
+
redirected?: boolean;
|
|
188
|
+
headers: [string, string][];
|
|
189
|
+
} | {
|
|
190
|
+
op: 'body';
|
|
191
|
+
chunk: Uint8Array;
|
|
192
|
+
} | {
|
|
193
|
+
op: 'end';
|
|
194
|
+
} | {
|
|
195
|
+
op: 'error';
|
|
196
|
+
message: string;
|
|
197
|
+
};
|
|
198
|
+
export interface McpServerEntry {
|
|
199
|
+
server: string;
|
|
200
|
+
url: string;
|
|
201
|
+
names?: string[];
|
|
202
|
+
}
|
|
203
|
+
export interface ScrubHit {
|
|
204
|
+
name: string;
|
|
205
|
+
form: string;
|
|
206
|
+
count: number;
|
|
207
|
+
}
|
|
156
208
|
export interface AuditPage {
|
|
157
209
|
audit: AuditEntry[];
|
|
158
210
|
more: boolean;
|
|
@@ -304,6 +356,60 @@ export type Op = {
|
|
|
304
356
|
} | {
|
|
305
357
|
op: 'policy';
|
|
306
358
|
files: Attestation[];
|
|
359
|
+
} | {
|
|
360
|
+
op: 'forward';
|
|
361
|
+
head: RequestHead;
|
|
362
|
+
body?: Uint8Array | string;
|
|
363
|
+
owner: Stamp;
|
|
364
|
+
exit: ExitName;
|
|
365
|
+
rawTraits: RawTraits;
|
|
366
|
+
};
|
|
367
|
+
export type AgentOp = {
|
|
368
|
+
op: 'redact';
|
|
369
|
+
texts: (string | Uint8Array)[];
|
|
370
|
+
} | {
|
|
371
|
+
op: 'redactStream';
|
|
372
|
+
stream: string;
|
|
373
|
+
} | {
|
|
374
|
+
op: 'push';
|
|
375
|
+
stream: string;
|
|
376
|
+
chunk: Uint8Array;
|
|
377
|
+
} | {
|
|
378
|
+
op: 'idle';
|
|
379
|
+
stream: string;
|
|
380
|
+
} | {
|
|
381
|
+
op: 'end';
|
|
382
|
+
stream: string;
|
|
383
|
+
} | {
|
|
384
|
+
op: 'drop';
|
|
385
|
+
stream: string;
|
|
386
|
+
} | {
|
|
387
|
+
op: 'endpoints';
|
|
388
|
+
model?: string[];
|
|
389
|
+
mcp?: (string | McpServerEntry)[];
|
|
390
|
+
};
|
|
391
|
+
export type AgentReply = {
|
|
392
|
+
op: 'redact';
|
|
393
|
+
texts: (string | Uint8Array)[];
|
|
394
|
+
hits: ScrubHit[];
|
|
395
|
+
version: number;
|
|
396
|
+
} | {
|
|
397
|
+
op: 'redactStream';
|
|
398
|
+
stream: string;
|
|
399
|
+
idleMs: number;
|
|
400
|
+
version: number;
|
|
401
|
+
} | {
|
|
402
|
+
op: 'push' | 'idle';
|
|
403
|
+
chunk: Uint8Array;
|
|
404
|
+
} | {
|
|
405
|
+
op: 'end';
|
|
406
|
+
chunk: Uint8Array;
|
|
407
|
+
hits: ScrubHit[];
|
|
408
|
+
} | {
|
|
409
|
+
op: 'drop';
|
|
410
|
+
} | {
|
|
411
|
+
op: 'endpoints';
|
|
412
|
+
ok: true;
|
|
307
413
|
};
|
|
308
414
|
export type OpReply = {
|
|
309
415
|
op: 'sealed';
|
|
@@ -337,7 +443,9 @@ export type OpReply = {
|
|
|
337
443
|
backupReminder: BackupReminder;
|
|
338
444
|
} | ({
|
|
339
445
|
op: 'policy';
|
|
340
|
-
} & PolicyResult)
|
|
446
|
+
} & PolicyResult) | ({
|
|
447
|
+
op: 'forward';
|
|
448
|
+
} & ForwardResult);
|
|
341
449
|
export type Request = Op & {
|
|
342
450
|
v: Protocol;
|
|
343
451
|
id: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-vault",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.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
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"dist/types"
|
|
32
32
|
],
|
|
33
33
|
"scripts": {
|
|
34
|
-
"prepare": "[ ! -e .git ] || lefthook install",
|
|
35
|
-
"build": "node build.mjs && tsc -p tsconfig.build.json",
|
|
34
|
+
"prepare": "node scripts/endpoints.mjs && { [ ! -e .git ] || lefthook install; }",
|
|
35
|
+
"build": "node scripts/endpoints.mjs && node build.mjs && tsc -p tsconfig.build.json",
|
|
36
36
|
"prepack": "npm run build",
|
|
37
37
|
"start": "npm run build && node test/integration/serve.mjs",
|
|
38
38
|
"pretest": "npm run build && playwright-core install --no-shell chromium",
|
|
39
39
|
"test": "node --test --test-timeout=300000 --test-global-setup=node_modules/@ai-ecoverse/slicc-shared-web/harness/global.mjs 'test/integration/*.test.mjs'",
|
|
40
|
-
"test:unit": "NODE_NO_WARNINGS=1 mcr -c node_modules/@ai-ecoverse/slicc-shared-web/mcr.config.mjs node --import fake-indexeddb/auto --test --test-force-exit 'test/unit/**/*.test.mjs'",
|
|
40
|
+
"test:unit": "node scripts/endpoints.mjs && NODE_NO_WARNINGS=1 mcr -c node_modules/@ai-ecoverse/slicc-shared-web/mcr.config.mjs node --import fake-indexeddb/auto --test --test-force-exit 'test/unit/**/*.test.mjs'",
|
|
41
41
|
"typecheck": "tsc",
|
|
42
42
|
"lint": "slicc-lint",
|
|
43
43
|
"format": "biome check --write .",
|
|
@@ -46,8 +46,10 @@
|
|
|
46
46
|
"release": "semantic-release"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
+
"@ai-ecoverse/slicc-scrub": "1.0.0",
|
|
49
50
|
"@ai-ecoverse/slicc-shared-web": "1.13.1",
|
|
50
51
|
"@biomejs/biome": "2.5.15",
|
|
52
|
+
"@earendil-works/pi-ai": "1.0.4",
|
|
51
53
|
"@happy-dom/global-registrator": "20.14.5",
|
|
52
54
|
"@spectrum-css/button": "14.2.0",
|
|
53
55
|
"@spectrum-css/textfield": "8.2.0",
|