@registrystack/client 0.39.0 → 0.41.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 +31 -7
- package/breg/client.d.ts +100 -10
- package/breg/client.js +41 -34
- package/breg/index.d.ts +56 -2
- package/casework/client.d.ts +90 -30
- package/casework/client.js +22 -17
- package/casework/index.d.ts +7 -0
- package/discovery/client.d.ts +7 -7
- package/discovery/client.js +1 -1
- package/evidence/client.d.ts +1 -1
- package/evidence/index.d.ts +3 -6
- package/index.d.ts +2 -1
- package/index.js +2 -1
- package/messaging/client.d.ts +26 -4
- package/messaging/client.js +33 -21
- package/messaging/index.d.ts +2 -10
- package/native.js +2 -2
- package/package.json +10 -8
- package/scheduling/client.d.ts +229 -0
- package/scheduling/client.js +142 -0
- package/scheduling/index.d.ts +28 -0
- package/scheduling/index.js +3 -0
package/casework/client.d.ts
CHANGED
|
@@ -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' | '
|
|
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' | '
|
|
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' | '
|
|
24
|
-
export type HistoryKind = 'observed' | 'opened' | 'claimed' | 'assigned' | 'delegated' | '
|
|
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> }
|
|
@@ -29,15 +37,21 @@ export interface TaskPermission { collection: string; operations: ReadonlyArray<
|
|
|
29
37
|
export interface SchedulingTaskPermission { service: string; location: string; actions: ReadonlyArray<string> }
|
|
30
38
|
export interface EvidenceRequesterContext { requesterTags: ReadonlyArray<string>; audience: string }
|
|
31
39
|
export interface TaskApprovalRequest { templateId: string; templateVersion: string }
|
|
40
|
+
/** Deferred authority keeps its approved deadline; execution credentials stay short-lived. */
|
|
41
|
+
export type TaskAuthorizationMode = 'immediate' | 'deferred'
|
|
32
42
|
export interface TaskTemplatePreview {
|
|
33
43
|
id: string; version: string; label: string; agent: IssuerPrincipal; client: string; resource: string; scopes: ReadonlyArray<string>; purpose: string
|
|
34
44
|
evidenceContext?: EvidenceRequesterContext; bounds: TaskGrantBounds; subjects: { readonly [key: string]: Exclude<JsonScalar, null> }; lifetimeSeconds: SafeInteger
|
|
45
|
+
/** Omitted for the existing immediate mode. */
|
|
46
|
+
authorizationMode?: TaskAuthorizationMode
|
|
35
47
|
}
|
|
36
48
|
export interface TaskTemplatePreviews { itemRevision: SafeInteger; templates: ReadonlyArray<TaskTemplatePreview> }
|
|
37
49
|
/** Grant metadata deliberately excludes stored subject values. */
|
|
38
50
|
export interface TaskGrantView {
|
|
39
51
|
id: string; templateId: string; templateVersion: string; agent: IssuerPrincipal; client: string; resource: string; scopes: ReadonlyArray<string>; purpose: string
|
|
40
52
|
evidenceContext?: EvidenceRequesterContext; bounds: TaskGrantBounds; expiresAt: SafeInteger; invalidated: boolean
|
|
53
|
+
/** Omitted for the existing immediate mode. */
|
|
54
|
+
authorizationMode?: TaskAuthorizationMode
|
|
41
55
|
}
|
|
42
56
|
export interface TaskGrantList { grants: ReadonlyArray<TaskGrantView> }
|
|
43
57
|
export interface TaskGrantRevocation { id: string; invalidated: boolean }
|
|
@@ -94,14 +108,14 @@ export interface WorkItem {
|
|
|
94
108
|
}
|
|
95
109
|
export interface Page<T> { items: ReadonlyArray<T>; nextCursor?: string; status: PageStatus }
|
|
96
110
|
export interface WorkItemPage extends Page<WorkItem> { servedQueues: ReadonlyArray<string> }
|
|
97
|
-
export type DirectoryTargetPurpose = 'assignment' | '
|
|
111
|
+
export type DirectoryTargetPurpose = 'assignment' | 'absence-person' | 'absence-cover'
|
|
98
112
|
export type DirectoryTargetsQuery = {
|
|
99
113
|
cursor?: string
|
|
100
114
|
limit?: SafeInteger
|
|
101
115
|
} & (
|
|
102
116
|
| { purpose: 'assignment'; queue: string; personIssuer?: never; personSubject?: never }
|
|
103
|
-
| { purpose: '
|
|
104
|
-
| { purpose: '
|
|
117
|
+
| { purpose: 'absence-person'; queue?: never; personIssuer?: never; personSubject?: never }
|
|
118
|
+
| { purpose: 'absence-cover'; queue?: never; personIssuer: string; personSubject: string }
|
|
105
119
|
)
|
|
106
120
|
export type DirectoryTargetPage = Page<DirectoryMember>
|
|
107
121
|
export type ListWorkItemsQuery = {
|
|
@@ -167,11 +181,11 @@ export interface HistoryEntryBase {
|
|
|
167
181
|
profileId: string
|
|
168
182
|
}
|
|
169
183
|
export interface AttemptReservedHistoryEntry extends HistoryEntryBase {
|
|
170
|
-
kind: '
|
|
184
|
+
kind: 'attempt-reserved'
|
|
171
185
|
detail: JsonObject & { attemptId: string; bindingReference: string; operation: OperationName }
|
|
172
186
|
}
|
|
173
187
|
/**
|
|
174
|
-
* An
|
|
188
|
+
* An attempt-uncertain detail takes one of three shapes: recovery left the
|
|
175
189
|
* attempt uncertain, the source definitively refused it, or an operator marked
|
|
176
190
|
* an expired pending attempt uncertain. reason is the original decision reason.
|
|
177
191
|
*/
|
|
@@ -186,19 +200,19 @@ export type AttemptUncertainHistoryDetail = JsonObject & {
|
|
|
186
200
|
| { operatorReason: string; decidedBy: string; originalActor: IssuerPrincipal; originalProfileId: string; definitivelyRefused?: never }
|
|
187
201
|
)
|
|
188
202
|
export interface AttemptUncertainHistoryEntry extends HistoryEntryBase {
|
|
189
|
-
kind: '
|
|
203
|
+
kind: 'attempt-uncertain'
|
|
190
204
|
detail: AttemptUncertainHistoryDetail
|
|
191
205
|
}
|
|
192
206
|
export interface ActionCompletedHistoryEntry extends HistoryEntryBase {
|
|
193
|
-
kind: '
|
|
207
|
+
kind: 'action-completed'
|
|
194
208
|
detail: JsonObject & { attemptId: string; bindingReference: string; sourceRevision: string; sourceReceipt: SourceReceipt }
|
|
195
209
|
}
|
|
196
210
|
export interface AttemptSettledHistoryEntry extends HistoryEntryBase {
|
|
197
|
-
kind: '
|
|
198
|
-
detail: JsonObject & { attemptId: string; bindingReference: string; operation: OperationName; outcome: 'applied' | '
|
|
211
|
+
kind: 'attempt-settled'
|
|
212
|
+
detail: JsonObject & { attemptId: string; bindingReference: string; operation: OperationName; outcome: 'applied' | 'not-applied'; reason: string; decidedBy: string }
|
|
199
213
|
}
|
|
200
214
|
export interface OtherHistoryEntry extends HistoryEntryBase {
|
|
201
|
-
kind: Exclude<HistoryKind, '
|
|
215
|
+
kind: Exclude<HistoryKind, 'attempt-reserved' | 'attempt-uncertain' | 'action-completed' | 'attempt-settled'>
|
|
202
216
|
detail: JsonValue
|
|
203
217
|
}
|
|
204
218
|
export type HistoryEntry = AttemptReservedHistoryEntry | AttemptUncertainHistoryEntry | ActionCompletedHistoryEntry | AttemptSettledHistoryEntry | OtherHistoryEntry
|
|
@@ -220,9 +234,9 @@ export interface CalendarPolicy { id: string; timezone: string; workingWeekdays:
|
|
|
220
234
|
export interface ClockReminder { id: string; workingDaysBefore: SafeInteger }
|
|
221
235
|
export interface ClockStep { id: string; because: string; at: 'due'; action: { reassign: { queue: string } } }
|
|
222
236
|
export type ClockPolicy = {
|
|
223
|
-
|
|
237
|
+
type: 'subject'; id: string; anchor: 'first-submitted-at'; completeOn: 'review-completed'; after: { elapsed: string }; pauseWhile: ReadonlyArray<'awaiting-applicant'>
|
|
224
238
|
} | {
|
|
225
|
-
|
|
239
|
+
type: 'activity'; id: string; anchor: 'stage-entered-at'; calendar: string; after: { workingDays: SafeInteger }; dueTime: string;
|
|
226
240
|
atRisk?: { workingDaysBefore: SafeInteger }; reminders?: ReadonlyArray<ClockReminder>; steps?: ReadonlyArray<ClockStep>
|
|
227
241
|
}
|
|
228
242
|
export interface SourcePolicy {
|
|
@@ -252,14 +266,14 @@ export interface AbsenceInput { person: IssuerPrincipal; from: string; until: st
|
|
|
252
266
|
export interface AbsenceRecord extends AbsenceInput { absenceId: string; revision: SafeInteger }
|
|
253
267
|
export interface AbsencesQuery { cursor?: string; limit?: SafeInteger }
|
|
254
268
|
export interface AbsenceList { directoryRevision: SafeInteger; items: ReadonlyArray<AbsenceRecord>; nextCursor?: string }
|
|
255
|
-
export interface AssignmentContext { owner?: IssuerPrincipal; assignedBy?: IssuerPrincipal; absenceIds: ReadonlyArray<string>; staffingDiagnostic?: '
|
|
269
|
+
export interface AssignmentContext { owner?: IssuerPrincipal; assignedBy?: IssuerPrincipal; absenceIds: ReadonlyArray<string>; staffingDiagnostic?: 'no-cover-available' }
|
|
256
270
|
export interface AssignmentRequest { assignee: IssuerPrincipal; reason?: string }
|
|
257
271
|
export interface DelegateRequest { delegate: IssuerPrincipal; reason?: string }
|
|
258
272
|
export interface CaseloadMoveRequest { from: IssuerPrincipal; to: IssuerPrincipal; queueId?: string; reason: string }
|
|
259
273
|
export interface CaseloadItemSelection { itemId: string; expectedRevision: SafeInteger }
|
|
260
274
|
export interface CaseloadApplyRequest { movement: CaseloadMoveRequest; items: ReadonlyArray<CaseloadItemSelection> }
|
|
261
275
|
export interface CaseloadPreviewQuery { cursor?: string; limit?: SafeInteger }
|
|
262
|
-
export interface CaseloadItemResult { itemId: string; result: 'moved' | '
|
|
276
|
+
export interface CaseloadItemResult { itemId: string; result: 'moved' | 'not-visible' | 'not-eligible' | 'attempt-in-progress' | 'conflict'; revision?: SafeInteger }
|
|
263
277
|
export interface BootstrapDirectoryRequest {
|
|
264
278
|
teamId: string
|
|
265
279
|
staff: ReadonlyArray<IssuerPrincipal>
|
|
@@ -316,10 +330,23 @@ export type KnownCaseworkProblemCode =
|
|
|
316
330
|
| 'work-item.source-unavailable'
|
|
317
331
|
| 'work-item.superseded'
|
|
318
332
|
export type CaseworkProblemCode = KnownCaseworkProblemCode | (string & {})
|
|
319
|
-
export type CaseworkProtocolFailure = '
|
|
333
|
+
export type CaseworkProtocolFailure = 'header-bounds' | 'trace-context' | 'media-type' | 'body' | 'problem' | 'status' | 'protocol'
|
|
320
334
|
|
|
321
335
|
export class CaseworkClientError extends Error {
|
|
322
|
-
readonly kind: 'configuration' | '
|
|
336
|
+
readonly kind: 'configuration' | 'invalid-request' | 'transport' | 'problem' | 'protocol'
|
|
337
|
+
/**
|
|
338
|
+
* Whether the request may have taken effect although this error was
|
|
339
|
+
* raised: a timeout or broken exchange after sending, an unusable answer,
|
|
340
|
+
* or a 5xx. When true, recover a keyed request by sending it again under
|
|
341
|
+
* the same idempotency key; a new key could apply it twice. False for a
|
|
342
|
+
* configuration or request defect, a connection never established, and
|
|
343
|
+
* every 4xx refusal. It is false for `410 idempotency.expired` too, but
|
|
344
|
+
* there an earlier attempt under the key committed and only its stored
|
|
345
|
+
* response was erased by retention: reconcile the original operation, by
|
|
346
|
+
* reading the item, review request, or directory, before choosing a new
|
|
347
|
+
* key.
|
|
348
|
+
*/
|
|
349
|
+
readonly outcomeUnknown: boolean
|
|
323
350
|
readonly code?: CaseworkProblemCode
|
|
324
351
|
readonly detail?: string
|
|
325
352
|
readonly status?: SafeInteger
|
|
@@ -327,13 +354,13 @@ export class CaseworkClientError extends Error {
|
|
|
327
354
|
readonly originalAttemptId?: string
|
|
328
355
|
readonly validation?: {
|
|
329
356
|
readonly path: string
|
|
330
|
-
readonly reason: '
|
|
357
|
+
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
358
|
}
|
|
332
359
|
readonly transportKind?: string
|
|
333
360
|
readonly protocolFailure?: CaseworkProtocolFailure
|
|
334
361
|
}
|
|
335
362
|
|
|
336
|
-
export type ClockRuntimeState = 'running' | 'paused' | 'completed' | 'cancelled' | '
|
|
363
|
+
export type ClockRuntimeState = 'running' | 'paused' | 'completed' | 'cancelled' | 'verification-pending' | 'source-facts-missing'
|
|
337
364
|
export type ClockNextEffect =
|
|
338
365
|
| { kind: 'reminder'; id: string; at: string }
|
|
339
366
|
| { kind: 'reassign'; id: string; at: string; because: string; queueId: string }
|
|
@@ -382,7 +409,7 @@ export interface ReviewRequestAccepted {
|
|
|
382
409
|
policy: ReviewPolicyBinding
|
|
383
410
|
submissionDigest: ContentDigest
|
|
384
411
|
}
|
|
385
|
-
export type ReviewRequestLifecycle = 'reviewing' | 'approved' | 'rejected' | '
|
|
412
|
+
export type ReviewRequestLifecycle = 'reviewing' | 'approved' | 'rejected' | 'changes-requested' | 'answered' | 'cancelled' | 'superseded'
|
|
386
413
|
export interface ReviewRequestView extends ReviewRequestAccepted {
|
|
387
414
|
requesterReference: string
|
|
388
415
|
lifecycle: ReviewRequestLifecycle
|
|
@@ -390,7 +417,7 @@ export interface ReviewRequestView extends ReviewRequestAccepted {
|
|
|
390
417
|
createdAt: string
|
|
391
418
|
updatedAt: string
|
|
392
419
|
}
|
|
393
|
-
export type ReviewResultStatus = 'approved' | 'rejected' | '
|
|
420
|
+
export type ReviewResultStatus = 'approved' | 'rejected' | 'changes-requested' | 'answered' | 'cancelled' | 'superseded'
|
|
394
421
|
export interface ReviewResult extends ReviewRequestAccepted {
|
|
395
422
|
resultId: Uuid
|
|
396
423
|
status: ReviewResultStatus
|
|
@@ -407,11 +434,30 @@ export interface ReviewResultFeedPage { items: ReadonlyArray<ReviewResultFeedEnt
|
|
|
407
434
|
export interface ReviewCancelRequest { subject: ReviewSubjectBinding; reason: string }
|
|
408
435
|
export type ReviewCancelResponse =
|
|
409
436
|
| { outcome: 'cancelled'; result: ReviewResult }
|
|
410
|
-
| { outcome: '
|
|
437
|
+
| { outcome: 'already-terminal'; result: ReviewResult }
|
|
411
438
|
export interface ReviewPageQuery { cursor?: Uuid; limit?: SafeInteger }
|
|
412
|
-
export
|
|
439
|
+
export type ReviewTaskOwnership = 'assigned-to-me' | 'unclaimed'
|
|
440
|
+
export interface ReviewTaskQuery extends ReviewPageQuery { queue?: string; ownership?: ReviewTaskOwnership }
|
|
441
|
+
export interface SupervisoryReviewTaskQuery extends ReviewPageQuery { queue?: string; requestId?: Uuid }
|
|
442
|
+
export interface OwnReviewDecisionQuery extends ReviewPageQuery { queue?: string }
|
|
413
443
|
export interface WorkItemHistoryQuery { cursor?: string; limit?: SafeInteger }
|
|
414
444
|
export type ReviewerTaskState = 'open' | { held: { holder: IssuerPrincipal } } | 'decided'
|
|
445
|
+
export type ReviewDecisionType = 'approve' | 'reject' | 'changes-requested' | 'answer'
|
|
446
|
+
export interface ReviewDecisionReceipt {
|
|
447
|
+
policy: ReviewPolicyBinding
|
|
448
|
+
decision: ReviewDecisionType
|
|
449
|
+
outcome?: string
|
|
450
|
+
outcomeLabel?: string
|
|
451
|
+
decidedAt: string
|
|
452
|
+
}
|
|
453
|
+
export interface OwnReviewDecision {
|
|
454
|
+
taskId: Uuid
|
|
455
|
+
requestId: Uuid
|
|
456
|
+
queue: string
|
|
457
|
+
requesterReference: string
|
|
458
|
+
decisionReceipt: ReviewDecisionReceipt
|
|
459
|
+
}
|
|
460
|
+
export interface OwnReviewDecisionPage { items: ReadonlyArray<OwnReviewDecision>; nextCursor?: Uuid; status: PageStatus }
|
|
415
461
|
export interface ReviewerTask {
|
|
416
462
|
taskId: Uuid
|
|
417
463
|
requestId: Uuid
|
|
@@ -422,9 +468,20 @@ export interface ReviewerTask {
|
|
|
422
468
|
eligibleProfiles: ReadonlyArray<string>
|
|
423
469
|
state: ReviewerTaskState
|
|
424
470
|
decidedByCaller?: boolean
|
|
471
|
+
decisionReceipt?: ReviewDecisionReceipt
|
|
425
472
|
}
|
|
426
473
|
export interface ReviewTaskPage { items: ReadonlyArray<ReviewerTask>; nextCursor?: Uuid; status: PageStatus }
|
|
427
|
-
export type
|
|
474
|
+
export type SupervisoryReviewTaskState = 'open' | 'held' | 'decided'
|
|
475
|
+
export interface SupervisoryReviewTask {
|
|
476
|
+
taskId: Uuid
|
|
477
|
+
requestId: Uuid
|
|
478
|
+
queue: string
|
|
479
|
+
revision: SafeInteger
|
|
480
|
+
state: SupervisoryReviewTaskState
|
|
481
|
+
accountabilityEventId?: Uuid
|
|
482
|
+
}
|
|
483
|
+
export interface SupervisoryReviewTaskPage { items: ReadonlyArray<SupervisoryReviewTask>; nextCursor?: Uuid; status: PageStatus }
|
|
484
|
+
export type ReviewSourceBindingStatus = 'current' | 'binding-changed'
|
|
428
485
|
export interface ReviewSourceProjection { binding: SourceBinding; displayReference?: string; display: Readonly<Record<string, JsonValue>> }
|
|
429
486
|
export type ReviewTaskContextData =
|
|
430
487
|
| { strategy: 'submitted'; snapshot: Readonly<Record<string, JsonValue>> }
|
|
@@ -447,7 +504,7 @@ export interface ReviewClockOccurrence {
|
|
|
447
504
|
clockId: string
|
|
448
505
|
requestId: Uuid
|
|
449
506
|
correlation: ReviewClockCorrelation
|
|
450
|
-
state: 'running' | 'paused' | 'completed' | 'cancelled' | '
|
|
507
|
+
state: 'running' | 'paused' | 'completed' | 'cancelled' | 'source-facts-missing'
|
|
451
508
|
policyDigest: ContentDigest
|
|
452
509
|
anchorAt: string
|
|
453
510
|
dueAt?: string
|
|
@@ -458,7 +515,7 @@ export interface ReviewTaskDraftInput { body: JsonValue }
|
|
|
458
515
|
export interface ReviewTaskDraft { taskId: Uuid; author: IssuerPrincipal; body: JsonValue; revision: SafeInteger; updatedAt: string }
|
|
459
516
|
export type ReviewerDecision =
|
|
460
517
|
| { type: 'approve' }
|
|
461
|
-
| { type: 'reject' | '
|
|
518
|
+
| { type: 'reject' | 'changes-requested' | 'answer'; outcome: string; reason?: string | null; result?: JsonObject | null }
|
|
462
519
|
export interface ReviewTaskDecisionRequest { decision: ReviewerDecision }
|
|
463
520
|
export type ReviewHistoryAudience = 'reviewers' | 'requester'
|
|
464
521
|
export interface ReviewNoteRequest { audience: ReviewHistoryAudience; note: string }
|
|
@@ -468,6 +525,7 @@ export interface ReviewAccountabilityRecord {
|
|
|
468
525
|
eventId: Uuid; requestId: Uuid; taskId: Uuid; actorRef: string; actor: IssuerPrincipal
|
|
469
526
|
profileId: string; decision: string; privateReason?: string; resultDigest?: string
|
|
470
527
|
occurredAt: string; retainedUntil: string
|
|
528
|
+
decisionReceipt?: ReviewDecisionReceipt
|
|
471
529
|
}
|
|
472
530
|
export interface ReviewStagePolicy { id: string; queue: string; decidingProfiles: ReadonlyArray<string>; requiredApprovals: SafeInteger; excludeInitiator?: boolean; excludePreviousStageReviewers?: boolean }
|
|
473
531
|
export interface ReviewRetentionPolicy { terminalDays: SafeInteger; accountabilityDays: SafeInteger }
|
|
@@ -480,7 +538,7 @@ export interface ReviewKindPolicySnapshot {
|
|
|
480
538
|
retention: ReviewRetentionPolicy
|
|
481
539
|
displaySchema: JsonValue
|
|
482
540
|
resultSchema?: JsonValue
|
|
483
|
-
outcomes?: ReadonlyArray<{ id: string; label: string; settlement: 'rejected' | '
|
|
541
|
+
outcomes?: ReadonlyArray<{ id: string; label: string; settlement: 'rejected' | 'changes-requested' | 'answered'; reasonRequired: boolean; resultRequired?: boolean }>
|
|
484
542
|
}
|
|
485
543
|
|
|
486
544
|
export class CaseworkClient {
|
|
@@ -494,6 +552,8 @@ export class CaseworkClient {
|
|
|
494
552
|
reviewKinds(token: string, profile: string): Promise<CaseworkOutcome<ReadonlyArray<ReviewKindPolicySnapshot>>>
|
|
495
553
|
reviewKind(token: string, profile: string, kindId: string): Promise<CaseworkOutcome<ReviewKindPolicySnapshot>>
|
|
496
554
|
reviewTasks(token: string, profile: string, query?: ReviewTaskQuery | null, sourceProfile?: string | null): Promise<CaseworkOutcome<ReviewTaskPage>>
|
|
555
|
+
supervisoryReviewTasks(token: string, profile: string, query?: SupervisoryReviewTaskQuery | null, sourceProfile?: string | null): Promise<CaseworkOutcome<SupervisoryReviewTaskPage>>
|
|
556
|
+
ownReviewDecisions(token: string, profile: string, query?: OwnReviewDecisionQuery | null, sourceProfile?: string | null): Promise<CaseworkOutcome<OwnReviewDecisionPage>>
|
|
497
557
|
reviewTask(token: string, profile: string, taskId: Uuid, sourceProfile?: string | null): Promise<CaseworkOutcome<ReviewerTask>>
|
|
498
558
|
reviewTaskContext(token: string, profile: string, taskId: Uuid, sourceProfile?: string | null): Promise<CaseworkOutcome<ReviewTaskContext>>
|
|
499
559
|
previewReviewTaskTemplates(token: string, profile: string, sourceProfile: string, taskId: Uuid): Promise<CaseworkOutcome<TaskTemplatePreviews>>
|
package/casework/client.js
CHANGED
|
@@ -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({},
|
|
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({},
|
|
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({},
|
|
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({},
|
|
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({},
|
|
63
|
+
throw normalized({}, kind);
|
|
63
64
|
}
|
|
64
|
-
if (budget.active.has(value)) throw normalized({},
|
|
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({},
|
|
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({},
|
|
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
|
-
|
|
82
|
-
|
|
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, '
|
|
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, '
|
|
182
|
+
throw normalized(error, 'invalid-request');
|
|
178
183
|
}
|
|
179
184
|
};
|
|
180
185
|
}
|
package/casework/index.d.ts
CHANGED
|
@@ -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 {
|
package/discovery/client.d.ts
CHANGED
|
@@ -111,13 +111,13 @@ export type ServiceSelection = CommonServiceSelection;
|
|
|
111
111
|
export type DiscoveryClientErrorKind =
|
|
112
112
|
| 'configuration'
|
|
113
113
|
| 'query'
|
|
114
|
-
| '
|
|
115
|
-
| '
|
|
116
|
-
| '
|
|
117
|
-
| '
|
|
118
|
-
| '
|
|
119
|
-
| '
|
|
120
|
-
| '
|
|
114
|
+
| 'no-matching-service'
|
|
115
|
+
| 'ambiguous-selection'
|
|
116
|
+
| 'no-matching-alternative'
|
|
117
|
+
| 'ambiguous-alternative'
|
|
118
|
+
| 'capability-mismatch'
|
|
119
|
+
| 'local-acceptance-refused'
|
|
120
|
+
| 'selection-changed'
|
|
121
121
|
| 'transport'
|
|
122
122
|
| 'problem'
|
|
123
123
|
| 'protocol'
|
package/discovery/client.js
CHANGED
|
@@ -55,7 +55,7 @@ function inputError(kind) {
|
|
|
55
55
|
|
|
56
56
|
function localAcceptanceError() {
|
|
57
57
|
return new DiscoveryClientError({
|
|
58
|
-
kind: '
|
|
58
|
+
kind: 'local-acceptance-refused',
|
|
59
59
|
message: 'the relying application refused the advertised service',
|
|
60
60
|
});
|
|
61
61
|
}
|
package/evidence/client.d.ts
CHANGED
|
@@ -351,7 +351,7 @@ export interface EvidenceRequestBatchSpec {
|
|
|
351
351
|
* is `protocol`
|
|
352
352
|
* - `code`: `denied`, `protocol` (optional), `verification`, and any `token`
|
|
353
353
|
* failure whose `tokenKind` is `refused`
|
|
354
|
-
* - `traceId`: `denied`, `
|
|
354
|
+
* - `traceId`: `denied`, `not-available`, `protocol` (all optional)
|
|
355
355
|
* - `retryAfterSeconds`: `denied`, `protocol` (both optional)
|
|
356
356
|
* - `transportKind`: `transport`, and any `token` failure whose `tokenKind`
|
|
357
357
|
* is `transport`
|
package/evidence/index.d.ts
CHANGED
|
@@ -154,11 +154,8 @@ export declare class EvidenceClient {
|
|
|
154
154
|
export declare class PreparedEvidenceRequest {
|
|
155
155
|
/** The nonce this request carries. Retain it with the transaction record. */
|
|
156
156
|
get requestNonce(): string
|
|
157
|
-
/**
|
|
158
|
-
|
|
159
|
-
* it.
|
|
160
|
-
*/
|
|
161
|
-
get policyDocument(): any
|
|
157
|
+
/** The complete enveloped policy, with the subject set as `prepare` left it. */
|
|
158
|
+
get policyDocument(): { apiVersion: 'id.registrystack.org/formats/evidence/verification-policy/v1'; kind: 'EvidenceVerificationPolicy'; [field: string]: unknown }
|
|
162
159
|
/**
|
|
163
160
|
* `"acceptFirstUse"` or `{ pinned: [{ role, binding }, ...] }`, exactly as
|
|
164
161
|
* this request was prepared.
|
|
@@ -178,7 +175,7 @@ export declare class PreparedEvidenceRequestBatch {
|
|
|
178
175
|
/** Independently generated item nonces in request order. */
|
|
179
176
|
get requestNonces(): Array<string>
|
|
180
177
|
/** Independently closed policy documents in request order. */
|
|
181
|
-
get policyDocuments(): Array<
|
|
178
|
+
get policyDocuments(): Array<{ apiVersion: 'id.registrystack.org/formats/evidence/verification-policy/v1'; kind: 'EvidenceVerificationPolicy'; [field: string]: unknown }>
|
|
182
179
|
/** Subject-verification stances in request order. */
|
|
183
180
|
get subjectExpectations(): Array<any>
|
|
184
181
|
/** Number of positional requests in this batch. */
|
package/index.d.ts
CHANGED
|
@@ -3,5 +3,6 @@ import * as evidence from './evidence/client'
|
|
|
3
3
|
import * as breg from './breg/client'
|
|
4
4
|
import * as casework from './casework/client'
|
|
5
5
|
import * as messaging from './messaging/client'
|
|
6
|
+
import * as scheduling from './scheduling/client'
|
|
6
7
|
|
|
7
|
-
export { discovery, evidence, breg, casework, messaging }
|
|
8
|
+
export { discovery, evidence, breg, casework, messaging, scheduling }
|
package/index.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
// One assignment per namespace, never a `module.exports` object literal: Node
|
|
4
4
|
// scans this file for these statements to synthesise the named exports an ESM
|
|
5
|
-
// consumer imports, and `require()` sees the same
|
|
5
|
+
// consumer imports, and `require()` sees the same six properties either way.
|
|
6
6
|
exports.discovery = require('./discovery/client');
|
|
7
7
|
exports.evidence = require('./evidence/client');
|
|
8
8
|
exports.breg = require('./breg/client');
|
|
9
9
|
exports.casework = require('./casework/client');
|
|
10
10
|
exports.messaging = require('./messaging/client');
|
|
11
|
+
exports.scheduling = require('./scheduling/client');
|
package/messaging/client.d.ts
CHANGED
|
@@ -14,6 +14,13 @@ export interface MessagingClientConfig {
|
|
|
14
14
|
maxResponseBytes?: SafeInteger | null
|
|
15
15
|
userAgent?: string | null
|
|
16
16
|
trustedRootCertificates?: string | null
|
|
17
|
+
/**
|
|
18
|
+
* How many times a submission whose outcome is unknown is resent,
|
|
19
|
+
* identically and under the same idempotency key, before its error is
|
|
20
|
+
* returned: a whole number from 0 to 2, default 2; 0 sends it once. Any
|
|
21
|
+
* other value is a `configuration` error.
|
|
22
|
+
*/
|
|
23
|
+
maxMutationRetries?: SafeInteger | null
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
export type Channel = 'email' | 'sms'
|
|
@@ -102,6 +109,7 @@ export type MessagingProblemCode =
|
|
|
102
109
|
| 'profile.not-authorized'
|
|
103
110
|
| 'quota.exceeded'
|
|
104
111
|
| 'rate-limit.exceeded'
|
|
112
|
+
| 'receipt.unresolved'
|
|
105
113
|
| 'request.body-too-large'
|
|
106
114
|
| 'request.invalid'
|
|
107
115
|
| 'request.method-not-allowed'
|
|
@@ -113,10 +121,21 @@ export type MessagingProblemCode =
|
|
|
113
121
|
| 'template.locale-unavailable'
|
|
114
122
|
| 'template.not-found'
|
|
115
123
|
| 'template.render-refused'
|
|
116
|
-
export type MessagingProtocolFailure = '
|
|
124
|
+
export type MessagingProtocolFailure = 'header-bounds' | 'trace-context' | 'media-type' | 'body' | 'problem' | 'status' | 'protocol'
|
|
117
125
|
|
|
118
126
|
export class MessagingClientError extends Error {
|
|
119
|
-
readonly kind: 'configuration' | '
|
|
127
|
+
readonly kind: 'configuration' | 'invalid-request' | 'transport' | 'problem' | 'protocol'
|
|
128
|
+
/**
|
|
129
|
+
* Whether the request may have taken effect although this error was
|
|
130
|
+
* raised: a timeout or broken exchange after sending, an unusable answer,
|
|
131
|
+
* or a 5xx. When true, recover a keyed request by sending it again under
|
|
132
|
+
* the same idempotency key; a new key could apply it twice. False for a
|
|
133
|
+
* configuration or request defect, a connection never established, and
|
|
134
|
+
* every 4xx refusal. It is false for `410 idempotency.expired` too, but
|
|
135
|
+
* there an earlier submission under the key was accepted and its message
|
|
136
|
+
* may have been sent: reconcile that submission before choosing a new key.
|
|
137
|
+
*/
|
|
138
|
+
readonly outcomeUnknown: boolean
|
|
120
139
|
readonly code?: MessagingProblemCode
|
|
121
140
|
readonly title?: string
|
|
122
141
|
readonly detail?: string
|
|
@@ -124,8 +143,9 @@ export class MessagingClientError extends Error {
|
|
|
124
143
|
readonly traceId?: string
|
|
125
144
|
/**
|
|
126
145
|
* Whole seconds a 429 limit refusal asked the caller to wait, from
|
|
127
|
-
* `Retry-After`, at most one day. Absent on every other failure
|
|
128
|
-
* client never waits or retries
|
|
146
|
+
* `Retry-After`, at most one day. Absent on every other failure. The
|
|
147
|
+
* client never waits on a 429 or retries it; the wait is the caller's to
|
|
148
|
+
* honor.
|
|
129
149
|
*/
|
|
130
150
|
readonly retryAfterSeconds?: SafeInteger
|
|
131
151
|
readonly transportKind?: string
|
|
@@ -137,6 +157,8 @@ export class MessagingClient {
|
|
|
137
157
|
health(): Promise<MessagingOutcome<null>>
|
|
138
158
|
ready(): Promise<MessagingOutcome<null>>
|
|
139
159
|
submit(token: string, idempotencyKey: string, request: SubmitMessageRequest): Promise<MessagingOutcome<MessageReceipt>>
|
|
160
|
+
/** Observe the original success using the same body/key and current token; never resend or mutate. */
|
|
161
|
+
messageReceipt(token: string, idempotencyKey: string, request: SubmitMessageRequest): Promise<MessagingOutcome<MessageReceipt>>
|
|
140
162
|
message(token: string, messageId: MessageId): Promise<MessagingOutcome<MessageView>>
|
|
141
163
|
cancel(token: string, messageId: MessageId): Promise<MessagingOutcome<MessageView>>
|
|
142
164
|
preview(token: string, templateId: string, version: string, request: TemplatePreviewRequest): Promise<MessagingOutcome<TemplatePreview>>
|