@north-light/cli 0.3.538 → 0.3.540

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 (87) hide show
  1. package/dist/api/contract.d.ts +1 -1
  2. package/dist/api/contract.js +1 -1
  3. package/dist/api/dto/profiles.d.ts +2 -0
  4. package/dist/builtin-memory/crouter-sdk/release-notes.md +10 -0
  5. package/dist/builtin-memory/northlight-apps/concepts/apps-and-sign-in.md +1 -1
  6. package/dist/builtin-memory/northlight-apps/concepts/connections.md +1 -1
  7. package/dist/builtin-memory/northlight-apps/errors.md +1 -1
  8. package/dist/builtin-memory/northlight-apps/guides/many-users.md +2 -2
  9. package/dist/clients/attach/viewer.js +454 -454
  10. package/dist/commands/profile/list.js +1 -1
  11. package/dist/commands/profile/show.js +1 -1
  12. package/dist/commands/sys/join.js +1 -1
  13. package/dist/commands/sys/sync-shared.d.ts +1 -1
  14. package/dist/commands/sys/sync-shared.js +1 -1
  15. package/dist/core/canvas/canvas.d.ts +0 -6
  16. package/dist/core/canvas/canvas.js +17 -22
  17. package/dist/core/canvas/crons.js +10 -10
  18. package/dist/core/canvas/db.js +4 -4
  19. package/dist/core/canvas/export-sqlite.js +1 -1
  20. package/dist/core/canvas/legacy-person.d.ts +4 -0
  21. package/dist/core/canvas/legacy-person.js +1 -0
  22. package/dist/core/canvas/migrations.js +58 -58
  23. package/dist/core/canvas/node-tokens.d.ts +0 -4
  24. package/dist/core/canvas/node-tokens.js +3 -3
  25. package/dist/core/canvas/person.d.ts +39 -0
  26. package/dist/core/canvas/person.js +18 -0
  27. package/dist/core/canvas/schema-pg.sql +11 -0
  28. package/dist/core/directory/join.d.ts +2 -2
  29. package/dist/core/environments.d.ts +10 -0
  30. package/dist/core/environments.js +1 -0
  31. package/dist/core/grants/local.d.ts +4 -4
  32. package/dist/core/grants/local.js +1 -1
  33. package/dist/core/grants/mirror.d.ts +1 -1
  34. package/dist/core/grants/on-sync.js +1 -1
  35. package/dist/core/grants/sync.js +1 -1
  36. package/dist/core/graph/kinds/environment.d.ts +2 -0
  37. package/dist/core/graph/kinds/environment.js +2 -0
  38. package/dist/core/graph/kinds/registry.js +1 -1
  39. package/dist/core/graph/objects.d.ts +1 -1
  40. package/dist/core/graph/objects.js +7 -7
  41. package/dist/core/graph/reader.d.ts +0 -1
  42. package/dist/core/graph/reader.js +3 -3
  43. package/dist/core/layout-migrate/index.js +3 -3
  44. package/dist/core/layout-migrate/stores.js +3 -3
  45. package/dist/core/peer/stubs.js +1 -1
  46. package/dist/core/runs/events.d.ts +0 -2
  47. package/dist/core/runs/events.js +4 -4
  48. package/dist/core/runs/operations.d.ts +0 -3
  49. package/dist/core/runs/operations.js +6 -6
  50. package/dist/core/runtime/close.js +1 -1
  51. package/dist/core/runtime/host.js +3 -3
  52. package/dist/core/runtime/launch-target.d.ts +10 -1
  53. package/dist/core/runtime/launch-target.js +1 -1
  54. package/dist/core/runtime/nodes.js +1 -1
  55. package/dist/core/scoped-state/db.js +2 -2
  56. package/dist/core/scoped-state/profiles.js +1 -1
  57. package/dist/core/scoped-state/schema.d.ts +4 -0
  58. package/dist/core/scoped-state/schema.js +3 -3
  59. package/dist/core/spaces/process.js +1 -1
  60. package/dist/daemon/api/handlers/crons.js +1 -1
  61. package/dist/daemon/api/handlers/hook-exec.js +1 -1
  62. package/dist/daemon/api/handlers/memory.js +5 -5
  63. package/dist/daemon/api/handlers/messages.js +2 -2
  64. package/dist/daemon/api/handlers/nodes.js +1 -1
  65. package/dist/daemon/api/handlers/profiles.js +1 -1
  66. package/dist/daemon/api/reader.js +1 -1
  67. package/dist/daemon/api/router.js +1 -1
  68. package/dist/daemon/cron/armed-context.js +1 -1
  69. package/dist/daemon/cron/authority.d.ts +1 -2
  70. package/dist/daemon/cron/authority.js +1 -1
  71. package/dist/daemon/crtrd.js +12 -12
  72. package/dist/daemon/reconcilers/storage-maintenance.d.ts +3 -0
  73. package/dist/daemon/reconcilers/storage-maintenance.js +1 -1
  74. package/dist/migrations/004-canvas-documents/apply.js +1 -1
  75. package/dist/migrations/004-canvas-documents/index.js +2 -2
  76. package/dist/types.d.ts +2 -0
  77. package/docs/apps/concepts/apps-and-sign-in.md +1 -1
  78. package/docs/apps/concepts/connections.md +1 -1
  79. package/docs/apps/errors.md +1 -1
  80. package/docs/apps/guides/many-users.md +2 -2
  81. package/docs/cli/join-northlight.md +1 -1
  82. package/docs/sdk/release-notes.md +10 -0
  83. package/package.json +2 -2
  84. package/packages/crouter-identity/package.json +1 -1
  85. package/runtime.lock.json +12 -12
  86. package/dist/daemon/joined-owner.d.ts +0 -5
  87. package/dist/daemon/joined-owner.js +0 -1
