@ai-ecoverse/slicc-vault 1.8.1 → 1.8.3

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 (2) hide show
  1. package/README.md +3 -3
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -222,13 +222,13 @@ bios relays each kernel request unchanged as the `sealed` op, with the kernel's
222
222
 
223
223
  The vault has no network stack, so sign-ins run in seven's page (route (b), §3.11) and the vault keeps only the results.
224
224
  - **A sign-in's tokens:** bios runs the sign-in, does the code exchange, and hands the results to `seal`, keeping no copy:
225
- - the refresh token as `{ kind: 'grant', name, value, source: 'oauth:<provider>', oauth: { tokenUrl, clientId, scope?, resource? } }`. A grant is never injected and never exported; `tokenUrl` must be `https:`;
225
+ - the refresh token as `{ kind: 'grant', name, value, source: 'oauth:<provider>', oauth: { tokenUrl, clientId, scope?, resource? } }`. A grant is never injected and never exported; `tokenUrl` must be `https:`, without userinfo (`user:pw@`, `user@`, even an empty `:@`, also when hidden by whitespace or backslashes the URL parser normalises: any `@` in the authority refuses);
226
226
  - the access token as `{ name, value, source: 'oauth:<provider>', expiresAt, refresh: '<grant name>' }`. A grant name needs an `oauth:` source and `jerk-seal` a `jerk:` one (`EINVAL`), and a refresh uses the grant only when its source is the token's own (else the grant is missing).
227
227
  - With `request` (only for a `secret`; the id of a pending `oauth` request for the same provider as `oauth:<provider>`, or a `jerk-seal` request for the provider of `jerk:<provider>@…`) and `jerk` (`{ exit, user?, scopes?, expires_at? }`), `seal` also answers that request, in the same transaction that stores the record (a request that ended meanwhile refuses with `EINVAL`, and nothing is stored): its `/dev/sealed` `status` becomes `done`, with `jerk`, the record's `placeholder` and `record` state.
228
228
  - **A J1 lease:** `{ name, value, source: 'jerk:<provider>@<device>', expiresAt, refresh: 'jerk-seal' }`.
229
- - **When a token is due** (5 minutes before `expiresAt`): the core frame checks once a minute, for every connected namespace and for `secret`, `model` and `mcp` records alike, and `refresh { name }` asks for it at once. Vault frames of the same storage (several tabs) take a Web Lock per refresh source, so one grant is sent to its IdP by one frame at a time; a frame that finds the token changed while it waited (refreshed or sealed again) sends nothing and answers with the stored token's `{ state: 'refreshed', expiresAt? }`.
229
+ - **When a token is due** (5 minutes before `expiresAt`): the core frame checks once a minute, and right after a page says hello, for every connected namespace and for `secret`, `model` and `mcp` records alike, and `refresh { name }` asks for it at once. Vault frames of the same storage (several tabs) take a Web Lock per refresh source, so one grant is sent to its IdP by one frame at a time; a frame that finds the token changed while it waited (refreshed or sealed again) sends nothing and answers with the stored token's `{ state: 'refreshed', expiresAt? }`.
230
230
  - A `jerk-seal` token is announced once per `expiresAt` (kept in IndexedDB, so across frames), and again every 10 minutes while it stays unsealed, in case no live page heard it, with the `refresh` event, and bios runs J1 `seal` again (`{ state: 'requested' }`).
231
- - An OAuth token is refreshed in the vault: it builds `POST tokenUrl` with `grant_type=refresh_token`, the refresh token, `client_id` and any `scope` and `resource` (form-encoded), and sends it through bios with the `egress` event. bios sends the request through its exits and posts `{ status, headers, body }` (or `{ error }`) on the event's port within 30 s. The event goes to the page port of the namespace that connected last. A port that doesn't answer in time (`ETIMEDOUT`), closed or not, keeps its ops and events but gets no more `egress`, and the next refresh goes to the page port before it. The vault reads `access_token`, `expires_in` and any new `refresh_token`, checks them as values, and rotates the records in one transaction with the `refresh` audit entry (their placeholders stay; if the token or its grant was changed, removed or restored during the round trip, nothing is written and it answers `EAGAIN`). An `expires_in` of 0 makes the token due at once, and one that isn't a non-negative finite number is `EACCES: refresh failed: the IdP returned an invalid expires_in` (likewise a `refresh_token` that is present but not a string, and a `token_type` other than `Bearer`); a response carrying `error` fails even with a token; a response without `expires_in` leaves the new token without an expiry, so it isn't refreshed again until a new one is sealed. It answers `{ state: 'refreshed', expiresAt? }`, without `expiresAt` when the token has none. A failed refresh is `EACCES: refresh failed: <the IdP's error code>`, scrubbed. Without a connected page it's `ENOTCONN`.
231
+ - An OAuth token is refreshed in the vault: it builds `POST tokenUrl` with `grant_type=refresh_token`, the refresh token, `client_id` and any `scope` and `resource` (form-encoded), and sends it through bios with the `egress` event. bios sends the request through its exits and posts `{ status, headers, body }` (or `{ error }`) on the event's port within 30 s. The event goes to the page port of the namespace that connected last. A port that doesn't answer in time (`ETIMEDOUT`), closed or not, keeps its ops and events but gets no more `egress`, and the next refresh goes to the page port before it. The vault reads `access_token`, `expires_in` and any new `refresh_token`, checks them as values, and rotates the records in one transaction with the `refresh` audit entry (their placeholders stay; if the token or its grant was changed, removed or restored during the round trip, nothing is written and it answers `EAGAIN`). An `expires_in` of 0 makes the token due at once, and one that isn't a non-negative finite number is `EACCES: refresh failed: the IdP returned an invalid expires_in` (likewise a `refresh_token` that is present but not a string, a `token_type` other than `Bearer`, and `access_token`, `refresh_token`, `token_type` or `expires_in` given twice: `EACCES: refresh failed: the IdP returned NAME twice`); a response carrying `error` fails even with a token; a response without `expires_in` leaves the new token without an expiry, so it isn't refreshed again until a new one is sealed. It answers `{ state: 'refreshed', expiresAt? }`, without `expiresAt` when the token has none. A failed refresh is `EACCES: refresh failed: <the IdP's error code>`, scrubbed. Without a connected page it's `ENOTCONN`.
232
232
  - `egress` carries the refresh token to the page, in transit only; the response goes back to the vault, never to the kernel.
233
233
 
234
234
  ## Import and export
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-vault",
3
- "version": "1.8.1",
3
+ "version": "1.8.3",
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",