@stratusagent/permissions 0.10.0 → 0.11.0

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.
@@ -1,26 +1,51 @@
1
1
  import { type CommandScope } from './commands.ts';
2
+ import { type OriginScope } from './origins.ts';
2
3
  /**
3
4
  * What one agent may run unattended, beyond the built-in safe list.
4
5
  *
5
6
  * Per agent, because "always allow" is an answer about one identity's work
6
7
  * — a scope somebody granted Ava in a repository of theirs is not a scope
7
- * Juno inherits.
8
+ * Juno inherits, and neither is a site.
8
9
  */
9
10
  export interface CommandWhitelistStore {
10
11
  scopesFor(agentId: string): Promise<CommandScope[]>;
11
12
  remember(agentId: string, scope: CommandScope): Promise<void>;
12
13
  }
14
+ /**
15
+ * Which origins one agent may act on unattended — `commandFor`'s half of
16
+ * the same file, for `originFor`.
17
+ *
18
+ * A separate interface rather than two more methods on the one above,
19
+ * because they are separate answers: a host that judges commands need not
20
+ * judge browser actions, and `createFileCommandWhitelist` returns one
21
+ * object satisfying both because there is one file and an operator should
22
+ * have one place to look.
23
+ */
24
+ export interface OriginWhitelistStore {
25
+ originsFor(agentId: string): Promise<OriginScope[]>;
26
+ rememberOrigin(agentId: string, scope: OriginScope): Promise<void>;
27
+ }
13
28
  /** `<id>.whitelist.json`, beside the agent's soul in ~/.stratus/agents. */
14
29
  export declare const whitelistPathFor: (directory: string, agentId: string) => string;
15
30
  /**
16
- * The persistent half of the three-tier resolution, on disk.
31
+ * Thrown by `remember` for an agent whose whitelist exists but could not be
32
+ * read. The policy catches it by type: the answer still holds for the
33
+ * session, and the log says why it was not saved.
34
+ */
35
+ export declare class WhitelistUnreadableError extends Error {
36
+ constructor(file: string, reason: string);
37
+ }
38
+ /**
39
+ * The persistent tier of the scope resolution, on disk — both kinds of
40
+ * grant, in one file per agent.
17
41
  *
18
42
  * Written `0600` with an explicit `chmod`, like every other file in
19
- * `~/.stratus` that decides something: this one lists commands that run
20
- * with nobody watching, so another account on the machine appending a line
21
- * to it is the whole permission engine defeated. `writeFile`'s mode only
22
- * applies when it creates the file, so an upgrade over a looser install
23
- * would otherwise keep the old permissions.
43
+ * `~/.stratus` that decides something: this one lists commands that run,
44
+ * and sites that get clicked on, with nobody watching — so another account
45
+ * on the machine appending a line to it is the whole permission engine
46
+ * defeated. `writeFile`'s mode only applies when it creates the file, so
47
+ * an upgrade over a looser install would otherwise keep the old
48
+ * permissions.
24
49
  *
25
50
  * Scopes are cached in memory once read. A daemon therefore does not notice
26
51
  * a hand-edited file until it restarts — which is the right way round for a
@@ -29,5 +54,11 @@ export declare const whitelistPathFor: (directory: string, agentId: string) => s
29
54
  */
30
55
  export declare const createFileCommandWhitelist: (options: {
31
56
  directory: string;
32
- }) => CommandWhitelistStore;
57
+ /**
58
+ * Where to say that a whitelist exists but could not be read. Once per
59
+ * agent per process; a host that omits it gets the same behavior with
60
+ * no line about it.
61
+ */
62
+ warn?: (line: string) => void;
63
+ }) => CommandWhitelistStore & OriginWhitelistStore;
33
64
  //# sourceMappingURL=whitelist.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"whitelist.d.ts","sourceRoot":"","sources":["../src/whitelist.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAEhF;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AASD,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,GAAI,WAAW,MAAM,EAAE,SAAS,MAAM,KAAG,MACnB,CAAC;AAEpD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,KAAG,qBA+C3E,CAAC"}
