@mnemom/mnemom 0.17.34-next.1 → 0.17.34-next.2
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/base-url-proxy.mjs +18 -4
- package/dist/commands/agent-config.js +5 -1
- package/dist/commands/agent-doctor.d.ts +9 -0
- package/dist/commands/agent-doctor.js +4 -0
- package/dist/commands/agent-session.d.ts +1 -2
- package/dist/commands/agent-session.js +1 -2
- package/dist/commands/agent-setup.d.ts +6 -0
- package/dist/commands/agent-setup.js +12 -1
- package/dist/commands/agent.d.ts +11 -0
- package/dist/commands/agent.js +145 -46
- package/dist/commands/durable-doctor.d.ts +50 -0
- package/dist/commands/durable-doctor.js +186 -0
- package/dist/commands/durable-lock.d.ts +254 -0
- package/dist/commands/durable-lock.js +595 -0
- package/dist/commands/durable-sessions.d.ts +87 -0
- package/dist/commands/durable-sessions.js +303 -0
- package/dist/commands/durable-verbs.d.ts +116 -0
- package/dist/commands/durable-verbs.js +393 -0
- package/dist/durable/flock.d.ts +26 -0
- package/dist/durable/flock.js +80 -0
- package/dist/durable/launch-spec.d.ts +7 -1
- package/dist/durable/launch-spec.js +10 -3
- package/dist/durable/seat-proxy-entry.d.ts +11 -0
- package/dist/durable/seat-proxy-entry.js +25 -0
- package/dist/durable/seat-proxy.d.ts +107 -0
- package/dist/durable/seat-proxy.js +599 -0
- package/dist/durable/seat-socket.d.ts +46 -0
- package/dist/durable/seat-socket.js +179 -0
- package/dist/durable/seat-spec-validator.d.ts +28 -0
- package/dist/durable/seat-spec-validator.js +59 -0
- package/dist/durable/test-mode.mjs +81 -0
- package/dist/durable/turn-chain.d.ts +55 -0
- package/dist/durable/turn-chain.js +178 -0
- package/dist/host/auto-continue.d.ts +67 -0
- package/dist/host/auto-continue.js +118 -0
- package/dist/host/bootid.d.ts +13 -0
- package/dist/host/bootid.js +41 -0
- package/dist/host/client.d.ts +123 -0
- package/dist/host/client.js +171 -0
- package/dist/host/commands.d.ts +2 -0
- package/dist/host/commands.js +122 -0
- package/dist/host/control.d.ts +33 -0
- package/dist/host/control.js +144 -0
- package/dist/host/daemon.d.ts +217 -0
- package/dist/host/daemon.js +606 -0
- package/dist/host/gate.d.ts +46 -0
- package/dist/host/gate.js +82 -0
- package/dist/host/grant.d.ts +24 -0
- package/dist/host/grant.js +24 -0
- package/dist/host/instance.d.ts +35 -0
- package/dist/host/instance.js +62 -0
- package/dist/host/integrity.d.ts +35 -0
- package/dist/host/integrity.js +115 -0
- package/dist/host/launchd.d.ts +16 -0
- package/dist/host/launchd.js +45 -0
- package/dist/host/lock.d.ts +20 -0
- package/dist/host/lock.js +63 -0
- package/dist/host/owner.d.ts +55 -0
- package/dist/host/owner.js +121 -0
- package/dist/host/plist.d.ts +16 -0
- package/dist/host/plist.js +85 -0
- package/dist/host/procs.d.ts +27 -0
- package/dist/host/procs.js +105 -0
- package/dist/host/run.d.ts +66 -0
- package/dist/host/run.js +314 -0
- package/dist/host/runtime.d.ts +8 -0
- package/dist/host/runtime.js +22 -0
- package/dist/host/s1-names.d.ts +22 -0
- package/dist/host/s1-names.js +21 -0
- package/dist/host/seat-credential.d.ts +27 -0
- package/dist/host/seat-credential.js +41 -0
- package/dist/host/seat-launch-main.d.ts +1 -0
- package/dist/host/seat-launch-main.js +59 -0
- package/dist/host/seat-launch.d.ts +116 -0
- package/dist/host/seat-launch.js +302 -0
- package/dist/host/seat.d.ts +48 -0
- package/dist/host/seat.js +149 -0
- package/dist/host/state.d.ts +33 -0
- package/dist/host/state.js +117 -0
- package/dist/host/status.d.ts +101 -0
- package/dist/host/status.js +307 -0
- package/dist/host/tmux.d.ts +56 -0
- package/dist/host/tmux.js +182 -0
- package/dist/host/transcript.d.ts +30 -0
- package/dist/host/transcript.js +130 -0
- package/dist/host/verbs.d.ts +50 -0
- package/dist/host/verbs.js +271 -0
- package/dist/index.d.ts +8 -6
- package/dist/index.js +197 -35
- package/dist/lib/agent.d.ts +8 -26
- package/dist/lib/agent.js +11 -26
- package/dist/lib/claude-plugin.d.ts +11 -2
- package/dist/lib/claude-plugin.js +10 -1
- package/dist/lib/durable/api.d.ts +136 -0
- package/dist/lib/durable/api.js +220 -0
- package/dist/lib/durable/codes.d.ts +8 -0
- package/dist/lib/durable/codes.js +2 -0
- package/dist/lib/durable/first-turn.d.ts +50 -0
- package/dist/lib/durable/first-turn.js +102 -0
- package/dist/lib/durable/gate.d.ts +48 -0
- package/dist/lib/durable/gate.js +122 -0
- package/dist/lib/durable/handover.d.ts +101 -0
- package/dist/lib/durable/handover.js +175 -0
- package/dist/lib/durable/launch.d.ts +182 -0
- package/dist/lib/durable/launch.js +443 -0
- package/dist/lib/durable/launching.d.ts +15 -0
- package/dist/lib/durable/launching.js +70 -0
- package/dist/lib/durable/live.d.ts +194 -0
- package/dist/lib/durable/live.js +635 -0
- package/dist/lib/durable/refusal.d.ts +57 -0
- package/dist/lib/durable/refusal.js +78 -0
- package/dist/lib/durable/view.d.ts +83 -0
- package/dist/lib/durable/view.js +244 -0
- package/dist/lib/experimental.d.ts +0 -9
- package/dist/lib/experimental.js +18 -17
- package/dist/lib/launcher-config.d.ts +7 -0
- package/dist/lib/launcher-config.js +21 -0
- package/dist/lib/scan/report-email.d.ts +1 -1
- package/dist/lib/scan/report-email.js +9 -1
- package/dist/lib/subscription-login.d.ts +15 -0
- package/dist/lib/subscription-login.js +28 -1
- package/dist/vendor/durable-contract/index.js +240 -18
- package/dist/vendor/shared/durable-contract/admission.d.ts +240 -0
- package/dist/vendor/shared/durable-contract/admission.js +533 -0
- package/dist/vendor/shared/durable-contract/arm.d.ts +51 -0
- package/dist/vendor/shared/durable-contract/arm.js +133 -0
- package/dist/vendor/shared/durable-contract/canonical.d.ts +29 -0
- package/dist/vendor/shared/durable-contract/canonical.js +98 -0
- package/dist/vendor/shared/durable-contract/cell-id.d.ts +22 -0
- package/dist/vendor/shared/durable-contract/cell-id.js +38 -0
- package/dist/vendor/shared/durable-contract/cli-output.d.ts +342 -0
- package/dist/vendor/shared/durable-contract/cli-output.js +201 -0
- package/dist/vendor/shared/durable-contract/cli-surface.d.ts +119 -0
- package/dist/vendor/shared/durable-contract/cli-surface.js +270 -0
- package/dist/vendor/shared/durable-contract/codes.d.ts +537 -0
- package/dist/vendor/shared/durable-contract/codes.js +475 -0
- package/dist/vendor/shared/durable-contract/constants.d.ts +153 -0
- package/dist/vendor/shared/durable-contract/constants.js +179 -0
- package/dist/vendor/shared/durable-contract/doors.d.ts +119 -0
- package/dist/vendor/shared/durable-contract/doors.js +249 -0
- package/dist/vendor/shared/durable-contract/envelope.d.ts +103 -0
- package/dist/vendor/shared/durable-contract/envelope.js +317 -0
- package/dist/vendor/shared/durable-contract/events.d.ts +147 -0
- package/dist/vendor/shared/durable-contract/events.js +630 -0
- package/dist/vendor/shared/durable-contract/executor-state.d.ts +41 -0
- package/dist/vendor/shared/durable-contract/executor-state.js +32 -0
- package/dist/vendor/shared/durable-contract/fixlines.d.ts +318 -0
- package/dist/vendor/shared/durable-contract/fixlines.js +483 -0
- package/dist/vendor/shared/durable-contract/freeze-record.d.ts +787 -0
- package/dist/vendor/shared/durable-contract/freeze-record.js +361 -0
- package/dist/vendor/shared/durable-contract/index.d.ts +36 -0
- package/dist/vendor/shared/durable-contract/index.js +37 -0
- package/dist/vendor/shared/durable-contract/journal-approvals.d.ts +29 -0
- package/dist/vendor/shared/durable-contract/journal-approvals.js +60 -0
- package/dist/vendor/shared/durable-contract/keys.d.ts +24 -0
- package/dist/vendor/shared/durable-contract/keys.js +66 -0
- package/dist/vendor/shared/durable-contract/lock.d.ts +128 -0
- package/dist/vendor/shared/durable-contract/lock.js +151 -0
- package/dist/vendor/shared/durable-contract/names.d.ts +25 -0
- package/dist/vendor/shared/durable-contract/names.js +78 -0
- package/dist/vendor/shared/durable-contract/owner-verbs.d.ts +175 -0
- package/dist/vendor/shared/durable-contract/owner-verbs.js +403 -0
- package/dist/vendor/shared/durable-contract/paths.d.ts +23 -0
- package/dist/vendor/shared/durable-contract/paths.js +35 -0
- package/dist/vendor/shared/durable-contract/pure-fn.d.ts +48 -0
- package/dist/vendor/shared/durable-contract/pure-fn.js +89 -0
- package/dist/vendor/shared/durable-contract/routes.d.ts +205 -0
- package/dist/vendor/shared/durable-contract/routes.js +315 -0
- package/dist/vendor/shared/durable-contract/schema.d.ts +126 -0
- package/dist/vendor/shared/durable-contract/schema.js +441 -0
- package/dist/vendor/shared/durable-contract/seal.d.ts +54 -0
- package/dist/vendor/shared/durable-contract/seal.js +99 -0
- package/dist/vendor/shared/durable-contract/secret-scope.d.ts +28 -0
- package/dist/vendor/shared/durable-contract/secret-scope.js +76 -0
- package/dist/vendor/shared/durable-contract/session-id.d.ts +21 -0
- package/dist/vendor/shared/durable-contract/session-id.js +58 -0
- package/dist/vendor/shared/durable-contract/spec.d.ts +162 -0
- package/dist/vendor/shared/durable-contract/spec.js +286 -0
- package/dist/vendor/shared/durable-contract/states.d.ts +96 -0
- package/dist/vendor/shared/durable-contract/states.js +218 -0
- package/dist/vendor/shared/durable-contract/telemetry.d.ts +94 -0
- package/dist/vendor/shared/durable-contract/telemetry.js +180 -0
- package/dist/vendor/shared/durable-contract/test-mode.d.ts +62 -0
- package/dist/vendor/shared/durable-contract/test-mode.js +140 -0
- package/dist/vendor/shared/durable-contract/turn.d.ts +57 -0
- package/dist/vendor/shared/durable-contract/turn.js +81 -0
- package/dist/vendor/shared/durable-contract/vectors.d.ts +191 -0
- package/dist/vendor/shared/durable-contract/vectors.js +208 -0
- package/package.json +3 -2
- package/plugins/integrity-manifest.json +35 -0
- package/plugins/mnemom/hooks/hooks.json +15 -1
- package/plugins/mnemom/hooks/register.tsx +60 -2
- package/plugins/mnemom/hooks/seat-hello.mjs +116 -0
- package/dist/commands/agent-implicit-notice.d.ts +0 -31
- package/dist/commands/agent-implicit-notice.js +0 -73
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
// GENERATED from shared/durable-contract/src/schema.ts by cli/scripts/sync-durable-contract.mjs; do not edit.
|
|
2
|
+
/**
|
|
3
|
+
* The M1 database catalogue S1 freezes for A1 and for the C17 catalog oracle (C17-R23..R27;
|
|
4
|
+
* BACKBONE A1; design §3.3). A1 implements exactly this; a needed difference is an S1 amendment.
|
|
5
|
+
*
|
|
6
|
+
* Column decisions beyond design §3.3 (whose lists end in "…"):
|
|
7
|
+
* - agent_sessions.cwd: the registered worktree root (the idle builder source reads it);
|
|
8
|
+
* - agent_sessions.spawn_id / hello_at: the current epoch's registered spawn and its accepted
|
|
9
|
+
* hello (heartbeat revival and durable_seat_exit test them in one row read);
|
|
10
|
+
* - durable_lease_keys.agent_id / org_id: attribution at the source (C14-R14);
|
|
11
|
+
* - agent_executors.label: the machine label `show` and `session_homed_elsewhere` print;
|
|
12
|
+
* - agent_session_events.principal_ref (C10-R0 (d)) and durable_event_kinds.writer (C10-R0 (e));
|
|
13
|
+
* - durable_approvals.subject / requested_by: the owner_mutation subject kind and requester.
|
|
14
|
+
*
|
|
15
|
+
* Doors amendment columns (rulings 34.03, 34.06, 34.10), each appended to its table:
|
|
16
|
+
* - agent_sessions.wait_ref (JSONB, NULL unless wait_reason is a PARKED_ONLY_WAIT_REASONS value);
|
|
17
|
+
* - agent_executors.scope (TEXT NOT NULL DEFAULT 'user', EXECUTOR_SCOPES);
|
|
18
|
+
* - durable_org_policy.dispatch_agent_id (nullable FK agents, same org).
|
|
19
|
+
*
|
|
20
|
+
* Amendment 54 (signed off by Wassim 2026-10-29; ruling B5a as amended, 1a + 2a), appended to its table:
|
|
21
|
+
* - agent_sessions.new_session (BOOLEAN NOT NULL DEFAULT false): true only on a row that
|
|
22
|
+
* create-and-lock inserted (`--new` under durable=always on a durable-only agent, one
|
|
23
|
+
* transaction with the lock); a plain lock never sets it. The executor learns it only from the
|
|
24
|
+
* claim success answer (`new_session: true`, while no seat hello was ever accepted for the
|
|
25
|
+
* session); EXEC_SESSIONS_RESPONSE item keys are unchanged.
|
|
26
|
+
*/
|
|
27
|
+
import { canonicalJson, sha256Hex, UUID_RE } from "./canonical.js";
|
|
28
|
+
import { CANONICAL_CELL_IDS } from "./cell-id.js";
|
|
29
|
+
import { LEASE_SECONDS_DEFAULT, RESUME_RESET_SECONDS_DEFAULT } from "./constants.js";
|
|
30
|
+
import { PARKED_ONLY_WAIT_REASONS } from "./states.js";
|
|
31
|
+
export const M1_TABLES = [
|
|
32
|
+
"agent_sessions",
|
|
33
|
+
"durable_lease_keys",
|
|
34
|
+
"agent_session_charters",
|
|
35
|
+
"agent_session_events",
|
|
36
|
+
"durable_event_kinds",
|
|
37
|
+
"agent_session_chains",
|
|
38
|
+
"agent_executors",
|
|
39
|
+
"agent_durable_profiles",
|
|
40
|
+
"durable_cell_state",
|
|
41
|
+
"durable_org_policy",
|
|
42
|
+
"durable_user_policy",
|
|
43
|
+
"durable_approvals",
|
|
44
|
+
"durable_approval_attestations",
|
|
45
|
+
];
|
|
46
|
+
export const M1_COLUMNS = {
|
|
47
|
+
agent_sessions: [
|
|
48
|
+
"id",
|
|
49
|
+
"agent_id",
|
|
50
|
+
"org_id",
|
|
51
|
+
"conversation_id",
|
|
52
|
+
"aip_session_id",
|
|
53
|
+
"name",
|
|
54
|
+
"created_by",
|
|
55
|
+
"durable_mode",
|
|
56
|
+
"state",
|
|
57
|
+
"state_reason",
|
|
58
|
+
"wait_reason",
|
|
59
|
+
"resume_failures",
|
|
60
|
+
"running_since",
|
|
61
|
+
"home_cell",
|
|
62
|
+
"home_executor_id",
|
|
63
|
+
"profile_id",
|
|
64
|
+
"profile_version",
|
|
65
|
+
"charter_hash",
|
|
66
|
+
"cwd",
|
|
67
|
+
"lease_executor_id",
|
|
68
|
+
"attach_until",
|
|
69
|
+
"lease_epoch",
|
|
70
|
+
"lease_nonce",
|
|
71
|
+
"lease_expires_at",
|
|
72
|
+
"spawn_id",
|
|
73
|
+
"hello_at",
|
|
74
|
+
"outage_mode",
|
|
75
|
+
"outage_bound_s",
|
|
76
|
+
"outage_set_by",
|
|
77
|
+
"cc_session_id",
|
|
78
|
+
"guard_state",
|
|
79
|
+
"hmac_salt",
|
|
80
|
+
"journal_tip_hash",
|
|
81
|
+
"journal_tip_seq",
|
|
82
|
+
"expires_at",
|
|
83
|
+
"created_at",
|
|
84
|
+
"updated_at",
|
|
85
|
+
"wait_ref",
|
|
86
|
+
"new_session",
|
|
87
|
+
],
|
|
88
|
+
durable_lease_keys: [
|
|
89
|
+
"key_hash",
|
|
90
|
+
"session_id",
|
|
91
|
+
"agent_id",
|
|
92
|
+
"org_id",
|
|
93
|
+
"epoch",
|
|
94
|
+
"revoked_at",
|
|
95
|
+
"last_used_at",
|
|
96
|
+
"created_at",
|
|
97
|
+
],
|
|
98
|
+
agent_session_charters: [
|
|
99
|
+
"session_id",
|
|
100
|
+
"version",
|
|
101
|
+
"hash",
|
|
102
|
+
"prev_hash",
|
|
103
|
+
"charter",
|
|
104
|
+
"contract_ciphertext",
|
|
105
|
+
"wrapped_data_key",
|
|
106
|
+
"cipher_key_ref",
|
|
107
|
+
"contract_purge_after",
|
|
108
|
+
"signature",
|
|
109
|
+
"created_at",
|
|
110
|
+
],
|
|
111
|
+
agent_session_events: [
|
|
112
|
+
"session_id",
|
|
113
|
+
"seq",
|
|
114
|
+
"ts",
|
|
115
|
+
"kind",
|
|
116
|
+
"principal_uid",
|
|
117
|
+
"principal_ref",
|
|
118
|
+
"epoch",
|
|
119
|
+
"idempotency_key",
|
|
120
|
+
"detail",
|
|
121
|
+
"detail_sha256",
|
|
122
|
+
"refs",
|
|
123
|
+
"refs_sha256",
|
|
124
|
+
"prev_hash",
|
|
125
|
+
"hash",
|
|
126
|
+
],
|
|
127
|
+
durable_event_kinds: ["kind", "grp", "writer", "refs_schema", "added_at"],
|
|
128
|
+
agent_session_chains: ["session_id", "chain_id", "posture", "decided_at"],
|
|
129
|
+
agent_executors: [
|
|
130
|
+
"id",
|
|
131
|
+
"org_id",
|
|
132
|
+
"owner_user_id",
|
|
133
|
+
"kind",
|
|
134
|
+
"key_id",
|
|
135
|
+
"label",
|
|
136
|
+
"runtime",
|
|
137
|
+
"contract_version",
|
|
138
|
+
"grant_expires_at",
|
|
139
|
+
"age_recipient",
|
|
140
|
+
"heartbeat_data",
|
|
141
|
+
"revoked_at",
|
|
142
|
+
"breakglass_at",
|
|
143
|
+
"last_seen_at",
|
|
144
|
+
"risk_line_version",
|
|
145
|
+
"created_at",
|
|
146
|
+
"scope",
|
|
147
|
+
],
|
|
148
|
+
agent_durable_profiles: [
|
|
149
|
+
"id",
|
|
150
|
+
"org_id",
|
|
151
|
+
"owner_user_id",
|
|
152
|
+
"name",
|
|
153
|
+
"version",
|
|
154
|
+
"hash",
|
|
155
|
+
"body",
|
|
156
|
+
"created_at",
|
|
157
|
+
],
|
|
158
|
+
durable_cell_state: [
|
|
159
|
+
"cell_id",
|
|
160
|
+
"cell_generation",
|
|
161
|
+
"unattended_enabled",
|
|
162
|
+
"lease_seconds",
|
|
163
|
+
"resume_reset_seconds",
|
|
164
|
+
],
|
|
165
|
+
durable_org_policy: [
|
|
166
|
+
"org_id",
|
|
167
|
+
"host_unattended",
|
|
168
|
+
"outage_bound_max_s",
|
|
169
|
+
"limits",
|
|
170
|
+
"executor_kinds",
|
|
171
|
+
"updated_by",
|
|
172
|
+
"updated_at",
|
|
173
|
+
"dispatch_agent_id",
|
|
174
|
+
],
|
|
175
|
+
durable_user_policy: ["org_id", "user_id", "host_unattended_off"],
|
|
176
|
+
durable_approvals: [
|
|
177
|
+
"id",
|
|
178
|
+
"org_id",
|
|
179
|
+
"session_id",
|
|
180
|
+
"kind",
|
|
181
|
+
"subject",
|
|
182
|
+
"subject_hash",
|
|
183
|
+
"subject_ciphertext",
|
|
184
|
+
"question_ciphertext",
|
|
185
|
+
"cipher_key_ref",
|
|
186
|
+
"redaction_version",
|
|
187
|
+
"gateway_witness",
|
|
188
|
+
"requested_by",
|
|
189
|
+
"state",
|
|
190
|
+
"consumed_at",
|
|
191
|
+
"expires_at",
|
|
192
|
+
"created_at",
|
|
193
|
+
],
|
|
194
|
+
durable_approval_attestations: [
|
|
195
|
+
"approval_id",
|
|
196
|
+
"principal_uid",
|
|
197
|
+
"decision",
|
|
198
|
+
"via",
|
|
199
|
+
"assurance",
|
|
200
|
+
"external_actor",
|
|
201
|
+
"trust_root_id",
|
|
202
|
+
"notary_jws",
|
|
203
|
+
"created_at",
|
|
204
|
+
],
|
|
205
|
+
};
|
|
206
|
+
/** Columns no anon/authenticated column-level grant may reach (C17-R27, C17-M44). */
|
|
207
|
+
export const CIPHERTEXT_COLUMNS = [
|
|
208
|
+
["agent_session_charters", "contract_ciphertext"],
|
|
209
|
+
["agent_session_charters", "wrapped_data_key"],
|
|
210
|
+
];
|
|
211
|
+
/** Columns that must NOT exist (dropped seams, cut items). */
|
|
212
|
+
export const FORBIDDEN_COLUMNS = [["durable_cell_state", "test_barriers_enabled"]];
|
|
213
|
+
const TERMINAL_ARRAY = "ARRAY['completed'::text, 'failed'::text, 'killed'::text, 'expired'::text]";
|
|
214
|
+
/** Every unique index an M1 ON CONFLICT relies on (C17-R24). */
|
|
215
|
+
export const M1_ARBITERS = [
|
|
216
|
+
{
|
|
217
|
+
name: "agent_sessions_live_name_key",
|
|
218
|
+
table: "agent_sessions",
|
|
219
|
+
columns: ["org_id", "created_by", "name"],
|
|
220
|
+
nullsNotDistinct: true,
|
|
221
|
+
where: `(state <> ALL (${TERMINAL_ARRAY}))`,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: "agent_sessions_agent_conversation_key",
|
|
225
|
+
table: "agent_sessions",
|
|
226
|
+
columns: ["agent_id", "conversation_id"],
|
|
227
|
+
nullsNotDistinct: false,
|
|
228
|
+
where: null,
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
name: "agent_session_events_idempotency_key",
|
|
232
|
+
table: "agent_session_events",
|
|
233
|
+
columns: ["session_id", "idempotency_key"],
|
|
234
|
+
nullsNotDistinct: false,
|
|
235
|
+
where: null,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: "agent_session_events_seq_key",
|
|
239
|
+
table: "agent_session_events",
|
|
240
|
+
columns: ["session_id", "seq"],
|
|
241
|
+
nullsNotDistinct: false,
|
|
242
|
+
where: null,
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
name: "agent_session_chains_chain_key",
|
|
246
|
+
table: "agent_session_chains",
|
|
247
|
+
columns: ["session_id", "chain_id"],
|
|
248
|
+
nullsNotDistinct: false,
|
|
249
|
+
where: null,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "agent_session_charters_version_key",
|
|
253
|
+
table: "agent_session_charters",
|
|
254
|
+
columns: ["session_id", "version"],
|
|
255
|
+
nullsNotDistinct: false,
|
|
256
|
+
where: null,
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
name: "durable_approvals_open_key",
|
|
260
|
+
table: "durable_approvals",
|
|
261
|
+
columns: ["org_id", "session_id", "kind", "subject_hash"],
|
|
262
|
+
nullsNotDistinct: true,
|
|
263
|
+
where: "(state = 'open'::text)",
|
|
264
|
+
},
|
|
265
|
+
];
|
|
266
|
+
/** The indexdef pg_get_indexdef prints for an arbiter (public schema, btree). */
|
|
267
|
+
export function arbiterIndexDef(a) {
|
|
268
|
+
const nnd = a.nullsNotDistinct ? " NULLS NOT DISTINCT" : "";
|
|
269
|
+
const where = a.where === null ? "" : ` WHERE ${a.where}`;
|
|
270
|
+
return `CREATE UNIQUE INDEX ${a.name} ON public.${a.table} USING btree (${a.columns.join(", ")})${nnd}${where}`;
|
|
271
|
+
}
|
|
272
|
+
export const M1_FUNCTIONS = [
|
|
273
|
+
"resolve_durable_session_key",
|
|
274
|
+
"agent_durable_only",
|
|
275
|
+
"durable_schema_version",
|
|
276
|
+
"durable_attest_begin",
|
|
277
|
+
"durable_claim_lease",
|
|
278
|
+
"durable_heartbeat",
|
|
279
|
+
"durable_seat_hello",
|
|
280
|
+
"durable_seat_exit",
|
|
281
|
+
"durable_fail_session",
|
|
282
|
+
"durable_release_lease",
|
|
283
|
+
"durable_append_event",
|
|
284
|
+
"durable_fence_check",
|
|
285
|
+
"durable_guard_add",
|
|
286
|
+
"durable_revoke_executor",
|
|
287
|
+
"durable_sweep",
|
|
288
|
+
"durable_kill_agent_sessions",
|
|
289
|
+
"durable_agent_killed",
|
|
290
|
+
];
|
|
291
|
+
/** Functions keeping EXECUTE for PUBLIC/anon/authenticated: none in M1. */
|
|
292
|
+
export const EXECUTE_EXCEPTIONS = [];
|
|
293
|
+
export const M1_TRIGGERS = [
|
|
294
|
+
{ name: "durable_agent_killed", table: "agents", fn: "durable_agent_killed" },
|
|
295
|
+
];
|
|
296
|
+
/** Not in M1: must be absent from the catalog. */
|
|
297
|
+
export const ABSENT_FUNCTIONS_M1 = [
|
|
298
|
+
"durable_assert_attach",
|
|
299
|
+
"durable_set_org_policy",
|
|
300
|
+
"durable_test_barrier",
|
|
301
|
+
];
|
|
302
|
+
/** Down migrations refuse while any of these has rows. */
|
|
303
|
+
export const LEDGER_TABLES = [
|
|
304
|
+
"agent_sessions",
|
|
305
|
+
"agent_session_events",
|
|
306
|
+
"agent_session_charters",
|
|
307
|
+
"durable_approvals",
|
|
308
|
+
"durable_approval_attestations",
|
|
309
|
+
"agent_executors",
|
|
310
|
+
];
|
|
311
|
+
export const MIGRATION_LOCK_TIMEOUT = "3s";
|
|
312
|
+
/** The durable_cell_state seed: exactly one row per canonical cell id. */
|
|
313
|
+
export function cellSeedRows() {
|
|
314
|
+
return CANONICAL_CELL_IDS.map((cell_id) => ({
|
|
315
|
+
cell_id,
|
|
316
|
+
cell_generation: 0,
|
|
317
|
+
unattended_enabled: false,
|
|
318
|
+
lease_seconds: LEASE_SECONDS_DEFAULT,
|
|
319
|
+
resume_reset_seconds: RESUME_RESET_SECONDS_DEFAULT,
|
|
320
|
+
}));
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* durable_approvals.subject (kind owner_mutation) and its target rule (ruling 32.12). An enrollment
|
|
324
|
+
* approval is a row with subject 'enrollment' and a NULL session_id, scoped by org_id and
|
|
325
|
+
* requested_by; a grant_renewal names its executor inside the subject. Every other subject names a
|
|
326
|
+
* session, question included (ruling 34.06.1.1: the question wait's approval, appended). A1
|
|
327
|
+
* mirrors both CHECKs. The journal's approval.requested refs enum does not gain
|
|
328
|
+
* 'enrollment' (events.ts): executor.enrolled is journaled into no session (C10-R0(f)).
|
|
329
|
+
*/
|
|
330
|
+
export const DURABLE_APPROVAL_SUBJECTS = [
|
|
331
|
+
"unlock",
|
|
332
|
+
"unpause_contained",
|
|
333
|
+
"grant_renewal",
|
|
334
|
+
"budget_raise",
|
|
335
|
+
"enrollment",
|
|
336
|
+
"question",
|
|
337
|
+
];
|
|
338
|
+
/** Subjects whose row may carry a NULL session_id. */
|
|
339
|
+
export const DURABLE_APPROVAL_SESSIONLESS_SUBJECTS = [
|
|
340
|
+
"grant_renewal",
|
|
341
|
+
"enrollment",
|
|
342
|
+
];
|
|
343
|
+
const sqlList = (xs) => xs.map((x) => `'${x}'`).join(",");
|
|
344
|
+
export const DURABLE_APPROVALS_SUBJECT_CHECK = `subject IN (${sqlList(DURABLE_APPROVAL_SUBJECTS)})`;
|
|
345
|
+
export const DURABLE_APPROVALS_TARGET_CHECK = `subject IN (${sqlList(DURABLE_APPROVAL_SESSIONLESS_SUBJECTS)}) OR session_id IS NOT NULL`;
|
|
346
|
+
/** The target CHECK as a predicate. */
|
|
347
|
+
export function approvalTargetOk(subject, sessionId) {
|
|
348
|
+
return (DURABLE_APPROVAL_SESSIONLESS_SUBJECTS.includes(subject) ||
|
|
349
|
+
sessionId !== null);
|
|
350
|
+
}
|
|
351
|
+
/** The enrollment subject's risk_line_version: decimal text, never a number (ruling 32.30). */
|
|
352
|
+
export const RISK_LINE_VERSION_TEXT_RE = /^[1-9][0-9]{0,31}$/;
|
|
353
|
+
const nonEmpty = (v) => typeof v === "string" && v.length > 0;
|
|
354
|
+
const uuid = (v) => typeof v === "string" && UUID_RE.test(v);
|
|
355
|
+
const riskLineVersion = (v) => typeof v === "string" && RISK_LINE_VERSION_TEXT_RE.test(v);
|
|
356
|
+
const SESSION_SUBJECT = { session_id: uuid };
|
|
357
|
+
/** The closed subject shapes (besides `subject` itself), one per subject (ruling 32.12). */
|
|
358
|
+
const SUBJECT_SHAPES = {
|
|
359
|
+
enrollment: {
|
|
360
|
+
org_id: nonEmpty,
|
|
361
|
+
owner_user_id: nonEmpty,
|
|
362
|
+
runtime: nonEmpty,
|
|
363
|
+
risk_line_version: riskLineVersion,
|
|
364
|
+
},
|
|
365
|
+
grant_renewal: { executor_id: uuid },
|
|
366
|
+
unlock: SESSION_SUBJECT,
|
|
367
|
+
unpause_contained: SESSION_SUBJECT,
|
|
368
|
+
budget_raise: SESSION_SUBJECT,
|
|
369
|
+
// ruling 34.06.1.1: a question wait parks on an open owner_mutation approval of the
|
|
370
|
+
// parking session, so its subject names that session like the other session subjects.
|
|
371
|
+
question: SESSION_SUBJECT,
|
|
372
|
+
};
|
|
373
|
+
/** Keys a subject may carry besides its shape, each present only with the one value it allows. */
|
|
374
|
+
const OPTIONAL_SUBJECT_KEYS = {
|
|
375
|
+
enrollment: { scope: (v) => v === "org" },
|
|
376
|
+
};
|
|
377
|
+
/**
|
|
378
|
+
* durable_approvals.subject_hash: lowercase hex sha256 of canonicalJson(subject) (rulings 32.12,
|
|
379
|
+
* 32.30). Subjects: {subject: 'enrollment', org_id, owner_user_id, runtime, risk_line_version},
|
|
380
|
+
* {subject: 'grant_renewal', executor_id}, {subject, session_id} for the session subjects. Rejects
|
|
381
|
+
* with RangeError on an unknown subject, an extra or missing key, or a value of the wrong form.
|
|
382
|
+
* An enrollment subject may also carry scope: 'org' and nothing else (ruling 34.03.1), so an org
|
|
383
|
+
* enrollment commits the approver to a runner that can claim any pool session in the org; without
|
|
384
|
+
* it the subject, and its hash, are M1's byte for byte.
|
|
385
|
+
*/
|
|
386
|
+
export async function approvalSubjectHash(subject) {
|
|
387
|
+
if (subject === null || typeof subject !== "object" || Array.isArray(subject))
|
|
388
|
+
throw new RangeError("approval subject must be an object");
|
|
389
|
+
const kind = subject.subject;
|
|
390
|
+
if (typeof kind !== "string" || !Object.prototype.hasOwnProperty.call(SUBJECT_SHAPES, kind))
|
|
391
|
+
throw new RangeError(`unknown approval subject: ${String(kind)}`);
|
|
392
|
+
const shape = SUBJECT_SHAPES[kind];
|
|
393
|
+
const optional = Object.keys(OPTIONAL_SUBJECT_KEYS[kind] ?? {});
|
|
394
|
+
const keys = Object.keys(subject).filter((k) => k !== "subject" && !optional.includes(k));
|
|
395
|
+
const want = Object.keys(shape);
|
|
396
|
+
if (keys.length !== want.length || !want.every((k) => keys.includes(k)))
|
|
397
|
+
throw new RangeError(`approval subject ${kind}: keys must be exactly subject, ${want.join(", ")}`);
|
|
398
|
+
for (const k of want)
|
|
399
|
+
if (!shape[k](subject[k]))
|
|
400
|
+
throw new RangeError(`approval subject ${kind}: bad ${k}`);
|
|
401
|
+
for (const k of optional)
|
|
402
|
+
if (k in subject &&
|
|
403
|
+
!OPTIONAL_SUBJECT_KEYS[kind][k](subject[k]))
|
|
404
|
+
throw new RangeError(`approval subject ${kind}: bad ${k}`);
|
|
405
|
+
return sha256Hex(canonicalJson(subject));
|
|
406
|
+
}
|
|
407
|
+
// ---- Doors amendment CHECKs (rulings 34.02, 34.03, 34.06) ---------------------------------------
|
|
408
|
+
/**
|
|
409
|
+
* agent_sessions_ready_ck (ruling 34.02 (1), (2)): a ready row is locked, has no reason, no home and
|
|
410
|
+
* no holder. agent_sessions_state_reason_ck gains the arm `WHEN 'ready' THEN state_reason IS NULL`
|
|
411
|
+
* (STATE_REASONS.ready), and the state CHECK lists SESSION_STATES.
|
|
412
|
+
*/
|
|
413
|
+
export const AGENT_SESSIONS_READY_CHECK = "state <> 'ready' OR (durable_mode = 'locked' AND state_reason IS NULL AND home_executor_id IS NULL" +
|
|
414
|
+
" AND lease_executor_id IS NULL AND lease_expires_at IS NULL AND spawn_id IS NULL AND hello_at IS NULL)";
|
|
415
|
+
/**
|
|
416
|
+
* agent_sessions_wait_parked_ck (ruling 34.06 (1), (2)): ci, question and budget are valid only with
|
|
417
|
+
* state 'parked', and wait_ref is set exactly when wait_reason is one of them. The wait_reason
|
|
418
|
+
* CHECK lists WAIT_REASONS.
|
|
419
|
+
*/
|
|
420
|
+
export const AGENT_SESSIONS_WAIT_PARKED_CHECK = "CASE WHEN wait_reason IN ('ci','question','budget') THEN state = 'parked' AND wait_ref IS NOT NULL" +
|
|
421
|
+
" ELSE wait_ref IS NULL END";
|
|
422
|
+
/** agent_executors.scope CHECK (ruling 34.03 (1)). */
|
|
423
|
+
export const AGENT_EXECUTORS_SCOPE_CHECK = "scope IN ('user','org')";
|
|
424
|
+
/** The ready-row CHECK as a predicate over the columns it reads. */
|
|
425
|
+
export function readyRowOk(row) {
|
|
426
|
+
return (row.state !== "ready" ||
|
|
427
|
+
(row.durable_mode === "locked" &&
|
|
428
|
+
row.state_reason === null &&
|
|
429
|
+
row.home_executor_id === null &&
|
|
430
|
+
row.lease_executor_id === null &&
|
|
431
|
+
row.lease_expires_at === null &&
|
|
432
|
+
row.spawn_id === null &&
|
|
433
|
+
row.hello_at === null));
|
|
434
|
+
}
|
|
435
|
+
/** The wait-parked CHECK as a predicate. */
|
|
436
|
+
export function waitParkedRowOk(row) {
|
|
437
|
+
return row.wait_reason !== null &&
|
|
438
|
+
PARKED_ONLY_WAIT_REASONS.includes(row.wait_reason)
|
|
439
|
+
? row.state === "parked" && row.wait_ref !== null
|
|
440
|
+
: row.wait_ref === null;
|
|
441
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The durable seal round trip (S1 amendment 55, signed off by Wassim 2026-10-29; C07-R02, R13, R14).
|
|
3
|
+
* A reloaded durable seal keeps exactly what the owner sealed.
|
|
4
|
+
*
|
|
5
|
+
* The gateway seals a goal contract (its `SealedContract`, every field below). At lock the API
|
|
6
|
+
* splits it with splitSealedContract: the text goes into the encrypted Contract (envelope.ts) and
|
|
7
|
+
* everything else into the charter commitments, including `contract_hash`, the full sha256 of the
|
|
8
|
+
* sealed contract (the gateway's 16-hex x-mnemom-contract-hash is its first 16 characters). A
|
|
9
|
+
* rehydrate rebuilds the seal with sealedContractFromCharter, which returns null unless the rebuilt
|
|
10
|
+
* contract hashes to the committed contract_hash, so a reload can never serve a different contract.
|
|
11
|
+
*
|
|
12
|
+
* Contract (ciphertext) statement, requirements, allowed_paths, forbidden_paths, goal_id,
|
|
13
|
+
* work_card, shape
|
|
14
|
+
* commitments statement_hash, requirements_hash, contract_hash, mode, budget_usd,
|
|
15
|
+
* max_turns, stall_turns, active_time_limit_s (the seal's time_limit_s)
|
|
16
|
+
*
|
|
17
|
+
* The seal's sealed_at is charter v1's created_at (charterV1CreatedAt), not a commitment.
|
|
18
|
+
*/
|
|
19
|
+
import { type CONTRACT_MODE_VALUES, type Contract } from "./envelope.js";
|
|
20
|
+
export type ContractMode = (typeof CONTRACT_MODE_VALUES)[number];
|
|
21
|
+
/** The gateway's sealed goal contract, field for field (gateway/src/goal-contract.ts SealedContract). */
|
|
22
|
+
export interface SealedGoalContract extends Contract {
|
|
23
|
+
max_turns?: number;
|
|
24
|
+
budget_usd?: number;
|
|
25
|
+
stall_turns?: number;
|
|
26
|
+
time_limit_s?: number;
|
|
27
|
+
mode?: ContractMode;
|
|
28
|
+
}
|
|
29
|
+
/** Every field the gateway hashes into a sealed contract. */
|
|
30
|
+
export declare const SEALED_CONTRACT_FIELDS: readonly ["goal_id", "statement", "requirements", "allowed_paths", "forbidden_paths", "max_turns", "budget_usd", "stall_turns", "time_limit_s", "mode", "work_card", "shape"];
|
|
31
|
+
/**
|
|
32
|
+
* The full sha256 the gateway's canonicalHash truncates: canonicalJson of the contract with `mode`
|
|
33
|
+
* omitted when it is "nudge" or absent (MNE-8199: the default never moves a legacy hash).
|
|
34
|
+
*/
|
|
35
|
+
export declare function sealedContractHash(c: SealedGoalContract): Promise<string>;
|
|
36
|
+
export interface SplitSeal {
|
|
37
|
+
contract: Contract;
|
|
38
|
+
/** The seal's commitments; the lock adds pins, tool_classes, launch_spec and the wake caps. */
|
|
39
|
+
commitments: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Split a gateway seal into the encrypted Contract and its charter commitments. Null when the seal
|
|
43
|
+
* cannot be committed exactly: an unknown field, a text field the Contract refuses, or a value the
|
|
44
|
+
* commitment schema refuses (a fractional max_turns, say). Never drops a field.
|
|
45
|
+
*/
|
|
46
|
+
export declare function splitSealedContract(seal: SealedGoalContract): Promise<SplitSeal | null>;
|
|
47
|
+
/**
|
|
48
|
+
* Rebuild the seal a charter describes from its decrypted Contract and its commitments. Null when
|
|
49
|
+
* the charter commits no contract_hash, or when the rebuilt contract does not hash to it.
|
|
50
|
+
*/
|
|
51
|
+
export declare function sealedContractFromCharter(contract: Contract, charter: Readonly<Record<string, unknown>>): Promise<{
|
|
52
|
+
contract: SealedGoalContract;
|
|
53
|
+
contract_hash: string;
|
|
54
|
+
} | null>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// GENERATED from shared/durable-contract/src/seal.ts by cli/scripts/sync-durable-contract.mjs; do not edit.
|
|
2
|
+
/**
|
|
3
|
+
* The durable seal round trip (S1 amendment 55, signed off by Wassim 2026-10-29; C07-R02, R13, R14).
|
|
4
|
+
* A reloaded durable seal keeps exactly what the owner sealed.
|
|
5
|
+
*
|
|
6
|
+
* The gateway seals a goal contract (its `SealedContract`, every field below). At lock the API
|
|
7
|
+
* splits it with splitSealedContract: the text goes into the encrypted Contract (envelope.ts) and
|
|
8
|
+
* everything else into the charter commitments, including `contract_hash`, the full sha256 of the
|
|
9
|
+
* sealed contract (the gateway's 16-hex x-mnemom-contract-hash is its first 16 characters). A
|
|
10
|
+
* rehydrate rebuilds the seal with sealedContractFromCharter, which returns null unless the rebuilt
|
|
11
|
+
* contract hashes to the committed contract_hash, so a reload can never serve a different contract.
|
|
12
|
+
*
|
|
13
|
+
* Contract (ciphertext) statement, requirements, allowed_paths, forbidden_paths, goal_id,
|
|
14
|
+
* work_card, shape
|
|
15
|
+
* commitments statement_hash, requirements_hash, contract_hash, mode, budget_usd,
|
|
16
|
+
* max_turns, stall_turns, active_time_limit_s (the seal's time_limit_s)
|
|
17
|
+
*
|
|
18
|
+
* The seal's sealed_at is charter v1's created_at (charterV1CreatedAt), not a commitment.
|
|
19
|
+
*/
|
|
20
|
+
import { canonicalJson, sha256Hex } from "./canonical.js";
|
|
21
|
+
import { isValidCommitment, parseContract, requirementsHash, statementHash, } from "./envelope.js";
|
|
22
|
+
/** Every field the gateway hashes into a sealed contract. */
|
|
23
|
+
export const SEALED_CONTRACT_FIELDS = [
|
|
24
|
+
"goal_id",
|
|
25
|
+
"statement",
|
|
26
|
+
"requirements",
|
|
27
|
+
"allowed_paths",
|
|
28
|
+
"forbidden_paths",
|
|
29
|
+
"max_turns",
|
|
30
|
+
"budget_usd",
|
|
31
|
+
"stall_turns",
|
|
32
|
+
"time_limit_s",
|
|
33
|
+
"mode",
|
|
34
|
+
"work_card",
|
|
35
|
+
"shape",
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* The full sha256 the gateway's canonicalHash truncates: canonicalJson of the contract with `mode`
|
|
39
|
+
* omitted when it is "nudge" or absent (MNE-8199: the default never moves a legacy hash).
|
|
40
|
+
*/
|
|
41
|
+
export async function sealedContractHash(c) {
|
|
42
|
+
const normalised = { ...c };
|
|
43
|
+
if ((c.mode ?? "nudge") === "nudge")
|
|
44
|
+
delete normalised.mode;
|
|
45
|
+
return sha256Hex(canonicalJson(normalised));
|
|
46
|
+
}
|
|
47
|
+
/** The commitment field each sealed ceiling is committed as. */
|
|
48
|
+
const CEILINGS = [
|
|
49
|
+
["budget_usd", "budget_usd"],
|
|
50
|
+
["max_turns", "max_turns"],
|
|
51
|
+
["stall_turns", "stall_turns"],
|
|
52
|
+
["time_limit_s", "active_time_limit_s"],
|
|
53
|
+
];
|
|
54
|
+
/**
|
|
55
|
+
* Split a gateway seal into the encrypted Contract and its charter commitments. Null when the seal
|
|
56
|
+
* cannot be committed exactly: an unknown field, a text field the Contract refuses, or a value the
|
|
57
|
+
* commitment schema refuses (a fractional max_turns, say). Never drops a field.
|
|
58
|
+
*/
|
|
59
|
+
export async function splitSealedContract(seal) {
|
|
60
|
+
const known = SEALED_CONTRACT_FIELDS;
|
|
61
|
+
if (Object.keys(seal).some((k) => !known.includes(k)))
|
|
62
|
+
return null;
|
|
63
|
+
const text = {};
|
|
64
|
+
for (const k of ["statement", "requirements", "allowed_paths", "forbidden_paths", "goal_id", "work_card", "shape"])
|
|
65
|
+
if (seal[k] !== undefined)
|
|
66
|
+
text[k] = seal[k];
|
|
67
|
+
const contract = parseContract(text);
|
|
68
|
+
if (contract === null)
|
|
69
|
+
return null;
|
|
70
|
+
const commitments = {
|
|
71
|
+
statement_hash: await statementHash(contract.statement),
|
|
72
|
+
requirements_hash: await requirementsHash(contract.requirements),
|
|
73
|
+
contract_hash: await sealedContractHash(seal),
|
|
74
|
+
};
|
|
75
|
+
if (seal.mode !== undefined)
|
|
76
|
+
commitments.mode = seal.mode;
|
|
77
|
+
for (const [from, to] of CEILINGS)
|
|
78
|
+
if (seal[from] !== undefined)
|
|
79
|
+
commitments[to] = seal[from];
|
|
80
|
+
return isValidCommitment(commitments) ? { contract, commitments } : null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Rebuild the seal a charter describes from its decrypted Contract and its commitments. Null when
|
|
84
|
+
* the charter commits no contract_hash, or when the rebuilt contract does not hash to it.
|
|
85
|
+
*/
|
|
86
|
+
export async function sealedContractFromCharter(contract, charter) {
|
|
87
|
+
if (typeof charter.contract_hash !== "string")
|
|
88
|
+
return null;
|
|
89
|
+
const seal = { ...contract };
|
|
90
|
+
if (typeof charter.mode === "string")
|
|
91
|
+
seal.mode = charter.mode;
|
|
92
|
+
for (const [to, from] of CEILINGS) {
|
|
93
|
+
const v = charter[from];
|
|
94
|
+
if (typeof v === "number")
|
|
95
|
+
seal[to] = v;
|
|
96
|
+
}
|
|
97
|
+
const hash = await sealedContractHash(seal);
|
|
98
|
+
return hash === charter.contract_hash ? { contract: seal, contract_hash: hash } : null;
|
|
99
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The secret scope (BACKBONE line 69; C04-P01; wave-0 fix ruling 2), frozen as data so every lane
|
|
3
|
+
* greps the same list: which secrets, in which encodings, may appear on which surfaces. None may
|
|
4
|
+
* appear on any surface, with one allowance: the executor key in EXECUTOR_STATE_FILE (mode 0600).
|
|
5
|
+
* The owner's own files in `excluded_paths` are outside the scan. Paths are HOME-relative.
|
|
6
|
+
*/
|
|
7
|
+
export declare const SECRET_KINDS: readonly ["owner_jwt", "owner_refresh_token", "owner_api_key", "lease_key", "executor_key", "enroll_poll_secret"];
|
|
8
|
+
export type SecretKind = (typeof SECRET_KINDS)[number];
|
|
9
|
+
export declare const SECRET_ENCODINGS: readonly ["raw", "base64", "base64url", "hex", "percent", "json_escaped"];
|
|
10
|
+
export type SecretEncoding = (typeof SECRET_ENCODINGS)[number];
|
|
11
|
+
/** Where no secret may appear. */
|
|
12
|
+
export declare const SECRET_SURFACES: readonly ["host_files", "process_env", "process_argv", "tmux_global_env", "tmux_session_env", "tmux_scrollback", "tmpdir_files", "seat_transcripts", "durable_spans", "durable_logs"];
|
|
13
|
+
export type SecretSurface = (typeof SECRET_SURFACES)[number];
|
|
14
|
+
export declare const SECRET_SCOPE: Readonly<{
|
|
15
|
+
secrets: readonly ["owner_jwt", "owner_refresh_token", "owner_api_key", "lease_key", "executor_key", "enroll_poll_secret"];
|
|
16
|
+
encodings: readonly ["raw", "base64", "base64url", "hex", "percent", "json_escaped"];
|
|
17
|
+
surfaces: readonly ["host_files", "process_env", "process_argv", "tmux_global_env", "tmux_session_env", "tmux_scrollback", "tmpdir_files", "seat_transcripts", "durable_spans", "durable_logs"];
|
|
18
|
+
allow: readonly Readonly<{
|
|
19
|
+
secret: SecretKind;
|
|
20
|
+
path: ".mnemom/durable/executor-state.json";
|
|
21
|
+
}>[];
|
|
22
|
+
excluded_paths: readonly string[];
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Every encoded form of one secret value the scan greps for, keyed by encoding (UTF-8 bytes;
|
|
26
|
+
* base64 and base64url without padding variants, so a padded copy still matches as a substring).
|
|
27
|
+
*/
|
|
28
|
+
export declare function secretEncodings(value: string): Readonly<Record<SecretEncoding, string>>;
|