@sema-agent/core 7.4.0 → 7.5.1
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 +69 -0
- package/dist/agents/cascade.d.ts +2 -1
- package/dist/agents/peer-notices.d.ts +11 -1
- package/dist/agents/peer-session-drain.js +2 -0
- package/dist/agents/verify.d.ts +2 -1
- package/dist/core/ask-origin.d.ts +130 -0
- package/dist/core/ask-origin.js +35 -0
- package/dist/core/auto-mode-arming.d.ts +40 -1
- package/dist/core/auto-mode-arming.js +51 -3
- package/dist/core/auto-mode.d.ts +87 -10
- package/dist/core/auto-mode.js +34 -6
- package/dist/core/checkpoint-store.d.ts +41 -6
- package/dist/core/checkpoint-store.js +8 -0
- package/dist/core/hooks.d.ts +63 -19
- package/dist/core/hooks.js +37 -16
- package/dist/core/mcp.d.ts +47 -55
- package/dist/core/mcp.js +89 -31
- package/dist/core/park-selfcheck.js +3 -0
- package/dist/core/permission-rule-consent.d.ts +2 -11
- package/dist/core/permission-rule-consent.js +13 -62
- package/dist/core/permission-rule-org.d.ts +70 -54
- package/dist/core/permission-rule-org.js +47 -61
- package/dist/core/permission-rule-provider.d.ts +162 -0
- package/dist/core/permission-rule-provider.js +148 -0
- package/dist/core/permission-rule-session.d.ts +23 -19
- package/dist/core/permission-rule-session.js +5 -5
- package/dist/core/permission-rule-store.d.ts +46 -21
- package/dist/core/permission-rule-store.js +13 -6
- package/dist/core/permission-rule-sync.d.ts +2 -1
- package/dist/core/permission-rule-sync.js +11 -0
- package/dist/core/runner/assemble-result.d.ts +3 -2
- package/dist/core/runner/checkpoint-scope.d.ts +32 -0
- package/dist/core/runner/checkpoint-scope.js +4 -0
- package/dist/core/runner/contracts.d.ts +1878 -0
- package/dist/core/runner/contracts.js +1 -0
- package/dist/core/runner/denial-limit-arms.d.ts +57 -31
- package/dist/core/runner/denial-limit-arms.js +42 -17
- package/dist/core/runner/derived-route-fallback.d.ts +34 -0
- package/dist/core/runner/derived-route-fallback.js +16 -0
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +1 -1
- package/dist/core/runner/prepare-announce-once.d.ts +83 -0
- package/dist/core/runner/prepare-announce-once.js +105 -0
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +170 -0
- package/dist/core/runner/prepare-caps-and-workflow.js +255 -0
- package/dist/core/runner/prepare-config-doors.d.ts +2 -10
- package/dist/core/runner/prepare-defer-classify.d.ts +86 -0
- package/dist/core/runner/prepare-defer-classify.js +107 -0
- package/dist/core/runner/prepare-delegation-surface.d.ts +104 -0
- package/dist/core/runner/prepare-delegation-surface.js +144 -0
- package/dist/core/runner/prepare-execution-env.d.ts +54 -0
- package/dist/core/runner/prepare-execution-env.js +86 -0
- package/dist/core/runner/prepare-file-history.d.ts +95 -0
- package/dist/core/runner/prepare-file-history.js +383 -0
- package/dist/core/runner/prepare-hands-readface.d.ts +6 -8
- package/dist/core/runner/prepare-hands-readface.js +3 -3
- package/dist/core/runner/prepare-inherited-gate.d.ts +268 -0
- package/dist/core/runner/prepare-inherited-gate.js +266 -0
- package/dist/core/runner/prepare-listings.d.ts +77 -0
- package/dist/core/runner/prepare-listings.js +76 -0
- package/dist/core/runner/prepare-lsp.d.ts +55 -0
- package/dist/core/runner/prepare-lsp.js +27 -0
- package/dist/core/runner/prepare-memory.d.ts +1 -1
- package/dist/core/runner/prepare-offload-wrappers.d.ts +62 -0
- package/dist/core/runner/prepare-offload-wrappers.js +45 -0
- package/dist/core/runner/prepare-permission-rules.d.ts +132 -0
- package/dist/core/runner/prepare-permission-rules.js +140 -0
- package/dist/core/runner/prepare-project-context.d.ts +131 -0
- package/dist/core/runner/prepare-project-context.js +150 -0
- package/dist/core/runner/prepare-prompt-inputs.d.ts +138 -0
- package/dist/core/runner/prepare-prompt-inputs.js +141 -0
- package/dist/core/runner/prepare-protocol-tools.d.ts +91 -0
- package/dist/core/runner/prepare-protocol-tools.js +182 -0
- package/dist/core/runner/prepare-question-face.d.ts +119 -0
- package/dist/core/runner/prepare-question-face.js +83 -0
- package/dist/core/runner/prepare-run-refs.d.ts +89 -0
- package/dist/core/runner/prepare-run-refs.js +39 -0
- package/dist/core/runner/prepare-safety-scan.d.ts +3 -2
- package/dist/core/runner/prepare-task.d.ts +11 -1815
- package/dist/core/runner/prepare-task.js +138 -2542
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +111 -0
- package/dist/core/runner/prepare-tool-disclosure-mount.js +219 -0
- package/dist/core/runner/prepare-wiring-manifest.d.ts +184 -0
- package/dist/core/runner/prepare-wiring-manifest.js +240 -0
- package/dist/core/runner/prepare-workspace-restore.d.ts +1 -27
- package/dist/core/runner/prepare-workspace-restore.js +1 -22
- package/dist/core/runner/rollback-stack.d.ts +32 -0
- package/dist/core/runner/rollback-stack.js +30 -0
- package/dist/core/runner/runtask.d.ts +11 -2
- package/dist/core/runner/runtask.js +27 -9
- package/dist/core/runner/workspace-path.d.ts +33 -0
- package/dist/core/runner/workspace-path.js +22 -0
- package/dist/core/sensitive-path-policy.d.ts +16 -0
- package/dist/core/sensitive-path-policy.js +1 -1
- package/dist/core/tool-policy.d.ts +57 -9
- package/dist/core/tool-policy.js +11 -0
- package/dist/core/types.d.ts +63 -51
- package/dist/core/wiring-manifest.d.ts +40 -3
- package/dist/core/wiring-manifest.js +4 -3
- package/dist/core/write-protect.d.ts +13 -2
- package/dist/core/write-protect.js +58 -29
- package/dist/engine/harness/types.d.ts +38 -16
- package/dist/engine/harness/types.js +25 -1
- package/dist/engine/session/session.d.ts +3 -11
- package/dist/index.d.ts +10 -6
- package/dist/index.js +9 -5
- package/dist/internal/harness.d.ts +1 -0
- package/dist/stores/file/adoption/adopt.d.ts +1 -1
- package/dist/stores/file/adoption/marker.d.ts +1 -1
- package/dist/stores/file/permission-rule-adopt.js +4 -3
- package/dist/stores/file/permission-rule-store.d.ts +65 -25
- package/dist/stores/file/permission-rule-store.js +215 -37
- package/dist/stores/file/task-list-store.d.ts +1 -1
- package/dist/tools/fs/read-face.d.ts +1 -1
- package/package.json +8 -2
- package/test/export-surface.snapshot.json +76 -28
|
@@ -585,12 +585,42 @@ export interface PromptEpochEntry extends SessionTreeEntryBase, PromptEpochDescr
|
|
|
585
585
|
* replay remain as the second/third rungs of the resume-seed ladder for pre-entry sessions.
|
|
586
586
|
* Present-only arms — an absent arm means "no announcement recorded for that face", same Q5
|
|
587
587
|
* discipline as the checkpoint mirror.
|
|
588
|
+
*
|
|
589
|
+
* Two further arms ride the same snapshot for the prepare-time ONE-SHOT announcements, which are
|
|
590
|
+
* per-SESSION facts even though prepare runs once per run (a serving layer maps one user message to
|
|
591
|
+
* one run, so a per-run count re-announces them on every message):
|
|
592
|
+
* - `mcpFailed`: the MCP servers whose connect failure the model has been TOLD about, as the
|
|
593
|
+
* `{name, error}` pairs the reminder printed. The next run announces only the pairs that are not
|
|
594
|
+
* in this set (a changed error text is a new pair); a server that is no longer failing is dropped
|
|
595
|
+
* from the set without any "recovered" line, so a later failure of the same server announces again.
|
|
596
|
+
* - `advisories`: digests of the operator-lane advisory lines already emitted on this branch
|
|
597
|
+
* (the `(code, message)` of each `onError` warning, plus the model-facing dropped-tool entries)
|
|
598
|
+
* — the same `(code, text)` is emitted once per session. Grow-only, bounded (oldest dropped).
|
|
588
599
|
*/
|
|
589
|
-
export interface AnnouncedListingEntry extends SessionTreeEntryBase {
|
|
600
|
+
export interface AnnouncedListingEntry extends SessionTreeEntryBase, AnnouncedListingSnapshot {
|
|
590
601
|
type: "announced_listing";
|
|
602
|
+
}
|
|
603
|
+
/** One announced MCP connect failure — the pair the reminder line printed (both fields already
|
|
604
|
+
* neutralized + bounded at intake; compared field-wise, CC `deferred_tools_delta` form). */
|
|
605
|
+
export interface AnnouncedMcpFailure {
|
|
606
|
+
name: string;
|
|
607
|
+
error?: string;
|
|
608
|
+
}
|
|
609
|
+
/** The announced-listing snapshot's arms (see {@link AnnouncedListingEntry}). Present-only. */
|
|
610
|
+
export interface AnnouncedListingSnapshot {
|
|
591
611
|
agents?: string[];
|
|
592
612
|
skills?: string[];
|
|
593
613
|
models?: string[];
|
|
614
|
+
mcpFailed?: AnnouncedMcpFailure[];
|
|
615
|
+
advisories?: string[];
|
|
616
|
+
}
|
|
617
|
+
/** The same snapshot as an APPEND input (borrowed arrays; the store copies through the shape gate). */
|
|
618
|
+
export interface AnnouncedListingSnapshotInput {
|
|
619
|
+
agents?: readonly string[];
|
|
620
|
+
skills?: readonly string[];
|
|
621
|
+
models?: readonly string[];
|
|
622
|
+
mcpFailed?: ReadonlyArray<AnnouncedMcpFailure>;
|
|
623
|
+
advisories?: readonly string[];
|
|
594
624
|
}
|
|
595
625
|
/**
|
|
596
626
|
* REF-D3/D4 merge target: the active EnterWorktree session (M22 live-CC anchor —
|
|
@@ -732,6 +762,10 @@ export declare function normalizeWorkspaceState(value: unknown): WorkspaceState
|
|
|
732
762
|
* a "name" is a short identifier, never a document. Oversize ⇒ structurally invalid (forgery signal). */
|
|
733
763
|
export declare const ANNOUNCED_LISTING_MAX_NAMES = 500;
|
|
734
764
|
export declare const ANNOUNCED_LISTING_MAX_NAME_CHARS = 200;
|
|
765
|
+
/** Bound (in CODE POINTS, the producer's unit) for an announced MCP failure's `error` text — intake
|
|
766
|
+
* caps it at 240 code points plus the truncation ellipsis; anything past this bound never came from
|
|
767
|
+
* the engine's own projection. The `name` rides the listing name bound, also counted in code points. */
|
|
768
|
+
export declare const ANNOUNCED_MCP_ERROR_MAX_CHARS = 400;
|
|
735
769
|
export declare function normalizeCompactionStateCarrier(v: unknown): {
|
|
736
770
|
thinkingLevel?: string;
|
|
737
771
|
model?: {
|
|
@@ -790,11 +824,7 @@ export declare function isSyntheticApiErrorMessage(m: unknown): boolean;
|
|
|
790
824
|
* the contamination lands on disk and every later `open()` throws a raw `TypeError` (not even a `SessionError`).
|
|
791
825
|
* Unrecoverable through the API, which is why this belongs at the import door. */
|
|
792
826
|
export declare function isOptionalDisplayString(v: unknown, max?: number): boolean;
|
|
793
|
-
export declare function normalizeAnnouncedListing(v: unknown):
|
|
794
|
-
agents?: string[];
|
|
795
|
-
skills?: string[];
|
|
796
|
-
models?: string[];
|
|
797
|
-
} | undefined;
|
|
827
|
+
export declare function normalizeAnnouncedListing(v: unknown): AnnouncedListingSnapshot | undefined;
|
|
798
828
|
/** All persisted session tree entry variants. */
|
|
799
829
|
export type SessionTreeEntry = MessageEntry | ThinkingLevelChangeEntry | ModelChangeEntry | CompactionEntry | CustomEntry | CustomMessageEntry | LabelEntry | SessionInfoEntry | LeafEntry | PromptEpochEntry | AnnouncedListingEntry | GitAnnouncementEntry | WorkspaceStateEntry | ReminderMarkEntry;
|
|
800
830
|
export interface SessionContext {
|
|
@@ -916,18 +946,10 @@ export interface Session<TMetadata extends SessionMetadata = SessionMetadata> {
|
|
|
916
946
|
appendSessionName(name: string): Promise<string>;
|
|
917
947
|
/** design/150 (RB-25): persist the listing announced name-sets as a first-class
|
|
918
948
|
* {@link AnnouncedListingEntry} (snapshot semantics; see `Session.appendAnnouncedListing`). */
|
|
919
|
-
appendAnnouncedListing(snapshot:
|
|
920
|
-
agents?: readonly string[];
|
|
921
|
-
skills?: readonly string[];
|
|
922
|
-
models?: readonly string[];
|
|
923
|
-
}): Promise<string>;
|
|
949
|
+
appendAnnouncedListing(snapshot: AnnouncedListingSnapshotInput): Promise<string>;
|
|
924
950
|
/** design/150 (RB-25): nearest announced-listing snapshot on the active branch (first rung of the
|
|
925
951
|
* resume-seed ladder); undefined ⇒ pre-entry session. */
|
|
926
|
-
getAnnouncedListing(): Promise<
|
|
927
|
-
agents?: string[];
|
|
928
|
-
skills?: string[];
|
|
929
|
-
models?: string[];
|
|
930
|
-
} | undefined>;
|
|
952
|
+
getAnnouncedListing(): Promise<AnnouncedListingSnapshot | undefined>;
|
|
931
953
|
/** design/155: persist the settle-time workspace state (tracked cwd + active worktree) as a
|
|
932
954
|
* first-class {@link WorkspaceStateEntry} (snapshot semantics; see `Session.appendWorkspaceState`). */
|
|
933
955
|
appendWorkspaceState(state: WorkspaceState): Promise<string>;
|
|
@@ -127,6 +127,7 @@ export function normalizeWorkspaceState(value) {
|
|
|
127
127
|
}
|
|
128
128
|
export const ANNOUNCED_LISTING_MAX_NAMES = 500;
|
|
129
129
|
export const ANNOUNCED_LISTING_MAX_NAME_CHARS = 200;
|
|
130
|
+
export const ANNOUNCED_MCP_ERROR_MAX_CHARS = 400;
|
|
130
131
|
const THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
131
132
|
export function normalizeCompactionStateCarrier(v) {
|
|
132
133
|
if (typeof v !== "object" || v === null)
|
|
@@ -180,14 +181,37 @@ export function normalizeAnnouncedListing(v) {
|
|
|
180
181
|
}
|
|
181
182
|
return out;
|
|
182
183
|
};
|
|
184
|
+
const cps = (t) => [...t].length;
|
|
185
|
+
const failureArm = (a) => {
|
|
186
|
+
if (a === undefined)
|
|
187
|
+
return undefined;
|
|
188
|
+
if (!Array.isArray(a) || a.length > ANNOUNCED_LISTING_MAX_NAMES)
|
|
189
|
+
return null;
|
|
190
|
+
const out = [];
|
|
191
|
+
for (const e of a) {
|
|
192
|
+
if (typeof e !== "object" || e === null)
|
|
193
|
+
return null;
|
|
194
|
+
const { name, error } = e;
|
|
195
|
+
if (typeof name !== "string" || cps(name) > ANNOUNCED_LISTING_MAX_NAME_CHARS)
|
|
196
|
+
return null;
|
|
197
|
+
if (error !== undefined && (typeof error !== "string" || cps(error) > ANNOUNCED_MCP_ERROR_MAX_CHARS))
|
|
198
|
+
return null;
|
|
199
|
+
out.push({ name, ...(error !== undefined ? { error } : {}) });
|
|
200
|
+
}
|
|
201
|
+
return out;
|
|
202
|
+
};
|
|
183
203
|
const agents = arm(src.agents);
|
|
184
204
|
const skills = arm(src.skills);
|
|
185
205
|
const models = arm(src.models);
|
|
186
|
-
|
|
206
|
+
const mcpFailed = failureArm(src.mcpFailed);
|
|
207
|
+
const advisories = arm(src.advisories);
|
|
208
|
+
if (agents === null || skills === null || models === null || mcpFailed === null || advisories === null)
|
|
187
209
|
return undefined;
|
|
188
210
|
return {
|
|
189
211
|
...(agents !== undefined ? { agents } : {}),
|
|
190
212
|
...(skills !== undefined ? { skills } : {}),
|
|
191
213
|
...(models !== undefined ? { models } : {}),
|
|
214
|
+
...(mcpFailed !== undefined ? { mcpFailed } : {}),
|
|
215
|
+
...(advisories !== undefined ? { advisories } : {}),
|
|
192
216
|
};
|
|
193
217
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ImageContent, TextContent } from "../llm/index.js";
|
|
2
2
|
import type { AgentMessage } from "../loop/types.js";
|
|
3
|
-
import type { GitAnnouncementState, Session, SessionContext, SessionMetadata, SessionStorage, SessionTreeEntry, WorkspaceState } from "../harness/types.js";
|
|
3
|
+
import type { AnnouncedListingSnapshot, AnnouncedListingSnapshotInput, GitAnnouncementState, Session, SessionContext, SessionMetadata, SessionStorage, SessionTreeEntry, WorkspaceState } from "../harness/types.js";
|
|
4
4
|
import type { BuildContextOptions } from "../harness/types.js";
|
|
5
5
|
import type { PromptEpochDescriptor } from "../../prompt-assembly/epoch.js";
|
|
6
6
|
/** Build model context from the active session branch and its latest state markers.
|
|
@@ -40,11 +40,7 @@ export declare class StoredSession<TMetadata extends SessionMetadata = SessionMe
|
|
|
40
40
|
* Called best-effort at every listing COMMIT point (the run loop's announce mirror sites) —
|
|
41
41
|
* an append failure degrades to the checkpoint-mirror/transcript-probe rungs, never fails the run.
|
|
42
42
|
*/
|
|
43
|
-
appendAnnouncedListing(snapshot:
|
|
44
|
-
agents?: readonly string[];
|
|
45
|
-
skills?: readonly string[];
|
|
46
|
-
models?: readonly string[];
|
|
47
|
-
}): Promise<string>;
|
|
43
|
+
appendAnnouncedListing(snapshot: AnnouncedListingSnapshotInput): Promise<string>;
|
|
48
44
|
/**
|
|
49
45
|
* Git-status frame announced state (branch-authority mirror): persist the `(kind, hash)` tuple —
|
|
50
46
|
* announced form carries the frame's own entry id; a compaction restates the tuple as `pending`
|
|
@@ -121,11 +117,7 @@ export declare class StoredSession<TMetadata extends SessionMetadata = SessionMe
|
|
|
121
117
|
* loss). A floor-anchor seam (the getEpochAnchor analog) is deliberately deferred until a real
|
|
122
118
|
* deployment hits that window.
|
|
123
119
|
*/
|
|
124
|
-
getAnnouncedListing(): Promise<
|
|
125
|
-
agents?: string[];
|
|
126
|
-
skills?: string[];
|
|
127
|
-
models?: string[];
|
|
128
|
-
} | undefined>;
|
|
120
|
+
getAnnouncedListing(): Promise<AnnouncedListingSnapshot | undefined>;
|
|
129
121
|
/**
|
|
130
122
|
* Recover the pinned prompt epoch for the ACTIVE branch (stage S3). Walks the branch from the
|
|
131
123
|
* leaf backwards: the nearest `compaction` entry's `details.promptEpoch` restatement wins (the
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,7 @@ export { decideAutoPromote, deriveTripwire, FROZEN_DENYLIST_FLOOR, type AutoProm
|
|
|
50
50
|
export { runCascade, type CascadeRung, type CascadeConfig, type CascadeAttempt, type CascadeRunResult, type GateVerdict, } from "./agents/cascade.js";
|
|
51
51
|
export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
|
|
52
52
|
export { materializeMcpTools, MCP_PREFIX, type MaterializedMcp, type McpServerStatus, type McpRefreshResult } from "./core/mcp.js";
|
|
53
|
+
export { MCP_FAILURE_CODES, mcpFailureCodeOf, type McpFailureCode } from "./core/mcp.js";
|
|
53
54
|
export { materializeA2aTools, A2aRpcError, type MaterializedA2a, type A2aPeerStatus, type A2aRefreshResult, type A2aToolAxis } from "./core/a2a.js";
|
|
54
55
|
export { PROTOCOL_TABLE, MCP_NAMESPACE, A2A_NAMESPACE, protocolOf, type ProtocolNamespace, type ProtocolId } from "./core/protocol-table.js";
|
|
55
56
|
export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, type SessionPolicyStore, type SessionPermissionRules, type StoredSessionRules, type SessionRulesRecord, type PutRulesOptions, } from "./core/session-policy-store.js";
|
|
@@ -119,7 +120,7 @@ export { createFsWriteGatePolicy, type FsWriteGatePolicyOptions } from "./core/f
|
|
|
119
120
|
export { RETIRED_TOOL_NAMES } from "./core/tool-name-aliases.js";
|
|
120
121
|
export { DEFAULT_SUBAGENT_TOOL_NAME } from "./agents/subagent.js";
|
|
121
122
|
export { renderTaskNotificationXml, taskNotificationDedupKey, isDelegatedAgentTerminal, isTerminalTaskNotification, SystemInjectionQueue, type TaskNotificationPayload, type TaskNotificationStatus, type ExternalNotificationInput, type SystemInjection, type SystemInjectionPriority, SYSTEM_INJECTION_PRIORITIES, isSystemInjectionPriority, AGENT_MESSAGE_TAG, renderAgentMessageFrame, type SemaProvenance, } from "./core/task-notification.js";
|
|
122
|
-
export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, type SubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, AUTO_MODE_ARM_REASONS, type AutoModeArmReason, type WiringManifest, type WiringFacts, type WiringLegKind, type AskSeamForm, type AskEffective, type QuestionChannelState, type SeamProvenance, type ParkLaneReason, type ManifestDurability, type StaticWiringDeps, type StaticWiringSpec, } from "./core/wiring-manifest.js";
|
|
123
|
+
export { describeStaticWiring, deriveWiringManifest, deriveAskEffective, resolveDeclaredDurability, resolveSubagentTranscriptTier, type SubagentTranscriptTier, resolveAskSeamForm, resolveQuestionSeam, countElicitOptIns, AUTO_MODE_ARM_REASONS, type AutoModeArmReason, type WiringManifest, type WiringManifestMcpEntry, type WiringFacts, type WiringLegKind, type AskSeamForm, type AskEffective, type QuestionChannelState, type SeamProvenance, type ParkLaneReason, type ManifestDurability, type StaticWiringDeps, type StaticWiringSpec, } from "./core/wiring-manifest.js";
|
|
123
124
|
export { probeParkRoundTrip, durableParkGapOf, durableParkGapFor, PARK_SELFCHECK_SCOPE_PREFIX, type ParkSelfCheckResult, type ParkProbeFinding, type ParkProbeFindingCode, } from "./core/park-selfcheck.js";
|
|
124
125
|
export { type StoreDurability } from "./core/checkpoint-store.js";
|
|
125
126
|
export { type StoreFidelity } from "./core/checkpoint-store.js";
|
|
@@ -145,7 +146,9 @@ export { createSchedulerTools, type SchedulerToolContext, SCHEDULE_WAKEUP_TOOL_N
|
|
|
145
146
|
export { resolveAutonomousLoopPrompt, AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT, type AutonomousLoopPromptOptions, } from "./tools/loop-tick.js";
|
|
146
147
|
export { tightenTaskSpec, TaskSpecTightenError } from "./core/tighten-task-spec.js";
|
|
147
148
|
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, type ToolPolicyNameSets, type NamedToolPolicy, type ToolPolicyProjection, type ToolPolicyProjectionComponent, type ConstraintChainEntry, checkToolPolicyProjection, constraintChainEntryOf, constraintChainDigest, type ToolPolicy, type ToolCallRequest, type PermissionResult, type DecisionReason, type ApprovalSettledBy, APPROVAL_SETTLED_BY_VALUES, isApprovalSettledBy, type AskDenyResolution, ASK_DENY_RESOLUTION_VALUES, isAskDenyResolution, screenApproverAttribution, APPROVER_ATTRIBUTION_MAX_CHARS, type OnAsk, type AskOutcome, type ResolvedAsk, type AskRequest, type AskDelegationProvenance, type AskRuleEvidence, type AskEvidenceAbsence, ASK_EVIDENCE_ABSENCE_VALUES, } from "./core/tool-policy.js";
|
|
148
|
-
export {
|
|
149
|
+
export { type AskOrigin, ASK_ORIGINS, isAskOrigin, classifierMayAnswer } from "./core/ask-origin.js";
|
|
150
|
+
export { type AskCarry } from "./core/hooks.js";
|
|
151
|
+
export { parseAutoModeResponse, createAutoModeDecider, type AutoModeVerdict, type AutoModeDecider, type AutoModeDeciderOptions, type AutoModeClassifyFn, type AutoModeClassifyInput, createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow, type AutoModeDenialTracker, type AutoModeDenialLimitOptions, type DenialLimitCounts, type DenialLimitFallbackFace, type UnarmedDenialLimitFallback, type DenialLimitFallback, type DenialLimitVerdict, } from "./core/auto-mode.js";
|
|
149
152
|
export { AUTO_MODE_DENIAL_LIMIT_DEFAULTS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS } from "./core/auto-mode-defaults.js";
|
|
150
153
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, type AutoModeRules, type BuildAutoModePromptOptions, type AutoModeWindowOptions, } from "./core/auto-mode-prompt.js";
|
|
151
154
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|
|
@@ -168,13 +171,14 @@ export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRul
|
|
|
168
171
|
* allowed and widening is not.
|
|
169
172
|
*/
|
|
170
173
|
export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, type UncoveredSegmentDetail, type EditedRuleBreadthWarning, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, type PersistedAllowRule, type RuleTombstone, type RuleScope, type RuleDot, type RuleAdd, type RuleAddOrigin, type RuleOffer, type RuleOfferBatchMember, type SegmentRuleSuggestion, type SegmentCoverage, type RuleReject, type RuleRejectCode, type ParsedAllowRule, type PersistedRuleTool, type PersistedRuleMatch, } from "./core/permission-rule-model.js";
|
|
171
|
-
export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope,
|
|
174
|
+
export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, type DurableRulePartition, type DurableRulePartitionProvider, type RuleWriteOutcome, type StoredAllowRules, type RemoveResult, type PutResult, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, type RuleSyncState, type RuleSyncFrontier, type RuleSyncDrop, type RuleSyncLandingReport, type RuleOwner, type QuarantinedRuleAdd, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, type PermissionRuleWriter, type WritableDurableRulePartition, type RuleWriteDelta, type RuleAddDelta, type RuleDeleteDelta, type RuleSyncJoinDelta, type RawRuleSyncState, type RedemptionAuthorization, } from "./core/permission-rule-store.js";
|
|
172
175
|
export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, type PermissionRuleSyncTransport, type PermissionRuleSyncResult, type RuleSyncRequestBody, type RuleSyncResponseBody, } from "./core/permission-rule-sync.js";
|
|
173
|
-
export {
|
|
174
|
-
export {
|
|
176
|
+
export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, type PermissionRuleStore, type PermissionRuleStoreProvider, type PermissionRuleStoreConfig, type EffectivePermissionRules, type EffectivePermissionRule, type RemovedPermissionRule, type RuleSource, } from "./core/permission-rule-provider.js";
|
|
177
|
+
export { InMemorySessionRulePartition, type SessionRulePartition, type SessionRuleAdd, type SessionRuleApplyResult, } from "./core/permission-rule-session.js";
|
|
178
|
+
export { orgRuleVerdictFor, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, type OrgPermissionRule, type OrgRuleSnapshot, type OrgRuleSnapshotProvider, type OrgRuleStatePersistence, type PersistedOrgRuleState, type OrgRulePartitionConfig, type OrgRuleResolution, type OrgRuleStatus, } from "./core/permission-rule-org.js";
|
|
175
179
|
export { RULE_SYNC_DROP_CODES, type RuleSyncDropReason, type RuleQuarantineReason } from "./core/governance-codes.js";
|
|
176
180
|
export { prepareCardApproval, confirmRuleApproval, type ConfirmResult, type ConfirmRefusalReason, precheckEditedRuleText, type EditedRuleTextPrecheck, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, ruleOffersOfRecord, type RuleTicket, type RuleCandidate, type RuleApprovalKind, type RuleApprovalRecord, type RuleApprovalRecordStore, type RuleOffer2, type StaleRuleApprovalRecord, type RuleConsentDeps, type RedeemResult, type RedeemedBatchMember, type CcImportLayer, type ImportedSettingsLayer, type ImportPreview, } from "./core/permission-rule-consent.js";
|
|
177
|
-
export {
|
|
181
|
+
export { FileDurableRulePartitionProvider, ORG_STATE_FILE } from "./stores/file/permission-rule-store.js";
|
|
178
182
|
export { adoptFilePermissionRuleStore, type AdoptFileRuleStoreResult } from "./stores/file/permission-rule-adopt.js";
|
|
179
183
|
export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootAdoptionFile, ROOT_ADOPTION_FILE, type AdoptionErrorCode, type AdoptionSource, type AdoptionReport, type AdoptionReceipt, type AdoptionLegReport, type AffectedDeploymentConfig, type RootAdoptionFile, } from "./stores/file/adoption/marker.js";
|
|
180
184
|
export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, type AdoptionStatus, type AdoptLocalDataRootOptions, type AdoptLocalDataRootResult, type AdoptionCarriageLeg, type AdoptionCarriageLegContext, type AdoptionConfigWitnessReceipt, } from "./stores/file/adoption/adopt.js";
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,7 @@ export { decideAutoPromote, deriveTripwire, FROZEN_DENYLIST_FLOOR, } from "./cor
|
|
|
38
38
|
export { runCascade, } from "./agents/cascade.js";
|
|
39
39
|
export { pgQuery, mysqlQuery, sqliteQuery } from "./tools/sql-adapters.js";
|
|
40
40
|
export { materializeMcpTools, MCP_PREFIX } from "./core/mcp.js";
|
|
41
|
+
export { MCP_FAILURE_CODES, mcpFailureCodeOf } from "./core/mcp.js";
|
|
41
42
|
export { materializeA2aTools, A2aRpcError } from "./core/a2a.js";
|
|
42
43
|
export { PROTOCOL_TABLE, MCP_NAMESPACE, A2A_NAMESPACE, protocolOf } from "./core/protocol-table.js";
|
|
43
44
|
export { InMemorySessionPolicyStore, SessionPolicyError, loosenReasons, normalizeRules, stripRev, } from "./core/session-policy-store.js";
|
|
@@ -120,7 +121,9 @@ export { createSchedulerTools, SCHEDULE_WAKEUP_TOOL_NAME, AUTONOMOUS_LOOP_SENTIN
|
|
|
120
121
|
export { resolveAutonomousLoopPrompt, AUTONOMOUS_LOOP_PREAMBLE, AUTONOMOUS_LOOP_PREAMBLE_PERSISTENT, } from "./tools/loop-tick.js";
|
|
121
122
|
export { tightenTaskSpec, TaskSpecTightenError } from "./core/tighten-task-spec.js";
|
|
122
123
|
export { createAllowDenyPolicy, createApprovalPolicy, COARSE_SHELL_TOOLS, createCoarseCommandNamePolicy, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, findUnverifiableRecursiveDelete, combinePolicies, decisionText, resolveAsk, toolPolicyNameSets, checkToolPolicyProjection, constraintChainEntryOf, constraintChainDigest, APPROVAL_SETTLED_BY_VALUES, isApprovalSettledBy, ASK_DENY_RESOLUTION_VALUES, isAskDenyResolution, screenApproverAttribution, APPROVER_ATTRIBUTION_MAX_CHARS, ASK_EVIDENCE_ABSENCE_VALUES, } from "./core/tool-policy.js";
|
|
123
|
-
export {
|
|
124
|
+
export { ASK_ORIGINS, isAskOrigin, classifierMayAnswer } from "./core/ask-origin.js";
|
|
125
|
+
export {} from "./core/hooks.js";
|
|
126
|
+
export { parseAutoModeResponse, createAutoModeDecider, createAutoModeDenialTracker, denialLimitFallbackMessage, denialLimitSentence, unarmedWindow, } from "./core/auto-mode.js";
|
|
124
127
|
export { AUTO_MODE_DENIAL_LIMIT_DEFAULTS, AUTO_MODE_DENIAL_AUTO_DENY_DEFAULT_MS } from "./core/auto-mode-defaults.js";
|
|
125
128
|
export { buildAutoModePrompt, renderAutoModeWindow, renderAutoModeAction, AUTO_MODE_DEFAULTS_SENTINEL, } from "./core/auto-mode-prompt.js";
|
|
126
129
|
export { AUTO_MODE_BASE_PROMPT, AUTO_MODE_PERMISSIONS_EXTERNAL } from "./core/auto-mode-prompt-assets.js";
|
|
@@ -128,13 +131,14 @@ export { AUTO_MODE_ARMING_RECIPE_VERSION, autoModeArmingRecipeOf, sanitizeAutoMo
|
|
|
128
131
|
export { rebuildAutoModeDecider, } from "./core/auto-mode-rebuild.js";
|
|
129
132
|
export { createPermissionRulePolicy, validatePermissionRules, parsePermissionRule, wildcardMatch, isNamespacedCoveringRuleName, namespacedRuleNameCovers, } from "./core/permission-rules.js";
|
|
130
133
|
export { parseAllowRuleText, formatAllowRuleText, ruleAdmitsCommand, findAdmittingRule, suggestRulesForCommand, scopeCoversCwd, pathWithinRoot, isRuleLive, renderUntrustedCommandText, stripFormatCharacters, UNCOVERED_SEGMENT_REASON_BASELINE, RULE_OFFERS_ABSENCE_BASELINE, directoryRuleAdmits, BARE_INTERPRETER_NAMES, MAX_RULE_TEXT_CHARS, } from "./core/permission-rule-model.js";
|
|
131
|
-
export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope,
|
|
134
|
+
export { removePersistedRule, applyTombstones, sameScope, isValidConsentScope, isValidDurableScope, InMemoryDurableRulePartition, EMPTY_DURABLE_RULE_PARTITION, joinRuleStates, screenRuleSyncState, collectBelowFrontier, ruleSyncVector, joinFrontiers, dotAtOrBelowFrontier, sameRuleOwner, PERMISSION_RULE_WRITER, writerOf, foldDelta, addDotsOf, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, } from "./core/permission-rule-store.js";
|
|
132
135
|
export { syncPermissionRules, parseRuleSyncResponse, PERMISSION_RULE_SYNC_PATH, LOCAL_OWNER_UNSYNCABLE_CODE, } from "./core/permission-rule-sync.js";
|
|
133
|
-
export {
|
|
134
|
-
export {
|
|
136
|
+
export { createPermissionRuleStoreProvider, effectivePermissionRules, effectiveOrThrow, ruleSourceOf, } from "./core/permission-rule-provider.js";
|
|
137
|
+
export { InMemorySessionRulePartition, } from "./core/permission-rule-session.js";
|
|
138
|
+
export { orgRuleVerdictFor, orgRuleShadows, unenforceableOrgRules, ORG_UNAVAILABLE_DECISION_REASON, ORG_RULE_DECISION_REASON, ORG_ADJUDICATION_TIMEOUT_MS, } from "./core/permission-rule-org.js";
|
|
135
139
|
export { RULE_SYNC_DROP_CODES } from "./core/governance-codes.js";
|
|
136
140
|
export { prepareCardApproval, confirmRuleApproval, precheckEditedRuleText, redeemRuleTicket, redeemRuleBatch, prepareCcImport, prepareStarterBatch, mintRuleTicket, STARTER_RULES, InMemoryRuleApprovalRecordStore, ruleOffersOfRecord, } from "./core/permission-rule-consent.js";
|
|
137
|
-
export {
|
|
141
|
+
export { FileDurableRulePartitionProvider, ORG_STATE_FILE } from "./stores/file/permission-rule-store.js";
|
|
138
142
|
export { adoptFilePermissionRuleStore } from "./stores/file/permission-rule-adopt.js";
|
|
139
143
|
export { AdoptionError, assertAdoptionBootGate, readRootAdoptionFile, writeRootAdoptionFile, ROOT_ADOPTION_FILE, } from "./stores/file/adoption/marker.js";
|
|
140
144
|
export { adoptLocalDataRoot, ackAdoptionConfig, witnessAdoptionConfig, listAdoptionQuarantine, readAdoptionStatus, } from "./stores/file/adoption/adopt.js";
|
|
@@ -23,6 +23,7 @@ export { InMemorySessionStorage } from "../engine/session/memory-storage.js";
|
|
|
23
23
|
export { InMemorySessionRepo } from "../engine/session/memory-repo.js";
|
|
24
24
|
export { uuidv7 } from "../engine/session/uuid.js";
|
|
25
25
|
export { SessionError } from "../engine/harness/types.js";
|
|
26
|
+
export type { AnnouncedListingSnapshot, AnnouncedListingSnapshotInput, AnnouncedMcpFailure } from "../engine/harness/types.js";
|
|
26
27
|
export { normalizeGitAnnouncement } from "../engine/harness/types.js";
|
|
27
28
|
export { gitFrameContextVisible } from "../engine/session/session.js";
|
|
28
29
|
export { isSyntheticApiErrorMessage } from "../engine/harness/types.js";
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
* independent store faces — `new FileMemoryStore(root)`, the mailbox family). It keeps its open
|
|
39
39
|
* handles, and I6 is a construction-time gate, not a write-time one;
|
|
40
40
|
* · a NEW construction whose anchor is not the data root. Two faces take a directory that need not
|
|
41
|
-
* BE the data root — `
|
|
41
|
+
* BE the data root — `FileDurableRulePartitionProvider` (the rule bucket) and
|
|
42
42
|
* `createFileTaskListStore` (the document's own directory) — so each takes its root anchor as an
|
|
43
43
|
* explicit option, and a caller that omits it constructs unGATED during a freeze. That default is
|
|
44
44
|
* what this arc's own nested rule leg rides (it must reach the bucket while the marker is in
|
|
@@ -197,7 +197,7 @@ export declare function writeRootAdoptionFile(root: string, content: RootAdoptio
|
|
|
197
197
|
*
|
|
198
198
|
* WHO calls it, precisely: every store constructor whose argument IS the data root (that is most of
|
|
199
199
|
* the family — they derive their own subdirectory from it). The two faces whose argument is a
|
|
200
|
-
* caller-chosen directory instead — `
|
|
200
|
+
* caller-chosen directory instead — `FileDurableRulePartitionProvider` (a rule bucket) and
|
|
201
201
|
* `createFileTaskListStore` (the document's directory) — cannot anchor on their argument, so each
|
|
202
202
|
* takes the data root as an explicit option and is gated only when given one. `root` here is always
|
|
203
203
|
* the ANCHOR, never "wherever this store keeps its bytes": passing a subdirectory reads a marker that
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { existsSync, renameSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { writerOf } from "../../core/permission-rule-store.js";
|
|
4
|
+
import { createPermissionRuleStoreProvider } from "../../core/permission-rule-provider.js";
|
|
4
5
|
import { syncPermissionRules } from "../../core/permission-rule-sync.js";
|
|
5
|
-
import {
|
|
6
|
+
import { FileDurableRulePartitionProvider, LOCAL_OWNER_FILE, principalRuleFileName, readRuleAdoptionFile, writeRuleAdoptionFile, } from "./permission-rule-store.js";
|
|
6
7
|
export async function adoptFilePermissionRuleStore(opts) {
|
|
7
8
|
if (typeof opts.toPrincipal !== "string" || opts.toPrincipal === "") {
|
|
8
9
|
throw new Error("adoptFilePermissionRuleStore requires the adopting principal — adoption is the act of giving this bucket an identity");
|
|
@@ -26,7 +27,7 @@ export async function adoptFilePermissionRuleStore(opts) {
|
|
|
26
27
|
else if (existsSync(targetFile)) {
|
|
27
28
|
throw new Error(`the target bucket for "${opts.toPrincipal}" already exists — merging two existing buckets goes through an explicit sync join, not a rename`);
|
|
28
29
|
}
|
|
29
|
-
const provider = new
|
|
30
|
+
const provider = new FileDurableRulePartitionProvider(opts.dir, opts.onError);
|
|
30
31
|
try {
|
|
31
32
|
const lockProbe = writerOf(provider.forPrincipal(opts.toPrincipal));
|
|
32
33
|
if (lockProbe === undefined)
|
|
@@ -55,7 +56,7 @@ export async function adoptFilePermissionRuleStore(opts) {
|
|
|
55
56
|
if (phase < 5) {
|
|
56
57
|
try {
|
|
57
58
|
syncResult = await syncPermissionRules({
|
|
58
|
-
provider,
|
|
59
|
+
provider: createPermissionRuleStoreProvider({ durable: provider }),
|
|
59
60
|
principal: opts.toPrincipal,
|
|
60
61
|
transport: opts.transport,
|
|
61
62
|
...(opts.now !== undefined ? { now: opts.now } : {}),
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* design/179 §5/§8 — the file backend
|
|
2
|
+
* design/179 §5/§8 / design/389 — the file backend of the permission-rule store's DURABLE partition (one
|
|
3
|
+
* bucket file per owner), plus the file home of the ORG partition's durable state (`org.json`).
|
|
4
|
+
*
|
|
5
|
+
* ## Schema 3 and the one-time migration
|
|
6
|
+
*
|
|
7
|
+
* Pre-389 files (schema 1/2) kept the org last-known-good snapshot as an `org` block INSIDE each
|
|
8
|
+
* principal's bucket file — deployment-wide policy stored per person. Schema 3 drops that block; the org
|
|
9
|
+
* state lives in one `org.json` beside the buckets. `FileDurableRulePartitionProvider` migrates every
|
|
10
|
+
* legacy bucket file ONCE at construction (under the writer lock: the migration is a write, and a live
|
|
11
|
+
* older writer over the same directory is refused rather than raced), folding each file's `org` block
|
|
12
|
+
* into `org.json` by the anti-rollback rule (the highest high-water wins; an equal revision with
|
|
13
|
+
* different content keeps what is already installed and discloses). After that the reader accepts
|
|
14
|
+
* schema 3 ONLY — a 1/2/4 file is refused whole, loudly (zero rules + disclosure). There is no second
|
|
15
|
+
* read path for the old shapes: the migrator is the only code that reads them, and it runs once.
|
|
3
16
|
*
|
|
4
17
|
* ## Why this store builds its own symlink refusal
|
|
5
18
|
*
|
|
@@ -43,23 +56,18 @@
|
|
|
43
56
|
* For this backend the trust is host = user, exactly as for the settings file it mirrors.
|
|
44
57
|
*/
|
|
45
58
|
import type { PersistedAllowRule, RuleTombstone } from "../../core/permission-rule-model.js";
|
|
46
|
-
import type {
|
|
59
|
+
import type { DurableRulePartition, DurableRulePartitionProvider, PermissionRuleWriter, QuarantinedRuleAdd, RuleOwner, RuleSyncFrontier, StoredAllowRules, WritableDurableRulePartition } from "../../core/permission-rule-store.js";
|
|
47
60
|
import { PERMISSION_RULE_WRITER } from "../../core/permission-rule-store.js";
|
|
48
|
-
import type { PersistedOrgRuleState } from "../../core/permission-rule-org.js";
|
|
61
|
+
import type { OrgRuleStatePersistence, PersistedOrgRuleState } from "../../core/permission-rule-org.js";
|
|
49
62
|
import type { StoreDurability, StoreFidelity } from "../../core/checkpoint-store.js";
|
|
50
63
|
/**
|
|
51
|
-
* The on-disk shape. `schemaVersion` is the only field a future reader may rely on before
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* the live view, bytes preserved). The five v1 fields are byte-identical in meaning. A file only ever
|
|
56
|
-
* ESCALATES to v2 when a write actually carries v2 content (a sync round, an org install, a
|
|
57
|
-
* quarantine): a deployment that never syncs keeps writing v1 files forever, and a v1 reader handed a
|
|
58
|
-
* v2 file refuses the whole file loudly (zero rules + disclosure — fail-closed, more asks, and the
|
|
59
|
-
* documented cost of rolling the engine back under an already-synced store).
|
|
64
|
+
* The on-disk shape of one bucket. `schemaVersion` is the only field a future reader may rely on before
|
|
65
|
+
* validating. Schema 3 (design/389): the five core fields plus the OPTIONAL `sync` block (observation
|
|
66
|
+
* vector + round timestamp) and `quarantined` area (rows moved out of the live view, bytes preserved).
|
|
67
|
+
* The org state is NOT here — see {@link OrgStateFile}.
|
|
60
68
|
*/
|
|
61
69
|
interface RuleFile {
|
|
62
|
-
schemaVersion:
|
|
70
|
+
schemaVersion: 3;
|
|
63
71
|
actor: string;
|
|
64
72
|
counter: number;
|
|
65
73
|
rev: number;
|
|
@@ -69,10 +77,27 @@ interface RuleFile {
|
|
|
69
77
|
observedVector?: RuleSyncFrontier;
|
|
70
78
|
lastRoundAtMs?: number;
|
|
71
79
|
};
|
|
72
|
-
org?: PersistedOrgRuleState;
|
|
73
80
|
quarantined?: QuarantinedRuleAdd[];
|
|
74
81
|
checksum: string;
|
|
75
82
|
}
|
|
83
|
+
/** The deployment-wide org state file: last-known-good snapshot + anti-rollback high-water, one blob. */
|
|
84
|
+
interface OrgStateFile {
|
|
85
|
+
schemaVersion: 1;
|
|
86
|
+
state: PersistedOrgRuleState;
|
|
87
|
+
checksum: string;
|
|
88
|
+
}
|
|
89
|
+
/** The org partition's durable home in a rule directory. */
|
|
90
|
+
export declare const ORG_STATE_FILE = "org.json";
|
|
91
|
+
/** Written once the directory is known to hold only schema-3 buckets. Its presence ends the legacy
|
|
92
|
+
* scan for good: a schema 1/2 bucket that appears AFTERWARDS (an older engine writing after the
|
|
93
|
+
* cutover) is refused by the reader on every later construction too, never re-admitted by a restart. */
|
|
94
|
+
export declare const SCHEMA3_MARKER_FILE = ".rule-schema-3";
|
|
95
|
+
/** The anti-rollback contract's DESIGNED refusal (a lower high-water mark, or different content under
|
|
96
|
+
* the same revision) — distinguished by class from every other install failure, because the two are
|
|
97
|
+
* handled in opposite directions by the migration: a refusal means the block is superseded and may be
|
|
98
|
+
* dropped; anything else means the block has no second home yet and the legacy copy must be kept. */
|
|
99
|
+
export declare class OrgRevisionRefusal extends Error {
|
|
100
|
+
}
|
|
76
101
|
/** The local-owner bucket's FIXED file name — never a principal-hash path (identity absence is a
|
|
77
102
|
* structural position, not a name; design/182 §4.5). Cannot collide with `forPrincipal` names, which
|
|
78
103
|
* are 64 hex characters. */
|
|
@@ -100,7 +125,7 @@ export declare function readRuleAdoptionFile(dir: string): RuleAdoptionFile | un
|
|
|
100
125
|
/** Atomically publish the adoption marker (same write-temp → fsync → rename discipline as the store). */
|
|
101
126
|
export declare function writeRuleAdoptionFile(dir: string, content: RuleAdoptionFile): void;
|
|
102
127
|
/** One principal's rule file. */
|
|
103
|
-
declare class
|
|
128
|
+
declare class FileDurableRulePartition implements WritableDurableRulePartition {
|
|
104
129
|
private readonly dir;
|
|
105
130
|
private readonly file;
|
|
106
131
|
private readonly acquireWriteLock;
|
|
@@ -126,12 +151,6 @@ declare class FilePermissionRuleStore implements WritablePermissionRuleStore {
|
|
|
126
151
|
list(): Promise<StoredAllowRules>;
|
|
127
152
|
/** The quarantine area (design/182 §5.2/§8.3): introspection only — never part of `list()`. */
|
|
128
153
|
quarantined(): Promise<QuarantinedRuleAdd[]>;
|
|
129
|
-
/** design/182 §7.4 — the durable org block: last-known-good snapshot + anti-rollback high-water,
|
|
130
|
-
* installed in ONE atomic publish, surviving restarts. Reading takes no lock (the gate reads);
|
|
131
|
-
* installing takes the writer lock (it is a write) but does not move `rev` — nothing about the
|
|
132
|
-
* PERSONAL rule set changed, and an OCC holder must not be disturbed (the `nextDot` precedent). */
|
|
133
|
-
readOrgState(): Promise<PersistedOrgRuleState | undefined>;
|
|
134
|
-
installOrgState(state: PersistedOrgRuleState): Promise<void>;
|
|
135
154
|
/**
|
|
136
155
|
* The current file, for a WRITE.
|
|
137
156
|
*
|
|
@@ -180,17 +199,38 @@ declare class FilePermissionRuleStore implements WritablePermissionRuleStore {
|
|
|
180
199
|
* provider without a `dataRoot` precisely because it runs while the marker is in flight, and the
|
|
181
200
|
* bucket-level marker (read in `forPrincipal`/`forLocalOwner`) is what governs writes inside that arc.
|
|
182
201
|
*/
|
|
183
|
-
export declare class
|
|
202
|
+
export declare class FileDurableRulePartitionProvider implements DurableRulePartitionProvider {
|
|
184
203
|
private readonly dir;
|
|
185
204
|
private readonly onError?;
|
|
186
205
|
private lock;
|
|
206
|
+
private orgPersistence;
|
|
187
207
|
constructor(dir: string, onError?: ((message: string) => void) | undefined, opts?: {
|
|
188
208
|
/** The data root whose adoption marker gates construction (design/183 I6). Absent ⇒ no root gate. */
|
|
189
209
|
dataRoot?: string;
|
|
190
210
|
});
|
|
211
|
+
/**
|
|
212
|
+
* Fold every legacy bucket file in `dir` into schema 3 and its `org` block into `org.json`. A no-op on a
|
|
213
|
+
* directory with no legacy file (zero writes, the lock untouched — the second construction over a
|
|
214
|
+
* migrated directory is byte-silent). A legacy file whose checksum or shape does not hold is NOT
|
|
215
|
+
* migrated: its bytes stay where they are for a person to look at, and the reader keeps refusing it
|
|
216
|
+
* whole. A live writer holding the directory (an older engine still running over it, or a directory
|
|
217
|
+
* this process cannot write) DEFERS the migration: the construction succeeds as a read face, the
|
|
218
|
+
* deferral is disclosed, and the marker stays unwritten so the next construction that can take the
|
|
219
|
+
* lock performs the cutover. Two engine versions writing one rule directory is still not a supported
|
|
220
|
+
* shape — the old engine's buckets are refused whole until they are migrated.
|
|
221
|
+
*/
|
|
222
|
+
private migrateLegacyBuckets;
|
|
223
|
+
/** Publish the schema-3 completion marker (idempotent, atomic, no lock: its content never changes and
|
|
224
|
+
* a concurrent writer of the same bytes is harmless). A failure to write it is disclosed, not thrown —
|
|
225
|
+
* the next construction simply scans again, which is the safe direction. */
|
|
226
|
+
private writeSchema3Marker;
|
|
227
|
+
/** The org partition's durable home in this directory (design/182 §7.4 contract; `org.json`). Shares
|
|
228
|
+
* this provider's writer lock — an install is a write. */
|
|
229
|
+
orgStatePersistence(): OrgRuleStatePersistence;
|
|
230
|
+
private fileOrgPersistence;
|
|
191
231
|
/** Take the writer lock, once, on first use of a write face. Reading never calls this. */
|
|
192
232
|
private acquireWriteLock;
|
|
193
|
-
forPrincipal(principal: string | undefined):
|
|
233
|
+
forPrincipal(principal: string | undefined): DurableRulePartition;
|
|
194
234
|
/** The read-only resolution of an adoption SOURCE: post-flip (phase ≥ 4 / terminal) always the
|
|
195
235
|
* target; pre-flip, whichever path currently holds the bytes (source first — it is the pre-flip
|
|
196
236
|
* truth when both somehow exist, which the resume path refuses loudly anyway). */
|
|
@@ -202,7 +242,7 @@ export declare class FilePermissionRuleStoreProvider implements PermissionRuleSt
|
|
|
202
242
|
* reads, not the other way round, so a crash between marker and host-config change cannot fork writes
|
|
203
243
|
* into a retired bucket. A corrupt marker throws (fail-closed) rather than guessing an owner.
|
|
204
244
|
*/
|
|
205
|
-
forLocalOwner():
|
|
245
|
+
forLocalOwner(): DurableRulePartition;
|
|
206
246
|
/** Release the writer lock. A long-lived deployment holds it for its lifetime; a test or a short-lived
|
|
207
247
|
* tool releases so the next holder is not told a live process owns the directory. */
|
|
208
248
|
dispose(): void;
|
|
@@ -211,4 +251,4 @@ export declare class FilePermissionRuleStoreProvider implements PermissionRuleSt
|
|
|
211
251
|
* and the resolver can never disagree about where a principal lives. */
|
|
212
252
|
export declare function principalRuleFileName(principal: string): string;
|
|
213
253
|
export { LOCAL_OWNER_FILE };
|
|
214
|
-
export type {
|
|
254
|
+
export type { FileDurableRulePartition, RuleFile, OrgStateFile };
|