@north-light/cli 0.3.491 → 0.3.492
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/api/command-manifest/index.d.ts +1 -0
- package/dist/api/command-manifest/index.js +1 -1
- package/dist/api/command-manifest/object-kinds.d.ts +20 -0
- package/dist/api/command-manifest/object-kinds.js +1 -0
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +1 -1
- package/dist/clients/attach/viewer.js +429 -429
- package/dist/core/graph/access.d.ts +3 -0
- package/dist/core/graph/access.js +3 -3
- package/dist/core/plugin-objects-manifest.d.ts +2 -16
- package/dist/core/plugin-objects-manifest.js +1 -1
- package/docs/sdk/release-notes.md +1 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -15,6 +15,9 @@ export declare function isShipped(db: DatabaseSync, object: ObjectRow): boolean;
|
|
|
15
15
|
export declare function toolApps(db: DatabaseSync, reader: Reader): ObjectRow[];
|
|
16
16
|
/** May `reader` use any of `app`'s tool groups? v0: every run may use every installed plugin's tools. */
|
|
17
17
|
export declare function mayUseTools(_db: DatabaseSync, _reader: Reader, app: ObjectRow): boolean;
|
|
18
|
+
/** Whether `scopes` hold a provider-group scope `<provider>:<group>` of `app`: what a run needs to call that app's provider commands
|
|
19
|
+
* (`requireGroup`). The provider id is the app's client id. */
|
|
20
|
+
export declare function holdsProviderGroup(db: DatabaseSync, scopes: readonly string[], app: ObjectRow): boolean;
|
|
18
21
|
/** Whether this reader may register, publish or watch as an object owned by `owner`. */
|
|
19
22
|
export declare function mayActAs(db: DatabaseSync, reader: Reader, owner: ObjectRow): boolean;
|
|
20
23
|
/** Run confinement for a node acting on a custom object of its app (Silas, 2026-09-30):
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
1
|
+
var R=Object.defineProperty;var s=(n,t)=>R(n,"name",{value:t,configurable:!0});import{prepared as f}from"../sqlite-statements.js";import{covers as O}from"@north-light/identity";import{objectPlace as x,runPlace as N,runsSeeEachOther as g}from"../runs/confinement.js";import{missingOwnMemoryScope as E}from"./spaces/own-memory.js";import{SPACES as L,identityOf as u}from"./spaces/index.js";import{insideRepo as C}from"./spaces/repo.js";function T(n,t){return f(n,`WITH RECURSIVE chain(rowid, depth) AS (
|
|
2
2
|
SELECT owner, 1 FROM objects WHERE rowid = ? AND owner IS NOT NULL
|
|
3
3
|
UNION ALL
|
|
4
4
|
SELECT o.owner, c.depth + 1 FROM objects o JOIN chain c ON o.rowid = c.rowid WHERE o.owner IS NOT NULL
|
|
5
|
-
) SELECT o.* FROM chain c CROSS JOIN objects o WHERE o.rowid = c.rowid ORDER BY c.depth`).all(t.rowid)}s(T,"ownerChain");function
|
|
5
|
+
) SELECT o.* FROM chain c CROSS JOIN objects o WHERE o.rowid = c.rowid ORDER BY c.depth`).all(t.rowid)}s(T,"ownerChain");function J(n,t){return c(n,t).space}s(J,"spaceOf");function c(n,t){const e=T(n,t),p=e.length?e[e.length-1]:t,o=L[p.type];if(!o)throw new Error(`${t.type} ${t.id} has no space: its owner chain ends at ${p.type} ${p.id}`);const r=e.length?[...e.slice(0,-1).reverse(),t]:[];return{space:p,path:r,impl:o}}s(c,"locate");function m(n,t){return t.type!=="document"?!1:f(n,"SELECT source_path FROM documents WHERE object = ?").get(t.rowid)?.source_path!=null}s(m,"isShipped");function B(n,t){return f(n,`SELECT a.* FROM objects a WHERE a.type = 'app' AND a.deleted_at IS NULL AND EXISTS (
|
|
6
6
|
SELECT 1 FROM objects o JOIN documents d ON d.object = o.rowid
|
|
7
7
|
WHERE o.owner = a.rowid AND o.type = 'document' AND o.deleted_at IS NULL AND d.source_path IS NOT NULL)
|
|
8
|
-
ORDER BY a.name = 'crtr', a.name`).all().filter(p=>h(
|
|
8
|
+
ORDER BY a.name = 'crtr', a.name`).all().filter(p=>h(n,t,p))}s(B,"toolApps");function h(n,t,e){return e.type==="app"}s(h,"mayUseTools");const A=s(n=>n.class!=="app"||n.place!==void 0,"isRun");function I(n,t,e){const p=`${u(n,e).external_id.replace(/^app:/,"")}:`;return t.some(o=>o.startsWith(p)&&!o.slice(p.length).includes(":"))}s(I,"holdsProviderGroup");function _(n,t,e){return t.class==="person"?!0:t.class==="object"?t.owner.rowid===e.rowid:t.class==="app"?t.app.rowid===e.rowid||e.type==="profile"&&e.owner===t.app.rowid:t.app.rowid===e.rowid||e.type==="profile"&&t.profile?.rowid===e.rowid||e.type==="repo"&&C(n,t,e,"rw")}s(_,"mayActAs");function M(n,t,e){if(t.class!=="node"&&!(t.class==="app"&&t.place!==void 0))return!0;const p=t.class==="app"?t.place:N(t.node.id,n);if(p===null)return!0;const o=x(e.rowid,n);return o===null?!p.isolated:g(p,o)}s(M,"customReachable");const w=s(n=>n.type.includes("."),"isCustom");function Y(n,t,e){return d(n,c(n,t),t,e)}s(Y,"objectsTargets");function d(n,{space:t,path:e},p,o){const r=[];if(t.type==="person")r.push("user");else if(t.type==="app"&&e.length>0){const i=e[0];if(i.type==="profile")e.length>1&&r.push(`profile:${u(n,i).external_id}`);else if(i.type==="node"||w(i)){const l=u(n,t).external_id;l!==o&&r.push(l)}}return p.type==="node"&&r.push("node"),r}s(d,"targetsOf");function a(n,t,e,p,o){if(t.class==="person"||t.scopes===null)return!1;const r=t.scopes;if(r.length===0||p.space.type==="app"&&t.app.rowid===p.space.rowid)return!1;const i=u(n,t.app).external_id;return d(n,p,o,i).some(l=>{const y=`crtr:objects:${e}:${l}`;return r.some(S=>O(S,y))})}s(a,"holdsInLocated");function U(n,t,e,p){return t.class==="person"||t.scopes===null?!1:a(n,t,e,c(n,p),p)}s(U,"holdsObjectsScope");function z(n,t,e,p,o){const r=p.owner===null?null:n.prepare("SELECT * FROM objects WHERE rowid = ?").get(p.owner)??null;if(r===null)return!1;const i={class:"app",app:t,scopes:e??[]};return _(n,i,r)?e===null||U(n,i,"link",o):!1}s(z,"linkAuthorizes");function G(n,t,e){return W(n,e)(t)}s(G,"canRead");function W(n,t){let e=null,p=null;return o=>{if(o.class==="person")return!0;if(e??=c(n,t),e.space.type==="app"&&e.path.length>0){if(p??=m(n,t),p&&h(n,o,e.space))return!0;if(w(t)){if(o.app.rowid===e.space.rowid&&!M(n,o,t))return!1;if(o.app.rowid!==e.space.rowid&&o.scopes!==null&&h(n,o,e.space)&&(t.privacy==="public"||A(o)&&I(n,o.scopes,e.space)))return!0}}return a(n,o,"read",e,t)||o.class==="object"&&w(o.object)&&a(n,o,"watch",e,t)?!0:e.impl.canRead(n,o,e.space,e.path,t)}}s(W,"readCheck");function V(n,t,e){if(m(n,e))return!1;const p=c(n,e);if(a(n,t,"write",p,e))return!0;const{space:o,path:r,impl:i}=p;return i.canChange(n,t,o,r,e)}s(V,"canChange");function X(n,t,e,p){if(t.class==="person")return null;const{space:o,path:r}=c(n,e);return o.type==="app"&&t.app.rowid===o.rowid?E(n,t,o,r,e,p):null}s(X,"missingMemoryScope");function q(n,t,e,p){if(t.class==="person")return null;const o=c(n,e),{space:r}=o;return r.type!=="app"||t.app.rowid!==r.rowid?null:E(n,t,r,o.path.length===0?[e]:[...o.path],null,p)}s(q,"missingMemoryScopeUnder");export{V as canChange,G as canRead,M as customReachable,U as holdsObjectsScope,I as holdsProviderGroup,m as isShipped,z as linkAuthorizes,_ as mayActAs,h as mayUseTools,X as missingMemoryScope,q as missingMemoryScopeUnder,Y as objectsTargets,T as ownerChain,W as readCheck,J as spaceOf,B as toolApps};
|
|
@@ -1,21 +1,7 @@
|
|
|
1
1
|
import type { DeclLeaf, DeclNode } from '../api/command-manifest/schema.js';
|
|
2
|
+
import { KIND, LOCAL, RESERVED_KIND_ROOTS, MAX_KIND_EVENTS, MIN_EVENT_LEVEL, MAX_EVENT_LEVEL, eventCatalogReasons, objectBlocksShapeReasons, objectKindReadReasons } from '../api/command-manifest/object-kinds.js';
|
|
2
3
|
import type { PluginManifest } from '../types.js';
|
|
3
|
-
|
|
4
|
-
* The `object_kinds` and `scopes` blocks of a plugin manifest (`plugin.json`, `bundle.json`) and the one
|
|
5
|
-
* validator every install, update, enable, provider-bundle and reconcile path shares. Canvas-free by
|
|
6
|
-
* design: the CLI and the bundle parser import it, so it must not reach `node:sqlite` or the canvas.
|
|
7
|
-
*/
|
|
8
|
-
export declare const KIND: RegExp;
|
|
9
|
-
export declare const LOCAL: RegExp;
|
|
10
|
-
/** A kind's first segment may not be one of the built-in object types. */
|
|
11
|
-
export declare const RESERVED_KIND_ROOTS: readonly string[];
|
|
12
|
-
export declare const MAX_KIND_EVENTS = 64;
|
|
13
|
-
export declare const MIN_EVENT_LEVEL = 1;
|
|
14
|
-
export declare const MAX_EVENT_LEVEL = 10;
|
|
15
|
-
/** Reasons a catalog (`events` map) is invalid; shared with `registerCustomObject`. */
|
|
16
|
-
export declare function eventCatalogReasons(events: unknown, where: string): string[];
|
|
17
|
-
/** The JSON shape of both blocks of a raw manifest record, independent of the plugin's name and commands. */
|
|
18
|
-
export declare function objectBlocksShapeReasons(record: Record<string, unknown>): string[];
|
|
4
|
+
export { KIND, LOCAL, RESERVED_KIND_ROOTS, MAX_KIND_EVENTS, MIN_EVENT_LEVEL, MAX_EVENT_LEVEL, eventCatalogReasons, objectBlocksShapeReasons, objectKindReadReasons };
|
|
19
5
|
/**
|
|
20
6
|
* The full check. `leafPaths` holds the space-joined path of every leaf below the plugin's root command
|
|
21
7
|
* (`page read` for plugin `search`'s leaf `search page read`); `streamingLeafPaths` holds those declared `rest.streaming: true`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var l=Object.defineProperty;var r=(e,n)=>l(e,"name",{value:n,configurable:!0});import{parseScope as h}from"@north-light/identity";import{KIND as g,LOCAL as k,RESERVED_KIND_ROOTS as b,MAX_KIND_EVENTS as E,MIN_EVENT_LEVEL as j,MAX_EVENT_LEVEL as _,eventCatalogReasons as S,objectBlocksShapeReasons as a,objectKindReadReasons as f}from"../api/command-manifest/object-kinds.js";const w=/^crtr:objects:(?:read|watch|link|write):/;function L(e,n){const t=a(e);if(t.length>0)return t;const{name:c,leafPaths:p,streamingLeafPaths:s}=n;for(const[o,u]of Object.entries(e.object_kinds??{}))o.split(".")[0]!==c&&t.push(`object_kinds ${JSON.stringify(o)} must start with the plugin name "${c}."`),t.push(...f(o,u,c,p,s));const i=e.scopes??[];e.scopes!==void 0&&e.provider!==void 0&&t.push("scopes is for local plugins; a provider gets its scopes from directory consent");for(const o of i){try{h(o)}catch{t.push(`scope ${JSON.stringify(o)} is not a recognized scope`);continue}w.test(o)?o.endsWith(`:app:${c}`)&&t.push(`scope ${JSON.stringify(o)} names the plugin's own space; an app needs no scope for its own objects`):t.push(`scope ${JSON.stringify(o)} must be crtr:objects:<read|watch|link|write>:<target>`)}return t}r(L,"objectBlocksReasons");function m(e){return e.object_kinds!==void 0||e.scopes!==void 0}r(m,"declaresObjectBlocks");function y(e){return e.provider!==void 0?!1:Object.keys(e.object_kinds??{}).length>0||(e.scopes?.length??0)>0||e.transport?.kind==="http"}r(y,"needsAppToken");function P(e,n){return d(e,n,()=>!0)}r(P,"leafPathsBelowRoot");function V(e,n){return d(e,n,t=>"rest"in t&&t.rest.streaming===!0)}r(V,"streamingLeafPathsBelowRoot");function d(e,n,t){const c=new Set,p=r((s,i)=>{if(s.kind==="leaf")t(s)&&c.add([...i,s.name].join(" "));else for(const o of s.children)p(o,[...i,s.name])},"walk");for(const s of n)if(s.name===e&&s.kind==="branch")for(const i of s.children)p(i,[]);return c}r(d,"collectLeafPaths");export{g as KIND,k as LOCAL,_ as MAX_EVENT_LEVEL,E as MAX_KIND_EVENTS,j as MIN_EVENT_LEVEL,b as RESERVED_KIND_ROOTS,m as declaresObjectBlocks,S as eventCatalogReasons,P as leafPathsBelowRoot,y as needsAppToken,L as objectBlocksReasons,a as objectBlocksShapeReasons,f as objectKindReadReasons,V as streamingLeafPathsBelowRoot};
|
|
@@ -58,7 +58,7 @@ Plugins can now declare canvas object kinds and act on the canvas, and an app to
|
|
|
58
58
|
- `app:<x>`: nodes and custom objects of another app `x`. An app never needs a scope for its own objects, and a plugin may not declare its own `app:<plugin>` space.
|
|
59
59
|
- `node`: any node, including the stub of a node on another of the account's machines.
|
|
60
60
|
|
|
61
|
-
`read` lets the holder read objects of the target, `write` change them, and `link` (below) make a node watch an object the holder owns. `watch` lets a custom object that watches an object of the target read it. Holding a scope never lifts run confinement inside the owning app, and a revoked grant holds nothing. A public custom object is readable by any app that may use the owning app's tools, with no scope. The app listener now serves the canvas operations (`objects.*`, `custom-objects.*`, `docs.*`) to an app grant token under its resolved scopes; those rows answered `unknown operation` there before.
|
|
61
|
+
`read` lets the holder read objects of the target, `write` change them, and `link` (below) make a node watch an object the holder owns. `watch` lets a custom object that watches an object of the target read it. Holding a scope never lifts run confinement inside the owning app, and a revoked grant holds nothing. A public custom object is readable by any app that may use the owning app's tools, with no scope. A `friends` or `private` instance is readable, with no read scope, only by a run (a node, or a node of another machine) that holds one of the owning app's provider-group scopes `<app>:<group>`, the scopes a call to that app's provider commands needs; another app's server reads it only through a held `crtr:objects:read:app:<app>` scope. The app listener now serves the canvas operations (`objects.*`, `custom-objects.*`, `docs.*`) to an app grant token under its resolved scopes; those rows answered `unknown operation` there before.
|
|
62
62
|
|
|
63
63
|
### The `crtr_app_` credential and its socket fetch (additive)
|
|
64
64
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.492",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
"license": "UNLICENSED",
|
|
140
140
|
"dependencies": {
|
|
141
|
-
"@north-light/identity": "0.3.
|
|
141
|
+
"@north-light/identity": "0.3.492",
|
|
142
142
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
143
143
|
"@earendil-works/pi-ai": "1.1.0",
|
|
144
144
|
"@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.492",
|
|
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.492",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@earendil-works/pi-ai": "1.1.0",
|
|
19
19
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
20
20
|
"@earendil-works/pi-tui": "1.1.0",
|
|
21
|
-
"@north-light/identity": "0.3.
|
|
21
|
+
"@north-light/identity": "0.3.492",
|
|
22
22
|
"cron-parser": "^5.6.0",
|
|
23
23
|
"esbuild": "^0.27.7",
|
|
24
24
|
"jose": "^6.2.12",
|
|
@@ -12116,17 +12116,17 @@
|
|
|
12116
12116
|
},
|
|
12117
12117
|
"packages/crouter-api": {
|
|
12118
12118
|
"name": "@north-light/api",
|
|
12119
|
-
"version": "0.3.
|
|
12119
|
+
"version": "0.3.492",
|
|
12120
12120
|
"license": "UNLICENSED"
|
|
12121
12121
|
},
|
|
12122
12122
|
"packages/crouter-env-docker": {
|
|
12123
12123
|
"name": "@north-light/env-docker",
|
|
12124
|
-
"version": "0.3.
|
|
12124
|
+
"version": "0.3.492",
|
|
12125
12125
|
"license": "UNLICENSED"
|
|
12126
12126
|
},
|
|
12127
12127
|
"packages/crouter-identity": {
|
|
12128
12128
|
"name": "@north-light/identity",
|
|
12129
|
-
"version": "0.3.
|
|
12129
|
+
"version": "0.3.492",
|
|
12130
12130
|
"license": "UNLICENSED",
|
|
12131
12131
|
"dependencies": {
|
|
12132
12132
|
"jose": "^6.2.1"
|
|
@@ -12134,20 +12134,20 @@
|
|
|
12134
12134
|
},
|
|
12135
12135
|
"packages/crouter-plugin": {
|
|
12136
12136
|
"name": "@north-light/plugin",
|
|
12137
|
-
"version": "0.3.
|
|
12137
|
+
"version": "0.3.492",
|
|
12138
12138
|
"license": "UNLICENSED",
|
|
12139
12139
|
"dependencies": {
|
|
12140
|
-
"@north-light/api": "0.3.
|
|
12141
|
-
"@north-light/identity": "0.3.
|
|
12140
|
+
"@north-light/api": "0.3.492",
|
|
12141
|
+
"@north-light/identity": "0.3.492"
|
|
12142
12142
|
}
|
|
12143
12143
|
},
|
|
12144
12144
|
"packages/crouter-sdk": {
|
|
12145
12145
|
"name": "@north-light/sdk",
|
|
12146
|
-
"version": "0.3.
|
|
12146
|
+
"version": "0.3.492",
|
|
12147
12147
|
"license": "UNLICENSED",
|
|
12148
12148
|
"dependencies": {
|
|
12149
|
-
"@north-light/api": "0.3.
|
|
12150
|
-
"@north-light/identity": "0.3.
|
|
12149
|
+
"@north-light/api": "0.3.492",
|
|
12150
|
+
"@north-light/identity": "0.3.492",
|
|
12151
12151
|
"jose": "^6.2.1"
|
|
12152
12152
|
},
|
|
12153
12153
|
"bin": {
|