1
+ {"version":3,"file":"whitelist.d.ts","sourceRoot":"","sources":["../src/whitelist.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEnF;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACpD,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAgCD,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,GAAI,WAAW,MAAM,EAAE,SAAS,MAAM,KAAG,MACnB,CAAC;AAEpD;;;;GAIG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAIzC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B,KAAG,qBAAqB,GAAG,oBAmJ3B,CAAC"}
package/dist/whitelist.js CHANGED
@@ -1,18 +1,32 @@
1
1
  import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { parseCommandScope, sameScope } from "./commands.js";
4
+ import { parseOriginScope, sameOriginScope } from "./origins.js";
4
5
  const WHITELIST_VERSION = 1;
5
6
  /** `<id>.whitelist.json`, beside the agent's soul in ~/.stratus/agents. */
6
7
  export const whitelistPathFor = (directory, agentId) => path.join(directory, `${agentId}.whitelist.json`);
7
8
  /**
8
- * The persistent half of the three-tier resolution, on disk.
9
+ * Thrown by `remember` for an agent whose whitelist exists but could not be
10
+ * read. The policy catches it by type: the answer still holds for the
11
+ * session, and the log says why it was not saved.
12
+ */
13
+ export class WhitelistUnreadableError extends Error {
14
+ constructor(file, reason) {
15
+ super(`${file} could not be read (${reason}), so nothing is written over it. Fix the file and restart the daemon.`);
16
+ this.name = 'WhitelistUnreadableError';
17
+ }
18
+ }
19
+ /**
20
+ * The persistent tier of the scope resolution, on disk — both kinds of
21
+ * grant, in one file per agent.
9
22
  *
10
23
  * Written `0600` with an explicit `chmod`, like every other file in
11
- * `~/.stratus` that decides something: this one lists commands that run
12
- * with nobody watching, so another account on the machine appending a line
13
- * to it is the whole permission engine defeated. `writeFile`'s mode only
14
- * applies when it creates the file, so an upgrade over a looser install
15
- * would otherwise keep the old permissions.
24
+ * `~/.stratus` that decides something: this one lists commands that run,
25
+ * and sites that get clicked on, with nobody watching — so another account
26
+ * on the machine appending a line to it is the whole permission engine
27
+ * defeated. `writeFile`'s mode only applies when it creates the file, so
28
+ * an upgrade over a looser install would otherwise keep the old
29
+ * permissions.
16
30
  *
17
31
  * Scopes are cached in memory once read. A daemon therefore does not notice
18
32
  * a hand-edited file until it restarts — which is the right way round for a
@@ -20,49 +34,142 @@ export const whitelistPathFor = (directory, agentId) => path.join(directory, `${
20
34
  * store makes.
21
35
  */
22
36
  export const createFileCommandWhitelist = (options) => {
37
+ /**
38
+ * One read per agent per process, shared by everyone who asks — as a
39
+ * promise, so two sessions asking for the same agent at once share the
40
+ * read in flight rather than each missing an empty cache, each failing,
41
+ * and each warning.
42
+ *
43
+ * Both grant lists come out of one read, because they come out of one
44
+ * file: reading it twice would give a shell call and a browser call
45
+ * different views of a file somebody edited between them.
46
+ */
23
47
  const cache = new Map();
24
- const read = async (agentId) => {
48
+ /** Files that exist and could not be read, by agent — never written over. */
49
+ const unreadable = new Map();
50
+ const read = (agentId) => {
25
51
  const cached = cache.get(agentId);
26
52
  if (cached) {
27
53
  return cached;
28
54
  }
55
+ const reading = readFresh(agentId);
56
+ cache.set(agentId, reading);
57
+ return reading;
58
+ };
59
+ const readFresh = async (agentId) => {
29
60
  let scopes = [];
61
+ let origins = [];
62
+ // The agent id is a validated invariant by the time it reaches any
63
+ // path join (see 03) — it is a single path segment or it was refused
64
+ // at the parse boundary, so this does not re-check it.
65
+ const file = whitelistPathFor(options.directory, agentId);
30
66
  try {
31
- // The agent id is a validated invariant by the time it reaches any
32
- // path join (see 03) — it is a single path segment or it was refused
33
- // at the parse boundary, so this does not re-check it.
34
- const raw = await readFile(whitelistPathFor(options.directory, agentId), 'utf8');
67
+ const raw = await readFile(file, 'utf8');
35
68
  const parsed = JSON.parse(raw);
36
69
  scopes = Array.isArray(parsed.scopes)
37
70
  ? parsed.scopes.map(parseCommandScope).filter((scope) => scope !== undefined)
38
71
  : [];
72
+ origins = Array.isArray(parsed.origins)
73
+ ? parsed.origins.map(parseOriginScope).filter((scope) => scope !== undefined)
74
+ : [];
39
75
  }
40
- catch {
41
- // No whitelist, or one that will not parse. Both mean the same thing
42
- // to a caller — no stored scopes — and neither is worth failing a
76
+ catch (error) {
77
+ // No whitelist means no stored scopes, and is not worth failing a
43
78
  // turn over: the fallback is asking a human, which is where an agent
44
- // with no whitelist starts anyway.
79
+ // with no whitelist starts anyway. A whitelist that exists and will
80
+ // not read is the same to this call and not the same to the file:
81
+ // one hand-edited comma made a grant list read as empty with no line
82
+ // about it, and the next "always" wrote a single new scope over
83
+ // every grant it held. So it is said once, and `remember` refuses.
45
84
  scopes = [];
85
+ origins = [];
86
+ if (error.code !== 'ENOENT') {
87
+ const reason = error instanceof Error ? error.message : String(error);
88
+ unreadable.set(agentId, reason);
89
+ options.warn?.(`${file} could not be read (${reason}); its scopes are ignored and "always" answers for ${agentId} `
90
+ + 'are not saved over it until it is fixed and the daemon restarted.');
91
+ }
92
+ }
93
+ return { scopes, origins };
94
+ };
95
+ /**
96
+ * Both lists, always — a write of one carries the other through
97
+ * untouched. Persisting only the half that changed would drop the other
98
+ * half of a file this daemon had read and understood, which is the same
99
+ * data loss the unreadable-file guard above exists to prevent.
100
+ */
101
+ const save = async (agentId, grants) => {
102
+ cache.set(agentId, Promise.resolve(grants));
103
+ await mkdir(options.directory, { recursive: true });
104
+ const file = {
105
+ version: WHITELIST_VERSION,
106
+ scopes: grants.scopes,
107
+ ...(grants.origins.length > 0 ? { origins: grants.origins } : {}),
108
+ };
109
+ const target = whitelistPathFor(options.directory, agentId);
110
+ await writeFile(target, `${JSON.stringify(file, null, 2)}\n`, { mode: 0o600 });
111
+ await chmod(target, 0o600);
112
+ };
113
+ /**
114
+ * Read-modify-write runs one at a time per agent.
115
+ *
116
+ * Every grant is "read what is there, add one, write it all back", and
117
+ * the read yields — so two answers settling together both saw the file
118
+ * before either changed it, and the second write drops the first grant.
119
+ * It bites hardest across the two kinds now that one file holds both: a
120
+ * shell "always" and a browser "always" resolved in the same moment, and
121
+ * whichever landed second silently deleted the other agent's site grant.
122
+ * Serializing also means only one `writeFile` is ever open on the file,
123
+ * so two overlapping writes cannot leave a mixed one behind.
124
+ *
125
+ * A queue, like the browser pool's admission: the work is short, and the
126
+ * alternative (reserving and unwinding) is the same serialization with
127
+ * more ways to leak a reservation. The tail swallows failures, so one
128
+ * grant that throws does not reject every grant queued behind it — the
129
+ * caller still sees its own rejection, because that is `queued`.
130
+ */
131
+ const writes = new Map();
132
+ const serialized = (agentId, work) => {
133
+ const queued = (writes.get(agentId) ?? Promise.resolve()).then(work, work);
134
+ writes.set(agentId, queued.then(() => undefined, () => undefined));
135
+ return queued;
136
+ };
137
+ /** Nothing is written over a grant list nobody could read. */
138
+ const refuseIfUnreadable = (agentId) => {
139
+ const reason = unreadable.get(agentId);
140
+ if (reason !== undefined) {
141
+ throw new WhitelistUnreadableError(whitelistPathFor(options.directory, agentId), reason);
46
142
  }
47
- cache.set(agentId, scopes);
48
- return scopes;
49
143
  };
50
144
  return {
51
145
  async scopesFor(agentId) {
52
- return [...(await read(agentId))];
146
+ return [...(await read(agentId)).scopes];
53
147
  },
54
148
  async remember(agentId, scope) {
55
- const scopes = await read(agentId);
56
- if (scopes.some((existing) => sameScope(existing, scope))) {
57
- return;
58
- }
59
- const updated = [...scopes, scope];
60
- cache.set(agentId, updated);
61
- await mkdir(options.directory, { recursive: true });
62
- const file = { version: WHITELIST_VERSION, scopes: updated };
63
- const target = whitelistPathFor(options.directory, agentId);
64
- await writeFile(target, `${JSON.stringify(file, null, 2)}\n`, { mode: 0o600 });
65
- await chmod(target, 0o600);
149
+ // The read is inside the queue, not before it: a grant that started
150
+ // from a snapshot taken before the one ahead of it saved would write
151
+ // that one back out of existence, which is the whole race.
152
+ return serialized(agentId, async () => {
153
+ const grants = await read(agentId);
154
+ refuseIfUnreadable(agentId);
155
+ if (grants.scopes.some((existing) => sameScope(existing, scope))) {
156
+ return;
157
+ }
158
+ await save(agentId, { ...grants, scopes: [...grants.scopes, scope] });
159
+ });
160
+ },
161
+ async originsFor(agentId) {
162
+ return [...(await read(agentId)).origins];
163
+ },
164
+ async rememberOrigin(agentId, scope) {
165
+ return serialized(agentId, async () => {
166
+ const grants = await read(agentId);
167
+ refuseIfUnreadable(agentId);
168
+ if (grants.origins.some((existing) => sameOriginScope(existing, scope))) {
169
+ return;
170
+ }
171
+ await save(agentId, { ...grants, origins: [...grants.origins, scope] });
172
+ });
66
173
  },
67
174
  };
68
175
  };
@@ -1 +1 @@
1
- {"version":3,"file":"whitelist.js","sourceRoot":"","sources":["../src/whitelist.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"whitelist.js","sourceRoot":"","sources":["../src/whitelist.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratusagent/permissions",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -17,7 +17,7 @@
17
17
  "node": ">=22.13 <23 || >=23.4"
18
18
  },
19
19
  "dependencies": {
20
- "@stratusagent/core": "0.10.0"
20
+ "@stratusagent/core": "0.11.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^24.6.0",