@north-light/api 0.3.440 → 0.3.441
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.
|
@@ -39,6 +39,8 @@ export declare function isolatedNodeHome(nodeId: string, grantee: string): strin
|
|
|
39
39
|
/** The HOME a node's processes get: its own home in an isolated run, else the app's. */
|
|
40
40
|
export declare function nodeHome(nodeId: string, grantee: string, isolated: boolean): string;
|
|
41
41
|
export declare function nodeRunDir(nodeId: string): string;
|
|
42
|
+
/** The run's scope allow-list as a JSON array, beside `broker-launch.json`. */
|
|
43
|
+
export declare function scopesFilePath(nodeId: string): string;
|
|
42
44
|
export declare function contextDir(nodeId: string, grantee?: string): string;
|
|
43
45
|
/** Replace the literal env-var tokens `$CRTR_CONTEXT_DIR` / `$CRTR_NODE_ID` in
|
|
44
46
|
* agent-facing doc text with the node's real values, so a doc surfaced INTO a
|
|
@@ -96,6 +96,10 @@ export function nodeRunDir(nodeId) {
|
|
|
96
96
|
assertSafeNodeId(nodeId);
|
|
97
97
|
return process.platform === 'linux' ? join(socketDir(), 'nodes', nodeId) : join(nodeRecordDir(nodeId), 'run');
|
|
98
98
|
}
|
|
99
|
+
/** The run's scope allow-list as a JSON array, beside `broker-launch.json`. */
|
|
100
|
+
export function scopesFilePath(nodeId) {
|
|
101
|
+
return join(nodeRunDir(nodeId), 'scopes.json');
|
|
102
|
+
}
|
|
99
103
|
export function contextDir(nodeId, grantee) {
|
|
100
104
|
return join(nodeAgentDir(nodeId, grantee), 'context');
|
|
101
105
|
}
|
package/dist/shared/env.d.ts
CHANGED
|
@@ -18,10 +18,17 @@ export declare function envGrantee(): string | undefined;
|
|
|
18
18
|
* that variable is not this signal. */
|
|
19
19
|
export declare const INBOX_BETWEEN_TURNS_ENV = "CRTR_INBOX_BETWEEN_TURNS";
|
|
20
20
|
export declare function envInboxBetweenTurns(): boolean;
|
|
21
|
+
/** Path of the JSON file holding the run's scope allow-list (set by `nodeEnv`). */
|
|
22
|
+
export declare const SCOPES_FILE_ENV = "CRTR_SCOPES_FILE";
|
|
21
23
|
/** The current run's scope allow-list; null means the row inherits everything. */
|
|
22
24
|
export declare function envScopes(): readonly string[] | null;
|
|
23
25
|
/** Whether a launched scope list covers a capability. Null means not narrowed. */
|
|
24
26
|
export declare function scopeAllowed(scopes: readonly string[] | null | undefined, scope: string): boolean;
|
|
27
|
+
/** Whether any held scope covers `scope`. A held scope equal to the request always covers it, so the
|
|
28
|
+
* common case of a run narrowed to a subset of its grant is a string scan instead of `covers` on every
|
|
29
|
+
* pair (a 10,000-scope grant checked against 10,000 scopes is otherwise ~15 s). A request `covers`
|
|
30
|
+
* would reject as unparseable still throws. */
|
|
31
|
+
export declare function coveredByAny(held: readonly string[], scope: string): boolean;
|
|
25
32
|
export declare function envExecutionId(): string | undefined;
|
|
26
33
|
/** The current node's target profile id (`CRTR_PROFILE_ID`), or undefined. */
|
|
27
34
|
export declare function envProfileId(): string | undefined;
|
package/dist/shared/env.js
CHANGED
|
@@ -75,8 +75,18 @@ export const INBOX_BETWEEN_TURNS_ENV = 'CRTR_INBOX_BETWEEN_TURNS';
|
|
|
75
75
|
export function envInboxBetweenTurns() {
|
|
76
76
|
return process.env[INBOX_BETWEEN_TURNS_ENV] === '1';
|
|
77
77
|
}
|
|
78
|
+
/** Path of the JSON file holding the run's scope allow-list (set by `nodeEnv`). */
|
|
79
|
+
export const SCOPES_FILE_ENV = 'CRTR_SCOPES_FILE';
|
|
78
80
|
/** The current run's scope allow-list; null means the row inherits everything. */
|
|
79
81
|
export function envScopes() {
|
|
82
|
+
const file = process.env[SCOPES_FILE_ENV];
|
|
83
|
+
if (file !== undefined && file !== '') {
|
|
84
|
+
// A listed file that cannot be read must not widen the run: fail closed.
|
|
85
|
+
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
86
|
+
if (!Array.isArray(parsed) || parsed.some((scope) => typeof scope !== 'string'))
|
|
87
|
+
throw new Error(`invalid scopes file ${file}`);
|
|
88
|
+
return parsed;
|
|
89
|
+
}
|
|
80
90
|
const raw = process.env['CRTR_SCOPES'];
|
|
81
91
|
return raw === undefined ? null : raw === '' ? [] : raw.split(',');
|
|
82
92
|
}
|
|
@@ -84,7 +94,18 @@ export function envScopes() {
|
|
|
84
94
|
export function scopeAllowed(scopes, scope) {
|
|
85
95
|
if (scopes === null || scopes === undefined)
|
|
86
96
|
return true;
|
|
87
|
-
return scopes
|
|
97
|
+
return coveredByAny(scopes, scope);
|
|
98
|
+
}
|
|
99
|
+
/** Whether any held scope covers `scope`. A held scope equal to the request always covers it, so the
|
|
100
|
+
* common case of a run narrowed to a subset of its grant is a string scan instead of `covers` on every
|
|
101
|
+
* pair (a 10,000-scope grant checked against 10,000 scopes is otherwise ~15 s). A request `covers`
|
|
102
|
+
* would reject as unparseable still throws. */
|
|
103
|
+
export function coveredByAny(held, scope) {
|
|
104
|
+
if (held.includes(scope)) {
|
|
105
|
+
covers(scope, scope);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
return held.some((h) => covers(h, scope));
|
|
88
109
|
}
|
|
89
110
|
export function envExecutionId() {
|
|
90
111
|
return process.env['CRTR_EXECUTION_ID'];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/api",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.441",
|
|
4
4
|
"description": "Typed crtrd /v1 API contract — DTOs, route builders, the error contract, the CrtrClient, and the command-plugin manifest format. Zero runtime dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/api/index.js",
|