@ai-ecoverse/slicc-vault 1.13.0 → 1.14.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 +4 -3
- package/dist/types/contract.d.ts +7 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -174,7 +174,7 @@ iframe.contentWindow.postMessage({ type: 'slicc-vault', v: 1, op: 'hello', role:
|
|
|
174
174
|
| `placeholders` | — | `{ placeholders, scrub }`: every placeholder of a record that isn't removed, active and inert, sorted |
|
|
175
175
|
| `list` | — | `{ list: { secrets, refused, audit, auditMore, exits } }` for Settings › Secrets |
|
|
176
176
|
| `audit` | `before?` (a `seq`), `limit?` (1–1000, default 100) | `{ audit, more, next? }`, newest first; pass `next` as `before` for the next page |
|
|
177
|
-
| `put` | `name`, `value`, `kind?` (`secret`, the default, `model` or `mcp`), `provider?`, `server?`, `settings?`, `request?` | `{ name, placeholder, state }`. A value typed in Settings (Settings › Accounts puts model keys as `kind: 'model'` with their `provider`), with source `settings`; on an existing name it's a rotation that keeps the placeholder. With `request`, it answers that value request, which must still be pending and ask for `name`, and the record must be a `secret` (else `EINVAL`, and nothing is stored), so its `/dev/sealed` `status` becomes `done` |
|
|
177
|
+
| `put` | `name`, `value`, `kind?` (`secret`, the default, `model` or `mcp`), `provider?`, `server?`, `settings?`, `request?` | `{ name, placeholder, state }`. A value typed in Settings (Settings › Accounts puts model keys as `kind: 'model'` with their `provider`), with source `settings`; on an existing name it's a rotation that keeps the placeholder. Without `value`, for an existing `model` or `mcp` record, it only updates `provider`, `server` or `settings` (say, a new Cloudflare account id), keeping the value and placeholder (`ENOENT` if there's no such live record; like every `put`, it needs the vault unlocked), audited as a `seal` entry with `rebound: true`; a new `server` clears a first-use pin, and a new `provider` drops the record's custom base URLs. With `request`, it answers that value request, which must still be pending and ask for `name`, and the record must be a `secret` (else `EINVAL`, and nothing is stored), so its `/dev/sealed` `status` becomes `done` |
|
|
178
178
|
| `seal` | `name`, `value`, `source`, `kind?` (default `secret`), `expiresAt?`, `refresh?`, `oauth?`, `provider?`, `server?`, `settings?`, `request?`, `jerk?` | `{ name, placeholder, state }`. bios's, for J1 leases and sign-in tokens, below (Tokens and refresh) |
|
|
179
179
|
| `answer` | `request`, `state` (`progress` or `done`), `progress?` (≤ 200), `exit?`, `user?`, `scopes?`, `message?` (≤ 500), `rows?`, `placeholder?` | `{ state }`. The answer to a `jerk` or `unseal` request (or a sign-in that failed: for `oauth` and `jerk-seal`, `done` needs a nonzero `exit`, since only `seal` completes them); fields merge into the request, and `status` returns them. `rows` (for `jop: "list"`) are `{ provider, name?, env, device?, signedIn?, user?, scopes? }`, with any other field dropped, so no token can pass. For a `jop: "status"` answered `done` with `exit` 0, the vault adds the placeholder of the provider's own `oauth:<provider>` or `jerk:<provider>@…` record; a `placeholder` given by bios must be one of those records of the provider |
|
|
180
180
|
| `refresh` | `name` | `{ state: 'refreshed', expiresAt? }` or `{ state: 'requested' }`, below |
|
|
@@ -183,7 +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
|
+
| `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; a field other than `model`, `mcp`, `remove` and `unpin` is `EINVAL` too. `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` |
|
|
187
187
|
| `forward` | `head`, `body?`, `owner`, `exit`, `rawTraits`, with a `MessagePort` transferred alongside | the injected head, below (Forward) |
|
|
188
188
|
| `materializeConsume` | `ticket`, `stamp`, `path`, `resolved`, `argv`, `cwd`, `interpreters`, `trusted` | the values for the child's environment, below (Exec) |
|
|
189
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) |
|
|
@@ -360,7 +360,8 @@ The candidates are the placeholders that would pass the per-placeholder checks a
|
|
|
360
360
|
## Model and MCP endpoints
|
|
361
361
|
|
|
362
362
|
The vault never injects a secret into a model or MCP endpoint, whatever a rule says.
|
|
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).
|
|
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 (or segment). 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
|
+
- **Tenants (V3):** a built-in wildcard named after a tenant setting is bound to the key's own record. `gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}/…`, `api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai…` and the Azure hosts `{AZURE_OPENAI_RESOURCE_NAME}.openai.azure.com`, `.services.ai.azure.com` and `.cognitiveservices.azure.com/openai` fill a key only where each label or segment equals the record's `settings` entry of that name (Azure's host label case-insensitively, Cloudflare's path segments exactly), when the record has one. A record without them still reaches any tenant on that vendor's domain, as before; re-saving its `settings` binds it. Other wildcards (Bedrock's region, Vertex's location) aren't tenants and stay open.
|
|
364
365
|
- **Registered endpoints** only ever add, per namespace, and who registers them decides what they do:
|
|
365
366
|
- **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
367
|
- **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.
|
package/dist/types/contract.d.ts
CHANGED
|
@@ -205,6 +205,7 @@ export interface SealEntry extends AuditBase {
|
|
|
205
205
|
type: 'seal';
|
|
206
206
|
source: RecordSource;
|
|
207
207
|
rotated: boolean;
|
|
208
|
+
rebound?: true;
|
|
208
209
|
}
|
|
209
210
|
export interface RemoveEntry extends AuditBase {
|
|
210
211
|
type: 'remove' | 'restore';
|
|
@@ -451,6 +452,12 @@ export type Op = {
|
|
|
451
452
|
value: string;
|
|
452
453
|
kind?: 'secret' | 'model' | 'mcp';
|
|
453
454
|
request?: string;
|
|
455
|
+
} & RecordBinding) | ({
|
|
456
|
+
op: 'put';
|
|
457
|
+
name: string;
|
|
458
|
+
value?: never;
|
|
459
|
+
kind: 'model' | 'mcp';
|
|
460
|
+
request?: never;
|
|
454
461
|
} & RecordBinding) | {
|
|
455
462
|
op: 'cancel';
|
|
456
463
|
request: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-vault",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.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.
|
|
51
|
+
"@ai-ecoverse/slicc-kernel": "1.130.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",
|