@@ -1,5 +1,5 @@
1
1
  /** The contract level this build serves and requires. Written by `scripts/contract.mjs release`; never edit by hand. */
2
- export declare const CONTRACT_LEVEL = "1.27";
2
+ export declare const CONTRACT_LEVEL = "1.28";
3
3
  /** Request header naming the one contract level the caller needs, e.g. `1.3`. Optional: absent means no check. */
4
4
  export declare const REQUIRED_CONTRACT_HEADER = "Crouter-Required-Contract";
5
5
  /** Response header listing the contract levels the server serves, comma-separated, one per major, e.g. `1.3`. */
@@ -1 +1 @@
1
- var c=Object.defineProperty;var e=(r,t)=>c(r,"name",{value:t,configurable:!0});const f="1.27",i="Crouter-Required-Contract",p="Crouter-Contract";function l(r){const t=/^(\d+)\.(\d+)$/.exec(r.trim());return t===null?null:{major:Number(t[1]),minor:Number(t[2])}}e(l,"parseContractLevel");function a(r){return r==null?[]:r.split(",").map(t=>l(t)).filter(t=>t!==null)}e(a,"parseServedContracts");function s(r,t){const n=l(r);return n===null?!1:(typeof t=="string"||t===null||t===void 0?a(t):t).some(u=>u.major===n.major&&u.minor>=n.minor)}e(s,"contractSatisfies");function C(r,t,n={}){if(r===void 0)return null;if(l(r)===null)return{status:400,code:"invalid_request",param:i,message:`${i} must be a contract level like 1.0.`};if(s(r,t))return null;const o=r.trim();return{status:426,code:"runtime_version_unsupported",message:t===null||a(t).length===0?`The runtime did not name its contract level; the caller requires contract ${o} or later. Roll the runtime forward.`:`The runtime serves contract ${t}; the caller requires contract ${o} or later within the same major. Roll the runtime forward, or pin an SDK whose crouterContract the runtime serves.`,details:{sdk_version:(n.legacyMinimum??"").trim(),runtime_version:n.runtimeVersion??null,required_contract:o,runtime_contract:t}}}e(C,"contractRefusal");export{p as CONTRACT_HEADER,f as CONTRACT_LEVEL,i as REQUIRED_CONTRACT_HEADER,C as contractRefusal,s as contractSatisfies,l as parseContractLevel,a as parseServedContracts};
1
+ var c=Object.defineProperty;var e=(r,t)=>c(r,"name",{value:t,configurable:!0});const f="1.28",i="Crouter-Required-Contract",p="Crouter-Contract";function l(r){const t=/^(\d+)\.(\d+)$/.exec(r.trim());return t===null?null:{major:Number(t[1]),minor:Number(t[2])}}e(l,"parseContractLevel");function a(r){return r==null?[]:r.split(",").map(t=>l(t)).filter(t=>t!==null)}e(a,"parseServedContracts");function s(r,t){const n=l(r);return n===null?!1:(typeof t=="string"||t===null||t===void 0?a(t):t).some(u=>u.major===n.major&&u.minor>=n.minor)}e(s,"contractSatisfies");function C(r,t,n={}){if(r===void 0)return null;if(l(r)===null)return{status:400,code:"invalid_request",param:i,message:`${i} must be a contract level like 1.0.`};if(s(r,t))return null;const o=r.trim();return{status:426,code:"runtime_version_unsupported",message:t===null||a(t).length===0?`The runtime did not name its contract level; the caller requires contract ${o} or later. Roll the runtime forward.`:`The runtime serves contract ${t}; the caller requires contract ${o} or later within the same major. Roll the runtime forward, or pin an SDK whose crouterContract the runtime serves.`,details:{sdk_version:(n.legacyMinimum??"").trim(),runtime_version:n.runtimeVersion??null,required_contract:o,runtime_contract:t}}}e(C,"contractRefusal");export{p as CONTRACT_HEADER,f as CONTRACT_LEVEL,i as REQUIRED_CONTRACT_HEADER,C as contractRefusal,s as contractSatisfies,l as parseContractLevel,a as parseServedContracts};
@@ -112,6 +112,8 @@ export interface ProfileDTO {
112
112
  created_at: string;
113
113
  /** ISO timestamp of the most recent selection, or null if never selected. */
114
114
  last_used_at: string | null;
115
+ /** The environment the profile's nodes run in: the stored pointer, or the install's machine environment when none is stored. */
116
+ environment_id?: string;
115
117
  /** Absolute path of the profile's directory, `<app space>/profiles/<id>`: its settings root. The profile's documents live in the canvas, not here. */
116
118
  profile_path: string;
117
119
  }
