@atlasent/sdk 1.5.0 → 2.5.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/README.md +106 -27
- package/dist/hono.cjs +1507 -62
- package/dist/hono.cjs.map +1 -1
- package/dist/hono.d.cts +4 -4
- package/dist/hono.d.ts +4 -4
- package/dist/hono.js +1497 -62
- package/dist/hono.js.map +1 -1
- package/dist/index.cjs +3038 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3940 -496
- package/dist/index.d.ts +3940 -496
- package/dist/index.js +2932 -110
- package/dist/index.js.map +1 -1
- package/dist/protect-DiRVfVLq.d.cts +1329 -0
- package/dist/protect-DiRVfVLq.d.ts +1329 -0
- package/dist/state.cjs +46 -0
- package/dist/state.cjs.map +1 -0
- package/dist/state.d.cts +152 -0
- package/dist/state.d.ts +152 -0
- package/dist/state.js +21 -0
- package/dist/state.js.map +1 -0
- package/package.json +24 -2
- package/dist/protect-BKxcoR_2.d.cts +0 -159
- package/dist/protect-BKxcoR_2.d.ts +0 -159
package/dist/index.d.ts
CHANGED
|
@@ -1,599 +1,4035 @@
|
|
|
1
|
+
import { R as RateLimitState, c as AtlaSentClientOptions, E as EvaluateRequest, d as EvaluateResponse, e as EvaluatePreflightResponse, V as VerifyPermitRequest, f as VerifyPermitResponse, D as DeployGateRequest, g as DeployGateResponse, h as RevokePermitRequest, i as RevokePermitResponse, j as RevokePermitByIdInput, k as RevokePermitByIdResponse, l as VerifyPermitByIdResponse, G as GetPermitResponse, m as PermitValidResponse, L as ListPermitsRequest, n as ListPermitsResponse, o as ApiKeySelfResponse, p as AuditEventsQuery, q as AuditEventsResult, r as AuditExportRequest, s as AuditExportResult, S as StreamOptions, t as StreamEvent, b as ProtectRequest, P as Permit, a as AtlaSentError, u as protect, v as deployGate, w as configure, A as AtlaSentDeniedError } from './protect-DiRVfVLq.js';
|
|
2
|
+
export { x as AtlaSentDecision, y as AtlaSentDeniedErrorInit, z as AtlaSentErrorCode, B as AtlaSentErrorInit, C as AtlaSentEscalateError, F as AtlaSentEscalateErrorInit, H as AuditDecision, I as AuditEvent, J as AuditEventsPage, K as AuditExport, M as AuditExportSignatureStatus, N as ConfigureOptions, O as ConstraintTrace, Q as ConstraintTracePolicy, T as ConstraintTraceStage, U as DEFAULT_RETRY_POLICY, W as DEPLOYMENT_PRODUCTION_ACTION, X as DEPLOY_GATE_CODES, Y as Decision, Z as DecisionCanonical, _ as DeployGateContext, $ as DeployGateDenyCode, a0 as DeployGateEvidence, a1 as DeployOverrideClaim, a2 as DeployPermitClaim, a3 as EvaluateResponsePermit, a4 as PRODUCTION_DEPLOY_ACTION, a5 as PermitOutcome, a6 as PermitRecord, a7 as PermitRevoked, a8 as PermitStatus, a9 as RetryPolicy, aa as StreamDecisionEvent, ab as StreamParseError, ac as StreamProgressEvent, ad as StreamTimeoutError, ae as computeBackoffMs, af as hasAttemptsLeft, ag as isRetryable, ah as mergePolicy, ai as normalizePermitOutcome } from './protect-DiRVfVLq.js';
|
|
1
3
|
import { webcrypto } from 'node:crypto';
|
|
2
|
-
import { p as protect, c as configure, a as AtlaSentError, A as AtlaSentDeniedError } from './protect-BKxcoR_2.js';
|
|
3
|
-
export { d as AtlaSentDecision, e as AtlaSentDeniedErrorInit, f as AtlaSentErrorCode, g as AtlaSentErrorInit, C as ConfigureOptions, P as Permit, b as ProtectRequest } from './protect-BKxcoR_2.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Dual-shape input bridge for the v2.0.0 wire format change.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* at the top of that file describes these shapes. Keep this module in
|
|
12
|
-
* lockstep with it; `test/audit-types.test.ts` contains type-level
|
|
13
|
-
* assertions against the field set to make drift obvious.
|
|
8
|
+
* The v2.0.0 wire format renamed the evaluate request fields:
|
|
9
|
+
* OLD: { action, agent, context, api_key }
|
|
10
|
+
* NEW: { action_type, actor_id, context }
|
|
14
11
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
12
|
+
* And the response fields:
|
|
13
|
+
* OLD: { permitted, decision_id }
|
|
14
|
+
* NEW: { decision, permit_token }
|
|
15
|
+
*
|
|
16
|
+
* TypeScript callers on the old v1.x request shape receive a
|
|
17
|
+
* deprecation warning and are transparently upgraded to the new
|
|
18
|
+
* shape. The response compat bridge normalises the legacy
|
|
19
|
+
* `permitted` boolean to `decision === "allow"`.
|
|
20
|
+
*
|
|
21
|
+
* Both shims will be removed in v3.0.0.
|
|
22
|
+
*/
|
|
23
|
+
/** Legacy v1.x evaluate request shape. */
|
|
24
|
+
interface LegacyEvaluateRequest {
|
|
25
|
+
action?: string;
|
|
26
|
+
agent?: string;
|
|
27
|
+
context?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
/** v2.0 evaluate request shape (canonical wire format). */
|
|
30
|
+
interface V2EvaluateRequest {
|
|
31
|
+
action_type: string;
|
|
32
|
+
actor_id: string;
|
|
33
|
+
context?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Normalise an evaluate request from either the legacy v1.x shape
|
|
37
|
+
* (`action` / `agent`) or the current v2.0 shape (`action_type` /
|
|
38
|
+
* `actor_id`) into the canonical v2.0 wire format.
|
|
39
|
+
*
|
|
40
|
+
* When the legacy shape is detected a `console.warn` deprecation
|
|
41
|
+
* notice is emitted once per call-site process lifetime. The shim
|
|
42
|
+
* will be removed in v3.0.0.
|
|
43
|
+
*/
|
|
44
|
+
declare function normalizeEvaluateRequest(input: LegacyEvaluateRequest | V2EvaluateRequest): V2EvaluateRequest;
|
|
45
|
+
/**
|
|
46
|
+
* Legacy v1.x evaluate response shape returned by older server
|
|
47
|
+
* deployments.
|
|
20
48
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
49
|
+
interface LegacyEvaluateResponse {
|
|
50
|
+
permitted?: boolean;
|
|
51
|
+
decision_id?: string;
|
|
52
|
+
reason?: string;
|
|
53
|
+
audit_hash?: string;
|
|
54
|
+
timestamp?: string;
|
|
55
|
+
}
|
|
56
|
+
/** v2.0 evaluate response shape (canonical wire format). */
|
|
57
|
+
interface V2EvaluateResponse {
|
|
58
|
+
decision: 'allow' | 'deny' | 'hold' | 'escalate';
|
|
59
|
+
permit_token?: string;
|
|
60
|
+
request_id?: string;
|
|
61
|
+
expires_at?: string;
|
|
62
|
+
denial?: {
|
|
63
|
+
reason?: string;
|
|
64
|
+
code?: string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
23
67
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
68
|
+
* Normalise an evaluate response from either the legacy v1.x shape
|
|
69
|
+
* (`permitted` / `decision_id`) or the current v2.0 shape
|
|
70
|
+
* (`decision` / `permit_token`) into the canonical v2.0 wire format.
|
|
71
|
+
*
|
|
72
|
+
* Used internally by the client to tolerate older atlasent-api
|
|
73
|
+
* deployments without surfacing the impedance mismatch to callers.
|
|
28
74
|
*/
|
|
29
|
-
|
|
75
|
+
declare function normalizeEvaluateResponse(wire: LegacyEvaluateResponse | V2EvaluateResponse): V2EvaluateResponse;
|
|
76
|
+
|
|
30
77
|
/**
|
|
31
|
-
*
|
|
32
|
-
* `GET /v1/audit/events` and embedded inside `AuditExport.events`.
|
|
78
|
+
* Human-in-the-loop (HITL) types — wire shape for `/v1/hitl/*`.
|
|
33
79
|
*
|
|
34
|
-
* `
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
80
|
+
* Mirrors `supabase/functions/_shared/hitl-policy.ts` and the
|
|
81
|
+
* `hitl_escalations` row shape after migration 20260507060000.
|
|
82
|
+
* Treat as wire-types only: do not embed business logic that the
|
|
83
|
+
* server-side resolver owns (quorum math, status transitions).
|
|
38
84
|
*/
|
|
39
|
-
|
|
40
|
-
|
|
85
|
+
type HitlQuorumTier = "single_approver" | "simple_majority" | "two_thirds" | "unanimous";
|
|
86
|
+
type HitlStatus = "pending" | "escalated" | "approved" | "rejected" | "auto_approved" | "timed_out";
|
|
87
|
+
type HitlFallbackDecision = "reject" | "approve";
|
|
88
|
+
interface HitlQuorumProgress {
|
|
89
|
+
required: number;
|
|
90
|
+
approved: number;
|
|
91
|
+
rejected: number;
|
|
92
|
+
remaining: number;
|
|
93
|
+
satisfied: boolean;
|
|
94
|
+
rejected_terminal: boolean;
|
|
95
|
+
}
|
|
96
|
+
interface HitlEscalation {
|
|
41
97
|
id: string;
|
|
42
|
-
/** Organization this event belongs to. */
|
|
43
98
|
org_id: string;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
99
|
+
agent_id: string;
|
|
100
|
+
sandbox_run_id: string | null;
|
|
101
|
+
status: HitlStatus;
|
|
102
|
+
escalation_reason: string;
|
|
103
|
+
proposed_action: Record<string, unknown> | null;
|
|
104
|
+
risk_score: number | null;
|
|
105
|
+
assigned_to_user_id: string | null;
|
|
106
|
+
assigned_to_role: string | null;
|
|
107
|
+
resolved_by: string | null;
|
|
108
|
+
resolution_note: string | null;
|
|
109
|
+
auto_approved_reason: string | null;
|
|
110
|
+
resolved_at: string | null;
|
|
111
|
+
timeout_at: string | null;
|
|
112
|
+
created_at: string;
|
|
113
|
+
quorum_required: HitlQuorumTier;
|
|
114
|
+
min_approvers: number;
|
|
115
|
+
approver_pool_size: number;
|
|
116
|
+
escalation_depth: number;
|
|
117
|
+
max_escalation_depth: number;
|
|
118
|
+
fallback_decision: HitlFallbackDecision;
|
|
119
|
+
governance_advisory_id: string | null;
|
|
120
|
+
expired_reason: "sla_expired" | "escalation_chain_exhausted" | "manual_expire" | null;
|
|
121
|
+
/**
|
|
122
|
+
* Arbitrary key/value metadata attached at creation time.
|
|
123
|
+
* `null` when none was provided.
|
|
124
|
+
*/
|
|
125
|
+
metadata: Record<string, unknown> | null;
|
|
126
|
+
quorum_progress?: HitlQuorumProgress;
|
|
127
|
+
approver_pool?: HitlApproverPoolEntry[];
|
|
128
|
+
quorum_threshold?: number | null;
|
|
129
|
+
ai_unavailable_fallback?: HitlAiUnavailableFallback;
|
|
130
|
+
fallback_human_role?: string | null;
|
|
131
|
+
pool_unavailable_at?: string | null;
|
|
132
|
+
/** Populated when the server attaches a heterogeneous-quorum tally. */
|
|
133
|
+
heterogeneous_tally?: HitlHeterogeneousQuorumTally;
|
|
134
|
+
}
|
|
135
|
+
interface HitlApprovalRecord {
|
|
136
|
+
id: string;
|
|
137
|
+
user_id: string | null;
|
|
138
|
+
actor_label: string | null;
|
|
139
|
+
decision: "approve" | "reject";
|
|
140
|
+
note: string | null;
|
|
141
|
+
quorum_at_vote: HitlQuorumTier;
|
|
142
|
+
created_at: string;
|
|
143
|
+
/** Which kind of approver cast this vote (default `"human"`). */
|
|
144
|
+
approver_type?: HitlApproverType;
|
|
145
|
+
}
|
|
146
|
+
interface HitlChainHop {
|
|
147
|
+
id: string;
|
|
148
|
+
depth: number;
|
|
149
|
+
from_user_id: string | null;
|
|
150
|
+
from_role: string | null;
|
|
151
|
+
to_user_id: string | null;
|
|
152
|
+
to_role: string | null;
|
|
153
|
+
escalated_by: string | null;
|
|
154
|
+
reason: string | null;
|
|
155
|
+
created_at: string;
|
|
156
|
+
}
|
|
157
|
+
interface ListHitlEscalationsRequest {
|
|
158
|
+
status?: HitlStatus;
|
|
159
|
+
agentId?: string;
|
|
160
|
+
assignedToUserId?: string;
|
|
161
|
+
limit?: number;
|
|
162
|
+
cursor?: string;
|
|
163
|
+
}
|
|
164
|
+
interface ListHitlEscalationsResponse {
|
|
165
|
+
escalations: HitlEscalation[];
|
|
166
|
+
total: number;
|
|
167
|
+
next_cursor?: string;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Wire shape for `POST /v1/hitl` — open a new escalation.
|
|
171
|
+
*
|
|
172
|
+
* The agent-side bridge between a `hold` outcome from `protect()`
|
|
173
|
+
* and the approval queue. Only `agent_id` and `escalation_reason`
|
|
174
|
+
* are required; the rest map to defaults configured on the
|
|
175
|
+
* server-side policy. Pass `approver_pool` to use the heterogeneous
|
|
176
|
+
* N-of-M extension instead of the homogeneous quorum tier.
|
|
177
|
+
*/
|
|
178
|
+
interface HitlCreateRequest {
|
|
179
|
+
agent_id: string;
|
|
180
|
+
escalation_reason: string;
|
|
181
|
+
sandbox_run_id?: string;
|
|
182
|
+
proposed_action?: Record<string, unknown>;
|
|
183
|
+
risk_score?: number;
|
|
184
|
+
assigned_to_user_id?: string;
|
|
185
|
+
assigned_to_role?: string;
|
|
186
|
+
quorum_required?: HitlQuorumTier;
|
|
187
|
+
min_approvers?: number;
|
|
188
|
+
approver_pool_size?: number;
|
|
189
|
+
max_escalation_depth?: number;
|
|
190
|
+
fallback_decision?: HitlFallbackDecision;
|
|
191
|
+
timeout_at?: string;
|
|
192
|
+
governance_advisory_id?: string;
|
|
193
|
+
approver_pool?: HitlApproverPoolEntry[];
|
|
194
|
+
quorum_threshold?: number;
|
|
195
|
+
ai_unavailable_fallback?: HitlAiUnavailableFallback;
|
|
196
|
+
fallback_human_role?: string;
|
|
197
|
+
/** Arbitrary key/value metadata to attach to the escalation record. */
|
|
198
|
+
metadata?: Record<string, unknown>;
|
|
199
|
+
}
|
|
200
|
+
interface HitlApproveRequest {
|
|
201
|
+
note?: string;
|
|
202
|
+
}
|
|
203
|
+
interface HitlRejectRequest {
|
|
204
|
+
note?: string;
|
|
205
|
+
}
|
|
206
|
+
interface HitlEscalateRequest {
|
|
207
|
+
to_role?: string;
|
|
208
|
+
to_user_id?: string;
|
|
209
|
+
reason?: string;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Wire shape for `POST /v1/escalations/:id/respond` — cast a vote on an
|
|
213
|
+
* existing escalation. Mirrors the `RespondBody` schema in
|
|
214
|
+
* atlasent-control-plane `api/src/routes/hitl.ts`.
|
|
215
|
+
*/
|
|
216
|
+
interface HitlRespondRequest {
|
|
217
|
+
/** The approver's decision. */
|
|
218
|
+
decision: "approve" | "reject";
|
|
219
|
+
/** Optional human-readable note attached to the approval record. */
|
|
220
|
+
note?: string;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Translate a quorum tier and approver-pool size to the minimum
|
|
224
|
+
* number of `approve` votes required to resolve the escalation.
|
|
225
|
+
*
|
|
226
|
+
* Mirrors the canonical `requiredApproverCount()` in
|
|
227
|
+
* atlasent-api `_shared/hitl-policy.ts` and the SQL
|
|
228
|
+
* `public.hitl_required_approver_count()` helper. Provided here so
|
|
229
|
+
* SDK consumers can render a "you are the Nth of M approvers" hint
|
|
230
|
+
* without a server round-trip; the authoritative count still comes
|
|
231
|
+
* from the server's `quorum_progress` payload.
|
|
232
|
+
*/
|
|
233
|
+
declare function hitlRequiredApproverCount(quorum: HitlQuorumTier, poolSize: number): number;
|
|
234
|
+
type HitlApproverType = "human" | "ai_supervisor" | "automated_compliance" | "hardware_signer" | "service_account";
|
|
235
|
+
type HitlAiUnavailableFallback = "escalate_to_human" | "reduce_pool" | "fail_closed";
|
|
236
|
+
interface HitlApproverPoolEntry {
|
|
237
|
+
type: HitlApproverType;
|
|
238
|
+
principal_id: string;
|
|
239
|
+
role?: string;
|
|
240
|
+
weight?: number;
|
|
241
|
+
required?: boolean;
|
|
242
|
+
/** Marker for slots inserted by the AI-unavailable fallback. */
|
|
243
|
+
origin?: string;
|
|
244
|
+
}
|
|
245
|
+
interface HitlHeterogeneousQuorumExtension {
|
|
246
|
+
approver_pool: HitlApproverPoolEntry[];
|
|
247
|
+
quorum_threshold: number | null;
|
|
248
|
+
ai_unavailable_fallback: HitlAiUnavailableFallback;
|
|
249
|
+
fallback_human_role: string | null;
|
|
250
|
+
pool_unavailable_at: string | null;
|
|
251
|
+
}
|
|
252
|
+
interface HitlHeterogeneousQuorumTally {
|
|
253
|
+
pool_size: number;
|
|
254
|
+
effective_pool_size: number;
|
|
255
|
+
required_threshold: number;
|
|
256
|
+
approve_count: number;
|
|
257
|
+
reject_count: number;
|
|
258
|
+
unavailable_count: number;
|
|
259
|
+
/** Per-approver-type breakdown: `{ ai_supervisor: { approve: 1, reject: 0 } }` */
|
|
260
|
+
by_type: Record<HitlApproverType, {
|
|
261
|
+
approve: number;
|
|
262
|
+
reject: number;
|
|
263
|
+
}>;
|
|
264
|
+
meets_threshold: boolean;
|
|
265
|
+
any_required_reject: boolean;
|
|
266
|
+
any_required_missing: boolean;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Detail response returned by `GET /v1/escalations/:id`.
|
|
270
|
+
*
|
|
271
|
+
* Mirrors `HitlDetailResponse` in atlasent-control-plane
|
|
272
|
+
* `api/src/schemas/hitl.ts`.
|
|
273
|
+
*/
|
|
274
|
+
interface HitlDetailResponse {
|
|
275
|
+
escalation: HitlEscalation;
|
|
276
|
+
approval_records: HitlApprovalRecord[];
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Paginated list response returned by `GET /v1/escalations`.
|
|
280
|
+
*
|
|
281
|
+
* Mirrors `HitlListResponse` in atlasent-control-plane
|
|
282
|
+
* `api/src/schemas/hitl.ts`.
|
|
283
|
+
*/
|
|
284
|
+
interface HitlListResponse {
|
|
285
|
+
escalations: HitlEscalation[];
|
|
286
|
+
total: number;
|
|
287
|
+
next_cursor: string | null;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Governance graph types: named query results, graph node/edge shapes.
|
|
292
|
+
*
|
|
293
|
+
* Mirrors the `query_governance_graph()` SQL function dispatched by
|
|
294
|
+
* `GET /v1/governance/graph/query?type=<query_type>`.
|
|
295
|
+
*/
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Named traversal queries dispatched by `query_governance_graph()`.
|
|
299
|
+
*
|
|
300
|
+
* | Type | Returns |
|
|
301
|
+
* |---|---|
|
|
302
|
+
* | `production_deployers` | Actors with `executed_in → environment=production` edges |
|
|
303
|
+
* | `execution_approvers` | Actors as targets of `approved_by` edges |
|
|
304
|
+
* | `quorum_bypass_connectors` | Connector nodes with outbound `violates` edges |
|
|
305
|
+
* | `emergency_override_actions` | Execution nodes with `metadata.used_override = true` |
|
|
306
|
+
* | `connected_systems` | Connector/service/external-system nodes with `connected_to`/`synced_from` edges |
|
|
307
|
+
* | `user_approvals` | `approved_by` edges where target `external_id = params.actor_id` (requires `actor_id` param) |
|
|
308
|
+
*/
|
|
309
|
+
type GovernanceGraphQueryType = "production_deployers" | "execution_approvers" | "quorum_bypass_connectors" | "emergency_override_actions" | "connected_systems" | "user_approvals";
|
|
310
|
+
/**
|
|
311
|
+
* Node type values from the `graph_node_type` DB enum.
|
|
312
|
+
* Additional values may be introduced server-side; treat as open.
|
|
313
|
+
*/
|
|
314
|
+
type GraphNodeType = "execution" | "permit" | "incident" | "connector" | "service" | "external_system" | "actor" | "policy" | "environment" | (string & Record<never, never>);
|
|
315
|
+
/**
|
|
316
|
+
* Edge type values from the `graph_edge_type` DB enum.
|
|
317
|
+
* Additional values may be introduced server-side; treat as open.
|
|
318
|
+
*/
|
|
319
|
+
type GraphEdgeType = "governed_by" | "incident_involves" | "synced_from" | "approved_by" | "executed_in" | "violates" | "connected_to" | (string & Record<never, never>);
|
|
320
|
+
/** Full graph node row returned by `GET /v1/governance/graph`. */
|
|
321
|
+
interface GraphNode {
|
|
322
|
+
id: string;
|
|
323
|
+
org_id: string;
|
|
324
|
+
node_type: GraphNodeType;
|
|
325
|
+
external_id: string | null;
|
|
326
|
+
metadata: Record<string, unknown>;
|
|
327
|
+
created_at: string;
|
|
328
|
+
updated_at: string;
|
|
329
|
+
}
|
|
330
|
+
/** Full graph edge row returned by `GET /v1/governance/graph/edges`. */
|
|
331
|
+
interface GraphEdge {
|
|
332
|
+
id: string;
|
|
333
|
+
org_id: string;
|
|
334
|
+
edge_type: GraphEdgeType;
|
|
335
|
+
source_node_id: string;
|
|
336
|
+
target_node_id: string;
|
|
337
|
+
metadata: Record<string, unknown>;
|
|
338
|
+
created_at: string;
|
|
339
|
+
}
|
|
340
|
+
/** Row returned by `query_type = "production_deployers"`. */
|
|
341
|
+
interface ProductionDeployerRow {
|
|
342
|
+
node_id: string;
|
|
343
|
+
actor_id: string | null;
|
|
344
|
+
exec_count: number;
|
|
345
|
+
last_seen: string | null;
|
|
346
|
+
}
|
|
347
|
+
/** Row returned by `query_type = "execution_approvers"`. */
|
|
348
|
+
interface ExecutionApproverRow {
|
|
349
|
+
node_id: string;
|
|
350
|
+
actor_id: string | null;
|
|
351
|
+
approval_count: number;
|
|
352
|
+
}
|
|
353
|
+
/** Row returned by `query_type = "quorum_bypass_connectors"`. */
|
|
354
|
+
interface QuorumBypassConnectorRow {
|
|
355
|
+
node_id: string;
|
|
356
|
+
connector_id: string | null;
|
|
357
|
+
violation_count: number;
|
|
358
|
+
}
|
|
359
|
+
/** Row returned by `query_type = "emergency_override_actions"`. */
|
|
360
|
+
interface EmergencyOverrideActionRow {
|
|
361
|
+
node_id: string;
|
|
362
|
+
execution_id: string | null;
|
|
363
|
+
actor_id: string | null;
|
|
364
|
+
timestamp: string | null;
|
|
365
|
+
}
|
|
366
|
+
/** Row returned by `query_type = "connected_systems"`. */
|
|
367
|
+
interface ConnectedSystemRow {
|
|
368
|
+
node_id: string;
|
|
369
|
+
system_id: string | null;
|
|
370
|
+
node_type: GraphNodeType;
|
|
371
|
+
edge_type: GraphEdgeType;
|
|
372
|
+
}
|
|
373
|
+
/** Row returned by `query_type = "user_approvals"`. */
|
|
374
|
+
interface UserApprovalRow {
|
|
375
|
+
edge_id: string;
|
|
376
|
+
source_node_id: string;
|
|
377
|
+
created_at: string;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Conditional type mapping each {@link GovernanceGraphQueryType} to its
|
|
381
|
+
* per-row result shape. Use as `GovernanceGraphResultRow<"production_deployers">`.
|
|
382
|
+
*/
|
|
383
|
+
type GovernanceGraphResultRow<T extends GovernanceGraphQueryType = GovernanceGraphQueryType> = T extends "production_deployers" ? ProductionDeployerRow : T extends "execution_approvers" ? ExecutionApproverRow : T extends "quorum_bypass_connectors" ? QuorumBypassConnectorRow : T extends "emergency_override_actions" ? EmergencyOverrideActionRow : T extends "connected_systems" ? ConnectedSystemRow : T extends "user_approvals" ? UserApprovalRow : Record<string, unknown>;
|
|
384
|
+
/**
|
|
385
|
+
* Optional parameters for `queryGovernanceGraph()`.
|
|
386
|
+
*
|
|
387
|
+
* `actor_id` is required when `query_type = "user_approvals"`.
|
|
388
|
+
*/
|
|
389
|
+
interface GovernanceGraphQueryParams {
|
|
390
|
+
actor_id?: string;
|
|
391
|
+
}
|
|
392
|
+
/** Response from {@link AtlaSentClient.queryGovernanceGraph}. */
|
|
393
|
+
interface GovernanceGraphQueryResponse<T extends GovernanceGraphQueryType = GovernanceGraphQueryType> {
|
|
394
|
+
query_type: T;
|
|
395
|
+
results: GovernanceGraphResultRow<T>[];
|
|
396
|
+
org_id: string;
|
|
397
|
+
rateLimit: RateLimitState | null;
|
|
398
|
+
}
|
|
399
|
+
/** Response from `listGraphNodes()`. */
|
|
400
|
+
interface ListGraphNodesResponse {
|
|
401
|
+
nodes: GraphNode[];
|
|
402
|
+
total: number;
|
|
403
|
+
nextCursor?: string;
|
|
404
|
+
rateLimit: RateLimitState | null;
|
|
405
|
+
}
|
|
406
|
+
/** Response from `listGraphEdges()`. */
|
|
407
|
+
interface ListGraphEdgesResponse {
|
|
408
|
+
edges: GraphEdge[];
|
|
409
|
+
total: number;
|
|
410
|
+
nextCursor?: string;
|
|
411
|
+
rateLimit: RateLimitState | null;
|
|
412
|
+
}
|
|
413
|
+
/** Input for `createGraphNode()`. */
|
|
414
|
+
interface CreateGraphNodeInput {
|
|
415
|
+
node_type: GraphNodeType;
|
|
416
|
+
external_id?: string;
|
|
417
|
+
metadata?: Record<string, unknown>;
|
|
418
|
+
}
|
|
419
|
+
/** Input for `createGraphEdge()`. */
|
|
420
|
+
interface CreateGraphEdgeInput {
|
|
421
|
+
edge_type: GraphEdgeType;
|
|
422
|
+
source_node_id: string;
|
|
423
|
+
target_node_id: string;
|
|
424
|
+
metadata?: Record<string, unknown>;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Incident reconstruction types: shapes returned by
|
|
429
|
+
* `reconstruct_incident_chains_v2()` via
|
|
430
|
+
* `GET /v1/governance/timeline/incident/{incidentId}`.
|
|
431
|
+
*/
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Single execution row returned by `reconstruct_incident_chains_v2()`.
|
|
435
|
+
*
|
|
436
|
+
* All §13.1 additive columns are nullable — rows inserted before the
|
|
437
|
+
* migration have `null` for any field added after their insert.
|
|
438
|
+
*/
|
|
439
|
+
interface IncidentChainExecutionRow {
|
|
440
|
+
execution_id: string;
|
|
51
441
|
actor_id: string | null;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
442
|
+
action_id: string | null;
|
|
443
|
+
/** Broad action category (e.g. `"write"`, `"admin"`). */
|
|
444
|
+
action_class: string | null;
|
|
445
|
+
outcome: string | null;
|
|
446
|
+
started_at: string | null;
|
|
447
|
+
completed_at: string | null;
|
|
448
|
+
/** UUID of the delegation chain this execution belongs to. */
|
|
449
|
+
delegation_chain_id: string | null;
|
|
450
|
+
/** UUID of the original execution this is a replay of. */
|
|
451
|
+
replay_of_execution_id: string | null;
|
|
452
|
+
/** UUID of the incident this execution is linked to (§13.1 column). */
|
|
453
|
+
incident_id: string | null;
|
|
454
|
+
/** UUID of the policy version pinned at evaluate() time. */
|
|
455
|
+
policy_version_id: string | null;
|
|
456
|
+
/** UUID of the bundle version pinned at evaluate() time. */
|
|
457
|
+
bundle_version_id: string | null;
|
|
458
|
+
decision_id: string | null;
|
|
459
|
+
subject_id: string | null;
|
|
55
460
|
resource_id: string | null;
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
461
|
+
/** Structured deny/abort code (e.g. `"policy_deny"`, `"quorum_failed"`). */
|
|
462
|
+
outcome_reason: string | null;
|
|
463
|
+
parent_execution_id: string | null;
|
|
464
|
+
}
|
|
465
|
+
/** Per-actor summary within the reconstructed incident chain. */
|
|
466
|
+
interface IncidentChainActorEntry {
|
|
467
|
+
actor_id: string;
|
|
468
|
+
execution_ids: string[];
|
|
469
|
+
execution_count: number;
|
|
470
|
+
}
|
|
471
|
+
/** Evidence row bound to the incident chain (shape is open/forward-compat). */
|
|
472
|
+
type IncidentChainEvidenceRow = Record<string, unknown>;
|
|
473
|
+
/**
|
|
474
|
+
* Full response from `GET /v1/governance/timeline/incident/{incidentId}`.
|
|
475
|
+
*
|
|
476
|
+
* Backed by `reconstruct_incident_chains_v2()` which fixes the
|
|
477
|
+
* `executor_id → actor_id` bug that caused silent empty timelines
|
|
478
|
+
* in the v1 function.
|
|
479
|
+
*/
|
|
480
|
+
interface IncidentTimelineResponse {
|
|
481
|
+
incident_id: string;
|
|
482
|
+
/** All execution rows in the incident, newest first. */
|
|
483
|
+
execution_rows: IncidentChainExecutionRow[];
|
|
484
|
+
/** Per-actor rollup: which executions each actor was responsible for. */
|
|
485
|
+
actor_timeline: IncidentChainActorEntry[];
|
|
486
|
+
/** Evidence rows bound to this incident's chain. */
|
|
487
|
+
evidence: IncidentChainEvidenceRow[];
|
|
488
|
+
rateLimit: RateLimitState | null;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Connector management types: connector lifecycle, credential security,
|
|
493
|
+
* enforcement policies, audit log, and sync state.
|
|
494
|
+
*
|
|
495
|
+
* Mirrors the `v1-connectors`, `v1-connector-enforcement` edge functions
|
|
496
|
+
* and associated DB tables (connector_credentials, connector_enforcement_policies,
|
|
497
|
+
* connector_audit_log, connector_sync_state).
|
|
498
|
+
*/
|
|
499
|
+
|
|
500
|
+
/** Supported external connector types. */
|
|
501
|
+
type ConnectorType = "github" | "stripe" | "slack" | "salesforce" | "jira" | "okta" | "aws" | "gcp" | "azure" | "ci_cd" | "custom" | (string & Record<never, never>);
|
|
502
|
+
/** Connector lifecycle status. */
|
|
503
|
+
type ConnectorStatus = "pending_install" | "active" | "syncing" | "error" | "revoked";
|
|
504
|
+
/** Full connector row returned by `GET /v1/governance/connectors`. */
|
|
505
|
+
interface ConnectorRow {
|
|
506
|
+
id: string;
|
|
507
|
+
org_id: string;
|
|
508
|
+
connector_type: ConnectorType;
|
|
509
|
+
name: string;
|
|
510
|
+
environment: string;
|
|
511
|
+
status: ConnectorStatus;
|
|
512
|
+
scopes: string[];
|
|
513
|
+
config: Record<string, unknown>;
|
|
514
|
+
last_synced_at: string | null;
|
|
515
|
+
created_at: string;
|
|
516
|
+
updated_at: string;
|
|
517
|
+
}
|
|
518
|
+
/** Credential type stored in connector_credentials. */
|
|
519
|
+
type ConnectorCredentialType = "oauth_token" | "api_key" | "webhook_secret" | "service_account" | "mtls_cert";
|
|
520
|
+
/**
|
|
521
|
+
* Credential metadata row.
|
|
522
|
+
* `encrypted_value` is never returned in API responses — only metadata is exposed.
|
|
523
|
+
*/
|
|
524
|
+
interface ConnectorCredentialRow {
|
|
525
|
+
id: string;
|
|
526
|
+
org_id: string;
|
|
527
|
+
connector_id: string;
|
|
528
|
+
credential_type: ConnectorCredentialType;
|
|
529
|
+
scope: string[];
|
|
530
|
+
expires_at: string | null;
|
|
531
|
+
rotated_at: string | null;
|
|
532
|
+
rotated_by: string | null;
|
|
533
|
+
revoked_at: string | null;
|
|
534
|
+
revoked_by: string | null;
|
|
535
|
+
revoke_reason: string | null;
|
|
536
|
+
version: number;
|
|
537
|
+
created_at: string;
|
|
538
|
+
updated_at: string;
|
|
539
|
+
}
|
|
540
|
+
/** Action a connector enforcement policy can require. */
|
|
541
|
+
type EnforcementAction = "require_permit" | "require_quorum" | "require_approval" | "block" | "audit_only";
|
|
542
|
+
/** Quorum configuration embedded in enforcement policies. */
|
|
543
|
+
interface EnforcementQuorumConfig {
|
|
544
|
+
min_approvers: number;
|
|
545
|
+
required_roles?: string[];
|
|
546
|
+
timeout_minutes?: number;
|
|
547
|
+
}
|
|
548
|
+
/** Single connector enforcement policy row. */
|
|
549
|
+
interface ConnectorEnforcementPolicy {
|
|
550
|
+
id: string;
|
|
551
|
+
org_id: string;
|
|
552
|
+
connector_type: ConnectorType;
|
|
553
|
+
/** Event type that triggers policy evaluation (e.g. `"push"`, `"deploy"`, `"merge"`). */
|
|
554
|
+
trigger_event: string;
|
|
555
|
+
/** Declarative condition evaluated against the event payload. */
|
|
556
|
+
condition: Record<string, unknown>;
|
|
557
|
+
required_action: EnforcementAction;
|
|
558
|
+
quorum_config: EnforcementQuorumConfig | null;
|
|
559
|
+
/** Environments this policy applies to (e.g. `["production"]`). Empty = all. */
|
|
560
|
+
environment_scope: string[];
|
|
561
|
+
enabled: boolean;
|
|
562
|
+
/** Higher priority policies are evaluated first. */
|
|
563
|
+
priority: number;
|
|
564
|
+
created_at: string;
|
|
565
|
+
updated_at: string;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Single append-only connector audit log entry from `connector_audit_log`.
|
|
569
|
+
* Entries are never updated or deleted — only inserted.
|
|
570
|
+
*/
|
|
571
|
+
interface ConnectorAuditLogEntry {
|
|
572
|
+
id: string;
|
|
573
|
+
org_id: string;
|
|
574
|
+
connector_id: string;
|
|
575
|
+
actor_id: string | null;
|
|
576
|
+
operation: string;
|
|
577
|
+
/** `"success"` | `"failure"` | `"blocked"` */
|
|
578
|
+
outcome: string;
|
|
579
|
+
detail: Record<string, unknown>;
|
|
580
|
+
ip_address: string | null;
|
|
63
581
|
occurred_at: string;
|
|
64
|
-
|
|
582
|
+
}
|
|
583
|
+
/** Sync state snapshot for a connector (one row per connector_id). */
|
|
584
|
+
interface ConnectorSyncState {
|
|
585
|
+
id: string;
|
|
586
|
+
org_id: string;
|
|
587
|
+
connector_id: string;
|
|
588
|
+
last_sync_at: string | null;
|
|
589
|
+
/** `"success"` | `"failure"` | `"running"` | `"skipped"` */
|
|
590
|
+
last_sync_status: string | null;
|
|
591
|
+
last_sync_error: string | null;
|
|
592
|
+
/** Opaque cursor passed to the next incremental sync. */
|
|
593
|
+
sync_cursor: Record<string, unknown> | null;
|
|
594
|
+
next_sync_at: string | null;
|
|
65
595
|
created_at: string;
|
|
596
|
+
updated_at: string;
|
|
597
|
+
}
|
|
598
|
+
/** Input event for connector enforcement evaluation via `v1-connector-enforcement`. */
|
|
599
|
+
interface ConnectorEnforcementEventInput {
|
|
600
|
+
connector_id: string;
|
|
601
|
+
event_type: string;
|
|
602
|
+
actor_id?: string;
|
|
603
|
+
environment?: string;
|
|
604
|
+
payload?: Record<string, unknown>;
|
|
605
|
+
}
|
|
606
|
+
/** Result of a connector enforcement evaluation. */
|
|
607
|
+
interface ConnectorEnforcementResult {
|
|
608
|
+
/** Enforcement decision — fail-closed: defaults to `"block"` on evaluation error. */
|
|
609
|
+
decision: "permit" | "block" | "require_quorum" | "require_approval" | "audit_only";
|
|
610
|
+
policy_id: string | null;
|
|
611
|
+
reason: string;
|
|
612
|
+
audit_log_id: string | null;
|
|
613
|
+
rateLimit: RateLimitState | null;
|
|
614
|
+
}
|
|
615
|
+
/** Input for `installConnector()`. */
|
|
616
|
+
interface InstallConnectorInput {
|
|
617
|
+
connector_type: ConnectorType;
|
|
618
|
+
name: string;
|
|
619
|
+
environment: string;
|
|
620
|
+
scopes?: string[];
|
|
621
|
+
config?: Record<string, unknown>;
|
|
622
|
+
}
|
|
623
|
+
/** Input for `authenticateConnector()`. The `encrypted_value` must be pre-encrypted by the caller. */
|
|
624
|
+
interface AuthenticateConnectorInput {
|
|
625
|
+
credential_type: ConnectorCredentialType;
|
|
626
|
+
/** Pre-encrypted credential value. Never transmit plaintext. */
|
|
627
|
+
encrypted_value: string;
|
|
628
|
+
scope?: string[];
|
|
629
|
+
expires_at?: string;
|
|
630
|
+
}
|
|
631
|
+
/** Input for `upsertEnforcementPolicy()`. */
|
|
632
|
+
interface UpsertEnforcementPolicyInput {
|
|
633
|
+
connector_type: ConnectorType;
|
|
634
|
+
trigger_event: string;
|
|
635
|
+
condition?: Record<string, unknown>;
|
|
636
|
+
required_action: EnforcementAction;
|
|
637
|
+
quorum_config?: EnforcementQuorumConfig;
|
|
638
|
+
environment_scope?: string[];
|
|
639
|
+
enabled?: boolean;
|
|
640
|
+
priority?: number;
|
|
641
|
+
}
|
|
642
|
+
/** Response from `listConnectors()`. */
|
|
643
|
+
interface ListConnectorsResponse {
|
|
644
|
+
connectors: ConnectorRow[];
|
|
645
|
+
total: number;
|
|
646
|
+
nextCursor?: string;
|
|
647
|
+
rateLimit: RateLimitState | null;
|
|
648
|
+
}
|
|
649
|
+
/** Response from `installConnector()`. */
|
|
650
|
+
interface InstallConnectorResponse {
|
|
651
|
+
connector: ConnectorRow;
|
|
652
|
+
rateLimit: RateLimitState | null;
|
|
653
|
+
}
|
|
654
|
+
/** Response from `authenticateConnector()`. */
|
|
655
|
+
interface AuthenticateConnectorResponse {
|
|
656
|
+
credential_id: string;
|
|
657
|
+
version: number;
|
|
658
|
+
rateLimit: RateLimitState | null;
|
|
659
|
+
}
|
|
660
|
+
/** Response from `syncConnector()`. */
|
|
661
|
+
interface SyncConnectorResponse {
|
|
662
|
+
connector_id: string;
|
|
663
|
+
status: ConnectorStatus;
|
|
664
|
+
sync_started_at: string;
|
|
665
|
+
rateLimit: RateLimitState | null;
|
|
666
|
+
}
|
|
667
|
+
/** Response from `revokeConnector()`. */
|
|
668
|
+
interface RevokeConnectorResponse {
|
|
669
|
+
connector_id: string;
|
|
670
|
+
revoked_at: string;
|
|
671
|
+
rateLimit: RateLimitState | null;
|
|
66
672
|
}
|
|
673
|
+
/** Response from `rotateConnectorCredentials()`. */
|
|
674
|
+
interface RotateCredentialsResponse {
|
|
675
|
+
connector_id: string;
|
|
676
|
+
new_version: number;
|
|
677
|
+
rotated_at: string;
|
|
678
|
+
rateLimit: RateLimitState | null;
|
|
679
|
+
}
|
|
680
|
+
/** Response from `listEnforcementPolicies()`. */
|
|
681
|
+
interface ListEnforcementPoliciesResponse {
|
|
682
|
+
policies: ConnectorEnforcementPolicy[];
|
|
683
|
+
total: number;
|
|
684
|
+
rateLimit: RateLimitState | null;
|
|
685
|
+
}
|
|
686
|
+
/** Response from `upsertEnforcementPolicy()`. */
|
|
687
|
+
interface UpsertEnforcementPolicyResponse {
|
|
688
|
+
policy: ConnectorEnforcementPolicy;
|
|
689
|
+
rateLimit: RateLimitState | null;
|
|
690
|
+
}
|
|
691
|
+
|
|
67
692
|
/**
|
|
68
|
-
*
|
|
693
|
+
* Organizational risk graph types: 5-dimension risk scoring and
|
|
694
|
+
* recompute trigger shapes.
|
|
69
695
|
*
|
|
70
|
-
* `
|
|
71
|
-
*
|
|
696
|
+
* Mirrors `v1-risk-graph` (compute_org_risk / get_latest_org_risk ops)
|
|
697
|
+
* and the `organizational_risk_scores` DB table.
|
|
698
|
+
*/
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Bucketed risk level derived from `overall_score`.
|
|
702
|
+
*
|
|
703
|
+
* | Level | Score range |
|
|
704
|
+
* |---|---|
|
|
705
|
+
* | `"low"` | 0–30 |
|
|
706
|
+
* | `"medium"` | 31–60 |
|
|
707
|
+
* | `"high"` | 61–85 |
|
|
708
|
+
* | `"critical"` | 86–100 |
|
|
709
|
+
*/
|
|
710
|
+
type OrgRiskLevel = "low" | "medium" | "high" | "critical";
|
|
711
|
+
/**
|
|
712
|
+
* Full organizational risk score from `organizational_risk_scores`.
|
|
72
713
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
714
|
+
* All sub-scores are 0–100 (higher = more risk). `overall_score` is a
|
|
715
|
+
* weighted composite of the five dimensions; weights are internal and
|
|
716
|
+
* may change between releases without a breaking-change notice.
|
|
717
|
+
*/
|
|
718
|
+
interface OrgRiskScore {
|
|
719
|
+
id: string;
|
|
720
|
+
org_id: string;
|
|
721
|
+
/** Composite risk score 0–100. */
|
|
722
|
+
overall_score: number;
|
|
723
|
+
risk_level: OrgRiskLevel;
|
|
724
|
+
/** Actor-level risk: recent overrides, blocked actions by specific actors. */
|
|
725
|
+
actor_risk_score: number;
|
|
726
|
+
/** Connector-level risk: revoked/errored connectors, failed sync cycles. */
|
|
727
|
+
connector_risk_score: number;
|
|
728
|
+
/** Gap between what enforcement policies require and what connectors actually enforce. */
|
|
729
|
+
enforcement_gap_score: number;
|
|
730
|
+
/** Normalized frequency of incidents within the scoring window. */
|
|
731
|
+
incident_frequency_score: number;
|
|
732
|
+
/** Rate of permits that were overridden relative to total permits issued. */
|
|
733
|
+
override_rate_score: number;
|
|
734
|
+
/** Actor IDs flagged as high-risk within the window. */
|
|
735
|
+
risky_actors: string[];
|
|
736
|
+
/** Connector IDs flagged as high-risk within the window. */
|
|
737
|
+
risky_systems: string[];
|
|
738
|
+
/** Execution IDs with repeated overrides in the window. */
|
|
739
|
+
repeated_overrides: string[];
|
|
740
|
+
/** Days of activity included in this score computation. */
|
|
741
|
+
window_days: number;
|
|
742
|
+
computed_at: string;
|
|
743
|
+
created_at: string;
|
|
744
|
+
}
|
|
745
|
+
/** Options for triggering an org risk recompute. */
|
|
746
|
+
interface ComputeOrgRiskOptions {
|
|
747
|
+
/** Activity window in days (server default: 30). */
|
|
748
|
+
window_days?: number;
|
|
749
|
+
}
|
|
750
|
+
/** Response from `computeOrgRisk()`. */
|
|
751
|
+
interface ComputeOrgRiskResponse {
|
|
752
|
+
score: OrgRiskScore;
|
|
753
|
+
rateLimit: RateLimitState | null;
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Response from `getLatestOrgRisk()`.
|
|
757
|
+
* `score` is `null` if no risk computation has been run yet for the org.
|
|
76
758
|
*/
|
|
77
|
-
interface
|
|
78
|
-
|
|
759
|
+
interface GetLatestOrgRiskResponse {
|
|
760
|
+
score: OrgRiskScore | null;
|
|
761
|
+
rateLimit: RateLimitState | null;
|
|
762
|
+
}
|
|
763
|
+
/** Response from `listOrgRiskHistory()`. */
|
|
764
|
+
interface ListOrgRiskHistoryResponse {
|
|
765
|
+
scores: OrgRiskScore[];
|
|
79
766
|
total: number;
|
|
80
|
-
|
|
767
|
+
nextCursor?: string;
|
|
768
|
+
rateLimit: RateLimitState | null;
|
|
81
769
|
}
|
|
770
|
+
|
|
82
771
|
/**
|
|
83
|
-
*
|
|
84
|
-
* URL search params — `types` is a comma-joined list on the wire
|
|
85
|
-
* (e.g. `types=evaluate.allow,policy.updated`).
|
|
772
|
+
* Cross-Org Permission Negotiation.
|
|
86
773
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
774
|
+
* Evaluates whether an identity in one organization is permitted to
|
|
775
|
+
* perform an action on resources owned by another organization.
|
|
776
|
+
* Resolves trust paths, conditions, and cross-org trust levels.
|
|
777
|
+
*
|
|
778
|
+
* Wire-stable as `cross_org_permission.v1`.
|
|
89
779
|
*/
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
780
|
+
/** A single hop in the cross-org trust path. */
|
|
781
|
+
interface CrossOrgTrustHop {
|
|
782
|
+
org_id: string;
|
|
783
|
+
trust_type: string;
|
|
784
|
+
trust_level: string;
|
|
785
|
+
}
|
|
786
|
+
/** Request payload for a cross-org permission check. */
|
|
787
|
+
interface CrossOrgPermissionCheckRequest {
|
|
788
|
+
source_org_id: string;
|
|
789
|
+
target_org_id: string;
|
|
790
|
+
identity_id?: string;
|
|
791
|
+
action: string;
|
|
792
|
+
resource_type?: string;
|
|
793
|
+
resource_id?: string;
|
|
794
|
+
}
|
|
795
|
+
/** Result of a cross-org permission evaluation. */
|
|
796
|
+
interface CrossOrgPermissionCheckResult {
|
|
797
|
+
check_id: string;
|
|
798
|
+
allowed: boolean;
|
|
799
|
+
reason: string;
|
|
800
|
+
trust_path: Array<CrossOrgTrustHop>;
|
|
801
|
+
conditions: string[];
|
|
802
|
+
checked_at: string;
|
|
803
|
+
}
|
|
804
|
+
/** Parameters for listing previous cross-org permission checks. */
|
|
805
|
+
interface CrossOrgPermissionCheckListParams {
|
|
806
|
+
source_org_id?: string;
|
|
807
|
+
target_org_id?: string;
|
|
808
|
+
allowed?: boolean;
|
|
100
809
|
limit?: number;
|
|
101
|
-
/** Opaque cursor returned as `next_cursor` by the prior page. */
|
|
102
|
-
cursor?: string;
|
|
103
810
|
}
|
|
104
811
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
812
|
+
* Summarize whether a cross-org check result is unconditionally allowed,
|
|
813
|
+
* conditionally allowed, or denied.
|
|
814
|
+
*/
|
|
815
|
+
declare function summarizeCrossOrgPermission(result: CrossOrgPermissionCheckResult): "allowed" | "conditional" | "denied";
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* Anomaly Response Automation.
|
|
107
819
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
820
|
+
* Rules-driven automated responses to governance anomalies detected
|
|
821
|
+
* during agent execution. Supports freezing agents, creating incidents,
|
|
822
|
+
* notifying administrators, requiring human-in-the-loop review,
|
|
823
|
+
* rolling back executions, and escalating to regulators.
|
|
111
824
|
*
|
|
112
|
-
*
|
|
113
|
-
* match the stored hash — even when `chain_integrity_ok` is false,
|
|
114
|
-
* the signature still covers whatever the server emitted, so callers
|
|
115
|
-
* that trust the signature must still inspect this list.
|
|
825
|
+
* Wire-stable as `anomaly_response.v1`.
|
|
116
826
|
*/
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
827
|
+
/** The automated action type to take when an anomaly rule triggers. */
|
|
828
|
+
type AnomalyActionType = "freeze_agent" | "create_incident" | "notify_admin" | "require_hitl" | "rollback_execution" | "escalate_to_regulator";
|
|
829
|
+
/** A rule that triggers an automated response when an anomaly threshold is crossed. */
|
|
830
|
+
interface AnomalyResponseRule {
|
|
831
|
+
id: string;
|
|
121
832
|
org_id: string;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
833
|
+
name: string;
|
|
834
|
+
description?: string;
|
|
835
|
+
anomaly_score_threshold: number;
|
|
836
|
+
action_type: AnomalyActionType;
|
|
837
|
+
action_config: Record<string, unknown>;
|
|
838
|
+
is_active: boolean;
|
|
839
|
+
created_at: string;
|
|
840
|
+
updated_at: string;
|
|
841
|
+
}
|
|
842
|
+
/** A record of an anomaly response that was triggered. */
|
|
843
|
+
interface AnomalyResponseEvent {
|
|
844
|
+
id: string;
|
|
845
|
+
rule_id: string;
|
|
846
|
+
execution_id: string;
|
|
847
|
+
org_id: string;
|
|
848
|
+
anomaly_score: number;
|
|
849
|
+
action_type: AnomalyActionType;
|
|
850
|
+
action_result: Record<string, unknown>;
|
|
851
|
+
triggered_at: string;
|
|
852
|
+
}
|
|
853
|
+
/** Request body for creating a new anomaly response rule. */
|
|
854
|
+
interface CreateAnomalyResponseRuleRequest {
|
|
855
|
+
name: string;
|
|
856
|
+
description?: string;
|
|
857
|
+
anomaly_score_threshold: number;
|
|
858
|
+
action_type: AnomalyActionType;
|
|
859
|
+
action_config?: Record<string, unknown>;
|
|
860
|
+
}
|
|
861
|
+
/** Request body for manually triggering an anomaly response check. */
|
|
862
|
+
interface TriggerAnomalyResponseRequest {
|
|
863
|
+
execution_id: string;
|
|
864
|
+
anomaly_score: number;
|
|
865
|
+
context?: Record<string, unknown>;
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Determine which rules from a set would trigger for a given anomaly score.
|
|
869
|
+
* Returns only active rules whose threshold is met or exceeded.
|
|
870
|
+
*/
|
|
871
|
+
declare function matchAnomalyRules(rules: readonly AnomalyResponseRule[], anomalyScore: number): AnomalyResponseRule[];
|
|
872
|
+
/**
|
|
873
|
+
* Determine the most severe action type from a set of triggered rules.
|
|
874
|
+
* Severity order (highest first):
|
|
875
|
+
* escalate_to_regulator > rollback_execution > freeze_agent >
|
|
876
|
+
* require_hitl > create_incident > notify_admin
|
|
877
|
+
*/
|
|
878
|
+
declare function highestSeverityAction(rules: readonly AnomalyResponseRule[]): AnomalyActionType | null;
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Budget Exception Workflows.
|
|
882
|
+
*
|
|
883
|
+
* Structured request-and-approval process for temporary exceptions
|
|
884
|
+
* to budget policy limits. Supports creation, review, approval,
|
|
885
|
+
* rejection, and cancellation lifecycles with full audit trails.
|
|
886
|
+
*
|
|
887
|
+
* Wire-stable as `budget_exceptions.v1`.
|
|
888
|
+
*/
|
|
889
|
+
/** Lifecycle status of a budget exception request. */
|
|
890
|
+
type BudgetExceptionStatus = "pending" | "under_review" | "approved" | "rejected" | "expired" | "cancelled";
|
|
891
|
+
/** A formal request for a temporary exception to a budget policy limit. */
|
|
892
|
+
interface BudgetExceptionRequest {
|
|
893
|
+
id: string;
|
|
894
|
+
org_id: string;
|
|
895
|
+
budget_policy_id?: string;
|
|
896
|
+
requested_by: string;
|
|
897
|
+
amount_requested: number;
|
|
898
|
+
currency: string;
|
|
899
|
+
reason: string;
|
|
900
|
+
justification?: string;
|
|
901
|
+
business_impact?: string;
|
|
902
|
+
status: BudgetExceptionStatus;
|
|
903
|
+
reviewed_by?: string;
|
|
904
|
+
reviewed_at?: string;
|
|
905
|
+
review_notes?: string;
|
|
906
|
+
effective_from?: string;
|
|
907
|
+
effective_until?: string;
|
|
908
|
+
approved_amount?: number;
|
|
909
|
+
conditions: string[];
|
|
910
|
+
created_at: string;
|
|
911
|
+
updated_at: string;
|
|
912
|
+
}
|
|
913
|
+
/** Request body for creating a new budget exception request. */
|
|
914
|
+
interface CreateBudgetExceptionRequest {
|
|
915
|
+
budget_policy_id?: string;
|
|
916
|
+
amount_requested: number;
|
|
917
|
+
currency?: string;
|
|
918
|
+
reason: string;
|
|
919
|
+
justification?: string;
|
|
920
|
+
business_impact?: string;
|
|
921
|
+
effective_from?: string;
|
|
922
|
+
effective_until?: string;
|
|
923
|
+
}
|
|
924
|
+
/** Request body for approving a budget exception. */
|
|
925
|
+
interface ApproveBudgetExceptionRequest {
|
|
926
|
+
review_notes?: string;
|
|
927
|
+
approved_amount: number;
|
|
928
|
+
conditions?: string[];
|
|
929
|
+
effective_from?: string;
|
|
930
|
+
effective_until?: string;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Returns true when an approved exception is currently in effect.
|
|
934
|
+
* An exception is in effect when:
|
|
935
|
+
* - status is "approved"
|
|
936
|
+
* - current time is within [effective_from, effective_until]
|
|
937
|
+
*/
|
|
938
|
+
declare function isBudgetExceptionActive(exception: BudgetExceptionRequest, now?: Date): boolean;
|
|
939
|
+
/**
|
|
940
|
+
* Returns true when a budget exception request is in a terminal state
|
|
941
|
+
* (no further transitions are possible).
|
|
942
|
+
*/
|
|
943
|
+
declare function isBudgetExceptionTerminal(status: BudgetExceptionStatus): boolean;
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* Regulatory Escalation Chain.
|
|
947
|
+
*
|
|
948
|
+
* Hierarchical escalation infrastructure for routing governance issues
|
|
949
|
+
* through defined authority levels. Supports multi-jurisdiction
|
|
950
|
+
* regulatory chains with SLA tracking and resolution workflows.
|
|
951
|
+
*
|
|
952
|
+
* Wire-stable as `regulatory_escalation.v1`.
|
|
953
|
+
*/
|
|
954
|
+
/**
|
|
955
|
+
* A defined level in the regulatory authority hierarchy.
|
|
956
|
+
* Levels are ordered numerically — lower numbers = lower authority.
|
|
957
|
+
*/
|
|
958
|
+
interface RegulatoryAuthorityLevel {
|
|
959
|
+
id: string;
|
|
960
|
+
org_id: string;
|
|
961
|
+
name: string;
|
|
962
|
+
level: number;
|
|
963
|
+
description?: string;
|
|
964
|
+
parent_level_id?: string;
|
|
965
|
+
jurisdiction?: string;
|
|
966
|
+
escalation_sla_hours: number;
|
|
967
|
+
created_at: string;
|
|
968
|
+
}
|
|
969
|
+
/** Lifecycle status of a regulatory escalation. */
|
|
970
|
+
type RegulatoryEscalationStatus = "pending" | "acknowledged" | "under_review" | "resolved" | "overridden";
|
|
971
|
+
/** A formal escalation between two regulatory authority levels. */
|
|
972
|
+
interface RegulatoryEscalation {
|
|
973
|
+
id: string;
|
|
974
|
+
org_id: string;
|
|
975
|
+
from_level_id: string;
|
|
976
|
+
to_level_id: string;
|
|
977
|
+
subject_type: string;
|
|
978
|
+
subject_id: string;
|
|
979
|
+
reason: string;
|
|
980
|
+
details: Record<string, unknown>;
|
|
981
|
+
status: RegulatoryEscalationStatus;
|
|
982
|
+
escalated_by: string;
|
|
983
|
+
acknowledged_by?: string;
|
|
984
|
+
acknowledged_at?: string;
|
|
985
|
+
resolved_by?: string;
|
|
986
|
+
resolved_at?: string;
|
|
987
|
+
resolution?: string;
|
|
988
|
+
resolution_details?: Record<string, unknown>;
|
|
989
|
+
created_at: string;
|
|
990
|
+
updated_at: string;
|
|
991
|
+
}
|
|
992
|
+
/** Request body for creating a new regulatory escalation. */
|
|
993
|
+
interface CreateRegulatoryEscalationRequest {
|
|
994
|
+
from_level_id: string;
|
|
995
|
+
to_level_id: string;
|
|
996
|
+
subject_type: string;
|
|
997
|
+
subject_id: string;
|
|
998
|
+
reason: string;
|
|
999
|
+
details?: Record<string, unknown>;
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Returns true when a regulatory escalation is in a terminal state.
|
|
1003
|
+
*/
|
|
1004
|
+
declare function isRegulatoryEscalationTerminal(status: RegulatoryEscalationStatus): boolean;
|
|
1005
|
+
/**
|
|
1006
|
+
* Determine whether an escalation has breached its SLA.
|
|
1007
|
+
* Compares the SLA hours on the target authority level against the
|
|
1008
|
+
* elapsed time since creation.
|
|
1009
|
+
*/
|
|
1010
|
+
declare function isEscalationSlaBreached(escalation: RegulatoryEscalation, targetLevel: RegulatoryAuthorityLevel, now?: Date): boolean;
|
|
1011
|
+
|
|
1012
|
+
/**
|
|
1013
|
+
* Incentive Signal Feedback Loop.
|
|
1014
|
+
*
|
|
1015
|
+
* Captures how governance actors respond to incentive alignment signals
|
|
1016
|
+
* and tracks outcomes. Feeds back into signal calibration and governance
|
|
1017
|
+
* health scoring over time.
|
|
1018
|
+
*
|
|
1019
|
+
* Wire-stable as `incentive_signal_feedback.v1`.
|
|
1020
|
+
*/
|
|
1021
|
+
/** The type of action taken in response to a governance signal. */
|
|
1022
|
+
type SignalActionType = "accepted" | "dismissed" | "escalated" | "delegated" | "policy_updated" | "training_initiated" | "process_changed" | "monitoring_increased" | "auto_remediated";
|
|
1023
|
+
/** A record of an action taken in response to a governance signal. */
|
|
1024
|
+
interface GovernanceSignalAction {
|
|
1025
|
+
id: string;
|
|
1026
|
+
signal_id: string;
|
|
1027
|
+
org_id: string;
|
|
1028
|
+
action_type: SignalActionType;
|
|
1029
|
+
action_description?: string;
|
|
1030
|
+
taken_by?: string;
|
|
1031
|
+
taken_at: string;
|
|
1032
|
+
outcome_score?: number;
|
|
1033
|
+
outcome_description?: string;
|
|
1034
|
+
outcome_recorded_at?: string;
|
|
1035
|
+
metadata: Record<string, unknown>;
|
|
1036
|
+
}
|
|
1037
|
+
/** Request body for recording a new signal action. */
|
|
1038
|
+
interface RecordSignalActionRequest {
|
|
1039
|
+
action_type: SignalActionType;
|
|
1040
|
+
action_description?: string;
|
|
1041
|
+
metadata?: Record<string, unknown>;
|
|
1042
|
+
}
|
|
1043
|
+
/** Request body for recording an outcome on a previous signal action. */
|
|
1044
|
+
interface RecordSignalOutcomeRequest {
|
|
1045
|
+
outcome_score: number;
|
|
1046
|
+
outcome_description?: string;
|
|
1047
|
+
}
|
|
1048
|
+
/** Aggregate summary of signal actions for an organization. */
|
|
1049
|
+
interface SignalActionSummary {
|
|
1050
|
+
total_signals: number;
|
|
1051
|
+
acted_on: number;
|
|
1052
|
+
dismissed: number;
|
|
1053
|
+
average_outcome_score: number;
|
|
1054
|
+
by_action_type: Record<SignalActionType, {
|
|
1055
|
+
count: number;
|
|
1056
|
+
avg_outcome: number;
|
|
1057
|
+
}>;
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Compute a simple engagement rate from a signal action summary.
|
|
1061
|
+
* Returns the fraction of signals that received a non-dismissed response.
|
|
1062
|
+
*/
|
|
1063
|
+
declare function computeSignalEngagementRate(summary: SignalActionSummary): number;
|
|
1064
|
+
/**
|
|
1065
|
+
* Determine whether a signal action represents a substantive governance
|
|
1066
|
+
* response (i.e. more than a dismissal or auto-remediation).
|
|
1067
|
+
*/
|
|
1068
|
+
declare function isSubstantiveSignalResponse(actionType: SignalActionType): boolean;
|
|
1069
|
+
|
|
1070
|
+
/**
|
|
1071
|
+
* Cross-Org Impersonation.
|
|
1072
|
+
*
|
|
1073
|
+
* Allows a service account in one organization to impersonate a role in
|
|
1074
|
+
* another organization under explicit, audited grants. Supports bounded
|
|
1075
|
+
* token issuance, grant revocation, and token validation.
|
|
1076
|
+
*
|
|
1077
|
+
* Wire-stable as `cross_org_impersonation.v1`.
|
|
1078
|
+
*/
|
|
1079
|
+
/** An explicit grant allowing one org's service account to impersonate a role in another org. */
|
|
1080
|
+
interface CrossOrgImpersonationGrant {
|
|
1081
|
+
id: string;
|
|
1082
|
+
grantor_org_id: string;
|
|
1083
|
+
grantee_org_id: string;
|
|
1084
|
+
grantee_service_account_id: string;
|
|
1085
|
+
impersonated_role: string;
|
|
1086
|
+
allowed_actions: string[];
|
|
1087
|
+
allowed_resource_types: string[];
|
|
1088
|
+
max_token_duration_seconds: number;
|
|
1089
|
+
is_active: boolean;
|
|
1090
|
+
created_by: string;
|
|
1091
|
+
created_at: string;
|
|
1092
|
+
expires_at?: string;
|
|
1093
|
+
revoked_at?: string;
|
|
1094
|
+
}
|
|
1095
|
+
/** Request body for creating a new impersonation grant. */
|
|
1096
|
+
interface CreateImpersonationGrantRequest {
|
|
1097
|
+
grantee_org_id: string;
|
|
1098
|
+
grantee_service_account_id: string;
|
|
1099
|
+
impersonated_role: string;
|
|
1100
|
+
allowed_actions: string[];
|
|
1101
|
+
allowed_resource_types: string[];
|
|
1102
|
+
max_token_duration_seconds?: number;
|
|
1103
|
+
expires_at?: string;
|
|
1104
|
+
}
|
|
1105
|
+
/** A short-lived impersonation token issued under a grant. */
|
|
1106
|
+
interface ImpersonationToken {
|
|
1107
|
+
token: string;
|
|
1108
|
+
expires_at: string;
|
|
1109
|
+
grant_id: string;
|
|
1110
|
+
}
|
|
1111
|
+
/** Result of validating an impersonation token. */
|
|
1112
|
+
interface ImpersonationValidationResult {
|
|
1113
|
+
valid: boolean;
|
|
1114
|
+
grant?: CrossOrgImpersonationGrant;
|
|
1115
|
+
impersonated_role?: string;
|
|
1116
|
+
allowed_actions?: string[];
|
|
1117
|
+
allowed_resource_types?: string[];
|
|
1118
|
+
error?: string;
|
|
1119
|
+
}
|
|
1120
|
+
/**
|
|
1121
|
+
* Returns true when an impersonation grant is currently usable:
|
|
1122
|
+
* - is_active is true
|
|
1123
|
+
* - not yet expired
|
|
1124
|
+
* - not revoked
|
|
1125
|
+
*/
|
|
1126
|
+
declare function isImpersonationGrantUsable(grant: CrossOrgImpersonationGrant, now?: Date): boolean;
|
|
1127
|
+
/**
|
|
1128
|
+
* Clamp a requested token duration to the grant's maximum.
|
|
1129
|
+
* Returns the minimum of the requested duration and the grant ceiling.
|
|
1130
|
+
*/
|
|
1131
|
+
declare function clampTokenDuration(grant: CrossOrgImpersonationGrant, requestedSeconds: number): number;
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* AtlaSent HTTP client.
|
|
1135
|
+
*
|
|
1136
|
+
* Two public methods, both backed by native `fetch`:
|
|
1137
|
+
* - {@link AtlaSentClient.evaluate} → POST {baseUrl}/v1-evaluate
|
|
1138
|
+
* - {@link AtlaSentClient.verifyPermit} → POST {baseUrl}/v1-verify-permit
|
|
1139
|
+
*
|
|
1140
|
+
* Fail-closed: a clean policy DENY is returned (not thrown), but
|
|
1141
|
+
* network, timeout, bad response, 4xx/5xx, and rate-limit conditions
|
|
1142
|
+
* all throw {@link AtlaSentError}.
|
|
1143
|
+
*/
|
|
1144
|
+
|
|
1145
|
+
declare class AtlaSentClient {
|
|
1146
|
+
private readonly apiKey;
|
|
1147
|
+
private readonly baseUrl;
|
|
1148
|
+
private readonly timeoutMs;
|
|
1149
|
+
private readonly fetchImpl;
|
|
1150
|
+
private readonly userAgent;
|
|
1151
|
+
private readonly retryPolicy;
|
|
1152
|
+
constructor(options: AtlaSentClientOptions);
|
|
1153
|
+
/**
|
|
1154
|
+
* Ask the policy engine whether an agent action is permitted.
|
|
1155
|
+
*
|
|
1156
|
+
* Accepts either the current v2.0 shape (`action_type` / `actor_id`)
|
|
1157
|
+
* or the legacy v1.x shape (`action` / `agent`). Legacy callers
|
|
1158
|
+
* receive a deprecation warning via `console.warn`; the shim is
|
|
1159
|
+
* handled by {@link normalizeEvaluateRequest} and will be removed
|
|
1160
|
+
* in v3.0.0.
|
|
1161
|
+
*
|
|
1162
|
+
* A "deny" is **not** thrown — it is returned in
|
|
1163
|
+
* `response.decision`. Network errors, invalid API key, rate
|
|
1164
|
+
* limits, timeouts, and malformed responses throw
|
|
1165
|
+
* {@link AtlaSentError}.
|
|
1166
|
+
*/
|
|
1167
|
+
evaluate(input: EvaluateRequest | LegacyEvaluateRequest): Promise<EvaluateResponse>;
|
|
1168
|
+
/**
|
|
1169
|
+
* Pre-flight evaluation that always returns the constraint trace.
|
|
1170
|
+
*
|
|
1171
|
+
* Wraps `POST /v1-evaluate?include=constraint_trace`. Use this from
|
|
1172
|
+
* a workflow's submission step to surface trivial defects (missing
|
|
1173
|
+
* fields, wrong roles, mis-set context) BEFORE pushing the request
|
|
1174
|
+
* onto an approval queue — only requests that would actually pass
|
|
1175
|
+
* make it through to a human reviewer.
|
|
1176
|
+
*
|
|
1177
|
+
* Returns an {@link EvaluatePreflightResponse} carrying the regular
|
|
1178
|
+
* {@link EvaluateResponse} plus the {@link ConstraintTrace}. Unlike
|
|
1179
|
+
* {@link evaluate}, this method does NOT mark a non-allow as a
|
|
1180
|
+
* thrown condition — the whole point is to inspect both the outcome
|
|
1181
|
+
* AND the per-policy trace, so the caller branches on
|
|
1182
|
+
* `result.evaluation.decision` and reads `result.constraintTrace`
|
|
1183
|
+
* to render the failing stages.
|
|
1184
|
+
*
|
|
1185
|
+
* The constraint-trace shape mirrors `ConstraintTraceResponse` in
|
|
1186
|
+
* atlasent-api (`packages/types/src/index.ts`). On older
|
|
1187
|
+
* atlasent-api deployments that omit the trace, `constraintTrace`
|
|
1188
|
+
* is `null` rather than throwing — forward-compatible degradation.
|
|
1189
|
+
*
|
|
1190
|
+
* Performance: one extra round-trip on submission. Latency is
|
|
1191
|
+
* comparable to {@link evaluate}; the response body is fuller
|
|
1192
|
+
* (includes the per-stage trace) so the wire payload is larger.
|
|
1193
|
+
* If the caller does not need the trace, prefer {@link evaluate}.
|
|
1194
|
+
*/
|
|
1195
|
+
evaluatePreflight(input: EvaluateRequest): Promise<EvaluatePreflightResponse>;
|
|
1196
|
+
/**
|
|
1197
|
+
* Verify that a previously issued permit is still valid.
|
|
1198
|
+
*
|
|
1199
|
+
* @deprecated Use {@link verifyPermitById} — the canonical REST
|
|
1200
|
+
* surface (`POST /v1/permits/{id}/verify`) returns the unified
|
|
1201
|
+
* verification envelope plus the full {@link PermitRecord}, instead
|
|
1202
|
+
* of the legacy `{verified, outcome, permitHash}` shape this method
|
|
1203
|
+
* emits. Will be removed in `@atlasent/sdk@3`.
|
|
1204
|
+
*
|
|
1205
|
+
* A `verified: false` response is **not** thrown — inspect the
|
|
1206
|
+
* returned object. Only transport / server errors throw.
|
|
1207
|
+
*/
|
|
1208
|
+
verifyPermit(input: VerifyPermitRequest): Promise<VerifyPermitResponse>;
|
|
1209
|
+
/**
|
|
1210
|
+
* Run the canonical Deploy Gate V1 flow:
|
|
1211
|
+
* evaluate `production.deploy`, verify the issued permit server-side,
|
|
1212
|
+
* and return allow/block plus audit/evidence metadata.
|
|
1213
|
+
*
|
|
1214
|
+
* This helper never treats a signed/offline permit artifact as sufficient
|
|
1215
|
+
* authorization. Execution is allowed only when `POST /v1-evaluate` returns
|
|
1216
|
+
* `decision: "allow"` with a permit AND `POST /v1-verify-permit` returns
|
|
1217
|
+
* `verified: true` / `valid: true`.
|
|
1218
|
+
*/
|
|
1219
|
+
deployGate(input?: DeployGateRequest): Promise<DeployGateResponse>;
|
|
1220
|
+
/**
|
|
1221
|
+
* Revoke a previously-issued permit so it can no longer pass
|
|
1222
|
+
* {@link verifyPermit}.
|
|
1223
|
+
*
|
|
1224
|
+
* @deprecated Use {@link revokePermitById} — the canonical REST
|
|
1225
|
+
* surface (`POST /v1/permits/{id}/revoke`) returns the full updated
|
|
1226
|
+
* {@link PermitRecord} with `revoked_at`/`revoked_by`/`revoke_reason`
|
|
1227
|
+
* populated, instead of the legacy `{revoked, permitId}` envelope
|
|
1228
|
+
* this method emits. Will be removed in `@atlasent/sdk@3`.
|
|
1229
|
+
*
|
|
1230
|
+
* Use this when an agent's action is cancelled, superseded, or
|
|
1231
|
+
* determined to be unauthorized after the fact. The revocation is
|
|
1232
|
+
* recorded in the audit log with the optional `reason`.
|
|
1233
|
+
*
|
|
1234
|
+
* Throws {@link AtlaSentError} on transport / auth failures.
|
|
1235
|
+
*/
|
|
1236
|
+
revokePermit(input: RevokePermitRequest): Promise<RevokePermitResponse>;
|
|
1237
|
+
/**
|
|
1238
|
+
* Revoke a permit through the canonical REST surface
|
|
1239
|
+
* (`POST /v1/permits/{permitId}/revoke`).
|
|
1240
|
+
*
|
|
1241
|
+
* Returns the full updated {@link PermitRecord} with `status === 'revoked'`
|
|
1242
|
+
* and `revoked_at` / `revoked_by` / `revoke_reason` populated. After
|
|
1243
|
+
* revocation, subsequent verify calls return `410 PERMIT_REVOKED`.
|
|
1244
|
+
*
|
|
1245
|
+
* Idempotent on `409 permit_revoked` for already-revoked permits;
|
|
1246
|
+
* server returns the existing revoked row in that case.
|
|
1247
|
+
*
|
|
1248
|
+
* Throws {@link AtlaSentError} on `404` (permit not in calling org),
|
|
1249
|
+
* `409` (already in a terminal state), `410` (expired before revoke),
|
|
1250
|
+
* or `429` (rate limited).
|
|
1251
|
+
*/
|
|
1252
|
+
revokePermitById(permitId: string, input?: RevokePermitByIdInput): Promise<RevokePermitByIdResponse>;
|
|
1253
|
+
/**
|
|
1254
|
+
* Verify a permit through the canonical REST surface
|
|
1255
|
+
* (`POST /v1/permits/{permitId}/verify`).
|
|
1256
|
+
*
|
|
1257
|
+
* Returns the unified verification envelope (`valid`,
|
|
1258
|
+
* `verification_type: 'permit'`, `reason`, `verified_at`, `evidence`)
|
|
1259
|
+
* plus the full {@link PermitRecord} fields preserved at the top
|
|
1260
|
+
* level. The `valid` field is the contract — pin to it.
|
|
1261
|
+
*
|
|
1262
|
+
* A `valid: false` is **not** thrown when the server returns 200 with
|
|
1263
|
+
* a denial reason (matches the verify-shape unification on the wire);
|
|
1264
|
+
* it is thrown on 4xx (`404` not found, `410` expired/consumed).
|
|
1265
|
+
*/
|
|
1266
|
+
verifyPermitById(permitId: string): Promise<VerifyPermitByIdResponse>;
|
|
1267
|
+
/**
|
|
1268
|
+
* Get a single permit's full lifecycle state.
|
|
1269
|
+
*
|
|
1270
|
+
* Calls `GET /v1/permits/{permitId}` (the canonical REST surface).
|
|
1271
|
+
* Returns `status`, all timestamps, `revoked_at` / `revoked_by` /
|
|
1272
|
+
* `revoke_reason` (when applicable), and the bound `payload_hash`
|
|
1273
|
+
* / `decision_id`.
|
|
1274
|
+
*
|
|
1275
|
+
* Operator-facing introspection — answers "what state is this permit
|
|
1276
|
+
* in, and why?" without reading audit logs.
|
|
1277
|
+
*
|
|
1278
|
+
* Throws {@link AtlaSentError} on `404` (permit not in calling org)
|
|
1279
|
+
* or `410` (expired before retrieval).
|
|
1280
|
+
*/
|
|
1281
|
+
getPermit(permitId: string): Promise<GetPermitResponse>;
|
|
1282
|
+
/**
|
|
1283
|
+
* Poll whether a permit is currently valid.
|
|
1284
|
+
*
|
|
1285
|
+
* Calls `GET /v1/permits/{permitId}/valid` — a lightweight read
|
|
1286
|
+
* returning only the status snapshot optimised for guard heartbeat
|
|
1287
|
+
* polling. Guards with `permitRevalidationIntervalMs` set race this
|
|
1288
|
+
* against `tool.execute()` and throw {@link PermitRevoked} when
|
|
1289
|
+
* `status === "revoked"` arrives.
|
|
1290
|
+
*
|
|
1291
|
+
* Throws {@link AtlaSentError} on transport / auth failures.
|
|
1292
|
+
*/
|
|
1293
|
+
checkPermitValid(permitId: string): Promise<PermitValidResponse>;
|
|
1294
|
+
/**
|
|
1295
|
+
* List permits issued to the calling org, most-recently-issued first.
|
|
1296
|
+
*
|
|
1297
|
+
* Calls `GET /v1/permits` (the canonical REST surface). Cursor-paged.
|
|
1298
|
+
* Filters narrow on server side; pagination uses the `created_at`
|
|
1299
|
+
* timestamp opaquely (`nextCursor`).
|
|
1300
|
+
*
|
|
1301
|
+
* Designed for incident review, debugging, and compliance
|
|
1302
|
+
* reconstruction.
|
|
1303
|
+
*/
|
|
1304
|
+
listPermits(input?: ListPermitsRequest): Promise<ListPermitsResponse>;
|
|
1305
|
+
/**
|
|
1306
|
+
* Self-introspection: ask the server to describe the API key this
|
|
1307
|
+
* client was constructed with. Returns the key's ID, organization,
|
|
1308
|
+
* environment, scopes, IP allowlist, per-minute rate limit, the
|
|
1309
|
+
* client IP the server observed, and the expiry (if any).
|
|
1310
|
+
*
|
|
1311
|
+
* Never includes the raw key or its hash. Safe to surface in operator
|
|
1312
|
+
* dashboards. Useful for `IP_NOT_ALLOWED` debugging (the server tells
|
|
1313
|
+
* you exactly which IP it saw) and for proactive expiry warnings.
|
|
1314
|
+
*
|
|
1315
|
+
* Throws {@link AtlaSentError} on transport / auth failures — same
|
|
1316
|
+
* taxonomy as {@link AtlaSentClient.evaluate}.
|
|
1317
|
+
*/
|
|
1318
|
+
keySelf(): Promise<ApiKeySelfResponse>;
|
|
1319
|
+
/**
|
|
1320
|
+
* List persisted audit events for the authenticated organization
|
|
1321
|
+
* (`GET /v1-audit/events`). Returned rows are wire-identical with
|
|
1322
|
+
* the server: snake_case field names, including `previous_hash` and
|
|
1323
|
+
* the `hash` chain, so the response can be fed straight into the
|
|
1324
|
+
* offline verifier when paired with a signed export.
|
|
1325
|
+
*
|
|
1326
|
+
* `query.types` is a comma-joined list (e.g.
|
|
1327
|
+
* `"evaluate.allow,policy.updated"`). `cursor` is the opaque
|
|
1328
|
+
* `next_cursor` from the prior page. All fields are optional; the
|
|
1329
|
+
* server defaults `limit` to 50 (capped at 500).
|
|
1330
|
+
*
|
|
1331
|
+
* Throws {@link AtlaSentError} on transport / auth failures — same
|
|
1332
|
+
* taxonomy as {@link AtlaSentClient.evaluate}.
|
|
1333
|
+
*/
|
|
1334
|
+
listAuditEvents(query?: AuditEventsQuery): Promise<AuditEventsResult>;
|
|
1335
|
+
/**
|
|
1336
|
+
* Request a signed audit export bundle
|
|
1337
|
+
* (`POST /v1-audit/exports`). The returned object is wire-identical
|
|
1338
|
+
* with the server — `signature`, `chain_head_hash`, `events`, and
|
|
1339
|
+
* friends survive untouched so the bundle can be persisted to disk
|
|
1340
|
+
* and handed to the offline verifier (`verifyBundle` /
|
|
1341
|
+
* `verifyAuditBundle`) without any reshaping.
|
|
1342
|
+
*
|
|
1343
|
+
* Pass `filter.types`, `filter.from`, `filter.to`, or `filter.actor_id`
|
|
1344
|
+
* to narrow the export; omit for a full-org bundle. `rateLimit` is
|
|
1345
|
+
* attached alongside the wire fields for observability.
|
|
1346
|
+
*
|
|
1347
|
+
* Throws {@link AtlaSentError} on transport / auth failures — same
|
|
1348
|
+
* taxonomy as {@link AtlaSentClient.evaluate}.
|
|
1349
|
+
*/
|
|
1350
|
+
createAuditExport(filter?: AuditExportRequest): Promise<AuditExportResult>;
|
|
1351
|
+
/**
|
|
1352
|
+
* Open a streaming evaluation session against `POST /v1-evaluate-stream`.
|
|
1353
|
+
*
|
|
1354
|
+
* Yields {@link StreamDecisionEvent} and {@link StreamProgressEvent} objects
|
|
1355
|
+
* as the server emits them. The iterator ends cleanly when the server sends
|
|
1356
|
+
* `event: done`; it throws {@link AtlaSentError} on transport errors or when
|
|
1357
|
+
* the server sends `event: error`.
|
|
1358
|
+
*
|
|
1359
|
+
* The final {@link StreamDecisionEvent} (isFinal: true) carries a `permitId`
|
|
1360
|
+
* suitable for passing to {@link verifyPermit} after the stream closes.
|
|
1361
|
+
*
|
|
1362
|
+
* Hardening:
|
|
1363
|
+
* - Throws {@link StreamTimeoutError} when no event arrives within
|
|
1364
|
+
* `opts.timeoutMs` (default 30 s). Pass `0` to disable.
|
|
1365
|
+
* - Retries up to `opts.maxRetries` times (default 3) with 1 s / 2 s / 4 s
|
|
1366
|
+
* delays on network drop (before a terminal event). Sends `Last-Event-ID`
|
|
1367
|
+
* on reconnect when the server has emitted event IDs.
|
|
1368
|
+
* - Throws {@link StreamParseError} on partial / malformed JSON rather than
|
|
1369
|
+
* crashing with a raw `SyntaxError`.
|
|
1370
|
+
* - Closes cleanly on `event: done` or a decision event with `done: true`.
|
|
1371
|
+
*
|
|
1372
|
+
* ```ts
|
|
1373
|
+
* for await (const event of client.protectStream({ agent, action })) {
|
|
1374
|
+
* if (event.type === "decision" && event.isFinal) {
|
|
1375
|
+
* await client.verifyPermit({ permitId: event.permitId });
|
|
1376
|
+
* }
|
|
1377
|
+
* }
|
|
1378
|
+
* ```
|
|
1379
|
+
*/
|
|
1380
|
+
protectStream(input: EvaluateRequest, opts?: StreamOptions): AsyncIterable<StreamEvent>;
|
|
1381
|
+
private post;
|
|
1382
|
+
private get;
|
|
1383
|
+
private request;
|
|
1384
|
+
/**
|
|
1385
|
+
* Open a new HITL escalation. Bridges a `hold` outcome from
|
|
1386
|
+
* `protect()` to the approval queue: an agent that receives a
|
|
1387
|
+
* `hold` decision calls this to enroll the proposed action for
|
|
1388
|
+
* human review. The returned escalation can then be polled with
|
|
1389
|
+
* `getHitlEscalation()` or driven to terminal by
|
|
1390
|
+
* `approveHitlEscalation()` / `rejectHitlEscalation()`.
|
|
1391
|
+
*
|
|
1392
|
+
* Quorum, pool size, fallback decision and routing inherit from
|
|
1393
|
+
* the server-side policy when omitted from `input`.
|
|
1394
|
+
*
|
|
1395
|
+
* Calls `POST /v1/hitl`.
|
|
1396
|
+
*/
|
|
1397
|
+
createHitlEscalation(input: HitlCreateRequest): Promise<{
|
|
1398
|
+
escalation: HitlEscalation;
|
|
1399
|
+
rateLimit: RateLimitState | null;
|
|
1400
|
+
}>;
|
|
1401
|
+
/**
|
|
1402
|
+
* List HITL escalations for the calling org. Defaults to
|
|
1403
|
+
* `status=pending`; pass `status` to query other queues
|
|
1404
|
+
* (`escalated`, `approved`, `rejected`, `auto_approved`,
|
|
1405
|
+
* `timed_out`).
|
|
1406
|
+
*
|
|
1407
|
+
* Calls `GET /v1/hitl`.
|
|
1408
|
+
*/
|
|
1409
|
+
listHitlEscalations(input?: ListHitlEscalationsRequest): Promise<{
|
|
1410
|
+
data: ListHitlEscalationsResponse;
|
|
1411
|
+
rateLimit: RateLimitState | null;
|
|
1412
|
+
}>;
|
|
1413
|
+
/**
|
|
1414
|
+
* Get a HITL escalation. The server payload includes a live
|
|
1415
|
+
* `quorum_progress` snapshot when the escalation is still open.
|
|
1416
|
+
*
|
|
1417
|
+
* Calls `GET /v1/hitl/:id`.
|
|
1418
|
+
*/
|
|
1419
|
+
getHitlEscalation(escalationId: string): Promise<{
|
|
1420
|
+
escalation: HitlEscalation;
|
|
1421
|
+
rateLimit: RateLimitState | null;
|
|
1422
|
+
}>;
|
|
1423
|
+
/**
|
|
1424
|
+
* List per-approver vote rows for an escalation.
|
|
1425
|
+
* Calls `GET /v1/hitl/:id/approvals`.
|
|
1426
|
+
*/
|
|
1427
|
+
listHitlApprovals(escalationId: string): Promise<{
|
|
1428
|
+
approvals: HitlApprovalRecord[];
|
|
1429
|
+
rateLimit: RateLimitState | null;
|
|
1430
|
+
}>;
|
|
1431
|
+
/**
|
|
1432
|
+
* List the escalation chain hops for an escalation. Each `/escalate`
|
|
1433
|
+
* call appends one row.
|
|
1434
|
+
* Calls `GET /v1/hitl/:id/chain`.
|
|
1435
|
+
*/
|
|
1436
|
+
getHitlChain(escalationId: string): Promise<{
|
|
1437
|
+
chain: HitlChainHop[];
|
|
1438
|
+
rateLimit: RateLimitState | null;
|
|
1439
|
+
}>;
|
|
1440
|
+
/**
|
|
1441
|
+
* Record an approve vote. Resolves the escalation only once the
|
|
1442
|
+
* server-side quorum count is satisfied; before that the response
|
|
1443
|
+
* carries a refreshed escalation row with the latest
|
|
1444
|
+
* `quorum_progress`.
|
|
1445
|
+
*
|
|
1446
|
+
* Calls `POST /v1/hitl/:id/approve`. The server returns 409
|
|
1447
|
+
* `duplicate_vote` if the same principal has already voted, and
|
|
1448
|
+
* 409 `already_rejected` if a concurrent reject crossed the line.
|
|
1449
|
+
*/
|
|
1450
|
+
approveHitlEscalation(escalationId: string, input?: HitlApproveRequest): Promise<{
|
|
1451
|
+
escalation: HitlEscalation;
|
|
1452
|
+
rateLimit: RateLimitState | null;
|
|
1453
|
+
}>;
|
|
1454
|
+
/**
|
|
1455
|
+
* Record a reject vote. Reject is short-circuit terminal — a single
|
|
1456
|
+
* reject closes the escalation regardless of how many approves have
|
|
1457
|
+
* accumulated.
|
|
1458
|
+
*
|
|
1459
|
+
* Calls `POST /v1/hitl/:id/reject`.
|
|
1460
|
+
*/
|
|
1461
|
+
rejectHitlEscalation(escalationId: string, input?: HitlRejectRequest): Promise<{
|
|
1462
|
+
escalation: HitlEscalation;
|
|
1463
|
+
rateLimit: RateLimitState | null;
|
|
1464
|
+
}>;
|
|
1465
|
+
/**
|
|
1466
|
+
* Re-route an open escalation to a higher tier. Bounded by the
|
|
1467
|
+
* escalation's `max_escalation_depth` — the server returns 409
|
|
1468
|
+
* `chain_exhausted` and applies the configured fallback decision
|
|
1469
|
+
* once the ceiling is hit.
|
|
1470
|
+
*
|
|
1471
|
+
* Calls `POST /v1/hitl/:id/escalate`.
|
|
1472
|
+
*/
|
|
1473
|
+
escalateHitlEscalation(escalationId: string, input: HitlEscalateRequest): Promise<{
|
|
1474
|
+
escalation: HitlEscalation;
|
|
1475
|
+
rateLimit: RateLimitState | null;
|
|
1476
|
+
}>;
|
|
1477
|
+
/**
|
|
1478
|
+
* Manually apply the escalation's `fallback_decision`. Useful for
|
|
1479
|
+
* admin recovery of a hung escalation when the cron sweeper hasn't
|
|
1480
|
+
* run yet, or to short-circuit a stuck flow during incident
|
|
1481
|
+
* response.
|
|
1482
|
+
*
|
|
1483
|
+
* Calls `POST /v1/hitl/:id/timeout`.
|
|
1484
|
+
*/
|
|
1485
|
+
timeoutHitlEscalation(escalationId: string): Promise<{
|
|
1486
|
+
escalation: HitlEscalation;
|
|
1487
|
+
rateLimit: RateLimitState | null;
|
|
1488
|
+
}>;
|
|
1489
|
+
/**
|
|
1490
|
+
* Run a named governance graph traversal query.
|
|
1491
|
+
*
|
|
1492
|
+
* Dispatches to `GET /v1/governance/graph/query?type=<queryType>`.
|
|
1493
|
+
* Each query type returns a different row shape — the return type
|
|
1494
|
+
* narrows automatically based on the literal `queryType` argument.
|
|
1495
|
+
*
|
|
1496
|
+
* `"user_approvals"` requires `params.actor_id` — the server returns
|
|
1497
|
+
* a 400 if it is absent.
|
|
1498
|
+
*/
|
|
1499
|
+
queryGovernanceGraph<T extends GovernanceGraphQueryType>(queryType: T, params?: GovernanceGraphQueryParams): Promise<GovernanceGraphQueryResponse<T>>;
|
|
1500
|
+
/**
|
|
1501
|
+
* Reconstruct the multi-system execution timeline for a specific incident.
|
|
1502
|
+
*
|
|
1503
|
+
* Calls `GET /v1/governance/timeline/incident/{incidentId}`. Backed
|
|
1504
|
+
* server-side by `reconstruct_incident_chains_v2()`, which fixes the
|
|
1505
|
+
* `executor_id → actor_id` bug that silently produced empty timelines
|
|
1506
|
+
* in the original function.
|
|
1507
|
+
*
|
|
1508
|
+
* Returns full execution rows including the §13.1 columns
|
|
1509
|
+
* (`delegation_chain_id`, `replay_of_execution_id`, `incident_id`,
|
|
1510
|
+
* `policy_version_id`, `bundle_version_id`) alongside the actor
|
|
1511
|
+
* timeline and evidence rows.
|
|
1512
|
+
*/
|
|
1513
|
+
getIncidentTimeline(incidentId: string): Promise<IncidentTimelineResponse>;
|
|
1514
|
+
/**
|
|
1515
|
+
* List connectors registered for the calling org.
|
|
1516
|
+
* Calls `GET /v1/governance/connectors`.
|
|
1517
|
+
*/
|
|
1518
|
+
listConnectors(options?: {
|
|
1519
|
+
cursor?: string;
|
|
1520
|
+
limit?: number;
|
|
1521
|
+
}): Promise<ListConnectorsResponse>;
|
|
1522
|
+
/**
|
|
1523
|
+
* Register and install a new connector for the calling org.
|
|
1524
|
+
* Calls `POST /v1/governance/connectors`.
|
|
1525
|
+
*/
|
|
1526
|
+
installConnector(input: InstallConnectorInput): Promise<InstallConnectorResponse>;
|
|
1527
|
+
/**
|
|
1528
|
+
* Store encrypted credentials for a connector.
|
|
1529
|
+
* Calls `POST /v1/governance/connectors/{id}/authenticate`.
|
|
1530
|
+
*/
|
|
1531
|
+
authenticateConnector(connectorId: string, input: AuthenticateConnectorInput): Promise<AuthenticateConnectorResponse>;
|
|
1532
|
+
/**
|
|
1533
|
+
* Trigger an incremental sync for a connector.
|
|
1534
|
+
* Calls `POST /v1/governance/connectors/{id}/sync`.
|
|
1535
|
+
*/
|
|
1536
|
+
syncConnector(connectorId: string): Promise<SyncConnectorResponse>;
|
|
1537
|
+
/**
|
|
1538
|
+
* Revoke a connector and all its associated credentials.
|
|
1539
|
+
* Calls `POST /v1/governance/connectors/{id}/revoke`.
|
|
1540
|
+
*/
|
|
1541
|
+
revokeConnector(connectorId: string, reason?: string): Promise<RevokeConnectorResponse>;
|
|
1542
|
+
/**
|
|
1543
|
+
* Rotate the credentials for a connector.
|
|
1544
|
+
* Calls `POST /v1/governance/connectors/{id}/rotate-credentials`.
|
|
1545
|
+
*/
|
|
1546
|
+
rotateConnectorCredentials(connectorId: string): Promise<RotateCredentialsResponse>;
|
|
1547
|
+
/**
|
|
1548
|
+
* List enforcement policies for the calling org, optionally filtered by connector type.
|
|
1549
|
+
* Calls `GET /v1/governance/enforcement-policies`.
|
|
1550
|
+
*/
|
|
1551
|
+
listEnforcementPolicies(connectorType?: ConnectorType): Promise<ListEnforcementPoliciesResponse>;
|
|
1552
|
+
/**
|
|
1553
|
+
* Create or update a connector enforcement policy.
|
|
1554
|
+
* Calls `POST /v1/governance/enforcement-policies`.
|
|
1555
|
+
*/
|
|
1556
|
+
upsertEnforcementPolicy(input: UpsertEnforcementPolicyInput): Promise<UpsertEnforcementPolicyResponse>;
|
|
1557
|
+
/**
|
|
1558
|
+
* Trigger a fresh org-level risk score computation.
|
|
1559
|
+
* Calls `POST /v1/governance/risk/compute`.
|
|
1560
|
+
*/
|
|
1561
|
+
computeOrgRisk(options?: ComputeOrgRiskOptions): Promise<ComputeOrgRiskResponse>;
|
|
1562
|
+
/**
|
|
1563
|
+
* Retrieve the most recently computed risk score for the calling org.
|
|
1564
|
+
* Calls `GET /v1/governance/risk/latest`.
|
|
1565
|
+
*/
|
|
1566
|
+
getLatestOrgRisk(): Promise<GetLatestOrgRiskResponse>;
|
|
1567
|
+
/**
|
|
1568
|
+
* Page through historical org risk scores, most-recent first.
|
|
1569
|
+
* Calls `GET /v1/governance/risk/history`.
|
|
1570
|
+
*/
|
|
1571
|
+
listOrgRiskHistory(options?: {
|
|
1572
|
+
cursor?: string;
|
|
1573
|
+
limit?: number;
|
|
1574
|
+
}): Promise<ListOrgRiskHistoryResponse>;
|
|
1575
|
+
checkCrossOrgPermission(req: CrossOrgPermissionCheckRequest): Promise<CrossOrgPermissionCheckResult>;
|
|
1576
|
+
listCrossOrgPermissionChecks(params?: CrossOrgPermissionCheckListParams): Promise<CrossOrgPermissionCheckResult[]>;
|
|
1577
|
+
listAnomalyResponseRules(): Promise<AnomalyResponseRule[]>;
|
|
1578
|
+
createAnomalyResponseRule(req: CreateAnomalyResponseRuleRequest): Promise<AnomalyResponseRule>;
|
|
1579
|
+
updateAnomalyResponseRule(id: string, updates: Partial<CreateAnomalyResponseRuleRequest>): Promise<AnomalyResponseRule>;
|
|
1580
|
+
deleteAnomalyResponseRule(id: string): Promise<void>;
|
|
1581
|
+
triggerAnomalyResponse(req: TriggerAnomalyResponseRequest): Promise<AnomalyResponseEvent[]>;
|
|
1582
|
+
listAnomalyResponseEvents(params?: {
|
|
1583
|
+
limit?: number;
|
|
1584
|
+
execution_id?: string;
|
|
1585
|
+
}): Promise<AnomalyResponseEvent[]>;
|
|
1586
|
+
listBudgetExceptions(params?: {
|
|
1587
|
+
status?: BudgetExceptionStatus;
|
|
1588
|
+
budget_policy_id?: string;
|
|
1589
|
+
limit?: number;
|
|
1590
|
+
offset?: number;
|
|
1591
|
+
}): Promise<BudgetExceptionRequest[]>;
|
|
1592
|
+
getBudgetException(id: string): Promise<BudgetExceptionRequest>;
|
|
1593
|
+
createBudgetException(req: CreateBudgetExceptionRequest): Promise<BudgetExceptionRequest>;
|
|
1594
|
+
approveBudgetException(id: string, req: ApproveBudgetExceptionRequest): Promise<BudgetExceptionRequest>;
|
|
1595
|
+
rejectBudgetException(id: string, review_notes?: string): Promise<BudgetExceptionRequest>;
|
|
1596
|
+
cancelBudgetException(id: string): Promise<BudgetExceptionRequest>;
|
|
1597
|
+
listRegulatoryAuthorityLevels(): Promise<RegulatoryAuthorityLevel[]>;
|
|
1598
|
+
createRegulatoryAuthorityLevel(req: Omit<RegulatoryAuthorityLevel, "id" | "org_id" | "created_at">): Promise<RegulatoryAuthorityLevel>;
|
|
1599
|
+
listRegulatoryEscalations(params?: {
|
|
1600
|
+
status?: RegulatoryEscalationStatus;
|
|
1601
|
+
subject_type?: string;
|
|
1602
|
+
subject_id?: string;
|
|
1603
|
+
}): Promise<RegulatoryEscalation[]>;
|
|
1604
|
+
createRegulatoryEscalation(req: CreateRegulatoryEscalationRequest): Promise<RegulatoryEscalation>;
|
|
1605
|
+
acknowledgeRegulatoryEscalation(id: string): Promise<RegulatoryEscalation>;
|
|
1606
|
+
resolveRegulatoryEscalation(id: string, resolution: string, resolution_details?: Record<string, unknown>): Promise<RegulatoryEscalation>;
|
|
1607
|
+
overrideRegulatoryEscalation(id: string, reason: string): Promise<RegulatoryEscalation>;
|
|
1608
|
+
listSignalActions(signal_id: string): Promise<GovernanceSignalAction[]>;
|
|
1609
|
+
recordSignalAction(signal_id: string, req: RecordSignalActionRequest): Promise<GovernanceSignalAction>;
|
|
1610
|
+
recordSignalOutcome(signal_id: string, action_id: string, req: RecordSignalOutcomeRequest): Promise<GovernanceSignalAction>;
|
|
1611
|
+
getSignalActionSummary(): Promise<SignalActionSummary>;
|
|
1612
|
+
listImpersonationGrants(): Promise<CrossOrgImpersonationGrant[]>;
|
|
1613
|
+
createImpersonationGrant(req: CreateImpersonationGrantRequest): Promise<CrossOrgImpersonationGrant>;
|
|
1614
|
+
revokeImpersonationGrant(id: string): Promise<void>;
|
|
1615
|
+
issueImpersonationToken(grant_id: string, requested_duration_seconds?: number): Promise<ImpersonationToken>;
|
|
1616
|
+
validateImpersonationToken(token: string): Promise<ImpersonationValidationResult>;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
/** Node's webcrypto CryptoKey — kept local so the module doesn't depend on DOM types. */
|
|
1620
|
+
type WebCryptoKey = webcrypto.CryptoKey;
|
|
1621
|
+
/** Public key candidate the verifier will try, tagged with its registry id. */
|
|
1622
|
+
interface VerifyKey {
|
|
1623
|
+
keyId: string;
|
|
1624
|
+
publicKey: WebCryptoKey;
|
|
1625
|
+
}
|
|
1626
|
+
interface BundleVerificationResult {
|
|
1627
|
+
/**
|
|
1628
|
+
* AND of three checks: adjacency (each event's `previous_hash`
|
|
1629
|
+
* equals the prior event's `hash`), per-event hash recomputation
|
|
1630
|
+
* from the canonical payload, and `chain_head_hash` matching the
|
|
1631
|
+
* last event's stored hash.
|
|
1632
|
+
*/
|
|
1633
|
+
chainIntegrityOk: boolean;
|
|
1634
|
+
/** Ed25519 signature verified against one of the supplied public keys. */
|
|
1635
|
+
signatureValid: boolean;
|
|
1636
|
+
/** `chain_head_hash` equals the last event's stored `hash`. */
|
|
1637
|
+
headHashMatches: boolean;
|
|
1638
|
+
/** Event ids whose recomputed hash != stored hash. */
|
|
1639
|
+
tamperedEventIds: string[];
|
|
1640
|
+
/** Which registry key id matched, when `signatureValid` is true. */
|
|
1641
|
+
matchedKeyId?: string | undefined;
|
|
1642
|
+
/** Non-fatal explanation when a flag is false. */
|
|
1643
|
+
reason?: string | undefined;
|
|
1644
|
+
/** Convenience: `chainIntegrityOk && signatureValid`. */
|
|
1645
|
+
verified: boolean;
|
|
1646
|
+
}
|
|
1647
|
+
/** Parsed bundle shape the verifier consumes. Fields beyond these are ignored. */
|
|
1648
|
+
interface AuditBundle {
|
|
1649
|
+
export_id?: unknown;
|
|
1650
|
+
org_id?: unknown;
|
|
1651
|
+
chain_head_hash?: unknown;
|
|
1652
|
+
event_count?: unknown;
|
|
1653
|
+
signed_at?: unknown;
|
|
1654
|
+
events?: unknown;
|
|
1655
|
+
signature?: unknown;
|
|
1656
|
+
signing_key_id?: unknown;
|
|
1657
|
+
[k: string]: unknown;
|
|
1658
|
+
}
|
|
1659
|
+
interface VerifyBundleOptions {
|
|
1660
|
+
/** SPKI-PEM strings (one per key in the active trust set). */
|
|
1661
|
+
publicKeysPem?: readonly string[];
|
|
1662
|
+
/** Already-imported keys, paired with registry ids (rotation hint). */
|
|
1663
|
+
keys?: readonly VerifyKey[];
|
|
1664
|
+
}
|
|
1665
|
+
/**
|
|
1666
|
+
* Reproduces `_shared/rules.ts::canonicalJSON` byte-for-byte:
|
|
1667
|
+
* - object keys sorted at every depth
|
|
1668
|
+
* - no whitespace
|
|
1669
|
+
* - `null`, `undefined`, `NaN`, `±Infinity` all render as `"null"`
|
|
1670
|
+
* - strings use standard `JSON.stringify` escapes
|
|
1671
|
+
*/
|
|
1672
|
+
declare function canonicalJSON(value: unknown): string;
|
|
1673
|
+
/**
|
|
1674
|
+
* Recreate the exact bytes `handleExport` signed. Key order is
|
|
1675
|
+
* load-bearing — must match the object literal in
|
|
1676
|
+
* `v1-audit/index.ts::handleExport`. V8 preserves insertion order, so
|
|
1677
|
+
* the literal below is byte-identical with what the backend signs.
|
|
1678
|
+
*/
|
|
1679
|
+
declare function signedBytesFor(bundle: AuditBundle): Uint8Array<ArrayBuffer>;
|
|
1680
|
+
declare function verifyAuditBundle(bundle: AuditBundle, keys: readonly VerifyKey[]): Promise<BundleVerificationResult>;
|
|
1681
|
+
/**
|
|
1682
|
+
* Load a bundle from disk (or a parsed object) and verify it.
|
|
1683
|
+
*
|
|
1684
|
+
* `publicKeysPem` is the active SPKI-PEM set from
|
|
1685
|
+
* `GET /v1-signing-keys`. When omitted, the chain check still runs
|
|
1686
|
+
* but `signatureValid` will be false with an explanatory `reason` —
|
|
1687
|
+
* callers that want a complete offline check MUST supply the trust
|
|
1688
|
+
* set.
|
|
1689
|
+
*/
|
|
1690
|
+
declare function verifyBundle(pathOrBundle: string | AuditBundle, options?: VerifyBundleOptions): Promise<BundleVerificationResult>;
|
|
1691
|
+
|
|
1692
|
+
/**
|
|
1693
|
+
* `requirePermit` — higher-order execution gate for dangerous operations.
|
|
1694
|
+
*
|
|
1695
|
+
* Wraps any dangerous operation so it can only run after AtlaSent
|
|
1696
|
+
* authorizes it end-to-end (evaluate + verifyPermit). If authorization
|
|
1697
|
+
* is denied or the transport fails, the executor is never called.
|
|
1698
|
+
*
|
|
1699
|
+
* ```ts
|
|
1700
|
+
* import atlasent from "@atlasent/sdk";
|
|
1701
|
+
*
|
|
1702
|
+
* await atlasent.requirePermit(
|
|
1703
|
+
* {
|
|
1704
|
+
* action_type: "database.table.drop",
|
|
1705
|
+
* actor_id: "agent:code-agent",
|
|
1706
|
+
* resource_id: "prod-db.users",
|
|
1707
|
+
* environment: "production",
|
|
1708
|
+
* context: { reversibility: "irreversible", blast_radius: "customer_data" },
|
|
1709
|
+
* },
|
|
1710
|
+
* async () => {
|
|
1711
|
+
* await db.raw("DROP TABLE users");
|
|
1712
|
+
* },
|
|
1713
|
+
* );
|
|
1714
|
+
* ```
|
|
1715
|
+
*
|
|
1716
|
+
* Unlike calling the executor directly, dangerous code cannot bypass
|
|
1717
|
+
* this gate: if `requirePermit` throws, the executor never runs.
|
|
1718
|
+
*/
|
|
1719
|
+
/**
|
|
1720
|
+
* Describes a potentially dangerous action to be authorized before
|
|
1721
|
+
* the executor runs. Passed as the first argument to {@link requirePermit}.
|
|
1722
|
+
*/
|
|
1723
|
+
type ProtectedAction = {
|
|
1724
|
+
/** Namespaced action type — e.g. "database.table.drop". */
|
|
1725
|
+
action_type: string;
|
|
1726
|
+
/** Agent or user requesting the action — e.g. "agent:deploy-bot". */
|
|
1727
|
+
actor_id: string;
|
|
1728
|
+
/** Resource being acted upon — e.g. "prod-db.users". */
|
|
1729
|
+
resource_id: string;
|
|
1730
|
+
/** Target deployment environment. Controls policy strictness. */
|
|
1731
|
+
environment: "development" | "staging" | "production";
|
|
1732
|
+
/** Arbitrary risk context forwarded to the policy engine. */
|
|
1733
|
+
context: Record<string, unknown>;
|
|
1734
|
+
};
|
|
1735
|
+
/**
|
|
1736
|
+
* Authorize a dangerous operation before running it.
|
|
1737
|
+
*
|
|
1738
|
+
* Calls `protect` (evaluate + verifyPermit) with the {@link ProtectedAction}
|
|
1739
|
+
* descriptor. If authorization succeeds, calls `execute` and returns its
|
|
1740
|
+
* result. On any failure — policy deny, invalid permit, transport error —
|
|
1741
|
+
* `execute` is never called and the error propagates to the caller.
|
|
1742
|
+
*
|
|
1743
|
+
* This is the pattern primitive: dangerous code should be callable
|
|
1744
|
+
* **only** through this wrapper. In code review, any operation in the list
|
|
1745
|
+
* below is illegal unless it appears inside `requirePermit(...)`:
|
|
1746
|
+
*
|
|
1747
|
+
* - `db.raw(...)` / `DROP TABLE` / `DELETE FROM` / `TRUNCATE TABLE`
|
|
1748
|
+
* - `exec(...)` / `rm -rf` / `kubectl delete` / `terraform destroy`
|
|
1749
|
+
* - `stripe.transfers.create(...)` / `github.deployments.create(...)`
|
|
1750
|
+
* - `railway.volumes.delete(...)` / `supabase.from(...).delete()`
|
|
1751
|
+
*/
|
|
1752
|
+
declare function requirePermit<T>(action: ProtectedAction, execute: () => Promise<T>): Promise<T>;
|
|
1753
|
+
/**
|
|
1754
|
+
* Classify a shell or database command as destructive.
|
|
1755
|
+
*
|
|
1756
|
+
* Returns the namespaced action type (e.g. `"destructive.command"`) when the
|
|
1757
|
+
* command matches a known dangerous pattern, or `null` when it appears safe.
|
|
1758
|
+
* Use the return value as `action_type` in a {@link requirePermit} call before
|
|
1759
|
+
* executing the command:
|
|
1760
|
+
*
|
|
1761
|
+
* ```ts
|
|
1762
|
+
* async function runCommand(command: string, actorId: string) {
|
|
1763
|
+
* const actionType = classifyCommand(command);
|
|
1764
|
+
* if (actionType) {
|
|
1765
|
+
* return requirePermit(
|
|
1766
|
+
* { action_type: actionType, actor_id: actorId, resource_id: command,
|
|
1767
|
+
* environment: "production", context: { command } },
|
|
1768
|
+
* () => exec(command),
|
|
1769
|
+
* );
|
|
1770
|
+
* }
|
|
1771
|
+
* return exec(command);
|
|
1772
|
+
* }
|
|
1773
|
+
* ```
|
|
1774
|
+
*/
|
|
1775
|
+
declare function classifyCommand(command: string): string | null;
|
|
1776
|
+
|
|
1777
|
+
/**
|
|
1778
|
+
* `atlasent.withPermit(...)` — the lexically-scoped form of
|
|
1779
|
+
* {@link protect}. TypeScript mirror of the Python SDK's
|
|
1780
|
+
* ``atlasent.with_permit(...)``.
|
|
1781
|
+
*
|
|
1782
|
+
* Same execution-boundary contract as {@link protect}: evaluate +
|
|
1783
|
+
* verifyPermit run end-to-end before the executor is invoked, and the
|
|
1784
|
+
* executor cannot run unless a verified {@link Permit} was returned.
|
|
1785
|
+
* The difference is purely lexical — `withPermit` binds the execution
|
|
1786
|
+
* to the permit's lifetime via a callback, so the call site reads as
|
|
1787
|
+
* "execute this body under a permit" rather than "fetch a permit and
|
|
1788
|
+
* run code under it manually."
|
|
1789
|
+
*
|
|
1790
|
+
* ```ts
|
|
1791
|
+
* import atlasent from "@atlasent/sdk";
|
|
1792
|
+
*
|
|
1793
|
+
* const ok = await atlasent.withPermit(
|
|
1794
|
+
* {
|
|
1795
|
+
* agent: "deploy-bot",
|
|
1796
|
+
* action: "production.deploy",
|
|
1797
|
+
* context: { commit, approver },
|
|
1798
|
+
* },
|
|
1799
|
+
* async (permit) => {
|
|
1800
|
+
* const result = await runDeploy(commit);
|
|
1801
|
+
* return { ok: true, permitId: permit.permitId, result };
|
|
1802
|
+
* },
|
|
1803
|
+
* );
|
|
1804
|
+
* ```
|
|
1805
|
+
*
|
|
1806
|
+
* Pick the form that fits the call site:
|
|
1807
|
+
*
|
|
1808
|
+
* - {@link protect} when the caller wants the verified permit as a
|
|
1809
|
+
* value (e.g. to pass it across a process boundary, persist it
|
|
1810
|
+
* alongside their own record, or interleave it with non-trivial
|
|
1811
|
+
* control flow).
|
|
1812
|
+
* - {@link withPermit} when the action body is a single lexical scope
|
|
1813
|
+
* and "no permit, no execution" is the only thing the call site
|
|
1814
|
+
* needs to express.
|
|
1815
|
+
*
|
|
1816
|
+
* Both surfaces use the same underlying primitive and produce the
|
|
1817
|
+
* same audit-chain entry.
|
|
1818
|
+
*/
|
|
1819
|
+
|
|
1820
|
+
/**
|
|
1821
|
+
* Authorize a request end-to-end and invoke `fn` only on a verified
|
|
1822
|
+
* permit.
|
|
1823
|
+
*
|
|
1824
|
+
* @param request Same shape as {@link ProtectRequest}.
|
|
1825
|
+
* @param fn Invoked with the verified {@link Permit}. Its return
|
|
1826
|
+
* value (awaited if it is a promise) is propagated to the caller.
|
|
1827
|
+
*
|
|
1828
|
+
* @returns Whatever `fn` returns.
|
|
1829
|
+
*
|
|
1830
|
+
* @throws {AtlaSentDeniedError} Policy denied, hold/escalate, or
|
|
1831
|
+
* permit failed verification. `fn` is never invoked.
|
|
1832
|
+
* @throws {AtlaSentError} Transport, timeout, auth, rate-limit, or
|
|
1833
|
+
* server error. `fn` is never invoked.
|
|
1834
|
+
*
|
|
1835
|
+
* Errors thrown inside `fn` propagate untouched — the permit is
|
|
1836
|
+
* already consumed by the verify step in v1, so there is no
|
|
1837
|
+
* compensating revoke.
|
|
1838
|
+
*/
|
|
1839
|
+
declare function withPermit<T>(request: ProtectRequest, fn: (permit: Permit) => Promise<T> | T): Promise<T>;
|
|
1840
|
+
|
|
1841
|
+
/**
|
|
1842
|
+
* Sandbox simulation diff — wire shape for `GET /v1/agent-sandbox/:id/diff`.
|
|
1843
|
+
*
|
|
1844
|
+
* Mirrors the `export_sandbox_diff()` SQL function added in migration
|
|
1845
|
+
* 20260509120000. Lets a caller render a sandbox-vs-live preview
|
|
1846
|
+
* before promoting a simulation to a real execution. Once a sandbox
|
|
1847
|
+
* run reaches a terminal status it is auto-torn-down; a follow-up
|
|
1848
|
+
* call returns the {@link SandboxDiffEmpty} shape so the UI can
|
|
1849
|
+
* surface "this run has been finalised" without a 404.
|
|
1850
|
+
*/
|
|
1851
|
+
type SandboxRunMode = "dry_run" | "simulation" | "constrained_execution" | "production_execution";
|
|
1852
|
+
type SandboxRunStatus = "pending" | "running" | "completed" | "failed" | "cancelled" | "timed_out";
|
|
1853
|
+
type SandboxWriteOp = "insert" | "update" | "delete";
|
|
1854
|
+
interface SandboxRunWrite {
|
|
1855
|
+
sequence: number;
|
|
1856
|
+
live_table: string;
|
|
1857
|
+
live_pk: string | null;
|
|
1858
|
+
op: SandboxWriteOp;
|
|
1859
|
+
payload_before: Record<string, unknown> | null;
|
|
1860
|
+
payload_after: Record<string, unknown> | null;
|
|
1861
|
+
metadata: Record<string, unknown>;
|
|
1862
|
+
created_at: string;
|
|
1863
|
+
}
|
|
1864
|
+
interface SandboxDiffPerTable {
|
|
1865
|
+
total: number;
|
|
1866
|
+
insert: number;
|
|
1867
|
+
update: number;
|
|
1868
|
+
delete: number;
|
|
1869
|
+
}
|
|
1870
|
+
/** Returned when staging rows are still present for the run. */
|
|
1871
|
+
interface SandboxDiff {
|
|
1872
|
+
simulation_run_id: string;
|
|
1873
|
+
org_id: string;
|
|
1874
|
+
final_status: SandboxRunStatus;
|
|
1875
|
+
mode: SandboxRunMode;
|
|
1876
|
+
total_writes: number;
|
|
1877
|
+
/** Keyed by live table name. */
|
|
1878
|
+
summary: Record<string, SandboxDiffPerTable>;
|
|
1879
|
+
writes: SandboxRunWrite[];
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* Returned when the run has been torn down — staging rows are gone
|
|
1883
|
+
* and the audit-log `agent_sandbox.teardown` event is the only
|
|
1884
|
+
* post-mortem record.
|
|
1885
|
+
*/
|
|
1886
|
+
interface SandboxDiffEmpty {
|
|
1887
|
+
simulation_run_id: string;
|
|
1888
|
+
status: SandboxRunStatus;
|
|
1889
|
+
mode: SandboxRunMode;
|
|
1890
|
+
torn_down: boolean;
|
|
1891
|
+
total_writes: 0;
|
|
1892
|
+
summary: Record<string, never>;
|
|
1893
|
+
writes: [];
|
|
1894
|
+
}
|
|
1895
|
+
type SandboxDiffResponse = SandboxDiff | SandboxDiffEmpty;
|
|
1896
|
+
/**
|
|
1897
|
+
* `true` when the response carries staging rows (i.e. the run has not
|
|
1898
|
+
* been torn down yet). Narrow before reading `summary` / `writes`.
|
|
1899
|
+
*/
|
|
1900
|
+
declare function isSandboxDiffPopulated(r: SandboxDiffResponse): r is SandboxDiff;
|
|
1901
|
+
|
|
1902
|
+
/**
|
|
1903
|
+
* Delegation revocation propagation — wire shape for the
|
|
1904
|
+
* `propagate_delegation_revocation()` summary returned by
|
|
1905
|
+
* `/v1/authority-delegations/:id/revoke` (and emitted as the
|
|
1906
|
+
* `authority_delegation.propagated` audit event).
|
|
1907
|
+
*
|
|
1908
|
+
* Mirrors migration 20260509120001. The propagator is invoked
|
|
1909
|
+
* automatically on `status -> revoked` via DB trigger; consumers
|
|
1910
|
+
* see the summary either as the audit-event payload (asynchronous)
|
|
1911
|
+
* or attached to the revoke response (synchronous).
|
|
1912
|
+
*/
|
|
1913
|
+
interface DelegationPropagationSummary {
|
|
1914
|
+
delegation_id: string;
|
|
1915
|
+
/** `[delegator_user_id, delegate_user_id]` — uuids as strings. */
|
|
1916
|
+
principals: [string, string];
|
|
1917
|
+
/** Phase-B role-justified delegations carry the role; user-justified
|
|
1918
|
+
* delegations omit it. */
|
|
1919
|
+
delegator_role?: string | null;
|
|
1920
|
+
hitl_reassigned: number;
|
|
1921
|
+
financial_invalidated: number;
|
|
1922
|
+
policies_flagged: number;
|
|
1923
|
+
revoked_reason?: string | null;
|
|
1924
|
+
}
|
|
1925
|
+
/**
|
|
1926
|
+
* Convenience predicate: `true` when the revocation produced any
|
|
1927
|
+
* downstream effect. Useful for "are we sure?" UI guards before
|
|
1928
|
+
* surfacing the summary toast.
|
|
1929
|
+
*/
|
|
1930
|
+
declare function delegationPropagationHadEffect(s: DelegationPropagationSummary): boolean;
|
|
1931
|
+
|
|
1932
|
+
/**
|
|
1933
|
+
* Public types for the AtlaSent **Identity Assertion** — a signed
|
|
1934
|
+
* attestation from an identity provider (OIDC / SSO) that the
|
|
1935
|
+
* reviewer named in an approval_artifact.v1 is a real human with a
|
|
1936
|
+
* specific role.
|
|
1937
|
+
*
|
|
1938
|
+
* Wire-stable as `identity_assertion.v1`. The contract lives in
|
|
1939
|
+
* `contract/schemas/identity-assertion.schema.json`. Verification is
|
|
1940
|
+
* server-side inside `/v1-evaluate`; the SDK exposes the types so
|
|
1941
|
+
* callers can construct or inspect the `identity_assertion` block on
|
|
1942
|
+
* an approval artifact.
|
|
1943
|
+
*
|
|
1944
|
+
* Why this matters: without identity attestation the artifact's
|
|
1945
|
+
* `reviewer.principal_kind: "human"` is a self-claim from the
|
|
1946
|
+
* approval issuer alone. With it, the IdP independently vouches for
|
|
1947
|
+
* the human — a separate trust root, defence in depth.
|
|
1948
|
+
*/
|
|
1949
|
+
|
|
1950
|
+
/** Identity-attested subject of the assertion. The verifier requires
|
|
1951
|
+
* `principal_kind === "human"`; the other variants exist so the
|
|
1952
|
+
* schema can structurally describe denied/declined assertions. */
|
|
1953
|
+
interface IdentitySubject {
|
|
1954
|
+
principal_id: string;
|
|
1955
|
+
principal_kind: PrincipalKind;
|
|
1956
|
+
}
|
|
1957
|
+
/** Cryptographic binding tying the assertion to a specific approval. */
|
|
1958
|
+
interface IdentityAssertionBinding {
|
|
1959
|
+
/** Must equal artifact.approval_id. */
|
|
1960
|
+
approval_id: string;
|
|
1961
|
+
/** Must equal the canonical action hash. */
|
|
1962
|
+
action_hash: string;
|
|
1963
|
+
/** Must equal the request's tenant_id. */
|
|
1964
|
+
tenant_id: string;
|
|
1965
|
+
/** Must equal the request's environment. Empty string allowed when
|
|
1966
|
+
* the verifier was not given one (explicit equality, no implicit
|
|
1967
|
+
* broadening). */
|
|
1968
|
+
environment: string;
|
|
1969
|
+
}
|
|
1970
|
+
/** Identity issuer (the IdP). Always OIDC-shaped. */
|
|
1971
|
+
interface IdentityIssuer {
|
|
1972
|
+
type: "oidc";
|
|
1973
|
+
issuer_id: string;
|
|
1974
|
+
/** Key id for rotation; looked up in IDENTITY_TRUSTED_ISSUERS. */
|
|
1975
|
+
kid: string;
|
|
1976
|
+
}
|
|
1977
|
+
/** A complete signed identity assertion. */
|
|
1978
|
+
interface IdentityAssertionV1 {
|
|
1979
|
+
version: "identity_assertion.v1";
|
|
1980
|
+
subject: IdentitySubject;
|
|
1981
|
+
/** Required role attested by the IdP (e.g. "qa_reviewer"). */
|
|
1982
|
+
role: string;
|
|
1983
|
+
binding: IdentityAssertionBinding;
|
|
1984
|
+
issuer: IdentityIssuer;
|
|
1985
|
+
issued_at: string;
|
|
1986
|
+
expires_at: string;
|
|
1987
|
+
/** Optional anti-replay nonce. The approval-artifact nonce is the
|
|
1988
|
+
* primary defence; deployments wanting assertion-level replay
|
|
1989
|
+
* protection ledger this separately. */
|
|
1990
|
+
nonce?: string;
|
|
1991
|
+
signature: string;
|
|
1992
|
+
}
|
|
1993
|
+
/** Per-issuer entry in IDENTITY_TRUSTED_ISSUERS. Server-side config
|
|
1994
|
+
* only — never on the wire. The SDK exposes the type so operators
|
|
1995
|
+
* can lint config in CI. */
|
|
1996
|
+
interface IdentityIssuerKey {
|
|
1997
|
+
alg: "HS256" | "Ed25519";
|
|
1998
|
+
key: string;
|
|
1999
|
+
/** Per-issuer scope: roles this kid may attest. Empty/missing = unscoped. */
|
|
2000
|
+
allowed_roles?: string[];
|
|
2001
|
+
/** Per-issuer scope: environments this kid may attest in. Empty/missing = unscoped. */
|
|
2002
|
+
allowed_environments?: string[];
|
|
2003
|
+
}
|
|
2004
|
+
/** JSON shape of IDENTITY_TRUSTED_ISSUERS. Keyed by issuer_id then by
|
|
2005
|
+
* kid. Independent trust root from APPROVAL_TRUSTED_ISSUERS. */
|
|
2006
|
+
type IdentityTrustedIssuersConfig = Record<string, Record<string, IdentityIssuerKey>>;
|
|
2007
|
+
|
|
2008
|
+
/**
|
|
2009
|
+
* Public types for the AtlaSent **Approval Artifact** — a signed
|
|
2010
|
+
* attestation that a *human* reviewer approved a specific action.
|
|
2011
|
+
*
|
|
2012
|
+
* Wire-stable as `approval_artifact.v1`. The contract lives in
|
|
2013
|
+
* `contract/schemas/approval-artifact.schema.json`. Verification is
|
|
2014
|
+
* server-side inside `/v1-evaluate`; the SDK exposes the types so
|
|
2015
|
+
* callers can construct the `approval` field on an evaluate request.
|
|
2016
|
+
*
|
|
2017
|
+
* Why this matters: the calling agent cannot self-declare authority
|
|
2018
|
+
* by passing reviewer flags in `context`. The artifact is bound to
|
|
2019
|
+
* the exact action via `action_hash`, signed by a trusted issuer,
|
|
2020
|
+
* and replay-protected via `nonce`.
|
|
2021
|
+
*/
|
|
2022
|
+
/** What kind of principal performed the approval. */
|
|
2023
|
+
type PrincipalKind = "human" | "agent" | "service_account";
|
|
2024
|
+
/** Identity of the reviewer recorded inside the artifact. */
|
|
2025
|
+
interface ApprovalReviewer {
|
|
2026
|
+
principal_id: string;
|
|
2027
|
+
principal_kind: PrincipalKind;
|
|
2028
|
+
email?: string;
|
|
2029
|
+
groups?: string[];
|
|
2030
|
+
roles?: string[];
|
|
2031
|
+
}
|
|
2032
|
+
/** Trusted issuer identification — used to look up the verification key. */
|
|
2033
|
+
interface ApprovalIssuer {
|
|
2034
|
+
type: "oidc" | "approval_service";
|
|
2035
|
+
issuer_id: string;
|
|
2036
|
+
kid: string;
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
/**
|
|
2040
|
+
* The full signed approval artifact. Producers (approval services)
|
|
2041
|
+
* compute `action_hash` over the canonical action payload and sign
|
|
2042
|
+
* the artifact with the `signature` field stripped; the SDK does not
|
|
2043
|
+
* sign or verify, it only carries the artifact to the server.
|
|
2044
|
+
*
|
|
2045
|
+
* `identity_assertion` is REQUIRED on the wire whenever
|
|
2046
|
+
* `/v1-evaluate` calls the verifier with `requireIdentityAssertion:
|
|
2047
|
+
* true` — i.e. when human approval is required. Without it, the
|
|
2048
|
+
* server returns deny:`missing identity assertion`. The SDK type
|
|
2049
|
+
* keeps the field optional to support shadow / preflight flows that
|
|
2050
|
+
* inspect an artifact without verifying.
|
|
2051
|
+
*/
|
|
2052
|
+
interface ApprovalArtifactV1 {
|
|
2053
|
+
version: "approval_artifact.v1";
|
|
2054
|
+
approval_id: string;
|
|
2055
|
+
tenant_id: string;
|
|
2056
|
+
action_type: string;
|
|
2057
|
+
resource_id: string;
|
|
2058
|
+
action_hash: string;
|
|
2059
|
+
reviewer: ApprovalReviewer;
|
|
2060
|
+
issuer: ApprovalIssuer;
|
|
2061
|
+
issued_at: string;
|
|
2062
|
+
expires_at: string;
|
|
2063
|
+
nonce: string;
|
|
2064
|
+
signature: string;
|
|
2065
|
+
identity_assertion?: IdentityAssertionV1;
|
|
2066
|
+
}
|
|
2067
|
+
/**
|
|
2068
|
+
* Optional `approval` field on an evaluate request. Either embed the
|
|
2069
|
+
* full artifact, or pass an `approval_id` and let the server resolve
|
|
2070
|
+
* it from a side channel (preferred when the artifact is large).
|
|
2071
|
+
*/
|
|
2072
|
+
interface ApprovalReference {
|
|
2073
|
+
approval_id?: string;
|
|
2074
|
+
artifact?: ApprovalArtifactV1;
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
/**
|
|
2078
|
+
* Public types for the AtlaSent **Approval Quorum** — the additive
|
|
2079
|
+
* layer that lets multiple individually-trustworthy approvals be
|
|
2080
|
+
* combined into a single quorum package.
|
|
2081
|
+
*
|
|
2082
|
+
* Wire-stable as `approval_quorum.v1`. The contract lives in
|
|
2083
|
+
* `contract/schemas/approval-quorum.schema.json`. Verification is
|
|
2084
|
+
* server-side inside `/v1-evaluate`; the SDK exposes the types so
|
|
2085
|
+
* callers can construct a quorum payload before submitting.
|
|
2086
|
+
*
|
|
2087
|
+
* Important invariant (locked): quorum does NOT relax artifact
|
|
2088
|
+
* verification. Every approval inside a quorum package must first
|
|
2089
|
+
* pass the locked single-approval verifier (artifact signature +
|
|
2090
|
+
* identity assertion + every binding) BEFORE quorum-level policy is
|
|
2091
|
+
* evaluated. If any single approval fails, the whole package is
|
|
2092
|
+
* denied with that approval's exact reason — no fallthrough.
|
|
2093
|
+
*/
|
|
2094
|
+
|
|
2095
|
+
/** Independence constraints on a quorum policy. Duplicate
|
|
2096
|
+
* `reviewer.principal_id` is ALWAYS rejected regardless of these
|
|
2097
|
+
* flags; these strengthen the requirement further. */
|
|
2098
|
+
interface QuorumIndependence {
|
|
2099
|
+
/** When true, requires distinct *approval-issuer* identities so
|
|
2100
|
+
* two tokens minted by the same QA system don't count separately
|
|
2101
|
+
* even if signed for different reviewers. */
|
|
2102
|
+
distinct_approval_issuers?: boolean;
|
|
2103
|
+
/** When true, requires distinct *identity-issuer* identities so
|
|
2104
|
+
* collusion between IdPs vouching for the same effective
|
|
2105
|
+
* reviewer pool is harder. */
|
|
2106
|
+
distinct_identity_issuers?: boolean;
|
|
2107
|
+
}
|
|
2108
|
+
/** A single role × count requirement in a quorum policy. */
|
|
2109
|
+
interface QuorumRoleRequirement {
|
|
2110
|
+
role: string;
|
|
2111
|
+
/** Minimum number of approvals carrying this role. */
|
|
2112
|
+
min: number;
|
|
2113
|
+
}
|
|
2114
|
+
/** Quorum policy describing what counts as passing. */
|
|
2115
|
+
interface QuorumPolicy {
|
|
2116
|
+
/** Minimum total approvals (regardless of role). */
|
|
2117
|
+
required_count: number;
|
|
2118
|
+
/** OPTIONAL role-mix requirements; each is checked independently. */
|
|
2119
|
+
required_role_mix?: QuorumRoleRequirement[];
|
|
2120
|
+
/** Independence constraints. Duplicate principal_id is always
|
|
2121
|
+
* rejected; these flags additionally require distinct issuers. */
|
|
2122
|
+
independence?: QuorumIndependence;
|
|
2123
|
+
/** OPTIONAL package-level staleness window in seconds. Layered on
|
|
2124
|
+
* top of each artifact's own `expires_at` — both must be in the
|
|
2125
|
+
* future. */
|
|
2126
|
+
max_age_seconds?: number;
|
|
2127
|
+
}
|
|
2128
|
+
/** A signed quorum package carrying multiple approvals. */
|
|
2129
|
+
interface ApprovalQuorumV1 {
|
|
2130
|
+
version: "approval_quorum.v1";
|
|
2131
|
+
tenant_id: string;
|
|
2132
|
+
/** Canonical action hash. Must match every approval's action_hash
|
|
2133
|
+
* and the verifier's expected_action_hash. */
|
|
2134
|
+
action_hash: string;
|
|
2135
|
+
environment: string;
|
|
2136
|
+
issued_at: string;
|
|
2137
|
+
policy: QuorumPolicy;
|
|
2138
|
+
/** The approvals being counted. Each is a full ApprovalArtifactV1
|
|
2139
|
+
* carrying its own identity_assertion. */
|
|
2140
|
+
approvals: ApprovalArtifactV1[];
|
|
2141
|
+
}
|
|
2142
|
+
/** Cryptographic proof material returned on a passing quorum.
|
|
2143
|
+
* Persisted on the audit row so external auditors can reconstruct
|
|
2144
|
+
* WHO approved together without per-approval row joins. */
|
|
2145
|
+
interface QuorumProof {
|
|
2146
|
+
/** sha256(canonical({ version, tenant_id, action_hash, environment,
|
|
2147
|
+
* issued_at, policy, sorted approval_hashes })). */
|
|
2148
|
+
quorum_hash: string;
|
|
2149
|
+
/** approval_id of every counted approval, in the order they were
|
|
2150
|
+
* submitted. */
|
|
2151
|
+
approval_ids: string[];
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
/**
|
|
2155
|
+
* Shared V1 API wire types used across multiple SDK modules.
|
|
2156
|
+
*
|
|
2157
|
+
* These reflect the canonical domain objects returned by the
|
|
2158
|
+
* atlasent-control-plane V1 API. Import from here to avoid circular
|
|
2159
|
+
* dependencies between proof.ts, overrides.ts, and types.ts.
|
|
2160
|
+
*/
|
|
2161
|
+
/**
|
|
2162
|
+
* Canonical Permit domain object as returned by the V1 API.
|
|
2163
|
+
*
|
|
2164
|
+
* All timestamps are ISO-8601 UTC strings.
|
|
2165
|
+
*
|
|
2166
|
+
* This is the richer V1 shape returned by `GET /v1/permits/:id` and
|
|
2167
|
+
* embedded in proof bundles. It differs from the legacy `PermitRecord`
|
|
2168
|
+
* in `types.ts` which uses snake_case and legacy fields from the
|
|
2169
|
+
* Supabase function surface.
|
|
2170
|
+
*/
|
|
2171
|
+
interface PermitV1 {
|
|
2172
|
+
id: string;
|
|
2173
|
+
orgId: string;
|
|
2174
|
+
/** Who the permit was issued for (actor or agent ID). */
|
|
2175
|
+
subject: string;
|
|
2176
|
+
/** What the permit grants (action/resource scope). */
|
|
2177
|
+
scope: string;
|
|
2178
|
+
status: "active" | "revoked" | "expired";
|
|
2179
|
+
/** The evaluation that produced this permit, or `null` for admin issuance. */
|
|
2180
|
+
evaluationId: string | null;
|
|
2181
|
+
/** Actor who issued the permit (system or admin). */
|
|
2182
|
+
issuedBy: string;
|
|
2183
|
+
/** Actor who revoked the permit, or `null`. */
|
|
2184
|
+
revokedBy: string | null;
|
|
2185
|
+
/** ISO-8601 issuance timestamp. */
|
|
2186
|
+
issuedAt: string;
|
|
2187
|
+
/** ISO-8601 revocation timestamp, or `null`. */
|
|
2188
|
+
revokedAt: string | null;
|
|
2189
|
+
/** ISO-8601 expiry timestamp, or `null` if the permit does not expire. */
|
|
2190
|
+
expiresAt: string | null;
|
|
2191
|
+
/** Arbitrary key/value metadata. `null` when none. */
|
|
2192
|
+
metadata: Record<string, unknown> | null;
|
|
2193
|
+
}
|
|
2194
|
+
/**
|
|
2195
|
+
* Canonical governance event as stored in the event log.
|
|
2196
|
+
*
|
|
2197
|
+
* `type` is a dotted domain-prefixed string, e.g. `override.created`,
|
|
2198
|
+
* `permit.revoked`, `evaluation.decided`.
|
|
2199
|
+
*
|
|
2200
|
+
* `actorId` is `null` for system-emitted events (expiry sweeps, etc.).
|
|
2201
|
+
*/
|
|
2202
|
+
interface GovernanceEvent {
|
|
2203
|
+
id: string;
|
|
2204
|
+
type: string;
|
|
2205
|
+
actorId: string | null;
|
|
2206
|
+
orgId: string;
|
|
2207
|
+
/** ISO-8601 timestamp. */
|
|
2208
|
+
at: string;
|
|
2209
|
+
/** Event-type-specific payload. Optional — shape varies by `type`. */
|
|
2210
|
+
payload?: Record<string, unknown>;
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
/**
|
|
2214
|
+
* Override types — wire shapes for `/v1/overrides`.
|
|
2215
|
+
*
|
|
2216
|
+
* Overrides allow an authorized actor to bypass a deny decision for a
|
|
2217
|
+
* specific evaluation. They must be approved before they take effect
|
|
2218
|
+
* and can be revoked at any time.
|
|
2219
|
+
*
|
|
2220
|
+
* Mirrors `api/src/schemas/overrides.ts` in atlasent-control-plane.
|
|
2221
|
+
*/
|
|
2222
|
+
/**
|
|
2223
|
+
* Lifecycle status of an override request.
|
|
2224
|
+
*
|
|
2225
|
+
* - `pending` — created, waiting for approval
|
|
2226
|
+
* - `approved` — approved and active; the evaluation's deny is lifted
|
|
2227
|
+
* - `revoked` — manually revoked
|
|
2228
|
+
* - `expired` — TTL elapsed before revocation
|
|
2229
|
+
*/
|
|
2230
|
+
type OverrideStatus = "pending" | "approved" | "revoked" | "expired";
|
|
2231
|
+
/**
|
|
2232
|
+
* The event types that can appear on an override's event log.
|
|
2233
|
+
*/
|
|
2234
|
+
type OverrideEventType = "created" | "approved" | "revoked";
|
|
2235
|
+
/**
|
|
2236
|
+
* Canonical Override domain object returned by the API.
|
|
2237
|
+
*
|
|
2238
|
+
* All timestamps are ISO-8601 UTC strings. Nullable fields are `null`
|
|
2239
|
+
* rather than omitted so wire shapes are stable.
|
|
2240
|
+
*/
|
|
2241
|
+
interface OverrideV1 {
|
|
2242
|
+
id: string;
|
|
2243
|
+
orgId: string;
|
|
2244
|
+
/** The evaluation ID this override applies to. */
|
|
2245
|
+
evaluationId: string;
|
|
2246
|
+
/** Human-readable justification provided at creation time. */
|
|
2247
|
+
reason: string;
|
|
2248
|
+
status: OverrideStatus;
|
|
2249
|
+
/** Actor who requested the override. */
|
|
2250
|
+
requestedBy: string;
|
|
2251
|
+
/** Actor who approved the override, or `null` if not yet approved. */
|
|
2252
|
+
approvedBy: string | null;
|
|
2253
|
+
/** Actor who revoked the override, or `null` if not revoked. */
|
|
2254
|
+
revokedBy: string | null;
|
|
2255
|
+
/** ISO-8601 creation timestamp. */
|
|
2256
|
+
createdAt: string;
|
|
2257
|
+
/** ISO-8601 approval timestamp, or `null`. */
|
|
2258
|
+
approvedAt: string | null;
|
|
2259
|
+
/** ISO-8601 revocation timestamp, or `null`. */
|
|
2260
|
+
revokedAt: string | null;
|
|
2261
|
+
/** ISO-8601 expiry timestamp, or `null` if no TTL was set. */
|
|
2262
|
+
expiresAt: string | null;
|
|
2263
|
+
/** Arbitrary key/value metadata attached at creation. `null` when none. */
|
|
2264
|
+
metadata: Record<string, unknown> | null;
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Paginated list of overrides.
|
|
2268
|
+
*/
|
|
2269
|
+
interface OverrideListResponse {
|
|
2270
|
+
items: OverrideV1[];
|
|
2271
|
+
/** Opaque cursor for the next page. `null` when there are no more results. */
|
|
2272
|
+
nextCursor: string | null;
|
|
2273
|
+
}
|
|
2274
|
+
/**
|
|
2275
|
+
* Input for `POST /v1/overrides` — request a new override.
|
|
2276
|
+
*/
|
|
2277
|
+
interface CreateOverrideRequest {
|
|
2278
|
+
/** Human-readable justification. Required; max 2000 characters. */
|
|
2279
|
+
reason: string;
|
|
2280
|
+
/** The evaluation ID to override. */
|
|
2281
|
+
evaluationId: string;
|
|
2282
|
+
/** Lifetime in seconds. Defaults to 3600. Max 604800 (7 days). */
|
|
2283
|
+
ttlSeconds?: number;
|
|
2284
|
+
/** Arbitrary metadata to attach to the override record. */
|
|
2285
|
+
metadata?: Record<string, unknown>;
|
|
2286
|
+
}
|
|
2287
|
+
/**
|
|
2288
|
+
* Audit event appended to an override's event log on every state mutation.
|
|
2289
|
+
*/
|
|
2290
|
+
interface OverrideEvent {
|
|
2291
|
+
id: string;
|
|
2292
|
+
overrideId: string;
|
|
2293
|
+
orgId: string;
|
|
2294
|
+
/** Actor who caused this event. */
|
|
2295
|
+
actorId: string;
|
|
2296
|
+
type: OverrideEventType;
|
|
2297
|
+
/** ISO-8601 timestamp. */
|
|
2298
|
+
at: string;
|
|
2299
|
+
/** Event-specific payload. `null` when none. */
|
|
2300
|
+
payload: Record<string, unknown> | null;
|
|
2301
|
+
}
|
|
2302
|
+
/**
|
|
2303
|
+
* Response for `GET /v1/overrides/:id/events`.
|
|
2304
|
+
*/
|
|
2305
|
+
interface OverrideEventsResponse {
|
|
2306
|
+
items: OverrideEvent[];
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
/**
|
|
2310
|
+
* Proof bundle types — wire shape for `GET /v1/proof/:evaluationId`.
|
|
2311
|
+
*
|
|
2312
|
+
* The proof endpoint reconstructs an evaluation from the governance event
|
|
2313
|
+
* log and returns it along with the associated permits, overrides, and events
|
|
2314
|
+
* as a signed bundle. Consumers use this for tamper-evident audit trails.
|
|
2315
|
+
*
|
|
2316
|
+
* Mirrors `api/src/schemas/proof.ts` in atlasent-control-plane.
|
|
2317
|
+
*/
|
|
2318
|
+
|
|
2319
|
+
/**
|
|
2320
|
+
* Reconstructed summary of the evaluation that produced the proof.
|
|
2321
|
+
*
|
|
2322
|
+
* Drawn from the `evaluation.decided` governance event. Timestamps
|
|
2323
|
+
* are ISO-8601 UTC strings.
|
|
2324
|
+
*/
|
|
2325
|
+
interface ProofEvaluationSummary {
|
|
2326
|
+
evaluationId: string;
|
|
2327
|
+
/** Policy decision: `"allow"` or `"deny"`. */
|
|
2328
|
+
decision: "allow" | "deny";
|
|
2329
|
+
/** Human-readable reasons emitted by the policy engine. */
|
|
2330
|
+
reasons: string[];
|
|
2331
|
+
/** The action that was evaluated. `null` when not stored on the event. */
|
|
2332
|
+
action: string | null;
|
|
2333
|
+
/** Resource type. `null` when not stored on the event. */
|
|
2334
|
+
resourceType: string | null;
|
|
2335
|
+
/** Resource identifier. `null` when not stored on the event. */
|
|
2336
|
+
resourceId: string | null;
|
|
2337
|
+
/** ISO-8601 timestamp of when the decision was made. */
|
|
2338
|
+
decidedAt: string;
|
|
2339
|
+
/** Actor who triggered the evaluation. `null` for system-initiated evaluations. */
|
|
2340
|
+
decidedBy: string | null;
|
|
2341
|
+
}
|
|
2342
|
+
/**
|
|
2343
|
+
* The proof payload — the data that is signed.
|
|
2344
|
+
*
|
|
2345
|
+
* Contains the reconstructed evaluation summary, the permits and overrides
|
|
2346
|
+
* that were active at decision time, and the full governance event trail.
|
|
2347
|
+
*/
|
|
2348
|
+
interface ProofPayload {
|
|
2349
|
+
evaluation: ProofEvaluationSummary;
|
|
2350
|
+
permits: PermitV1[];
|
|
2351
|
+
overrides: OverrideV1[];
|
|
2352
|
+
events: GovernanceEvent[];
|
|
2353
|
+
}
|
|
2354
|
+
/**
|
|
2355
|
+
* Full proof bundle returned by `GET /v1/proof/:evaluationId`.
|
|
2356
|
+
*
|
|
2357
|
+
* **Signature semantics:**
|
|
2358
|
+
*
|
|
2359
|
+
* When `PROOF_SIGNING_SECRET` is configured on the server:
|
|
2360
|
+
* - `algorithm === "hmac-sha256"`
|
|
2361
|
+
* - `signature` is the hex-encoded HMAC-SHA256 over
|
|
2362
|
+
* `evaluationId + "\n" + issuedAt + "\n" + JSON.stringify(payload)`
|
|
2363
|
+
*
|
|
2364
|
+
* When `PROOF_SIGNING_SECRET` is absent:
|
|
2365
|
+
* - `algorithm === "none"`, `signature === null`
|
|
2366
|
+
*
|
|
2367
|
+
* Consumers MUST reject proofs where `algorithm === "none"` in any
|
|
2368
|
+
* context where tamper-evidence is required.
|
|
2369
|
+
*/
|
|
2370
|
+
interface ProofResponse {
|
|
2371
|
+
evaluationId: string;
|
|
2372
|
+
/** Signing algorithm used. `"none"` means unsigned. */
|
|
2373
|
+
algorithm: "none" | "hmac-sha256";
|
|
2374
|
+
/** Hex-encoded HMAC-SHA256 signature, or `null` when unsigned. */
|
|
2375
|
+
signature: string | null;
|
|
2376
|
+
payload: ProofPayload;
|
|
2377
|
+
/** ISO-8601 timestamp of when the proof was issued. */
|
|
2378
|
+
issuedAt: string;
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
/**
|
|
2382
|
+
* Financial Action Model — canonical types for financial execution authority.
|
|
2383
|
+
*
|
|
2384
|
+
* Defines the core vocabulary for all financial actions governed by
|
|
2385
|
+
* AtlaSent's economic governance layer. Every consequential financial
|
|
2386
|
+
* operation must be classified here before execution authorization.
|
|
2387
|
+
*
|
|
2388
|
+
* Wire-stable as `financial_action.v1`.
|
|
2389
|
+
*/
|
|
2390
|
+
/** ISO 4217 currency code. */
|
|
2391
|
+
type CurrencyCode = "USD" | "EUR" | "GBP" | "JPY" | "CAD" | "AUD" | "CHF" | "CNY" | "SEK" | "NZD" | string;
|
|
2392
|
+
/**
|
|
2393
|
+
* Risk tier for a financial action.
|
|
2394
|
+
*
|
|
2395
|
+
* - low: < $1,000 — single-approver sufficient
|
|
2396
|
+
* - medium: $1,000–$50,000 — dual-control typically required
|
|
2397
|
+
* - high: $50,000–$1,000,000 — CFO-level required
|
|
2398
|
+
* - critical: > $1,000,000 or irreversible — board-level or emergency protocol
|
|
2399
|
+
*/
|
|
2400
|
+
type FinancialRiskTier = "low" | "medium" | "high" | "critical";
|
|
2401
|
+
/** How accountability is distributed across parties for a financial action. */
|
|
2402
|
+
type LiabilityClassification = "individual" | "shared" | "delegated" | "supervisory" | "emergency_override";
|
|
2403
|
+
/** Canonical set of financial action types. */
|
|
2404
|
+
type FinancialActionType = "refund" | "payment_release" | "invoice_approval" | "payroll_execution" | "procurement_approval" | "wire_transfer" | "trading_execution" | "budget_override" | "spending_authorization" | "vendor_payment" | "subscription_cancellation" | "credit_issuance" | "fee_waiver" | "chargeback" | "contract_commitment" | string;
|
|
2405
|
+
/**
|
|
2406
|
+
* Canonical definition of a financial action class.
|
|
2407
|
+
*
|
|
2408
|
+
* Stored in `financial_action_classes`. Drives quorum policy,
|
|
2409
|
+
* liability classification, and risk tier assignment.
|
|
2410
|
+
*/
|
|
2411
|
+
interface FinancialActionClass {
|
|
2412
|
+
/** Stable identifier (e.g. "wire_transfer.domestic"). */
|
|
2413
|
+
readonly action_class_id: string;
|
|
2414
|
+
readonly name: string;
|
|
2415
|
+
readonly action_type: FinancialActionType;
|
|
2416
|
+
readonly risk_tier: FinancialRiskTier;
|
|
2417
|
+
/** Minimum number of approvals before execution is permitted. */
|
|
2418
|
+
readonly required_approvals: number;
|
|
2419
|
+
readonly liability_classification: LiabilityClassification;
|
|
2420
|
+
/** Whether this action is reversible post-execution. */
|
|
2421
|
+
readonly reversible: boolean;
|
|
2422
|
+
/** Maximum allowed execution value for autonomous agents (null = no ceiling). */
|
|
2423
|
+
readonly autonomous_ceiling: number | null;
|
|
2424
|
+
readonly ceiling_currency: CurrencyCode | null;
|
|
2425
|
+
readonly created_at: string;
|
|
2426
|
+
readonly description?: string;
|
|
2427
|
+
}
|
|
2428
|
+
/** Status of a financial execution record. */
|
|
2429
|
+
type FinancialExecutionStatus = "pending_approval" | "approved" | "executing" | "completed" | "failed" | "reversed" | "disputed" | "frozen";
|
|
2430
|
+
/**
|
|
2431
|
+
* Immutable record of a financial action execution.
|
|
2432
|
+
*
|
|
2433
|
+
* Written at authorization time. Stored in `financial_execution_records`.
|
|
2434
|
+
*/
|
|
2435
|
+
interface FinancialExecutionRecord {
|
|
2436
|
+
readonly execution_id: string;
|
|
2437
|
+
readonly action_class_id: string;
|
|
2438
|
+
readonly org_id: string;
|
|
2439
|
+
readonly action_value: number;
|
|
2440
|
+
readonly currency: CurrencyCode;
|
|
2441
|
+
readonly risk_tier: FinancialRiskTier;
|
|
2442
|
+
readonly liability_classification: LiabilityClassification;
|
|
2443
|
+
readonly initiator_id: string;
|
|
2444
|
+
readonly executor_id: string;
|
|
2445
|
+
/** Ordered list of approver IDs. */
|
|
2446
|
+
readonly approver_ids: readonly string[];
|
|
2447
|
+
/** AtlaSent permit IDs — one per approval stage. */
|
|
2448
|
+
readonly permit_ids: readonly string[];
|
|
2449
|
+
readonly override_applied: boolean;
|
|
2450
|
+
readonly override_id: string | null;
|
|
2451
|
+
readonly status: FinancialExecutionStatus;
|
|
2452
|
+
readonly authorized_at: string;
|
|
2453
|
+
readonly executed_at: string | null;
|
|
2454
|
+
/** Hash-chained audit trail entry. */
|
|
2455
|
+
readonly audit_hash: string;
|
|
2456
|
+
readonly context: Record<string, unknown>;
|
|
2457
|
+
}
|
|
2458
|
+
/** Threshold configuration for risk-tier escalation. */
|
|
2459
|
+
interface RiskTierThreshold {
|
|
2460
|
+
readonly tier: FinancialRiskTier;
|
|
2461
|
+
/** Inclusive lower bound in the reference currency. */
|
|
2462
|
+
readonly lower_bound: number;
|
|
2463
|
+
/** Exclusive upper bound; null means unbounded. */
|
|
2464
|
+
readonly upper_bound: number | null;
|
|
2465
|
+
readonly reference_currency: CurrencyCode;
|
|
2466
|
+
}
|
|
2467
|
+
/** Default risk tier thresholds (USD-denominated). */
|
|
2468
|
+
declare const DEFAULT_RISK_TIER_THRESHOLDS: readonly RiskTierThreshold[];
|
|
2469
|
+
/**
|
|
2470
|
+
* Classify a financial action's risk tier based on its value.
|
|
2471
|
+
*/
|
|
2472
|
+
declare function classifyRiskTier(value: number, thresholds?: readonly RiskTierThreshold[]): FinancialRiskTier;
|
|
2473
|
+
/**
|
|
2474
|
+
* Return true when the action value is within the autonomous execution ceiling.
|
|
2475
|
+
* A null ceiling means no ceiling is configured (always within bounds).
|
|
2476
|
+
*/
|
|
2477
|
+
declare function withinAutonomousCeiling(actionValue: number, ceiling: number | null): boolean;
|
|
2478
|
+
|
|
2479
|
+
/**
|
|
2480
|
+
* Liability Attribution Engine.
|
|
2481
|
+
*
|
|
2482
|
+
* Tracks and computes liability across the full chain of parties involved
|
|
2483
|
+
* in a financial action: who authorized, delegated, executed, overrode,
|
|
2484
|
+
* and approved exceptions.
|
|
2485
|
+
*
|
|
2486
|
+
* Supports shared, delegated, supervisory, and emergency-override liability
|
|
2487
|
+
* regimes. Every attribution record is immutable once written.
|
|
2488
|
+
*
|
|
2489
|
+
* Wire-stable as `liability_attribution.v1`.
|
|
2490
|
+
*/
|
|
2491
|
+
|
|
2492
|
+
/** The role a party played in a financial action. */
|
|
2493
|
+
type LiabilityPartyRole = "authorizer" | "delegator" | "delegate" | "executor" | "approver" | "override_actor" | "supervisor" | "exception_approver";
|
|
2494
|
+
/** A single party in the liability chain. */
|
|
2495
|
+
interface LiabilityParty {
|
|
2496
|
+
readonly party_id: string;
|
|
2497
|
+
readonly party_label: string;
|
|
2498
|
+
readonly party_type: "human" | "agent" | "system";
|
|
2499
|
+
readonly role: LiabilityPartyRole;
|
|
2500
|
+
/** Fractional liability weight (0–1); all parties in chain sum to 1. */
|
|
2501
|
+
readonly liability_weight: number;
|
|
2502
|
+
readonly acted_at: string;
|
|
2503
|
+
readonly permit_id: string | null;
|
|
2504
|
+
}
|
|
2505
|
+
/**
|
|
2506
|
+
* Immutable liability attribution record for a financial execution.
|
|
2507
|
+
*
|
|
2508
|
+
* Stored in `liability_attribution_records`. One record per execution.
|
|
2509
|
+
*/
|
|
2510
|
+
interface LiabilityAttributionRecord {
|
|
2511
|
+
readonly attribution_id: string;
|
|
2512
|
+
readonly execution_id: string;
|
|
2513
|
+
readonly org_id: string;
|
|
2514
|
+
readonly classification: LiabilityClassification;
|
|
2515
|
+
readonly risk_tier: FinancialRiskTier;
|
|
2516
|
+
/** Ordered liability chain. First party = primary. */
|
|
2517
|
+
readonly liability_chain: readonly LiabilityParty[];
|
|
2518
|
+
readonly delegation_present: boolean;
|
|
2519
|
+
readonly supervisory_present: boolean;
|
|
2520
|
+
readonly emergency_override: boolean;
|
|
2521
|
+
readonly override_justification: string | null;
|
|
2522
|
+
readonly created_at: string;
|
|
2523
|
+
/** SHA-256 hash of the canonical chain for integrity verification. */
|
|
2524
|
+
readonly chain_hash: string;
|
|
2525
|
+
}
|
|
2526
|
+
/** Input required to build a liability attribution record. */
|
|
2527
|
+
interface LiabilityAttributionInput {
|
|
2528
|
+
readonly execution_id: string;
|
|
2529
|
+
readonly org_id: string;
|
|
2530
|
+
readonly classification: LiabilityClassification;
|
|
2531
|
+
readonly risk_tier: FinancialRiskTier;
|
|
2532
|
+
readonly authorizer: Omit<LiabilityParty, "role" | "liability_weight">;
|
|
2533
|
+
readonly executor: Omit<LiabilityParty, "role" | "liability_weight">;
|
|
2534
|
+
readonly approvers: readonly Omit<LiabilityParty, "role" | "liability_weight">[];
|
|
2535
|
+
readonly delegations?: readonly {
|
|
2536
|
+
readonly delegator_id: string;
|
|
2537
|
+
readonly delegate_id: string;
|
|
2538
|
+
readonly delegator_label: string;
|
|
2539
|
+
readonly delegate_label: string;
|
|
2540
|
+
readonly delegator_type: "human" | "agent" | "system";
|
|
2541
|
+
readonly delegate_type: "human" | "agent" | "system";
|
|
2542
|
+
readonly permit_id: string | null;
|
|
2543
|
+
readonly acted_at: string;
|
|
2544
|
+
}[];
|
|
2545
|
+
readonly supervisors?: readonly Omit<LiabilityParty, "role" | "liability_weight">[];
|
|
2546
|
+
readonly override?: {
|
|
2547
|
+
readonly actor_id: string;
|
|
2548
|
+
readonly actor_label: string;
|
|
2549
|
+
readonly actor_type: "human" | "agent" | "system";
|
|
2550
|
+
readonly justification: string;
|
|
2551
|
+
readonly permit_id: string | null;
|
|
2552
|
+
readonly acted_at: string;
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
/** Weight distribution strategy. */
|
|
2556
|
+
type WeightDistribution = "equal" | "role_weighted";
|
|
2557
|
+
/**
|
|
2558
|
+
* Compute liability weights for all parties in a chain.
|
|
2559
|
+
* Normalizes weights to sum to 1.0.
|
|
2560
|
+
*/
|
|
2561
|
+
declare function computeLiabilityWeights(parties: readonly {
|
|
2562
|
+
role: LiabilityPartyRole;
|
|
2563
|
+
}[], distribution?: WeightDistribution): number[];
|
|
2564
|
+
/**
|
|
2565
|
+
* Build a liability chain from attribution input.
|
|
2566
|
+
* Assigns roles and computes normalized weights for each party.
|
|
2567
|
+
*/
|
|
2568
|
+
declare function buildLiabilityChain(input: LiabilityAttributionInput, distribution?: WeightDistribution): LiabilityParty[];
|
|
2569
|
+
/**
|
|
2570
|
+
* Find all parties bearing primary liability (weight >= threshold).
|
|
2571
|
+
* Used in dispute workflows and regulatory reporting.
|
|
2572
|
+
*/
|
|
2573
|
+
declare function findPrimaryLiabilityParties(chain: readonly LiabilityParty[], threshold?: number): LiabilityParty[];
|
|
2574
|
+
/** Result of validating a liability chain. */
|
|
2575
|
+
interface LiabilityChainValidation {
|
|
2576
|
+
readonly valid: boolean;
|
|
2577
|
+
readonly errors: readonly string[];
|
|
2578
|
+
}
|
|
2579
|
+
/**
|
|
2580
|
+
* Validate structural correctness of a liability chain:
|
|
2581
|
+
* - At least one party present
|
|
2582
|
+
* - Weights sum to ~1.0
|
|
2583
|
+
* - No duplicate party_id+role pairs
|
|
2584
|
+
* - override_actor present when hasEmergencyOverride is true
|
|
2585
|
+
*/
|
|
2586
|
+
declare function validateLiabilityChain(chain: readonly LiabilityParty[], hasEmergencyOverride: boolean): LiabilityChainValidation;
|
|
2587
|
+
|
|
2588
|
+
/**
|
|
2589
|
+
* Economic Risk Engine.
|
|
2590
|
+
*
|
|
2591
|
+
* Computes financial exposure, approval concentration risk, override
|
|
2592
|
+
* frequency risk, budgetary drift, and execution anomaly risk for an
|
|
2593
|
+
* organization's financial governance posture.
|
|
2594
|
+
*
|
|
2595
|
+
* All computation is pure (no I/O). Inputs are derived from the
|
|
2596
|
+
* financial_execution_records and liability_attribution_records tables.
|
|
2597
|
+
*
|
|
2598
|
+
* Wire-stable as `economic_risk.v1`.
|
|
2599
|
+
*/
|
|
2600
|
+
|
|
2601
|
+
/** Aggregate financial risk score for an organization or scope. */
|
|
2602
|
+
interface FinancialRiskScore {
|
|
2603
|
+
readonly scope_id: string;
|
|
2604
|
+
/** Overall risk score (0–100; higher = riskier). */
|
|
2605
|
+
readonly overall_score: number;
|
|
2606
|
+
readonly exposure_score: number;
|
|
2607
|
+
readonly concentration_score: number;
|
|
2608
|
+
readonly override_score: number;
|
|
2609
|
+
readonly drift_score: number;
|
|
2610
|
+
readonly anomaly_score: number;
|
|
2611
|
+
readonly implied_tier: FinancialRiskTier;
|
|
2612
|
+
readonly computed_at: string;
|
|
2613
|
+
readonly factors: readonly RiskFactor[];
|
|
2614
|
+
}
|
|
2615
|
+
/** A single contributing risk factor. */
|
|
2616
|
+
interface RiskFactor {
|
|
2617
|
+
readonly name: string;
|
|
2618
|
+
readonly score: number;
|
|
2619
|
+
readonly weight: number;
|
|
2620
|
+
readonly description: string;
|
|
2621
|
+
readonly evidence?: readonly string[];
|
|
2622
|
+
}
|
|
2623
|
+
/** Alert raised when approval authority is too concentrated. */
|
|
2624
|
+
interface ConcentrationAlert {
|
|
2625
|
+
readonly approver_id: string;
|
|
2626
|
+
/** Percentage of total approvals (0–100). */
|
|
2627
|
+
readonly approval_share_pct: number;
|
|
2628
|
+
readonly total_value_approved: number;
|
|
2629
|
+
readonly approval_count: number;
|
|
2630
|
+
readonly severity: "warn" | "critical";
|
|
2631
|
+
readonly window_start: string;
|
|
2632
|
+
readonly window_end: string;
|
|
2633
|
+
}
|
|
2634
|
+
/** Per-approver breakdown within a concentration analysis. */
|
|
2635
|
+
interface ApproverBreakdown {
|
|
2636
|
+
readonly approver_id: string;
|
|
2637
|
+
readonly approval_count: number;
|
|
2638
|
+
readonly total_value: number;
|
|
2639
|
+
/** Share as a percentage (0–100). */
|
|
2640
|
+
readonly share_pct: number;
|
|
2641
|
+
}
|
|
2642
|
+
/** Result of approval concentration analysis. */
|
|
2643
|
+
interface ApprovalConcentrationAnalysis {
|
|
2644
|
+
readonly scope_id: string;
|
|
2645
|
+
readonly analysis_window_days: number;
|
|
2646
|
+
readonly total_approvals: number;
|
|
2647
|
+
readonly total_value: number;
|
|
2648
|
+
readonly approver_breakdown: readonly ApproverBreakdown[];
|
|
2649
|
+
readonly alerts: readonly ConcentrationAlert[];
|
|
2650
|
+
/** Herfindahl-Hirschman Index (0–10000). */
|
|
2651
|
+
readonly concentration_hhi: number;
|
|
2652
|
+
readonly computed_at: string;
|
|
2653
|
+
}
|
|
2654
|
+
/** Budgetary drift analysis for a scope/period. */
|
|
2655
|
+
interface BudgetaryDriftAnalysis {
|
|
2656
|
+
readonly scope_id: string;
|
|
2657
|
+
readonly department_id: string | null;
|
|
2658
|
+
readonly period_start: string;
|
|
2659
|
+
readonly period_end: string;
|
|
2660
|
+
readonly budgeted_amount: number;
|
|
2661
|
+
readonly actual_amount: number;
|
|
2662
|
+
readonly variance_amount: number;
|
|
2663
|
+
readonly variance_pct: number;
|
|
2664
|
+
readonly drift_detected: boolean;
|
|
2665
|
+
readonly drift_severity: "none" | "minor" | "moderate" | "severe";
|
|
2666
|
+
readonly override_contribution_pct: number;
|
|
2667
|
+
readonly unauthorized_escalation_detected: boolean;
|
|
2668
|
+
}
|
|
2669
|
+
/** A single execution anomaly signal. */
|
|
2670
|
+
interface ExecutionAnomaly {
|
|
2671
|
+
readonly anomaly_id: string;
|
|
2672
|
+
readonly execution_id: string;
|
|
2673
|
+
readonly anomaly_type: AnomalyType;
|
|
2674
|
+
readonly description: string;
|
|
2675
|
+
readonly severity: "low" | "medium" | "high";
|
|
2676
|
+
readonly detected_at: string;
|
|
2677
|
+
readonly evidence: Record<string, unknown>;
|
|
2678
|
+
}
|
|
2679
|
+
/** Known anomaly types detected by the risk engine. */
|
|
2680
|
+
type AnomalyType = "unusual_amount" | "unusual_frequency" | "off_hours_execution" | "rapid_sequential" | "self_approval" | "jurisdiction_mismatch" | "dormant_approver" | "velocity_spike" | string;
|
|
2681
|
+
/**
|
|
2682
|
+
* Compute the overall financial risk score from sub-scores.
|
|
2683
|
+
* Returns a value in [0, 100].
|
|
2684
|
+
*/
|
|
2685
|
+
declare function computeOverallRiskScore(subScores: {
|
|
2686
|
+
exposure: number;
|
|
2687
|
+
concentration: number;
|
|
2688
|
+
override: number;
|
|
2689
|
+
drift: number;
|
|
2690
|
+
anomaly: number;
|
|
2691
|
+
}): number;
|
|
2692
|
+
/**
|
|
2693
|
+
* Infer a risk tier from an overall score.
|
|
2694
|
+
* 0–25: low | 26–55: medium | 56–80: high | 81–100: critical
|
|
2695
|
+
*/
|
|
2696
|
+
declare function scoreToRiskTier(score: number): FinancialRiskTier;
|
|
2697
|
+
/**
|
|
2698
|
+
* Compute the Herfindahl-Hirschman Index from a list of shares (0–100 each).
|
|
2699
|
+
* HHI > 2500 indicates high concentration.
|
|
2700
|
+
*/
|
|
2701
|
+
declare function computeHHI(shares: readonly number[]): number;
|
|
2702
|
+
/** Map HHI (0–10000) to a concentration score (0–100). */
|
|
2703
|
+
declare function hhiToConcentrationScore(hhi: number): number;
|
|
2704
|
+
/**
|
|
2705
|
+
* Compute an exposure score (0–100) from execution records.
|
|
2706
|
+
* Total active-state value as a fraction of a reference ceiling.
|
|
2707
|
+
*/
|
|
2708
|
+
declare function computeExposureScore(records: readonly Pick<FinancialExecutionRecord, "action_value" | "status" | "risk_tier">[], exposureCeilingUSD?: number): number;
|
|
2709
|
+
/**
|
|
2710
|
+
* Compute an override frequency score (0–100).
|
|
2711
|
+
* More than 10% override rate → score = 100.
|
|
2712
|
+
*/
|
|
2713
|
+
declare function computeOverrideScore(totalExecutions: number, overriddenExecutions: number): number;
|
|
2714
|
+
/**
|
|
2715
|
+
* Detect self-approval: initiator and approver are the same party.
|
|
2716
|
+
*/
|
|
2717
|
+
declare function detectSelfApproval(initiatorId: string, approverIds: readonly string[]): boolean;
|
|
2718
|
+
/** Compute an approval risk score from concentration analysis. */
|
|
2719
|
+
declare function computeApprovalRiskScore(analysis: ApprovalConcentrationAnalysis): number;
|
|
2720
|
+
|
|
2721
|
+
/**
|
|
2722
|
+
* Financial Quorum — extends the AtlaSent approval quorum model with
|
|
2723
|
+
* monetary thresholds, dynamic escalation, and emergency freeze support.
|
|
2724
|
+
*
|
|
2725
|
+
* Builds on the base QuorumPolicy in approvalQuorum.ts. Every financial
|
|
2726
|
+
* quorum check MUST first satisfy base quorum requirements before
|
|
2727
|
+
* financial-layer policy is evaluated.
|
|
2728
|
+
*
|
|
2729
|
+
* Wire-stable as `financial_quorum.v1`.
|
|
2730
|
+
*/
|
|
2731
|
+
|
|
2732
|
+
/** A financial role requirement with optional monetary and tier filters. */
|
|
2733
|
+
interface FinancialRoleRequirement {
|
|
2734
|
+
readonly role: string;
|
|
2735
|
+
readonly min: number;
|
|
2736
|
+
/** Only apply this requirement when action value >= this amount. */
|
|
2737
|
+
readonly applies_above?: number;
|
|
2738
|
+
/** Only apply when the action's risk_tier is in this set. */
|
|
2739
|
+
readonly applies_to_tiers?: readonly FinancialRiskTier[];
|
|
2740
|
+
}
|
|
2741
|
+
/** Amount-based threshold that triggers additional quorum requirements. */
|
|
2742
|
+
interface AmountThreshold {
|
|
2743
|
+
readonly value: number;
|
|
2744
|
+
readonly currency: CurrencyCode;
|
|
2745
|
+
readonly additional_approvals: number;
|
|
2746
|
+
readonly additional_roles: readonly FinancialRoleRequirement[];
|
|
2747
|
+
readonly senior_review_required: boolean;
|
|
2748
|
+
}
|
|
2749
|
+
/**
|
|
2750
|
+
* Financial quorum policy.
|
|
2751
|
+
*
|
|
2752
|
+
* Extends the base QuorumPolicy with amount thresholds, financial role
|
|
2753
|
+
* requirements, regulator approval thresholds, and emergency freeze.
|
|
2754
|
+
*/
|
|
2755
|
+
interface FinancialQuorumPolicy extends QuorumPolicy {
|
|
2756
|
+
readonly financial_role_requirements: readonly FinancialRoleRequirement[];
|
|
2757
|
+
readonly amount_thresholds: readonly AmountThreshold[];
|
|
2758
|
+
readonly reference_currency: CurrencyCode;
|
|
2759
|
+
readonly emergency_freeze_active: boolean;
|
|
2760
|
+
/** Regulator approval required above this value (null = not required). */
|
|
2761
|
+
readonly regulator_approval_threshold: number | null;
|
|
2762
|
+
/** Customer + vendor dual-release required above this value. */
|
|
2763
|
+
readonly dual_release_threshold: number | null;
|
|
2764
|
+
}
|
|
2765
|
+
/** Emergency freeze record — applied org-wide or per scope. */
|
|
2766
|
+
interface EmergencyFreeze {
|
|
2767
|
+
readonly freeze_id: string;
|
|
2768
|
+
readonly scope_id: string;
|
|
2769
|
+
readonly scope_type: "org" | "department" | "action_class";
|
|
2770
|
+
readonly triggered_by: string;
|
|
2771
|
+
readonly reason: string;
|
|
2772
|
+
readonly triggered_at: string;
|
|
2773
|
+
readonly expires_at: string | null;
|
|
2774
|
+
readonly lifted: boolean;
|
|
2775
|
+
readonly lifted_at: string | null;
|
|
2776
|
+
readonly lifted_by: string | null;
|
|
2777
|
+
}
|
|
2778
|
+
/** Result of evaluating a financial quorum. */
|
|
2779
|
+
interface FinancialQuorumResult {
|
|
2780
|
+
readonly passed: boolean;
|
|
2781
|
+
readonly base_quorum_passed: boolean;
|
|
2782
|
+
readonly amount_threshold_satisfied: boolean;
|
|
2783
|
+
readonly financial_roles_satisfied: boolean;
|
|
2784
|
+
readonly regulator_approval_missing: boolean;
|
|
2785
|
+
readonly blocked_by_freeze: boolean;
|
|
2786
|
+
readonly base_quorum_proof: QuorumProof | null;
|
|
2787
|
+
readonly denial_reason: string | null;
|
|
2788
|
+
readonly unmet_requirements: readonly string[];
|
|
2789
|
+
}
|
|
2790
|
+
/** Input to financial quorum evaluation. */
|
|
2791
|
+
interface FinancialQuorumInput {
|
|
2792
|
+
readonly policy: FinancialQuorumPolicy;
|
|
2793
|
+
readonly action_value: number;
|
|
2794
|
+
readonly risk_tier: FinancialRiskTier;
|
|
2795
|
+
/** Roles present in the approval set (role → count). */
|
|
2796
|
+
readonly present_roles: Record<string, number>;
|
|
2797
|
+
readonly approval_count: number;
|
|
2798
|
+
readonly regulator_approval_present: boolean;
|
|
2799
|
+
readonly base_quorum_proof: QuorumProof | null;
|
|
2800
|
+
readonly active_freezes: readonly EmergencyFreeze[];
|
|
2801
|
+
}
|
|
2802
|
+
/**
|
|
2803
|
+
* Evaluate a financial quorum policy.
|
|
2804
|
+
*
|
|
2805
|
+
* Checks in order: emergency freeze → base count → amount thresholds
|
|
2806
|
+
* → financial roles → regulator approval.
|
|
2807
|
+
*/
|
|
2808
|
+
declare function evaluateFinancialQuorum(input: FinancialQuorumInput): FinancialQuorumResult;
|
|
2809
|
+
/**
|
|
2810
|
+
* Determine the escalated minimum approval count for a given action value.
|
|
2811
|
+
* Returns base count plus the largest additional_approvals from matching thresholds.
|
|
2812
|
+
*/
|
|
2813
|
+
declare function computeEscalatedApprovalCount(baseCount: number, actionValue: number, thresholds: readonly AmountThreshold[]): number;
|
|
2814
|
+
|
|
2815
|
+
/**
|
|
2816
|
+
* Budgetary Governance — policy and constraint infrastructure for
|
|
2817
|
+
* organizational financial limits.
|
|
2818
|
+
*
|
|
2819
|
+
* Prevents budget overruns, unauthorized escalations, and hidden approvals
|
|
2820
|
+
* by enforcing declared spending constraints before financial actions
|
|
2821
|
+
* are authorized.
|
|
2822
|
+
*
|
|
2823
|
+
* Wire-stable as `budget_governance.v1`.
|
|
2824
|
+
*/
|
|
2825
|
+
|
|
2826
|
+
/** Scope a budget limit applies to. */
|
|
2827
|
+
type BudgetScope = "org" | "department" | "team" | "environment" | "action_class" | "project" | "time_bounded";
|
|
2828
|
+
/** A declared budget limit for a scope. */
|
|
2829
|
+
interface BudgetLimit {
|
|
2830
|
+
readonly limit_id: string;
|
|
2831
|
+
readonly org_id: string;
|
|
2832
|
+
readonly scope_type: BudgetScope;
|
|
2833
|
+
readonly scope_id: string;
|
|
2834
|
+
readonly limit_amount: number;
|
|
2835
|
+
readonly currency: CurrencyCode;
|
|
2836
|
+
/** Hard limits block execution; soft limits warn only. */
|
|
2837
|
+
readonly enforcement: "hard" | "soft";
|
|
2838
|
+
readonly period_start: string | null;
|
|
2839
|
+
readonly period_end: string | null;
|
|
2840
|
+
readonly active: boolean;
|
|
2841
|
+
readonly created_by: string;
|
|
2842
|
+
readonly created_at: string;
|
|
2843
|
+
}
|
|
2844
|
+
/** Current spending state against a budget limit. */
|
|
2845
|
+
interface BudgetSpendingState {
|
|
2846
|
+
readonly limit_id: string;
|
|
2847
|
+
readonly spent_amount: number;
|
|
2848
|
+
readonly remaining_amount: number;
|
|
2849
|
+
readonly exceeded: boolean;
|
|
2850
|
+
/** Utilization percentage (0–100+). */
|
|
2851
|
+
readonly utilization_pct: number;
|
|
2852
|
+
readonly updated_at: string;
|
|
2853
|
+
}
|
|
2854
|
+
/** A spending constraint on a financial action class or type. */
|
|
2855
|
+
interface SpendingConstraint {
|
|
2856
|
+
readonly constraint_id: string;
|
|
2857
|
+
readonly org_id: string;
|
|
2858
|
+
/** "*" matches all action types. */
|
|
2859
|
+
readonly action_type: FinancialActionType | "*";
|
|
2860
|
+
readonly max_single_transaction: number;
|
|
2861
|
+
readonly max_daily_aggregate: number | null;
|
|
2862
|
+
readonly max_monthly_aggregate: number | null;
|
|
2863
|
+
readonly currency: CurrencyCode;
|
|
2864
|
+
readonly applies_to_tier_gte: FinancialRiskTier | null;
|
|
2865
|
+
readonly allow_anonymous_agents: boolean;
|
|
2866
|
+
readonly active: boolean;
|
|
2867
|
+
}
|
|
2868
|
+
/** A specific budget violation. */
|
|
2869
|
+
interface BudgetViolation {
|
|
2870
|
+
readonly violation_type: "limit_exceeded" | "single_transaction_exceeds" | "daily_aggregate_exceeds" | "monthly_aggregate_exceeds" | "anonymous_agent_blocked" | "period_expired";
|
|
2871
|
+
readonly limit_id?: string;
|
|
2872
|
+
readonly constraint_id?: string;
|
|
2873
|
+
readonly description: string;
|
|
2874
|
+
readonly overage_amount?: number;
|
|
2875
|
+
}
|
|
2876
|
+
/** Result of checking an action against budget constraints. */
|
|
2877
|
+
interface BudgetConstraintCheckResult {
|
|
2878
|
+
readonly permitted: boolean;
|
|
2879
|
+
readonly hard_blocks: readonly BudgetViolation[];
|
|
2880
|
+
readonly soft_warnings: readonly BudgetViolation[];
|
|
2881
|
+
readonly limits_checked: readonly string[];
|
|
2882
|
+
readonly constraints_checked: readonly string[];
|
|
2883
|
+
}
|
|
2884
|
+
/** A complete budget policy document for an organization. */
|
|
2885
|
+
interface BudgetPolicy {
|
|
2886
|
+
readonly policy_id: string;
|
|
2887
|
+
readonly org_id: string;
|
|
2888
|
+
readonly name: string;
|
|
2889
|
+
readonly limits: readonly BudgetLimit[];
|
|
2890
|
+
readonly constraints: readonly SpendingConstraint[];
|
|
2891
|
+
readonly override_requires_exception: boolean;
|
|
2892
|
+
readonly allow_approved_escalation: boolean;
|
|
2893
|
+
readonly version: string;
|
|
2894
|
+
readonly effective_from: string;
|
|
2895
|
+
readonly expires_at: string | null;
|
|
2896
|
+
}
|
|
2897
|
+
/**
|
|
2898
|
+
* Check an action value against applicable budget limits and constraints.
|
|
2899
|
+
*
|
|
2900
|
+
* Hard limits block execution; soft limits surface as warnings.
|
|
2901
|
+
*/
|
|
2902
|
+
declare function checkBudgetConstraints(params: {
|
|
2903
|
+
actionValue: number;
|
|
2904
|
+
currency: CurrencyCode;
|
|
2905
|
+
actionType: FinancialActionType;
|
|
2906
|
+
riskTier: FinancialRiskTier;
|
|
2907
|
+
isAnonymousAgent: boolean;
|
|
2908
|
+
currentDailySpend: number;
|
|
2909
|
+
currentMonthlySpend: number;
|
|
2910
|
+
applicableLimits: readonly (BudgetLimit & {
|
|
2911
|
+
spending: BudgetSpendingState;
|
|
2912
|
+
})[];
|
|
2913
|
+
applicableConstraints: readonly SpendingConstraint[];
|
|
2914
|
+
now?: Date;
|
|
2915
|
+
}): BudgetConstraintCheckResult;
|
|
2916
|
+
/**
|
|
2917
|
+
* Determine budget utilization severity for dashboard display.
|
|
2918
|
+
*/
|
|
2919
|
+
declare function budgetUtilizationSeverity(utilizationPct: number): "normal" | "warn" | "critical";
|
|
2920
|
+
|
|
2921
|
+
/**
|
|
2922
|
+
* Autonomous Financial Execution — governance for AI-driven financial actions.
|
|
2923
|
+
*
|
|
2924
|
+
* Defines bounded authority, execution ceilings, and runtime verification
|
|
2925
|
+
* requirements for autonomous agents performing financial operations:
|
|
2926
|
+
* refunds, procurement, cloud-cost optimization, vendor payments, etc.
|
|
2927
|
+
*
|
|
2928
|
+
* Wire-stable as `autonomous_financial.v1`.
|
|
2929
|
+
*/
|
|
2930
|
+
|
|
2931
|
+
/** Authority bounds for an autonomous financial agent. */
|
|
2932
|
+
interface AutonomousExecutionBounds {
|
|
2933
|
+
readonly bounds_id: string;
|
|
2934
|
+
readonly org_id: string;
|
|
2935
|
+
readonly agent_id: string;
|
|
2936
|
+
readonly agent_name: string;
|
|
2937
|
+
/** Action types this agent is permitted to execute autonomously. */
|
|
2938
|
+
readonly permitted_action_types: readonly FinancialActionType[];
|
|
2939
|
+
readonly ceilings: readonly ExecutionCeiling[];
|
|
2940
|
+
readonly daily_aggregate_ceiling: number;
|
|
2941
|
+
readonly aggregate_currency: CurrencyCode;
|
|
2942
|
+
/** Maximum risk tier the agent may autonomously execute. */
|
|
2943
|
+
readonly max_risk_tier: FinancialRiskTier;
|
|
2944
|
+
readonly require_runtime_verification: boolean;
|
|
2945
|
+
readonly anomaly_detection_enabled: boolean;
|
|
2946
|
+
readonly created_at: string;
|
|
2947
|
+
readonly expires_at: string | null;
|
|
2948
|
+
readonly active: boolean;
|
|
2949
|
+
}
|
|
2950
|
+
/** Per-action-type execution ceiling. */
|
|
2951
|
+
interface ExecutionCeiling {
|
|
2952
|
+
readonly action_type: FinancialActionType;
|
|
2953
|
+
readonly per_execution_max: number;
|
|
2954
|
+
readonly currency: CurrencyCode;
|
|
2955
|
+
readonly max_daily_count: number | null;
|
|
2956
|
+
readonly require_permit: boolean;
|
|
2957
|
+
}
|
|
2958
|
+
/** Record of an autonomous execution attempt. */
|
|
2959
|
+
interface AutonomousExecutionRecord {
|
|
2960
|
+
readonly record_id: string;
|
|
2961
|
+
readonly agent_id: string;
|
|
2962
|
+
readonly org_id: string;
|
|
2963
|
+
readonly action_type: FinancialActionType;
|
|
2964
|
+
readonly action_value: number;
|
|
2965
|
+
readonly currency: CurrencyCode;
|
|
2966
|
+
readonly permitted: boolean;
|
|
2967
|
+
readonly denial_reason: string | null;
|
|
2968
|
+
readonly permit_id: string | null;
|
|
2969
|
+
readonly anomaly_detected: boolean;
|
|
2970
|
+
readonly anomaly_description: string | null;
|
|
2971
|
+
readonly attempted_at: string;
|
|
2972
|
+
readonly executed_at: string | null;
|
|
2973
|
+
}
|
|
2974
|
+
/** Result of checking whether an autonomous execution is within bounds. */
|
|
2975
|
+
interface AutonomousExecutionCheckResult {
|
|
2976
|
+
readonly permitted: boolean;
|
|
2977
|
+
readonly action_type_permitted: boolean;
|
|
2978
|
+
readonly within_execution_ceiling: boolean;
|
|
2979
|
+
readonly within_daily_aggregate: boolean;
|
|
2980
|
+
readonly within_risk_tier: boolean;
|
|
2981
|
+
readonly bounds_active: boolean;
|
|
2982
|
+
readonly bounds_not_expired: boolean;
|
|
2983
|
+
readonly applicable_ceiling: ExecutionCeiling | null;
|
|
2984
|
+
readonly denial_reason: string | null;
|
|
2985
|
+
readonly violations: readonly string[];
|
|
2986
|
+
}
|
|
2987
|
+
/**
|
|
2988
|
+
* Check whether an autonomous execution is within declared bounds.
|
|
2989
|
+
*/
|
|
2990
|
+
declare function checkAutonomousBounds(params: {
|
|
2991
|
+
bounds: AutonomousExecutionBounds;
|
|
2992
|
+
actionType: FinancialActionType;
|
|
2993
|
+
actionValue: number;
|
|
2994
|
+
currency: CurrencyCode;
|
|
2995
|
+
riskTier: FinancialRiskTier;
|
|
2996
|
+
currentDailyAggregate: number;
|
|
2997
|
+
currentDailyCount: Partial<Record<string, number>>;
|
|
2998
|
+
now?: Date;
|
|
2999
|
+
}): AutonomousExecutionCheckResult;
|
|
3000
|
+
/**
|
|
3001
|
+
* Detect a potential anomaly in autonomous execution.
|
|
3002
|
+
* Returns a description when an anomaly is detected, or null.
|
|
3003
|
+
*/
|
|
3004
|
+
declare function detectAutonomousAnomaly(params: {
|
|
3005
|
+
actionValue: number;
|
|
3006
|
+
historicalMeanValue: number;
|
|
3007
|
+
historicalStdDev: number;
|
|
3008
|
+
recentExecutionCount: number;
|
|
3009
|
+
burstThreshold: number;
|
|
3010
|
+
isOffHours: boolean;
|
|
3011
|
+
}): {
|
|
3012
|
+
anomalyDetected: boolean;
|
|
3013
|
+
description: string | null;
|
|
3014
|
+
};
|
|
3015
|
+
|
|
3016
|
+
/**
|
|
3017
|
+
* Incentive Alignment Engine.
|
|
3018
|
+
*
|
|
3019
|
+
* Detects governance anti-patterns that indicate misaligned incentives:
|
|
3020
|
+
* excessive overrides, rushed approvals, emergency bypass repetition,
|
|
3021
|
+
* authority concentration, and governance fatigue.
|
|
3022
|
+
*
|
|
3023
|
+
* These signals are leading indicators of systemic governance failure.
|
|
3024
|
+
* They do not block execution but feed into risk scoring and dashboards.
|
|
3025
|
+
*
|
|
3026
|
+
* Wire-stable as `incentive_alignment.v1`.
|
|
3027
|
+
*/
|
|
3028
|
+
/** Categories of governance incentive signals. */
|
|
3029
|
+
type IncentiveSignalType = "excessive_overrides" | "rushed_approval" | "emergency_bypass_repeat" | "authority_concentration" | "rubber_stamping" | "approval_collusion" | "escalation_avoidance" | "governance_fatigue" | "delegation_chain_depth" | "approval_velocity_spike";
|
|
3030
|
+
/** A detected incentive alignment signal. */
|
|
3031
|
+
interface IncentiveSignal {
|
|
3032
|
+
readonly signal_id: string;
|
|
3033
|
+
readonly signal_type: IncentiveSignalType;
|
|
3034
|
+
readonly party_id: string;
|
|
3035
|
+
readonly party_label: string;
|
|
3036
|
+
/** Severity (0–100). */
|
|
3037
|
+
readonly severity: number;
|
|
3038
|
+
readonly description: string;
|
|
3039
|
+
readonly evidence: readonly string[];
|
|
3040
|
+
readonly detected_at: string;
|
|
3041
|
+
readonly reviewed: boolean;
|
|
3042
|
+
readonly reviewed_by: string | null;
|
|
3043
|
+
}
|
|
3044
|
+
/** Behavior pattern analysis for a governance actor. */
|
|
3045
|
+
interface GovernanceBehaviorPattern {
|
|
3046
|
+
readonly party_id: string;
|
|
3047
|
+
readonly party_label: string;
|
|
3048
|
+
readonly observation_window_days: number;
|
|
3049
|
+
readonly total_approvals: number;
|
|
3050
|
+
readonly total_overrides: number;
|
|
3051
|
+
readonly total_emergency_bypasses: number;
|
|
3052
|
+
readonly mean_approval_latency_seconds: number;
|
|
3053
|
+
readonly min_approval_latency_seconds: number;
|
|
3054
|
+
readonly approval_concentration_score: number;
|
|
3055
|
+
readonly delegation_depth_max: number;
|
|
3056
|
+
readonly signals: readonly IncentiveSignal[];
|
|
3057
|
+
/** 0–100; higher = healthier governance posture. */
|
|
3058
|
+
readonly governance_health_score: number;
|
|
3059
|
+
}
|
|
3060
|
+
/** Misalignment alert for operator review. */
|
|
3061
|
+
interface MisalignmentAlert {
|
|
3062
|
+
readonly alert_id: string;
|
|
3063
|
+
readonly org_id: string;
|
|
3064
|
+
readonly severity: "warn" | "critical";
|
|
3065
|
+
readonly alert_type: IncentiveSignalType;
|
|
3066
|
+
readonly affected_party_ids: readonly string[];
|
|
3067
|
+
readonly description: string;
|
|
3068
|
+
readonly recommendation: string;
|
|
3069
|
+
readonly signals: readonly IncentiveSignal[];
|
|
3070
|
+
readonly created_at: string;
|
|
3071
|
+
readonly resolved: boolean;
|
|
3072
|
+
readonly resolved_at: string | null;
|
|
3073
|
+
}
|
|
3074
|
+
/** Thresholds for incentive alignment detection. */
|
|
3075
|
+
interface IncentiveAlignmentConfig {
|
|
3076
|
+
readonly max_override_rate: number;
|
|
3077
|
+
readonly min_approval_latency_seconds: number;
|
|
3078
|
+
readonly max_emergency_bypasses_30d: number;
|
|
3079
|
+
readonly max_concentration_share: number;
|
|
3080
|
+
readonly max_delegation_depth: number;
|
|
3081
|
+
}
|
|
3082
|
+
declare const DEFAULT_INCENTIVE_CONFIG: IncentiveAlignmentConfig;
|
|
3083
|
+
/**
|
|
3084
|
+
* Analyze a governance actor's behavior to detect misaligned incentives.
|
|
3085
|
+
* Returns signals sorted by severity (highest first).
|
|
3086
|
+
*/
|
|
3087
|
+
declare function detectMisalignedIncentives(params: {
|
|
3088
|
+
partyId: string;
|
|
3089
|
+
partyLabel: string;
|
|
3090
|
+
windowDays: number;
|
|
3091
|
+
totalActions: number;
|
|
3092
|
+
overrideCount: number;
|
|
3093
|
+
emergencyBypassCount: number;
|
|
3094
|
+
approvalLatencies: readonly number[];
|
|
3095
|
+
approvalShare: number;
|
|
3096
|
+
delegationDepthMax: number;
|
|
3097
|
+
config?: IncentiveAlignmentConfig;
|
|
3098
|
+
now?: Date;
|
|
3099
|
+
}): IncentiveSignal[];
|
|
3100
|
+
/**
|
|
3101
|
+
* Compute a governance health score (0–100).
|
|
3102
|
+
* 100 = perfect governance; 0 = extreme misalignment.
|
|
3103
|
+
*/
|
|
3104
|
+
declare function computeGovernanceHealthScore(signals: readonly IncentiveSignal[]): number;
|
|
3105
|
+
|
|
3106
|
+
/**
|
|
3107
|
+
* Economic Evidence Bundles.
|
|
3108
|
+
*
|
|
3109
|
+
* Generates signed evidence proving approval provenance, execution
|
|
3110
|
+
* authorization, runtime conformity, liability chain, and policy compliance
|
|
3111
|
+
* for regulatory review, insurance, financial audit, and legal discovery.
|
|
3112
|
+
*
|
|
3113
|
+
* Follows the same signing pattern as auditBundle.ts, scoped to financial
|
|
3114
|
+
* governance evidence.
|
|
3115
|
+
*
|
|
3116
|
+
* Wire-stable as `economic_evidence.v1`.
|
|
3117
|
+
*/
|
|
3118
|
+
|
|
3119
|
+
/** Purpose for which an economic evidence bundle is generated. */
|
|
3120
|
+
type EvidencePurpose = "regulator_review" | "insurance_review" | "financial_audit" | "legal_discovery" | "internal_review" | "dispute_resolution";
|
|
3121
|
+
/** Approval provenance record within the evidence bundle. */
|
|
3122
|
+
interface ApprovalProvenance {
|
|
3123
|
+
readonly approver_id: string;
|
|
3124
|
+
readonly approver_label: string;
|
|
3125
|
+
readonly permit_id: string;
|
|
3126
|
+
readonly approved_at: string;
|
|
3127
|
+
readonly audit_hash: string;
|
|
3128
|
+
readonly role: string;
|
|
3129
|
+
}
|
|
3130
|
+
/** Complete economic evidence bundle. */
|
|
3131
|
+
interface EconomicEvidenceBundle {
|
|
3132
|
+
readonly version: "economic_evidence.v1";
|
|
3133
|
+
readonly bundle_id: string;
|
|
3134
|
+
readonly org_id: string;
|
|
3135
|
+
readonly purpose: EvidencePurpose;
|
|
3136
|
+
readonly execution_record: FinancialExecutionRecord;
|
|
3137
|
+
readonly liability_attribution: LiabilityAttributionRecord;
|
|
3138
|
+
readonly quorum_result: FinancialQuorumResult;
|
|
3139
|
+
readonly budget_check: BudgetConstraintCheckResult;
|
|
3140
|
+
readonly approval_provenance: readonly ApprovalProvenance[];
|
|
3141
|
+
readonly runtime_conformity: boolean;
|
|
3142
|
+
readonly runtime_conformity_notes: readonly string[];
|
|
3143
|
+
readonly policy_compliant: boolean;
|
|
3144
|
+
readonly policy_violations: readonly string[];
|
|
3145
|
+
readonly generated_at: string;
|
|
3146
|
+
readonly requested_by: string;
|
|
3147
|
+
/** SHA-256 hex of the canonical signable content. */
|
|
3148
|
+
readonly content_hash: string;
|
|
3149
|
+
/** Base64url Ed25519 signature of the canonical content. */
|
|
3150
|
+
readonly signature: string | null;
|
|
3151
|
+
readonly signing_key_id: string | null;
|
|
3152
|
+
}
|
|
3153
|
+
/** Canonical content shape that gets hashed and signed. */
|
|
3154
|
+
interface EvidenceBundleSignableContent {
|
|
3155
|
+
readonly bundle_id: string;
|
|
3156
|
+
readonly org_id: string;
|
|
3157
|
+
readonly purpose: EvidencePurpose;
|
|
3158
|
+
readonly execution_id: string;
|
|
3159
|
+
readonly attribution_id: string;
|
|
3160
|
+
readonly liability_chain_hash: string;
|
|
3161
|
+
readonly approval_count: number;
|
|
3162
|
+
readonly permit_ids: readonly string[];
|
|
3163
|
+
readonly policy_compliant: boolean;
|
|
3164
|
+
readonly generated_at: string;
|
|
3165
|
+
}
|
|
3166
|
+
/** Verification result for an economic evidence bundle. */
|
|
3167
|
+
interface EvidenceBundleVerificationResult {
|
|
3168
|
+
readonly valid: boolean;
|
|
3169
|
+
readonly content_hash_valid: boolean;
|
|
3170
|
+
readonly signature_valid: boolean;
|
|
3171
|
+
readonly liability_chain_hash_matches: boolean;
|
|
3172
|
+
readonly permit_ids_match: boolean;
|
|
3173
|
+
readonly reason: string | null;
|
|
3174
|
+
}
|
|
3175
|
+
/**
|
|
3176
|
+
* Canonicalize a value to a stable string representation.
|
|
3177
|
+
*
|
|
3178
|
+
* Exported (rather than file-private) to enable cross-language
|
|
3179
|
+
* byte-equivalence verification against the Python implementation in
|
|
3180
|
+
* ``atlasent-sdk/python/atlasent/governance/_canonical.py``. The shared
|
|
3181
|
+
* fixture lives at ``compat/governance/fixtures/parity.json``.
|
|
3182
|
+
*/
|
|
3183
|
+
declare function canonicalizeForEvidence(value: unknown): string;
|
|
3184
|
+
/**
|
|
3185
|
+
* Build the signable content object for a bundle.
|
|
3186
|
+
* Key order is load-bearing — must remain stable across versions.
|
|
3187
|
+
*/
|
|
3188
|
+
declare function buildSignableContent(bundle: Omit<EconomicEvidenceBundle, "content_hash" | "signature" | "signing_key_id">): EvidenceBundleSignableContent;
|
|
3189
|
+
/**
|
|
3190
|
+
* Serialize signable content to canonical UTF-8 bytes.
|
|
3191
|
+
* Uses the same sort-keyed canonicalization as auditBundle.
|
|
3192
|
+
*/
|
|
3193
|
+
declare function serializeSignableContent(content: EvidenceBundleSignableContent): Uint8Array;
|
|
3194
|
+
/**
|
|
3195
|
+
* Verify an economic evidence bundle's structural integrity.
|
|
3196
|
+
* Does NOT verify the Ed25519 signature (requires crypto keys).
|
|
3197
|
+
*/
|
|
3198
|
+
declare function verifyEvidenceBundleStructure(bundle: EconomicEvidenceBundle): EvidenceBundleVerificationResult;
|
|
3199
|
+
|
|
3200
|
+
/**
|
|
3201
|
+
* Dispute + Reversal Workflows.
|
|
3202
|
+
*
|
|
3203
|
+
* Manages disputed financial actions, rollback workflows, frozen actions,
|
|
3204
|
+
* and temporary suspensions. Tracks dispute origin, remediation timeline,
|
|
3205
|
+
* and reversal authority.
|
|
3206
|
+
*
|
|
3207
|
+
* Wire-stable as `dispute_reversal.v1`.
|
|
3208
|
+
*/
|
|
3209
|
+
|
|
3210
|
+
/** Who or what originated a dispute. */
|
|
3211
|
+
type DisputeOrigin = "counterparty" | "regulator" | "internal_audit" | "fraud_detection" | "approver_retract" | "policy_violation" | "agent_error";
|
|
3212
|
+
/** Current state of a dispute. */
|
|
3213
|
+
type DisputeStatus = "open" | "under_review" | "escalated" | "resolved_in_favor" | "resolved_against" | "reversed" | "withdrawn";
|
|
3214
|
+
/** A dispute record for a financial action. */
|
|
3215
|
+
interface DisputeRecord {
|
|
3216
|
+
readonly dispute_id: string;
|
|
3217
|
+
readonly execution_id: string;
|
|
3218
|
+
readonly org_id: string;
|
|
3219
|
+
readonly origin: DisputeOrigin;
|
|
3220
|
+
readonly filed_by: string;
|
|
3221
|
+
readonly description: string;
|
|
3222
|
+
readonly status: DisputeStatus;
|
|
3223
|
+
readonly execution_frozen: boolean;
|
|
3224
|
+
readonly opened_at: string;
|
|
3225
|
+
readonly resolution_deadline: string | null;
|
|
3226
|
+
readonly resolved_at: string | null;
|
|
3227
|
+
readonly resolved_by: string | null;
|
|
3228
|
+
readonly resolution_notes: string | null;
|
|
3229
|
+
readonly reversal_initiated: boolean;
|
|
3230
|
+
readonly reversal_id: string | null;
|
|
3231
|
+
}
|
|
3232
|
+
/** Reversal workflow stage. */
|
|
3233
|
+
type ReversalStage = "initiated" | "authorization_pending" | "authorized" | "executing" | "completed" | "failed" | "cancelled";
|
|
3234
|
+
/** A reversal workflow for a financial execution. */
|
|
3235
|
+
interface ReversalWorkflow {
|
|
3236
|
+
readonly reversal_id: string;
|
|
3237
|
+
readonly execution_id: string;
|
|
3238
|
+
readonly dispute_id: string | null;
|
|
3239
|
+
readonly org_id: string;
|
|
3240
|
+
readonly initiated_by: string;
|
|
3241
|
+
readonly reason: string;
|
|
3242
|
+
readonly stage: ReversalStage;
|
|
3243
|
+
readonly authorized_by: string | null;
|
|
3244
|
+
readonly authorization_permit_id: string | null;
|
|
3245
|
+
readonly initiated_at: string;
|
|
3246
|
+
readonly authorized_at: string | null;
|
|
3247
|
+
readonly completed_at: string | null;
|
|
3248
|
+
readonly reversal_value: number;
|
|
3249
|
+
readonly partial: boolean;
|
|
3250
|
+
}
|
|
3251
|
+
/** Action freeze record. */
|
|
3252
|
+
interface ActionFreeze {
|
|
3253
|
+
readonly freeze_id: string;
|
|
3254
|
+
readonly execution_id: string;
|
|
3255
|
+
readonly org_id: string;
|
|
3256
|
+
readonly triggered_by: string;
|
|
3257
|
+
readonly reason: string;
|
|
3258
|
+
readonly triggered_at: string;
|
|
3259
|
+
readonly expires_at: string | null;
|
|
3260
|
+
readonly lifted: boolean;
|
|
3261
|
+
readonly lifted_at: string | null;
|
|
3262
|
+
readonly lifted_by: string | null;
|
|
3263
|
+
readonly frozen_status: FinancialExecutionStatus;
|
|
3264
|
+
}
|
|
3265
|
+
/** Validate and apply a dispute status transition. */
|
|
3266
|
+
declare function transitionDispute(current: DisputeStatus, next: DisputeStatus): {
|
|
3267
|
+
success: boolean;
|
|
3268
|
+
new_status: DisputeStatus | null;
|
|
3269
|
+
error: string | null;
|
|
3270
|
+
};
|
|
3271
|
+
/** Validate and apply a reversal workflow stage transition. */
|
|
3272
|
+
declare function transitionReversal(current: ReversalStage, next: ReversalStage): {
|
|
3273
|
+
success: boolean;
|
|
3274
|
+
error: string | null;
|
|
3275
|
+
};
|
|
3276
|
+
/**
|
|
3277
|
+
* Return true when a freeze is currently active (not lifted and not expired).
|
|
3278
|
+
*/
|
|
3279
|
+
declare function isFreezeActive(freeze: ActionFreeze, now?: Date): boolean;
|
|
3280
|
+
/**
|
|
3281
|
+
* Compute remediation urgency based on dispute deadline.
|
|
3282
|
+
* Returns 'overdue' when past deadline, 'urgent' within 24h, else 'normal'.
|
|
3283
|
+
*/
|
|
3284
|
+
declare function computeRemediationUrgency(_openedAt: string, deadline: string | null, now?: Date): "normal" | "urgent" | "overdue";
|
|
3285
|
+
|
|
3286
|
+
/**
|
|
3287
|
+
* Financial Control Dashboard — types for governance visualization.
|
|
3288
|
+
*
|
|
3289
|
+
* Covers approval concentration analysis, override analytics, budget drift,
|
|
3290
|
+
* economic risk timelines, and liability visualization.
|
|
3291
|
+
*
|
|
3292
|
+
* These are pure data types; rendering is left to UI consumers.
|
|
3293
|
+
*
|
|
3294
|
+
* Wire-stable as `financial_dashboard.v1`.
|
|
3295
|
+
*/
|
|
3296
|
+
|
|
3297
|
+
/** Top-level financial governance summary for a dashboard view. */
|
|
3298
|
+
interface FinancialGovernanceSummary {
|
|
3299
|
+
readonly org_id: string;
|
|
3300
|
+
readonly generated_at: string;
|
|
3301
|
+
readonly window_days: number;
|
|
3302
|
+
readonly current_risk_score: FinancialRiskScore;
|
|
3303
|
+
readonly total_actions: number;
|
|
3304
|
+
readonly total_value: number;
|
|
3305
|
+
readonly override_count: number;
|
|
3306
|
+
readonly emergency_bypass_count: number;
|
|
3307
|
+
readonly active_dispute_count: number;
|
|
3308
|
+
readonly pending_reversal_count: number;
|
|
3309
|
+
readonly active_freeze_count: number;
|
|
3310
|
+
readonly budget_warning_count: number;
|
|
3311
|
+
readonly budget_critical_count: number;
|
|
3312
|
+
readonly concentration_analysis: ApprovalConcentrationAnalysis;
|
|
3313
|
+
readonly budget_drift: readonly BudgetaryDriftAnalysis[];
|
|
3314
|
+
readonly misalignment_alerts: readonly MisalignmentAlert[];
|
|
3315
|
+
readonly risk_timeline: readonly RiskTimelinePoint[];
|
|
3316
|
+
}
|
|
3317
|
+
/** A single point on the economic risk timeline. */
|
|
3318
|
+
interface RiskTimelinePoint {
|
|
3319
|
+
readonly date: string;
|
|
3320
|
+
readonly risk_score: number;
|
|
3321
|
+
readonly risk_tier: FinancialRiskTier;
|
|
3322
|
+
readonly action_count: number;
|
|
3323
|
+
readonly total_value: number;
|
|
3324
|
+
readonly override_count: number;
|
|
3325
|
+
readonly anomaly_count: number;
|
|
3326
|
+
}
|
|
3327
|
+
/** Override analytics for operator review. */
|
|
3328
|
+
interface OverrideAnalytics {
|
|
3329
|
+
readonly org_id: string;
|
|
3330
|
+
readonly window_days: number;
|
|
3331
|
+
readonly total_overrides: number;
|
|
3332
|
+
readonly override_rate: number;
|
|
3333
|
+
readonly overrides_by_actor: readonly ActorOverrideStat[];
|
|
3334
|
+
readonly overrides_by_action_type: readonly ActionTypeOverrideStat[];
|
|
3335
|
+
readonly override_value_total: number;
|
|
3336
|
+
readonly repeat_override_actors: readonly string[];
|
|
3337
|
+
readonly emergency_override_count: number;
|
|
3338
|
+
readonly computed_at: string;
|
|
3339
|
+
}
|
|
3340
|
+
interface ActorOverrideStat {
|
|
3341
|
+
readonly actor_id: string;
|
|
3342
|
+
readonly actor_label: string;
|
|
3343
|
+
readonly override_count: number;
|
|
3344
|
+
readonly override_value_total: number;
|
|
3345
|
+
readonly last_override_at: string;
|
|
3346
|
+
}
|
|
3347
|
+
interface ActionTypeOverrideStat {
|
|
3348
|
+
readonly action_type: string;
|
|
3349
|
+
readonly override_count: number;
|
|
3350
|
+
readonly total_value: number;
|
|
3351
|
+
}
|
|
3352
|
+
/** Liability visualization data for graph/chart rendering. */
|
|
3353
|
+
interface LiabilityVisualization {
|
|
3354
|
+
readonly execution_id: string;
|
|
3355
|
+
readonly org_id: string;
|
|
3356
|
+
readonly nodes: readonly LiabilityNode[];
|
|
3357
|
+
readonly edges: readonly LiabilityEdge[];
|
|
3358
|
+
readonly total_weight: number;
|
|
3359
|
+
}
|
|
3360
|
+
interface LiabilityNode {
|
|
3361
|
+
readonly id: string;
|
|
3362
|
+
readonly label: string;
|
|
3363
|
+
readonly party_type: "human" | "agent" | "system";
|
|
3364
|
+
readonly role: string;
|
|
3365
|
+
readonly liability_weight: number;
|
|
3366
|
+
readonly acted_at: string;
|
|
3367
|
+
}
|
|
3368
|
+
interface LiabilityEdge {
|
|
3369
|
+
readonly from_id: string;
|
|
3370
|
+
readonly to_id: string;
|
|
3371
|
+
readonly relationship: "authorized" | "delegated_to" | "approved_for" | "supervised" | "overrode";
|
|
3372
|
+
readonly weight: number;
|
|
3373
|
+
}
|
|
3374
|
+
/** Active disputes and reversals dashboard summary. */
|
|
3375
|
+
interface DisputeReversalSummary {
|
|
3376
|
+
readonly org_id: string;
|
|
3377
|
+
readonly active_disputes: readonly DisputeRecord[];
|
|
3378
|
+
readonly pending_reversals: readonly ReversalWorkflow[];
|
|
3379
|
+
readonly resolved_last_30d: number;
|
|
3380
|
+
readonly average_resolution_days: number;
|
|
3381
|
+
readonly overdue_disputes: readonly DisputeRecord[];
|
|
3382
|
+
readonly total_disputed_value: number;
|
|
3383
|
+
readonly total_reversed_value: number;
|
|
3384
|
+
readonly generated_at: string;
|
|
3385
|
+
}
|
|
3386
|
+
/**
|
|
3387
|
+
* Build a liability visualization graph from a liability chain.
|
|
3388
|
+
*/
|
|
3389
|
+
declare function buildLiabilityVisualization(executionId: string, orgId: string, chain: readonly LiabilityParty[]): LiabilityVisualization;
|
|
3390
|
+
/**
|
|
3391
|
+
* Build a risk timeline from daily snapshot data.
|
|
3392
|
+
*/
|
|
3393
|
+
declare function buildRiskTimeline(snapshots: readonly {
|
|
3394
|
+
date: string;
|
|
3395
|
+
riskScore: number;
|
|
3396
|
+
actionCount: number;
|
|
3397
|
+
totalValue: number;
|
|
3398
|
+
overrideCount: number;
|
|
3399
|
+
anomalyCount: number;
|
|
3400
|
+
}[]): RiskTimelinePoint[];
|
|
3401
|
+
|
|
3402
|
+
/**
|
|
3403
|
+
* Enforcement-layer helpers for the canonical economic governance primitives.
|
|
3404
|
+
*
|
|
3405
|
+
* The canonical EGAS modules (`financialQuorum`, `liabilityAttribution`,
|
|
3406
|
+
* `economicEvidence`, `budgetaryGovernance`, `autonomousFinancial`) are
|
|
3407
|
+
* **advisory**: they produce structured decision objects but never block
|
|
3408
|
+
* execution. This module converts "not permitted" advisory results into
|
|
3409
|
+
* thrown {@link GovernanceEnforcementError} so callers cannot silently
|
|
3410
|
+
* proceed when a governance gate refuses an action.
|
|
3411
|
+
*
|
|
3412
|
+
* Three gates, layered in this order at consumer call sites:
|
|
3413
|
+
*
|
|
3414
|
+
* ```ts
|
|
3415
|
+
* enforceFinancialQuorum(quorumResult);
|
|
3416
|
+
* enforceBudgetConstraint(budgetResult);
|
|
3417
|
+
* enforceAutonomousBounds(autonomousResult);
|
|
3418
|
+
* ```
|
|
3419
|
+
*
|
|
3420
|
+
* Each helper is a no-op when its result is permitted; otherwise it throws
|
|
3421
|
+
* with a stable {@link GovernanceEnforcementError.denyCode} matching a row
|
|
3422
|
+
* in `docs/APPROVAL_DENY_REASONS.md`. The deny-code taxonomy is locked
|
|
3423
|
+
* cross-language by the parity fixture at
|
|
3424
|
+
* `compat/governance/fixtures/parity.json`.
|
|
3425
|
+
*/
|
|
3426
|
+
|
|
3427
|
+
/** Which enforcement gate fired. */
|
|
3428
|
+
type GovernanceGate = "financial_quorum" | "budget" | "autonomous_bounds";
|
|
3429
|
+
/** Stable deny codes for the financial-quorum gate. */
|
|
3430
|
+
type FinancialQuorumDenyCode = "blocked_by_emergency_freeze" | "base_count_unmet" | "amount_threshold_unmet" | "financial_role_unmet" | "regulator_approval_missing";
|
|
3431
|
+
/** Stable deny codes for the budget gate. */
|
|
3432
|
+
type BudgetDenyCode = "limit_exceeded" | "single_transaction_exceeds" | "daily_aggregate_exceeds" | "monthly_aggregate_exceeds" | "anonymous_agent_blocked" | "period_expired";
|
|
3433
|
+
/** Stable deny codes for the autonomous-bounds gate. */
|
|
3434
|
+
type AutonomousBoundsDenyCode = "inactive" | "expired" | "action_type_not_permitted" | "execution_ceiling_exceeded" | "daily_aggregate_exceeded" | "risk_tier_exceeded";
|
|
3435
|
+
/** Initialization options for {@link GovernanceEnforcementError}. */
|
|
3436
|
+
interface GovernanceEnforcementErrorInit {
|
|
3437
|
+
gate: GovernanceGate;
|
|
3438
|
+
denyCode: string;
|
|
3439
|
+
reason: string;
|
|
3440
|
+
details: unknown;
|
|
3441
|
+
requestId?: string;
|
|
3442
|
+
}
|
|
3443
|
+
/**
|
|
3444
|
+
* Thrown when an EGAS advisory result fails an enforcement gate.
|
|
3445
|
+
*
|
|
3446
|
+
* Extends {@link AtlaSentError} so `instanceof AtlaSentError` catches
|
|
3447
|
+
* these too. Use `instanceof GovernanceEnforcementError` to distinguish
|
|
3448
|
+
* a governance refusal from a transport / config error.
|
|
3449
|
+
*/
|
|
3450
|
+
declare class GovernanceEnforcementError extends AtlaSentError {
|
|
3451
|
+
name: string;
|
|
3452
|
+
/** Which gate fired (`financial_quorum` / `budget` / `autonomous_bounds`). */
|
|
3453
|
+
readonly gate: GovernanceGate;
|
|
3454
|
+
/** Stable taxonomy code; maps to a row in `docs/APPROVAL_DENY_REASONS.md`. */
|
|
3455
|
+
readonly denyCode: string;
|
|
3456
|
+
/** Human-readable explanation. Do NOT branch on this string — branch on `denyCode`. */
|
|
3457
|
+
readonly reason: string;
|
|
3458
|
+
/** The structured advisory result that produced the denial. */
|
|
3459
|
+
readonly details: unknown;
|
|
3460
|
+
constructor(init: GovernanceEnforcementErrorInit);
|
|
3461
|
+
/** Combined `<gate>/<denyCode>` string used in audit records. */
|
|
3462
|
+
get fullyQualifiedCode(): string;
|
|
3463
|
+
}
|
|
3464
|
+
/**
|
|
3465
|
+
* Throw {@link GovernanceEnforcementError} when a quorum result fails.
|
|
3466
|
+
* Returns silently when `result.passed` is true.
|
|
3467
|
+
*/
|
|
3468
|
+
declare function enforceFinancialQuorum(result: FinancialQuorumResult): void;
|
|
3469
|
+
/**
|
|
3470
|
+
* Throw {@link GovernanceEnforcementError} on a budget hard block.
|
|
3471
|
+
*
|
|
3472
|
+
* Returns silently when `result.permitted` is true (no hard blocks; soft
|
|
3473
|
+
* warnings do not cause enforcement to fire).
|
|
3474
|
+
*/
|
|
3475
|
+
declare function enforceBudgetConstraint(result: BudgetConstraintCheckResult): void;
|
|
3476
|
+
/**
|
|
3477
|
+
* Throw {@link GovernanceEnforcementError} when autonomous bounds fail.
|
|
3478
|
+
* Returns silently when `result.permitted` is true.
|
|
3479
|
+
*/
|
|
3480
|
+
declare function enforceAutonomousBounds(result: AutonomousExecutionCheckResult): void;
|
|
3481
|
+
/**
|
|
3482
|
+
* Convenience: layer all three gates in canonical order.
|
|
3483
|
+
*
|
|
3484
|
+
* Order: quorum (who approved) → budget (does it fit policy spend) →
|
|
3485
|
+
* autonomous_bounds (is the agent allowed to do this autonomously). The
|
|
3486
|
+
* first failing gate throws; subsequent gates are not evaluated.
|
|
3487
|
+
*
|
|
3488
|
+
* Pass `undefined` for gates that don't apply (e.g. omit `autonomous` for
|
|
3489
|
+
* human-initiated actions).
|
|
3490
|
+
*/
|
|
3491
|
+
declare function enforceEconomicGovernance(params: {
|
|
3492
|
+
quorum?: FinancialQuorumResult;
|
|
3493
|
+
budget?: BudgetConstraintCheckResult;
|
|
3494
|
+
autonomous?: AutonomousExecutionCheckResult;
|
|
3495
|
+
}): void;
|
|
3496
|
+
|
|
3497
|
+
/**
|
|
3498
|
+
* Governance and enforcement webhook types — wire shapes for
|
|
3499
|
+
* `v1-governance-webhooks` and `v1-enforcement-webhooks`.
|
|
3500
|
+
*
|
|
3501
|
+
* Covers subscription management, signed delivery callbacks, and
|
|
3502
|
+
* delivery receipt records. Use `verifyWebhookSignature` in your
|
|
3503
|
+
* receiver to authenticate payloads.
|
|
3504
|
+
*/
|
|
3505
|
+
type GovernanceWebhookEvent = "enforcement.blocked" | "policy.violation" | "access_review.completed" | "mfa.enrollment_required" | "contract.activated" | "replay.drift_detected";
|
|
3506
|
+
type EnforcementWebhookEvent = "enforcement.blocked" | "enforcement.pending_approval" | "enforcement.approved" | "enforcement.expired";
|
|
3507
|
+
type WebhookDeliveryStatus = "pending" | "delivered" | "failed";
|
|
3508
|
+
interface WebhookSubscription {
|
|
3509
|
+
id: string;
|
|
3510
|
+
org_id: string;
|
|
3511
|
+
url: string;
|
|
3512
|
+
events: string[];
|
|
3513
|
+
enabled: boolean;
|
|
3514
|
+
description: string | null;
|
|
3515
|
+
created_at: string;
|
|
3516
|
+
}
|
|
3517
|
+
interface WebhookDelivery {
|
|
3518
|
+
id: string;
|
|
3519
|
+
subscription_id: string;
|
|
3520
|
+
event_type: string;
|
|
3521
|
+
payload: Record<string, unknown>;
|
|
3522
|
+
status: WebhookDeliveryStatus;
|
|
3523
|
+
response_status: number | null;
|
|
3524
|
+
response_body: string | null;
|
|
3525
|
+
attempted_at: string;
|
|
3526
|
+
}
|
|
3527
|
+
interface CreateWebhookSubscriptionRequest {
|
|
3528
|
+
url: string;
|
|
3529
|
+
events: string[];
|
|
3530
|
+
enabled?: boolean;
|
|
3531
|
+
description?: string;
|
|
3532
|
+
}
|
|
3533
|
+
interface ListWebhookSubscriptionsResponse {
|
|
3534
|
+
subscriptions: WebhookSubscription[];
|
|
3535
|
+
/** For governance webhooks, the server returns supported event names. */
|
|
3536
|
+
valid_events?: string[];
|
|
3537
|
+
}
|
|
3538
|
+
interface ListWebhookDeliveriesResponse {
|
|
3539
|
+
deliveries: WebhookDelivery[];
|
|
3540
|
+
}
|
|
3541
|
+
/**
|
|
3542
|
+
* Signed webhook payload delivered to subscriber endpoints.
|
|
3543
|
+
*
|
|
3544
|
+
* AtlaSent sets two headers on every delivery:
|
|
3545
|
+
* - `X-AtlaSent-Signature: sha256=<hex>` — HMAC-SHA256 of the raw body
|
|
3546
|
+
* - `X-AtlaSent-Event: <event_type>`
|
|
3547
|
+
*
|
|
3548
|
+
* Verify with `verifyWebhookSignature` before processing.
|
|
3549
|
+
*/
|
|
3550
|
+
interface WebhookPayload<T = Record<string, unknown>> {
|
|
3551
|
+
id: string;
|
|
3552
|
+
org_id: string;
|
|
3553
|
+
event_type: string;
|
|
3554
|
+
source_id: string | null;
|
|
3555
|
+
data: T;
|
|
3556
|
+
created_at: string;
|
|
3557
|
+
}
|
|
3558
|
+
/**
|
|
3559
|
+
* Verify a webhook delivery signature using the subscription secret.
|
|
3560
|
+
*
|
|
3561
|
+
* Performs a constant-time HMAC-SHA256 comparison so timing attacks
|
|
3562
|
+
* cannot reveal secret length. Requires `globalThis.crypto.subtle`
|
|
3563
|
+
* (Node 20+, all modern browsers, Deno, Cloudflare Workers).
|
|
3564
|
+
*
|
|
3565
|
+
* @param payload Raw UTF-8 request body string.
|
|
3566
|
+
* @param signature Value of the `X-AtlaSent-Signature` header.
|
|
3567
|
+
* @param secret Webhook subscription secret from the AtlaSent console.
|
|
3568
|
+
* @returns `true` when the signature is valid.
|
|
3569
|
+
*
|
|
3570
|
+
* @example
|
|
3571
|
+
* ```ts
|
|
3572
|
+
* import { verifyWebhookSignature } from "@atlasent/sdk";
|
|
3573
|
+
*
|
|
3574
|
+
* app.post("/webhook", async (req, res) => {
|
|
3575
|
+
* const ok = await verifyWebhookSignature(
|
|
3576
|
+
* req.rawBody,
|
|
3577
|
+
* req.headers["x-atlasent-signature"],
|
|
3578
|
+
* process.env.WEBHOOK_SECRET!,
|
|
3579
|
+
* );
|
|
3580
|
+
* if (!ok) return res.status(401).send("invalid signature");
|
|
3581
|
+
* // process req.body …
|
|
3582
|
+
* });
|
|
3583
|
+
* ```
|
|
3584
|
+
*/
|
|
3585
|
+
declare function verifyWebhookSignature(payload: string, signature: string, secret: string): Promise<boolean>;
|
|
3586
|
+
|
|
3587
|
+
/**
|
|
3588
|
+
* Compliance evidence types — wire shapes for `v1-compliance-evidence`.
|
|
3589
|
+
*
|
|
3590
|
+
* Supports on-demand SOC 2 Type II control evidence collection. The
|
|
3591
|
+
* same run shape is used for ISO 27001, GDPR, and HIPAA; control IDs
|
|
3592
|
+
* differ per framework.
|
|
3593
|
+
*/
|
|
3594
|
+
type ComplianceFramework = "soc2" | "iso27001" | "gdpr" | "hipaa";
|
|
3595
|
+
type EvidenceControlStatus = "pass" | "gap" | "finding";
|
|
3596
|
+
type ComplianceRunStatus = "pending" | "running" | "completed" | "failed";
|
|
3597
|
+
/**
|
|
3598
|
+
* A single evaluated control within an evidence run.
|
|
3599
|
+
* `evidence` is a free-form object whose keys are framework-specific
|
|
3600
|
+
* metric names (e.g. `mfa_enforced_policies`, `audit_events_last_30d`).
|
|
3601
|
+
*/
|
|
3602
|
+
interface EvidenceControl {
|
|
3603
|
+
control_id: string;
|
|
3604
|
+
title: string;
|
|
3605
|
+
status: EvidenceControlStatus;
|
|
3606
|
+
evidence: Record<string, unknown>;
|
|
3607
|
+
}
|
|
3608
|
+
interface ComplianceEvidenceSummary {
|
|
3609
|
+
total: number;
|
|
3610
|
+
pass: number;
|
|
3611
|
+
gap: number;
|
|
3612
|
+
finding: number;
|
|
3613
|
+
}
|
|
3614
|
+
interface ComplianceEvidenceRun {
|
|
3615
|
+
id: string;
|
|
3616
|
+
org_id: string;
|
|
3617
|
+
framework: ComplianceFramework;
|
|
3618
|
+
period_start: string;
|
|
3619
|
+
period_end: string;
|
|
3620
|
+
status: ComplianceRunStatus;
|
|
3621
|
+
controls: EvidenceControl[];
|
|
3622
|
+
summary: ComplianceEvidenceSummary | null;
|
|
3623
|
+
applied_by: string | null;
|
|
3624
|
+
created_at: string;
|
|
3625
|
+
}
|
|
3626
|
+
interface TriggerEvidenceRunRequest {
|
|
3627
|
+
framework: ComplianceFramework;
|
|
3628
|
+
/** ISO 8601 date string; defaults to 30 days ago on the server. */
|
|
3629
|
+
period_start?: string;
|
|
3630
|
+
/** ISO 8601 date string; defaults to now on the server. */
|
|
3631
|
+
period_end?: string;
|
|
3632
|
+
}
|
|
3633
|
+
interface TriggerEvidenceRunResponse {
|
|
3634
|
+
run: ComplianceEvidenceRun;
|
|
3635
|
+
}
|
|
3636
|
+
interface ListEvidenceRunsResponse {
|
|
3637
|
+
runs: ComplianceEvidenceRun[];
|
|
138
3638
|
}
|
|
139
|
-
|
|
140
3639
|
/**
|
|
141
|
-
*
|
|
3640
|
+
* SOC 2 control IDs evaluated by `v1-compliance-evidence`.
|
|
142
3641
|
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
3642
|
+
* | ID | Area |
|
|
3643
|
+
* |--------|------|
|
|
3644
|
+
* | CC6.1 | MFA enforcement |
|
|
3645
|
+
* | CC6.3 | Periodic access reviews |
|
|
3646
|
+
* | CC7.2 | Audit trail completeness |
|
|
3647
|
+
* | CC8.1 | Change management / HITL |
|
|
3648
|
+
* | CC3.2 | Policy violations |
|
|
3649
|
+
*/
|
|
3650
|
+
type SOC2ControlId = "CC6.1" | "CC6.3" | "CC7.2" | "CC8.1" | "CC3.2";
|
|
3651
|
+
/**
|
|
3652
|
+
* Returns `true` when every control in the run has `pass` or `gap`
|
|
3653
|
+
* status (no `finding`). A `gap` means a control is partially met;
|
|
3654
|
+
* a `finding` is a blocking deficiency that requires remediation.
|
|
3655
|
+
*/
|
|
3656
|
+
declare function evidenceRunPasses(run: ComplianceEvidenceRun): boolean;
|
|
3657
|
+
/**
|
|
3658
|
+
* Returns controls that do not have `pass` status, sorted so
|
|
3659
|
+
* `finding` controls appear before `gap` controls.
|
|
146
3660
|
*/
|
|
3661
|
+
declare function nonPassingControls(run: ComplianceEvidenceRun): EvidenceControl[];
|
|
147
3662
|
|
|
148
|
-
/** The two possible policy decisions. */
|
|
149
|
-
type Decision = "ALLOW" | "DENY";
|
|
150
3663
|
/**
|
|
151
|
-
*
|
|
3664
|
+
* Policy-as-code GitOps sync types — wire shapes for `v1-policy-sync`.
|
|
3665
|
+
*
|
|
3666
|
+
* Supports a dry-run diff preview / apply workflow for pushing policy
|
|
3667
|
+
* bundles from CI/CD pipelines or the AtlaSent console.
|
|
152
3668
|
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
3669
|
+
* Typical flow:
|
|
3670
|
+
* 1. POST `{ policies, dry_run: true }` → receive `run` with `diff`
|
|
3671
|
+
* 2. Review diff, then POST `/{run.id}/apply` to execute
|
|
156
3672
|
*
|
|
157
|
-
*
|
|
158
|
-
* preemptively back off before hitting a 429.
|
|
3673
|
+
* Or POST `{ policies, dry_run: false }` for an immediate apply.
|
|
159
3674
|
*/
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Parsed `X-RateLimit-Reset` — the UTC instant when the current
|
|
167
|
-
* window's counter zeroes. Accepts either a unix-seconds integer or
|
|
168
|
-
* an ISO 8601 string on the wire.
|
|
169
|
-
*/
|
|
170
|
-
resetAt: Date;
|
|
3675
|
+
type PolicySyncStatus = "pending" | "validating" | "applying" | "completed" | "failed" | "rejected";
|
|
3676
|
+
interface PolicyRef {
|
|
3677
|
+
name: string;
|
|
3678
|
+
/** SHA-256 hex of the policy body. */
|
|
3679
|
+
body_hash?: string;
|
|
171
3680
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
/** The action being authorized (e.g. "modify_patient_record"). */
|
|
177
|
-
action: string;
|
|
178
|
-
/** Arbitrary policy context (user, environment, resource IDs). */
|
|
179
|
-
context?: Record<string, unknown>;
|
|
3681
|
+
interface PolicySyncDiff {
|
|
3682
|
+
added: PolicyRef[];
|
|
3683
|
+
updated: PolicyRef[];
|
|
3684
|
+
removed: PolicyRef[];
|
|
180
3685
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
rateLimit: RateLimitState | null;
|
|
3686
|
+
interface PolicySyncRun {
|
|
3687
|
+
id: string;
|
|
3688
|
+
org_id: string;
|
|
3689
|
+
/** Identifies the caller: `"console"`, `"github-actions"`, etc. */
|
|
3690
|
+
source: string;
|
|
3691
|
+
commit_sha: string | null;
|
|
3692
|
+
ref: string | null;
|
|
3693
|
+
bundle_hash: string | null;
|
|
3694
|
+
status: PolicySyncStatus;
|
|
3695
|
+
policies_added: number;
|
|
3696
|
+
policies_updated: number;
|
|
3697
|
+
policies_removed: number;
|
|
3698
|
+
/** Populated on dry-run; null after apply. */
|
|
3699
|
+
diff: PolicySyncDiff | null;
|
|
3700
|
+
applied_by: string | null;
|
|
3701
|
+
created_at: string;
|
|
198
3702
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
/** Optional: re-state the agent for cross-check with the server. */
|
|
206
|
-
agent?: string;
|
|
207
|
-
/** Optional: re-state the context for cross-check with the server. */
|
|
208
|
-
context?: Record<string, unknown>;
|
|
3703
|
+
interface PolicyBundleEntry {
|
|
3704
|
+
name: string;
|
|
3705
|
+
/** Policy body — OPA Rego, JSON schema, or custom DSL depending on config. */
|
|
3706
|
+
body: string;
|
|
3707
|
+
description?: string;
|
|
3708
|
+
tags?: string[];
|
|
209
3709
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
/** Verification hash bound to the permit. */
|
|
217
|
-
permitHash: string;
|
|
218
|
-
/** ISO 8601 timestamp of the verification. */
|
|
219
|
-
timestamp: string;
|
|
3710
|
+
interface SubmitPolicySyncRequest {
|
|
3711
|
+
policies: PolicyBundleEntry[];
|
|
3712
|
+
/** Identifies the caller (e.g. `"github-actions"`, `"console"`). */
|
|
3713
|
+
source?: string;
|
|
3714
|
+
commit_sha?: string;
|
|
3715
|
+
ref?: string;
|
|
220
3716
|
/**
|
|
221
|
-
*
|
|
222
|
-
*
|
|
3717
|
+
* When `true` (default), computes the diff without applying changes.
|
|
3718
|
+
* The returned run will have `status: "pending"` and a populated `diff`.
|
|
3719
|
+
* POST to `/{run.id}/apply` to execute.
|
|
223
3720
|
*/
|
|
224
|
-
|
|
3721
|
+
dry_run?: boolean;
|
|
225
3722
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
* key the client was constructed with. Returned by `GET /v1/api-key-self`.
|
|
229
|
-
*
|
|
230
|
-
* Never includes the raw key or its hash — introspection is intentionally
|
|
231
|
-
* read-only and safe to surface in operator dashboards. Useful for:
|
|
232
|
-
* - "which key am I?" debugging
|
|
233
|
-
* - IP_NOT_ALLOWED failures — `clientIp` is the IP the server observed
|
|
234
|
-
* - proactive expiry warnings — `expiresAt` is the server-stored expiry
|
|
235
|
-
* (`null` means the key does not auto-expire)
|
|
236
|
-
* - verifying scopes before attempting a scope-gated action
|
|
237
|
-
*/
|
|
238
|
-
interface ApiKeySelfResponse {
|
|
239
|
-
/** Server-side UUID of the api_keys row for this key. */
|
|
240
|
-
keyId: string;
|
|
241
|
-
/** Organization the key belongs to. */
|
|
242
|
-
organizationId: string;
|
|
243
|
-
/** "live" or "test" (or any future environment label the server introduces). */
|
|
244
|
-
environment: string;
|
|
245
|
-
/** Granted scopes — e.g. ["evaluate", "audit.read"]. */
|
|
246
|
-
scopes: string[];
|
|
247
|
-
/**
|
|
248
|
-
* Per-key IP allowlist as CIDR strings (e.g. ["10.0.0.0/8"]). `null`
|
|
249
|
-
* when the key is unrestricted.
|
|
250
|
-
*/
|
|
251
|
-
allowedCidrs: string[] | null;
|
|
252
|
-
/** Server-enforced per-minute rate limit for this key. */
|
|
253
|
-
rateLimitPerMinute: number;
|
|
254
|
-
/** Client IP as the server observed it (first hop of X-Forwarded-For). */
|
|
255
|
-
clientIp: string | null;
|
|
256
|
-
/** Server-stored expiry; `null` means the key does not auto-expire. */
|
|
257
|
-
expiresAt: string | null;
|
|
258
|
-
/**
|
|
259
|
-
* Per-key rate-limit state for this request's response, parsed from
|
|
260
|
-
* `X-RateLimit-*` headers. `null` when the server didn't emit them.
|
|
261
|
-
*/
|
|
262
|
-
rateLimit: RateLimitState | null;
|
|
3723
|
+
interface SubmitPolicySyncResponse {
|
|
3724
|
+
run: PolicySyncRun;
|
|
263
3725
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
* byte-identical behaviour.
|
|
270
|
-
*/
|
|
271
|
-
interface AuditEventsResult extends AuditEventsPage {
|
|
272
|
-
/**
|
|
273
|
-
* Per-key rate-limit state for this request's response, parsed from
|
|
274
|
-
* `X-RateLimit-*` headers. `null` when the server didn't emit them.
|
|
275
|
-
*/
|
|
276
|
-
rateLimit: RateLimitState | null;
|
|
3726
|
+
interface ListPolicySyncRunsResponse {
|
|
3727
|
+
runs: PolicySyncRun[];
|
|
3728
|
+
}
|
|
3729
|
+
interface ApplyPolicySyncResponse {
|
|
3730
|
+
run: PolicySyncRun;
|
|
277
3731
|
}
|
|
278
3732
|
/**
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
3733
|
+
* Returns a human-readable one-line diff summary suitable for CI logs.
|
|
3734
|
+
*
|
|
3735
|
+
* @example
|
|
3736
|
+
* formatPolicySyncDiff(run) // "+3 added, ~1 updated, -2 removed"
|
|
3737
|
+
* formatPolicySyncDiff(run) // "no changes"
|
|
282
3738
|
*/
|
|
283
|
-
|
|
284
|
-
/** Comma-joined list of event types to include (e.g. `"evaluate.allow,policy.updated"`). */
|
|
285
|
-
types?: string;
|
|
286
|
-
/** Filter to a single actor. */
|
|
287
|
-
actor_id?: string;
|
|
288
|
-
/** Inclusive lower bound on `occurred_at` (ISO 8601). */
|
|
289
|
-
from?: string;
|
|
290
|
-
/** Inclusive upper bound on `occurred_at` (ISO 8601). */
|
|
291
|
-
to?: string;
|
|
292
|
-
}
|
|
3739
|
+
declare function formatPolicySyncDiff(run: Pick<PolicySyncRun, "policies_added" | "policies_updated" | "policies_removed">): string;
|
|
293
3740
|
/**
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
* envelope fields (`export_id`, `org_id`, `chain_head_hash`,
|
|
297
|
-
* `event_count`, `signed_at`, `events`, `signature`) are preserved
|
|
298
|
-
* byte-for-byte so the object can be handed straight to
|
|
299
|
-
* `verifyAuditBundle(bundle, keys)`.
|
|
3741
|
+
* Returns `true` when a sync run is in a terminal state
|
|
3742
|
+
* (completed, failed, or rejected) and no further transitions are expected.
|
|
300
3743
|
*/
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Per-key rate-limit state for this request's response, parsed from
|
|
304
|
-
* `X-RateLimit-*` headers. `null` when the server didn't emit them.
|
|
305
|
-
*/
|
|
306
|
-
rateLimit: RateLimitState | null;
|
|
307
|
-
}
|
|
308
|
-
/** Constructor options for {@link AtlaSentClient}. */
|
|
309
|
-
interface AtlaSentClientOptions {
|
|
310
|
-
/** Required. Your AtlaSent API key. */
|
|
311
|
-
apiKey: string;
|
|
312
|
-
/** API base URL. Defaults to "https://api.atlasent.io". */
|
|
313
|
-
baseUrl?: string;
|
|
314
|
-
/** Per-request timeout in milliseconds. Defaults to 10_000. */
|
|
315
|
-
timeoutMs?: number;
|
|
316
|
-
/**
|
|
317
|
-
* Inject a fetch implementation (primarily for testing).
|
|
318
|
-
* Defaults to `globalThis.fetch`.
|
|
319
|
-
*/
|
|
320
|
-
fetch?: typeof fetch;
|
|
321
|
-
}
|
|
3744
|
+
declare function isPolicySyncTerminal(run: PolicySyncRun): boolean;
|
|
322
3745
|
|
|
323
3746
|
/**
|
|
324
|
-
*
|
|
3747
|
+
* Webhook signature verification for AtlaSent.
|
|
325
3748
|
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
* - {@link AtlaSentClient.verifyPermit} → POST {baseUrl}/v1-verify-permit
|
|
3749
|
+
* AtlaSent signs webhook payloads with HMAC-SHA256 using your webhook secret.
|
|
3750
|
+
* The signature is sent in the `X-AtlaSent-Signature` header as `sha256=<hex>`.
|
|
329
3751
|
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
3752
|
+
* Usage:
|
|
3753
|
+
* ```ts
|
|
3754
|
+
* import { verifyWebhook, assertWebhook, WebhookVerificationError } from "@atlasent/sdk";
|
|
3755
|
+
*
|
|
3756
|
+
* // Returns true/false — good for middleware that needs to continue on failure
|
|
3757
|
+
* const valid = verifyWebhook(rawBody, req.headers["x-atlasent-signature"], secret);
|
|
3758
|
+
*
|
|
3759
|
+
* // Throws WebhookVerificationError on failure — good for middleware that throws
|
|
3760
|
+
* assertWebhook(rawBody, req.headers["x-atlasent-signature"], secret);
|
|
3761
|
+
* ```
|
|
333
3762
|
*/
|
|
334
|
-
|
|
335
|
-
declare class AtlaSentClient {
|
|
336
|
-
private readonly apiKey;
|
|
337
|
-
private readonly baseUrl;
|
|
338
|
-
private readonly timeoutMs;
|
|
339
|
-
private readonly fetchImpl;
|
|
340
|
-
constructor(options: AtlaSentClientOptions);
|
|
341
|
-
/**
|
|
342
|
-
* Ask the policy engine whether an agent action is permitted.
|
|
343
|
-
*
|
|
344
|
-
* A "DENY" is **not** thrown — it is returned in
|
|
345
|
-
* `response.decision`. Network errors, invalid API key, rate
|
|
346
|
-
* limits, timeouts, and malformed responses throw
|
|
347
|
-
* {@link AtlaSentError}.
|
|
348
|
-
*/
|
|
349
|
-
evaluate(input: EvaluateRequest): Promise<EvaluateResponse>;
|
|
350
|
-
/**
|
|
351
|
-
* Verify that a previously issued permit is still valid.
|
|
352
|
-
*
|
|
353
|
-
* A `verified: false` response is **not** thrown — inspect the
|
|
354
|
-
* returned object. Only transport / server errors throw.
|
|
355
|
-
*/
|
|
356
|
-
verifyPermit(input: VerifyPermitRequest): Promise<VerifyPermitResponse>;
|
|
357
|
-
/**
|
|
358
|
-
* Self-introspection: ask the server to describe the API key this
|
|
359
|
-
* client was constructed with. Returns the key's ID, organization,
|
|
360
|
-
* environment, scopes, IP allowlist, per-minute rate limit, the
|
|
361
|
-
* client IP the server observed, and the expiry (if any).
|
|
362
|
-
*
|
|
363
|
-
* Never includes the raw key or its hash. Safe to surface in operator
|
|
364
|
-
* dashboards. Useful for `IP_NOT_ALLOWED` debugging (the server tells
|
|
365
|
-
* you exactly which IP it saw) and for proactive expiry warnings.
|
|
366
|
-
*
|
|
367
|
-
* Throws {@link AtlaSentError} on transport / auth failures — same
|
|
368
|
-
* taxonomy as {@link AtlaSentClient.evaluate}.
|
|
369
|
-
*/
|
|
370
|
-
keySelf(): Promise<ApiKeySelfResponse>;
|
|
371
|
-
/**
|
|
372
|
-
* List persisted audit events for the authenticated organization
|
|
373
|
-
* (`GET /v1-audit/events`). Returned rows are wire-identical with
|
|
374
|
-
* the server: snake_case field names, including `previous_hash` and
|
|
375
|
-
* the `hash` chain, so the response can be fed straight into the
|
|
376
|
-
* offline verifier when paired with a signed export.
|
|
377
|
-
*
|
|
378
|
-
* `query.types` is a comma-joined list (e.g.
|
|
379
|
-
* `"evaluate.allow,policy.updated"`). `cursor` is the opaque
|
|
380
|
-
* `next_cursor` from the prior page. All fields are optional; the
|
|
381
|
-
* server defaults `limit` to 50 (capped at 500).
|
|
382
|
-
*
|
|
383
|
-
* Throws {@link AtlaSentError} on transport / auth failures — same
|
|
384
|
-
* taxonomy as {@link AtlaSentClient.evaluate}.
|
|
385
|
-
*/
|
|
386
|
-
listAuditEvents(query?: AuditEventsQuery): Promise<AuditEventsResult>;
|
|
387
|
-
/**
|
|
388
|
-
* Request a signed audit export bundle
|
|
389
|
-
* (`POST /v1-audit/exports`). The returned object is wire-identical
|
|
390
|
-
* with the server — `signature`, `chain_head_hash`, `events`, and
|
|
391
|
-
* friends survive untouched so the bundle can be persisted to disk
|
|
392
|
-
* and handed to the offline verifier (`verifyBundle` /
|
|
393
|
-
* `verifyAuditBundle`) without any reshaping.
|
|
394
|
-
*
|
|
395
|
-
* Pass `filter.types`, `filter.from`, `filter.to`, or `filter.actor_id`
|
|
396
|
-
* to narrow the export; omit for a full-org bundle. `rateLimit` is
|
|
397
|
-
* attached alongside the wire fields for observability.
|
|
398
|
-
*
|
|
399
|
-
* Throws {@link AtlaSentError} on transport / auth failures — same
|
|
400
|
-
* taxonomy as {@link AtlaSentClient.evaluate}.
|
|
401
|
-
*/
|
|
402
|
-
createAuditExport(filter?: AuditExportRequest): Promise<AuditExportResult>;
|
|
403
|
-
private post;
|
|
404
|
-
private get;
|
|
405
|
-
private request;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/** Node's webcrypto CryptoKey — kept local so the module doesn't depend on DOM types. */
|
|
409
|
-
type WebCryptoKey = webcrypto.CryptoKey;
|
|
410
|
-
/** Public key candidate the verifier will try, tagged with its registry id. */
|
|
411
|
-
interface VerifyKey {
|
|
412
|
-
keyId: string;
|
|
413
|
-
publicKey: WebCryptoKey;
|
|
414
|
-
}
|
|
415
|
-
interface BundleVerificationResult {
|
|
416
|
-
/**
|
|
417
|
-
* AND of three checks: adjacency (each event's `previous_hash`
|
|
418
|
-
* equals the prior event's `hash`), per-event hash recomputation
|
|
419
|
-
* from the canonical payload, and `chain_head_hash` matching the
|
|
420
|
-
* last event's stored hash.
|
|
421
|
-
*/
|
|
422
|
-
chainIntegrityOk: boolean;
|
|
423
|
-
/** Ed25519 signature verified against one of the supplied public keys. */
|
|
424
|
-
signatureValid: boolean;
|
|
425
|
-
/** `chain_head_hash` equals the last event's stored `hash`. */
|
|
426
|
-
headHashMatches: boolean;
|
|
427
|
-
/** Event ids whose recomputed hash != stored hash. */
|
|
428
|
-
tamperedEventIds: string[];
|
|
429
|
-
/** Which registry key id matched, when `signatureValid` is true. */
|
|
430
|
-
matchedKeyId?: string | undefined;
|
|
431
|
-
/** Non-fatal explanation when a flag is false. */
|
|
432
|
-
reason?: string | undefined;
|
|
433
|
-
/** Convenience: `chainIntegrityOk && signatureValid`. */
|
|
434
|
-
verified: boolean;
|
|
435
|
-
}
|
|
436
|
-
/** Parsed bundle shape the verifier consumes. Fields beyond these are ignored. */
|
|
437
|
-
interface AuditBundle {
|
|
438
|
-
export_id?: unknown;
|
|
439
|
-
org_id?: unknown;
|
|
440
|
-
chain_head_hash?: unknown;
|
|
441
|
-
event_count?: unknown;
|
|
442
|
-
signed_at?: unknown;
|
|
443
|
-
events?: unknown;
|
|
444
|
-
signature?: unknown;
|
|
445
|
-
signing_key_id?: unknown;
|
|
446
|
-
[k: string]: unknown;
|
|
447
|
-
}
|
|
448
|
-
interface VerifyBundleOptions {
|
|
449
|
-
/** SPKI-PEM strings (one per key in the active trust set). */
|
|
450
|
-
publicKeysPem?: readonly string[];
|
|
451
|
-
/** Already-imported keys, paired with registry ids (rotation hint). */
|
|
452
|
-
keys?: readonly VerifyKey[];
|
|
453
|
-
}
|
|
454
3763
|
/**
|
|
455
|
-
*
|
|
456
|
-
*
|
|
457
|
-
* - no whitespace
|
|
458
|
-
* - `null`, `undefined`, `NaN`, `±Infinity` all render as `"null"`
|
|
459
|
-
* - strings use standard `JSON.stringify` escapes
|
|
3764
|
+
* Thrown by {@link assertWebhook} when the signature is missing,
|
|
3765
|
+
* malformed, or does not match the payload.
|
|
460
3766
|
*/
|
|
461
|
-
declare
|
|
3767
|
+
declare class WebhookVerificationError extends Error {
|
|
3768
|
+
name: string;
|
|
3769
|
+
constructor(message: string);
|
|
3770
|
+
}
|
|
462
3771
|
/**
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
3772
|
+
* Verifies an AtlaSent webhook payload signature.
|
|
3773
|
+
*
|
|
3774
|
+
* AtlaSent signs webhook payloads with HMAC-SHA256 using your webhook secret.
|
|
3775
|
+
* The signature is sent in the `X-AtlaSent-Signature` header as `"sha256=<hex>"`.
|
|
3776
|
+
*
|
|
3777
|
+
* @param payload - Raw request body as a string (do **not** parse before verifying)
|
|
3778
|
+
* @param signature - Value of the `X-AtlaSent-Signature` header
|
|
3779
|
+
* @param secret - Your webhook signing secret
|
|
3780
|
+
* @returns `true` if the signature is valid, `false` otherwise
|
|
3781
|
+
*
|
|
3782
|
+
* @remarks
|
|
3783
|
+
* Returns `false` (does not throw) for malformed or missing signatures.
|
|
3784
|
+
* Use {@link assertWebhook} if you prefer exception-based control flow.
|
|
467
3785
|
*/
|
|
468
|
-
declare function
|
|
469
|
-
declare function verifyAuditBundle(bundle: AuditBundle, keys: readonly VerifyKey[]): Promise<BundleVerificationResult>;
|
|
3786
|
+
declare function verifyWebhook(payload: string, signature: string, secret: string): Promise<boolean>;
|
|
470
3787
|
/**
|
|
471
|
-
*
|
|
3788
|
+
* Same as {@link verifyWebhook} but throws {@link WebhookVerificationError}
|
|
3789
|
+
* on failure instead of returning `false`. Useful in middleware where
|
|
3790
|
+
* throwing is cleaner than inspecting a boolean return value.
|
|
472
3791
|
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
* set.
|
|
3792
|
+
* @param payload - Raw request body as a string (do **not** parse before verifying)
|
|
3793
|
+
* @param signature - Value of the `X-AtlaSent-Signature` header
|
|
3794
|
+
* @param secret - Your webhook signing secret
|
|
3795
|
+
* @throws {@link WebhookVerificationError} if the signature is invalid or malformed
|
|
478
3796
|
*/
|
|
479
|
-
declare function
|
|
3797
|
+
declare function assertWebhook(payload: string, signature: string, secret: string): Promise<void>;
|
|
480
3798
|
|
|
481
3799
|
/**
|
|
482
|
-
*
|
|
3800
|
+
* V2 Wave-A endpoints (V2-D3, V2-D4, V2-D8) — additive on top of v1.
|
|
483
3801
|
*
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
* {@link isRetryable} whether to retry a given {@link AtlaSentError},
|
|
488
|
-
* then ask {@link computeBackoffMs} how long to sleep before the next
|
|
489
|
-
* attempt.
|
|
3802
|
+
* Three additional methods on top of the v1 {@link AtlaSentClient}
|
|
3803
|
+
* surface that target the new wire endpoints landed in `atlasent-api`
|
|
3804
|
+
* PRs #742 (batch), #745 (stream), and #746 (graphql).
|
|
490
3805
|
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
* loop is wired into `client.ts`.
|
|
3806
|
+
* The v1 substrate is frozen (post-GA 2026-05-17) — this module is
|
|
3807
|
+
* purely additive. Existing 1.x methods (`protect`, `requirePermit`,
|
|
3808
|
+
* `evaluate`, …) are untouched.
|
|
495
3809
|
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
3810
|
+
* ## Closed-by-default discipline
|
|
3811
|
+
*
|
|
3812
|
+
* Each tenant gates the new endpoints behind `v2_batch`,
|
|
3813
|
+
* `v2_streaming`, and `v2_graphql` flags. When the flag is off the
|
|
3814
|
+
* API returns HTTP 404, surfaced here as {@link FeatureNotEnabledError}
|
|
3815
|
+
* so callers can deterministically fall back (typically to a per-item
|
|
3816
|
+
* `/v1-evaluate` loop). The SDK never silently falls back — that would
|
|
3817
|
+
* change billing and audit semantics.
|
|
3818
|
+
*/
|
|
3819
|
+
|
|
3820
|
+
declare const V2_BATCH_PATH = "/v1/evaluate/batch";
|
|
3821
|
+
declare const V2_STREAM_PATH = "/v1/evaluate/stream";
|
|
3822
|
+
declare const V2_GRAPHQL_PATH = "/v1/graphql";
|
|
3823
|
+
/** Maximum items per batch (mirrors the server-side cap, V2-D3). */
|
|
3824
|
+
declare const V2_MAX_BATCH_ITEMS = 100;
|
|
3825
|
+
/** Maximum request body size (mirrors the server-side 1MB cap). */
|
|
3826
|
+
declare const V2_MAX_BODY_BYTES = 1000000;
|
|
3827
|
+
/** GraphQL document depth cap (V2-D2). */
|
|
3828
|
+
declare const V2_GRAPHQL_MAX_DEPTH = 8;
|
|
3829
|
+
/**
|
|
3830
|
+
* Identifier of the tenant flag gating a V2 endpoint.
|
|
3831
|
+
*/
|
|
3832
|
+
type V2Feature = "batch" | "streaming" | "graphql";
|
|
3833
|
+
/**
|
|
3834
|
+
* Initialization options for {@link FeatureNotEnabledError}.
|
|
3835
|
+
*/
|
|
3836
|
+
interface FeatureNotEnabledErrorInit {
|
|
3837
|
+
feature: V2Feature;
|
|
3838
|
+
endpoint: string;
|
|
3839
|
+
requestId?: string;
|
|
3840
|
+
}
|
|
3841
|
+
/**
|
|
3842
|
+
* Thrown when a V2 endpoint returns 404 because the tenant feature
|
|
3843
|
+
* flag is off.
|
|
502
3844
|
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
3845
|
+
* The three V2 endpoints (`/v1/evaluate/batch`, `/v1/evaluate/stream`,
|
|
3846
|
+
* `/v1/graphql`) are close-by-default per tenant. When the
|
|
3847
|
+
* corresponding flag is unset, the API returns HTTP 404; the SDK
|
|
3848
|
+
* surfaces that as this distinct error so the caller can
|
|
3849
|
+
* deterministically fall back to the v1 per-item loop.
|
|
505
3850
|
*
|
|
506
|
-
*
|
|
507
|
-
*
|
|
508
|
-
* It avoids thundering-herd retries from many SDK instances that hit
|
|
509
|
-
* a 429 in the same window.
|
|
3851
|
+
* Subclass of {@link AtlaSentError} so `instanceof AtlaSentError`
|
|
3852
|
+
* catches it alongside the SDK's other typed errors.
|
|
510
3853
|
*/
|
|
511
|
-
|
|
512
|
-
|
|
3854
|
+
declare class FeatureNotEnabledError extends AtlaSentError {
|
|
3855
|
+
name: string;
|
|
3856
|
+
/** Which tenant flag is gating the endpoint. */
|
|
3857
|
+
readonly feature: V2Feature;
|
|
3858
|
+
/** The wire path the SDK attempted (for diagnostics). */
|
|
3859
|
+
readonly endpoint: string;
|
|
3860
|
+
constructor(init: FeatureNotEnabledErrorInit);
|
|
3861
|
+
}
|
|
513
3862
|
/**
|
|
514
|
-
*
|
|
515
|
-
*
|
|
3863
|
+
* One element of an {@link EvaluateBatchResponse.items} list.
|
|
3864
|
+
*
|
|
3865
|
+
* Preserves input order — `items[i]` corresponds to `request.items[i]`.
|
|
3866
|
+
* On a per-item RPC failure the server returns `decision: undefined`
|
|
3867
|
+
* and populates `errorCode` / `errorMessage` instead.
|
|
516
3868
|
*/
|
|
517
|
-
interface
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
3869
|
+
interface EvaluateBatchItem {
|
|
3870
|
+
index: number;
|
|
3871
|
+
decision?: string;
|
|
3872
|
+
decisionId?: string;
|
|
3873
|
+
permitToken?: string;
|
|
3874
|
+
reason?: string;
|
|
3875
|
+
errorCode?: string;
|
|
3876
|
+
errorMessage?: string;
|
|
3877
|
+
}
|
|
3878
|
+
/** Response shape for `POST /v1/evaluate/batch`. */
|
|
3879
|
+
interface EvaluateBatchResponse {
|
|
3880
|
+
batchId: string;
|
|
3881
|
+
items: ReadonlyArray<EvaluateBatchItem>;
|
|
3882
|
+
partial: boolean;
|
|
3883
|
+
}
|
|
3884
|
+
/** Request payload for {@link evaluateMany} and {@link authorizeStream}. */
|
|
3885
|
+
interface EvaluateManyRequest {
|
|
3886
|
+
items: ReadonlyArray<Record<string, unknown>>;
|
|
3887
|
+
batchId?: string;
|
|
3888
|
+
}
|
|
3889
|
+
/** `event: decision` frame surfaced via the `onDecision` callback. */
|
|
3890
|
+
interface StreamDecisionFrame {
|
|
3891
|
+
index: number;
|
|
3892
|
+
decision: string;
|
|
3893
|
+
decisionId?: string;
|
|
3894
|
+
permitToken?: string;
|
|
3895
|
+
reason?: string;
|
|
3896
|
+
}
|
|
3897
|
+
/** `event: error` frame surfaced via the `onError` callback. */
|
|
3898
|
+
interface StreamErrorFrame {
|
|
3899
|
+
index: number;
|
|
3900
|
+
errorCode: string;
|
|
3901
|
+
message: string;
|
|
3902
|
+
}
|
|
3903
|
+
/** Terminal `event: complete` payload returned by {@link authorizeStream}. */
|
|
3904
|
+
interface StreamComplete {
|
|
3905
|
+
batchId: string;
|
|
3906
|
+
count: number;
|
|
3907
|
+
partial: boolean;
|
|
3908
|
+
}
|
|
3909
|
+
/** GraphQL request body. */
|
|
3910
|
+
interface GraphQLRequest {
|
|
3911
|
+
query: string;
|
|
3912
|
+
variables?: Record<string, unknown>;
|
|
3913
|
+
operationName?: string;
|
|
3914
|
+
}
|
|
3915
|
+
/**
|
|
3916
|
+
* GraphQL response. Resolver errors land on `errors`; the SDK does
|
|
3917
|
+
* not throw on them — the caller branches.
|
|
3918
|
+
*/
|
|
3919
|
+
interface GraphQLResponse<T = unknown> {
|
|
3920
|
+
data: T | null;
|
|
3921
|
+
errors?: ReadonlyArray<Record<string, unknown>>;
|
|
533
3922
|
}
|
|
534
3923
|
/**
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
* so
|
|
539
|
-
* (
|
|
3924
|
+
* The minimal subset of an {@link AtlaSentClient}-like object this
|
|
3925
|
+
* module needs: a `fetch`-compatible HTTP function and a base URL.
|
|
3926
|
+
*
|
|
3927
|
+
* Passed explicitly so the v2 module never reaches into v1 internals
|
|
3928
|
+
* (and so callers can plug in a custom fetch for testing / edge
|
|
3929
|
+
* runtimes / Node fetch wrappers).
|
|
540
3930
|
*/
|
|
541
|
-
|
|
3931
|
+
interface V2Transport {
|
|
3932
|
+
/** Base URL (no trailing slash), e.g. `https://api.atlasent.io`. */
|
|
3933
|
+
baseUrl: string;
|
|
3934
|
+
/** Bearer API key (without the `Bearer ` prefix). */
|
|
3935
|
+
apiKey: string;
|
|
3936
|
+
/** A `fetch`-like function. Defaults to global `fetch` if omitted. */
|
|
3937
|
+
fetch?: typeof fetch;
|
|
3938
|
+
}
|
|
542
3939
|
/**
|
|
543
|
-
*
|
|
544
|
-
* (zero-indexed: `attempt = 0` is the first retry, i.e. the second
|
|
545
|
-
* total request). Uses capped exponential backoff with full jitter.
|
|
3940
|
+
* `POST /v1/evaluate/batch` — V2-D3.
|
|
546
3941
|
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
* server's hint is treated as a floor so we never retry sooner than
|
|
550
|
-
* the server asked.
|
|
3942
|
+
* One round-trip for up to {@link V2_MAX_BATCH_ITEMS} evaluate items.
|
|
3943
|
+
* Items are returned in input order — `response.items[i].index === i`.
|
|
551
3944
|
*
|
|
552
|
-
* @
|
|
553
|
-
* @
|
|
554
|
-
* @
|
|
555
|
-
*
|
|
556
|
-
* return values in `[0, 1)` to preserve the
|
|
557
|
-
* distribution.
|
|
3945
|
+
* @throws {FeatureNotEnabledError} When the tenant `v2_batch` flag is off (404).
|
|
3946
|
+
* @throws {AtlaSentError} For any other transport / HTTP failure.
|
|
3947
|
+
* @throws {TypeError} When `items` is empty, exceeds the cap, or
|
|
3948
|
+
* `batchId` is not a valid UUID.
|
|
558
3949
|
*/
|
|
559
|
-
declare function
|
|
3950
|
+
declare function evaluateMany(transport: V2Transport, req: EvaluateManyRequest): Promise<EvaluateBatchResponse>;
|
|
560
3951
|
/**
|
|
561
|
-
*
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
3952
|
+
* Callbacks consumed by {@link authorizeStream}.
|
|
3953
|
+
*/
|
|
3954
|
+
interface AuthorizeStreamHandlers {
|
|
3955
|
+
onDecision?: (frame: StreamDecisionFrame) => void;
|
|
3956
|
+
onError?: (frame: StreamErrorFrame) => void;
|
|
3957
|
+
}
|
|
3958
|
+
/**
|
|
3959
|
+
* `POST /v1/evaluate/stream` — V2-D4.
|
|
565
3960
|
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
* ```
|
|
3961
|
+
* Streams `event: decision` frames in input order. Per-item RPC
|
|
3962
|
+
* failures arrive as `event: error` frames and do not tear down the
|
|
3963
|
+
* stream (V2-D7 async semantics). Resolves with the terminal
|
|
3964
|
+
* `event: complete` payload.
|
|
3965
|
+
*
|
|
3966
|
+
* @throws {FeatureNotEnabledError} When the tenant `v2_streaming` flag is off.
|
|
3967
|
+
* @throws {AtlaSentError} For transport failures, including the stream
|
|
3968
|
+
* closing without a `complete` frame.
|
|
575
3969
|
*/
|
|
576
|
-
declare function
|
|
3970
|
+
declare function authorizeStream(transport: V2Transport, req: EvaluateManyRequest, handlers?: AuthorizeStreamHandlers): Promise<StreamComplete>;
|
|
577
3971
|
/**
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
*
|
|
3972
|
+
* `POST /v1/graphql` — V2-D2 + V2-D8.
|
|
3973
|
+
*
|
|
3974
|
+
* Bearer-only auth (no query-param). Wave A schema is read-only
|
|
3975
|
+
* (`recentEvaluations(limit)` + `activeBundle`). Server enforces the
|
|
3976
|
+
* V2-D8 OR-gate (`audit:read` OR `policy:read`) at request layer and
|
|
3977
|
+
* a per-resolver AND-gate at field resolution time.
|
|
3978
|
+
*
|
|
3979
|
+
* Resolver-level errors surface on `response.errors` — the SDK does
|
|
3980
|
+
* not throw on them so callers can inspect partial data.
|
|
3981
|
+
*
|
|
3982
|
+
* @throws {FeatureNotEnabledError} When the tenant `v2_graphql` flag is off.
|
|
3983
|
+
* @throws {AtlaSentError} For transport / HTTP failures.
|
|
3984
|
+
* @throws {TypeError} When `query` is empty or the body exceeds the 1MB cap.
|
|
581
3985
|
*/
|
|
582
|
-
declare function
|
|
3986
|
+
declare function graphql<T = unknown>(transport: V2Transport, req: GraphQLRequest): Promise<GraphQLResponse<T>>;
|
|
583
3987
|
|
|
584
3988
|
/**
|
|
585
3989
|
* @atlasent/sdk — execution-time authorization for AI agents.
|
|
586
3990
|
*
|
|
587
|
-
*
|
|
3991
|
+
* The canonical execution-boundary surface is two forms of the same
|
|
3992
|
+
* contract. Both mint and verify a Permit end-to-end; both fail closed.
|
|
3993
|
+
* Pick the form that fits the call site.
|
|
3994
|
+
*
|
|
3995
|
+
* `protect` — the primitive. Returns the verified {@link Permit} so
|
|
3996
|
+
* the caller can pass it across a boundary, persist it alongside
|
|
3997
|
+
* their own record, or interleave it with non-trivial control flow:
|
|
588
3998
|
*
|
|
589
3999
|
* ```ts
|
|
590
4000
|
* import atlasent from "@atlasent/sdk";
|
|
591
4001
|
*
|
|
592
4002
|
* const permit = await atlasent.protect({
|
|
593
4003
|
* agent: "deploy-bot",
|
|
594
|
-
* action: "
|
|
4004
|
+
* action: "production.deploy",
|
|
595
4005
|
* context: { commit, approver },
|
|
596
4006
|
* });
|
|
4007
|
+
* // permit is verified end-to-end. Execute the action.
|
|
4008
|
+
* ```
|
|
4009
|
+
*
|
|
4010
|
+
* `withPermit` — the lexically-scoped form. Binds the action body to
|
|
4011
|
+
* the permit's lifetime via a callback so the call site reads as
|
|
4012
|
+
* "execute this body under a permit":
|
|
4013
|
+
*
|
|
4014
|
+
* ```ts
|
|
4015
|
+
* const result = await atlasent.withPermit(
|
|
4016
|
+
* { agent: "deploy-bot", action: "production.deploy",
|
|
4017
|
+
* context: { commit, approver } },
|
|
4018
|
+
* async (permit) => runDeploy(commit, { permitId: permit.permitId }),
|
|
4019
|
+
* );
|
|
4020
|
+
* ```
|
|
4021
|
+
*
|
|
4022
|
+
* `requirePermit` — descriptor form for dangerous operations carrying
|
|
4023
|
+
* `resource_id` + `environment`. The executor only runs when AtlaSent
|
|
4024
|
+
* authorizes it end-to-end:
|
|
4025
|
+
*
|
|
4026
|
+
* ```ts
|
|
4027
|
+
* await atlasent.requirePermit(
|
|
4028
|
+
* { action_type: "database.table.drop", actor_id: "agent:code-agent",
|
|
4029
|
+
* resource_id: "prod-db.users", environment: "production",
|
|
4030
|
+
* context: { reversibility: "irreversible" } },
|
|
4031
|
+
* async () => { await db.raw("DROP TABLE users"); },
|
|
4032
|
+
* );
|
|
597
4033
|
* ```
|
|
598
4034
|
*
|
|
599
4035
|
* Named exports remain available for the lower-level
|
|
@@ -605,16 +4041,24 @@ declare function mergePolicy(policy: RetryPolicy): Required<RetryPolicy>;
|
|
|
605
4041
|
*
|
|
606
4042
|
* ```ts
|
|
607
4043
|
* import atlasent from "@atlasent/sdk";
|
|
608
|
-
* await atlasent.protect({ ... });
|
|
4044
|
+
* const permit = await atlasent.protect({ ... }); // primitive
|
|
4045
|
+
* await atlasent.withPermit({ ... }, async (permit) => …); // scoped form
|
|
4046
|
+
* await atlasent.requirePermit({ ... }, executor); // descriptor form
|
|
609
4047
|
* ```
|
|
610
4048
|
*/
|
|
611
4049
|
declare const atlasent: {
|
|
612
4050
|
readonly protect: typeof protect;
|
|
4051
|
+
readonly withPermit: typeof withPermit;
|
|
4052
|
+
readonly deployGate: typeof deployGate;
|
|
613
4053
|
readonly configure: typeof configure;
|
|
4054
|
+
readonly requirePermit: typeof requirePermit;
|
|
4055
|
+
readonly classifyCommand: typeof classifyCommand;
|
|
614
4056
|
readonly verifyBundle: typeof verifyBundle;
|
|
4057
|
+
readonly PRODUCTION_DEPLOY_ACTION: "production.deploy";
|
|
4058
|
+
readonly DEPLOYMENT_PRODUCTION_ACTION: "deployment.production";
|
|
615
4059
|
readonly AtlaSentClient: typeof AtlaSentClient;
|
|
616
4060
|
readonly AtlaSentError: typeof AtlaSentError;
|
|
617
4061
|
readonly AtlaSentDeniedError: typeof AtlaSentDeniedError;
|
|
618
4062
|
};
|
|
619
4063
|
|
|
620
|
-
export { type ApiKeySelfResponse,
|
|
4064
|
+
export { type ActionFreeze, type ActionTypeOverrideStat, type ActorOverrideStat, type AmountThreshold, type AnomalyActionType, type AnomalyResponseEvent, type AnomalyResponseRule, type AnomalyType, ApiKeySelfResponse, type ApplyPolicySyncResponse, type ApprovalArtifactV1, type ApprovalConcentrationAnalysis, type ApprovalIssuer, type ApprovalProvenance, type ApprovalQuorumV1, type ApprovalReference, type ApprovalReviewer, type ApproveBudgetExceptionRequest, type ApproverBreakdown, AtlaSentClient, AtlaSentClientOptions, AtlaSentDeniedError, AtlaSentError, type AuditBundle, AuditEventsQuery, AuditEventsResult, AuditExportRequest, AuditExportResult, type AuthenticateConnectorInput, type AuthenticateConnectorResponse, type AuthorizeStreamHandlers, type AutonomousBoundsDenyCode, type AutonomousExecutionBounds, type AutonomousExecutionCheckResult, type AutonomousExecutionRecord, type BudgetConstraintCheckResult, type BudgetDenyCode, type BudgetExceptionRequest, type BudgetExceptionStatus, type BudgetLimit, type BudgetPolicy, type BudgetScope, type BudgetSpendingState, type BudgetViolation, type BudgetaryDriftAnalysis, type BundleVerificationResult, type ComplianceEvidenceRun, type ComplianceEvidenceSummary, type ComplianceFramework, type ComplianceRunStatus, type ComputeOrgRiskOptions, type ComputeOrgRiskResponse, type ConcentrationAlert, type ConnectedSystemRow, type ConnectorAuditLogEntry, type ConnectorCredentialRow, type ConnectorCredentialType, type ConnectorEnforcementEventInput, type ConnectorEnforcementPolicy, type ConnectorEnforcementResult, type ConnectorRow, type ConnectorStatus, type ConnectorSyncState, type ConnectorType, type CreateAnomalyResponseRuleRequest, type CreateBudgetExceptionRequest, type CreateGraphEdgeInput, type CreateGraphNodeInput, type CreateImpersonationGrantRequest, type CreateOverrideRequest, type CreateRegulatoryEscalationRequest, type CreateWebhookSubscriptionRequest, type CrossOrgImpersonationGrant, type CrossOrgPermissionCheckListParams, type CrossOrgPermissionCheckRequest, type CrossOrgPermissionCheckResult, type CrossOrgTrustHop, type CurrencyCode, DEFAULT_INCENTIVE_CONFIG, DEFAULT_RISK_TIER_THRESHOLDS, type DelegationPropagationSummary, DeployGateRequest, DeployGateResponse, type DisputeOrigin, type DisputeRecord, type DisputeReversalSummary, type DisputeStatus, type EconomicEvidenceBundle, type EmergencyFreeze, type EmergencyOverrideActionRow, type EnforcementAction, type EnforcementQuorumConfig, type EnforcementWebhookEvent, type EvaluateBatchItem, type EvaluateBatchResponse, type EvaluateManyRequest, EvaluatePreflightResponse, EvaluateRequest, EvaluateResponse, type EvidenceBundleSignableContent, type EvidenceBundleVerificationResult, type EvidenceControl, type EvidenceControlStatus, type EvidencePurpose, type ExecutionAnomaly, type ExecutionApproverRow, type ExecutionCeiling, FeatureNotEnabledError, type FeatureNotEnabledErrorInit, type FinancialActionClass, type FinancialActionType, type FinancialExecutionRecord, type FinancialExecutionStatus, type FinancialGovernanceSummary, type FinancialQuorumDenyCode, type FinancialQuorumInput, type FinancialQuorumPolicy, type FinancialQuorumResult, type FinancialRiskScore, type FinancialRiskTier, type FinancialRoleRequirement, type GetLatestOrgRiskResponse, GetPermitResponse, type GovernanceBehaviorPattern, GovernanceEnforcementError, type GovernanceEnforcementErrorInit, type GovernanceEvent, type GovernanceGate, type GovernanceGraphQueryParams, type GovernanceGraphQueryResponse, type GovernanceGraphQueryType, type GovernanceGraphResultRow, type GovernanceSignalAction, type GovernanceWebhookEvent, type GraphEdge, type GraphEdgeType, type GraphNode, type GraphNodeType, type GraphQLRequest, type GraphQLResponse, type HitlAiUnavailableFallback, type HitlApprovalRecord, type HitlApproveRequest, type HitlApproverPoolEntry, type HitlApproverType, type HitlChainHop, type HitlCreateRequest, type HitlDetailResponse, type HitlEscalateRequest, type HitlEscalation, type HitlFallbackDecision, type HitlHeterogeneousQuorumExtension, type HitlHeterogeneousQuorumTally, type HitlListResponse, type HitlQuorumProgress, type HitlQuorumTier, type HitlRejectRequest, type HitlRespondRequest, type HitlStatus, type IdentityAssertionBinding, type IdentityAssertionV1, type IdentityIssuer, type IdentityIssuerKey, type IdentitySubject, type IdentityTrustedIssuersConfig, type ImpersonationToken, type ImpersonationValidationResult, type IncentiveAlignmentConfig, type IncentiveSignal, type IncentiveSignalType, type IncidentChainActorEntry, type IncidentChainEvidenceRow, type IncidentChainExecutionRow, type IncidentTimelineResponse, type InstallConnectorInput, type InstallConnectorResponse, type LegacyEvaluateRequest, type LegacyEvaluateResponse, type LiabilityAttributionInput, type LiabilityAttributionRecord, type LiabilityChainValidation, type LiabilityClassification, type LiabilityEdge, type LiabilityNode, type LiabilityParty, type LiabilityPartyRole, type LiabilityVisualization, type ListConnectorsResponse, type ListEnforcementPoliciesResponse, type ListEvidenceRunsResponse, type ListGraphEdgesResponse, type ListGraphNodesResponse, type ListHitlEscalationsRequest, type ListHitlEscalationsResponse, type ListOrgRiskHistoryResponse, ListPermitsRequest, ListPermitsResponse, type ListPolicySyncRunsResponse, type ListWebhookDeliveriesResponse, type ListWebhookSubscriptionsResponse, type MisalignmentAlert, type OrgRiskLevel, type OrgRiskScore, type OverrideAnalytics, type OverrideEvent, type OverrideEventType, type OverrideEventsResponse, type OverrideListResponse, type OverrideStatus, type OverrideV1, Permit, type PermitV1, PermitValidResponse, type PolicyBundleEntry, type PolicyRef, type PolicySyncDiff, type PolicySyncRun, type PolicySyncStatus, type PrincipalKind, type ProductionDeployerRow, type ProofEvaluationSummary, type ProofPayload, type ProofResponse, ProtectRequest, type ProtectedAction, type QuorumBypassConnectorRow, type QuorumIndependence, type QuorumPolicy, type QuorumProof, type QuorumRoleRequirement, RateLimitState, type RecordSignalActionRequest, type RecordSignalOutcomeRequest, type RegulatoryAuthorityLevel, type RegulatoryEscalation, type RegulatoryEscalationStatus, type ReversalStage, type ReversalWorkflow, type RevokeConnectorResponse, RevokePermitByIdInput, RevokePermitByIdResponse, RevokePermitRequest, RevokePermitResponse, type RiskFactor, type RiskTierThreshold, type RiskTimelinePoint, type RotateCredentialsResponse, type SOC2ControlId, type SandboxDiff, type SandboxDiffEmpty, type SandboxDiffPerTable, type SandboxDiffResponse, type SandboxRunMode, type SandboxRunStatus, type SandboxRunWrite, type SandboxWriteOp, type SignalActionSummary, type SignalActionType, type SpendingConstraint, type StreamComplete, type StreamDecisionFrame, type StreamErrorFrame, StreamEvent, StreamOptions, type SubmitPolicySyncRequest, type SubmitPolicySyncResponse, type SyncConnectorResponse, type TriggerAnomalyResponseRequest, type TriggerEvidenceRunRequest, type TriggerEvidenceRunResponse, type UpsertEnforcementPolicyInput, type UpsertEnforcementPolicyResponse, type UserApprovalRow, type V2EvaluateRequest, type V2EvaluateResponse, type V2Feature, type V2Transport, V2_BATCH_PATH, V2_GRAPHQL_MAX_DEPTH, V2_GRAPHQL_PATH, V2_MAX_BATCH_ITEMS, V2_MAX_BODY_BYTES, V2_STREAM_PATH, type VerifyBundleOptions, type VerifyKey, VerifyPermitByIdResponse, VerifyPermitRequest, VerifyPermitResponse, type WebhookDelivery, type WebhookDeliveryStatus, type WebhookPayload, type WebhookSubscription, WebhookVerificationError, type WeightDistribution, assertWebhook, authorizeStream, budgetUtilizationSeverity, buildLiabilityChain, buildLiabilityVisualization, buildRiskTimeline, buildSignableContent, canonicalJSON, canonicalizeForEvidence, checkAutonomousBounds, checkBudgetConstraints, clampTokenDuration, classifyCommand, classifyRiskTier, computeApprovalRiskScore, computeEscalatedApprovalCount, computeExposureScore, computeGovernanceHealthScore, computeHHI, computeLiabilityWeights, computeOverallRiskScore, computeOverrideScore, computeRemediationUrgency, computeSignalEngagementRate, configure, atlasent as default, delegationPropagationHadEffect, deployGate, detectAutonomousAnomaly, detectMisalignedIncentives, detectSelfApproval, enforceAutonomousBounds, enforceBudgetConstraint, enforceEconomicGovernance, enforceFinancialQuorum, evaluateFinancialQuorum, evaluateMany, evidenceRunPasses, findPrimaryLiabilityParties, formatPolicySyncDiff, graphql, hhiToConcentrationScore, highestSeverityAction, hitlRequiredApproverCount, isBudgetExceptionActive, isBudgetExceptionTerminal, isEscalationSlaBreached, isFreezeActive, isImpersonationGrantUsable, isPolicySyncTerminal, isRegulatoryEscalationTerminal, isSandboxDiffPopulated, isSubstantiveSignalResponse, matchAnomalyRules, nonPassingControls, normalizeEvaluateRequest, normalizeEvaluateResponse, protect, requirePermit, scoreToRiskTier, serializeSignableContent, signedBytesFor, summarizeCrossOrgPermission, transitionDispute, transitionReversal, validateLiabilityChain, verifyAuditBundle, verifyBundle, verifyEvidenceBundleStructure, verifyWebhook, verifyWebhookSignature, withPermit, withinAutonomousCeiling };
|