@victframework/runtime 0.1.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/dist/agent-governance.d.ts +285 -0
- package/dist/agent-governance.js +438 -0
- package/dist/agent-governance.js.map +1 -0
- package/dist/agent-registry.d.ts +103 -0
- package/dist/agent-registry.js +758 -0
- package/dist/agent-registry.js.map +1 -0
- package/dist/agent-types.d.ts +433 -0
- package/dist/agent-types.js +480 -0
- package/dist/agent-types.js.map +1 -0
- package/dist/authority.d.ts +83 -0
- package/dist/authority.js +170 -0
- package/dist/authority.js.map +1 -0
- package/dist/boundary-conformance.d.ts +51 -0
- package/dist/boundary-conformance.js +364 -0
- package/dist/boundary-conformance.js.map +1 -0
- package/dist/control-conformance.d.ts +68 -0
- package/dist/control-conformance.js +1131 -0
- package/dist/control-conformance.js.map +1 -0
- package/dist/control-in-memory.d.ts +257 -0
- package/dist/control-in-memory.js +886 -0
- package/dist/control-in-memory.js.map +1 -0
- package/dist/control-types.d.ts +1017 -0
- package/dist/control-types.js +779 -0
- package/dist/control-types.js.map +1 -0
- package/dist/durable-run.d.ts +73 -0
- package/dist/durable-run.js +262 -0
- package/dist/durable-run.js.map +1 -0
- package/dist/effect-policy.d.ts +22 -0
- package/dist/effect-policy.js +45 -0
- package/dist/effect-policy.js.map +1 -0
- package/dist/errors.d.ts +36 -0
- package/dist/errors.js +71 -0
- package/dist/errors.js.map +1 -0
- package/dist/in-memory-stores.d.ts +16 -0
- package/dist/in-memory-stores.js +522 -0
- package/dist/in-memory-stores.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/operator-config.d.ts +141 -0
- package/dist/operator-config.js +289 -0
- package/dist/operator-config.js.map +1 -0
- package/dist/orchestration-activation.d.ts +116 -0
- package/dist/orchestration-activation.js +223 -0
- package/dist/orchestration-activation.js.map +1 -0
- package/dist/orchestration-canary-conformance.d.ts +10 -0
- package/dist/orchestration-canary-conformance.js +726 -0
- package/dist/orchestration-canary-conformance.js.map +1 -0
- package/dist/orchestration-commands.d.ts +47 -0
- package/dist/orchestration-commands.js +538 -0
- package/dist/orchestration-commands.js.map +1 -0
- package/dist/orchestration-conformance.d.ts +59 -0
- package/dist/orchestration-conformance.js +594 -0
- package/dist/orchestration-conformance.js.map +1 -0
- package/dist/orchestration-driver-types.d.ts +163 -0
- package/dist/orchestration-driver-types.js +21 -0
- package/dist/orchestration-driver-types.js.map +1 -0
- package/dist/orchestration-driver.d.ts +48 -0
- package/dist/orchestration-driver.js +1030 -0
- package/dist/orchestration-driver.js.map +1 -0
- package/dist/orchestration-in-memory.d.ts +18 -0
- package/dist/orchestration-in-memory.js +1313 -0
- package/dist/orchestration-in-memory.js.map +1 -0
- package/dist/orchestration-join-conformance.d.ts +20 -0
- package/dist/orchestration-join-conformance.js +542 -0
- package/dist/orchestration-join-conformance.js.map +1 -0
- package/dist/orchestration-plan.d.ts +52 -0
- package/dist/orchestration-plan.js +265 -0
- package/dist/orchestration-plan.js.map +1 -0
- package/dist/orchestration-race-conformance.d.ts +35 -0
- package/dist/orchestration-race-conformance.js +1265 -0
- package/dist/orchestration-race-conformance.js.map +1 -0
- package/dist/orchestration-remediation-conformance.d.ts +54 -0
- package/dist/orchestration-remediation-conformance.js +632 -0
- package/dist/orchestration-remediation-conformance.js.map +1 -0
- package/dist/orchestration-store-types.d.ts +568 -0
- package/dist/orchestration-store-types.js +2 -0
- package/dist/orchestration-store-types.js.map +1 -0
- package/dist/pack-conformance.d.ts +59 -0
- package/dist/pack-conformance.js +222 -0
- package/dist/pack-conformance.js.map +1 -0
- package/dist/pack-install.d.ts +44 -0
- package/dist/pack-install.js +126 -0
- package/dist/pack-install.js.map +1 -0
- package/dist/registry.d.ts +107 -0
- package/dist/registry.js +481 -0
- package/dist/registry.js.map +1 -0
- package/dist/runtime.d.ts +158 -0
- package/dist/runtime.js +1341 -0
- package/dist/runtime.js.map +1 -0
- package/dist/serialization.d.ts +26 -0
- package/dist/serialization.js +162 -0
- package/dist/serialization.js.map +1 -0
- package/dist/store-conformance.d.ts +45 -0
- package/dist/store-conformance.js +876 -0
- package/dist/store-conformance.js.map +1 -0
- package/dist/store-errors.d.ts +49 -0
- package/dist/store-errors.js +48 -0
- package/dist/store-errors.js.map +1 -0
- package/dist/store-types.d.ts +331 -0
- package/dist/store-types.js +14 -0
- package/dist/store-types.js.map +1 -0
- package/dist/store-validation.d.ts +63 -0
- package/dist/store-validation.js +164 -0
- package/dist/store-validation.js.map +1 -0
- package/dist/stream-hub.d.ts +151 -0
- package/dist/stream-hub.js +402 -0
- package/dist/stream-hub.js.map +1 -0
- package/dist/testing.d.ts +25 -0
- package/dist/testing.js +19 -0
- package/dist/testing.js.map +1 -0
- package/dist/types.d.ts +221 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import { validateAgentActivationRecord } from './agent-types.js';
|
|
2
|
+
import { VictRuntimeError } from './errors.js';
|
|
3
|
+
/** Error thrown for credential-resolution failures (stable, non-echoing). */
|
|
4
|
+
export class AgentCredentialError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
credentialName;
|
|
7
|
+
constructor(credentialName) {
|
|
8
|
+
super(`Credential '${credentialName}' could not be resolved through the protected provider.`);
|
|
9
|
+
this.name = 'AgentCredentialError';
|
|
10
|
+
this.code = 'VICT_AGENT_CREDENTIAL_UNAVAILABLE';
|
|
11
|
+
this.credentialName = credentialName;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A credential name: the accepted credential-reference policy is the SAME
|
|
16
|
+
* closed pattern the profile compiler enforces for
|
|
17
|
+
* `providerCredentialVar` — an environment-variable-style NAME matching
|
|
18
|
+
* `^[A-Za-z_][A-Za-z0-9_]*$` (at most 128 characters). Value-like inputs
|
|
19
|
+
* (separators, `=`, whitespace, secret content) are rejected BEFORE they
|
|
20
|
+
* reach any provider, and an invalid name is never echoed.
|
|
21
|
+
*/
|
|
22
|
+
const CREDENTIAL_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
23
|
+
const MAX_CREDENTIAL_NAME_LENGTH = 128;
|
|
24
|
+
/** A credential name: validated against the accepted credential-reference policy. */
|
|
25
|
+
export function assertCredentialName(name) {
|
|
26
|
+
if (typeof name !== 'string' ||
|
|
27
|
+
name.length === 0 ||
|
|
28
|
+
name.length > MAX_CREDENTIAL_NAME_LENGTH ||
|
|
29
|
+
!CREDENTIAL_NAME_PATTERN.test(name)) {
|
|
30
|
+
throw new AgentCredentialError('(invalid credential name)');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Wrap a credential provider with the protected-resolution discipline:
|
|
35
|
+
* - names are validated before reaching the provider;
|
|
36
|
+
* - provider exceptions are converted into stable sanitized failures whose
|
|
37
|
+
* messages never include provider content;
|
|
38
|
+
* - values are never cached — every read passes through to the provider, so
|
|
39
|
+
* rotation is observed and a rejected read cannot poison later reads.
|
|
40
|
+
*/
|
|
41
|
+
export function protectCredentialPort(port) {
|
|
42
|
+
return {
|
|
43
|
+
async get(name) {
|
|
44
|
+
assertCredentialName(name);
|
|
45
|
+
let value;
|
|
46
|
+
try {
|
|
47
|
+
value = await port.get(name);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// The provider's message never propagates; the failure is not
|
|
51
|
+
// recorded anywhere and cannot poison later invocations.
|
|
52
|
+
throw new AgentCredentialError(name);
|
|
53
|
+
}
|
|
54
|
+
if (value === undefined) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
if (typeof value !== 'string') {
|
|
58
|
+
throw new AgentCredentialError(name);
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Stable non-echoing failure for a missing required credential. */
|
|
65
|
+
export function requireCredential(value, name) {
|
|
66
|
+
assertCredentialName(name);
|
|
67
|
+
if (value === undefined) {
|
|
68
|
+
throw new AgentCredentialError(name);
|
|
69
|
+
}
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The closed deletion-step domain. Both store adapters (in-memory and
|
|
74
|
+
* SQLite) enforce the SAME receipt-step domain at their API boundary so
|
|
75
|
+
* unknown (e.g. legacy or fabricated) steps are rejected with the same
|
|
76
|
+
* stable, non-echoing error BEFORE any mutation (adapter parity).
|
|
77
|
+
*/
|
|
78
|
+
export const DELETION_STEP_DOMAIN = new Set([
|
|
79
|
+
'application-domain',
|
|
80
|
+
'memory-store',
|
|
81
|
+
]);
|
|
82
|
+
/** The exact stable, non-echoing rejection text shared by every adapter. */
|
|
83
|
+
export const DELETION_RECEIPT_STEP_INVALID_MESSAGE = 'VICT_AGENT_DELETION_RECEIPT_STEP_INVALID: the deletion receipt step must be a governed durable step.';
|
|
84
|
+
/**
|
|
85
|
+
* Validate one deletion-receipt step against the closed domain (shared by
|
|
86
|
+
* the in-memory and SQLite adapters). Invalid or legacy steps are rejected
|
|
87
|
+
* with the SAME stable, non-echoing error on every adapter, before any
|
|
88
|
+
* durable mutation occurs.
|
|
89
|
+
*/
|
|
90
|
+
export function assertDeletionReceiptStep(step) {
|
|
91
|
+
if (typeof step !== 'string' || !DELETION_STEP_DOMAIN.has(step)) {
|
|
92
|
+
throw new Error(DELETION_RECEIPT_STEP_INVALID_MESSAGE);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const INTENT_STATE_ORDER = [
|
|
96
|
+
'pending',
|
|
97
|
+
'application-domain-deleted',
|
|
98
|
+
'completed',
|
|
99
|
+
];
|
|
100
|
+
/**
|
|
101
|
+
* Shared invariant enforcement for in-memory and SQLite stores.
|
|
102
|
+
*
|
|
103
|
+
* Transitions are forward-only AND stepwise: a state may only move to the
|
|
104
|
+
* IMMEDIATELY next state in the lifecycle. Skipped transitions (for example
|
|
105
|
+
* `pending` directly to `completed`) are rejected — completion always
|
|
106
|
+
* requires both durable step receipts, which a skipped transition would
|
|
107
|
+
* fabricate. Same-state updates are idempotent no-ops.
|
|
108
|
+
*/
|
|
109
|
+
export function assertDeletionStateTransition(from, to) {
|
|
110
|
+
if (from === to) {
|
|
111
|
+
return; // idempotent no-op
|
|
112
|
+
}
|
|
113
|
+
const fromIndex = INTENT_STATE_ORDER.indexOf(from);
|
|
114
|
+
const toIndex = INTENT_STATE_ORDER.indexOf(to);
|
|
115
|
+
if (toIndex < fromIndex) {
|
|
116
|
+
throw new Error(`VICT_AGENT_DELETION_STATE_REGRESSION: refusing to move deletion intent from '${from}' back to '${to}'.`);
|
|
117
|
+
}
|
|
118
|
+
if (toIndex !== fromIndex + 1) {
|
|
119
|
+
throw new Error(`VICT_AGENT_DELETION_STATE_SKIP: refusing to move deletion intent from '${from}' directly to '${to}'; completion requires each step's durable receipt.`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Receipt-enforced transition validation (shared by in-memory and SQLite
|
|
124
|
+
* stores): a state may only advance when the receipt of the step it
|
|
125
|
+
* ENTERS is durably recorded.
|
|
126
|
+
*
|
|
127
|
+
* - entering `application-domain-deleted` requires the durable
|
|
128
|
+
* `application-domain` receipt;
|
|
129
|
+
* - entering `completed` requires BOTH durable step receipts.
|
|
130
|
+
*
|
|
131
|
+
* The check reads the ACTUAL STORED receipts — the caller must pass the
|
|
132
|
+
* receipts exactly as they exist in the same store, and each store must
|
|
133
|
+
* perform the check and the state update ATOMICALLY (one synchronous
|
|
134
|
+
* critical section in memory; one transaction in SQLite). A receipt-free
|
|
135
|
+
* two-step bypass (`pending → application-domain-deleted → completed`)
|
|
136
|
+
* therefore fails at the FIRST transition and leaves the stored state
|
|
137
|
+
* unchanged.
|
|
138
|
+
*/
|
|
139
|
+
export function assertDeletionStateTransitionWithReceipts(from, to, receipts) {
|
|
140
|
+
assertDeletionStateTransition(from, to);
|
|
141
|
+
if (from === to) {
|
|
142
|
+
return; // idempotent no-op: no new state is entered
|
|
143
|
+
}
|
|
144
|
+
const has = (step) => receipts.some((receipt) => receipt.step === step);
|
|
145
|
+
if (to === 'application-domain-deleted' && !has('application-domain')) {
|
|
146
|
+
throw new Error("VICT_AGENT_DELETION_RECEIPT_REQUIRED: entering 'application-domain-deleted' requires the durable 'application-domain' receipt; refusing to advance without it.");
|
|
147
|
+
}
|
|
148
|
+
if (to === 'completed' && !(has('application-domain') && has('memory-store'))) {
|
|
149
|
+
throw new Error("VICT_AGENT_DELETION_RECEIPT_REQUIRED: entering 'completed' requires BOTH durable step receipts ('application-domain' and 'memory-store'); refusing to advance without them.");
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validate a deletion-intent record at the durable boundary (shared by the
|
|
154
|
+
* in-memory and SQLite stores). A NEW intent must start as `pending` with
|
|
155
|
+
* NO receipts — arbitrary initial states and fabricated receipts are
|
|
156
|
+
* rejected.
|
|
157
|
+
*/
|
|
158
|
+
export function assertDeletionIntentRecord(record) {
|
|
159
|
+
if (typeof record.intentId !== 'string' || record.intentId.length === 0) {
|
|
160
|
+
throw new VictRuntimeError('VICT_AGENT_DELETION_INTENT_INVALID', 'A deletion intent requires a non-empty intentId.');
|
|
161
|
+
}
|
|
162
|
+
if (typeof record.conversationId !== 'string' || record.conversationId.length === 0) {
|
|
163
|
+
throw new VictRuntimeError('VICT_AGENT_DELETION_INTENT_INVALID', 'A deletion intent requires a non-empty conversationId.');
|
|
164
|
+
}
|
|
165
|
+
if (typeof record.actorId !== 'string' || record.actorId.length === 0) {
|
|
166
|
+
throw new VictRuntimeError('VICT_AGENT_DELETION_INTENT_INVALID', 'A deletion intent requires a non-empty actorId.');
|
|
167
|
+
}
|
|
168
|
+
if (typeof record.createdAt !== 'number' ||
|
|
169
|
+
!Number.isFinite(record.createdAt) ||
|
|
170
|
+
record.createdAt < 0) {
|
|
171
|
+
throw new VictRuntimeError('VICT_AGENT_DELETION_INTENT_INVALID', 'A deletion intent requires a finite createdAt epoch-ms value.');
|
|
172
|
+
}
|
|
173
|
+
if (record.state !== 'pending') {
|
|
174
|
+
throw new VictRuntimeError('VICT_AGENT_DELETION_INTENT_INVALID', `A deletion intent must be recorded in the 'pending' state; arbitrary initial states are rejected.`);
|
|
175
|
+
}
|
|
176
|
+
if (!Array.isArray(record.receipts) || record.receipts.length > 0) {
|
|
177
|
+
throw new VictRuntimeError('VICT_AGENT_DELETION_INTENT_INVALID', 'A new deletion intent must carry no receipts; fabricated receipts are rejected.');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** In-memory AgentGovernanceStore (tests and non-durable compositions). */
|
|
181
|
+
export class InMemoryAgentGovernanceStore {
|
|
182
|
+
#activations = new Map();
|
|
183
|
+
#intents = new Map();
|
|
184
|
+
async saveAgentActivation(record) {
|
|
185
|
+
const validation = validateAgentActivationRecord(record);
|
|
186
|
+
if (!validation.ok) {
|
|
187
|
+
throw new VictRuntimeError('VICT_AGENT_ACTIVATION_RECORD_INVALID', `The activation record is malformed and was not persisted: ${validation.reason}`);
|
|
188
|
+
}
|
|
189
|
+
const existing = this.#activations.get(record.activationVersion);
|
|
190
|
+
if (existing !== undefined) {
|
|
191
|
+
if (JSON.stringify(existing) !== JSON.stringify(record)) {
|
|
192
|
+
throw new Error('VICT_AGENT_ACTIVATION_COLLISION: an activation record exists with different content.');
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
this.#activations.set(record.activationVersion, structuredCloneAgent(record));
|
|
197
|
+
}
|
|
198
|
+
async getAgentActivation(activationVersion) {
|
|
199
|
+
const record = this.#activations.get(activationVersion);
|
|
200
|
+
return record === undefined ? undefined : structuredCloneAgent(record);
|
|
201
|
+
}
|
|
202
|
+
async recordDeletionIntent(record) {
|
|
203
|
+
assertDeletionIntentRecord(record);
|
|
204
|
+
const existing = this.#intents.get(record.intentId);
|
|
205
|
+
if (existing !== undefined) {
|
|
206
|
+
if (existing.conversationId !== record.conversationId ||
|
|
207
|
+
existing.actorId !== record.actorId ||
|
|
208
|
+
existing.createdAt !== record.createdAt) {
|
|
209
|
+
throw new Error('VICT_AGENT_DELETION_INTENT_COLLISION: an intent exists with different content.');
|
|
210
|
+
}
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
this.#intents.set(record.intentId, structuredCloneAgent(record));
|
|
214
|
+
}
|
|
215
|
+
async getDeletionIntent(intentId) {
|
|
216
|
+
const record = this.#intents.get(intentId);
|
|
217
|
+
return record === undefined ? undefined : structuredCloneAgent(record);
|
|
218
|
+
}
|
|
219
|
+
async listOpenDeletionIntents() {
|
|
220
|
+
return [...this.#intents.values()]
|
|
221
|
+
.filter((record) => record.state !== 'completed')
|
|
222
|
+
.sort((a, b) => (a.intentId < b.intentId ? -1 : 1))
|
|
223
|
+
.map((record) => structuredCloneAgent(record));
|
|
224
|
+
}
|
|
225
|
+
async listDeletionIntents() {
|
|
226
|
+
return [...this.#intents.values()]
|
|
227
|
+
.sort((a, b) => (a.intentId < b.intentId ? -1 : 1))
|
|
228
|
+
.map((record) => structuredCloneAgent(record));
|
|
229
|
+
}
|
|
230
|
+
async recordDeletionReceipt(intentId, step, at) {
|
|
231
|
+
// Closed step domain — enforced at the API boundary of BOTH adapters
|
|
232
|
+
// (shared helper), before any mutation, with the same stable,
|
|
233
|
+
// non-echoing error (adapter parity).
|
|
234
|
+
assertDeletionReceiptStep(step);
|
|
235
|
+
const record = this.#intents.get(intentId);
|
|
236
|
+
if (record === undefined) {
|
|
237
|
+
throw new Error('VICT_AGENT_DELETION_INTENT_MISSING');
|
|
238
|
+
}
|
|
239
|
+
if (record.receipts.some((receipt) => receipt.step === step)) {
|
|
240
|
+
return; // idempotent: no duplicate receipt
|
|
241
|
+
}
|
|
242
|
+
// Receipt order mirrors the governed execution order: the memory step
|
|
243
|
+
// receipt can only exist after the application-domain receipt. An
|
|
244
|
+
// out-of-order receipt would fabricate durable progress and is
|
|
245
|
+
// rejected.
|
|
246
|
+
if (step === 'memory-store' &&
|
|
247
|
+
!record.receipts.some((receipt) => receipt.step === 'application-domain')) {
|
|
248
|
+
throw new Error('VICT_AGENT_DELETION_RECEIPT_ORDER: the memory step receipt requires the application-domain receipt to exist first.');
|
|
249
|
+
}
|
|
250
|
+
const updated = {
|
|
251
|
+
...record,
|
|
252
|
+
receipts: [...record.receipts, { step, at }].sort((a, b) => (a.step < b.step ? -1 : 1)),
|
|
253
|
+
};
|
|
254
|
+
this.#intents.set(intentId, updated);
|
|
255
|
+
}
|
|
256
|
+
async updateDeletionIntentState(intentId, state) {
|
|
257
|
+
// Atomic check-and-update: the transition is validated against the
|
|
258
|
+
// ACTUAL stored receipts inside the same synchronous critical section
|
|
259
|
+
// that performs the update, so no interleaving write can slip between
|
|
260
|
+
// the check and the update.
|
|
261
|
+
const record = this.#intents.get(intentId);
|
|
262
|
+
if (record === undefined) {
|
|
263
|
+
throw new Error('VICT_AGENT_DELETION_INTENT_MISSING');
|
|
264
|
+
}
|
|
265
|
+
assertDeletionStateTransitionWithReceipts(record.state, state, record.receipts);
|
|
266
|
+
this.#intents.set(intentId, { ...record, state });
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function structuredCloneAgent(value) {
|
|
270
|
+
return JSON.parse(JSON.stringify(value));
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Governed conversation deletion across stores (amendment §8.1, MSTR-011).
|
|
274
|
+
*
|
|
275
|
+
* Cross-store atomicity is impossible and is never claimed. The
|
|
276
|
+
* coordinator:
|
|
277
|
+
* 1. records the durable deletion intent BEFORE touching either store;
|
|
278
|
+
* 2. deletes the VICT application-domain resource through its governed
|
|
279
|
+
* port and records a durable receipt;
|
|
280
|
+
* 3. deletes the the agent framework thread through the adapter port and records a
|
|
281
|
+
* durable receipt;
|
|
282
|
+
* 4. advances the intent to `completed` only when both receipts exist.
|
|
283
|
+
*
|
|
284
|
+
* Every step is idempotent; receipts deduplicate; `recoverPending()`
|
|
285
|
+
* resumes safely after a crash at ANY boundary without duplicating
|
|
286
|
+
* receipts, losing completions, or resurrecting deleted data.
|
|
287
|
+
*/
|
|
288
|
+
export class ConversationDeletionCoordinator {
|
|
289
|
+
#governance;
|
|
290
|
+
#domain;
|
|
291
|
+
#memory;
|
|
292
|
+
#clock;
|
|
293
|
+
constructor(options) {
|
|
294
|
+
this.#governance = options.governance;
|
|
295
|
+
this.#domain = options.domain;
|
|
296
|
+
this.#memory = options.memory;
|
|
297
|
+
this.#clock = options.clock ?? (() => Date.now());
|
|
298
|
+
}
|
|
299
|
+
/** Deterministic intent id per conversation (idempotent re-deletes). */
|
|
300
|
+
intentIdFor(conversationId) {
|
|
301
|
+
return `vict-del-${conversationId}`;
|
|
302
|
+
}
|
|
303
|
+
async deleteConversation(options) {
|
|
304
|
+
const intentId = this.intentIdFor(options.conversationId);
|
|
305
|
+
const existing = await this.#governance.getDeletionIntent(intentId);
|
|
306
|
+
if (existing === undefined) {
|
|
307
|
+
await this.#governance.recordDeletionIntent({
|
|
308
|
+
intentId,
|
|
309
|
+
conversationId: options.conversationId,
|
|
310
|
+
actorId: options.actorId,
|
|
311
|
+
createdAt: this.#clock(),
|
|
312
|
+
state: 'pending',
|
|
313
|
+
receipts: [],
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
else if (existing.actorId !== options.actorId) {
|
|
317
|
+
throw new Error('VICT_AGENT_DELETION_ACTOR_MISMATCH: the intent exists under a different actor.');
|
|
318
|
+
}
|
|
319
|
+
return this.#runSteps(intentId);
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Resume every open intent (crash recovery, process restart). Each open
|
|
323
|
+
* intent continues from its recorded receipts; completed steps are never
|
|
324
|
+
* re-executed against the stores... the underlying ports are idempotent
|
|
325
|
+
* besides, but receipts are authoritative: a recorded receipt means the
|
|
326
|
+
* step is durable and is NOT re-driven.
|
|
327
|
+
*/
|
|
328
|
+
async recoverPending() {
|
|
329
|
+
const open = await this.#governance.listOpenDeletionIntents();
|
|
330
|
+
let completed = 0;
|
|
331
|
+
let pending = 0;
|
|
332
|
+
for (const intent of open) {
|
|
333
|
+
const outcome = await this.#runSteps(intent.intentId);
|
|
334
|
+
if (outcome.status === 'completed') {
|
|
335
|
+
completed += 1;
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
pending += 1;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return { resumed: open.length, completed, pending };
|
|
342
|
+
}
|
|
343
|
+
async #runSteps(intentId) {
|
|
344
|
+
const intent = await this.#governance.getDeletionIntent(intentId);
|
|
345
|
+
if (intent === undefined) {
|
|
346
|
+
throw new Error('VICT_AGENT_DELETION_INTENT_MISSING');
|
|
347
|
+
}
|
|
348
|
+
if (intent.state !== 'completed') {
|
|
349
|
+
if (!intent.receipts.some((receipt) => receipt.step === 'application-domain')) {
|
|
350
|
+
const result = await this.#domain.deleteConversation(intent.conversationId);
|
|
351
|
+
if (typeof result?.deleted !== 'boolean') {
|
|
352
|
+
throw new Error('VICT_AGENT_DELETION_DOMAIN_INVALID_RESULT');
|
|
353
|
+
}
|
|
354
|
+
await this.#governance.recordDeletionReceipt(intentId, 'application-domain', this.#clock());
|
|
355
|
+
}
|
|
356
|
+
// Advance stepwise (a crash may have left the durable state one step
|
|
357
|
+
// behind its receipts; same-state updates are idempotent no-ops).
|
|
358
|
+
const afterDomain = await this.#governance.getDeletionIntent(intentId);
|
|
359
|
+
if (afterDomain !== undefined && afterDomain.state === 'pending') {
|
|
360
|
+
await this.#governance.updateDeletionIntentState(intentId, 'application-domain-deleted');
|
|
361
|
+
}
|
|
362
|
+
const current = await this.#governance.getDeletionIntent(intentId);
|
|
363
|
+
if (current === undefined) {
|
|
364
|
+
throw new Error('VICT_AGENT_DELETION_INTENT_MISSING');
|
|
365
|
+
}
|
|
366
|
+
if (!current.receipts.some((receipt) => receipt.step === 'memory-store')) {
|
|
367
|
+
const result = await this.#memory.deleteConversationThread(intent.conversationId);
|
|
368
|
+
if (typeof result?.deleted !== 'boolean') {
|
|
369
|
+
throw new Error('VICT_AGENT_DELETION_MEMORY_INVALID_RESULT');
|
|
370
|
+
}
|
|
371
|
+
await this.#governance.recordDeletionReceipt(intentId, 'memory-store', this.#clock());
|
|
372
|
+
}
|
|
373
|
+
const after = await this.#governance.getDeletionIntent(intentId);
|
|
374
|
+
if (after !== undefined &&
|
|
375
|
+
after.receipts.some((receipt) => receipt.step === 'application-domain') &&
|
|
376
|
+
after.receipts.some((receipt) => receipt.step === 'memory-store') &&
|
|
377
|
+
after.state !== 'completed') {
|
|
378
|
+
// Completion always passes through the intermediate state — the
|
|
379
|
+
// stepwise invariant forbids skipping it.
|
|
380
|
+
await this.#governance.updateDeletionIntentState(intentId, 'application-domain-deleted');
|
|
381
|
+
await this.#governance.updateDeletionIntentState(intentId, 'completed');
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const final = await this.#governance.getDeletionIntent(intentId);
|
|
385
|
+
if (final === undefined) {
|
|
386
|
+
throw new Error('VICT_AGENT_DELETION_INTENT_MISSING');
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
389
|
+
status: final.state === 'completed' ? 'completed' : 'pending',
|
|
390
|
+
intentId,
|
|
391
|
+
conversationId: final.conversationId,
|
|
392
|
+
completedSteps: final.receipts.map((receipt) => receipt.step),
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/** Error carrying a stable export denial (never raw content). */
|
|
397
|
+
export class AgentConversationExportError extends Error {
|
|
398
|
+
code;
|
|
399
|
+
constructor(code) {
|
|
400
|
+
super(code);
|
|
401
|
+
this.name = 'AgentConversationExportError';
|
|
402
|
+
this.code = code;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Governed conversation export (MSTR-011). Explicit and request-scoped:
|
|
407
|
+
* the requestor must present the owning actor identity; the export
|
|
408
|
+
* contains only classification-policy data; the result is handed to the
|
|
409
|
+
* caller and never logged or retained by the service.
|
|
410
|
+
*/
|
|
411
|
+
export class ConversationExportService {
|
|
412
|
+
#memory;
|
|
413
|
+
constructor(options) {
|
|
414
|
+
this.#memory = options.memory;
|
|
415
|
+
}
|
|
416
|
+
async export(options) {
|
|
417
|
+
const found = await this.#memory.exportConversationThread(options.conversationId);
|
|
418
|
+
if (found === undefined) {
|
|
419
|
+
throw new AgentConversationExportError('VICT_AGENT_EXPORT_NOT_FOUND');
|
|
420
|
+
}
|
|
421
|
+
if (found.actorId !== options.actorId) {
|
|
422
|
+
throw new AgentConversationExportError('VICT_AGENT_EXPORT_ACTOR_MISMATCH');
|
|
423
|
+
}
|
|
424
|
+
// Deterministic ordering by sequence; exportedAt comes from the
|
|
425
|
+
// injected clock. The service retains nothing and logs nothing.
|
|
426
|
+
const sorted = [...found.messages].sort((a, b) => a.seq - b.seq);
|
|
427
|
+
return {
|
|
428
|
+
export: {
|
|
429
|
+
conversationId: found.conversationId,
|
|
430
|
+
actorId: found.actorId,
|
|
431
|
+
threadCreatedAt: found.threadCreatedAt,
|
|
432
|
+
messages: sorted,
|
|
433
|
+
},
|
|
434
|
+
retained: false,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=agent-governance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-governance.js","sourceRoot":"","sources":["../src/agent-governance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { AgentArtifact, AgentActivationRecord, AgentActivationRestoreResult, AgentProfileActivation } from './agent-types.js';
|
|
2
|
+
import type { CompiledAgentProfile } from '@victframework/kernel';
|
|
3
|
+
import type { AgentProfileAuthoring } from '@victframework/sdk';
|
|
4
|
+
/** Options for constructing an AgentProfileRegistry. */
|
|
5
|
+
export interface AgentProfileRegistryOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a capability reference to exact-revision existence for the
|
|
8
|
+
* authority envelope (fail closed at activation when missing). The
|
|
9
|
+
* composition wires this to the capability registry's revision history.
|
|
10
|
+
*/
|
|
11
|
+
readonly resolveCapabilityRevision?: (id: string, revision: string) => boolean;
|
|
12
|
+
/** Injected clock (epoch ms); defaults to `Date.now`. */
|
|
13
|
+
readonly clock?: () => number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Owns registered agent artifacts and compiled agent profiles for one
|
|
17
|
+
* runtime composition. Not a global registry: every composition carries
|
|
18
|
+
* its own.
|
|
19
|
+
*/
|
|
20
|
+
export declare class AgentProfileRegistry {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(options?: AgentProfileRegistryOptions);
|
|
23
|
+
/** Register one artifact atomically; duplicates of the same (id, revision) fail. */
|
|
24
|
+
registerArtifact(artifact: AgentArtifact): void;
|
|
25
|
+
/**
|
|
26
|
+
* Register many artifacts atomically: ALL or NOTHING.
|
|
27
|
+
*
|
|
28
|
+
* Preflight (before anything becomes observable):
|
|
29
|
+
* 1. every artifact is validated and staged;
|
|
30
|
+
* 2. every staged key is checked against the EXISTING registry content;
|
|
31
|
+
* 3. every staged key is checked against the OTHER staged entries
|
|
32
|
+
* (intra-batch duplicates).
|
|
33
|
+
*
|
|
34
|
+
* If any artifact is invalid or conflicting, nothing from the batch is
|
|
35
|
+
* committed — the registry is byte-for-byte unchanged, and a corrected
|
|
36
|
+
* batch can be retried.
|
|
37
|
+
*/
|
|
38
|
+
installArtifacts(artifacts: readonly AgentArtifact[]): void;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve one artifact by kind + exact revision. The result is a FRESH
|
|
41
|
+
* defensive descriptor: data members are deep-copied and frozen, function
|
|
42
|
+
* references are preserved by reference, and the registry's internal
|
|
43
|
+
* objects are never exposed. Mutating a resolved value cannot alter a
|
|
44
|
+
* later resolution or an activation.
|
|
45
|
+
*/
|
|
46
|
+
resolveArtifact<T extends AgentArtifact>(kind: T['kind'], id: string, revision: string): T | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Register a compiled agent profile atomically. Duplicate registration
|
|
49
|
+
* of the same (id, revision) fails; a NEW revision for the same id adds
|
|
50
|
+
* a resolvable revision for exact pinned restoration.
|
|
51
|
+
*/
|
|
52
|
+
registerProfile(profile: AgentProfileAuthoring): {
|
|
53
|
+
readonly agentProfileVersion: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Intentional replacement: registers a new profile revision and REPLACES
|
|
57
|
+
* the current pointer only when the caller pins the expected previous
|
|
58
|
+
* revision. Affects only later activations — never an active snapshot.
|
|
59
|
+
*/
|
|
60
|
+
replaceProfile(options: {
|
|
61
|
+
readonly profile: AgentProfileAuthoring;
|
|
62
|
+
readonly expectedPreviousRevision: string;
|
|
63
|
+
}): {
|
|
64
|
+
readonly agentProfileVersion: string;
|
|
65
|
+
};
|
|
66
|
+
/** Resolve a compiled profile by id + exact revision (default: current). */
|
|
67
|
+
resolveProfile(id: string, revision?: string): CompiledAgentProfile | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Activate an agent profile: resolve EVERY revisioned component to its
|
|
70
|
+
* exact revision — including a declared structured-output contract —
|
|
71
|
+
* verify the capability envelope (fail closed when a resolver is missing),
|
|
72
|
+
* and capture an immutable snapshot. Missing or mismatched artifacts fail
|
|
73
|
+
* closed; identity-only references are never treated as executable
|
|
74
|
+
* bindings.
|
|
75
|
+
*/
|
|
76
|
+
activateAgentProfile(options: {
|
|
77
|
+
readonly id: string;
|
|
78
|
+
readonly revision?: string;
|
|
79
|
+
}): AgentProfileActivation;
|
|
80
|
+
/**
|
|
81
|
+
* Restore an activation from its persisted identity record: the record is
|
|
82
|
+
* identity, NOT executable code, and it is NEVER trusted on identity
|
|
83
|
+
* strings alone. Restoration:
|
|
84
|
+
*
|
|
85
|
+
* 1. structurally validates the record (closed field sets, canonical
|
|
86
|
+
* version forms, well-formed artifact entries — extra or
|
|
87
|
+
* secret-bearing injected fields fail);
|
|
88
|
+
* 2. re-activates from the exact pinned revision (re-resolving EVERY
|
|
89
|
+
* artifact — a newer live definition never substitutes);
|
|
90
|
+
* 3. recomputes the canonical activation manifest (including the resolved
|
|
91
|
+
* sub-agent identities) and compares the stored manifest BYTES exactly
|
|
92
|
+
* (tampered manifests, and activations whose resolved sub-agent
|
|
93
|
+
* profiles differ from the pinned ones, fail);
|
|
94
|
+
* 4. compares both derived identities (profile + activation versions);
|
|
95
|
+
* 5. compares the stored artifact list against the reconstructed
|
|
96
|
+
* activation for exact kind/id/revision equality in canonical order
|
|
97
|
+
* (missing, additional, reordered, or inconsistent entries fail);
|
|
98
|
+
* 6. preserves the stored activation `createdAt`: the restored snapshot
|
|
99
|
+
* carries the PERSISTED creation time, never the current clock of the
|
|
100
|
+
* restoring process.
|
|
101
|
+
*/
|
|
102
|
+
restoreActivation(record: AgentActivationRecord): AgentActivationRestoreResult;
|
|
103
|
+
}
|