@openresidency/sdk 0.1.0 → 0.2.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 +68 -11
- package/dist/index.d.ts +503 -9
- package/dist/index.js +322 -69
- package/dist/openapi.d.ts +6172 -0
- package/dist/openapi.js +6 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
# @openresidency/sdk
|
|
2
2
|
|
|
3
3
|
Typed client for the OpenResidency API. Dependency-free, uses the global `fetch`
|
|
4
|
-
(Node 18+ or any browser).
|
|
4
|
+
(Node 18+ or any browser).
|
|
5
|
+
|
|
6
|
+
The client reaches the whole API. Its types are generated from `docs/openapi.yaml`
|
|
7
|
+
(`sdk/src/openapi.ts`, regenerated with `npm run sdk:generate` at the repository root), and
|
|
8
|
+
CI fails if the spec misses a route the server declares or if the generated file is stale.
|
|
9
|
+
So what the client can call is what the server serves, by construction.
|
|
5
10
|
|
|
6
11
|
## Install
|
|
7
12
|
|
|
@@ -9,12 +14,18 @@ Typed client for the OpenResidency API. Dependency-free, uses the global `fetch`
|
|
|
9
14
|
npm install @openresidency/sdk
|
|
10
15
|
```
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
Pin the version to the server release you integrate against; `@openresidency/sdk@0.1.0` is
|
|
18
|
+
the client for `v0.1.0`.
|
|
19
|
+
|
|
20
|
+
## Two ways in
|
|
21
|
+
|
|
22
|
+
**Named methods** cover what a sector service, a wallet backend or a registry console calls,
|
|
23
|
+
and pick the right credential for each:
|
|
13
24
|
|
|
14
25
|
```ts
|
|
15
26
|
import { OpenResidencyClient } from '@openresidency/sdk';
|
|
16
27
|
|
|
17
|
-
// Identity verification
|
|
28
|
+
// Identity verification and issuance are operator actions, so the client needs a credential.
|
|
18
29
|
const client = new OpenResidencyClient({
|
|
19
30
|
baseUrl: 'https://id.katsina.gov.ng',
|
|
20
31
|
operatorKey: process.env.OPERATOR_KEY, // ork_..., minted at POST /operator/keys
|
|
@@ -39,6 +50,13 @@ console.log(issued.residentId, issued.credentialJwt);
|
|
|
39
50
|
const check = await client.verifyCredential(issued.credentialJwt!);
|
|
40
51
|
console.log(check.valid, check.subject);
|
|
41
52
|
|
|
53
|
+
// The relationship's ORCS state, and moving it
|
|
54
|
+
const rel = await client.relationship(issued.residentId!);
|
|
55
|
+
await client.transitionRelationship(issued.residentId!, {
|
|
56
|
+
status: 'SUSPENDED',
|
|
57
|
+
reason: 'Address under review',
|
|
58
|
+
});
|
|
59
|
+
|
|
42
60
|
// Consent
|
|
43
61
|
await client.grantConsent({
|
|
44
62
|
residentId: issued.residentId!,
|
|
@@ -49,19 +67,58 @@ await client.grantConsent({
|
|
|
49
67
|
const consents = await client.listConsents(issued.residentId!);
|
|
50
68
|
```
|
|
51
69
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Pass `adminKey` to reach the registry and audit endpoints:
|
|
70
|
+
**`request`** reaches every operation in the spec, including the ones with no named method.
|
|
71
|
+
The path is a string literal from the spec; its parameters, body and response are typed:
|
|
55
72
|
|
|
56
73
|
```ts
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
74
|
+
const credential = await client.request('get', '/residency/{residentId}/credential', {
|
|
75
|
+
path: { residentId: 'KT-GT1F-75WJ-6' },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const page = await client.request('get', '/admin/residents', {
|
|
79
|
+
query: { countryCode: 'NG', limit: 50 },
|
|
80
|
+
auth: 'operator',
|
|
60
81
|
});
|
|
61
|
-
const chain = await admin.verifyAuditChain(); // { ok: true, length: N }
|
|
62
|
-
const page = await admin.listResidents({ countryCode: 'NG', limit: 50 });
|
|
63
82
|
```
|
|
64
83
|
|
|
84
|
+
`auth` is `'auto'` by default (the configured operator credential, if any), `'operator'` to
|
|
85
|
+
require one, `'none'` to send nothing, `{ bearer }` for a one-off token such as the
|
|
86
|
+
OpenID4VCI access token, or `{ headers }` for a one-off header such as `x-ussd-secret`.
|
|
87
|
+
|
|
88
|
+
## What the named methods cover
|
|
89
|
+
|
|
90
|
+
| Area | Methods |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| Health | `live`, `ready` |
|
|
93
|
+
| Identity | `identityChallenge`, `verifyIdentity` |
|
|
94
|
+
| Residency | `countries`, `issueResidency`, `residencyStatus`, `verifyCredential`, `revokeResidency`, `eraseResidency`, `retentionSweep`, `provisionalSweep`, `reconcile` |
|
|
95
|
+
| Relationship and credential lifecycle (ORCS §6, §10) | `relationship`, `transitionRelationship`, `credential`, `transitionCredential`, `refusal`, `reviewRefusal` |
|
|
96
|
+
| Assurance (ORCS §7) | `assuranceProfiles`, `assuranceMappings`, `resolveAssurance`, `residentAssurance` |
|
|
97
|
+
| Consent and legal bases (ORCS §9) | `listConsents`, `grantConsent`, `revokeConsent`, `legalBases`, `legalBasis`, `deactivateLegalBasis` |
|
|
98
|
+
| Operator identity | `operatorLogin`, `me`, `listOperators`, `createOperator`, `disableOperator`, `listKeys`, `createKey`, `rotateKey`, `revokeKey` |
|
|
99
|
+
| Audit and admin | `auditLog`, `verifyAuditChain`, `listResidents`, `stats`, `statistics`, `statisticsCsv` |
|
|
100
|
+
| Offline | `qr`, `ussd` |
|
|
101
|
+
| OpenID4VCI (issuing into a wallet) | `credentialIssuerMetadata`, `oauthAuthorizationServerMetadata`, `createCredentialOffer`, `walletToken`, `walletNonce`, `walletCredential` |
|
|
102
|
+
| OpenID4VP (asking a wallet to present) | `createPresentationRequest`, `presentationRequest`, `submitPresentation`, `presentationResult` |
|
|
103
|
+
| W3C VC-API | `vcIssue`, `vcVerify`, `vpVerify` |
|
|
104
|
+
| Discovery and trust | `didDocument`, `didDocumentFor`, `statusList`, `oidcDiscovery` |
|
|
105
|
+
|
|
106
|
+
The OIDC login interaction (`/interaction/{uid}/...`), WebAuthn registration and the upstream
|
|
107
|
+
enrolment callback are browser-driven and have no named method. `request` reaches them.
|
|
108
|
+
|
|
109
|
+
## Types
|
|
110
|
+
|
|
111
|
+
`paths` and `components` are exported from the generated contract, so a caller can name
|
|
112
|
+
any request or response type:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import type { components } from '@openresidency/sdk';
|
|
116
|
+
type Relationship = components['schemas']['RelationshipStatus'];
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The hand-written interfaces the 0.1.0 methods return (`IssueResult`, `ResidencyStatus`,
|
|
120
|
+
`ConsentRecord`, ...) are unchanged.
|
|
121
|
+
|
|
65
122
|
## Errors
|
|
66
123
|
|
|
67
124
|
Non-2xx responses throw `OpenResidencyError` with `status` and parsed `body`.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,10 +2,112 @@
|
|
|
2
2
|
* OpenResidency Interoperability SDK.
|
|
3
3
|
*
|
|
4
4
|
* A small, dependency-free typed client for the OpenResidency API. Uses the global
|
|
5
|
-
* fetch (Node 18+ or any browser).
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* fetch (Node 18+ or any browser).
|
|
6
|
+
*
|
|
7
|
+
* Two layers:
|
|
8
|
+
*
|
|
9
|
+
* - `client.request(method, path, opts)` reaches EVERY operation in docs/openapi.yaml. The
|
|
10
|
+
* path, its parameters, the request body and the response are typed from `openapi.ts`,
|
|
11
|
+
* which is generated from that file (`npm run sdk:generate` at the repository root) and
|
|
12
|
+
* checked in CI against the controllers, so the client cannot fall behind the server.
|
|
13
|
+
* - Named methods (`issueResidency`, `transitionRelationship`, ...) wrap the operations a
|
|
14
|
+
* sector service, a wallet backend or a registry console calls, and choose the right
|
|
15
|
+
* credentials for each. They are thin: each is one `request` call.
|
|
16
|
+
*
|
|
17
|
+
* Browser-driven flows (the OIDC login interaction under /interaction, WebAuthn
|
|
18
|
+
* registration, the upstream enrolment callback) have no named method; a server-side
|
|
19
|
+
* client does not drive them, but `request` reaches them if one has to.
|
|
20
|
+
*/
|
|
21
|
+
import type { components, paths } from './openapi.js';
|
|
22
|
+
export type { components, paths } from './openapi.js';
|
|
23
|
+
export type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
|
|
24
|
+
type OperationLike = {
|
|
25
|
+
responses: unknown;
|
|
26
|
+
};
|
|
27
|
+
/** The paths that serve `M` (`PathsFor<'post'>` is every POST route). */
|
|
28
|
+
export type PathsFor<M extends HttpMethod> = {
|
|
29
|
+
[P in keyof paths]: paths[P][M] extends OperationLike ? P : never;
|
|
30
|
+
}[keyof paths];
|
|
31
|
+
/** The operation object for `M path`. */
|
|
32
|
+
export type Operation<M extends HttpMethod, P extends PathsFor<M>> = paths[P][M] extends OperationLike ? paths[P][M] : never;
|
|
33
|
+
export type PathParams<O> = O extends {
|
|
34
|
+
parameters: {
|
|
35
|
+
path: infer X;
|
|
36
|
+
};
|
|
37
|
+
} ? X : never;
|
|
38
|
+
export type QueryParams<O> = O extends {
|
|
39
|
+
parameters: {
|
|
40
|
+
query?: infer Q;
|
|
41
|
+
};
|
|
42
|
+
} ? Exclude<Q, undefined> : never;
|
|
43
|
+
export type RequestBody<O> = O extends {
|
|
44
|
+
requestBody: {
|
|
45
|
+
content: {
|
|
46
|
+
'application/json': infer B;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
} ? B : O extends {
|
|
50
|
+
requestBody?: {
|
|
51
|
+
content: {
|
|
52
|
+
'application/json': infer B;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
} ? B | undefined : never;
|
|
56
|
+
type SuccessCode = 200 | 201 | 202 | 204;
|
|
57
|
+
type ContentOf<R> = R extends {
|
|
58
|
+
content: infer C;
|
|
59
|
+
} ? C[keyof C] : R extends {
|
|
60
|
+
content?: never;
|
|
61
|
+
} ? undefined : unknown;
|
|
62
|
+
/** The body of a successful response, whatever its media type. `undefined` for 204. */
|
|
63
|
+
export type ResponseBody<O> = O extends {
|
|
64
|
+
responses: infer R;
|
|
65
|
+
} ? {
|
|
66
|
+
[K in keyof R & SuccessCode]: ContentOf<R[K]>;
|
|
67
|
+
}[keyof R & SuccessCode] : never;
|
|
68
|
+
/**
|
|
69
|
+
* Which credential a call carries.
|
|
70
|
+
*
|
|
71
|
+
* - `'auto'` (default): the operator credential from `ClientOptions` if one is set,
|
|
72
|
+
* otherwise nothing. Right for the named methods, wrong for nothing.
|
|
73
|
+
* - `'operator'`: an operator credential is required; throws before the request if none
|
|
74
|
+
* is configured, so a misconfigured service fails at the call site and not with a 401.
|
|
75
|
+
* - `'none'`: send no credential even if one is configured (a public endpoint).
|
|
76
|
+
* - `{ bearer }`: a bearer token for this call only, such as the OpenID4VCI access token
|
|
77
|
+
* at `/openid4vci/credential`.
|
|
78
|
+
* - `{ headers }`: arbitrary headers for this call only, such as `x-ussd-secret`.
|
|
8
79
|
*/
|
|
80
|
+
export type Auth = 'auto' | 'operator' | 'none' | {
|
|
81
|
+
bearer: string;
|
|
82
|
+
} | {
|
|
83
|
+
headers: Record<string, string>;
|
|
84
|
+
};
|
|
85
|
+
type PathOpt<O> = [PathParams<O>] extends [never] ? {
|
|
86
|
+
path?: undefined;
|
|
87
|
+
} : {
|
|
88
|
+
path: PathParams<O>;
|
|
89
|
+
};
|
|
90
|
+
type QueryOpt<O> = [QueryParams<O>] extends [never] ? {
|
|
91
|
+
query?: undefined;
|
|
92
|
+
} : {
|
|
93
|
+
query?: QueryParams<O>;
|
|
94
|
+
};
|
|
95
|
+
type BodyOpt<O> = [RequestBody<O>] extends [never] ? {
|
|
96
|
+
body?: undefined;
|
|
97
|
+
} : undefined extends RequestBody<O> ? {
|
|
98
|
+
body?: RequestBody<O>;
|
|
99
|
+
} : {
|
|
100
|
+
body: RequestBody<O>;
|
|
101
|
+
};
|
|
102
|
+
/** Options for `request`, derived from the operation: what it needs is required. */
|
|
103
|
+
export type RequestOptions<O> = PathOpt<O> & QueryOpt<O> & BodyOpt<O> & {
|
|
104
|
+
auth?: Auth;
|
|
105
|
+
/** Extra headers, merged after the ones the client sets. */
|
|
106
|
+
headers?: Record<string, string>;
|
|
107
|
+
/** Override the `accept` header (default `application/json`). */
|
|
108
|
+
accept?: string;
|
|
109
|
+
};
|
|
110
|
+
type RequestArgs<O> = {} extends RequestOptions<O> ? [opts?: RequestOptions<O>] : [opts: RequestOptions<O>];
|
|
9
111
|
export type AssuranceLevel = 'none' | 'basic' | 'verified' | 'high';
|
|
10
112
|
export interface ClientOptions {
|
|
11
113
|
baseUrl: string;
|
|
@@ -124,6 +226,26 @@ export declare class OpenResidencyClient {
|
|
|
124
226
|
private operatorToken?;
|
|
125
227
|
private doFetch;
|
|
126
228
|
constructor(opts: ClientOptions);
|
|
229
|
+
/**
|
|
230
|
+
* Call any operation in docs/openapi.yaml. Path parameters, query, body and the
|
|
231
|
+
* response are typed from the generated contract:
|
|
232
|
+
*
|
|
233
|
+
* ```ts
|
|
234
|
+
* const rel = await client.request('get', '/residency/{residentId}/relationship', {
|
|
235
|
+
* path: { residentId },
|
|
236
|
+
* });
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
request<M extends HttpMethod, P extends PathsFor<M>>(method: M, path: P, ...args: RequestArgs<Operation<M, P>>): Promise<ResponseBody<Operation<M, P>>>;
|
|
240
|
+
live(): Promise<{
|
|
241
|
+
status?: "ok";
|
|
242
|
+
}>;
|
|
243
|
+
ready(): Promise<{
|
|
244
|
+
status: "ok" | "unavailable";
|
|
245
|
+
checks: {
|
|
246
|
+
database?: "ok" | "failed";
|
|
247
|
+
};
|
|
248
|
+
}>;
|
|
127
249
|
/** Operator action: needs the `registrar` role. */
|
|
128
250
|
identityChallenge(countryCode: string, identifiers: Record<string, string>): Promise<{
|
|
129
251
|
challengeRequired: boolean;
|
|
@@ -132,12 +254,12 @@ export declare class OpenResidencyClient {
|
|
|
132
254
|
}>;
|
|
133
255
|
/** Operator action: needs the `registrar` role. */
|
|
134
256
|
verifyIdentity(req: IdentityVerifyRequest): Promise<IdentityVerifyResponse>;
|
|
135
|
-
countries(): Promise<{
|
|
257
|
+
countries(): Promise<Array<{
|
|
136
258
|
countryCode: string;
|
|
137
259
|
countryName: string;
|
|
138
260
|
provider: string;
|
|
139
261
|
inputs: unknown[];
|
|
140
|
-
}
|
|
262
|
+
}>>;
|
|
141
263
|
/** Operator action: needs the `registrar` role. */
|
|
142
264
|
issueResidency(req: IssueRequest): Promise<IssueResult>;
|
|
143
265
|
residencyStatus(residentId: string): Promise<ResidencyStatus>;
|
|
@@ -146,6 +268,130 @@ export declare class OpenResidencyClient {
|
|
|
146
268
|
revokeResidency(residentId: string): Promise<{
|
|
147
269
|
revoked: boolean;
|
|
148
270
|
}>;
|
|
271
|
+
/** Operator action: needs the `admin` role. Revokes first, then destroys personal data. */
|
|
272
|
+
eraseResidency(residentId: string, body?: RequestBody<Operation<'post', '/residency/{residentId}/erase'>>): Promise<{
|
|
273
|
+
status: "erased" | "already-erased" | "unknown";
|
|
274
|
+
residentId: string;
|
|
275
|
+
erasedAt?: string;
|
|
276
|
+
auditEventsRedacted: number;
|
|
277
|
+
auditChainIntact: boolean;
|
|
278
|
+
}>;
|
|
279
|
+
/** Operator action. Erases records whose retention period has ended. */
|
|
280
|
+
retentionSweep(body?: RequestBody<Operation<'post', '/residency/retention/sweep'>>): Promise<{
|
|
281
|
+
dryRun: boolean;
|
|
282
|
+
auditChainIntact: boolean;
|
|
283
|
+
results: {
|
|
284
|
+
countryCode: string;
|
|
285
|
+
dueCount: number;
|
|
286
|
+
due: string[];
|
|
287
|
+
erased: number;
|
|
288
|
+
skipped?: "legal-hold" | "no-policy";
|
|
289
|
+
}[];
|
|
290
|
+
}>;
|
|
291
|
+
/** Operator action. Expires provisional registrations that were never completed. */
|
|
292
|
+
provisionalSweep(body?: RequestBody<Operation<'post', '/residency/provisional/sweep'>>): Promise<{
|
|
293
|
+
report?: components["schemas"]["ProvisionalSweepEntry"][];
|
|
294
|
+
}>;
|
|
295
|
+
/** Operator action. Re-verifies a resident against the foundational source. */
|
|
296
|
+
reconcile(residentId: string, body: RequestBody<Operation<'post', '/residency/{residentId}/reconcile'>>): Promise<{
|
|
297
|
+
status: "confirmed" | "already-confirmed" | "unknown" | "unconfirmed" | "mismatch";
|
|
298
|
+
reason?: string;
|
|
299
|
+
provisional?: boolean;
|
|
300
|
+
}>;
|
|
301
|
+
/** The relationship's ORCS state and how it got there. */
|
|
302
|
+
relationship(residentId: string): Promise<{
|
|
303
|
+
residentId?: string;
|
|
304
|
+
relationship?: components["schemas"]["RelationshipAttributes"];
|
|
305
|
+
}>;
|
|
306
|
+
/** Operator action. Move the relationship to a new ORCS state. */
|
|
307
|
+
transitionRelationship(residentId: string, body: RequestBody<Operation<'post', '/residency/{residentId}/relationship/transition'>>): Promise<{
|
|
308
|
+
residentId?: string;
|
|
309
|
+
from?: components["schemas"]["RelationshipStatus"];
|
|
310
|
+
to?: components["schemas"]["RelationshipStatus"];
|
|
311
|
+
relationship?: components["schemas"]["RelationshipAttributes"];
|
|
312
|
+
}>;
|
|
313
|
+
/** The credential's ORCS status. */
|
|
314
|
+
credential(residentId: string): Promise<{
|
|
315
|
+
residentId?: string;
|
|
316
|
+
credentialStatus?: components["schemas"]["CredentialStatusRecord"];
|
|
317
|
+
}>;
|
|
318
|
+
/** Operator action. Move the credential to a new ORCS status. */
|
|
319
|
+
transitionCredential(residentId: string, body: RequestBody<Operation<'post', '/residency/{residentId}/credential/transition'>>): Promise<{
|
|
320
|
+
residentId?: string;
|
|
321
|
+
from?: components["schemas"]["CredentialStatus"];
|
|
322
|
+
to?: components["schemas"]["CredentialStatus"];
|
|
323
|
+
credentialStatus?: components["schemas"]["CredentialStatusRecord"];
|
|
324
|
+
}>;
|
|
325
|
+
/** Why an application was refused, and how to appeal. */
|
|
326
|
+
refusal(reference: string): Promise<{
|
|
327
|
+
reference: string;
|
|
328
|
+
countryCode: string;
|
|
329
|
+
subnationalUnit: string;
|
|
330
|
+
subjectRef?: string;
|
|
331
|
+
reason: string;
|
|
332
|
+
decidedBy: string;
|
|
333
|
+
submittedBy?: string;
|
|
334
|
+
appealPath: string;
|
|
335
|
+
humanReviewPath?: string;
|
|
336
|
+
reviewStatus: "none" | "requested" | "upheld" | "overturned";
|
|
337
|
+
reviewedBy?: string;
|
|
338
|
+
reviewedAt?: string;
|
|
339
|
+
reviewNote?: string;
|
|
340
|
+
refusedAt: string;
|
|
341
|
+
}>;
|
|
342
|
+
/** Operator action. Record the outcome of reviewing a refusal. */
|
|
343
|
+
reviewRefusal(reference: string, body: RequestBody<Operation<'post', '/residency/refusals/{reference}/review'>>): Promise<{
|
|
344
|
+
reference: string;
|
|
345
|
+
countryCode: string;
|
|
346
|
+
subnationalUnit: string;
|
|
347
|
+
subjectRef?: string;
|
|
348
|
+
reason: string;
|
|
349
|
+
decidedBy: string;
|
|
350
|
+
submittedBy?: string;
|
|
351
|
+
appealPath: string;
|
|
352
|
+
humanReviewPath?: string;
|
|
353
|
+
reviewStatus: "none" | "requested" | "upheld" | "overturned";
|
|
354
|
+
reviewedBy?: string;
|
|
355
|
+
reviewedAt?: string;
|
|
356
|
+
reviewNote?: string;
|
|
357
|
+
refusedAt: string;
|
|
358
|
+
}>;
|
|
359
|
+
assuranceProfiles(): Promise<{
|
|
360
|
+
id: string;
|
|
361
|
+
name: string;
|
|
362
|
+
version: string;
|
|
363
|
+
issuer: string;
|
|
364
|
+
dimensions: components["schemas"]["AssuranceDimensions"];
|
|
365
|
+
limitations: string[];
|
|
366
|
+
}[]>;
|
|
367
|
+
assuranceMappings(): Promise<{
|
|
368
|
+
providerCode: string;
|
|
369
|
+
assuranceValue: string;
|
|
370
|
+
profileId: string;
|
|
371
|
+
version: string;
|
|
372
|
+
issuer: string;
|
|
373
|
+
verificationMethod: string;
|
|
374
|
+
limitations: string[];
|
|
375
|
+
}[]>;
|
|
376
|
+
/** Resolve a source-specific assurance value to the ORCS assurance profile. */
|
|
377
|
+
resolveAssurance(value: string): Promise<{
|
|
378
|
+
id: string;
|
|
379
|
+
name: string;
|
|
380
|
+
version: string;
|
|
381
|
+
issuer: string;
|
|
382
|
+
dimensions: components["schemas"]["AssuranceDimensions"];
|
|
383
|
+
limitations: string[];
|
|
384
|
+
}>;
|
|
385
|
+
residentAssurance(residentId: string): Promise<{
|
|
386
|
+
residentId: string;
|
|
387
|
+
declaredValue: string;
|
|
388
|
+
providerCode: string;
|
|
389
|
+
profile: components["schemas"]["AssuranceProfile"];
|
|
390
|
+
mapping?: components["schemas"]["ProviderAssuranceMapping"];
|
|
391
|
+
dimensions: components["schemas"]["AssuranceDimensions"];
|
|
392
|
+
limitations: string[];
|
|
393
|
+
authenticationAssurance: string;
|
|
394
|
+
}>;
|
|
149
395
|
listConsents(residentId: string): Promise<{
|
|
150
396
|
residentId: string;
|
|
151
397
|
consents: ConsentRecord[];
|
|
@@ -164,6 +410,69 @@ export declare class OpenResidencyClient {
|
|
|
164
410
|
revokeConsent(id: string): Promise<{
|
|
165
411
|
consent: ConsentRecord;
|
|
166
412
|
}>;
|
|
413
|
+
legalBases(): Promise<{
|
|
414
|
+
legalBases: components["schemas"]["LegalBasis"][];
|
|
415
|
+
}>;
|
|
416
|
+
legalBasis(id: string): Promise<{
|
|
417
|
+
legalBasis: components["schemas"]["LegalBasis"];
|
|
418
|
+
inForce: boolean;
|
|
419
|
+
}>;
|
|
420
|
+
/** Operator action. Withdraw a legal basis; consents resting on it stop being valid. */
|
|
421
|
+
deactivateLegalBasis(id: string, body: RequestBody<Operation<'post', '/consent/legal-bases/{id}/deactivate'>>): Promise<{
|
|
422
|
+
legalBasis: components["schemas"]["LegalBasis"];
|
|
423
|
+
}>;
|
|
424
|
+
/** Local sign-in (`operatorAuth.mode: local`). The token goes in `ClientOptions.operatorToken`. */
|
|
425
|
+
operatorLogin(body: RequestBody<Operation<'post', '/operator/login'>>): Promise<{
|
|
426
|
+
accessToken?: string;
|
|
427
|
+
tokenType?: string;
|
|
428
|
+
expiresIn?: number;
|
|
429
|
+
operator?: {
|
|
430
|
+
id?: string;
|
|
431
|
+
displayName?: string;
|
|
432
|
+
roles?: components["schemas"]["OperatorRole"][];
|
|
433
|
+
};
|
|
434
|
+
} | {
|
|
435
|
+
mfaRequired?: true;
|
|
436
|
+
}>;
|
|
437
|
+
/** The calling operator's identity and roles. */
|
|
438
|
+
me(): Promise<{
|
|
439
|
+
id?: string;
|
|
440
|
+
displayName?: string;
|
|
441
|
+
roles?: components["schemas"]["OperatorRole"][];
|
|
442
|
+
via?: "oidc" | "local" | "apiKey" | "sharedKey";
|
|
443
|
+
}>;
|
|
444
|
+
listOperators(): Promise<{
|
|
445
|
+
operators?: components["schemas"]["OperatorSummary"][];
|
|
446
|
+
}>;
|
|
447
|
+
createOperator(body: RequestBody<Operation<'post', '/operator/operators'>>): Promise<{
|
|
448
|
+
id?: string;
|
|
449
|
+
email?: string;
|
|
450
|
+
roles?: components["schemas"]["OperatorRole"][];
|
|
451
|
+
totpSecret?: string;
|
|
452
|
+
totpUri?: string;
|
|
453
|
+
}>;
|
|
454
|
+
/** Disable (or with `disabled: false`, re-enable) an operator account. Needs the `admin` role. */
|
|
455
|
+
disableOperator(operatorId: string, disabled?: boolean): Promise<{
|
|
456
|
+
ok?: boolean;
|
|
457
|
+
}>;
|
|
458
|
+
listKeys(): Promise<{
|
|
459
|
+
keys?: components["schemas"]["OperatorKeySummary"][];
|
|
460
|
+
}>;
|
|
461
|
+
/** Mint a per-operator API key. The secret is returned once. */
|
|
462
|
+
createKey(body: RequestBody<Operation<'post', '/operator/keys'>>): Promise<{
|
|
463
|
+
id?: string;
|
|
464
|
+
key?: string;
|
|
465
|
+
expiresAt?: string;
|
|
466
|
+
}>;
|
|
467
|
+
/** Mint a replacement key; the old one keeps working for the overlap window. */
|
|
468
|
+
rotateKey(body: RequestBody<Operation<'post', '/operator/keys/rotate'>>): Promise<{
|
|
469
|
+
id?: string;
|
|
470
|
+
key?: string;
|
|
471
|
+
oldKeyRetiresAt?: string;
|
|
472
|
+
}>;
|
|
473
|
+
revokeKey(body: RequestBody<Operation<'post', '/operator/keys/revoke'>>): Promise<{
|
|
474
|
+
revoked?: boolean;
|
|
475
|
+
}>;
|
|
167
476
|
listResidents(params?: {
|
|
168
477
|
countryCode?: string;
|
|
169
478
|
limit?: number;
|
|
@@ -185,8 +494,193 @@ export declare class OpenResidencyClient {
|
|
|
185
494
|
length: number;
|
|
186
495
|
brokenAtSeq?: number;
|
|
187
496
|
}>;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
497
|
+
/** Counts by country. */
|
|
498
|
+
stats(): Promise<{
|
|
499
|
+
countries: number;
|
|
500
|
+
residentsByCountry: {
|
|
501
|
+
[key: string]: number;
|
|
502
|
+
};
|
|
503
|
+
}>;
|
|
504
|
+
/** Aggregate, non-PII statistics (the open-data surface), as JSON. */
|
|
505
|
+
statistics(query?: QueryParams<Operation<'get', '/admin/statistics'>>): Promise<{
|
|
506
|
+
generatedAt: string;
|
|
507
|
+
suppressionThreshold: number;
|
|
508
|
+
totalResidents: number | null;
|
|
509
|
+
countries: number;
|
|
510
|
+
cells: {
|
|
511
|
+
countryCode: string;
|
|
512
|
+
subnationalUnit: string;
|
|
513
|
+
providerCode: string;
|
|
514
|
+
assuranceLevel: string;
|
|
515
|
+
provisional: boolean;
|
|
516
|
+
count: number | null;
|
|
517
|
+
suppressed: boolean;
|
|
518
|
+
}[];
|
|
519
|
+
}>;
|
|
520
|
+
/** The same report as RFC 4180 CSV. */
|
|
521
|
+
statisticsCsv(query?: QueryParams<Operation<'get', '/admin/statistics.csv'>>): Promise<string>;
|
|
522
|
+
/** Render a credential as an SVG QR for paper or low-connectivity carriage. */
|
|
523
|
+
qr(body: RequestBody<Operation<'post', '/offline/qr'>>): Promise<{
|
|
524
|
+
mode: "full" | "pointer";
|
|
525
|
+
svg: string;
|
|
526
|
+
}>;
|
|
527
|
+
/** The USSD aggregator webhook. `secret` is the shared USSD_GATEWAY_SECRET. */
|
|
528
|
+
ussd(body: RequestBody<Operation<'post', '/offline/ussd'>>, secret: string): Promise<string>;
|
|
529
|
+
credentialIssuerMetadata(): Promise<Record<string, never>>;
|
|
530
|
+
oauthAuthorizationServerMetadata(): Promise<{
|
|
531
|
+
issuer?: string;
|
|
532
|
+
token_endpoint?: string;
|
|
533
|
+
grant_types_supported?: "urn:ietf:params:oauth:grant-type:pre-authorized_code"[];
|
|
534
|
+
response_types_supported?: string[];
|
|
535
|
+
"pre-authorized_grant_anonymous_access_supported"?: boolean;
|
|
536
|
+
token_endpoint_auth_methods_supported?: "none"[];
|
|
537
|
+
}>;
|
|
538
|
+
/** Operator action. Create a credential offer for a resident's wallet to redeem. */
|
|
539
|
+
createCredentialOffer(body: RequestBody<Operation<'post', '/openid4vci/offer'>>): Promise<{
|
|
540
|
+
offerId?: string;
|
|
541
|
+
offerUri?: string;
|
|
542
|
+
offer?: {
|
|
543
|
+
credential_issuer?: string;
|
|
544
|
+
credential_configuration_ids?: string[];
|
|
545
|
+
grants?: {
|
|
546
|
+
"urn:ietf:params:oauth:grant-type:pre-authorized_code"?: {
|
|
547
|
+
"pre-authorized_code"?: string;
|
|
548
|
+
tx_code?: {
|
|
549
|
+
length?: number;
|
|
550
|
+
input_mode?: "numeric";
|
|
551
|
+
description?: string;
|
|
552
|
+
};
|
|
553
|
+
};
|
|
554
|
+
};
|
|
555
|
+
};
|
|
556
|
+
txCode?: string;
|
|
557
|
+
expiresAt?: string;
|
|
558
|
+
credentialConfigurationIds?: string[];
|
|
559
|
+
}>;
|
|
560
|
+
/** The wallet side: exchange the pre-authorized code for an access token. */
|
|
561
|
+
walletToken(body: RequestBody<Operation<'post', '/openid4vci/token'>>): Promise<{
|
|
562
|
+
access_token?: string;
|
|
563
|
+
token_type?: string;
|
|
564
|
+
expires_in?: number;
|
|
565
|
+
authorization_details?: {
|
|
566
|
+
type?: "openid_credential";
|
|
567
|
+
credential_configuration_id?: string;
|
|
568
|
+
}[];
|
|
569
|
+
c_nonce?: string;
|
|
570
|
+
c_nonce_expires_in?: number;
|
|
571
|
+
}>;
|
|
572
|
+
walletNonce(): Promise<{
|
|
573
|
+
c_nonce?: string;
|
|
574
|
+
}>;
|
|
575
|
+
/** The wallet side: obtain the credential with the access token from `walletToken`. */
|
|
576
|
+
walletCredential(accessToken: string, body: RequestBody<Operation<'post', '/openid4vci/credential'>>): Promise<{
|
|
577
|
+
credentials?: {
|
|
578
|
+
credential?: unknown;
|
|
579
|
+
}[];
|
|
580
|
+
format?: "ldp_vc" | "jwt_vc_json";
|
|
581
|
+
credential?: unknown;
|
|
582
|
+
c_nonce?: string;
|
|
583
|
+
c_nonce_expires_in?: number;
|
|
584
|
+
}>;
|
|
585
|
+
/** Create a presentation request for a wallet to answer. */
|
|
586
|
+
createPresentationRequest(body?: RequestBody<Operation<'post', '/openid4vp/request'>>): Promise<{
|
|
587
|
+
requestId?: string;
|
|
588
|
+
requestUri?: string;
|
|
589
|
+
expiresAt?: string;
|
|
590
|
+
}>;
|
|
591
|
+
/** The request object a wallet fetches (the `request_uri`). */
|
|
592
|
+
presentationRequest(id: string): Promise<string>;
|
|
593
|
+
/** The wallet side: submit the presentation. */
|
|
594
|
+
submitPresentation(id: string, body: RequestBody<Operation<'post', '/openid4vp/response/{id}'>>): Promise<{
|
|
595
|
+
status?: "accepted";
|
|
596
|
+
}>;
|
|
597
|
+
/** What the wallet presented, once it has. */
|
|
598
|
+
presentationResult(id: string): Promise<{
|
|
599
|
+
requestId?: string;
|
|
600
|
+
status?: "pending" | "fulfilled" | "failed";
|
|
601
|
+
reference?: string;
|
|
602
|
+
purpose?: string;
|
|
603
|
+
expiresAt?: string;
|
|
604
|
+
outcome?: components["schemas"]["PresentationOutcome"];
|
|
605
|
+
}>;
|
|
606
|
+
/** Operator action. Issue a credential through the VC-API issuer interface. */
|
|
607
|
+
vcIssue(body: RequestBody<Operation<'post', '/credentials/issue'>>): Promise<{
|
|
608
|
+
verifiableCredential?: components["schemas"]["DataIntegrityCredential"];
|
|
609
|
+
}>;
|
|
610
|
+
/** Verify a Verifiable Credential (JWT or Data Integrity) through the VC-API verifier interface. */
|
|
611
|
+
vcVerify(body: RequestBody<Operation<'post', '/credentials/verify'>>): Promise<{
|
|
612
|
+
checks: ("proof" | "expiration" | "credentialStatus")[];
|
|
613
|
+
warnings: string[];
|
|
614
|
+
errors: string[];
|
|
615
|
+
}>;
|
|
616
|
+
/** Verify a Verifiable Presentation through the VC-API verifier interface. */
|
|
617
|
+
vpVerify(body: RequestBody<Operation<'post', '/presentations/verify'>>): Promise<{
|
|
618
|
+
checks: ("proof" | "expiration" | "credentialStatus")[];
|
|
619
|
+
warnings: string[];
|
|
620
|
+
errors: string[];
|
|
621
|
+
}>;
|
|
622
|
+
/** This deployment's DID document (`did:web`). */
|
|
623
|
+
didDocument(): Promise<Record<string, never>>;
|
|
624
|
+
/** The DID document for one country's issuer key. */
|
|
625
|
+
didDocumentFor(countryCode: string): Promise<{
|
|
626
|
+
"@context": string[];
|
|
627
|
+
id: string;
|
|
628
|
+
verificationMethod: {
|
|
629
|
+
id: string;
|
|
630
|
+
type: "JsonWebKey2020" | "Multikey";
|
|
631
|
+
controller: string;
|
|
632
|
+
publicKeyJwk?: {
|
|
633
|
+
[key: string]: unknown;
|
|
634
|
+
};
|
|
635
|
+
publicKeyMultibase?: string;
|
|
636
|
+
}[];
|
|
637
|
+
assertionMethod: string[];
|
|
638
|
+
authentication: string[];
|
|
639
|
+
}>;
|
|
640
|
+
/** A Bitstring Status List credential, for offline revocation checks. */
|
|
641
|
+
statusList(file: string): Promise<{
|
|
642
|
+
"@context": string[];
|
|
643
|
+
id: string;
|
|
644
|
+
type: string[];
|
|
645
|
+
issuer: string;
|
|
646
|
+
validFrom: string;
|
|
647
|
+
credentialSubject: {
|
|
648
|
+
id: string;
|
|
649
|
+
type: "BitstringStatusList";
|
|
650
|
+
statusPurpose: "revocation" | "suspension";
|
|
651
|
+
encodedList: string;
|
|
652
|
+
};
|
|
653
|
+
proof: components["schemas"]["DataIntegrityProof"];
|
|
654
|
+
}>;
|
|
655
|
+
/** OpenID Connect discovery for the SSO provider mounted under /oidc. */
|
|
656
|
+
oidcDiscovery(): Promise<{
|
|
657
|
+
issuer?: string;
|
|
658
|
+
authorization_endpoint?: string;
|
|
659
|
+
token_endpoint?: string;
|
|
660
|
+
userinfo_endpoint?: string;
|
|
661
|
+
jwks_uri?: string;
|
|
662
|
+
revocation_endpoint?: string;
|
|
663
|
+
introspection_endpoint?: string;
|
|
664
|
+
end_session_endpoint?: string;
|
|
665
|
+
pushed_authorization_request_endpoint?: string;
|
|
666
|
+
scopes_supported?: string[];
|
|
667
|
+
claims_supported?: string[];
|
|
668
|
+
response_types_supported?: string[];
|
|
669
|
+
grant_types_supported?: string[];
|
|
670
|
+
response_modes_supported?: string[];
|
|
671
|
+
subject_types_supported?: ("public" | "pairwise")[];
|
|
672
|
+
id_token_signing_alg_values_supported?: string[];
|
|
673
|
+
token_endpoint_auth_methods_supported?: string[];
|
|
674
|
+
token_endpoint_auth_signing_alg_values_supported?: string[];
|
|
675
|
+
code_challenge_methods_supported?: "S256"[];
|
|
676
|
+
dpop_signing_alg_values_supported?: string[];
|
|
677
|
+
claims_parameter_supported?: boolean;
|
|
678
|
+
request_uri_parameter_supported?: boolean;
|
|
679
|
+
authorization_response_iss_parameter_supported?: boolean;
|
|
680
|
+
claim_types_supported?: "normal"[];
|
|
681
|
+
} & {
|
|
682
|
+
[key: string]: unknown;
|
|
683
|
+
}>;
|
|
684
|
+
private send;
|
|
685
|
+
private applyAuth;
|
|
192
686
|
}
|