@registrystack/client 0.42.0 → 0.44.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 +37 -7
- package/breg/client.d.ts +49 -27
- package/breg/client.js +18 -8
- package/breg/index.d.ts +31 -16
- package/casework/client.d.ts +11 -10
- package/casework/client.js +39 -1
- package/casework/index.d.ts +3 -3
- package/compatibility.json +18 -0
- package/coordinator/client.d.ts +218 -0
- package/coordinator/client.js +140 -0
- package/coordinator/index.d.ts +19 -0
- package/coordinator/index.js +3 -0
- package/discovery/client.d.ts +2 -2
- package/discovery/client.js +3 -3
- package/discovery/index.d.ts +2 -2
- package/evidence/client.d.ts +9 -16
- package/evidence/index.d.ts +1 -1
- package/index.d.ts +2 -1
- package/index.js +2 -1
- package/messaging/client.d.ts +7 -6
- package/native.js +2 -2
- package/package.json +15 -6
- package/scheduling/client.d.ts +177 -11
- package/scheduling/client.js +6 -1
- package/scheduling/index.d.ts +6 -1
package/README.md
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
# @registrystack/client
|
|
2
2
|
|
|
3
3
|
One versioned Node.js package for the Discovery, Evidence, Base Registry
|
|
4
|
-
Engine, Casework, Messaging, and
|
|
4
|
+
Engine, Casework, Messaging, Scheduling, and Coordinator client APIs in Registry Stack.
|
|
5
|
+
|
|
6
|
+
Coordinator joins the client roster at v0.44.0. Its imports below require a
|
|
7
|
+
Coordinator-enabled v0.44.0 candidate or published package; published v0.43.0
|
|
8
|
+
contains the earlier six products. Check the version-specific release assets
|
|
9
|
+
before installing. Source integration does not establish publication.
|
|
5
10
|
|
|
6
11
|
## Install
|
|
7
12
|
|
|
@@ -11,13 +16,13 @@ npm install "@registrystack/client@<version>"
|
|
|
11
16
|
|
|
12
17
|
Requires Node.js 24.11 or newer. Supported targets are macOS arm64, Linux
|
|
13
18
|
arm64 with glibc, and Linux x64 with glibc; installing the package pulls in
|
|
14
|
-
one platform-specific optional dependency containing all
|
|
19
|
+
one platform-specific optional dependency containing all seven native
|
|
15
20
|
bindings.
|
|
16
21
|
|
|
17
22
|
## Usage
|
|
18
23
|
|
|
19
24
|
```js
|
|
20
|
-
const { discovery, evidence, breg, casework, messaging, scheduling } = require('@registrystack/client');
|
|
25
|
+
const { discovery, evidence, breg, casework, messaging, scheduling, coordinator } = require('@registrystack/client');
|
|
21
26
|
|
|
22
27
|
const registry = new breg.BaseRegistryClient({
|
|
23
28
|
baseUrl: 'https://registry.example.invalid/',
|
|
@@ -31,6 +36,9 @@ const messages = new messaging.MessagingClient({
|
|
|
31
36
|
const appointments = new scheduling.SchedulingClient({
|
|
32
37
|
baseUrl: 'https://scheduling.example.invalid/',
|
|
33
38
|
});
|
|
39
|
+
const workflows = new coordinator.CoordinatorClient({
|
|
40
|
+
baseUrl: 'https://coordinator.example.invalid/',
|
|
41
|
+
});
|
|
34
42
|
```
|
|
35
43
|
|
|
36
44
|
## Products
|
|
@@ -48,9 +56,22 @@ const appointments = new scheduling.SchedulingClient({
|
|
|
48
56
|
- `scheduling`: Registry Scheduling, published offerings, availability,
|
|
49
57
|
holds, and appointments over operator-anchored supply.
|
|
50
58
|
|
|
59
|
+
- `coordinator`: Registry Coordinator, workflow contracts, admission, run status,
|
|
60
|
+
inspection, and operator recovery. It is optional for direct product composition.
|
|
61
|
+
|
|
51
62
|
Each product remains in its own namespace because its routing,
|
|
52
63
|
authentication, errors, and verification rules are different.
|
|
53
64
|
|
|
65
|
+
## Compatibility metadata
|
|
66
|
+
|
|
67
|
+
The package includes the tested server baseline and compatible patch line for
|
|
68
|
+
the Discovery namespace. Read the version-matched record through the exported
|
|
69
|
+
JSON path:
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
const compatibility = require('@registrystack/client/compatibility.json');
|
|
73
|
+
```
|
|
74
|
+
|
|
54
75
|
## TypeScript
|
|
55
76
|
|
|
56
77
|
A TypeScript consumer also needs the Node type definitions, and must name
|
|
@@ -90,7 +111,7 @@ for the full rules.
|
|
|
90
111
|
|
|
91
112
|
A keyed BReg, Casework, Messaging, or Scheduling mutation whose outcome is
|
|
92
113
|
unknown is resent identically under the same idempotency key up to
|
|
93
|
-
`
|
|
114
|
+
`maximumMutationRetries` times, a client option: 0 to 2, default 2, and 0 sends it
|
|
94
115
|
once. Casework review-request create and cancel are excluded from this retry.
|
|
95
116
|
Reads, unkeyed calls, and every 4xx refusal are never resent. When the returned error
|
|
96
117
|
still reports `outcomeUnknown`, the mutation may have taken effect: recover by
|
|
@@ -100,12 +121,12 @@ attempt under the key was answered and may have committed: reconcile that
|
|
|
100
121
|
attempt before choosing a new key.
|
|
101
122
|
See [Unknown outcomes](https://docs.registrystack.org/reference/client-api/#unknown-outcomes-and-the-same-key-retry).
|
|
102
123
|
|
|
103
|
-
`breg.
|
|
104
|
-
the exact bytes of one Version 1
|
|
124
|
+
`breg.verifyHookDelivery({ method, path, headers, body, key })` authenticates
|
|
125
|
+
the exact bytes of one Version 1 hook delivery. The result returns
|
|
105
126
|
`deliveryTime` and `idempotencyKey`; the receiver must bound clock skew and
|
|
106
127
|
deduplicate once-only effects on authenticated `source` plus `id`, or on an
|
|
107
128
|
application business key. See
|
|
108
|
-
[Verify a
|
|
129
|
+
[Verify a hook delivery](https://docs.registrystack.org/reference/client-api/#verify-a-hook-delivery)
|
|
109
130
|
for a receiver example.
|
|
110
131
|
|
|
111
132
|
## Versioning
|
|
@@ -163,3 +184,12 @@ without the cursor after `410 review.result-expired`.
|
|
|
163
184
|
## License
|
|
164
185
|
|
|
165
186
|
Apache-2.0
|
|
187
|
+
|
|
188
|
+
Coordinator joins the seven-product roster at v0.44.0. The source facade also
|
|
189
|
+
contains held `render` and `@registrystack/client/render` namespaces. Default
|
|
190
|
+
assembly omits Render; `--include-render` adds it to an explicit local candidate
|
|
191
|
+
and does not authorize publication. Render takes a token or a resource-bound provider with
|
|
192
|
+
`bearerToken()` and performs one bounded render exchange. A correlation key is
|
|
193
|
+
not a durable idempotency promise. `outcomeUnknown` and `transportKind` preserve
|
|
194
|
+
whether an exchange may have completed; provider errors keep their own class.
|
|
195
|
+
Coordinator is optional.
|
package/breg/client.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type JsonObject = { readonly [key: string]: JsonValue }
|
|
|
7
7
|
/** An integer that satisfies `Number.isSafeInteger` and the option's documented bounds. */
|
|
8
8
|
export type SafeInteger = number
|
|
9
9
|
|
|
10
|
-
export type
|
|
10
|
+
export type HookVerificationRefusalCode =
|
|
11
11
|
| 'missing-header'
|
|
12
12
|
| 'invalid-delivery-time'
|
|
13
13
|
| 'duplicate-header'
|
|
@@ -17,7 +17,7 @@ export type WebhookVerificationRefusalCode =
|
|
|
17
17
|
| 'signature-mismatch'
|
|
18
18
|
| 'unsupported-version'
|
|
19
19
|
|
|
20
|
-
export interface
|
|
20
|
+
export interface HookDeliveryInput {
|
|
21
21
|
method: string
|
|
22
22
|
path: string
|
|
23
23
|
headers: Readonly<Record<string, string>>
|
|
@@ -27,7 +27,7 @@ export interface WebhookDeliveryInput {
|
|
|
27
27
|
key: Buffer
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export interface
|
|
30
|
+
export interface VerifiedHookDelivery {
|
|
31
31
|
readonly id: string
|
|
32
32
|
readonly source: string
|
|
33
33
|
readonly type: string
|
|
@@ -41,10 +41,21 @@ export interface VerifiedWebhookDelivery {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Authenticate one exact Base Registry Engine Version 1
|
|
44
|
+
* Authenticate one exact Base Registry Engine Version 1 hook delivery.
|
|
45
45
|
* Apply delivery-time skew and idempotency policy before acting on the body.
|
|
46
46
|
*/
|
|
47
|
-
export declare function
|
|
47
|
+
export declare function verifyHookDelivery(input: HookDeliveryInput): VerifiedHookDelivery
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Project one record revision into the event record view. `argumentsJson` is a
|
|
51
|
+
* JSON object with `registryRevision`, `recordType`, `descriptor`, `record`
|
|
52
|
+
* and optional `creationRevision`, `actionReceipts` and
|
|
53
|
+
* `proposalApplications`. The result is the view document as JSON text.
|
|
54
|
+
* Failures carry kind `event-record` and one of the codes `not-an-event-record`,
|
|
55
|
+
* `unsupported-version`, `malformed-descriptor`, `wrong-record-evidence`,
|
|
56
|
+
* `revision-mismatch`, `incompatible-metadata` or `invalid-input`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function eventRecordView(argumentsJson: string): string
|
|
48
59
|
|
|
49
60
|
export interface PrivateJwk {
|
|
50
61
|
readonly kty: string
|
|
@@ -62,24 +73,24 @@ export interface PrivateKeyJwtConfig {
|
|
|
62
73
|
* authentication). Defaults to the token endpoint URL. This is not the
|
|
63
74
|
* `resource` of the token request.
|
|
64
75
|
*/
|
|
65
|
-
audience?: string
|
|
76
|
+
audience?: string
|
|
66
77
|
/**
|
|
67
78
|
* The RFC 8707 resource indicator the token is requested for: the resource
|
|
68
79
|
* server's registered identifier, not a URL to fetch.
|
|
69
80
|
*/
|
|
70
|
-
resource?: string
|
|
81
|
+
resource?: string
|
|
71
82
|
/**
|
|
72
83
|
* The scopes requested for the token, sent as one space-delimited `scope`
|
|
73
84
|
* parameter. A requested scope may narrow the client's registered
|
|
74
85
|
* permission set; it can never widen it.
|
|
75
86
|
*/
|
|
76
|
-
scopes?: ReadonlyArray<string>
|
|
77
|
-
assertionLifetimeSeconds?: SafeInteger
|
|
78
|
-
refreshMarginSeconds?: SafeInteger
|
|
79
|
-
|
|
80
|
-
connectTimeoutMilliseconds?: SafeInteger
|
|
81
|
-
userAgent?: string
|
|
82
|
-
trustedRootCertificates?: string
|
|
87
|
+
scopes?: ReadonlyArray<string>
|
|
88
|
+
assertionLifetimeSeconds?: SafeInteger
|
|
89
|
+
refreshMarginSeconds?: SafeInteger
|
|
90
|
+
attemptTimeoutMilliseconds?: SafeInteger
|
|
91
|
+
connectTimeoutMilliseconds?: SafeInteger
|
|
92
|
+
userAgent?: string
|
|
93
|
+
trustedRootCertificates?: string
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
/** OAuth credentials are returned to the caller. Keep them out of logs and persistence. */
|
|
@@ -98,7 +109,7 @@ export interface ExchangeContext {
|
|
|
98
109
|
audience: string
|
|
99
110
|
generation: string
|
|
100
111
|
deadlineSeconds: SafeInteger
|
|
101
|
-
grantId?: string
|
|
112
|
+
grantId?: string
|
|
102
113
|
}
|
|
103
114
|
|
|
104
115
|
export type ExchangePrivateKeyJwtConfig = PrivateKeyJwtConfig & {
|
|
@@ -118,10 +129,10 @@ export interface RemoteExchangeSource {
|
|
|
118
129
|
bootstrap: ExchangePrivateKeyJwtConfig
|
|
119
130
|
bootstrapResource: string
|
|
120
131
|
bootstrapScope: string
|
|
121
|
-
|
|
122
|
-
connectTimeoutMilliseconds?: SafeInteger
|
|
123
|
-
userAgent?: string
|
|
124
|
-
trustedRootCertificates?: string
|
|
132
|
+
attemptTimeoutMilliseconds?: SafeInteger
|
|
133
|
+
connectTimeoutMilliseconds?: SafeInteger
|
|
134
|
+
userAgent?: string
|
|
135
|
+
trustedRootCertificates?: string
|
|
125
136
|
}
|
|
126
137
|
|
|
127
138
|
export type ExchangeAuthorizationConfig =
|
|
@@ -135,12 +146,12 @@ export type BaseRegistryAuthorization =
|
|
|
135
146
|
|
|
136
147
|
export interface BaseRegistryClientConfig {
|
|
137
148
|
baseUrl: string
|
|
138
|
-
authorization?: BaseRegistryAuthorization
|
|
139
|
-
|
|
140
|
-
connectTimeoutMilliseconds?: SafeInteger
|
|
141
|
-
|
|
142
|
-
userAgent?: string
|
|
143
|
-
trustedRootCertificates?: string
|
|
149
|
+
authorization?: BaseRegistryAuthorization
|
|
150
|
+
attemptTimeoutMilliseconds?: SafeInteger
|
|
151
|
+
connectTimeoutMilliseconds?: SafeInteger
|
|
152
|
+
maximumResponseBytes?: SafeInteger
|
|
153
|
+
userAgent?: string
|
|
154
|
+
trustedRootCertificates?: string
|
|
144
155
|
/**
|
|
145
156
|
* How many times a keyed mutation (create, patch, attachment upload or
|
|
146
157
|
* delete, lifecycle action, immediate action, batch, tombstone, statistics
|
|
@@ -149,7 +160,7 @@ export interface BaseRegistryClientConfig {
|
|
|
149
160
|
* number from 0 to 2, default 2; 0 sends it once. Any other value is a
|
|
150
161
|
* `configuration` error.
|
|
151
162
|
*/
|
|
152
|
-
|
|
163
|
+
maximumMutationRetries?: SafeInteger
|
|
153
164
|
}
|
|
154
165
|
|
|
155
166
|
export type RecordFormat = 'json' | 'json-ld'
|
|
@@ -473,6 +484,7 @@ export interface BRegProposalActionDescriptor {
|
|
|
473
484
|
readonly accessProfile: string
|
|
474
485
|
readonly operations: ReadonlyArray<string>
|
|
475
486
|
readonly readableInputs: ReadonlyArray<string>
|
|
487
|
+
readonly readableContextFields: ReadonlyArray<string>
|
|
476
488
|
}
|
|
477
489
|
|
|
478
490
|
export interface BRegActionAttachmentDescriptor {
|
|
@@ -536,7 +548,7 @@ export interface BRegActionReceipt {
|
|
|
536
548
|
|
|
537
549
|
export type BRegActionAvailability =
|
|
538
550
|
| { readonly available: true; readonly observedRevision: number }
|
|
539
|
-
| { readonly available: false; readonly observedRevision: number; readonly reason: 'guard-not-satisfied'; readonly recovery: 'none' }
|
|
551
|
+
| { readonly available: false; readonly observedRevision: number; readonly reason: 'guard-not-satisfied'; readonly guardReason?: string; readonly recovery: 'none' }
|
|
540
552
|
| { readonly available: null; readonly observedRevision: number; readonly reason: 'input-required'; readonly recovery: 'correct-input'; readonly missingInputs: ReadonlyArray<string> }
|
|
541
553
|
| { readonly available: null; readonly observedRevision: null; readonly reason: 'not-disclosed'; readonly recovery: 'none' }
|
|
542
554
|
|
|
@@ -795,6 +807,8 @@ export declare class BRegMetadata {
|
|
|
795
807
|
selectAction(actionIdentifier: string, expectedProfile: string): BRegActionBinding
|
|
796
808
|
selectTombstone(recordTypeIdentifier: string, expectedProfile: string): BRegTombstoneBinding
|
|
797
809
|
selectBatch(recordTypeIdentifier: string, expectedProfile: string): BRegBatchBinding
|
|
810
|
+
/** The event record descriptor declared for a record type, as JSON text. */
|
|
811
|
+
eventRecordDescriptor(recordType: string): string
|
|
798
812
|
}
|
|
799
813
|
|
|
800
814
|
/** Bounded declared identifiers; absent when any referenced field is unreadable. */
|
|
@@ -815,6 +829,7 @@ export interface BaseRegistryClientFailure extends Error {
|
|
|
815
829
|
readonly code?: string
|
|
816
830
|
readonly refusalCode?: string
|
|
817
831
|
readonly reasonCode?: string
|
|
832
|
+
readonly guardReason?: string
|
|
818
833
|
readonly fieldPath?: string
|
|
819
834
|
readonly constraint?: BRegConstraintViolation
|
|
820
835
|
readonly status?: number
|
|
@@ -842,6 +857,7 @@ export declare class BaseRegistryClientError extends Error implements BaseRegist
|
|
|
842
857
|
readonly code?: string
|
|
843
858
|
readonly refusalCode?: string
|
|
844
859
|
readonly reasonCode?: string
|
|
860
|
+
readonly guardReason?: string
|
|
845
861
|
readonly fieldPath?: string
|
|
846
862
|
readonly constraint?: BRegConstraintViolation
|
|
847
863
|
readonly status?: number
|
|
@@ -879,6 +895,12 @@ export declare class BaseRegistryClient {
|
|
|
879
895
|
ready(): Promise<CompleteOutcome<ProbeStatus>>
|
|
880
896
|
openapi(accessProfile?: string | null): Promise<RawOutcome>
|
|
881
897
|
registryMetadata(accessProfile?: string | null): Promise<RawOutcome>
|
|
898
|
+
/**
|
|
899
|
+
* The first revision of a record as
|
|
900
|
+
* `{recordType, recordId, revision, createdAt}` JSON text, or null when the
|
|
901
|
+
* caller may not read it (403 or 404).
|
|
902
|
+
*/
|
|
903
|
+
eventRecordCreationRevision(entityRoute: string, recordIdentifier: string, accessProfile?: string | null): Promise<string | null>
|
|
882
904
|
statisticsLive(dataset: string, from?: string | null, to?: string | null, accessProfile?: string | null, format?: StatisticsFormat | null): Promise<RawOutcome>
|
|
883
905
|
statisticsReleases(dataset: string, top?: SafeInteger | null, skipToken?: string | null, accessProfile?: string | null): Promise<RawOutcome>
|
|
884
906
|
statisticsLatestRelease(dataset: string, period: string, selection: StatisticsReleaseSelection, accessProfile?: string | null, format?: StatisticsFormat | null): Promise<RawOutcome>
|
package/breg/client.js
CHANGED
|
@@ -16,7 +16,7 @@ class BaseRegistryClientError extends Error {
|
|
|
16
16
|
for (const field of ['code', 'refusalCode', 'reasonCode', 'status', 'traceId', 'transportKind', 'tokenKind']) {
|
|
17
17
|
if (envelope[field] !== undefined && envelope[field] !== null) this[field] = envelope[field];
|
|
18
18
|
}
|
|
19
|
-
for (const field of ['fieldPath', 'constraint']) {
|
|
19
|
+
for (const field of ['fieldPath', 'constraint', 'guardReason']) {
|
|
20
20
|
if (envelope[field] !== undefined && envelope[field] !== null) {
|
|
21
21
|
Object.defineProperty(this, field, {
|
|
22
22
|
value: envelope[field],
|
|
@@ -82,7 +82,7 @@ function plainDataObject(value, expectedFields) {
|
|
|
82
82
|
return result;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
function
|
|
85
|
+
function hookHeaders(value) {
|
|
86
86
|
if (value === null || typeof value !== 'object' || Array.isArray(value) || isProxy(value)) {
|
|
87
87
|
throw inputError('invalid-request');
|
|
88
88
|
}
|
|
@@ -102,7 +102,7 @@ function webhookHeaders(value) {
|
|
|
102
102
|
return result;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
function
|
|
105
|
+
function verifyHookDelivery(value) {
|
|
106
106
|
try {
|
|
107
107
|
const input = plainDataObject(value, ['method', 'path', 'headers', 'body', 'key']);
|
|
108
108
|
if (typeof input.method !== 'string' || typeof input.path !== 'string'
|
|
@@ -110,10 +110,19 @@ function verifyWebhookDelivery(value) {
|
|
|
110
110
|
|| isSharedArrayBuffer(input.body.buffer) || isSharedArrayBuffer(input.key.buffer)) {
|
|
111
111
|
throw inputError('invalid-request');
|
|
112
112
|
}
|
|
113
|
-
input.headers =
|
|
113
|
+
input.headers = hookHeaders(input.headers);
|
|
114
114
|
input.body = Buffer.from(input.body);
|
|
115
115
|
input.key = Buffer.from(input.key);
|
|
116
|
-
return native.
|
|
116
|
+
return native.verifyHookDelivery(input);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
throw normalize(error, 'invalid-request');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function eventRecordView(argumentsJson) {
|
|
123
|
+
try {
|
|
124
|
+
if (typeof argumentsJson !== 'string') throw inputError('invalid-request');
|
|
125
|
+
return native.eventRecordView(argumentsJson);
|
|
117
126
|
} catch (error) {
|
|
118
127
|
throw normalize(error, 'invalid-request');
|
|
119
128
|
}
|
|
@@ -211,7 +220,7 @@ for (const [method, jsonIndexes, requiredIndexes] of [
|
|
|
211
220
|
['statisticsLive'], ['statisticsReleases'], ['statisticsLatestRelease'],
|
|
212
221
|
['statisticsReleaseVersion'], ['statisticsReleaseSeries'], ['statisticsPublish'],
|
|
213
222
|
['statisticsWithdraw'],
|
|
214
|
-
['recordRevisions'], ['getRecordRevision', [3]],
|
|
223
|
+
['recordRevisions'], ['getRecordRevision', [3]], ['eventRecordCreationRevision'],
|
|
215
224
|
['getRecord', [2]], ['listRecords', [1]], ['continueList', [0], [0]],
|
|
216
225
|
['getGeoJsonRecord', [2]], ['listGeoJsonRecords', [1]], ['continueGeoJsonList', [0], [0]],
|
|
217
226
|
['listCurrentRecords', [1]], ['continueCurrentList', [0], [0]],
|
|
@@ -298,7 +307,7 @@ const BRegPreparedProposal = preparedClass(native.BRegPreparedProposal, 'BRegPre
|
|
|
298
307
|
for (const name of [
|
|
299
308
|
'selectCreate', 'selectPatch',
|
|
300
309
|
'selectAction', 'selectTombstone', 'selectBatch', 'selectProposals', 'selectProposalGet',
|
|
301
|
-
'selectProposalReviewContext', 'selectProposalReviewStatus',
|
|
310
|
+
'selectProposalReviewContext', 'selectProposalReviewStatus', 'eventRecordDescriptor',
|
|
302
311
|
]) {
|
|
303
312
|
const original = native.BRegMetadata.prototype[name];
|
|
304
313
|
native.BRegMetadata.prototype[name] = function (...args) {
|
|
@@ -373,7 +382,8 @@ class PrivateKeyJwt {
|
|
|
373
382
|
}
|
|
374
383
|
|
|
375
384
|
module.exports = {
|
|
376
|
-
|
|
385
|
+
verifyHookDelivery,
|
|
386
|
+
eventRecordView,
|
|
377
387
|
PrivateKeyJwt,
|
|
378
388
|
BaseRegistryClient,
|
|
379
389
|
BaseRegistryClientError,
|
package/breg/index.d.ts
CHANGED
|
@@ -20,6 +20,12 @@ export declare class BaseRegistryClient {
|
|
|
20
20
|
recordRevisions(entityRoute: string, recordIdentifier: string, accessProfile?: string | undefined | null): Promise<RawOutcome>
|
|
21
21
|
/** Retrieve one exact retained revision as validated inert record JSON. */
|
|
22
22
|
getRecordRevision(entityRoute: string, recordIdentifier: string, revision: number, options?: any | undefined | null): Promise<RawOutcome>
|
|
23
|
+
/**
|
|
24
|
+
* Read the first revision of one record as the compact
|
|
25
|
+
* `{recordType, recordId, revision, createdAt}` JSON, or null when the
|
|
26
|
+
* caller may not read it.
|
|
27
|
+
*/
|
|
28
|
+
eventRecordCreationRevision(entityRoute: string, recordIdentifier: string, accessProfile?: string | undefined | null): Promise<string | null>
|
|
23
29
|
getRecord(entityRoute: string, recordIdentifier: string, options?: any | undefined | null): Promise<CompleteOutcome>
|
|
24
30
|
listRecords(entityRoute: string, options?: any | undefined | null): Promise<PageOutcome>
|
|
25
31
|
continueList(value: any): Promise<PageOutcome>
|
|
@@ -58,7 +64,7 @@ export declare class BaseRegistryClient {
|
|
|
58
64
|
/**
|
|
59
65
|
* Invoke one metadata-selected immediate action. An invocation whose
|
|
60
66
|
* outcome is unknown is resent identically under the same key, at most
|
|
61
|
-
* `
|
|
67
|
+
* `maximumMutationRetries` times.
|
|
62
68
|
*/
|
|
63
69
|
invokeAction(binding: BRegActionBinding, inputs: any, idempotencyKey: string, conditions?: BRegActionTargetConditions | undefined | null): Promise<CompleteOutcome>
|
|
64
70
|
/**
|
|
@@ -75,7 +81,7 @@ export declare class BaseRegistryClient {
|
|
|
75
81
|
/**
|
|
76
82
|
* Explicitly send a recovered invocation under its original key. An
|
|
77
83
|
* invocation whose outcome is unknown is resent identically under that
|
|
78
|
-
* key, at most `
|
|
84
|
+
* key, at most `maximumMutationRetries` times.
|
|
79
85
|
*/
|
|
80
86
|
executeRecoveredAction(binding: BRegActionBinding, recovered: BRegRecoveredAction): Promise<CompleteOutcome>
|
|
81
87
|
/** Execute a recovered proposal start with its exact original request and key. */
|
|
@@ -91,7 +97,7 @@ export declare class BaseRegistryClient {
|
|
|
91
97
|
/**
|
|
92
98
|
* Execute one metadata-selected atomic batch. A batch whose outcome is
|
|
93
99
|
* unknown is resent identically under the same key, at most
|
|
94
|
-
* `
|
|
100
|
+
* `maximumMutationRetries` times.
|
|
95
101
|
*/
|
|
96
102
|
batchRecords(binding: BRegBatchBinding, request: any, idempotencyKey: string): Promise<CompleteOutcome>
|
|
97
103
|
/**
|
|
@@ -207,6 +213,8 @@ export declare class BRegIngestionPrefixDigest {
|
|
|
207
213
|
export type IngestionPrefixDigest = BRegIngestionPrefixDigest
|
|
208
214
|
|
|
209
215
|
export declare class BRegMetadata {
|
|
216
|
+
/** The event record descriptor declared for one record type, as JSON text. */
|
|
217
|
+
eventRecordDescriptor(recordType: string): string
|
|
210
218
|
/** Read-only capability inventory for each exact Action/profile pair. */
|
|
211
219
|
get proposalActions(): any
|
|
212
220
|
/** Caller-filtered inert descriptors. Selectors below remain the only authority constructors. */
|
|
@@ -328,6 +336,22 @@ export interface CompleteOutcome {
|
|
|
328
336
|
*/
|
|
329
337
|
export declare function encodeIngestionChunk(chunkIndex: number, items: any, prefixDigest: string): BRegIngestionChunk
|
|
330
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Project one record revision into the event record view. The input is the
|
|
341
|
+
* JSON arguments document of the Rust projection; the result is the view
|
|
342
|
+
* document as JSON text.
|
|
343
|
+
*/
|
|
344
|
+
export declare function eventRecordView(argumentsJson: string): string
|
|
345
|
+
|
|
346
|
+
/** Exact BReg hook request supplied by a receiver. */
|
|
347
|
+
export interface HookDeliveryInput {
|
|
348
|
+
method: string
|
|
349
|
+
path: string
|
|
350
|
+
headers: Record<string, string>
|
|
351
|
+
body: Buffer
|
|
352
|
+
key: Buffer
|
|
353
|
+
}
|
|
354
|
+
|
|
331
355
|
/** Validated product result serialized before the JavaScript number boundary. */
|
|
332
356
|
export interface JsonOutcome {
|
|
333
357
|
kind: string
|
|
@@ -364,8 +388,8 @@ export interface RawOutcome {
|
|
|
364
388
|
reprDigest?: string
|
|
365
389
|
}
|
|
366
390
|
|
|
367
|
-
/** Authenticated BReg
|
|
368
|
-
export interface
|
|
391
|
+
/** Authenticated BReg hook metadata and exact body. */
|
|
392
|
+
export interface VerifiedHookDelivery {
|
|
369
393
|
id: string
|
|
370
394
|
source: string
|
|
371
395
|
type: string
|
|
@@ -378,14 +402,5 @@ export interface VerifiedWebhookDelivery {
|
|
|
378
402
|
body: Buffer
|
|
379
403
|
}
|
|
380
404
|
|
|
381
|
-
/** Verify a BReg Version 1
|
|
382
|
-
export declare function
|
|
383
|
-
|
|
384
|
-
/** Exact BReg webhook request supplied by a receiver. */
|
|
385
|
-
export interface WebhookDeliveryInput {
|
|
386
|
-
method: string
|
|
387
|
-
path: string
|
|
388
|
-
headers: Record<string, string>
|
|
389
|
-
body: Buffer
|
|
390
|
-
key: Buffer
|
|
391
|
-
}
|
|
405
|
+
/** Verify a BReg Version 1 hook signature without applying receiver policy. */
|
|
406
|
+
export declare function verifyHookDelivery(input: HookDeliveryInput): VerifiedHookDelivery
|
package/casework/client.d.ts
CHANGED
|
@@ -8,11 +8,11 @@ export type JsonObject = { readonly [key: string]: JsonValue }
|
|
|
8
8
|
|
|
9
9
|
export interface CaseworkClientConfig {
|
|
10
10
|
baseUrl: string
|
|
11
|
-
|
|
12
|
-
connectTimeoutMilliseconds?: SafeInteger
|
|
13
|
-
|
|
14
|
-
userAgent?: string
|
|
15
|
-
trustedRootCertificates?: string
|
|
11
|
+
attemptTimeoutMilliseconds?: SafeInteger
|
|
12
|
+
connectTimeoutMilliseconds?: SafeInteger
|
|
13
|
+
maximumResponseBytes?: SafeInteger
|
|
14
|
+
userAgent?: string
|
|
15
|
+
trustedRootCertificates?: string
|
|
16
16
|
/**
|
|
17
17
|
* How many times an idempotency-keyed mutation whose outcome is unknown is
|
|
18
18
|
* resent, identically and under the same key, before its error is
|
|
@@ -20,7 +20,7 @@ export interface CaseworkClientConfig {
|
|
|
20
20
|
* unkeyed operations, and review request create and cancel are never
|
|
21
21
|
* resent. Any other value is a `configuration` error.
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
maximumMutationRetries?: SafeInteger
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export type PageStatus = 'complete' | 'budget-exhausted' | 'source-unavailable'
|
|
@@ -72,7 +72,7 @@ export type DirectoryTargetPage = Page<DirectoryMember>
|
|
|
72
72
|
export interface QueueRecord { id: string; label: string }
|
|
73
73
|
export type RoutingPredicate = { equals: JsonValue } | { oneOf: ReadonlyArray<JsonValue> }
|
|
74
74
|
export interface RoutingCondition { stage?: string; fields?: Readonly<Record<string, RoutingPredicate>> }
|
|
75
|
-
export interface RoutingRule { id: string; because: string; when: RoutingCondition; queue: string }
|
|
75
|
+
export interface RoutingRule { id: string; label?: string; because: string; when: RoutingCondition; queue: string }
|
|
76
76
|
export type WorkingWeekday = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday'
|
|
77
77
|
export interface CalendarPolicy { id: string; timezone: string; workingWeekdays: ReadonlyArray<WorkingWeekday>; holidaySet: string }
|
|
78
78
|
export interface WorkingDays { workingDays: SafeInteger }
|
|
@@ -189,7 +189,7 @@ export class CaseworkClientError extends Error {
|
|
|
189
189
|
readonly traceId?: string
|
|
190
190
|
readonly validation?: {
|
|
191
191
|
readonly path: string
|
|
192
|
-
readonly reason: 'policy-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' | 'public-reason-required' | 'public-reason-not-declared' | 'approval-outcome-differs'
|
|
192
|
+
readonly reason: 'binding-invalid' | 'field-required' | 'policy-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' | 'public-reason-required' | 'public-reason-not-declared' | 'approval-outcome-differs'
|
|
193
193
|
/** Outcome identifiers the review policy declares for the requested settlement when an outcome is refused; empty otherwise. */
|
|
194
194
|
readonly allowed: ReadonlyArray<string>
|
|
195
195
|
}
|
|
@@ -364,15 +364,16 @@ export interface ReviewAccountabilityRecord {
|
|
|
364
364
|
occurredAt: string; retainedUntil: string
|
|
365
365
|
decisionReceipt?: ReviewDecisionReceipt
|
|
366
366
|
}
|
|
367
|
-
export interface ReviewStagePolicy { id: string; queue: string; decidingProfiles: ReadonlyArray<string>; requiredApprovals: SafeInteger; excludeInitiator?: boolean; excludePreviousStageReviewers?: boolean }
|
|
367
|
+
export interface ReviewStagePolicy { id: string; label?: string; queue: string; decidingProfiles: ReadonlyArray<string>; requiredApprovals: SafeInteger; negativeDecisions?: 'settle' | 'advise'; excludeInitiator?: boolean; excludePreviousStageReviewers?: boolean }
|
|
368
368
|
export interface ReviewRetentionPolicy { terminalRetentionDays: SafeInteger; accountabilityRetentionDays: SafeInteger }
|
|
369
369
|
export interface ReviewContextContract { id: string; revision: ContentDigest; schemaDigest: ContentDigest }
|
|
370
370
|
export type ReviewContextPolicy = { mode: 'submitted' } | { mode: 'current-source'; provider: string; contract: ReviewContextContract }
|
|
371
371
|
export type ReviewContextCapability = 'human-display' | 'service-status' | 'task-grant-context' | 'routing-context'
|
|
372
372
|
export interface ReviewContextProviderPolicy { id: string; capabilities: ReadonlyArray<ReviewContextCapability>; sourceNamespace: string; deploymentRef: string; serviceProfiles?: Partial<Record<ReviewContextCapability, string>> }
|
|
373
|
-
export interface ReviewPolicy { id: string; version: string; purpose: 'approval' | 'answer'; context: ReviewContextPolicy; routing?: ReadonlyArray<RoutingRule>; stages: ReadonlyArray<ReviewStagePolicy>; clocks?: ReadonlyArray<string>; retention: ReviewRetentionPolicy; displaySchema: JsonValue; resultSchema?: JsonValue; outcomes?: ReadonlyArray<{ id: string; label: string; settlement: 'approved' | 'rejected' | 'changes-requested' | 'answered'; reasonRequired: boolean; publicReason: 'required' | 'optional' | 'none'; resultRequired?: boolean }> }
|
|
373
|
+
export interface ReviewPolicy { id: string; label?: string; version: string; purpose: 'approval' | 'answer'; context: ReviewContextPolicy; routing?: ReadonlyArray<RoutingRule>; stages: ReadonlyArray<ReviewStagePolicy>; clocks?: ReadonlyArray<string>; retention: ReviewRetentionPolicy; displaySchema: JsonValue; resultSchema?: JsonValue; outcomes?: ReadonlyArray<{ id: string; label: string; settlement: 'approved' | 'rejected' | 'changes-requested' | 'answered'; reasonRequired: boolean; publicReason: 'required' | 'optional' | 'none'; resultRequired?: boolean }> }
|
|
374
374
|
export interface ReviewPolicyClosure {
|
|
375
375
|
identity: PolicyBinding
|
|
376
|
+
label?: string
|
|
376
377
|
purpose: 'approval' | 'answer'
|
|
377
378
|
context: ReviewContextPolicy
|
|
378
379
|
routing?: ReadonlyArray<RoutingRule>
|
package/casework/client.js
CHANGED
|
@@ -85,12 +85,50 @@ function sanitize(value, kind) {
|
|
|
85
85
|
return cloneJson(value, { nodes: 0, bytes: 0, active: new WeakSet() }, 0, kind);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
function configurationValue(config) {
|
|
89
|
+
if (!config || typeof config !== 'object' || Array.isArray(config) || isProxy(config)) {
|
|
90
|
+
throw normalized({}, 'configuration');
|
|
91
|
+
}
|
|
92
|
+
const prototype = Object.getPrototypeOf(config);
|
|
93
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
94
|
+
throw normalized({}, 'configuration');
|
|
95
|
+
}
|
|
96
|
+
const allowed = new Set([
|
|
97
|
+
'baseUrl',
|
|
98
|
+
'attemptTimeoutMilliseconds',
|
|
99
|
+
'connectTimeoutMilliseconds',
|
|
100
|
+
'maximumResponseBytes',
|
|
101
|
+
'userAgent',
|
|
102
|
+
'trustedRootCertificates',
|
|
103
|
+
'maximumMutationRetries',
|
|
104
|
+
]);
|
|
105
|
+
const copy = Object.create(null);
|
|
106
|
+
for (const key of Reflect.ownKeys(config)) {
|
|
107
|
+
if (typeof key !== 'string' || !allowed.has(key)) throw normalized({}, 'configuration');
|
|
108
|
+
const descriptor = Object.getOwnPropertyDescriptor(config, key);
|
|
109
|
+
if (!descriptor || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')) {
|
|
110
|
+
throw normalized({}, 'configuration');
|
|
111
|
+
}
|
|
112
|
+
const value = descriptor.value;
|
|
113
|
+
if (key === 'baseUrl' || key === 'userAgent' || key === 'trustedRootCertificates') {
|
|
114
|
+
if (typeof value !== 'string') throw normalized({}, 'configuration');
|
|
115
|
+
copy[key] = value;
|
|
116
|
+
} else {
|
|
117
|
+
if (!Number.isSafeInteger(value) || value < 0 || value > 0xffff_ffff) {
|
|
118
|
+
throw normalized({}, 'configuration');
|
|
119
|
+
}
|
|
120
|
+
copy[key] = value;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return copy;
|
|
124
|
+
}
|
|
125
|
+
|
|
88
126
|
const NativeCaseworkClient = native.CaseworkClient;
|
|
89
127
|
|
|
90
128
|
class CaseworkClient {
|
|
91
129
|
constructor(config) {
|
|
92
130
|
try {
|
|
93
|
-
this.native = new NativeCaseworkClient(
|
|
131
|
+
this.native = new NativeCaseworkClient(configurationValue(config));
|
|
94
132
|
} catch (error) {
|
|
95
133
|
throw normalized(error, 'configuration');
|
|
96
134
|
}
|
package/casework/index.d.ts
CHANGED
|
@@ -55,16 +55,16 @@ export declare class CaseworkClient {
|
|
|
55
55
|
|
|
56
56
|
export interface CaseworkClientConfig {
|
|
57
57
|
baseUrl: string
|
|
58
|
-
|
|
58
|
+
attemptTimeoutMilliseconds?: number
|
|
59
59
|
connectTimeoutMilliseconds?: number
|
|
60
|
-
|
|
60
|
+
maximumResponseBytes?: number
|
|
61
61
|
userAgent?: string
|
|
62
62
|
trustedRootCertificates?: string
|
|
63
63
|
/**
|
|
64
64
|
* How many times a keyed mutation whose outcome is unknown is resent under
|
|
65
65
|
* the same idempotency key: 0 to 2, default 2, and 0 disables the resend.
|
|
66
66
|
*/
|
|
67
|
-
|
|
67
|
+
maximumMutationRetries?: number
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
export interface CaseworkOutcome {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "registry-stack.sdk-compatibility.v1",
|
|
3
|
+
"sdkPackage": {
|
|
4
|
+
"name": "registry-stack-client",
|
|
5
|
+
"version": "0.44.0"
|
|
6
|
+
},
|
|
7
|
+
"namespaces": {
|
|
8
|
+
"discovery": {
|
|
9
|
+
"testedServerBaseline": "0.44.0",
|
|
10
|
+
"compatibleServerPatchLine": "0.44.x",
|
|
11
|
+
"responseCompatibility": {
|
|
12
|
+
"additiveObjectMembers": "ignored-after-duplicate-key-rejection",
|
|
13
|
+
"unknownProblemCodes": "http-status-only",
|
|
14
|
+
"proof": "registry-discovery-client::client::tests::real_client_ignores_additive_response_members_at_every_response_level"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|