witnora 0.13.2 → 0.13.4

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.
@@ -0,0 +1,359 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { mkdir, open, readFile, readdir, rename } from "node:fs/promises";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { canonicalJson } from "./canonical.js";
5
+ export class FileActionCheckpointStore {
6
+ directory;
7
+ constructor(directory) { this.directory = resolve(directory); }
8
+ async load(actionId) {
9
+ try {
10
+ return parseCheckpoint(await readFile(this.path(actionId), "utf8"));
11
+ }
12
+ catch (error) {
13
+ if (isMissing(error))
14
+ return undefined;
15
+ throw error;
16
+ }
17
+ }
18
+ async save(checkpoint) {
19
+ const path = this.path(checkpoint.actionId);
20
+ await mkdir(dirname(path), { recursive: true });
21
+ const temporary = `${path}.${process.pid}.${randomUUID()}.tmp`;
22
+ const handle = await open(temporary, "w", 0o600);
23
+ try {
24
+ await handle.writeFile(`${JSON.stringify(checkpoint, null, 2)}\n`, "utf8");
25
+ await handle.sync();
26
+ }
27
+ finally {
28
+ await handle.close();
29
+ }
30
+ await rename(temporary, path);
31
+ }
32
+ async list() {
33
+ let names;
34
+ try {
35
+ names = await readdir(this.directory);
36
+ }
37
+ catch (error) {
38
+ if (isMissing(error))
39
+ return [];
40
+ throw error;
41
+ }
42
+ const values = await Promise.all(names.filter((name) => name.endsWith(".json")).map(async (name) => parseCheckpoint(await readFile(join(this.directory, name), "utf8"))));
43
+ return values.sort((left, right) => left.updatedAt.localeCompare(right.updatedAt));
44
+ }
45
+ async claimExecution(actionId, ownerId, claimedAt) {
46
+ const path = this.claimPath(actionId);
47
+ await mkdir(dirname(path), { recursive: true });
48
+ const claimId = randomUUID();
49
+ try {
50
+ const handle = await open(path, "wx", 0o600);
51
+ try {
52
+ await handle.writeFile(`${JSON.stringify({ schemaVersion: "witnora.execution_claim.v0.1", actionId, claimId, ownerId, claimedAt })}\n`, "utf8");
53
+ await handle.sync();
54
+ }
55
+ finally {
56
+ await handle.close();
57
+ }
58
+ return { acquired: true, claimId };
59
+ }
60
+ catch (error) {
61
+ if (!isAlreadyExists(error))
62
+ throw error;
63
+ const existing = JSON.parse(await readFile(path, "utf8"));
64
+ if (typeof existing.claimId !== "string" || !existing.claimId)
65
+ throw new Error("Existing execution claim is invalid; refusing to dispatch.");
66
+ return { acquired: false, claimId: existing.claimId };
67
+ }
68
+ }
69
+ path(actionId) {
70
+ if (!/^[A-Za-z0-9._:-]+$/.test(actionId))
71
+ throw new Error("actionId contains unsupported characters.");
72
+ return join(this.directory, `${actionId}.json`);
73
+ }
74
+ claimPath(actionId) {
75
+ if (!/^[A-Za-z0-9._:-]+$/.test(actionId))
76
+ throw new Error("actionId contains unsupported characters.");
77
+ return join(this.directory, `${actionId}.execution-claim`);
78
+ }
79
+ }
80
+ export class DurableApprovedActionWorker {
81
+ options;
82
+ now;
83
+ chains = new Map();
84
+ timer;
85
+ lastHeartbeatAt;
86
+ lastError;
87
+ workerId = randomUUID();
88
+ constructor(options) {
89
+ this.options = options;
90
+ this.now = options.now ?? (() => new Date());
91
+ if (!options.config.adapterId || !validVersion(options.config.adapterVersion))
92
+ throw new Error("An exact adapter id and semantic version are required.");
93
+ if (!options.config.probeId || !options.config.probeCredentialHandle || options.probe.id !== options.config.probeId
94
+ || options.probe.credentialHandle !== options.config.probeCredentialHandle || options.probe.readOnly !== true)
95
+ throw new Error("An exact separate read-only probe credential is required.");
96
+ if (options.config.adapterId === options.config.probeId)
97
+ throw new Error("The adapter and outcome probe must be separate.");
98
+ if (options.runtime.reconcileReadOnly !== true)
99
+ throw new Error("Unknown writes require an explicitly read-only reconciliation path.");
100
+ this.lastHeartbeatAt = this.now().toISOString();
101
+ }
102
+ async track(input) {
103
+ assertProposal(input.proposal);
104
+ const existing = await this.options.store.load(input.actionId);
105
+ const digest = sha256(input.proposal);
106
+ if (existing) {
107
+ if (existing.proposalSha256 !== digest)
108
+ throw new Error("Action id was already tracked with a different proposal.");
109
+ return existing;
110
+ }
111
+ const checkpoint = {
112
+ schemaVersion: "witnora.durable_action_checkpoint.v0.1", actionId: input.actionId, phase: "TRACKED",
113
+ proposal: structuredClone(input.proposal), proposalSha256: digest, updatedAt: this.now().toISOString(),
114
+ };
115
+ await this.options.store.save(checkpoint);
116
+ return checkpoint;
117
+ }
118
+ tick(actionId) {
119
+ const previous = this.chains.get(actionId) ?? Promise.resolve(undefined);
120
+ const next = previous.catch(() => undefined).then(() => this.tickOnce(actionId));
121
+ this.chains.set(actionId, next);
122
+ return next.finally(() => { if (this.chains.get(actionId) === next)
123
+ this.chains.delete(actionId); });
124
+ }
125
+ start() {
126
+ if (this.timer)
127
+ return;
128
+ const poll = async () => {
129
+ this.lastHeartbeatAt = this.now().toISOString();
130
+ const checkpoints = await this.options.store.list();
131
+ let cycleError;
132
+ await Promise.all(checkpoints.filter((item) => !terminal(item.phase)).map((item) => this.tick(item.actionId).catch((error) => { cycleError = message(error); })));
133
+ this.lastError = cycleError;
134
+ };
135
+ void poll().catch((error) => { this.lastError = message(error); });
136
+ this.timer = setInterval(() => void poll().catch((error) => { this.lastError = message(error); }), this.options.config.pollIntervalMs ?? 2_000);
137
+ this.timer.unref();
138
+ }
139
+ stop() { if (this.timer)
140
+ clearInterval(this.timer); this.timer = undefined; }
141
+ async status() {
142
+ const checkpoints = await this.options.store.list();
143
+ return {
144
+ schemaVersion: "witnora.durable_action_worker_status.v0.1",
145
+ ready: Boolean(this.timer) && !this.lastError,
146
+ trackedActionCount: checkpoints.length,
147
+ pendingActionCount: checkpoints.filter((item) => !terminal(item.phase)).length,
148
+ unknownResultCount: checkpoints.filter((item) => item.phase === "UNKNOWN_RESULT").length,
149
+ lastHeartbeatAt: this.lastHeartbeatAt,
150
+ ...(this.lastError ? { lastError: this.lastError } : {}),
151
+ };
152
+ }
153
+ async tickOnce(actionId) {
154
+ let checkpoint = await this.options.store.load(actionId);
155
+ if (!checkpoint)
156
+ throw new Error(`Action ${actionId} is not tracked.`);
157
+ if (terminal(checkpoint.phase))
158
+ return checkpoint;
159
+ const action = await this.options.hosted.getAction(actionId);
160
+ if (!exactActionMatches(action, actionId, checkpoint.proposal, this.options.config.adapterId, this.options.config.adapterVersion)) {
161
+ return this.persist(checkpoint, "BLOCKED", { limitation: "Hosted action no longer matches the exact locally configured action, adapter, or build binding." });
162
+ }
163
+ if ((checkpoint.phase === "EXECUTION_STARTED" || checkpoint.phase === "UNKNOWN_RESULT") && checkpoint.grant) {
164
+ if (!exactGrantMatches(checkpoint.grant, actionId, checkpoint.proposal, this.options.config.runtimeIdentityId)) {
165
+ return this.persist(checkpoint, "BLOCKED", { limitation: "Hosted grant does not match the exact approved local action binding." });
166
+ }
167
+ const reconciled = await this.options.runtime.reconcile({ action, proposal: checkpoint.proposal, grant: checkpoint.grant });
168
+ if (!reconciled)
169
+ return this.persist(checkpoint, "UNKNOWN_RESULT", { limitation: "Write result is unknown. The worker will only use read-only reconciliation and will never redispatch this grant." });
170
+ checkpoint = await this.persist(checkpoint, "EXECUTED", { execution: reconciled, limitation: undefined });
171
+ }
172
+ if (!checkpoint.execution) {
173
+ if (action.status === "REJECTED" || action.status === "DENIED")
174
+ return this.persist(checkpoint, "DENIED");
175
+ if (action.status === "APPROVAL_EXPIRED" || action.status === "GRANT_EXPIRED" || (action.status === "APPROVED" && expired(action.approvalExpiresAt, this.now())))
176
+ return this.persist(checkpoint, "EXPIRED");
177
+ if (action.status === "PENDING_APPROVAL")
178
+ return this.persist(checkpoint, "WAITING_APPROVAL");
179
+ if (action.status !== "APPROVED" && action.status !== "ALLOWED") {
180
+ return this.persist(checkpoint, "BLOCKED", { limitation: `Action status ${action.status} is not executable.` });
181
+ }
182
+ }
183
+ if (!checkpoint.grant && !checkpoint.execution) {
184
+ const intent = checkpoint.proposal.executionIntent;
185
+ const grant = await this.options.hosted.issueExecutionGrant(actionId, {
186
+ runtimeIdentityId: this.options.config.runtimeIdentityId,
187
+ adapterId: intent.adapterId,
188
+ adapterVersionConstraint: intent.adapterVersionConstraint,
189
+ allowedOrigins: intent.allowedOrigins,
190
+ allowedOperation: intent.allowedOperation,
191
+ allowedResource: intent.allowedResource,
192
+ approvedParameters: intent.approvedParameters,
193
+ outcomePredicate: intent.outcomePredicate,
194
+ agentBuildId: intent.agentBuildId,
195
+ agentBuildDigest: intent.agentBuildDigest,
196
+ ttlSeconds: this.options.config.grantTtlSeconds ?? 120,
197
+ }, `durable-worker:grant:${actionId}`);
198
+ checkpoint = await this.persist(checkpoint, "GRANT_ISSUED", { grant });
199
+ }
200
+ const grant = checkpoint.grant;
201
+ if (!grant)
202
+ return this.persist(checkpoint, "BLOCKED", { limitation: "A durable execution result exists without its bound Hosted grant." });
203
+ const grantPayload = grant.grant.payload ?? {};
204
+ if (!exactGrantMatches(grant, actionId, checkpoint.proposal, this.options.config.runtimeIdentityId)) {
205
+ return this.persist(checkpoint, "BLOCKED", { limitation: "Hosted grant does not match the exact approved local action binding." });
206
+ }
207
+ if (!checkpoint.execution) {
208
+ if (grant.status !== "ISSUED" || expired(stringValue(grantPayload.expiresAt), this.now()))
209
+ return this.persist(checkpoint, "EXPIRED");
210
+ const claim = await this.options.store.claimExecution(actionId, this.workerId, this.now().toISOString());
211
+ if (!claim.acquired) {
212
+ checkpoint = await this.persist(checkpoint, "UNKNOWN_RESULT", {
213
+ executionClaimId: claim.claimId,
214
+ limitation: "Another Gateway process owns the durable execution claim. This worker will only reconcile and will never dispatch.",
215
+ });
216
+ const reconciled = await this.options.runtime.reconcile({ action, proposal: checkpoint.proposal, grant });
217
+ if (!reconciled)
218
+ return checkpoint;
219
+ checkpoint = await this.persist(checkpoint, "EXECUTED", { execution: reconciled, limitation: undefined });
220
+ }
221
+ else {
222
+ checkpoint = await this.persist(checkpoint, "EXECUTION_STARTED", { executionClaimId: claim.claimId });
223
+ }
224
+ }
225
+ if (!checkpoint.execution && checkpoint.phase === "EXECUTION_STARTED") {
226
+ if (!checkpoint.hostedReservation) {
227
+ const reservation = await this.options.runtime.prepareClaim({ action, proposal: checkpoint.proposal, grant });
228
+ if (!exactHostedReservation(reservation, actionId, grant.id))
229
+ return this.persist(checkpoint, "BLOCKED", { limitation: "Runtime claim is not bound to the exact action, grant, and execution session." });
230
+ const claimed = await this.options.hosted.claimExecutionGrant(grant.id, reservation.claim, `durable-worker:claim:${grant.id}`);
231
+ if (!claimed.acquired) {
232
+ checkpoint = await this.persist(checkpoint, "UNKNOWN_RESULT", {
233
+ limitation: "Hosted already has an execution reservation for this grant. This worker will only reconcile and will never dispatch.",
234
+ });
235
+ const reconciled = await this.options.runtime.reconcile({ action, proposal: checkpoint.proposal, grant });
236
+ if (!reconciled)
237
+ return checkpoint;
238
+ checkpoint = await this.persist(checkpoint, "EXECUTED", { execution: reconciled, limitation: undefined });
239
+ }
240
+ else {
241
+ checkpoint = await this.persist(checkpoint, "EXECUTION_STARTED", { hostedReservation: reservation });
242
+ }
243
+ }
244
+ }
245
+ if (!checkpoint.execution && checkpoint.phase === "EXECUTION_STARTED" && checkpoint.hostedReservation) {
246
+ try {
247
+ const execution = await this.options.runtime.execute({ action, proposal: checkpoint.proposal, grant, hostedReservation: checkpoint.hostedReservation });
248
+ checkpoint = await this.persist(checkpoint, "EXECUTED", { execution });
249
+ }
250
+ catch {
251
+ checkpoint = await this.persist(checkpoint, "UNKNOWN_RESULT", { limitation: "Write result is unknown. The worker will only use read-only reconciliation and will never redispatch this grant." });
252
+ const reconciled = await this.options.runtime.reconcile({ action, proposal: checkpoint.proposal, grant });
253
+ if (!reconciled)
254
+ return checkpoint;
255
+ checkpoint = await this.persist(checkpoint, "EXECUTED", { execution: reconciled, limitation: undefined });
256
+ }
257
+ }
258
+ if (!checkpoint.observation) {
259
+ const observation = await this.options.probe.observe({ action, proposal: checkpoint.proposal, grant, execution: checkpoint.execution });
260
+ if (!observation.observationSource || observation.observationSource !== this.options.config.probeId)
261
+ throw new Error("Outcome observation did not come from the exact configured probe.");
262
+ checkpoint = await this.persist(checkpoint, "PROBED", { observation });
263
+ }
264
+ const verified = await this.options.hosted.verifyAction(actionId, {
265
+ ...checkpoint.observation,
266
+ executionGrantId: grant.id,
267
+ executionSessionId: checkpoint.execution.executionSessionId,
268
+ }, `durable-worker:verify:${actionId}:${checkpoint.execution.executionSessionId}`);
269
+ if (verified.status !== "VERIFIED" || verified.verificationSuccess !== true)
270
+ throw new Error("Hosted outcome verification did not establish the expected result.");
271
+ const receipts = await this.options.hosted.listActionReceipts(actionId);
272
+ const signed = receipts.find((item) => Array.isArray(item.receipt?.signatureSet) && item.receipt.signatureSet.length > 0);
273
+ if (!signed)
274
+ throw new Error("Hosted did not automatically issue a signed action receipt.");
275
+ return this.persist(checkpoint, "COMPLETED", { receiptId: signed.id });
276
+ }
277
+ async persist(checkpoint, phase, patch = {}) {
278
+ const next = { ...checkpoint, ...patch, phase, updatedAt: this.now().toISOString() };
279
+ if (patch.limitation === undefined && "limitation" in patch)
280
+ delete next.limitation;
281
+ await this.options.store.save(next);
282
+ return next;
283
+ }
284
+ }
285
+ function exactActionMatches(action, actionId, proposal, adapterId, adapterVersion) {
286
+ const approved = action.assuranceContext?.executionIntent;
287
+ const proposed = proposal.executionIntent;
288
+ return action.id === actionId && action.externalId === proposal.externalId && action.actionType === proposal.actionType
289
+ && action.targetSystem === proposal.targetSystem && sha256(action.expectedState ?? {}) === sha256(proposal.expectedState ?? {})
290
+ && proposed.adapterId === adapterId && runtimeAdapterVersionSatisfies(adapterVersion, proposed.adapterVersionConstraint)
291
+ && approved?.adapterId === proposed.adapterId && approved.adapterVersionConstraint === proposed.adapterVersionConstraint
292
+ && canonicalJson(approved.allowedOrigins) === canonicalJson(proposed.allowedOrigins)
293
+ && approved.allowedOperation === proposed.allowedOperation && approved.allowedResource === proposed.allowedResource
294
+ && approved.approvedParametersDigest === sha256(proposed.approvedParameters)
295
+ && approved.outcomePredicateDigest === sha256(proposed.outcomePredicate)
296
+ && approved.agentBuildId === proposed.agentBuildId && approved.agentBuildDigest === proposed.agentBuildDigest;
297
+ }
298
+ function exactGrantMatches(grant, actionId, proposal, runtimeIdentityId) {
299
+ const payload = grant.grant.payload ?? {};
300
+ const intent = proposal.executionIntent;
301
+ return payload.executionGrantId === grant.id && payload.actionId === actionId && payload.adapterId === intent.adapterId
302
+ && payload.adapterVersionConstraint === intent.adapterVersionConstraint && payload.expectedRuntimeIdentityId === runtimeIdentityId
303
+ && canonicalJson(payload.allowedOrigins) === canonicalJson(intent.allowedOrigins)
304
+ && payload.allowedOperation === intent.allowedOperation && payload.allowedResource === intent.allowedResource
305
+ && payload.agentBuildId === intent.agentBuildId && payload.agentBuildDigest === intent.agentBuildDigest
306
+ && payload.parametersDigest === sha256(intent.approvedParameters) && payload.outcomePredicateDigest === sha256(intent.outcomePredicate);
307
+ }
308
+ function exactHostedReservation(reservation, actionId, executionGrantId) {
309
+ if (!reservation || typeof reservation !== "object" || typeof reservation.executionSessionId !== "string"
310
+ || !reservation.executionSessionId || !reservation.claim || typeof reservation.claim !== "object" || Array.isArray(reservation.claim))
311
+ return false;
312
+ const payload = reservation.claim.payload;
313
+ return Boolean(payload && typeof payload === "object" && !Array.isArray(payload)
314
+ && payload.actionId === actionId
315
+ && payload.executionGrantId === executionGrantId
316
+ && payload.executionSessionId === reservation.executionSessionId);
317
+ }
318
+ function parseCheckpoint(raw) {
319
+ const value = JSON.parse(raw);
320
+ if (value.schemaVersion !== "witnora.durable_action_checkpoint.v0.1" || !value.actionId || !value.phase || !value.proposal || !value.proposalSha256 || !value.updatedAt) {
321
+ throw new Error("Durable action checkpoint is invalid.");
322
+ }
323
+ return value;
324
+ }
325
+ function assertProposal(value) {
326
+ const intent = value?.executionIntent;
327
+ if (!value?.externalId || !value.actionType || !value.targetSystem || !intent?.adapterId || !intent.adapterVersionConstraint
328
+ || !Array.isArray(intent.allowedOrigins) || !intent.allowedOrigins.length || !intent.allowedOperation || !intent.allowedResource
329
+ || !intent.approvedParameters || typeof intent.approvedParameters !== "object" || !intent.outcomePredicate || typeof intent.outcomePredicate !== "object"
330
+ || !intent.agentBuildId || !/^[a-f0-9]{64}$/.test(intent.agentBuildDigest)) {
331
+ throw new Error("Tracked action is missing an exact execution intent.");
332
+ }
333
+ }
334
+ function sha256(value) { return createHash("sha256").update(canonicalJson(value)).digest("hex"); }
335
+ function expired(value, now) { return !value || !Number.isFinite(Date.parse(value)) || Date.parse(value) <= now.getTime(); }
336
+ function stringValue(value) { return typeof value === "string" ? value : undefined; }
337
+ function validVersion(value) { return /^v?\d+\.\d+\.\d+$/.test(value); }
338
+ export function runtimeAdapterVersionSatisfies(version, constraint) {
339
+ const parsed = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(version);
340
+ const exact = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(constraint);
341
+ if (!parsed)
342
+ return false;
343
+ if (exact)
344
+ return parsed.slice(1).join(".") === exact.slice(1).join(".");
345
+ const compatible = /^\^v?(\d+)\.(\d+)\.(\d+)$/.exec(constraint);
346
+ if (!compatible)
347
+ return false;
348
+ const [major, minor, patch] = parsed.slice(1).map(Number);
349
+ const [requiredMajor, requiredMinor, requiredPatch] = compatible.slice(1).map(Number);
350
+ if (requiredMajor > 0)
351
+ return major === requiredMajor && (minor > requiredMinor || (minor === requiredMinor && patch >= requiredPatch));
352
+ if (requiredMinor > 0)
353
+ return major === 0 && minor === requiredMinor && patch >= requiredPatch;
354
+ return major === 0 && minor === 0 && patch === requiredPatch;
355
+ }
356
+ function terminal(phase) { return phase === "DENIED" || phase === "EXPIRED" || phase === "BLOCKED" || phase === "COMPLETED"; }
357
+ function isMissing(error) { return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT"); }
358
+ function isAlreadyExists(error) { return Boolean(error && typeof error === "object" && "code" in error && error.code === "EEXIST"); }
359
+ function message(error) { return error instanceof Error ? error.message : String(error); }
@@ -0,0 +1,132 @@
1
+ export interface CustomerSourceSigner {
2
+ keyId: string;
3
+ privateKeyPem: string;
4
+ publicKeyPem: string;
5
+ }
6
+ export interface RemoteTrustedSourceRecord {
7
+ schemaVersion: "agentcert.trusted_action_record.v0.1";
8
+ recordId: string;
9
+ runId: string;
10
+ sequence: number;
11
+ occurredAt: string;
12
+ type: string;
13
+ collector: {
14
+ id: string;
15
+ version: string;
16
+ environment: string;
17
+ keyId: string;
18
+ publicKeySha256: string;
19
+ };
20
+ previousEventHash?: string;
21
+ payload: Record<string, unknown>;
22
+ payloadSha256: string;
23
+ eventHash: string;
24
+ sourceSignature: {
25
+ algorithm: "Ed25519";
26
+ keyId: string;
27
+ signature: string;
28
+ };
29
+ }
30
+ export interface RemoteCollectorAck {
31
+ schemaVersion: "agentcert.remote_collector_ack.v0.2";
32
+ accepted: number;
33
+ replayed: number;
34
+ ack: {
35
+ sequence: number;
36
+ eventHash: string;
37
+ };
38
+ alerts: Array<Record<string, unknown>>;
39
+ run: Record<string, unknown>;
40
+ }
41
+ export interface RemoteCollectorClientOptions {
42
+ baseUrl: string;
43
+ projectId: string;
44
+ apiKey: string;
45
+ fetch?: typeof fetch;
46
+ }
47
+ export declare class CustomerSourceKeyRing {
48
+ readonly filePath: string;
49
+ private value;
50
+ private constructor();
51
+ static create(filePath: string, collectorId: string, keyId?: string): Promise<CustomerSourceKeyRing>;
52
+ static open(filePath: string): Promise<CustomerSourceKeyRing>;
53
+ get collectorId(): string;
54
+ activeSigner(): CustomerSourceSigner;
55
+ signerFor(keyId: string): CustomerSourceSigner;
56
+ registration(previousKeyId?: string): {
57
+ collectorId: string;
58
+ keyId: string;
59
+ publicKeyPem: string;
60
+ previousKeyId?: string;
61
+ };
62
+ rotate(keyId?: string): Promise<{
63
+ previousKeyId: string;
64
+ signer: CustomerSourceSigner;
65
+ }>;
66
+ private persist;
67
+ }
68
+ export declare class RemoteCollectorClient {
69
+ readonly baseUrl: string;
70
+ readonly projectId: string;
71
+ private readonly apiKey;
72
+ private readonly requestFetch;
73
+ constructor(options: RemoteCollectorClientOptions);
74
+ registerSourceKey(input: {
75
+ collectorId: string;
76
+ keyId: string;
77
+ publicKeyPem: string;
78
+ previousKeyId?: string;
79
+ }): Promise<Record<string, unknown>>;
80
+ append(runId: string, records: RemoteTrustedSourceRecord[], idempotencyKey?: string): Promise<RemoteCollectorAck>;
81
+ heartbeat(input: {
82
+ collectorId: string;
83
+ signer: CustomerSourceSigner;
84
+ runId?: string;
85
+ pendingRecordCount: number;
86
+ lastAckSequence?: number;
87
+ occurredAt?: string;
88
+ }): Promise<Record<string, unknown>>;
89
+ reconcile(runId: string, receipt: Record<string, unknown>): Promise<Record<string, unknown>>;
90
+ proposeAction(proposal: Record<string, unknown>, idempotencyKey: string): Promise<Record<string, unknown>>;
91
+ getAction(actionId: string): Promise<Record<string, unknown>>;
92
+ issueExecutionGrant(actionId: string, grant: Record<string, unknown>, idempotencyKey: string): Promise<Record<string, unknown>>;
93
+ status(): Promise<Record<string, unknown>>;
94
+ revokeSourceKey(keyId: string): Promise<Record<string, unknown>>;
95
+ sink(): {
96
+ name: string;
97
+ write(record: RemoteTrustedSourceRecord): Promise<void>;
98
+ };
99
+ private json;
100
+ }
101
+ export declare class DurableRemoteCollectorQueue {
102
+ readonly runId: string;
103
+ readonly journalPath: string;
104
+ readonly ackPath: string;
105
+ private replayChain;
106
+ constructor(directory: string, runId: string);
107
+ enqueue(record: RemoteTrustedSourceRecord): Promise<void>;
108
+ pending(): Promise<RemoteTrustedSourceRecord[]>;
109
+ all(): Promise<RemoteTrustedSourceRecord[]>;
110
+ currentAck(): Promise<{
111
+ sequence: number;
112
+ eventHash?: string;
113
+ }>;
114
+ replay(client: {
115
+ append(runId: string, records: RemoteTrustedSourceRecord[], idempotencyKey?: string): Promise<RemoteCollectorAck>;
116
+ }): Promise<{
117
+ delivered: number;
118
+ ack?: {
119
+ sequence: number;
120
+ eventHash: string;
121
+ };
122
+ }>;
123
+ private readAck;
124
+ private writeAck;
125
+ }
126
+ export declare class RemoteCollectorApiError extends Error {
127
+ readonly status: number;
128
+ readonly code: string;
129
+ readonly recovery?: string | undefined;
130
+ constructor(status: number, code: string, message: string, recovery?: string | undefined);
131
+ }
132
+ //# sourceMappingURL=remote-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-collector.d.ts","sourceRoot":"","sources":["../../../../agentcert-sdk/src/remote-collector.ts"],"names":[],"mappings":"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"}