@@ -9,6 +9,16 @@ when-and-why-to-read: When you need Release notes, this knowledge should be read
9
9
 
10
10
  Changes to `@north-light/sdk` that can change what an existing app sees. Newest first.
11
11
 
12
+ ## 0.3.539
13
+
14
+ `exchangeIdentity` now returns the verified identity when the directory's token answer also carries a runtime connection. It used to throw `oauth_exchange_mismatch`, so no member could sign in to an app held by a team with a runtime grant (the directory gives that app a connection on every sign-in). The SDK revokes the unneeded refresh token best-effort; revocation removes only that token, never the grant. `exchangeCode` still refuses a sign-in-only answer.
15
+
16
+ A run started with no `kind` and no `model`, in a profile with no `default_kind` (every app's own default profile), now starts as the `general` kind on the `medium` rung. It used to start as `developer` on that kind's model (`openai/medium`). `profile.list` reports `general` as such a profile's `default_kind`. On an app-paid grant the run lands on the app's `medium` inference rung, where it used to land on `strong`. Pass `model` on `run.start` to keep another rung.
17
+
18
+ Profiles name the machine environment they run on. Additive: no request or response an existing app sends or reads changes.
19
+
20
+ - Profile reads (`GET /v1/profiles`, `GET /v1/profiles/:name`) carry an optional `environment_id`: the profile's pinned environment, or this machine's environment when none is pinned. A runtime that predates the field omits it.
21
+
12
22
  ## 0.3.534
13
23
 
14
24
  A cron armed by a caller with no scope limit follows the grant, and a narrowed scope pauses it.
@@ -76,7 +76,7 @@ Then set your own session for the person. The SDK does not manage your sessions.
76
76
 
77
77
  ### Scopes decide what comes back
78
78
 
79
- A sign-in that asks only for `openid`, optionally with `email` and `profile`, creates no connection. Finish it with `oauth.exchangeIdentity(...)`, which returns the verified `Identity` (`sub`, and `email`, `name` and `picture` when approved and present). A sign-in that asks for runtime scopes such as `crtr:llm` finishes with `exchangeCode`. Each method refuses the other's answer with `oauth_exchange_mismatch`.
79
+ A sign-in that asks only for `openid`, optionally with `email` and `profile`, creates no connection. Finish it with `oauth.exchangeIdentity(...)`, which returns the verified `Identity` (`sub`, and `email`, `name` and `picture` when approved and present). A sign-in that asks for runtime scopes such as `crtr:llm` finishes with `exchangeCode`. `exchangeCode` refuses a sign-in-only answer with `oauth_exchange_mismatch`; `exchangeIdentity` accepts an answer that also carries a connection, returns the identity, and revokes the unneeded refresh token.
80
80
 
81
81
  ### When the directory refuses to sign someone in
82
82
 
@@ -119,7 +119,7 @@ It needs the app registered with the `app_token_for_user` operation, and an acti
119
119
 
120
120
  ## Signing in a visitor
121
121
 
122
- A person who only needs to be recognized, not connected, signs in with identity only: request `openid`, optionally with `email` and `profile`, and no runtime scope. Finish with `exchangeIdentity`, not `exchangeCode`. An `Identity` is not a connection: no runtime URL, grant or refresh token, nothing goes in the store, and you keep your own session. To act for that person later, send them through `authorizeUrl` again with the runtime scopes you need.
122
+ A person who only needs to be recognized, not connected, signs in with identity only: request `openid`, optionally with `email` and `profile`, and no runtime scope. Finish with `exchangeIdentity`, not `exchangeCode`. An `Identity` is not a connection: no runtime URL, grant or refresh token (if the directory answers with one anyway, `exchangeIdentity` revokes the refresh token), nothing goes in the store, and you keep your own session. To act for that person later, send them through `authorizeUrl` again with the runtime scopes you need.
123
123
 
124
124
  ## Checked and not checked
125
125
 
@@ -18,7 +18,7 @@ Codes the SDK raises itself are listed in `sdkErrorCodes`, and `CrouterError.cod
18
18
  | Code | Means | What to do |
19
19
  |---|---|---|
20
20
  | `id_token_invalid` | An ID token failed verification (signature, issuer, audience, expiry, missing or mismatched nonce), or a sign-in-only answer had no ID token. A JWKS that can't be fetched or is malformed is not this code: that error is thrown as is. | Restart the sign-in. |
21
- | `oauth_exchange_mismatch` | The wrong exchange call: `exchangeCode` on a sign-in-only answer, or `exchangeIdentity` on an answer that carries a connection. | Use the call that matches the scopes you requested ([[northlight-apps/guides/many-users]]). |
21
+ | `oauth_exchange_mismatch` | `exchangeCode` got a sign-in-only answer (no connection). | Finish a sign-in-only request with `exchangeIdentity` ([[northlight-apps/guides/many-users]]). |
22
22
  | `oauth_nonce_missing` | `exchangeIdentity` was called without the `nonce` from `authorizeUrl`. | Save the nonce in the visitor's session and pass it back. |
23
23
  | `oauth_state_mismatch` | The callback's `state` was missing or differed from the saved one. | Refuse the callback. |
24
24
  | `not_connected` | `oauth.client(userId)` or a refresh found no stored connection for that person. | Show "sign in again". |
@@ -18,7 +18,7 @@ Keep the connection and refresh token on the server, never in a visitor's browse
18
18
 
19
19
  ## Signing in a visitor
20
20
 
21
- A visitor who only needs to be recognized, not connected, signs in with identity only. Request `openid`, adding `email` for their email and `profile` for their name and photo, and no runtime scope. The directory shows one line ("Know who you are on Northlight"), writes no grant, and answers with an ID token and an access token usable only at `/userinfo`: no refresh token, grant or runtime URL. Finish that sign-in with `exchangeIdentity`, not `exchangeCode`:
21
+ A visitor who only needs to be recognized, not connected, signs in with identity only. Request `openid`, adding `email` for their email and `profile` for their name and photo, and no runtime scope. The directory shows one line ("Know who you are on Northlight"), writes no grant, and answers with an ID token and an access token usable only at `/userinfo`: no refresh token, grant or runtime URL. (An app held by a team with a runtime grant gets a connection on every sign-in; `exchangeIdentity` still returns only the identity and revokes the unneeded refresh token.) Finish that sign-in with `exchangeIdentity`, not `exchangeCode`:
22
22
 
23
23
  ```ts
24
24
  const {url, codeVerifier, state, nonce} = await oauth.authorizeUrl({scopes: ['openid', 'email', 'profile'], state: sessionState});
@@ -36,7 +36,7 @@ visitor.picture; // an https URL, present only when 'profile' was approved
36
36
 
37
37
  The SDK checks the ID token's ES256 signature against the directory's JWKS, its issuer, that `aud` is your client id, that it has not expired, and that its `nonce` equals the one `authorizeUrl` returned. `nonce` is required. Any failure throws `CrouterError` code `id_token_invalid`. If the directory's JWKS can't be fetched or is malformed, that error is thrown as is.
38
38
 
39
- An `Identity` is not a connection. Nothing is stored in a `ConnectionStore` and nothing refreshes; your app keeps its own session for the visitor, and the visitor's runtime can't be called on their behalf. To act for the visitor later, send them through `authorizeUrl` again with the runtime scopes you need and finish with `exchangeCode`, which returns a `Connection`. Each call refuses the other's answer with code `oauth_exchange_mismatch`. If `exchangeIdentity` refuses an answer that carries a connection, the directory has already recorded that grant; it shows in the person's approved apps until they or your app revoke it.
39
+ An `Identity` is not a connection. Nothing is stored in a `ConnectionStore` and nothing refreshes; your app keeps its own session for the visitor, and the visitor's runtime can't be called on their behalf. To act for the visitor later, send them through `authorizeUrl` again with the runtime scopes you need and finish with `exchangeCode`, which returns a `Connection`. `exchangeCode` refuses a sign-in-only answer with code `oauth_exchange_mismatch`.
40
40
 
41
41
  ## Whose action a call records
42
42