@sema-agent/core 6.0.0 → 7.0.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.
- package/CHANGELOG.md +12 -0
- package/dist/core/governance-codes.d.ts +11 -2
- package/dist/core/governance-codes.js +1 -0
- package/dist/core/permission-rule-consent.d.ts +42 -2
- package/dist/core/permission-rule-consent.js +93 -11
- package/dist/core/permission-rule-model.d.ts +51 -9
- package/dist/core/permission-rule-model.js +4 -2
- package/dist/core/permission-rule-session.d.ts +124 -0
- package/dist/core/permission-rule-session.js +121 -0
- package/dist/core/permission-rule-store.d.ts +65 -2
- package/dist/core/permission-rule-store.js +60 -6
- package/dist/core/permission-rule-sync.d.ts +9 -0
- package/dist/core/permission-rule-sync.js +37 -8
- package/dist/core/runner/prepare-task.js +35 -2
- package/dist/core/store-contracts/permission-rule-sync-contract.js +15 -1
- package/dist/core/trace.d.ts +7 -2
- package/dist/core/types.d.ts +11 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/stores/file/permission-rule-store.d.ts +11 -0
- package/dist/stores/file/permission-rule-store.js +22 -9
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +15 -1
|
@@ -111,6 +111,17 @@ declare class FilePermissionRuleStore implements WritablePermissionRuleStore {
|
|
|
111
111
|
/** Read and validate. Any refusal answers with an empty set AND says so — never a silent empty store. */
|
|
112
112
|
private read;
|
|
113
113
|
private disclose;
|
|
114
|
+
/**
|
|
115
|
+
* design/382 §4.3 — the AT-REST half of the durable two-member scope face: rows carrying a session
|
|
116
|
+
* scope, read out of persisted bytes (a hand edit or a foreign writer — the engine's own write arms
|
|
117
|
+
* refuse them loudly), are DROPPED from every read face and DISCLOSED. Never quarantined (the
|
|
118
|
+
* quarantine area is itself durable), never silently ridden: a session authorization must not gain
|
|
119
|
+
* an afterlife by being planted where the store cannot legally hold it. The write base
|
|
120
|
+
* (`current()`) is deliberately NOT screened — foreign bytes are left in place for a person to look
|
|
121
|
+
* at, exactly like every other damaged-row posture here; they simply never reach a live view, the
|
|
122
|
+
* sync wire (`readRaw`) or adjudication.
|
|
123
|
+
*/
|
|
124
|
+
private screenDurableRows;
|
|
114
125
|
private write;
|
|
115
126
|
list(): Promise<StoredAllowRules>;
|
|
116
127
|
/** The quarantine area (design/182 §5.2/§8.3): introspection only — never part of `list()`. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { closeSync, constants as FS, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
|
-
import { PERMISSION_RULE_WRITER, applySyncJoin, applyTombstones, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, foldDelta, } from "../../core/permission-rule-store.js";
|
|
4
|
+
import { PERMISSION_RULE_WRITER, applySyncJoin, applyTombstones, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, foldDelta, } from "../../core/permission-rule-store.js";
|
|
5
5
|
import { canonicalize } from "../../core/canonical-json.js";
|
|
6
6
|
import { BootLock } from "./fs-atomic.js";
|
|
7
7
|
import { assertAdoptionBootGate } from "./adoption/marker.js";
|
|
@@ -158,6 +158,17 @@ class FilePermissionRuleStore {
|
|
|
158
158
|
catch {
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
+
screenDurableRows(file) {
|
|
162
|
+
const isSession = (scope) => scope?.kind === "session";
|
|
163
|
+
const rules = file.rules.filter((r) => !isSession(r?.scope));
|
|
164
|
+
const tombstones = file.tombstones.filter((t) => !isSession(t?.scope));
|
|
165
|
+
const quarantined = (file.quarantined ?? []).filter((q) => !isSession(q?.scope));
|
|
166
|
+
const dropped = file.rules.length - rules.length + (file.tombstones.length - tombstones.length) + ((file.quarantined ?? []).length - quarantined.length);
|
|
167
|
+
if (dropped > 0) {
|
|
168
|
+
this.disclose(`${this.file} carries ${dropped} session-scope row(s) — a session authorization cannot live in the durable store (design/382 §4.3); those rows are ignored on every read face and never ride sync`);
|
|
169
|
+
}
|
|
170
|
+
return { rules, tombstones, quarantined };
|
|
171
|
+
}
|
|
161
172
|
write(next) {
|
|
162
173
|
assertSafeDir(this.dir);
|
|
163
174
|
atomicPublish(this.dir, this.file, JSON.stringify({ ...next, checksum: checksumOf(next) }, null, 2));
|
|
@@ -166,16 +177,17 @@ class FilePermissionRuleStore {
|
|
|
166
177
|
const r = this.read();
|
|
167
178
|
if (!("file" in r))
|
|
168
179
|
return { ...EMPTY_READ };
|
|
180
|
+
const screened = this.screenDurableRows(r.file);
|
|
169
181
|
return {
|
|
170
|
-
rules: applyTombstones(
|
|
171
|
-
tombstones:
|
|
182
|
+
rules: applyTombstones(screened.rules, screened.tombstones),
|
|
183
|
+
tombstones: screened.tombstones,
|
|
172
184
|
rev: r.file.rev,
|
|
173
185
|
checksum: r.file.checksum,
|
|
174
186
|
};
|
|
175
187
|
}
|
|
176
188
|
async quarantined() {
|
|
177
189
|
const r = this.read();
|
|
178
|
-
return "file" in r ? (r.file.quarantined
|
|
190
|
+
return "file" in r ? this.screenDurableRows(r.file).quarantined : [];
|
|
179
191
|
}
|
|
180
192
|
async readOrgState() {
|
|
181
193
|
const r = this.read();
|
|
@@ -245,14 +257,15 @@ class FilePermissionRuleStore {
|
|
|
245
257
|
}),
|
|
246
258
|
readRaw: async () => this.serialize(() => {
|
|
247
259
|
const cur = this.current();
|
|
260
|
+
const screened = this.screenDurableRows(cur);
|
|
248
261
|
return {
|
|
249
262
|
actor: cur.actor,
|
|
250
263
|
counter: cur.counter,
|
|
251
264
|
rev: cur.rev,
|
|
252
|
-
rules: structuredClone(
|
|
253
|
-
tombstones: structuredClone(
|
|
265
|
+
rules: structuredClone(screened.rules),
|
|
266
|
+
tombstones: structuredClone(screened.tombstones),
|
|
254
267
|
...(cur.sync?.observedVector !== undefined ? { observedVector: structuredClone(cur.sync.observedVector) } : {}),
|
|
255
|
-
quarantined: structuredClone(
|
|
268
|
+
quarantined: structuredClone(screened.quarantined),
|
|
256
269
|
};
|
|
257
270
|
}),
|
|
258
271
|
apply: async (delta, opts) => this.serialize(() => {
|
|
@@ -287,8 +300,8 @@ class FilePermissionRuleStore {
|
|
|
287
300
|
return { rev: cur.rev + 1, sync: report };
|
|
288
301
|
}
|
|
289
302
|
const next = delta.kind === "redemption-add"
|
|
290
|
-
? (assertRedemptionNotQuarantined(cur.quarantined ?? [], delta), { ...cur, rev: cur.rev + 1, rules: foldDelta(cur.rules, delta) })
|
|
291
|
-
: (assertDeleteDeltaCarriesNoAdd(delta), { ...cur, rev: cur.rev + 1, tombstones: [...cur.tombstones, delta.tombstone] });
|
|
303
|
+
? (assertWriteDeltaScopeDurable(delta), assertRedemptionNotQuarantined(cur.quarantined ?? [], delta), { ...cur, rev: cur.rev + 1, rules: foldDelta(cur.rules, delta) })
|
|
304
|
+
: (assertWriteDeltaScopeDurable(delta), assertDeleteDeltaCarriesNoAdd(delta), { ...cur, rev: cur.rev + 1, tombstones: [...cur.tombstones, delta.tombstone] });
|
|
292
305
|
if (!this.writeAndVerify(next)) {
|
|
293
306
|
throw new Error("the permission-rule store did not survive its own write; the change was not committed");
|
|
294
307
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "design/87 L3 — frozen public export surface of src/index.ts (name -> kind). DO NOT edit by hand to silence a red test. A removed/changed entry = a SemVer-BREAKING change; bump MAJOR and update this fixture in the SAME commit (design/87 §4.2 / §5.2). Regenerate via REGEN in test/export-surface.test.ts.",
|
|
3
3
|
"_tierComment": "#435 v1 — machine-readable layering of the public surface: stable = demonstrated by README.md / src/examples; internal = an `Internal`-marked name or a runner/engine deep-subtree declaration (the model seam src/engine/llm is excluded — it is the BYOM contract, not an engine internal); advanced = a supported export the front door does not walk you through. THIS IS AN INITIAL HEURISTIC, derived mechanically and expected to be refined ticket by ticket: no human reviewed these 1700+ entries one by one, and nothing here claims otherwise. Known bias: a short or English-word export name (ok, err, Result, Usage) can match ordinary prose in README.md and land `stable` on a coincidence. Every export MUST carry a tier — a new export with no row fails the gate in export-surface.test.ts.",
|
|
4
|
-
"count":
|
|
4
|
+
"count": 1841,
|
|
5
5
|
"exports": {
|
|
6
6
|
"A2ATaskState": "type",
|
|
7
7
|
"A2ATaskStateReversal": "type",
|
|
@@ -439,6 +439,7 @@
|
|
|
439
439
|
"InMemoryRuleApprovalRecordStore": "class",
|
|
440
440
|
"InMemorySessionPolicyStore": "class",
|
|
441
441
|
"InMemorySessionRepo": "class",
|
|
442
|
+
"InMemorySessionRuleOverlay": "class",
|
|
442
443
|
"InMemorySessionStorage": "class",
|
|
443
444
|
"InMemoryStrategyStore": "class",
|
|
444
445
|
"InMemoryToolResultStore": "class",
|
|
@@ -1002,6 +1003,9 @@
|
|
|
1002
1003
|
"SessionPolicyError": "class",
|
|
1003
1004
|
"SessionPolicyStore": "interface",
|
|
1004
1005
|
"SessionRepo": "interface",
|
|
1006
|
+
"SessionRuleOverlay": "interface",
|
|
1007
|
+
"SessionRuleOverlayAdd": "interface",
|
|
1008
|
+
"SessionRuleOverlayApplyResult": "type",
|
|
1005
1009
|
"SessionRulesRecord": "interface",
|
|
1006
1010
|
"SessionStorage": "interface",
|
|
1007
1011
|
"SessionStore": "interface",
|
|
@@ -1273,6 +1277,7 @@
|
|
|
1273
1277
|
"assertWorkflowDeterminism": "function",
|
|
1274
1278
|
"assertWorkflowPrimitivesWiring": "function",
|
|
1275
1279
|
"assertWorkflowSandboxConformance": "function",
|
|
1280
|
+
"assertWriteDeltaScopeDurable": "function",
|
|
1276
1281
|
"atomicWriteFile": "function",
|
|
1277
1282
|
"attachToolContract": "function",
|
|
1278
1283
|
"autoModeArmingRecipeOf": "function",
|
|
@@ -1537,7 +1542,9 @@
|
|
|
1537
1542
|
"isTerminalTaskNotification": "function",
|
|
1538
1543
|
"isTerminalWorkflowStatus": "function",
|
|
1539
1544
|
"isThinkingLevel": "function",
|
|
1545
|
+
"isValidConsentScope": "function",
|
|
1540
1546
|
"isValidCronExpr": "function",
|
|
1547
|
+
"isValidDurableScope": "function",
|
|
1541
1548
|
"isValidReminderMark": "function",
|
|
1542
1549
|
"isWslBashLauncher": "function",
|
|
1543
1550
|
"isolationPermitsAutoAccept": "function",
|
|
@@ -2275,6 +2282,7 @@
|
|
|
2275
2282
|
"InMemoryRuleApprovalRecordStore": "advanced",
|
|
2276
2283
|
"InMemorySessionPolicyStore": "advanced",
|
|
2277
2284
|
"InMemorySessionRepo": "internal",
|
|
2285
|
+
"InMemorySessionRuleOverlay": "advanced",
|
|
2278
2286
|
"InMemorySessionStorage": "internal",
|
|
2279
2287
|
"InMemoryStrategyStore": "advanced",
|
|
2280
2288
|
"InMemoryToolResultStore": "stable",
|
|
@@ -2838,6 +2846,9 @@
|
|
|
2838
2846
|
"SessionPolicyError": "advanced",
|
|
2839
2847
|
"SessionPolicyStore": "advanced",
|
|
2840
2848
|
"SessionRepo": "stable",
|
|
2849
|
+
"SessionRuleOverlay": "advanced",
|
|
2850
|
+
"SessionRuleOverlayAdd": "advanced",
|
|
2851
|
+
"SessionRuleOverlayApplyResult": "advanced",
|
|
2841
2852
|
"SessionRulesRecord": "advanced",
|
|
2842
2853
|
"SessionStorage": "internal",
|
|
2843
2854
|
"SessionStore": "advanced",
|
|
@@ -3109,6 +3120,7 @@
|
|
|
3109
3120
|
"assertWorkflowDeterminism": "advanced",
|
|
3110
3121
|
"assertWorkflowPrimitivesWiring": "advanced",
|
|
3111
3122
|
"assertWorkflowSandboxConformance": "advanced",
|
|
3123
|
+
"assertWriteDeltaScopeDurable": "advanced",
|
|
3112
3124
|
"atomicWriteFile": "advanced",
|
|
3113
3125
|
"attachToolContract": "advanced",
|
|
3114
3126
|
"autoModeArmingRecipeOf": "advanced",
|
|
@@ -3373,7 +3385,9 @@
|
|
|
3373
3385
|
"isTerminalTaskNotification": "advanced",
|
|
3374
3386
|
"isTerminalWorkflowStatus": "advanced",
|
|
3375
3387
|
"isThinkingLevel": "advanced",
|
|
3388
|
+
"isValidConsentScope": "advanced",
|
|
3376
3389
|
"isValidCronExpr": "advanced",
|
|
3390
|
+
"isValidDurableScope": "advanced",
|
|
3377
3391
|
"isValidReminderMark": "advanced",
|
|
3378
3392
|
"isWslBashLauncher": "internal",
|
|
3379
3393
|
"isolationPermitsAutoAccept": "advanced",
|