@registrystack/client 0.29.0 → 0.31.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.
@@ -0,0 +1,471 @@
1
+ export type SafeInteger = number
2
+ export type JsonScalar = string | number | boolean | null
3
+ export type JsonValue = JsonScalar | ReadonlyArray<JsonValue> | { readonly [key: string]: JsonValue }
4
+ export type JsonObject = { readonly [key: string]: JsonValue }
5
+
6
+ export interface CaseworkClientConfig {
7
+ baseUrl: string
8
+ requestTimeoutMilliseconds?: SafeInteger | null
9
+ connectTimeoutMilliseconds?: SafeInteger | null
10
+ maxResponseBytes?: SafeInteger | null
11
+ userAgent?: string | null
12
+ trustedRootCertificates?: string | null
13
+ }
14
+
15
+ export type InboxView = 'mine' | 'my_teams' | 'team_holdings' | 'overdue' | 'completed_by_me'
16
+ export type OccurrenceKind = 'review' | 'application' | 'hosted'
17
+ export type OccurrenceState = 'open' | 'claimed' | 'waiting_applicant' | 'waiting_application' | 'synchronizing' | 'completed' | 'superseded' | 'cancelled'
18
+ export type OperationName = string
19
+ export type AttemptState = 'pending' | 'uncertain' | 'completed' | 'refused'
20
+ export type PageStatus = 'complete' | 'budget_exhausted' | 'source_unavailable'
21
+ 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'
22
+
23
+ export interface IssuerPrincipal { issuer: string; subject: string }
24
+ export type TaskGrantBounds = { type: 'evidence'; requirement: string } | { type: 'breg'; permissions: ReadonlyArray<TaskPermission> }
25
+ export interface TaskPermission { collection: string; operations: ReadonlyArray<string> }
26
+ export interface EvidenceRequesterContext { requesterTags: ReadonlyArray<string>; audience: string }
27
+ export interface TaskApprovalRequest { templateId: string; templateVersion: string }
28
+ export interface TaskTemplatePreview {
29
+ id: string; version: string; label: string; agent: IssuerPrincipal; client: string; resource: string; scopes: ReadonlyArray<string>; purpose: string
30
+ evidenceContext?: EvidenceRequesterContext; bounds: TaskGrantBounds; subjects: { readonly [key: string]: Exclude<JsonScalar, null> }; lifetimeSeconds: SafeInteger
31
+ }
32
+ export interface TaskTemplatePreviews { itemRevision: SafeInteger; templates: ReadonlyArray<TaskTemplatePreview> }
33
+ /** Grant metadata deliberately excludes stored subject values. */
34
+ export interface TaskGrantView {
35
+ id: string; templateId: string; templateVersion: string; agent: IssuerPrincipal; client: string; resource: string; scopes: ReadonlyArray<string>; purpose: string
36
+ evidenceContext?: EvidenceRequesterContext; bounds: TaskGrantBounds; expiresAt: SafeInteger; invalidated: boolean
37
+ }
38
+ export interface TaskGrantList { grants: ReadonlyArray<TaskGrantView> }
39
+ export interface TaskGrantRevocation { id: string; invalidated: boolean }
40
+ /** A short-lived credential. Do not persist or log the assertion. */
41
+ export interface TaskAssertionResponse { assertion: string; expiresAt: SafeInteger; grantExpiresAt: SafeInteger }
42
+ export interface TaskGrantStatusDetails {
43
+ grantId: string; sourceIssuer: string; principal: string; client: string; resource: string; purpose: string
44
+ bounds: TaskGrantBounds; subjects: { readonly [key: string]: Exclude<JsonScalar, null> }; expiresAt: SafeInteger
45
+ }
46
+ export interface TaskGrantStatus { active: boolean; grant?: TaskGrantStatusDetails }
47
+
48
+ export interface DirectoryMember { issuer: string; subject: string; displayName?: string | null }
49
+ export interface SubjectRef { sourceId: string; kind: string; id: string }
50
+ export interface SourceBinding {
51
+ sourceRevision: string
52
+ version: string
53
+ integrity?: string
54
+ generation: string
55
+ }
56
+ export type CaseworkActionName = 'claim' | 'release' | OperationName
57
+ export interface CaseworkAction { operation: CaseworkActionName; href: string; ifMatch: string }
58
+ export interface CorrectionRoutingCopy {
59
+ sourceBinding: SourceBinding
60
+ reason?: string
61
+ flaggedFields: ReadonlyArray<string>
62
+ }
63
+ export interface WorkItemRouting {
64
+ ruleId?: string
65
+ because?: string
66
+ policyDigest?: string
67
+ }
68
+ export interface WorkItem {
69
+ itemId: string
70
+ subject: SubjectRef
71
+ occurrenceKind: OccurrenceKind
72
+ stage?: string
73
+ binding: SourceBinding
74
+ bindingReference: string
75
+ displayReference?: string
76
+ state: OccurrenceState
77
+ queueId: string
78
+ holder?: IssuerPrincipal
79
+ heldSince?: string
80
+ assignment?: AssignmentContext
81
+ revision: SafeInteger
82
+ firstObservedAt: string
83
+ passiveDueAt?: string
84
+ updatedAt: string
85
+ actions: ReadonlyArray<CaseworkAction>
86
+ routingCopy?: CorrectionRoutingCopy
87
+ hosted?: HostedWorkItemContext
88
+ routing?: WorkItemRouting
89
+ clockOccurrences?: ReadonlyArray<ClockOccurrenceView>
90
+ liveAttempt?: AttemptStatus
91
+ }
92
+ export interface Page<T> { items: ReadonlyArray<T>; nextCursor?: string; status: PageStatus }
93
+ export interface WorkItemPage extends Page<WorkItem> { servedQueues: ReadonlyArray<string> }
94
+ export type DirectoryTargetPurpose = 'assignment' | 'absence_person' | 'absence_cover'
95
+ export type DirectoryTargetsQuery = {
96
+ cursor?: string
97
+ limit?: SafeInteger
98
+ } & (
99
+ | { purpose: 'assignment'; queue: string; personIssuer?: never; personSubject?: never }
100
+ | { purpose: 'absence_person'; queue?: never; personIssuer?: never; personSubject?: never }
101
+ | { purpose: 'absence_cover'; queue?: never; personIssuer: string; personSubject: string }
102
+ )
103
+ export type DirectoryTargetPage = Page<DirectoryMember>
104
+ export type ListWorkItemsQuery = {
105
+ view: InboxView
106
+ sort?: InboxSort
107
+ queue?: string
108
+ cursor?: string
109
+ limit?: SafeInteger
110
+ } & (
111
+ | { sourceId: string; subjectKind: string; subjectId: string; reference?: never }
112
+ | { reference: string; sourceId?: never; subjectKind?: never; subjectId?: never }
113
+ | { reference?: never; sourceId?: never; subjectKind?: never; subjectId?: never }
114
+ )
115
+ export type InboxSort = 'due' | 'age' | 'type'
116
+ export interface NextWorkItemQuery { queue?: string; cursor?: string }
117
+ export interface SaveDraftRequest {
118
+ binding: SourceBinding
119
+ reason: string
120
+ flaggedFields?: ReadonlyArray<string>
121
+ }
122
+ export interface Draft {
123
+ itemId: string
124
+ author: IssuerPrincipal
125
+ binding: SourceBinding
126
+ reason: string
127
+ flaggedFields: ReadonlyArray<string>
128
+ revision: SafeInteger
129
+ updatedAt: string
130
+ }
131
+ export interface DraftResponse { draft: Draft }
132
+ export interface DecideRequest {
133
+ displayedBinding: SourceBinding
134
+ sourceProfileId: string
135
+ operation: OperationName
136
+ reason?: string
137
+ flaggedFields?: ReadonlyArray<string>
138
+ }
139
+ export interface RecoverAttemptRequest { sourceProfileId: string }
140
+ export interface SourceReceipt {
141
+ sourceRevision: string
142
+ resultingState: string
143
+ binding: SourceBinding
144
+ actorReference?: string
145
+ metadata: Readonly<Record<string, string>>
146
+ }
147
+ export interface AttemptStatus {
148
+ attemptId: string
149
+ itemId: string
150
+ state: AttemptState
151
+ itemRevision: SafeInteger
152
+ operation: OperationName
153
+ createdAt: string
154
+ receipt?: SourceReceipt
155
+ }
156
+ export interface MutationResponse { item: WorkItem; attempt?: AttemptStatus }
157
+ export interface HistoryEntryBase {
158
+ eventId: string
159
+ itemId: string
160
+ itemRevision: SafeInteger
161
+ kind: HistoryKind
162
+ occurredAt: string
163
+ actor?: IssuerPrincipal
164
+ profileId: string
165
+ }
166
+ export interface AttemptReservedHistoryEntry extends HistoryEntryBase {
167
+ kind: 'attempt_reserved'
168
+ detail: JsonObject & { attemptId: string; bindingReference: string; operation: OperationName }
169
+ }
170
+ export interface AttemptUncertainHistoryEntry extends HistoryEntryBase {
171
+ kind: 'attempt_uncertain'
172
+ detail: JsonObject & { attemptId: string; bindingReference: string; sourceRevision?: string | null; definitivelyRefused?: boolean }
173
+ }
174
+ export interface ActionCompletedHistoryEntry extends HistoryEntryBase {
175
+ kind: 'action_completed'
176
+ detail: JsonObject & { attemptId: string; bindingReference: string; sourceRevision: string; sourceReceipt: SourceReceipt }
177
+ }
178
+ export interface AttemptSettledHistoryEntry extends HistoryEntryBase {
179
+ kind: 'attempt_settled'
180
+ detail: JsonObject & { attemptId: string; bindingReference: string; operation: OperationName; outcome: 'applied' | 'not_applied'; reason: string; decidedBy: string }
181
+ }
182
+ export interface OtherHistoryEntry extends HistoryEntryBase {
183
+ kind: Exclude<HistoryKind, 'attempt_reserved' | 'attempt_uncertain' | 'action_completed' | 'attempt_settled'>
184
+ detail: JsonValue
185
+ }
186
+ export type HistoryEntry = AttemptReservedHistoryEntry | AttemptUncertainHistoryEntry | ActionCompletedHistoryEntry | AttemptSettledHistoryEntry | OtherHistoryEntry
187
+ export interface HoldingSummary {
188
+ principal: IssuerPrincipal
189
+ queueId: string
190
+ activeItems: SafeInteger
191
+ overdueItems: SafeInteger
192
+ }
193
+ export interface QueueRecord { id: string; label: string }
194
+ export interface PassiveTargetPolicy { id: string; after: { elapsed: string } }
195
+ export type RoutingPredicate = { equals: JsonValue } | { oneOf: ReadonlyArray<JsonValue> }
196
+ export interface RoutingCondition { activity?: 'review' | 'apply'; stage?: string; fields?: Readonly<Record<string, RoutingPredicate>> }
197
+ export interface RoutingRule { id: string; because: string; when: RoutingCondition; queue: string }
198
+ export interface DisplayReferencePolicy { field: string }
199
+ export interface SourceRequestPolicy { entity: string; queue: string; projection?: ReadonlyArray<string>; routing?: ReadonlyArray<RoutingRule>; displayReference?: DisplayReferencePolicy; clock?: string; target?: PassiveTargetPolicy }
200
+ export type WorkingWeekday = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday'
201
+ export interface CalendarPolicy { id: string; timezone: string; workingWeekdays: ReadonlyArray<WorkingWeekday>; holidaySet: string }
202
+ export interface ClockReminder { id: string; workingDaysBefore: SafeInteger }
203
+ export interface ClockStep { id: string; because: string; at: 'due'; action: { reassign: { queue: string } } }
204
+ export type ClockPolicy = {
205
+ scope: 'subject'; id: string; anchor: 'firstSubmittedAt'; completeOn: 'reviewCompleted'; after: { elapsed: string }; pauseWhile: ReadonlyArray<'awaitingApplicant'>
206
+ } | {
207
+ scope: 'activity'; id: string; anchor: 'stageEnteredAt'; calendar: string; after: { workingDays: SafeInteger }; dueTime: string;
208
+ atRisk?: { workingDaysBefore: SafeInteger }; reminders?: ReadonlyArray<ClockReminder>; steps?: ReadonlyArray<ClockStep>
209
+ }
210
+ export interface SourcePolicy {
211
+ id: string
212
+ adapter: string
213
+ description: string
214
+ requests: ReadonlyArray<SourceRequestPolicy>
215
+ }
216
+ export interface HostedRetentionPolicy { terminalDays: SafeInteger; accountabilityDays: SafeInteger }
217
+ export interface HostedOutcomePolicy { id: string; label: string; reasonRequired: boolean }
218
+ export interface HostedKindPolicy {
219
+ id: string
220
+ version: string
221
+ queue: string
222
+ decidingProfiles: ReadonlyArray<string>
223
+ retention: HostedRetentionPolicy
224
+ displaySchema: JsonValue
225
+ outcomes: ReadonlyArray<HostedOutcomePolicy>
226
+ }
227
+ export interface HostedWorkItemContext {
228
+ requesterReference: string
229
+ kind: string
230
+ version: string
231
+ display: JsonValue
232
+ kindPolicyDigest: string
233
+ outcomes: ReadonlyArray<HostedOutcomePolicy>
234
+ }
235
+ export interface HostedCreateRequest { kind: string; requesterReference: string; display: JsonValue }
236
+ export interface HostedNoteRequest { note: string }
237
+ export interface HostedCancelRequest { reason: string }
238
+ export interface HostedDecisionRequest { outcome: string; reason?: string }
239
+ export interface RequesterHostedItem {
240
+ itemId: string
241
+ requesterReference: string
242
+ kind: string
243
+ version: string
244
+ display: JsonValue
245
+ state: OccurrenceState
246
+ revision: SafeInteger
247
+ kindPolicyDigest: string
248
+ createdAt: string
249
+ updatedAt: string
250
+ }
251
+ export type HostedTerminalResult = {
252
+ itemId: string
253
+ eventId: string
254
+ requesterReference: string
255
+ kindPolicyDigest: string
256
+ terminalAt: string
257
+ } & (
258
+ | { state: 'completed'; outcome: string; actorRef: string }
259
+ | { state: 'cancelled'; cancellationReason: string }
260
+ )
261
+ export interface HostedTerminalQuery { cursor?: string; limit?: SafeInteger }
262
+ export interface HostedPageQuery { cursor?: string; limit?: SafeInteger }
263
+ export interface HostedNote {
264
+ noteId: string
265
+ itemId: string
266
+ note: string
267
+ itemRevision: SafeInteger
268
+ recordedAt: string
269
+ }
270
+ export type HostedHistoryKind = 'created' | 'claimed' | 'assigned' | 'delegated' | 'caseload_moved' | 'released' | 'note_added' | 'completed' | 'cancelled'
271
+ export interface HostedHistoryEntry {
272
+ eventId: string
273
+ itemId: string
274
+ itemRevision: SafeInteger
275
+ kind: HostedHistoryKind
276
+ occurredAt: string
277
+ actorRef?: string
278
+ assignment?: AssignmentContext
279
+ note?: string
280
+ outcome?: string
281
+ reason?: string
282
+ cancellationReason?: string
283
+ }
284
+ export interface HostedAccountabilityRecord {
285
+ itemId: string
286
+ eventId: string
287
+ actorRef: string
288
+ actor: IssuerPrincipal
289
+ profileId: string
290
+ outcome: string
291
+ reason?: string
292
+ recordedAt: string
293
+ retainedUntil: string
294
+ }
295
+ export interface Description {
296
+ projectId: string
297
+ policyVersion: string
298
+ queues: ReadonlyArray<QueueRecord>
299
+ sources: ReadonlyArray<SourcePolicy>
300
+ calendars: ReadonlyArray<CalendarPolicy>
301
+ clocks: ReadonlyArray<ClockPolicy>
302
+ hostedKinds: ReadonlyArray<HostedKindPolicy>
303
+ }
304
+ export interface TeamRecord {
305
+ id: string
306
+ members: ReadonlyArray<DirectoryMember>
307
+ supervisors: ReadonlyArray<DirectoryMember>
308
+ servedQueues: ReadonlyArray<string>
309
+ revision: SafeInteger
310
+ }
311
+ export interface DirectoryTeamUpdateRequest { staff: ReadonlyArray<DirectoryMember>; supervisors: ReadonlyArray<DirectoryMember>; servedQueues: ReadonlyArray<string> }
312
+ export interface DirectoryResponse { revision: SafeInteger; teams: ReadonlyArray<TeamRecord> }
313
+ export interface AbsenceInput { person: IssuerPrincipal; from: string; until: string; cover: IssuerPrincipal }
314
+ export interface AbsenceRecord extends AbsenceInput { absenceId: string; revision: SafeInteger }
315
+ export interface AbsencesQuery { cursor?: string; limit?: SafeInteger }
316
+ export interface AbsenceList { directoryRevision: SafeInteger; items: ReadonlyArray<AbsenceRecord>; nextCursor?: string }
317
+ export interface AssignmentContext { owner?: IssuerPrincipal; assignedBy?: IssuerPrincipal; absenceIds: ReadonlyArray<string>; staffingDiagnostic?: 'no_cover_available' }
318
+ export interface AssignmentRequest { assignee: IssuerPrincipal; reason?: string }
319
+ export interface DelegateRequest { delegate: IssuerPrincipal; reason?: string }
320
+ export interface CaseloadMoveRequest { from: IssuerPrincipal; to: IssuerPrincipal; queueId?: string; reason: string }
321
+ export interface CaseloadItemSelection { itemId: string; expectedRevision: SafeInteger }
322
+ export interface CaseloadApplyRequest { movement: CaseloadMoveRequest; items: ReadonlyArray<CaseloadItemSelection> }
323
+ export interface CaseloadPreviewQuery { cursor?: string; limit?: SafeInteger }
324
+ export interface CaseloadItemResult { itemId: string; result: 'moved' | 'not_visible' | 'not_eligible' | 'attempt_in_progress' | 'conflict'; revision?: SafeInteger }
325
+ export interface BootstrapDirectoryRequest {
326
+ teamId: string
327
+ staff: ReadonlyArray<IssuerPrincipal>
328
+ supervisors: ReadonlyArray<IssuerPrincipal>
329
+ queueId: string
330
+ }
331
+ export interface HoldingsQuery { cursor?: string; limit?: SafeInteger }
332
+ export interface CaseworkOutcome<T> { kind: 'complete'; value: T; traceId: string }
333
+
334
+ export type KnownCaseworkProblemCode =
335
+ | 'absence.cover-cycle'
336
+ | 'absence.invalid-period'
337
+ | 'absence.overlap'
338
+ | 'absence.self-cover'
339
+ | 'authentication.refused'
340
+ | 'clock.recompute-preview-expired' | 'cursor.expired'
341
+ | 'cursor.invalid'
342
+ | 'idempotency.expired'
343
+ | 'idempotency.key-reused'
344
+ | 'operation.not-authorized'
345
+ | 'precondition.failed'
346
+ | 'precondition.required'
347
+ | 'profile.not-authorized'
348
+ | 'profile.not-human'
349
+ | 'request.body-too-large'
350
+ | 'request.invalid'
351
+ | 'request.method-not-allowed'
352
+ | 'request.not-found'
353
+ | 'request.reason-unsupported'
354
+ | 'request.source-rejected'
355
+ | 'request.unprocessable'
356
+ | 'request.unsupported-media-type'
357
+ | 'runtime.failure'
358
+ | 'service.unavailable'
359
+ | 'source-profile.not-applicable'
360
+ | 'source-profile.required'
361
+ | 'source.bad-gateway'
362
+ | 'source.not-found'
363
+ | 'source.record-missing'
364
+ | 'source.reviewer-not-authorized'
365
+ | 'source.signature-invalid'
366
+ | 'work-item.already-claimed'
367
+ | 'work-item.not-holder'
368
+ | 'work-item.not-offered'
369
+ | 'work-item.not-visible'
370
+ | 'work-item.proposal-changed'
371
+ | 'work-item.recovery-pending'
372
+ | 'work-item.source-unavailable'
373
+ | 'work-item.superseded'
374
+ export type CaseworkProblemCode = KnownCaseworkProblemCode | (string & {})
375
+
376
+ export class CaseworkClientError extends Error {
377
+ readonly kind: 'configuration' | 'invalid_request' | 'transport' | 'problem' | 'protocol'
378
+ readonly code?: CaseworkProblemCode
379
+ readonly detail?: string
380
+ readonly status?: SafeInteger
381
+ readonly traceId?: string
382
+ readonly originalAttemptId?: string
383
+ readonly validation?: {
384
+ readonly path: string
385
+ readonly reason: 'kind_not_allowed' | 'reference_invalid' | 'object_required' | 'maximum_bytes_exceeded' | 'maximum_depth_exceeded' | 'schema_mismatch' | 'outcome_not_declared' | 'reason_required' | 'text_invalid'
386
+ }
387
+ readonly transportKind?: string
388
+ readonly protocolFailure?: string
389
+ }
390
+
391
+ export type ClockRuntimeState = 'running' | 'paused' | 'completed' | 'cancelled' | 'verification_pending' | 'source_facts_missing'
392
+ export type ClockNextEffect =
393
+ | { kind: 'reminder'; id: string; at: string }
394
+ | { kind: 'reassign'; id: string; at: string; because: string; queueId: string }
395
+ export interface ClockOccurrenceView {
396
+ clockOccurrenceId: string
397
+ subject: SubjectRef
398
+ clockId: string
399
+ state: ClockRuntimeState
400
+ policyDigest: string
401
+ calculationGeneration: SafeInteger
402
+ recomputeGeneration: SafeInteger
403
+ anchorAt?: string
404
+ startedAt?: string
405
+ dueAt?: string
406
+ atRiskAt?: string
407
+ completedAt?: string
408
+ nextEffect?: ClockNextEffect
409
+ upcomingEffects?: ReadonlyArray<ClockNextEffect>
410
+ }
411
+ export interface HolidaySetDocument { holidaySet: string; revision: SafeInteger; dates: ReadonlyArray<string> }
412
+ export interface HolidaySetRevisionInput { document: HolidaySetDocument }
413
+ export interface ClockRecomputeRequest { clockId: string; holidaySet: string; holidayRevision: SafeInteger }
414
+ export interface ClockRecomputeChange { clockOccurrenceId: string; itemId: string; expectedCalculationGeneration: SafeInteger; oldDueAt: string; proposedDueAt: string }
415
+ export interface ClockRecomputePreview { previewId: string; clockId: string; holidaySet: string; holidayRevision: SafeInteger; expiresAt: string; changes: ReadonlyArray<ClockRecomputeChange> }
416
+ export interface ClockRecomputeApplyRequest { previewId: string }
417
+ export interface ClockRecomputeResult { previewId: string; appliedOccurrences: ReadonlyArray<string> }
418
+
419
+ export class CaseworkClient {
420
+ constructor(config: CaseworkClientConfig)
421
+ description(token: string, profile: string): Promise<CaseworkOutcome<Description>>
422
+ createHostedItem(token: string, profile: string, idempotencyKey: string, request: HostedCreateRequest): Promise<CaseworkOutcome<RequesterHostedItem>>
423
+ getHostedItem(token: string, profile: string, itemId: string): Promise<CaseworkOutcome<RequesterHostedItem>>
424
+ addHostedNote(token: string, profile: string, itemId: string, expectedRevision: SafeInteger, idempotencyKey: string, note: HostedNoteRequest): Promise<CaseworkOutcome<RequesterHostedItem>>
425
+ requesterHostedNotes(token: string, profile: string, itemId: string, query?: HostedPageQuery | null): Promise<CaseworkOutcome<Page<HostedNote>>>
426
+ cancelHostedItem(token: string, profile: string, itemId: string, expectedRevision: SafeInteger, idempotencyKey: string, cancellation: HostedCancelRequest): Promise<CaseworkOutcome<HostedTerminalResult>>
427
+ hostedTerminalItems(token: string, profile: string, query?: HostedTerminalQuery | null): Promise<CaseworkOutcome<Page<HostedTerminalResult>>>
428
+ listHostedWorkItems(token: string, profile: string, query: ListWorkItemsQuery): Promise<CaseworkOutcome<WorkItemPage>>
429
+ getHostedWorkItem(token: string, profile: string, itemId: string): Promise<CaseworkOutcome<WorkItem>>
430
+ hostedWorkItemHistory(token: string, profile: string, itemId: string, query?: HostedPageQuery | null): Promise<CaseworkOutcome<Page<HostedHistoryEntry>>>
431
+ hostedAccountabilityRecord(token: string, profile: string, eventId: string): Promise<CaseworkOutcome<HostedAccountabilityRecord>>
432
+ claimHostedWorkItem(token: string, profile: string, action: CaseworkAction, idempotencyKey: string): Promise<CaseworkOutcome<MutationResponse>>
433
+ releaseHostedWorkItem(token: string, profile: string, action: CaseworkAction, idempotencyKey: string): Promise<CaseworkOutcome<MutationResponse>>
434
+ decideHostedWorkItem(token: string, profile: string, action: CaseworkAction, idempotencyKey: string, decision: HostedDecisionRequest): Promise<CaseworkOutcome<HostedTerminalResult>>
435
+ listWorkItems(token: string, profile: string, sourceProfile: string, query: ListWorkItemsQuery): Promise<CaseworkOutcome<WorkItemPage>>
436
+ nextWorkItem(token: string, profile: string, sourceProfile: string, query?: NextWorkItemQuery | null): Promise<CaseworkOutcome<WorkItemPage>>
437
+ getWorkItem(token: string, profile: string, sourceProfile: string, itemId: string): Promise<CaseworkOutcome<WorkItem>>
438
+ previewTaskTemplates(token: string, profile: string, sourceProfile: string, itemId: string): Promise<CaseworkOutcome<TaskTemplatePreviews>>
439
+ listTaskGrants(token: string, profile: string, sourceProfile: string, itemId: string): Promise<CaseworkOutcome<TaskGrantList>>
440
+ approveTaskGrant(token: string, profile: string, sourceProfile: string, itemId: string, expectedRevision: SafeInteger, idempotencyKey: string, approval: TaskApprovalRequest): Promise<CaseworkOutcome<TaskGrantView>>
441
+ revokeTaskGrant(token: string, profile: string, sourceProfile: string, itemId: string, grantId: string): Promise<CaseworkOutcome<TaskGrantRevocation>>
442
+ taskAssertion(token: string, grantId: string): Promise<CaseworkOutcome<TaskAssertionResponse>>
443
+ taskGrantStatus(token: string, grantId: string): Promise<CaseworkOutcome<TaskGrantStatus>>
444
+ claimWorkItem(token: string, profile: string, sourceProfile: string, action: CaseworkAction, idempotencyKey: string): Promise<CaseworkOutcome<MutationResponse>>
445
+ releaseWorkItem(token: string, profile: string, sourceProfile: string, action: CaseworkAction, idempotencyKey: string): Promise<CaseworkOutcome<MutationResponse>>
446
+ getDraft(token: string, profile: string, sourceProfile: string, itemId: string): Promise<CaseworkOutcome<DraftResponse>>
447
+ saveDraft(token: string, profile: string, sourceProfile: string, itemId: string, expectedRevision: SafeInteger, idempotencyKey: string, draft: SaveDraftRequest): Promise<CaseworkOutcome<DraftResponse>>
448
+ deleteDraft(token: string, profile: string, sourceProfile: string, itemId: string, expectedRevision: SafeInteger, idempotencyKey: string): Promise<CaseworkOutcome<null>>
449
+ decideWorkItem(token: string, profile: string, sourceProfile: string, action: CaseworkAction, idempotencyKey: string, decision: DecideRequest): Promise<CaseworkOutcome<MutationResponse>>
450
+ recoverDecision(token: string, profile: string, sourceProfile: string, itemId: string, attemptId: string, recovery: RecoverAttemptRequest): Promise<CaseworkOutcome<MutationResponse>>
451
+ recoverDecisionByKey(token: string, profile: string, sourceProfile: string, itemId: string, idempotencyKey: string, recovery: RecoverAttemptRequest): Promise<CaseworkOutcome<MutationResponse>>
452
+ workItemHistory(token: string, profile: string, sourceProfile: string, itemId: string, query?: HostedPageQuery | null): Promise<CaseworkOutcome<Page<HistoryEntry>>>
453
+ holdings(token: string, profile: string, sourceProfile: string, query?: HoldingsQuery | null): Promise<CaseworkOutcome<Page<HoldingSummary>>>
454
+ directory(token: string, profile: string): Promise<CaseworkOutcome<DirectoryResponse>>
455
+ directoryTargets(token: string, profile: string, query: DirectoryTargetsQuery): Promise<CaseworkOutcome<DirectoryTargetPage>>
456
+ bootstrapDirectory(token: string, profile: string, expectedRevision: SafeInteger, idempotencyKey: string, request: BootstrapDirectoryRequest): Promise<CaseworkOutcome<DirectoryResponse>>
457
+ updateDirectoryTeam(token: string, profile: string, teamId: string, expectedRevision: SafeInteger, idempotencyKey: string, request: DirectoryTeamUpdateRequest): Promise<CaseworkOutcome<DirectoryResponse>>
458
+ workItemClocks(token: string, profile: string, sourceProfile: string, itemId: string): Promise<CaseworkOutcome<ReadonlyArray<ClockOccurrenceView>>>
459
+ holidayRevision(token: string, profile: string, holidaySet: string, revision: SafeInteger): Promise<CaseworkOutcome<HolidaySetDocument>>
460
+ createHolidayRevision(token: string, profile: string, idempotencyKey: string, request: HolidaySetRevisionInput): Promise<CaseworkOutcome<HolidaySetDocument>>
461
+ previewClockRecompute(token: string, profile: string, request: ClockRecomputeRequest): Promise<CaseworkOutcome<ClockRecomputePreview>>
462
+ applyClockRecompute(token: string, profile: string, idempotencyKey: string, request: ClockRecomputeApplyRequest): Promise<CaseworkOutcome<ClockRecomputeResult>>
463
+ absences(token: string, profile: string, query?: AbsencesQuery | null): Promise<CaseworkOutcome<AbsenceList>>
464
+ createAbsence(token: string, profile: string, expectedRevision: SafeInteger, idempotencyKey: string, request: AbsenceInput): Promise<CaseworkOutcome<AbsenceRecord>>
465
+ updateAbsence(token: string, profile: string, absenceId: string, expectedRevision: SafeInteger, idempotencyKey: string, request: AbsenceInput): Promise<CaseworkOutcome<AbsenceRecord>>
466
+ deleteAbsence(token: string, profile: string, absenceId: string, expectedRevision: SafeInteger, idempotencyKey: string): Promise<CaseworkOutcome<null>>
467
+ assignWorkItem(token: string, profile: string, itemId: string, expectedRevision: SafeInteger, idempotencyKey: string, request: AssignmentRequest, sourceProfile?: string | null): Promise<CaseworkOutcome<MutationResponse>>
468
+ delegateWorkItem(token: string, profile: string, itemId: string, expectedRevision: SafeInteger, idempotencyKey: string, request: DelegateRequest, sourceProfile?: string | null): Promise<CaseworkOutcome<MutationResponse>>
469
+ previewCaseloadMove(token: string, profile: string, movement: CaseloadMoveRequest, query?: CaseloadPreviewQuery | null, sourceProfile?: string | null): Promise<CaseworkOutcome<Page<WorkItem>>>
470
+ applyCaseloadMove(token: string, profile: string, idempotencyKey: string, request: CaseloadApplyRequest, sourceProfile?: string | null): Promise<CaseworkOutcome<ReadonlyArray<CaseloadItemResult>>>
471
+ }
@@ -0,0 +1,161 @@
1
+ 'use strict';
2
+
3
+ const { types: { isProxy } } = require('node:util');
4
+ const native = require('./index');
5
+
6
+ const MAX_JSON_DEPTH = 64;
7
+ const MAX_JSON_NODES = 20_000;
8
+ const MAX_JSON_STRING_BYTES = 1024 * 1024;
9
+
10
+ class CaseworkClientError extends Error {
11
+ constructor(envelope) {
12
+ super(envelope.message);
13
+ this.name = 'CaseworkClientError';
14
+ this.kind = envelope.kind;
15
+ for (const field of ['code', 'detail', 'status', 'traceId', 'originalAttemptId', 'validation', 'transportKind', 'protocolFailure']) {
16
+ if (envelope[field] !== undefined && envelope[field] !== null) this[field] = envelope[field];
17
+ }
18
+ }
19
+ }
20
+
21
+ function normalized(error, fallbackKind) {
22
+ if (error instanceof CaseworkClientError) return error;
23
+ if (error instanceof Error && typeof error.message === 'string') {
24
+ try {
25
+ const envelope = JSON.parse(error.message);
26
+ if (envelope && typeof envelope.kind === 'string') return new CaseworkClientError(envelope);
27
+ } catch {
28
+ // napi argument conversion errors have no mapped envelope.
29
+ }
30
+ }
31
+ if (fallbackKind) {
32
+ return new CaseworkClientError({
33
+ kind: fallbackKind,
34
+ message: fallbackKind === 'configuration'
35
+ ? 'Casework client configuration is invalid'
36
+ : 'Casework client arguments are invalid',
37
+ });
38
+ }
39
+ return error;
40
+ }
41
+
42
+ function cloneJson(value, budget, depth) {
43
+ if (depth > MAX_JSON_DEPTH || ++budget.nodes > MAX_JSON_NODES) throw normalized({}, 'invalid_request');
44
+ if (value === null || typeof value === 'boolean') return value;
45
+ if (typeof value === 'string') {
46
+ budget.bytes += Buffer.byteLength(value, 'utf8');
47
+ if (budget.bytes > MAX_JSON_STRING_BYTES) throw normalized({}, 'invalid_request');
48
+ return value;
49
+ }
50
+ if (typeof value === 'number') {
51
+ if (!Number.isFinite(value) || (Number.isInteger(value) && !Number.isSafeInteger(value))) {
52
+ throw normalized({}, 'invalid_request');
53
+ }
54
+ return value;
55
+ }
56
+ if (value === undefined || typeof value !== 'object' || isProxy(value)) {
57
+ throw normalized({}, 'invalid_request');
58
+ }
59
+ const array = Array.isArray(value);
60
+ const prototype = Object.getPrototypeOf(value);
61
+ if (array ? prototype !== Array.prototype : prototype !== Object.prototype && prototype !== null) {
62
+ throw normalized({}, 'invalid_request');
63
+ }
64
+ if (budget.active.has(value)) throw normalized({}, 'invalid_request');
65
+ budget.active.add(value);
66
+ try {
67
+ if (array) return value.map((member) => cloneJson(member, budget, depth + 1));
68
+ const result = Object.create(null);
69
+ for (const key of Reflect.ownKeys(value)) {
70
+ if (typeof key !== 'string') throw normalized({}, 'invalid_request');
71
+ 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);
74
+ }
75
+ return result;
76
+ } finally {
77
+ budget.active.delete(value);
78
+ }
79
+ }
80
+
81
+ function sanitize(value) {
82
+ return cloneJson(value, { nodes: 0, bytes: 0, active: new WeakSet() }, 0);
83
+ }
84
+
85
+ const NativeCaseworkClient = native.CaseworkClient;
86
+
87
+ class CaseworkClient {
88
+ constructor(config) {
89
+ try {
90
+ this.native = new NativeCaseworkClient(sanitize(config));
91
+ } catch (error) {
92
+ throw normalized(error, 'configuration');
93
+ }
94
+ }
95
+ }
96
+
97
+ for (const [method, jsonIndexes] of [
98
+ ['description', []],
99
+ ['createHostedItem', [3]],
100
+ ['getHostedItem', []],
101
+ ['addHostedNote', [5]],
102
+ ['requesterHostedNotes', [3]],
103
+ ['cancelHostedItem', [5]],
104
+ ['hostedTerminalItems', [2]],
105
+ ['listHostedWorkItems', [2]],
106
+ ['getHostedWorkItem', []],
107
+ ['hostedWorkItemHistory', [3]],
108
+ ['hostedAccountabilityRecord', []],
109
+ ['claimHostedWorkItem', [2]],
110
+ ['releaseHostedWorkItem', [2]],
111
+ ['decideHostedWorkItem', [2, 4]],
112
+ ['listWorkItems', [3]],
113
+ ['nextWorkItem', [3]],
114
+ ['getWorkItem', []],
115
+ ['previewTaskTemplates', []],
116
+ ['listTaskGrants', []],
117
+ ['approveTaskGrant', [6]],
118
+ ['revokeTaskGrant', []],
119
+ ['taskAssertion', []],
120
+ ['taskGrantStatus', []],
121
+ ['claimWorkItem', [3]],
122
+ ['releaseWorkItem', [3]],
123
+ ['getDraft', []],
124
+ ['saveDraft', [6]],
125
+ ['deleteDraft', []],
126
+ ['decideWorkItem', [3, 5]],
127
+ ['recoverDecision', [5]],
128
+ ['recoverDecisionByKey', [5]],
129
+ ['workItemHistory', [4]],
130
+ ['holdings', [3]],
131
+ ['directory', []],
132
+ ['directoryTargets', [2]],
133
+ ['bootstrapDirectory', [4]],
134
+ ['updateDirectoryTeam', [5]],
135
+ ['workItemClocks', []],
136
+ ['holidayRevision', []],
137
+ ['createHolidayRevision', [3]],
138
+ ['previewClockRecompute', [2]],
139
+ ['applyClockRecompute', [3]],
140
+ ['absences', [2]],
141
+ ['createAbsence', [4]],
142
+ ['updateAbsence', [5]],
143
+ ['deleteAbsence', []],
144
+ ['assignWorkItem', [5]],
145
+ ['delegateWorkItem', [5]],
146
+ ['previewCaseloadMove', [2, 3]],
147
+ ['applyCaseloadMove', [3]],
148
+ ]) {
149
+ CaseworkClient.prototype[method] = function (...args) {
150
+ try {
151
+ for (const index of jsonIndexes) {
152
+ if (args[index] !== undefined && args[index] !== null) args[index] = sanitize(args[index]);
153
+ }
154
+ return this.native[method](...args).catch((error) => { throw normalized(error); });
155
+ } catch (error) {
156
+ throw normalized(error, 'invalid_request');
157
+ }
158
+ };
159
+ }
160
+
161
+ module.exports = { CaseworkClient, CaseworkClientError };