@registrystack/client 0.38.0 → 0.40.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/breg/index.d.ts CHANGED
@@ -7,6 +7,13 @@ export declare class BaseRegistryClient {
7
7
  ready(): Promise<CompleteOutcome>
8
8
  openapi(accessProfile?: string | undefined | null): Promise<RawOutcome>
9
9
  registryMetadata(accessProfile?: string | undefined | null): Promise<RawOutcome>
10
+ statisticsLive(dataset: string, from?: string | undefined | null, to?: string | undefined | null, accessProfile?: string | undefined | null, format?: string | undefined | null): Promise<RawOutcome>
11
+ statisticsReleases(dataset: string, top?: number | undefined | null, skipToken?: string | undefined | null, accessProfile?: string | undefined | null): Promise<RawOutcome>
12
+ statisticsLatestRelease(dataset: string, period: string, selection: string, accessProfile?: string | undefined | null, format?: string | undefined | null): Promise<RawOutcome>
13
+ statisticsReleaseVersion(dataset: string, period: string, version: number, accessProfile?: string | undefined | null, format?: string | undefined | null): Promise<RawOutcome>
14
+ statisticsReleaseSeries(dataset: string, from: string, to: string, selection: string, accessProfile?: string | undefined | null, format?: string | undefined | null): Promise<RawOutcome>
15
+ statisticsPublish(dataset: string, period: string, status: string, accessProfile: string, idempotencyKey: string): Promise<RawOutcome>
16
+ statisticsWithdraw(dataset: string, period: string, version: number, reason: string, accessProfile: string, idempotencyKey: string): Promise<RawOutcome>
10
17
  registryContract(accessProfile?: string | undefined | null): Promise<BRegMetadata>
11
18
  entitySchema(entityIdentifier: string, accessProfile?: string | undefined | null): Promise<RawOutcome>
12
19
  /** Retrieve one bounded first page of record revisions as inert JSON. */
@@ -30,8 +37,29 @@ export declare class BaseRegistryClient {
30
37
  lookupRecord(entityRoute: string, selector: string, values?: any | undefined | null, options?: any | undefined | null): Promise<CompleteOutcome>
31
38
  /** Fetch opaque target conditions for one metadata-selected action. */
32
39
  actionTargetConditions(binding: BRegImmediateActionBinding, inputs: any): Promise<BRegActionTargetConditions>
33
- /** Invoke one metadata-selected immediate action without automatic retry. */
40
+ /**
41
+ * Invoke one metadata-selected immediate action. An invocation whose
42
+ * outcome is unknown is resent identically under the same key, at most
43
+ * `maxMutationRetries` times.
44
+ */
34
45
  invokeAction(binding: BRegImmediateActionBinding, inputs: any, idempotencyKey: string, conditions?: BRegActionTargetConditions | undefined | null): Promise<CompleteOutcome>
46
+ /**
47
+ * Prepare inert invocation evidence before any token acquisition or I/O.
48
+ * Persist `toBytes` before invoking so a lost response can be recovered.
49
+ */
50
+ prepareAction(binding: BRegImmediateActionBinding, inputs: any, idempotencyKey: string, conditions?: BRegActionTargetConditions | undefined | null): BRegPreparedAction
51
+ /**
52
+ * Revalidate saved invocation evidence against freshly selected authority
53
+ * and the caller's original inputs and key. The saved target conditions
54
+ * are reused exactly; this never fetches conditions or sends a request.
55
+ */
56
+ recoverAction(binding: BRegImmediateActionBinding, prepared: BRegPreparedAction, inputs: any, idempotencyKey: string): BRegRecoveredAction
57
+ /**
58
+ * Explicitly send a recovered invocation under its original key. An
59
+ * invocation whose outcome is unknown is resent identically under that
60
+ * key, at most `maxMutationRetries` times.
61
+ */
62
+ executeRecoveredAction(binding: BRegImmediateActionBinding, recovered: BRegRecoveredAction): Promise<CompleteOutcome>
35
63
  createRecord(binding: BRegCreateBinding, data: any, idempotencyKey: string, formatValue?: string | undefined | null): Promise<CompleteOutcome>
36
64
  /** Prepare inert Create evidence before any token acquisition or I/O. */
37
65
  prepareCreate(binding: BRegCreateBinding, data: any, idempotencyKey: string, formatValue?: string | undefined | null): BRegPreparedCreate
@@ -40,7 +68,11 @@ export declare class BaseRegistryClient {
40
68
  /** Explicitly send a recovered Create request with fresh authority. */
41
69
  executeRecoveredCreate(binding: BRegCreateBinding, recovered: BRegRecoveredCreate): Promise<CompleteOutcome>
42
70
  patchRecord(binding: BRegPatchBinding, recordIdentifier: string, etag: string, operations: any, idempotencyKey: string, formatValue?: string | undefined | null): Promise<CompleteOutcome>
43
- /** Execute one metadata-selected atomic batch without automatic retry. */
71
+ /**
72
+ * Execute one metadata-selected atomic batch. A batch whose outcome is
73
+ * unknown is resent identically under the same key, at most
74
+ * `maxMutationRetries` times.
75
+ */
44
76
  batchRecords(binding: BRegBatchBinding, request: any, idempotencyKey: string): Promise<CompleteOutcome>
45
77
  /**
46
78
  * Announce one whole input and open a durable ingestion run for it. The
@@ -109,6 +141,12 @@ export declare class BaseRegistryClient {
109
141
  actionTargetConditionsJson(binding: BRegImmediateActionBinding, inputsJson: string): Promise<BRegActionTargetConditions>
110
142
  /** Invoke an action from exact JSON and preserve exact receipt values. */
111
143
  invokeActionJson(binding: BRegImmediateActionBinding, inputsJson: string, idempotencyKey: string, conditions?: BRegActionTargetConditions | undefined | null): Promise<JsonOutcome>
144
+ /** Prepare inert invocation evidence from exact action-input JSON. */
145
+ prepareActionJson(binding: BRegImmediateActionBinding, inputsJson: string, idempotencyKey: string, conditions?: BRegActionTargetConditions | undefined | null): BRegPreparedAction
146
+ /** Revalidate saved invocation evidence against exact original input JSON. */
147
+ recoverActionJson(binding: BRegImmediateActionBinding, prepared: BRegPreparedAction, inputsJson: string, idempotencyKey: string): BRegRecoveredAction
148
+ /** Explicitly send a recovered invocation and preserve exact receipt values. */
149
+ executeRecoveredActionJson(binding: BRegImmediateActionBinding, recovered: BRegRecoveredAction): Promise<JsonOutcome>
112
150
  createRecordJson(binding: BRegCreateBinding, dataJson: string, idempotencyKey: string, formatValue?: string | undefined | null): Promise<JsonOutcome>
113
151
  /** Prepare inert Create evidence from exact JSON text. */
114
152
  prepareCreateJson(binding: BRegCreateBinding, dataJson: string, idempotencyKey: string, formatValue?: string | undefined | null): BRegPreparedCreate
@@ -224,6 +262,8 @@ export declare class BRegMetadata {
224
262
  get immediateActions(): any
225
263
  /** Original caller-filtered action metadata as exact JSON text. */
226
264
  get actionsJson(): string | null
265
+ /** Validated caller-filtered statistical dataset descriptions, without entity authority. */
266
+ get statisticalDatasets(): any | null
227
267
  /** Descriptive change-request capability for one entity, when advertised. */
228
268
  changeRequestCapability(entityIdentifier: string): any | null
229
269
  get registryIdentifier(): string
@@ -244,6 +284,19 @@ export type Metadata = BRegMetadata
244
284
  export declare class BRegPatchBinding {}
245
285
  export type PatchBinding = BRegPatchBinding
246
286
 
287
+ /**
288
+ * Inert original immediate-action invocation evidence. The bytes carry the
289
+ * inputs, saved target conditions, and idempotency key, but no token or
290
+ * executable metadata authority.
291
+ */
292
+ export declare class BRegPreparedAction {
293
+ /** Restore bounded inert evidence previously returned by `toBytes`. */
294
+ static fromBytes(bytes: Buffer): BRegPreparedAction
295
+ /** Copy the exact evidence bytes for owner-protected persistence. */
296
+ toBytes(): Buffer
297
+ }
298
+ export type PreparedAction = BRegPreparedAction
299
+
247
300
  /**
248
301
  * Inert original Create request evidence. The bytes carry values and an
249
302
  * idempotency key, but no token or executable metadata authority.
@@ -268,6 +321,14 @@ export declare class BRegPreparedLifecycle {
268
321
  }
269
322
  export type PreparedLifecycle = BRegPreparedLifecycle
270
323
 
324
+ /**
325
+ * A recovered immediate-action invocation and key. This remains inert until
326
+ * `executeRecoveredAction` is explicitly called with freshly selected
327
+ * authority.
328
+ */
329
+ export declare class BRegRecoveredAction {}
330
+ export type RecoveredAction = BRegRecoveredAction
331
+
271
332
  /**
272
333
  * A recovered Create request, key, and representation. This remains inert
273
334
  * until `executeRecoveredCreate` is explicitly called with fresh authority.
@@ -369,6 +430,7 @@ export interface RawOutcome {
369
430
  mediaType: string
370
431
  traceId: string
371
432
  etag?: string
433
+ reprDigest?: string
372
434
  }
373
435
 
374
436
  /** Authenticated BReg webhook metadata and exact body. */
@@ -13,15 +13,23 @@ export interface CaseworkClientConfig {
13
13
  maxResponseBytes?: SafeInteger | null
14
14
  userAgent?: string | null
15
15
  trustedRootCertificates?: string | null
16
+ /**
17
+ * How many times an idempotency-keyed mutation whose outcome is unknown is
18
+ * resent, identically and under the same key, before its error is
19
+ * returned: a whole number from 0 to 2, default 2; 0 sends it once. Reads,
20
+ * unkeyed operations, and review request create and cancel are never
21
+ * resent. Any other value is a `configuration` error.
22
+ */
23
+ maxMutationRetries?: SafeInteger | null
16
24
  }
17
25
 
18
- export type InboxView = 'mine' | 'my_teams' | 'team_holdings' | 'overdue' | 'completed_by_me'
26
+ export type InboxView = 'mine' | 'my-teams' | 'team-holdings' | 'overdue' | 'completed-by-me'
19
27
  export type OccurrenceKind = 'review' | 'application'
20
- export type OccurrenceState = 'open' | 'claimed' | 'waiting_applicant' | 'waiting_application' | 'synchronizing' | 'completed' | 'superseded' | 'cancelled'
28
+ export type OccurrenceState = 'open' | 'claimed' | 'waiting-applicant' | 'waiting-application' | 'synchronizing' | 'completed' | 'superseded' | 'cancelled'
21
29
  export type OperationName = string
22
30
  export type AttemptState = 'pending' | 'uncertain' | 'completed' | 'refused'
23
- export type PageStatus = 'complete' | 'budget_exhausted' | 'source_unavailable'
24
- export type HistoryKind = 'observed' | 'opened' | 'claimed' | 'assigned' | 'delegated' | 'caseload_moved' | 'clock_reminder' | 'clock_step_applied' | 'clock_recomputed' | 'released' | 'draft_saved' | 'attempt_reserved' | 'attempt_uncertain' | 'action_completed' | 'attempt_settled' | 'superseded' | 'completed'
31
+ export type PageStatus = 'complete' | 'budget-exhausted' | 'source-unavailable'
32
+ export type HistoryKind = 'observed' | 'opened' | 'claimed' | 'assigned' | 'delegated' | 'caseload-moved' | 'clock-reminder' | 'clock-step-applied' | 'clock-recomputed' | 'released' | 'draft-saved' | 'attempt-reserved' | 'attempt-uncertain' | 'action-completed' | 'attempt-settled' | 'superseded' | 'completed'
25
33
 
26
34
  export interface IssuerPrincipal { issuer: string; subject: string }
27
35
  export type TaskGrantBounds = { type: 'evidence'; requirement: string } | { type: 'breg'; permissions: ReadonlyArray<TaskPermission> } | { type: 'scheduling'; permissions: ReadonlyArray<SchedulingTaskPermission> }
@@ -94,14 +102,14 @@ export interface WorkItem {
94
102
  }
95
103
  export interface Page<T> { items: ReadonlyArray<T>; nextCursor?: string; status: PageStatus }
96
104
  export interface WorkItemPage extends Page<WorkItem> { servedQueues: ReadonlyArray<string> }
97
- export type DirectoryTargetPurpose = 'assignment' | 'absence_person' | 'absence_cover'
105
+ export type DirectoryTargetPurpose = 'assignment' | 'absence-person' | 'absence-cover'
98
106
  export type DirectoryTargetsQuery = {
99
107
  cursor?: string
100
108
  limit?: SafeInteger
101
109
  } & (
102
110
  | { purpose: 'assignment'; queue: string; personIssuer?: never; personSubject?: never }
103
- | { purpose: 'absence_person'; queue?: never; personIssuer?: never; personSubject?: never }
104
- | { purpose: 'absence_cover'; queue?: never; personIssuer: string; personSubject: string }
111
+ | { purpose: 'absence-person'; queue?: never; personIssuer?: never; personSubject?: never }
112
+ | { purpose: 'absence-cover'; queue?: never; personIssuer: string; personSubject: string }
105
113
  )
106
114
  export type DirectoryTargetPage = Page<DirectoryMember>
107
115
  export type ListWorkItemsQuery = {
@@ -167,11 +175,11 @@ export interface HistoryEntryBase {
167
175
  profileId: string
168
176
  }
169
177
  export interface AttemptReservedHistoryEntry extends HistoryEntryBase {
170
- kind: 'attempt_reserved'
178
+ kind: 'attempt-reserved'
171
179
  detail: JsonObject & { attemptId: string; bindingReference: string; operation: OperationName }
172
180
  }
173
181
  /**
174
- * An attempt_uncertain detail takes one of three shapes: recovery left the
182
+ * An attempt-uncertain detail takes one of three shapes: recovery left the
175
183
  * attempt uncertain, the source definitively refused it, or an operator marked
176
184
  * an expired pending attempt uncertain. reason is the original decision reason.
177
185
  */
@@ -186,19 +194,19 @@ export type AttemptUncertainHistoryDetail = JsonObject & {
186
194
  | { operatorReason: string; decidedBy: string; originalActor: IssuerPrincipal; originalProfileId: string; definitivelyRefused?: never }
187
195
  )
188
196
  export interface AttemptUncertainHistoryEntry extends HistoryEntryBase {
189
- kind: 'attempt_uncertain'
197
+ kind: 'attempt-uncertain'
190
198
  detail: AttemptUncertainHistoryDetail
191
199
  }
192
200
  export interface ActionCompletedHistoryEntry extends HistoryEntryBase {
193
- kind: 'action_completed'
201
+ kind: 'action-completed'
194
202
  detail: JsonObject & { attemptId: string; bindingReference: string; sourceRevision: string; sourceReceipt: SourceReceipt }
195
203
  }
196
204
  export interface AttemptSettledHistoryEntry extends HistoryEntryBase {
197
- kind: 'attempt_settled'
198
- detail: JsonObject & { attemptId: string; bindingReference: string; operation: OperationName; outcome: 'applied' | 'not_applied'; reason: string; decidedBy: string }
205
+ kind: 'attempt-settled'
206
+ detail: JsonObject & { attemptId: string; bindingReference: string; operation: OperationName; outcome: 'applied' | 'not-applied'; reason: string; decidedBy: string }
199
207
  }
200
208
  export interface OtherHistoryEntry extends HistoryEntryBase {
201
- kind: Exclude<HistoryKind, 'attempt_reserved' | 'attempt_uncertain' | 'action_completed' | 'attempt_settled'>
209
+ kind: Exclude<HistoryKind, 'attempt-reserved' | 'attempt-uncertain' | 'action-completed' | 'attempt-settled'>
202
210
  detail: JsonValue
203
211
  }
204
212
  export type HistoryEntry = AttemptReservedHistoryEntry | AttemptUncertainHistoryEntry | ActionCompletedHistoryEntry | AttemptSettledHistoryEntry | OtherHistoryEntry
@@ -220,9 +228,9 @@ export interface CalendarPolicy { id: string; timezone: string; workingWeekdays:
220
228
  export interface ClockReminder { id: string; workingDaysBefore: SafeInteger }
221
229
  export interface ClockStep { id: string; because: string; at: 'due'; action: { reassign: { queue: string } } }
222
230
  export type ClockPolicy = {
223
- scope: 'subject'; id: string; anchor: 'firstSubmittedAt'; completeOn: 'reviewCompleted'; after: { elapsed: string }; pauseWhile: ReadonlyArray<'awaitingApplicant'>
231
+ type: 'subject'; id: string; anchor: 'first-submitted-at'; completeOn: 'review-completed'; after: { elapsed: string }; pauseWhile: ReadonlyArray<'awaiting-applicant'>
224
232
  } | {
225
- scope: 'activity'; id: string; anchor: 'stageEnteredAt'; calendar: string; after: { workingDays: SafeInteger }; dueTime: string;
233
+ type: 'activity'; id: string; anchor: 'stage-entered-at'; calendar: string; after: { workingDays: SafeInteger }; dueTime: string;
226
234
  atRisk?: { workingDaysBefore: SafeInteger }; reminders?: ReadonlyArray<ClockReminder>; steps?: ReadonlyArray<ClockStep>
227
235
  }
228
236
  export interface SourcePolicy {
@@ -252,14 +260,14 @@ export interface AbsenceInput { person: IssuerPrincipal; from: string; until: st
252
260
  export interface AbsenceRecord extends AbsenceInput { absenceId: string; revision: SafeInteger }
253
261
  export interface AbsencesQuery { cursor?: string; limit?: SafeInteger }
254
262
  export interface AbsenceList { directoryRevision: SafeInteger; items: ReadonlyArray<AbsenceRecord>; nextCursor?: string }
255
- export interface AssignmentContext { owner?: IssuerPrincipal; assignedBy?: IssuerPrincipal; absenceIds: ReadonlyArray<string>; staffingDiagnostic?: 'no_cover_available' }
263
+ export interface AssignmentContext { owner?: IssuerPrincipal; assignedBy?: IssuerPrincipal; absenceIds: ReadonlyArray<string>; staffingDiagnostic?: 'no-cover-available' }
256
264
  export interface AssignmentRequest { assignee: IssuerPrincipal; reason?: string }
257
265
  export interface DelegateRequest { delegate: IssuerPrincipal; reason?: string }
258
266
  export interface CaseloadMoveRequest { from: IssuerPrincipal; to: IssuerPrincipal; queueId?: string; reason: string }
259
267
  export interface CaseloadItemSelection { itemId: string; expectedRevision: SafeInteger }
260
268
  export interface CaseloadApplyRequest { movement: CaseloadMoveRequest; items: ReadonlyArray<CaseloadItemSelection> }
261
269
  export interface CaseloadPreviewQuery { cursor?: string; limit?: SafeInteger }
262
- export interface CaseloadItemResult { itemId: string; result: 'moved' | 'not_visible' | 'not_eligible' | 'attempt_in_progress' | 'conflict'; revision?: SafeInteger }
270
+ export interface CaseloadItemResult { itemId: string; result: 'moved' | 'not-visible' | 'not-eligible' | 'attempt-in-progress' | 'conflict'; revision?: SafeInteger }
263
271
  export interface BootstrapDirectoryRequest {
264
272
  teamId: string
265
273
  staff: ReadonlyArray<IssuerPrincipal>
@@ -316,10 +324,23 @@ export type KnownCaseworkProblemCode =
316
324
  | 'work-item.source-unavailable'
317
325
  | 'work-item.superseded'
318
326
  export type CaseworkProblemCode = KnownCaseworkProblemCode | (string & {})
319
- export type CaseworkProtocolFailure = 'header_bounds' | 'trace_context' | 'media_type' | 'body' | 'problem' | 'status' | 'protocol'
327
+ export type CaseworkProtocolFailure = 'header-bounds' | 'trace-context' | 'media-type' | 'body' | 'problem' | 'status' | 'protocol'
320
328
 
321
329
  export class CaseworkClientError extends Error {
322
- readonly kind: 'configuration' | 'invalid_request' | 'transport' | 'problem' | 'protocol'
330
+ readonly kind: 'configuration' | 'invalid-request' | 'transport' | 'problem' | 'protocol'
331
+ /**
332
+ * Whether the request may have taken effect although this error was
333
+ * raised: a timeout or broken exchange after sending, an unusable answer,
334
+ * or a 5xx. When true, recover a keyed request by sending it again under
335
+ * the same idempotency key; a new key could apply it twice. False for a
336
+ * configuration or request defect, a connection never established, and
337
+ * every 4xx refusal. It is false for `410 idempotency.expired` too, but
338
+ * there an earlier attempt under the key committed and only its stored
339
+ * response was erased by retention: reconcile the original operation, by
340
+ * reading the item, review request, or directory, before choosing a new
341
+ * key.
342
+ */
343
+ readonly outcomeUnknown: boolean
323
344
  readonly code?: CaseworkProblemCode
324
345
  readonly detail?: string
325
346
  readonly status?: SafeInteger
@@ -327,13 +348,13 @@ export class CaseworkClientError extends Error {
327
348
  readonly originalAttemptId?: string
328
349
  readonly validation?: {
329
350
  readonly path: string
330
- readonly reason: 'kind_not_allowed' | 'reference_invalid' | 'object_required' | 'maximum_bytes_exceeded' | 'maximum_depth_exceeded' | 'schema_mismatch' | 'outcome_not_declared' | 'reason_required' | 'text_invalid' | 'result_not_declared' | 'result_required' | 'field_not_declared' | 'constraint_invalid' | 'constraint_violated'
351
+ readonly reason: 'kind-not-allowed' | 'reference-invalid' | 'object-required' | 'maximum-bytes-exceeded' | 'maximum-depth-exceeded' | 'schema-mismatch' | 'outcome-not-declared' | 'reason-required' | 'text-invalid' | 'result-not-declared' | 'result-required' | 'field-not-declared' | 'constraint-invalid' | 'constraint-violated'
331
352
  }
332
353
  readonly transportKind?: string
333
354
  readonly protocolFailure?: CaseworkProtocolFailure
334
355
  }
335
356
 
336
- export type ClockRuntimeState = 'running' | 'paused' | 'completed' | 'cancelled' | 'verification_pending' | 'source_facts_missing'
357
+ export type ClockRuntimeState = 'running' | 'paused' | 'completed' | 'cancelled' | 'verification-pending' | 'source-facts-missing'
337
358
  export type ClockNextEffect =
338
359
  | { kind: 'reminder'; id: string; at: string }
339
360
  | { kind: 'reassign'; id: string; at: string; because: string; queueId: string }
@@ -382,7 +403,7 @@ export interface ReviewRequestAccepted {
382
403
  policy: ReviewPolicyBinding
383
404
  submissionDigest: ContentDigest
384
405
  }
385
- export type ReviewRequestLifecycle = 'reviewing' | 'approved' | 'rejected' | 'changes_requested' | 'answered' | 'cancelled' | 'superseded'
406
+ export type ReviewRequestLifecycle = 'reviewing' | 'approved' | 'rejected' | 'changes-requested' | 'answered' | 'cancelled' | 'superseded'
386
407
  export interface ReviewRequestView extends ReviewRequestAccepted {
387
408
  requesterReference: string
388
409
  lifecycle: ReviewRequestLifecycle
@@ -390,7 +411,7 @@ export interface ReviewRequestView extends ReviewRequestAccepted {
390
411
  createdAt: string
391
412
  updatedAt: string
392
413
  }
393
- export type ReviewResultStatus = 'approved' | 'rejected' | 'changes_requested' | 'answered' | 'cancelled' | 'superseded'
414
+ export type ReviewResultStatus = 'approved' | 'rejected' | 'changes-requested' | 'answered' | 'cancelled' | 'superseded'
394
415
  export interface ReviewResult extends ReviewRequestAccepted {
395
416
  resultId: Uuid
396
417
  status: ReviewResultStatus
@@ -407,11 +428,30 @@ export interface ReviewResultFeedPage { items: ReadonlyArray<ReviewResultFeedEnt
407
428
  export interface ReviewCancelRequest { subject: ReviewSubjectBinding; reason: string }
408
429
  export type ReviewCancelResponse =
409
430
  | { outcome: 'cancelled'; result: ReviewResult }
410
- | { outcome: 'already_terminal'; result: ReviewResult }
431
+ | { outcome: 'already-terminal'; result: ReviewResult }
411
432
  export interface ReviewPageQuery { cursor?: Uuid; limit?: SafeInteger }
412
- export interface ReviewTaskQuery extends ReviewPageQuery { queue?: string }
433
+ export type ReviewTaskOwnership = 'assigned-to-me' | 'unclaimed'
434
+ export interface ReviewTaskQuery extends ReviewPageQuery { queue?: string; ownership?: ReviewTaskOwnership }
435
+ export interface SupervisoryReviewTaskQuery extends ReviewPageQuery { queue?: string; requestId?: Uuid }
436
+ export interface OwnReviewDecisionQuery extends ReviewPageQuery { queue?: string }
413
437
  export interface WorkItemHistoryQuery { cursor?: string; limit?: SafeInteger }
414
438
  export type ReviewerTaskState = 'open' | { held: { holder: IssuerPrincipal } } | 'decided'
439
+ export type ReviewDecisionType = 'approve' | 'reject' | 'changes-requested' | 'answer'
440
+ export interface ReviewDecisionReceipt {
441
+ policy: ReviewPolicyBinding
442
+ decision: ReviewDecisionType
443
+ outcome?: string
444
+ outcomeLabel?: string
445
+ decidedAt: string
446
+ }
447
+ export interface OwnReviewDecision {
448
+ taskId: Uuid
449
+ requestId: Uuid
450
+ queue: string
451
+ requesterReference: string
452
+ decisionReceipt: ReviewDecisionReceipt
453
+ }
454
+ export interface OwnReviewDecisionPage { items: ReadonlyArray<OwnReviewDecision>; nextCursor?: Uuid; status: PageStatus }
415
455
  export interface ReviewerTask {
416
456
  taskId: Uuid
417
457
  requestId: Uuid
@@ -422,9 +462,20 @@ export interface ReviewerTask {
422
462
  eligibleProfiles: ReadonlyArray<string>
423
463
  state: ReviewerTaskState
424
464
  decidedByCaller?: boolean
465
+ decisionReceipt?: ReviewDecisionReceipt
425
466
  }
426
467
  export interface ReviewTaskPage { items: ReadonlyArray<ReviewerTask>; nextCursor?: Uuid; status: PageStatus }
427
- export type ReviewSourceBindingStatus = 'current' | 'binding_changed'
468
+ export type SupervisoryReviewTaskState = 'open' | 'held' | 'decided'
469
+ export interface SupervisoryReviewTask {
470
+ taskId: Uuid
471
+ requestId: Uuid
472
+ queue: string
473
+ revision: SafeInteger
474
+ state: SupervisoryReviewTaskState
475
+ accountabilityEventId?: Uuid
476
+ }
477
+ export interface SupervisoryReviewTaskPage { items: ReadonlyArray<SupervisoryReviewTask>; nextCursor?: Uuid; status: PageStatus }
478
+ export type ReviewSourceBindingStatus = 'current' | 'binding-changed'
428
479
  export interface ReviewSourceProjection { binding: SourceBinding; displayReference?: string; display: Readonly<Record<string, JsonValue>> }
429
480
  export type ReviewTaskContextData =
430
481
  | { strategy: 'submitted'; snapshot: Readonly<Record<string, JsonValue>> }
@@ -447,7 +498,7 @@ export interface ReviewClockOccurrence {
447
498
  clockId: string
448
499
  requestId: Uuid
449
500
  correlation: ReviewClockCorrelation
450
- state: 'running' | 'paused' | 'completed' | 'cancelled' | 'source_facts_missing'
501
+ state: 'running' | 'paused' | 'completed' | 'cancelled' | 'source-facts-missing'
451
502
  policyDigest: ContentDigest
452
503
  anchorAt: string
453
504
  dueAt?: string
@@ -458,7 +509,7 @@ export interface ReviewTaskDraftInput { body: JsonValue }
458
509
  export interface ReviewTaskDraft { taskId: Uuid; author: IssuerPrincipal; body: JsonValue; revision: SafeInteger; updatedAt: string }
459
510
  export type ReviewerDecision =
460
511
  | { type: 'approve' }
461
- | { type: 'reject' | 'changes_requested' | 'answer'; outcome: string; reason?: string | null; result?: JsonObject | null }
512
+ | { type: 'reject' | 'changes-requested' | 'answer'; outcome: string; reason?: string | null; result?: JsonObject | null }
462
513
  export interface ReviewTaskDecisionRequest { decision: ReviewerDecision }
463
514
  export type ReviewHistoryAudience = 'reviewers' | 'requester'
464
515
  export interface ReviewNoteRequest { audience: ReviewHistoryAudience; note: string }
@@ -468,6 +519,7 @@ export interface ReviewAccountabilityRecord {
468
519
  eventId: Uuid; requestId: Uuid; taskId: Uuid; actorRef: string; actor: IssuerPrincipal
469
520
  profileId: string; decision: string; privateReason?: string; resultDigest?: string
470
521
  occurredAt: string; retainedUntil: string
522
+ decisionReceipt?: ReviewDecisionReceipt
471
523
  }
472
524
  export interface ReviewStagePolicy { id: string; queue: string; decidingProfiles: ReadonlyArray<string>; requiredApprovals: SafeInteger; excludeInitiator?: boolean; excludePreviousStageReviewers?: boolean }
473
525
  export interface ReviewRetentionPolicy { terminalDays: SafeInteger; accountabilityDays: SafeInteger }
@@ -480,7 +532,7 @@ export interface ReviewKindPolicySnapshot {
480
532
  retention: ReviewRetentionPolicy
481
533
  displaySchema: JsonValue
482
534
  resultSchema?: JsonValue
483
- outcomes?: ReadonlyArray<{ id: string; label: string; settlement: 'rejected' | 'changes_requested' | 'answered'; reasonRequired: boolean; resultRequired?: boolean }>
535
+ outcomes?: ReadonlyArray<{ id: string; label: string; settlement: 'rejected' | 'changes-requested' | 'answered'; reasonRequired: boolean; resultRequired?: boolean }>
484
536
  }
485
537
 
486
538
  export class CaseworkClient {
@@ -494,6 +546,8 @@ export class CaseworkClient {
494
546
  reviewKinds(token: string, profile: string): Promise<CaseworkOutcome<ReadonlyArray<ReviewKindPolicySnapshot>>>
495
547
  reviewKind(token: string, profile: string, kindId: string): Promise<CaseworkOutcome<ReviewKindPolicySnapshot>>
496
548
  reviewTasks(token: string, profile: string, query?: ReviewTaskQuery | null, sourceProfile?: string | null): Promise<CaseworkOutcome<ReviewTaskPage>>
549
+ supervisoryReviewTasks(token: string, profile: string, query?: SupervisoryReviewTaskQuery | null, sourceProfile?: string | null): Promise<CaseworkOutcome<SupervisoryReviewTaskPage>>
550
+ ownReviewDecisions(token: string, profile: string, query?: OwnReviewDecisionQuery | null, sourceProfile?: string | null): Promise<CaseworkOutcome<OwnReviewDecisionPage>>
497
551
  reviewTask(token: string, profile: string, taskId: Uuid, sourceProfile?: string | null): Promise<CaseworkOutcome<ReviewerTask>>
498
552
  reviewTaskContext(token: string, profile: string, taskId: Uuid, sourceProfile?: string | null): Promise<CaseworkOutcome<ReviewTaskContext>>
499
553
  previewReviewTaskTemplates(token: string, profile: string, sourceProfile: string, taskId: Uuid): Promise<CaseworkOutcome<TaskTemplatePreviews>>
@@ -12,6 +12,7 @@ class CaseworkClientError extends Error {
12
12
  super(envelope.message);
13
13
  this.name = 'CaseworkClientError';
14
14
  this.kind = envelope.kind;
15
+ this.outcomeUnknown = envelope.outcomeUnknown === true;
15
16
  for (const field of ['code', 'detail', 'status', 'traceId', 'originalAttemptId', 'validation', 'transportKind', 'protocolFailure']) {
16
17
  if (envelope[field] !== undefined && envelope[field] !== null) this[field] = envelope[field];
17
18
  }
@@ -39,38 +40,38 @@ function normalized(error, fallbackKind) {
39
40
  return error;
40
41
  }
41
42
 
42
- function cloneJson(value, budget, depth) {
43
- if (depth > MAX_JSON_DEPTH || ++budget.nodes > MAX_JSON_NODES) throw normalized({}, 'invalid_request');
43
+ function cloneJson(value, budget, depth, kind) {
44
+ if (depth > MAX_JSON_DEPTH || ++budget.nodes > MAX_JSON_NODES) throw normalized({}, kind);
44
45
  if (value === null || typeof value === 'boolean') return value;
45
46
  if (typeof value === 'string') {
46
47
  budget.bytes += Buffer.byteLength(value, 'utf8');
47
- if (budget.bytes > MAX_JSON_STRING_BYTES) throw normalized({}, 'invalid_request');
48
+ if (budget.bytes > MAX_JSON_STRING_BYTES) throw normalized({}, kind);
48
49
  return value;
49
50
  }
50
51
  if (typeof value === 'number') {
51
52
  if (!Number.isFinite(value) || (Number.isInteger(value) && !Number.isSafeInteger(value))) {
52
- throw normalized({}, 'invalid_request');
53
+ throw normalized({}, kind);
53
54
  }
54
55
  return value;
55
56
  }
56
57
  if (value === undefined || typeof value !== 'object' || isProxy(value)) {
57
- throw normalized({}, 'invalid_request');
58
+ throw normalized({}, kind);
58
59
  }
59
60
  const array = Array.isArray(value);
60
61
  const prototype = Object.getPrototypeOf(value);
61
62
  if (array ? prototype !== Array.prototype : prototype !== Object.prototype && prototype !== null) {
62
- throw normalized({}, 'invalid_request');
63
+ throw normalized({}, kind);
63
64
  }
64
- if (budget.active.has(value)) throw normalized({}, 'invalid_request');
65
+ if (budget.active.has(value)) throw normalized({}, kind);
65
66
  budget.active.add(value);
66
67
  try {
67
- if (array) return value.map((member) => cloneJson(member, budget, depth + 1));
68
+ if (array) return value.map((member) => cloneJson(member, budget, depth + 1, kind));
68
69
  const result = Object.create(null);
69
70
  for (const key of Reflect.ownKeys(value)) {
70
- if (typeof key !== 'string') throw normalized({}, 'invalid_request');
71
+ if (typeof key !== 'string') throw normalized({}, kind);
71
72
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
72
- if (!descriptor || !Object.hasOwn(descriptor, 'value')) throw normalized({}, 'invalid_request');
73
- if (descriptor.enumerable) result[key] = cloneJson(descriptor.value, budget, depth + 1);
73
+ if (!descriptor || !Object.hasOwn(descriptor, 'value')) throw normalized({}, kind);
74
+ if (descriptor.enumerable) result[key] = cloneJson(descriptor.value, budget, depth + 1, kind);
74
75
  }
75
76
  return result;
76
77
  } finally {
@@ -78,8 +79,10 @@ function cloneJson(value, budget, depth) {
78
79
  }
79
80
  }
80
81
 
81
- function sanitize(value) {
82
- return cloneJson(value, { nodes: 0, bytes: 0, active: new WeakSet() }, 0);
82
+ // A refusal is reported as `kind`: `configuration` for the constructor's
83
+ // settings, `invalid-request` for a method's arguments.
84
+ function sanitize(value, kind) {
85
+ return cloneJson(value, { nodes: 0, bytes: 0, active: new WeakSet() }, 0, kind);
83
86
  }
84
87
 
85
88
  const NativeCaseworkClient = native.CaseworkClient;
@@ -87,7 +90,7 @@ const NativeCaseworkClient = native.CaseworkClient;
87
90
  class CaseworkClient {
88
91
  constructor(config) {
89
92
  try {
90
- this.native = new NativeCaseworkClient(sanitize(config));
93
+ this.native = new NativeCaseworkClient(sanitize(config, 'configuration'));
91
94
  } catch (error) {
92
95
  throw normalized(error, 'configuration');
93
96
  }
@@ -97,7 +100,7 @@ class CaseworkClient {
97
100
  try {
98
101
  return this.native.taskAssertionEndpoint(grantId);
99
102
  } catch (error) {
100
- throw normalized(error, 'invalid_request');
103
+ throw normalized(error, 'invalid-request');
101
104
  }
102
105
  }
103
106
  }
@@ -112,6 +115,8 @@ for (const [method, jsonIndexes] of [
112
115
  ['reviewKinds', []],
113
116
  ['reviewKind', []],
114
117
  ['reviewTasks', [2]],
118
+ ['ownReviewDecisions', [2]],
119
+ ['supervisoryReviewTasks', [2]],
115
120
  ['reviewTask', []],
116
121
  ['reviewTaskContext', []],
117
122
  ['previewReviewTaskTemplates', []],
@@ -170,11 +175,11 @@ for (const [method, jsonIndexes] of [
170
175
  CaseworkClient.prototype[method] = function (...args) {
171
176
  try {
172
177
  for (const index of jsonIndexes) {
173
- if (args[index] !== undefined && args[index] !== null) args[index] = sanitize(args[index]);
178
+ if (args[index] !== undefined && args[index] !== null) args[index] = sanitize(args[index], 'invalid-request');
174
179
  }
175
180
  return this.native[method](...args).catch((error) => { throw normalized(error); });
176
181
  } catch (error) {
177
- throw normalized(error, 'invalid_request');
182
+ throw normalized(error, 'invalid-request');
178
183
  }
179
184
  };
180
185
  }
@@ -13,6 +13,8 @@ export declare class CaseworkClient {
13
13
  reviewKind(token: string, profile: string, kindId: string): Promise<CaseworkOutcome>
14
14
  reviewTasks(token: string, profile: string, query?: any | undefined | null, sourceProfile?: string | undefined | null): Promise<CaseworkOutcome>
15
15
  reviewTask(token: string, profile: string, taskId: string, sourceProfile?: string | undefined | null): Promise<CaseworkOutcome>
16
+ ownReviewDecisions(token: string, profile: string, query?: any | undefined | null, sourceProfile?: string | undefined | null): Promise<CaseworkOutcome>
17
+ supervisoryReviewTasks(token: string, profile: string, query?: any | undefined | null, sourceProfile?: string | undefined | null): Promise<CaseworkOutcome>
16
18
  reviewTaskContext(token: string, profile: string, taskId: string, sourceProfile?: string | undefined | null): Promise<CaseworkOutcome>
17
19
  previewReviewTaskTemplates(token: string, profile: string, sourceProfile: string, taskId: string): Promise<CaseworkOutcome>
18
20
  listReviewTaskGrants(token: string, profile: string, sourceProfile: string, taskId: string): Promise<CaseworkOutcome>
@@ -76,6 +78,11 @@ export interface CaseworkClientConfig {
76
78
  maxResponseBytes?: number
77
79
  userAgent?: string
78
80
  trustedRootCertificates?: string
81
+ /**
82
+ * How many times a keyed mutation whose outcome is unknown is resent under
83
+ * the same idempotency key: 0 to 2, default 2, and 0 disables the resend.
84
+ */
85
+ maxMutationRetries?: number
79
86
  }
80
87
 
81
88
  export interface CaseworkOutcome {
@@ -1,4 +1,4 @@
1
- export type ServiceKind = 'evidence' | 'relay';
1
+ export type ServiceKind = 'evidence';
2
2
 
3
3
  export interface DiscoveryClientOptions {
4
4
  baseUrl: string;
@@ -32,8 +32,6 @@ export interface ServiceFilters {
32
32
  jurisdiction?: string[];
33
33
  conformsTo?: string[];
34
34
  evidenceType?: string[];
35
- semanticClass?: string[];
36
- operationFamily?: string[];
37
35
  }
38
36
 
39
37
  export interface EvidenceServiceQuery {
@@ -43,17 +41,6 @@ export interface EvidenceServiceQuery {
43
41
  conformsTo?: string[];
44
42
  }
45
43
 
46
- interface RelayServiceQueryOptions {
47
- jurisdiction?: string;
48
- serviceIds?: string[];
49
- conformsTo?: string[];
50
- }
51
-
52
- export type RelayServiceQuery = RelayServiceQueryOptions & (
53
- | { semanticClassId: string; operationFamilyId?: string }
54
- | { semanticClassId?: string; operationFamilyId: string }
55
- );
56
-
57
44
  export interface ServiceRecord {
58
45
  recordId: string;
59
46
  bindingId: string;
@@ -83,10 +70,7 @@ export interface ServiceSearchResponse {
83
70
  items: ServiceRecord[];
84
71
  }
85
72
 
86
- export type MatchedCapability =
87
- | { kind: 'evidence-type'; id: string }
88
- | { kind: 'semantic-class'; id: string }
89
- | { kind: 'operation-family'; id: string };
73
+ export type MatchedCapability = { kind: 'evidence-type'; id: string };
90
74
 
91
75
  export interface SelectionRequest {
92
76
  recordId: string;
@@ -110,15 +94,6 @@ export interface EvidenceSelectionRequest {
110
94
  resolution?: EvidenceResolutionContext;
111
95
  }
112
96
 
113
- export type RelayCapabilityMatch =
114
- | { semanticClassId: string; operationFamilyId?: string }
115
- | { semanticClassId?: string; operationFamilyId: string };
116
-
117
- export interface RelaySelectionRequest {
118
- recordId: string;
119
- capabilityMatch: RelayCapabilityMatch;
120
- }
121
-
122
97
  export interface CommonServiceSelection extends Omit<ServiceRecord, 'title' | 'description'> {
123
98
  matchedCapability: MatchedCapability;
124
99
  catalogRevision: string;
@@ -131,26 +106,18 @@ export interface EvidenceServiceSelection extends CommonServiceSelection {
131
106
  evidenceResolution?: EvidenceResolutionContext;
132
107
  }
133
108
 
134
- export interface RelayServiceSelection extends CommonServiceSelection {
135
- serviceKind: 'relay';
136
- matchedCapability:
137
- | { kind: 'semantic-class'; id: string }
138
- | { kind: 'operation-family'; id: string };
139
- relayCapabilityMatch: RelayCapabilityMatch;
140
- }
141
-
142
109
  export type ServiceSelection = CommonServiceSelection;
143
110
 
144
111
  export type DiscoveryClientErrorKind =
145
112
  | 'configuration'
146
113
  | 'query'
147
- | 'no_matching_service'
148
- | 'ambiguous_selection'
149
- | 'no_matching_alternative'
150
- | 'ambiguous_alternative'
151
- | 'capability_mismatch'
152
- | 'local_acceptance_refused'
153
- | 'selection_changed'
114
+ | 'no-matching-service'
115
+ | 'ambiguous-selection'
116
+ | 'no-matching-alternative'
117
+ | 'ambiguous-alternative'
118
+ | 'capability-mismatch'
119
+ | 'local-acceptance-refused'
120
+ | 'selection-changed'
154
121
  | 'transport'
155
122
  | 'problem'
156
123
  | 'protocol'
@@ -168,7 +135,6 @@ export class DiscoveryClient {
168
135
  resolveEvidenceTypes(request: EvidenceTypeResolveRequest): Promise<EvidenceTypeResolveResponse>;
169
136
  searchServices(filters?: ServiceFilters): Promise<ServiceSearchResponse>;
170
137
  searchEvidenceServices(query: EvidenceServiceQuery): Promise<ServiceSearchResponse>;
171
- searchRelayServices(query: RelayServiceQuery): Promise<ServiceSearchResponse>;
172
138
  selectExact(response: ServiceSearchResponse, request: SelectionRequest): CommonServiceSelection;
173
139
  selectEvidenceAlternative(
174
140
  response: EvidenceTypeResolveResponse,
@@ -178,10 +144,6 @@ export class DiscoveryClient {
178
144
  response: ServiceSearchResponse,
179
145
  request: EvidenceSelectionRequest,
180
146
  ): EvidenceServiceSelection;
181
- selectRelayService(
182
- response: ServiceSearchResponse,
183
- request: RelaySelectionRequest,
184
- ): RelayServiceSelection;
185
147
  }
186
148
 
187
149
  export function selectExact(
@@ -199,11 +161,6 @@ export function selectEvidenceService(
199
161
  request: EvidenceSelectionRequest,
200
162
  ): EvidenceServiceSelection;
201
163
 
202
- export function selectRelayService(
203
- response: ServiceSearchResponse,
204
- request: RelaySelectionRequest,
205
- ): RelayServiceSelection;
206
-
207
164
  /**
208
165
  * Validate closed shape and capability binding only.
209
166
  *