@tangle-network/agent-app 0.46.52 → 0.46.54

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,3 @@
1
+ import type { KeyCrypto } from './index';
2
+ /** Prove the at-rest crypto seam before a remote key is minted. */
3
+ export declare function assertWorkspaceKeyCryptoUsable(crypto: KeyCrypto): Promise<void>;
@@ -0,0 +1,183 @@
1
+ import type { KeyCrypto, KeyProvisioner } from './index';
2
+ /** Lifecycle state for a durable delegated key row. */
3
+ export type WorkspaceKeyStatus = 'legacy' | 'provisioning' | 'active' | 'revocation_pending' | 'revoked' | 'orphaned';
4
+ /** Product partition used by the key store and remote provisioner. */
5
+ export type WorkspaceKeyProduct = string;
6
+ /** The identity fields that bind a child key to its paying owner and source. */
7
+ export interface WorkspaceKeyIdentity {
8
+ workspaceId: string;
9
+ ownerUserId: string;
10
+ platformUserId: string;
11
+ sourceKeyId?: string | null;
12
+ /** A non-secret digest of the source credential. */
13
+ sourceKeyFingerprint: string;
14
+ }
15
+ /** A product/workspace/owner lookup scope. */
16
+ export interface DurableWorkspaceKeyScope {
17
+ workspaceId: string;
18
+ ownerUserId: string;
19
+ product: WorkspaceKeyProduct;
20
+ }
21
+ /** A persisted child-key row owned by this manager. */
22
+ export interface DurableWorkspaceKeyRecord {
23
+ id: string;
24
+ workspaceId: string;
25
+ ownerUserId: string;
26
+ product: WorkspaceKeyProduct;
27
+ platformUserId: string;
28
+ sourceKeyId: string | null;
29
+ sourceKeyFingerprint: string;
30
+ /** The persisted name used to recover a remote create after a crash. Null only for pre-name rows. */
31
+ name: string | null;
32
+ keyId: string;
33
+ keyEncrypted: string;
34
+ budgetUsd: number;
35
+ expiresAt: Date;
36
+ status: WorkspaceKeyStatus;
37
+ revocationAttempts: number;
38
+ nextRevocationAt: Date | null;
39
+ lastRevocationError: string | null;
40
+ createdAt: Date;
41
+ }
42
+ /** A row that has been written before its remote child key exists. */
43
+ export interface DurableWorkspaceKeyProvisioningRecord extends DurableWorkspaceKeyRecord {
44
+ status: 'provisioning';
45
+ }
46
+ type DurableWorkspaceKeyCreateResult = Awaited<ReturnType<KeyProvisioner['createKey']>> & {
47
+ budgetUsd?: number | null;
48
+ budgetRemaining?: number;
49
+ expiresAt?: string | null;
50
+ };
51
+ /** The remote operations required by the durable manager. */
52
+ export interface DurableWorkspaceKeyProvisioner {
53
+ createKey(input: Parameters<KeyProvisioner['createKey']>[0]): Promise<DurableWorkspaceKeyCreateResult>;
54
+ getKey(id: string): Promise<{
55
+ budgetUsd?: number | null;
56
+ budgetSpent?: number;
57
+ expiresAt?: string | null;
58
+ }>;
59
+ revokeKey: KeyProvisioner['revokeKey'];
60
+ /** Find remote keys for a specific persisted provisioning attempt. */
61
+ findCreatedKeys(input: {
62
+ name: string;
63
+ product: string;
64
+ sourceKeyId?: string | null;
65
+ }): Promise<Array<{
66
+ id: string;
67
+ }>>;
68
+ }
69
+ /** Persistence operations for identity-bound key lifecycle state. */
70
+ export interface DurableWorkspaceKeyStore {
71
+ /** Return the active row for this exact product scope. */
72
+ getActive(scope: DurableWorkspaceKeyScope): Promise<DurableWorkspaceKeyRecord | null>;
73
+ /** Return every unfinished provisioning row for this exact product scope. */
74
+ listProvisioning(scope: DurableWorkspaceKeyScope): Promise<DurableWorkspaceKeyProvisioningRecord[]>;
75
+ /** Insert before the remote create so a crashed create can be recovered. */
76
+ insertProvisioning(record: DurableWorkspaceKeyProvisioningRecord): Promise<void>;
77
+ /** Save the remote id while the row remains in provisioning state. */
78
+ markProvisioningRemote(input: {
79
+ id: string;
80
+ keyId: string;
81
+ }): Promise<void>;
82
+ /** Promote a fully encrypted row to active state. */
83
+ markActive(input: {
84
+ id: string;
85
+ keyId: string;
86
+ keyEncrypted: string;
87
+ expiresAt: Date;
88
+ budgetUsd: number;
89
+ }): Promise<void>;
90
+ /** Keep a failed cleanup visible and schedule a later retry. */
91
+ markRevocationPending(input: {
92
+ id: string;
93
+ error?: string | null;
94
+ nextAttemptAt: Date;
95
+ incrementAttempts: boolean;
96
+ }): Promise<void>;
97
+ /** Mark a remote key as revoked. Missing remote keys count as revoked. */
98
+ markRevoked(id: string, now: Date): Promise<void>;
99
+ /** Mark a provisioning row terminal when no remote key remains to clean. */
100
+ markOrphaned(id: string, error: string): Promise<void>;
101
+ /** Query due cleanup rows. The implementation should filter by the supplied scope. */
102
+ listPendingRevocations(input: {
103
+ product: WorkspaceKeyProduct;
104
+ workspaceId?: string;
105
+ ownerUserId?: string;
106
+ now: Date;
107
+ limit: number;
108
+ /** Include rows scheduled for a later retry when checking before issuance. */
109
+ includeFuture?: boolean;
110
+ }): Promise<DurableWorkspaceKeyRecord[]>;
111
+ /** Acquire a cross-process lease for one product/workspace/owner scope. */
112
+ acquireLease(scope: string, operationId: string, now: Date, leaseMs: number): Promise<boolean>;
113
+ /** Renew an acquired lease before its expiry. */
114
+ renewLease(scope: string, operationId: string, now: Date, leaseMs: number): Promise<boolean>;
115
+ /** Release an acquired lease. */
116
+ releaseLease(scope: string, operationId: string): Promise<void>;
117
+ }
118
+ /** Live budget information for a child key. */
119
+ export interface WorkspaceKeyUsage {
120
+ keyId: string;
121
+ budgetUsd: number;
122
+ budgetSpent: number;
123
+ budgetRemaining: number;
124
+ expiresAt: string;
125
+ exhausted: boolean;
126
+ }
127
+ /** The decrypted key plus the usage snapshot used to issue it. */
128
+ export interface WorkspaceRuntimeKey {
129
+ key: string;
130
+ usage: WorkspaceKeyUsage;
131
+ /** True when this call minted a new remote key. */
132
+ refreshed: boolean;
133
+ }
134
+ /** Identity-bound durable key manager API. */
135
+ export interface DurableWorkspaceKeyManager {
136
+ /** Reuse a matching active key or reconcile and mint one under a lease. */
137
+ ensureKey(identity: WorkspaceKeyIdentity, options?: {
138
+ budgetUsd?: number;
139
+ }): Promise<WorkspaceRuntimeKey>;
140
+ /** Read usage without returning the child secret. */
141
+ getUsage(identity: WorkspaceKeyIdentity): Promise<WorkspaceKeyUsage | null>;
142
+ /** Retry due cleanup rows. A supplied owner/workspace limits the retry to its scope. */
143
+ retryPendingRevocations(scope?: Pick<WorkspaceKeyIdentity, 'ownerUserId' | 'workspaceId'>): Promise<number>;
144
+ }
145
+ /** Configuration for {@link createIdentityBoundWorkspaceKeyManager}. */
146
+ export interface DurableWorkspaceKeyManagerOptions {
147
+ store: DurableWorkspaceKeyStore;
148
+ provisioner: DurableWorkspaceKeyProvisioner;
149
+ crypto: KeyCrypto;
150
+ /** Product partition. Products must use separate values. */
151
+ product: WorkspaceKeyProduct;
152
+ defaultBudgetUsd: number;
153
+ now?: () => Date;
154
+ /** Local lifetime used when the remote response omits an expiry. */
155
+ keyLifetimeMs?: number;
156
+ /** Lease lifetime for remote operations. */
157
+ leaseMs?: number;
158
+ /** Maximum time to wait for another issuer to release the scope lease. */
159
+ leaseWaitMs?: number;
160
+ /** Poll delay while waiting for a scope lease. */
161
+ leasePollMs?: number;
162
+ /** Renewal interval. It must be shorter than `leaseMs`. */
163
+ leaseRenewIntervalMs?: number;
164
+ /** Initial delay for a failed remote revoke. */
165
+ revocationRetryBaseMs?: number;
166
+ /** Maximum delay for a failed remote revoke. */
167
+ revocationRetryMaxMs?: number;
168
+ /** Stable remote name. The operation id makes the default crash-safe. */
169
+ nameForIdentity?: (identity: WorkspaceKeyIdentity, operationId: string) => string;
170
+ /** Resolve names for rows written before `name` became durable. Null blocks issuance safely. */
171
+ legacyNameForRecord?: (record: DurableWorkspaceKeyRecord) => string | null | undefined;
172
+ /** Recognize a missing remote key without depending on a provider SDK. */
173
+ isRemoteMissing?: (error: unknown) => boolean;
174
+ }
175
+ /**
176
+ * Create a product-neutral manager for child-key issuance and cleanup.
177
+ *
178
+ * The provisioner must already be authenticated for the current source
179
+ * credential. The manager persists only the source id and its non-secret
180
+ * fingerprint, then refuses to reuse a row from another identity.
181
+ */
182
+ export declare function createIdentityBoundWorkspaceKeyManager(options: DurableWorkspaceKeyManagerOptions): DurableWorkspaceKeyManager;
183
+ export {};
@@ -239,3 +239,4 @@ export interface PlatformBalanceManager<Plan extends string> {
239
239
  export declare function createPlatformBalanceManager<Plan extends string>(opts: PlatformBalanceManagerOptions<Plan>): PlatformBalanceManager<Plan>;
240
240
  /** Create a workspace key manager that handles key provisioning and budget tracking */
241
241
  export declare function createWorkspaceKeyManager(opts: WorkspaceKeyManagerOptions): WorkspaceKeyManager;
242
+ export { createIdentityBoundWorkspaceKeyManager, type DurableWorkspaceKeyManager, type DurableWorkspaceKeyManagerOptions, type DurableWorkspaceKeyProvisioner, type DurableWorkspaceKeyProvisioningRecord, type DurableWorkspaceKeyRecord, type DurableWorkspaceKeyScope, type DurableWorkspaceKeyStore, type WorkspaceKeyIdentity, type WorkspaceKeyProduct, type WorkspaceKeyStatus, type WorkspaceKeyUsage, type WorkspaceRuntimeKey, } from './identity-bound';
@@ -1,9 +1,11 @@
1
1
  import {
2
+ createIdentityBoundWorkspaceKeyManager,
2
3
  createPlatformBalanceManager,
3
4
  createTcloudKeyProvisioner,
4
5
  createWorkspaceKeyManager
5
- } from "../chunk-GXE6KHTS.js";
6
+ } from "../chunk-TS2ZIB53.js";
6
7
  export {
8
+ createIdentityBoundWorkspaceKeyManager,
7
9
  createPlatformBalanceManager,
8
10
  createTcloudKeyProvisioner,
9
11
  createWorkspaceKeyManager
@@ -112,7 +112,7 @@ import {
112
112
  flattenHistory,
113
113
  readSandboxBinaryBytes,
114
114
  statSandboxFileSize
115
- } from "../chunk-FS6YF4ZV.js";
115
+ } from "../chunk-T374KO42.js";
116
116
  import "../chunk-MCYJON3F.js";
