@north-light/cli 0.3.539 → 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.
- package/dist/builtin-memory/crouter-sdk/release-notes.md +2 -0
- package/dist/builtin-memory/northlight-apps/concepts/apps-and-sign-in.md +1 -1
- package/dist/builtin-memory/northlight-apps/concepts/connections.md +1 -1
- package/dist/builtin-memory/northlight-apps/errors.md +1 -1
- package/dist/builtin-memory/northlight-apps/guides/many-users.md +2 -2
- package/docs/apps/concepts/apps-and-sign-in.md +1 -1
- package/docs/apps/concepts/connections.md +1 -1
- package/docs/apps/errors.md +1 -1
- package/docs/apps/guides/many-users.md +2 -2
- package/docs/sdk/release-notes.md +2 -0
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -11,6 +11,8 @@ Changes to `@north-light/sdk` that can change what an existing app sees. Newest
|
|
|
11
11
|
|
|
12
12
|
## 0.3.539
|
|
13
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
|
+
|
|
14
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.
|
|
15
17
|
|
|
16
18
|
Profiles name the machine environment they run on. Additive: no request or response an existing app sends or reads changes.
|
|
@@ -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`.
|
|
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` |
|
|
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`.
|
|
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
|
|
|
@@ -49,7 +49,7 @@ Then set your own session for the person. The SDK does not manage your sessions.
|
|
|
49
49
|
|
|
50
50
|
### Scopes decide what comes back
|
|
51
51
|
|
|
52
|
-
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`.
|
|
52
|
+
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.
|
|
53
53
|
|
|
54
54
|
### When the directory refuses to sign someone in
|
|
55
55
|
|
|
@@ -116,7 +116,7 @@ It needs the app registered with the `app_token_for_user` operation, and an acti
|
|
|
116
116
|
|
|
117
117
|
## Signing in a visitor
|
|
118
118
|
|
|
119
|
-
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.
|
|
119
|
+
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.
|
|
120
120
|
|
|
121
121
|
## Checked and not checked
|
|
122
122
|
|
package/docs/apps/errors.md
CHANGED
|
@@ -16,7 +16,7 @@ Codes the SDK raises itself are listed in `sdkErrorCodes`, and `CrouterError.cod
|
|
|
16
16
|
| Code | Means | What to do |
|
|
17
17
|
|---|---|---|
|
|
18
18
|
| `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. |
|
|
19
|
-
| `oauth_exchange_mismatch` |
|
|
19
|
+
| `oauth_exchange_mismatch` | `exchangeCode` got a sign-in-only answer (no connection). | Finish a sign-in-only request with `exchangeIdentity` ([Many users](/docs/guides/many-users#signing-in-a-visitor)). |
|
|
20
20
|
| `oauth_nonce_missing` | `exchangeIdentity` was called without the `nonce` from `authorizeUrl`. | Save the nonce in the visitor's session and pass it back. |
|
|
21
21
|
| `oauth_state_mismatch` | The callback's `state` was missing or differed from the saved one. | Refuse the callback. |
|
|
22
22
|
| `not_connected` | `oauth.client(userId)` or a refresh found no stored connection for that person. | Show "sign in again". |
|
|
@@ -16,7 +16,7 @@ Keep the connection and refresh token on the server, never in a visitor's browse
|
|
|
16
16
|
|
|
17
17
|
## Signing in a visitor
|
|
18
18
|
|
|
19
|
-
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`:
|
|
19
|
+
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`:
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
22
|
const {url, codeVerifier, state, nonce} = await oauth.authorizeUrl({scopes: ['openid', 'email', 'profile'], state: sessionState});
|
|
@@ -34,7 +34,7 @@ visitor.picture; // an https URL, present only when 'profile' was approved
|
|
|
34
34
|
|
|
35
35
|
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.
|
|
36
36
|
|
|
37
|
-
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`.
|
|
37
|
+
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`.
|
|
38
38
|
|
|
39
39
|
## Whose action a call records
|
|
40
40
|
|
|
@@ -9,6 +9,8 @@ Changes to `@north-light/sdk` that can change what an existing app sees. Newest
|
|
|
9
9
|
|
|
10
10
|
## 0.3.539
|
|
11
11
|
|
|
12
|
+
`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.
|
|
13
|
+
|
|
12
14
|
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.
|
|
13
15
|
|
|
14
16
|
Profiles name the machine environment they run on. Additive: no request or response an existing app sends or reads changes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.540",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
},
|
|
141
141
|
"license": "UNLICENSED",
|
|
142
142
|
"dependencies": {
|
|
143
|
-
"@north-light/identity": "0.3.
|
|
143
|
+
"@north-light/identity": "0.3.540",
|
|
144
144
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
145
145
|
"@earendil-works/pi-ai": "1.1.0",
|
|
146
146
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.540",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/cli",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.540",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@milkdown/preset-gfm": "^7.22.3",
|
|
25
25
|
"@milkdown/prose": "^7.22.3",
|
|
26
26
|
"@milkdown/utils": "^7.22.3",
|
|
27
|
-
"@north-light/identity": "0.3.
|
|
27
|
+
"@north-light/identity": "0.3.540",
|
|
28
28
|
"cron-parser": "^5.6.0",
|
|
29
29
|
"esbuild": "^0.27.7",
|
|
30
30
|
"jose": "^6.2.12",
|
|
@@ -12455,17 +12455,17 @@
|
|
|
12455
12455
|
},
|
|
12456
12456
|
"packages/crouter-api": {
|
|
12457
12457
|
"name": "@north-light/api",
|
|
12458
|
-
"version": "0.3.
|
|
12458
|
+
"version": "0.3.540",
|
|
12459
12459
|
"license": "UNLICENSED"
|
|
12460
12460
|
},
|
|
12461
12461
|
"packages/crouter-env-docker": {
|
|
12462
12462
|
"name": "@north-light/env-docker",
|
|
12463
|
-
"version": "0.3.
|
|
12463
|
+
"version": "0.3.540",
|
|
12464
12464
|
"license": "UNLICENSED"
|
|
12465
12465
|
},
|
|
12466
12466
|
"packages/crouter-identity": {
|
|
12467
12467
|
"name": "@north-light/identity",
|
|
12468
|
-
"version": "0.3.
|
|
12468
|
+
"version": "0.3.540",
|
|
12469
12469
|
"license": "UNLICENSED",
|
|
12470
12470
|
"dependencies": {
|
|
12471
12471
|
"jose": "^6.2.1"
|
|
@@ -12473,20 +12473,20 @@
|
|
|
12473
12473
|
},
|
|
12474
12474
|
"packages/crouter-plugin": {
|
|
12475
12475
|
"name": "@north-light/plugin",
|
|
12476
|
-
"version": "0.3.
|
|
12476
|
+
"version": "0.3.540",
|
|
12477
12477
|
"license": "UNLICENSED",
|
|
12478
12478
|
"dependencies": {
|
|
12479
|
-
"@north-light/api": "0.3.
|
|
12480
|
-
"@north-light/identity": "0.3.
|
|
12479
|
+
"@north-light/api": "0.3.540",
|
|
12480
|
+
"@north-light/identity": "0.3.540"
|
|
12481
12481
|
}
|
|
12482
12482
|
},
|
|
12483
12483
|
"packages/crouter-sdk": {
|
|
12484
12484
|
"name": "@north-light/sdk",
|
|
12485
|
-
"version": "0.3.
|
|
12485
|
+
"version": "0.3.540",
|
|
12486
12486
|
"license": "UNLICENSED",
|
|
12487
12487
|
"dependencies": {
|
|
12488
|
-
"@north-light/api": "0.3.
|
|
12489
|
-
"@north-light/identity": "0.3.
|
|
12488
|
+
"@north-light/api": "0.3.540",
|
|
12489
|
+
"@north-light/identity": "0.3.540",
|
|
12490
12490
|
"jose": "^6.2.1"
|
|
12491
12491
|
},
|
|
12492
12492
|
"bin": {
|