@dreadkn1ght123/provisioning-client 1.0.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 +8 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +3 -0
- package/dist/browser.js.map +1 -0
- package/dist/client.d.ts +25 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +123 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +33 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +51 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +181 -0
- package/dist/index.js.map +1 -0
- package/dist/token.d.ts +27 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +66 -0
- package/dist/token.js.map +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# `@dreadkn1ght123/provisioning-client`
|
|
2
|
+
|
|
3
|
+
Backend-only typed `/v1` client. Supply a short-lived machine token through
|
|
4
|
+
`getAccessToken`; never import this package from browser code. Every call needs a
|
|
5
|
+
correlation ID and every mutation also needs a meaningful reason and an opaque
|
|
6
|
+
idempotency key. Preserve the same key and body when a result is
|
|
7
|
+
`operation_in_progress` or `ambiguous`. `reconciliation_required` must be handed
|
|
8
|
+
to an IAM operator; do not call Keycloak or create a duplicate identity.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;AACnG,OAAO,EAAE,CAAC"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { BackendTokenProvider } from "./token.js";
|
|
2
|
+
import type { Actor, InviteActor, LifecycleReason, MutationRequestOptions, MutationResponse, UpdateActorAccess } from "./types.js";
|
|
3
|
+
export interface ProvisioningClientOptions {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
tokenProvider: BackendTokenProvider;
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
fetch?: typeof globalThis.fetch;
|
|
8
|
+
}
|
|
9
|
+
export declare class ProvisioningClient {
|
|
10
|
+
private readonly options;
|
|
11
|
+
private readonly fetch;
|
|
12
|
+
private readonly timeoutMs;
|
|
13
|
+
private readonly baseUrl;
|
|
14
|
+
constructor(options: ProvisioningClientOptions);
|
|
15
|
+
invite(input: InviteActor, options: MutationRequestOptions): Promise<MutationResponse<Actor>>;
|
|
16
|
+
updateAccess(vvpActorId: string, input: UpdateActorAccess, options: MutationRequestOptions): Promise<MutationResponse<Actor>>;
|
|
17
|
+
disable(vvpActorId: string, input: LifecycleReason, options: MutationRequestOptions): Promise<MutationResponse<Actor>>;
|
|
18
|
+
restore(vvpActorId: string, input: LifecycleReason, options: MutationRequestOptions): Promise<MutationResponse<Actor>>;
|
|
19
|
+
getActor(vvpActorId: string, correlationId?: `${string}-${string}-${string}-${string}-${string}`): Promise<Actor>;
|
|
20
|
+
private mutate;
|
|
21
|
+
private request;
|
|
22
|
+
private actorId;
|
|
23
|
+
private jsonOrUndefined;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnI,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,oBAAoB,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAgBD,qBAAa,kBAAkB;IAKjB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEJ,OAAO,EAAE,yBAAyB;IAM/D,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB;IAG1D,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,sBAAsB;IAG1F,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,sBAAsB;IAGnF,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,sBAAsB;IAI7E,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,sDAAe,GAAG,OAAO,CAAC,KAAK,CAAC;YAQlE,MAAM;YAgDN,OAAO;IAcrB,OAAO,CAAC,OAAO;YAKD,eAAe;CAI9B"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { AmbiguousProvisioningResultError, errorFromResponse, ReconciliationRequiredError } from "./errors.js";
|
|
3
|
+
const safeId = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
4
|
+
const keyPattern = /^[A-Za-z0-9._:-]{16,128}$/;
|
|
5
|
+
function validateBackendUrl(value, label) {
|
|
6
|
+
let url;
|
|
7
|
+
try {
|
|
8
|
+
url = new URL(value);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
throw new Error(`${label} must be a valid absolute URL`);
|
|
12
|
+
}
|
|
13
|
+
const loopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1" || url.hostname === "[::1]";
|
|
14
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) {
|
|
15
|
+
throw new Error(`${label} must use HTTPS (HTTP is permitted only for exact loopback hosts)`);
|
|
16
|
+
}
|
|
17
|
+
if (url.username || url.password)
|
|
18
|
+
throw new Error(`${label} must not include URL credentials`);
|
|
19
|
+
return url;
|
|
20
|
+
}
|
|
21
|
+
export class ProvisioningClient {
|
|
22
|
+
options;
|
|
23
|
+
fetch;
|
|
24
|
+
timeoutMs;
|
|
25
|
+
baseUrl;
|
|
26
|
+
constructor(options) {
|
|
27
|
+
this.options = options;
|
|
28
|
+
this.baseUrl = validateBackendUrl(options.baseUrl, "Provisioning API URL").toString().replace(/\/+$/, "");
|
|
29
|
+
this.fetch = options.fetch ?? globalThis.fetch;
|
|
30
|
+
this.timeoutMs = Math.min(Math.max(options.timeoutMs ?? 10_000, 100), 30_000);
|
|
31
|
+
}
|
|
32
|
+
invite(input, options) {
|
|
33
|
+
return this.mutate("POST", "/v1/actors", input, options);
|
|
34
|
+
}
|
|
35
|
+
updateAccess(vvpActorId, input, options) {
|
|
36
|
+
return this.mutate("PUT", `/v1/actors/${this.actorId(vvpActorId)}/access`, input, options);
|
|
37
|
+
}
|
|
38
|
+
disable(vvpActorId, input, options) {
|
|
39
|
+
return this.mutate("POST", `/v1/actors/${this.actorId(vvpActorId)}/disable`, input, options);
|
|
40
|
+
}
|
|
41
|
+
restore(vvpActorId, input, options) {
|
|
42
|
+
return this.mutate("POST", `/v1/actors/${this.actorId(vvpActorId)}/restore`, input, options);
|
|
43
|
+
}
|
|
44
|
+
async getActor(vvpActorId, correlationId = randomUUID()) {
|
|
45
|
+
if (!safeId.test(correlationId))
|
|
46
|
+
throw new Error("Invalid correlation ID");
|
|
47
|
+
const token = await this.options.tokenProvider.getAccessToken();
|
|
48
|
+
const response = await this.request("GET", `/v1/actors/${this.actorId(vvpActorId)}`, correlationId, token);
|
|
49
|
+
if (!response.ok)
|
|
50
|
+
throw errorFromResponse(response.status, await this.jsonOrUndefined(response), correlationId);
|
|
51
|
+
return await response.json();
|
|
52
|
+
}
|
|
53
|
+
async mutate(method, path, body, options) {
|
|
54
|
+
if (typeof body.reason !== "string" || body.reason.trim().length < 3 || body.reason.trim().length > 500) {
|
|
55
|
+
throw new Error("A 3-500 character operator-meaningful reason is required");
|
|
56
|
+
}
|
|
57
|
+
const { idempotencyKey, correlationId } = options;
|
|
58
|
+
if (!keyPattern.test(idempotencyKey))
|
|
59
|
+
throw new Error("Invalid idempotency key");
|
|
60
|
+
if (!safeId.test(correlationId))
|
|
61
|
+
throw new Error("Invalid correlation ID");
|
|
62
|
+
// Acquiring a token precedes any request to the Provisioning API, so an
|
|
63
|
+
// acquisition failure is conclusively pre-effect and must not be treated
|
|
64
|
+
// as an ambiguous lifecycle mutation.
|
|
65
|
+
const token = await this.options.tokenProvider.getAccessToken();
|
|
66
|
+
let response;
|
|
67
|
+
try {
|
|
68
|
+
response = await this.request(method, path, correlationId, token, idempotencyKey, body);
|
|
69
|
+
}
|
|
70
|
+
catch (cause) {
|
|
71
|
+
throw new AmbiguousProvisioningResultError("Provisioning request did not produce an unambiguous response; retry only the exact request with the same idempotency key", idempotencyKey, correlationId, { cause });
|
|
72
|
+
}
|
|
73
|
+
if (!response.ok) {
|
|
74
|
+
const error = errorFromResponse(response.status, await this.jsonOrUndefined(response), response.headers.get("x-correlation-id") ?? correlationId);
|
|
75
|
+
if (response.status >= 500 && !(error instanceof ReconciliationRequiredError)) {
|
|
76
|
+
throw new AmbiguousProvisioningResultError("Provisioning API returned an ambiguous server failure; retry only the exact request with the same idempotency key", idempotencyKey, correlationId, { cause: error });
|
|
77
|
+
}
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
let value;
|
|
81
|
+
try {
|
|
82
|
+
value = await response.json();
|
|
83
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
84
|
+
throw new Error("successful response body is not an object");
|
|
85
|
+
}
|
|
86
|
+
catch (cause) {
|
|
87
|
+
throw new AmbiguousProvisioningResultError("Provisioning API acknowledged a mutation but returned an unreadable response; retry only the exact request with the same idempotency key", idempotencyKey, correlationId, { cause });
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
data: value,
|
|
91
|
+
replayed: response.headers.get("idempotency-replayed")?.toLowerCase() === "true",
|
|
92
|
+
correlationId: response.headers.get("x-correlation-id") ?? correlationId,
|
|
93
|
+
idempotencyKey,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async request(method, path, correlationId, token, idempotencyKey, body) {
|
|
97
|
+
return this.fetch(`${this.baseUrl}${path}`, {
|
|
98
|
+
method,
|
|
99
|
+
headers: {
|
|
100
|
+
authorization: `Bearer ${token}`,
|
|
101
|
+
"x-correlation-id": correlationId,
|
|
102
|
+
...(idempotencyKey ? { "idempotency-key": idempotencyKey } : {}),
|
|
103
|
+
...(body ? { "content-type": "application/json" } : {}),
|
|
104
|
+
},
|
|
105
|
+
...(body ? { body: JSON.stringify(body) } : {}),
|
|
106
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
actorId(value) {
|
|
110
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value))
|
|
111
|
+
throw new Error("Invalid VVP actor ID");
|
|
112
|
+
return encodeURIComponent(value);
|
|
113
|
+
}
|
|
114
|
+
async jsonOrUndefined(response) {
|
|
115
|
+
try {
|
|
116
|
+
return await response.json();
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface ProvisioningErrorEnvelope {
|
|
2
|
+
error: {
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
details?: Readonly<Record<string, string>>;
|
|
6
|
+
};
|
|
7
|
+
correlationId: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class ProvisioningApiError extends Error {
|
|
10
|
+
readonly code: string;
|
|
11
|
+
readonly status: number;
|
|
12
|
+
readonly correlationId?: string | undefined;
|
|
13
|
+
readonly details?: Readonly<Record<string, string>> | undefined;
|
|
14
|
+
constructor(code: string, status: number, message: string, correlationId?: string | undefined, details?: Readonly<Record<string, string>> | undefined);
|
|
15
|
+
}
|
|
16
|
+
export declare class IdempotencyConflictError extends ProvisioningApiError {
|
|
17
|
+
readonly name = "IdempotencyConflictError";
|
|
18
|
+
}
|
|
19
|
+
export declare class OperationInProgressError extends ProvisioningApiError {
|
|
20
|
+
readonly name = "OperationInProgressError";
|
|
21
|
+
}
|
|
22
|
+
export declare class ReconciliationRequiredError extends ProvisioningApiError {
|
|
23
|
+
readonly name = "ReconciliationRequiredError";
|
|
24
|
+
}
|
|
25
|
+
/** A transport failure has an unknown server outcome. Retry only with the same key and body. */
|
|
26
|
+
export declare class AmbiguousProvisioningResultError extends Error {
|
|
27
|
+
readonly idempotencyKey: string;
|
|
28
|
+
readonly correlationId: string;
|
|
29
|
+
readonly name = "AmbiguousProvisioningResultError";
|
|
30
|
+
constructor(message: string, idempotencyKey: string, correlationId: string, options?: ErrorOptions);
|
|
31
|
+
}
|
|
32
|
+
export declare function errorFromResponse(status: number, body: unknown, fallbackCorrelationId?: string): ProvisioningApiError;
|
|
33
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,CAAC;IACrF,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAE3C,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAEvB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAJ1C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EACN,aAAa,CAAC,EAAE,MAAM,YAAA,EACtB,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,YAAA;CAKtD;AAED,qBAAa,wBAAyB,SAAQ,oBAAoB;IAChE,SAAkB,IAAI,8BAA8B;CACrD;AACD,qBAAa,wBAAyB,SAAQ,oBAAoB;IAChE,SAAkB,IAAI,8BAA8B;CACrD;AACD,qBAAa,2BAA4B,SAAQ,oBAAoB;IACnE,SAAkB,IAAI,iCAAiC;CACxD;AAED,gGAAgG;AAChG,qBAAa,gCAAiC,SAAQ,KAAK;IAIvD,QAAQ,CAAC,cAAc,EAAE,MAAM;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM;IAJhC,SAAkB,IAAI,sCAAsC;gBAE1D,OAAO,EAAE,MAAM,EACN,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EAC9B,OAAO,CAAC,EAAE,YAAY;CAIzB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,oBAAoB,CAYrH"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export class ProvisioningApiError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
correlationId;
|
|
5
|
+
details;
|
|
6
|
+
constructor(code, status, message, correlationId, details) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.correlationId = correlationId;
|
|
11
|
+
this.details = details;
|
|
12
|
+
this.name = "ProvisioningApiError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export class IdempotencyConflictError extends ProvisioningApiError {
|
|
16
|
+
name = "IdempotencyConflictError";
|
|
17
|
+
}
|
|
18
|
+
export class OperationInProgressError extends ProvisioningApiError {
|
|
19
|
+
name = "OperationInProgressError";
|
|
20
|
+
}
|
|
21
|
+
export class ReconciliationRequiredError extends ProvisioningApiError {
|
|
22
|
+
name = "ReconciliationRequiredError";
|
|
23
|
+
}
|
|
24
|
+
/** A transport failure has an unknown server outcome. Retry only with the same key and body. */
|
|
25
|
+
export class AmbiguousProvisioningResultError extends Error {
|
|
26
|
+
idempotencyKey;
|
|
27
|
+
correlationId;
|
|
28
|
+
name = "AmbiguousProvisioningResultError";
|
|
29
|
+
constructor(message, idempotencyKey, correlationId, options) {
|
|
30
|
+
super(message, options);
|
|
31
|
+
this.idempotencyKey = idempotencyKey;
|
|
32
|
+
this.correlationId = correlationId;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function errorFromResponse(status, body, fallbackCorrelationId) {
|
|
36
|
+
const value = body;
|
|
37
|
+
const error = value?.error;
|
|
38
|
+
const code = typeof error?.code === "string" ? error.code : "HTTP_ERROR";
|
|
39
|
+
const message = typeof error?.message === "string" ? error.message : `Provisioning API returned HTTP ${status}`;
|
|
40
|
+
const correlationId = typeof value?.correlationId === "string" ? value.correlationId : fallbackCorrelationId;
|
|
41
|
+
const details = error?.details && typeof error.details === "object" ? error.details : undefined;
|
|
42
|
+
const args = [code, status, message, correlationId, details];
|
|
43
|
+
if (code === "IDEMPOTENCY_CONFLICT")
|
|
44
|
+
return new IdempotencyConflictError(...args);
|
|
45
|
+
if (code === "OPERATION_IN_PROGRESS")
|
|
46
|
+
return new OperationInProgressError(...args);
|
|
47
|
+
if (code === "RECONCILIATION_REQUIRED")
|
|
48
|
+
return new ReconciliationRequiredError(...args);
|
|
49
|
+
return new ProvisioningApiError(...args);
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAElC;IACA;IAEA;IACA;IALX,YACW,IAAY,EACZ,MAAc,EACvB,OAAe,EACN,aAAsB,EACtB,OAA0C;QAEnD,KAAK,CAAC,OAAO,CAAC,CAAC;QANN,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAQ;QAEd,kBAAa,GAAb,aAAa,CAAS;QACtB,YAAO,GAAP,OAAO,CAAmC;QAGnD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,oBAAoB;IAC9C,IAAI,GAAG,0BAA0B,CAAC;CACrD;AACD,MAAM,OAAO,wBAAyB,SAAQ,oBAAoB;IAC9C,IAAI,GAAG,0BAA0B,CAAC;CACrD;AACD,MAAM,OAAO,2BAA4B,SAAQ,oBAAoB;IACjD,IAAI,GAAG,6BAA6B,CAAC;CACxD;AAED,gGAAgG;AAChG,MAAM,OAAO,gCAAiC,SAAQ,KAAK;IAI9C;IACA;IAJO,IAAI,GAAG,kCAAkC,CAAC;IAC5D,YACE,OAAe,EACN,cAAsB,EACtB,aAAqB,EAC9B,OAAsB;QAEtB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAJf,mBAAc,GAAd,cAAc,CAAQ;QACtB,kBAAa,GAAb,aAAa,CAAQ;IAIhC,CAAC;CACF;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,IAAa,EAAE,qBAA8B;IAC7F,MAAM,KAAK,GAAG,IAAiD,CAAC;IAChE,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,CAAC;IAC3B,MAAM,IAAI,GAAG,OAAO,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC;IACzE,MAAM,OAAO,GAAG,OAAO,KAAK,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,kCAAkC,MAAM,EAAE,CAAC;IAChH,MAAM,aAAa,GAAG,OAAO,KAAK,EAAE,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,qBAAqB,CAAC;IAC7G,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAChG,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,CAAU,CAAC;IACtE,IAAI,IAAI,KAAK,sBAAsB;QAAE,OAAO,IAAI,wBAAwB,CAAC,GAAG,IAAI,CAAC,CAAC;IAClF,IAAI,IAAI,KAAK,uBAAuB;QAAE,OAAO,IAAI,wBAAwB,CAAC,GAAG,IAAI,CAAC,CAAC;IACnF,IAAI,IAAI,KAAK,yBAAyB;QAAE,OAAO,IAAI,2BAA2B,CAAC,GAAG,IAAI,CAAC,CAAC;IACxF,OAAO,IAAI,oBAAoB,CAAC,GAAG,IAAI,CAAC,CAAC;AAC3C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export * from "./client.js";
|
|
2
|
+
export * from "./errors.js";
|
|
3
|
+
export * from "./token.js";
|
|
4
|
+
export * from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Backend-only VVP Provisioning API client. This package deliberately has no
|
|
7
|
+
* Keycloak administration surface and must never be bundled for a browser.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PROVISIONING_CLIENT_VERSION = "1.0.0";
|
|
10
|
+
export interface InviteActor {
|
|
11
|
+
email: string;
|
|
12
|
+
externalId?: string;
|
|
13
|
+
actorType: string;
|
|
14
|
+
displayName?: string;
|
|
15
|
+
groups: readonly string[];
|
|
16
|
+
clientRoles: Readonly<Record<string, readonly string[]>>;
|
|
17
|
+
reason: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ProvisioningClientOptions {
|
|
20
|
+
baseUrl: string;
|
|
21
|
+
/** Supplies a short-lived machine token. It is never retained or included in errors. */
|
|
22
|
+
getAccessToken: () => Promise<string>;
|
|
23
|
+
fetch?: typeof globalThis.fetch;
|
|
24
|
+
timeoutMs?: number;
|
|
25
|
+
}
|
|
26
|
+
export type ActorState = "INVITED" | "ACTIVE" | "DISABLED" | "RECONCILIATION_REQUIRED";
|
|
27
|
+
export interface Actor {
|
|
28
|
+
vvpActorId: string;
|
|
29
|
+
keycloakSub?: string;
|
|
30
|
+
externalId?: string;
|
|
31
|
+
email: string;
|
|
32
|
+
actorType: string;
|
|
33
|
+
displayName?: string;
|
|
34
|
+
state: ActorState;
|
|
35
|
+
groups: readonly string[];
|
|
36
|
+
clientRoles: Readonly<Record<string, readonly string[]>>;
|
|
37
|
+
createdAt: string;
|
|
38
|
+
updatedAt: string;
|
|
39
|
+
disabledAt?: string;
|
|
40
|
+
reconciliation?: {
|
|
41
|
+
errorCode: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export interface ReadContext {
|
|
45
|
+
correlationId: string;
|
|
46
|
+
}
|
|
47
|
+
export declare function createProvisioningClient(options: ProvisioningClientOptions): {
|
|
48
|
+
invite: (body: InviteActor, ctx: MutationContext) => Promise<ProvisioningResult<Actor>>;
|
|
49
|
+
list: (query: ListActors, ctx: ReadContext) => Promise<ProvisioningResult<ActorPage>>;
|
|
50
|
+
get: (id: string, ctx: ReadContext) => Promise<ProvisioningResult<Actor>>;
|
|
51
|
+
updateAccess: (id: string, body: UpdateAccess, ctx: MutationContext) => Promise<ProvisioningResult<Actor>>;
|
|
52
|
+
access: (id: string, body: UpdateAccess, ctx: MutationContext) => Promise<ProvisioningResult<Actor>>;
|
|
53
|
+
disable: (id: string, reason: string, ctx: MutationContext) => Promise<ProvisioningResult<Actor>>;
|
|
54
|
+
restore: (id: string, reason: string, ctx: MutationContext) => Promise<ProvisioningResult<Actor>>;
|
|
55
|
+
resendInvitation: (id: string, reason: string, ctx: MutationContext) => Promise<ProvisioningResult<Actor>>;
|
|
56
|
+
resend: (id: string, reason: string, ctx: MutationContext) => Promise<ProvisioningResult<Actor>>;
|
|
57
|
+
};
|
|
58
|
+
export declare class ProvisioningClientError extends Error {
|
|
59
|
+
readonly code: ProvisioningErrorCode | "INVALID_CLIENT_CONFIGURATION" | "UNEXPECTED_RESPONSE";
|
|
60
|
+
readonly status: number | undefined;
|
|
61
|
+
readonly correlationId: string;
|
|
62
|
+
readonly details?: Readonly<Record<string, string>> | undefined;
|
|
63
|
+
constructor(code: ProvisioningErrorCode | "INVALID_CLIENT_CONFIGURATION" | "UNEXPECTED_RESPONSE", status: number | undefined, correlationId: string, message: string, details?: Readonly<Record<string, string>> | undefined);
|
|
64
|
+
}
|
|
65
|
+
export interface ListActors {
|
|
66
|
+
state?: ActorState;
|
|
67
|
+
email?: string;
|
|
68
|
+
cursor?: string;
|
|
69
|
+
limit?: number;
|
|
70
|
+
}
|
|
71
|
+
export interface ActorPage {
|
|
72
|
+
items: readonly Actor[];
|
|
73
|
+
nextCursor?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface MutationContext {
|
|
76
|
+
idempotencyKey: string;
|
|
77
|
+
correlationId: string;
|
|
78
|
+
}
|
|
79
|
+
export declare const PROVISIONING_ERROR_CODES: readonly ["INVALID_REQUEST", "AUTHENTICATION_REQUIRED", "PROVISIONING_FORBIDDEN", "ACTOR_NOT_FOUND", "EMAIL_CONFLICT", "EXTERNAL_ID_CONFLICT", "IDEMPOTENCY_KEY_REQUIRED", "IDEMPOTENCY_CONFLICT", "OPERATION_IN_PROGRESS", "ROLE_NOT_ALLOWED", "GROUP_NOT_ALLOWED", "INVALID_STATE", "KEYCLOAK_UNAVAILABLE", "KEYCLOAK_REJECTED", "REGISTRY_UNAVAILABLE", "RECONCILIATION_REQUIRED", "REQUEST_TOO_LARGE", "BROWSER_REQUEST_FORBIDDEN", "INTERNAL_ERROR"];
|
|
80
|
+
export type ProvisioningErrorCode = typeof PROVISIONING_ERROR_CODES[number];
|
|
81
|
+
export interface UpdateAccess {
|
|
82
|
+
groups: readonly string[];
|
|
83
|
+
clientRoles: Readonly<Record<string, readonly string[]>>;
|
|
84
|
+
reason: string;
|
|
85
|
+
}
|
|
86
|
+
export type ProvisioningResult<T> = {
|
|
87
|
+
status: "succeeded";
|
|
88
|
+
value: T;
|
|
89
|
+
correlationId: string;
|
|
90
|
+
} | {
|
|
91
|
+
status: "operation_in_progress";
|
|
92
|
+
correlationId: string;
|
|
93
|
+
retryable: true;
|
|
94
|
+
} | {
|
|
95
|
+
status: "reconciliation_required";
|
|
96
|
+
correlationId: string;
|
|
97
|
+
actor?: T;
|
|
98
|
+
retryable: false;
|
|
99
|
+
} | {
|
|
100
|
+
status: "ambiguous";
|
|
101
|
+
correlationId: string;
|
|
102
|
+
retryable: false;
|
|
103
|
+
instruction: "RETRY_SAME_REQUEST";
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
export * from "./client.js";
|
|
2
|
+
export * from "./errors.js";
|
|
3
|
+
export * from "./token.js";
|
|
4
|
+
export * from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Backend-only VVP Provisioning API client. This package deliberately has no
|
|
7
|
+
* Keycloak administration surface and must never be bundled for a browser.
|
|
8
|
+
*/
|
|
9
|
+
export const PROVISIONING_CLIENT_VERSION = "1.0.0";
|
|
10
|
+
function meaningfulReason(body) {
|
|
11
|
+
if (typeof body.reason !== "string" || body.reason.trim().length < 3 || body.reason.length > 500)
|
|
12
|
+
throw new ProvisioningClientError("INVALID_CLIENT_CONFIGURATION", undefined, "", "A meaningful reason is required");
|
|
13
|
+
}
|
|
14
|
+
export function createProvisioningClient(options) {
|
|
15
|
+
let base;
|
|
16
|
+
try {
|
|
17
|
+
base = new URL(options.baseUrl);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new ProvisioningClientError("INVALID_CLIENT_CONFIGURATION", undefined, "", "Invalid Provisioning API URL");
|
|
21
|
+
}
|
|
22
|
+
if ((base.protocol !== "https:" && !["localhost", "127.0.0.1", "::1"].includes(base.hostname)) ||
|
|
23
|
+
!!base.username || !!base.password || !!base.search || !!base.hash || (base.pathname !== "/" && base.pathname !== ""))
|
|
24
|
+
throw new ProvisioningClientError("INVALID_CLIENT_CONFIGURATION", undefined, "", "Provisioning API must use HTTPS");
|
|
25
|
+
if (options.timeoutMs !== undefined && (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > 120_000))
|
|
26
|
+
throw new ProvisioningClientError("INVALID_CLIENT_CONFIGURATION", undefined, "", "Timeout must be between 1 and 120000 milliseconds");
|
|
27
|
+
const request = async (method, path, ctx, shape, body) => {
|
|
28
|
+
const mutation = method !== "GET";
|
|
29
|
+
context(ctx, mutation);
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
let rejectDeadline;
|
|
32
|
+
const deadline = new Promise((_, reject) => {
|
|
33
|
+
rejectDeadline = () => {
|
|
34
|
+
controller.abort();
|
|
35
|
+
reject(new Error("provisioning deadline exceeded"));
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
const timeout = setTimeout(rejectDeadline, options.timeoutMs ?? 10_000);
|
|
39
|
+
let response;
|
|
40
|
+
try {
|
|
41
|
+
// The same deadline races both token acquisition and the HTTP exchange.
|
|
42
|
+
// AbortSignal alone cannot settle a misbehaving token provider.
|
|
43
|
+
const token = await Promise.race([options.getAccessToken(), deadline]);
|
|
44
|
+
if (!token)
|
|
45
|
+
throw new Error("empty token");
|
|
46
|
+
const exchange = (options.fetch ?? globalThis.fetch)(new URL(path, base), {
|
|
47
|
+
method,
|
|
48
|
+
headers: {
|
|
49
|
+
authorization: `Bearer ${token}`,
|
|
50
|
+
"x-correlation-id": ctx.correlationId,
|
|
51
|
+
...(mutation ? { "idempotency-key": ctx.idempotencyKey } : {}),
|
|
52
|
+
...(body === undefined ? {} : { "content-type": "application/json" }),
|
|
53
|
+
},
|
|
54
|
+
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
55
|
+
signal: controller.signal,
|
|
56
|
+
});
|
|
57
|
+
response = await Promise.race([exchange, deadline]);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return { status: "ambiguous", correlationId: ctx.correlationId, retryable: false, instruction: "RETRY_SAME_REQUEST" };
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
clearTimeout(timeout);
|
|
64
|
+
}
|
|
65
|
+
let data;
|
|
66
|
+
try {
|
|
67
|
+
data = await response.json();
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
data = undefined;
|
|
71
|
+
}
|
|
72
|
+
const responseCorrelation = response.headers.get("x-correlation-id") ?? ctx.correlationId;
|
|
73
|
+
if (response.ok) {
|
|
74
|
+
const parsed = shape === "actor" ? parseActor(data) : parsePage(data);
|
|
75
|
+
if (!parsed)
|
|
76
|
+
throw new ProvisioningClientError("UNEXPECTED_RESPONSE", response.status, responseCorrelation, "Provisioning API returned an invalid success payload");
|
|
77
|
+
return shape === "actor"
|
|
78
|
+
? actorOutcome(parsed, responseCorrelation)
|
|
79
|
+
: { status: "succeeded", value: parsed, correlationId: responseCorrelation };
|
|
80
|
+
}
|
|
81
|
+
const envelope = data;
|
|
82
|
+
const code = envelope?.error?.code;
|
|
83
|
+
const correlationId = envelope?.correlationId ?? responseCorrelation;
|
|
84
|
+
if (code === "OPERATION_IN_PROGRESS")
|
|
85
|
+
return { status: "operation_in_progress", correlationId, retryable: true };
|
|
86
|
+
if (code === "RECONCILIATION_REQUIRED")
|
|
87
|
+
return { status: "reconciliation_required", correlationId, retryable: false };
|
|
88
|
+
if (response.status >= 500)
|
|
89
|
+
return { status: "ambiguous", correlationId, retryable: false, instruction: "RETRY_SAME_REQUEST" };
|
|
90
|
+
const stable = PROVISIONING_ERROR_CODES.includes(code)
|
|
91
|
+
? code : "UNEXPECTED_RESPONSE";
|
|
92
|
+
throw new ProvisioningClientError(stable, response.status, correlationId, envelope?.error?.message ?? "Provisioning request failed", envelope?.error?.details);
|
|
93
|
+
};
|
|
94
|
+
const mutate = (method, path, body, ctx) => {
|
|
95
|
+
meaningfulReason(body);
|
|
96
|
+
return request(method, path, ctx, "actor", body);
|
|
97
|
+
};
|
|
98
|
+
const updateAccess = (id, body, ctx) => mutate("PUT", `/v1/actors/${encodeURIComponent(id)}/access`, body, ctx);
|
|
99
|
+
const resendInvitation = (id, reason, ctx) => mutate("POST", `/v1/actors/${encodeURIComponent(id)}/resend-invitation`, { reason }, ctx);
|
|
100
|
+
return {
|
|
101
|
+
invite: (body, ctx) => mutate("POST", "/v1/actors", body, ctx),
|
|
102
|
+
list: (query, ctx) => {
|
|
103
|
+
const params = new URLSearchParams();
|
|
104
|
+
for (const [key, value] of Object.entries(query))
|
|
105
|
+
if (value !== undefined)
|
|
106
|
+
params.set(key, String(value));
|
|
107
|
+
return request("GET", `/v1/actors${params.size ? `?${params}` : ""}`, ctx, "page");
|
|
108
|
+
},
|
|
109
|
+
get: (id, ctx) => request("GET", `/v1/actors/${encodeURIComponent(id)}`, ctx, "actor"),
|
|
110
|
+
updateAccess,
|
|
111
|
+
access: updateAccess,
|
|
112
|
+
disable: (id, reason, ctx) => mutate("POST", `/v1/actors/${encodeURIComponent(id)}/disable`, { reason }, ctx),
|
|
113
|
+
restore: (id, reason, ctx) => mutate("POST", `/v1/actors/${encodeURIComponent(id)}/restore`, { reason }, ctx),
|
|
114
|
+
resendInvitation,
|
|
115
|
+
resend: resendInvitation,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const opaque = /^[A-Za-z0-9._:-]+$/;
|
|
119
|
+
function parsePage(value) {
|
|
120
|
+
if (!object(value) || !Array.isArray(value["items"]))
|
|
121
|
+
return undefined;
|
|
122
|
+
const items = value["items"].map(parseActor);
|
|
123
|
+
if (items.some((item) => !item) || (value["nextCursor"] !== undefined && typeof value["nextCursor"] !== "string"))
|
|
124
|
+
return undefined;
|
|
125
|
+
return { items: items, ...(typeof value["nextCursor"] === "string" ? { nextCursor: value["nextCursor"] } : {}) };
|
|
126
|
+
}
|
|
127
|
+
export class ProvisioningClientError extends Error {
|
|
128
|
+
code;
|
|
129
|
+
status;
|
|
130
|
+
correlationId;
|
|
131
|
+
details;
|
|
132
|
+
constructor(code, status, correlationId, message, details) {
|
|
133
|
+
super(message);
|
|
134
|
+
this.code = code;
|
|
135
|
+
this.status = status;
|
|
136
|
+
this.correlationId = correlationId;
|
|
137
|
+
this.details = details;
|
|
138
|
+
this.name = "ProvisioningClientError";
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export const PROVISIONING_ERROR_CODES = [
|
|
142
|
+
"INVALID_REQUEST", "AUTHENTICATION_REQUIRED", "PROVISIONING_FORBIDDEN", "ACTOR_NOT_FOUND",
|
|
143
|
+
"EMAIL_CONFLICT", "EXTERNAL_ID_CONFLICT", "IDEMPOTENCY_KEY_REQUIRED", "IDEMPOTENCY_CONFLICT",
|
|
144
|
+
"OPERATION_IN_PROGRESS", "ROLE_NOT_ALLOWED", "GROUP_NOT_ALLOWED", "INVALID_STATE",
|
|
145
|
+
"KEYCLOAK_UNAVAILABLE", "KEYCLOAK_REJECTED", "REGISTRY_UNAVAILABLE", "RECONCILIATION_REQUIRED",
|
|
146
|
+
"REQUEST_TOO_LARGE", "BROWSER_REQUEST_FORBIDDEN", "INTERNAL_ERROR",
|
|
147
|
+
];
|
|
148
|
+
function context(value, mutation) {
|
|
149
|
+
if (!value.correlationId || value.correlationId.length > 128 || !opaque.test(value.correlationId))
|
|
150
|
+
throw new ProvisioningClientError("INVALID_CLIENT_CONFIGURATION", undefined, "", "Invalid correlation ID");
|
|
151
|
+
if (mutation && (!("idempotencyKey" in value) || value.idempotencyKey.length < 16 ||
|
|
152
|
+
value.idempotencyKey.length > 128 || !opaque.test(value.idempotencyKey)))
|
|
153
|
+
throw new ProvisioningClientError("INVALID_CLIENT_CONFIGURATION", undefined, value.correlationId, "Invalid idempotency key");
|
|
154
|
+
}
|
|
155
|
+
const object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
156
|
+
function actorOutcome(actor, correlationId) {
|
|
157
|
+
return actor.state === "RECONCILIATION_REQUIRED"
|
|
158
|
+
? { status: "reconciliation_required", correlationId, actor, retryable: false }
|
|
159
|
+
: { status: "succeeded", value: actor, correlationId };
|
|
160
|
+
}
|
|
161
|
+
function parseActor(value) {
|
|
162
|
+
const optionalString = (name) => value && object(value) &&
|
|
163
|
+
(value[name] === undefined || typeof value[name] === "string");
|
|
164
|
+
if (!object(value) || typeof value["vvpActorId"] !== "string" ||
|
|
165
|
+
!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value["vvpActorId"]) ||
|
|
166
|
+
typeof value["email"] !== "string" || typeof value["actorType"] !== "string" ||
|
|
167
|
+
!optionalString("keycloakSub") || !optionalString("externalId") || !optionalString("displayName") ||
|
|
168
|
+
!optionalString("disabledAt") ||
|
|
169
|
+
!["INVITED", "ACTIVE", "DISABLED", "RECONCILIATION_REQUIRED"].includes(String(value["state"])) ||
|
|
170
|
+
!Array.isArray(value["groups"]) || !value["groups"].every((item) => typeof item === "string") ||
|
|
171
|
+
!object(value["clientRoles"]) ||
|
|
172
|
+
!Object.values(value["clientRoles"]).every((roles) => Array.isArray(roles) && roles.every((role) => typeof role === "string")) ||
|
|
173
|
+
typeof value["createdAt"] !== "string" || !Number.isFinite(Date.parse(value["createdAt"])) ||
|
|
174
|
+
typeof value["updatedAt"] !== "string" || !Number.isFinite(Date.parse(value["updatedAt"])) ||
|
|
175
|
+
(value["disabledAt"] !== undefined && !Number.isFinite(Date.parse(value["disabledAt"]))) ||
|
|
176
|
+
(value["reconciliation"] !== undefined &&
|
|
177
|
+
(!object(value["reconciliation"]) || typeof value["reconciliation"]["errorCode"] !== "string")))
|
|
178
|
+
return undefined;
|
|
179
|
+
return value;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/token.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface BackendTokenProvider {
|
|
2
|
+
getAccessToken(): Promise<string>;
|
|
3
|
+
}
|
|
4
|
+
export interface ClientCredentialsTokenProviderOptions {
|
|
5
|
+
tokenEndpoint: string;
|
|
6
|
+
clientId: string;
|
|
7
|
+
clientSecret: string;
|
|
8
|
+
/** Defaults to and may only be provisioning-api. */
|
|
9
|
+
audience?: "provisioning-api";
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
maxCacheMs?: number;
|
|
12
|
+
fetch?: typeof globalThis.fetch;
|
|
13
|
+
now?: () => number;
|
|
14
|
+
}
|
|
15
|
+
export declare class ClientCredentialsTokenProvider implements BackendTokenProvider {
|
|
16
|
+
private readonly options;
|
|
17
|
+
private cached?;
|
|
18
|
+
private pending;
|
|
19
|
+
private readonly fetch;
|
|
20
|
+
private readonly timeoutMs;
|
|
21
|
+
private readonly maxCacheMs;
|
|
22
|
+
private readonly now;
|
|
23
|
+
constructor(options: ClientCredentialsTokenProviderOptions);
|
|
24
|
+
getAccessToken(): Promise<string>;
|
|
25
|
+
private acquire;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,qCAAqC;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,qBAAa,8BAA+B,YAAW,oBAAoB;IAQ7D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,MAAM,CAAC,CAAuC;IACtD,OAAO,CAAC,OAAO,CAA4D;IAC3E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEN,OAAO,EAAE,qCAAqC;IAerE,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;YAOzB,OAAO;CA2BtB"}
|
package/dist/token.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export class ClientCredentialsTokenProvider {
|
|
2
|
+
options;
|
|
3
|
+
cached;
|
|
4
|
+
pending;
|
|
5
|
+
fetch;
|
|
6
|
+
timeoutMs;
|
|
7
|
+
maxCacheMs;
|
|
8
|
+
now;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
let endpoint;
|
|
12
|
+
try {
|
|
13
|
+
endpoint = new URL(options.tokenEndpoint);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new Error("Token endpoint must be a valid absolute URL");
|
|
17
|
+
}
|
|
18
|
+
const loopback = endpoint.hostname === "localhost" || endpoint.hostname === "127.0.0.1" || endpoint.hostname === "::1" || endpoint.hostname === "[::1]";
|
|
19
|
+
if (endpoint.protocol !== "https:" && !(endpoint.protocol === "http:" && loopback)) {
|
|
20
|
+
throw new Error("Token endpoint must use HTTPS (HTTP is permitted only for exact loopback hosts)");
|
|
21
|
+
}
|
|
22
|
+
if (endpoint.username || endpoint.password)
|
|
23
|
+
throw new Error("Token endpoint must not include URL credentials");
|
|
24
|
+
this.fetch = options.fetch ?? globalThis.fetch;
|
|
25
|
+
this.timeoutMs = Math.min(Math.max(options.timeoutMs ?? 5_000, 100), 30_000);
|
|
26
|
+
this.maxCacheMs = Math.min(Math.max(options.maxCacheMs ?? 300_000, 1_000), 600_000);
|
|
27
|
+
this.now = options.now ?? Date.now;
|
|
28
|
+
}
|
|
29
|
+
async getAccessToken() {
|
|
30
|
+
if (this.cached && this.cached.expiresAt > this.now())
|
|
31
|
+
return this.cached.token;
|
|
32
|
+
this.pending ??= this.acquire().finally(() => { this.pending = undefined; });
|
|
33
|
+
this.cached = await this.pending;
|
|
34
|
+
return this.cached.token;
|
|
35
|
+
}
|
|
36
|
+
async acquire() {
|
|
37
|
+
const body = new URLSearchParams({
|
|
38
|
+
grant_type: "client_credentials",
|
|
39
|
+
client_id: this.options.clientId,
|
|
40
|
+
client_secret: this.options.clientSecret,
|
|
41
|
+
audience: this.options.audience ?? "provisioning-api",
|
|
42
|
+
});
|
|
43
|
+
let response;
|
|
44
|
+
try {
|
|
45
|
+
response = await this.fetch(this.options.tokenEndpoint, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
48
|
+
body,
|
|
49
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (cause) {
|
|
53
|
+
throw new Error("Machine token acquisition failed", { cause });
|
|
54
|
+
}
|
|
55
|
+
if (!response.ok)
|
|
56
|
+
throw new Error(`Machine token acquisition failed with HTTP ${response.status}`);
|
|
57
|
+
const value = await response.json();
|
|
58
|
+
if (typeof value.access_token !== "string" || (value.token_type !== undefined && String(value.token_type).toLowerCase() !== "bearer")) {
|
|
59
|
+
throw new Error("Machine token response is invalid");
|
|
60
|
+
}
|
|
61
|
+
const expiresIn = typeof value.expires_in === "number" && Number.isFinite(value.expires_in) ? value.expires_in * 1_000 : 60_000;
|
|
62
|
+
const ttl = Math.max(1_000, Math.min(this.maxCacheMs, expiresIn - 30_000));
|
|
63
|
+
return { token: value.access_token, expiresAt: this.now() + ttl };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export type ActorState = "INVITED" | "ACTIVE" | "DISABLED" | "RECONCILIATION_REQUIRED";
|
|
2
|
+
export interface Actor {
|
|
3
|
+
vvpActorId: string;
|
|
4
|
+
keycloakSub?: string;
|
|
5
|
+
externalId?: string;
|
|
6
|
+
email: string;
|
|
7
|
+
actorType: string;
|
|
8
|
+
displayName?: string;
|
|
9
|
+
state: ActorState;
|
|
10
|
+
groups: readonly string[];
|
|
11
|
+
clientRoles: Readonly<Record<string, readonly string[]>>;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
disabledAt?: string;
|
|
15
|
+
reconciliation?: {
|
|
16
|
+
errorCode: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface InviteActor {
|
|
20
|
+
email: string;
|
|
21
|
+
externalId?: string;
|
|
22
|
+
actorType: string;
|
|
23
|
+
displayName?: string;
|
|
24
|
+
groups: readonly string[];
|
|
25
|
+
clientRoles: Readonly<Record<string, readonly string[]>>;
|
|
26
|
+
/** Human-readable operator or business justification; 3-500 characters. */
|
|
27
|
+
reason: string;
|
|
28
|
+
}
|
|
29
|
+
export interface UpdateActorAccess {
|
|
30
|
+
groups: readonly string[];
|
|
31
|
+
clientRoles: Readonly<Record<string, readonly string[]>>;
|
|
32
|
+
/** Human-readable operator or business justification; 3-500 characters. */
|
|
33
|
+
reason: string;
|
|
34
|
+
}
|
|
35
|
+
export interface LifecycleReason {
|
|
36
|
+
/** Human-readable operator or business justification; 3-500 characters. */
|
|
37
|
+
reason: string;
|
|
38
|
+
}
|
|
39
|
+
export interface MutationRequestOptions {
|
|
40
|
+
/** Persist before sending. Reuse only to retry the exact same logical request and body. */
|
|
41
|
+
idempotencyKey: string;
|
|
42
|
+
/** Persist before sending. Stable safe identifier useful for tracing an exact retry. */
|
|
43
|
+
correlationId: string;
|
|
44
|
+
}
|
|
45
|
+
export interface MutationResponse<T> {
|
|
46
|
+
data: T;
|
|
47
|
+
replayed: boolean;
|
|
48
|
+
correlationId: string;
|
|
49
|
+
idempotencyKey: string;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,yBAAyB,CAAC;AAEvF,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IACzD,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IACzD,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,2FAA2F;IAC3F,cAAc,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dreadkn1ght123/provisioning-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Backend-only typed client for the VVP Provisioning API",
|
|
5
|
+
"browser": {
|
|
6
|
+
"./dist/index.js": "./dist/browser.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"browser": "./dist/browser.js",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public",
|
|
27
|
+
"provenance": true
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^22.15.0"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc -b",
|
|
34
|
+
"typecheck": "tsc -b --pretty false && tsc -p tsconfig.test.json --noEmit --pretty false",
|
|
35
|
+
"test": "vitest run --config vitest.config.ts"
|
|
36
|
+
}
|
|
37
|
+
}
|