117
117
  import "../chunk-LWSJK546.js";
118
118
  import "../chunk-P5PIAQVS.js";
@@ -2672,12 +2672,16 @@ async function driveSandboxTurn(shell, box, message, options) {
2672
2672
  sessionId: options.sessionId,
2673
2673
  ...options.turnId ? { turnId: options.turnId } : {},
2674
2674
  ...options.wallCapMs !== void 0 ? { wallCapMs: options.wallCapMs } : {},
2675
- ...options.executionId ? { executionId: options.executionId } : {},
2676
2675
  ...options.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : {},
2677
2676
  ...options.signal ? { signal: options.signal } : {},
2678
- // Deliberately NO `interactions` here: detached turns (cron / mission steps) have
2679
- // no consumer to answer a question. Interactive Q&A is streaming-path only.
2680
- backend: { type: harness, profile, ...model ? { model } : {} }
2677
+ // A durable caller with a session-gateway consumer can handle these events;
2678
+ // callers without one should omit interactions so the run stays unattended.
2679
+ backend: {
2680
+ type: harness,
2681
+ profile,
2682
+ ...model ? { model } : {},
2683
+ ...options.interactions ? { interactions: options.interactions } : {}
2684
+ }
2681
2685
  });
2682
2686
  emitSandboxActivity(options.spend, box);
2683
2687
  return ok(drive);
@@ -2829,4 +2833,4 @@ export {
2829
2833
  isTerminalPromptEvent,
2830
2834
  detectInteractiveQuestion
2831
2835
  };
2832
- //# sourceMappingURL=chunk-FS6YF4ZV.js.map
2836
+ //# sourceMappingURL=chunk-T374KO42.js.map