@reclaimprotocol/client 0.1.29 → 0.1.31
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 +255 -234
- package/lib/api.d.ts +2 -0
- package/lib/api.js +2 -0
- package/lib/client.js +2 -0
- package/lib/enckeys.d.ts +1 -1
- package/lib/enckeys.js +2 -2
- package/lib/encoding.d.ts +4 -0
- package/lib/encoding.js +10 -0
- package/lib/feature-flags.d.ts +9 -0
- package/lib/feature-flags.js +19 -0
- package/lib/index.d.ts +4 -4
- package/lib/index.js +4 -4
- package/lib/jwks.d.ts +8 -8
- package/lib/jwks.js +38 -17
- package/lib/launch/destination.d.ts +14 -0
- package/lib/launch/destination.js +89 -0
- package/lib/launch/device.d.ts +30 -0
- package/lib/launch/device.js +168 -0
- package/lib/launch/environment.d.ts +224 -0
- package/lib/launch/environment.js +98 -0
- package/lib/launch/errors.d.ts +20 -0
- package/lib/launch/errors.js +25 -0
- package/lib/launch/extension.d.ts +42 -0
- package/lib/launch/extension.js +72 -0
- package/lib/launch/flow.d.ts +82 -0
- package/lib/launch/flow.js +222 -0
- package/lib/launch/index.d.ts +16 -0
- package/lib/launch/index.js +12 -0
- package/lib/launch/mobile.d.ts +77 -0
- package/lib/launch/mobile.js +124 -0
- package/lib/launch/modal.d.ts +50 -0
- package/lib/launch/modal.js +258 -0
- package/lib/launch/options.d.ts +74 -0
- package/lib/launch/options.js +20 -0
- package/lib/launch/portal.d.ts +28 -0
- package/lib/launch/portal.js +68 -0
- package/lib/launch/qr.d.ts +5 -0
- package/lib/launch/qr.js +28 -0
- package/lib/launch/target.d.ts +46 -0
- package/lib/launch/target.js +128 -0
- package/lib/launch/vendor/qrcodegen.d.ts +134 -0
- package/lib/launch/vendor/qrcodegen.js +822 -0
- package/lib/legacy-proof.d.ts +2 -0
- package/lib/legacy-proof.js +37 -7
- package/lib/proof-hash.d.ts +5 -5
- package/lib/proof-hash.js +1 -1
- package/lib/proof-recipe.d.ts +3 -3
- package/lib/proof-recipe.js +1 -1
- package/lib/proof-types.d.ts +35 -8
- package/lib/reclaim.d.ts +81 -70
- package/lib/reclaim.js +79 -130
- package/lib/request-proof.d.ts +60 -0
- package/lib/request-proof.js +241 -0
- package/lib/result.d.ts +46 -38
- package/lib/result.js +160 -100
- package/lib/routes.gen.d.ts +76 -28
- package/lib/routes.gen.js +24 -11
- package/lib/tee-binding.d.ts +1 -1
- package/lib/types/openapi.d.ts +1 -0
- package/lib/types/openapi.gen.d.ts +1594 -488
- package/lib/types/openapi.gen.js +5 -0
- package/lib/verification-clients.d.ts +28 -14
- package/lib/verification-clients.js +31 -11
- package/lib/verify-attestor-tee.d.ts +19 -2
- package/lib/verify-attestor-tee.js +40 -4
- package/lib/verify-tee.d.ts +10 -1
- package/lib/verify-tee.js +34 -10
- package/package.json +5 -1
- package/src/api.ts +9 -0
- package/src/client.ts +2 -0
- package/src/enckeys.ts +2 -2
- package/src/encoding.ts +12 -0
- package/src/feature-flags.ts +39 -0
- package/src/index.ts +13 -14
- package/src/jwks.ts +52 -30
- package/src/launch/destination.ts +111 -0
- package/src/launch/device.ts +242 -0
- package/src/launch/environment.ts +337 -0
- package/src/launch/errors.ts +49 -0
- package/src/launch/extension.ts +124 -0
- package/src/launch/flow.ts +369 -0
- package/src/launch/index.ts +42 -0
- package/src/launch/mobile.ts +184 -0
- package/src/launch/modal.ts +378 -0
- package/src/launch/options.ts +99 -0
- package/src/launch/portal.ts +104 -0
- package/src/launch/qr.ts +37 -0
- package/src/launch/target.ts +150 -0
- package/src/launch/vendor/qrcodegen.ts +1034 -0
- package/src/proof-hash.ts +6 -6
- package/src/proof-recipe.ts +3 -3
- package/src/proof-types.ts +36 -8
- package/src/reclaim.ts +185 -218
- package/src/{legacy-proof.ts → request-proof.ts} +81 -36
- package/src/result.ts +238 -172
- package/src/routes.gen.ts +24 -11
- package/src/tee-binding.ts +1 -1
- package/src/types/openapi.gen.ts +1599 -488
- package/src/types/openapi.ts +3 -1
- package/src/verification-clients.ts +33 -19
- package/src/verify-attestor-tee.ts +66 -8
- package/src/verify-tee.ts +44 -13
- package/lib/api-client.d.ts +0 -31
- package/lib/api-client.js +0 -112
- package/lib/api-consts.d.ts +0 -4
- package/lib/api-consts.js +0 -4
- package/lib/api-errors.d.ts +0 -13
- package/lib/api-errors.js +0 -30
- package/lib/eip712.d.ts +0 -20
- package/lib/eip712.js +0 -108
package/lib/legacy-proof.d.ts
CHANGED
|
@@ -44,6 +44,8 @@ export interface LegacyProofOutcome {
|
|
|
44
44
|
reason?: string;
|
|
45
45
|
proofHashes?: string[];
|
|
46
46
|
isTeeAttestationVerified?: boolean;
|
|
47
|
+
/** True when at least one witness's `attestation_report` verified; false
|
|
48
|
+
* when the check ran and no witness carried one. */
|
|
47
49
|
isAttestorTeeAttestationVerified?: boolean;
|
|
48
50
|
data?: TrustedData[];
|
|
49
51
|
publicData?: unknown[];
|
package/lib/legacy-proof.js
CHANGED
|
@@ -20,8 +20,8 @@ export async function verifyProof(proofOrProofs, config) {
|
|
|
20
20
|
try {
|
|
21
21
|
const effective = await resolveValidation(config, proofs);
|
|
22
22
|
assertSessionAndContext(proofs, effective);
|
|
23
|
-
const
|
|
24
|
-
assertVerifiedSignatures(proofs,
|
|
23
|
+
const trust = await resolveAttestorTrust(effective);
|
|
24
|
+
assertVerifiedSignatures(proofs, trust.addresses);
|
|
25
25
|
await assertContent(proofs, effective);
|
|
26
26
|
let isTeeAttestationVerified;
|
|
27
27
|
if (effective.teeAttestation) {
|
|
@@ -29,9 +29,14 @@ export async function verifyProof(proofOrProofs, config) {
|
|
|
29
29
|
isTeeAttestationVerified = true;
|
|
30
30
|
}
|
|
31
31
|
let isAttestorTeeAttestationVerified;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const attestorTeeAttestation = resolveAttestorTeeAttestation(effective.attestorTeeAttestation, trust.imageDigests);
|
|
33
|
+
if (attestorTeeAttestation) {
|
|
34
|
+
// `verified` counts witnesses whose attestation report was checked.
|
|
35
|
+
// A proof whose witnesses carry no report still passes the address
|
|
36
|
+
// and signature bindings, but nothing was attested — say so rather
|
|
37
|
+
// than reporting a TEE attestation that never happened.
|
|
38
|
+
const summary = await runAttestorTeeVerification(proofs, attestorTeeAttestation);
|
|
39
|
+
isAttestorTeeAttestationVerified = summary.verified > 0;
|
|
35
40
|
}
|
|
36
41
|
return {
|
|
37
42
|
valid: true,
|
|
@@ -62,17 +67,42 @@ async function resolveValidation(config, proofs) {
|
|
|
62
67
|
}
|
|
63
68
|
return effective;
|
|
64
69
|
}
|
|
65
|
-
async function
|
|
70
|
+
async function resolveAttestorTrust(config) {
|
|
66
71
|
const addresses = config.attestorAddresses?.map(normalized) ?? [];
|
|
72
|
+
const imageDigests = [];
|
|
67
73
|
if (config.attestorJwksUrl) {
|
|
68
74
|
const registry = await fetchReclaimJwks(config.attestorJwksUrl, config.fetchImpl);
|
|
69
75
|
addresses.push(...(registry['x-reclaim-attestors'] ?? []), ...trustedAttestorAddresses(registry.keys));
|
|
76
|
+
imageDigests.push(...(registry['x-reclaim-attestor-image-digests'] ?? []));
|
|
70
77
|
}
|
|
71
78
|
const unique = [...new Set(addresses)];
|
|
72
79
|
if (!unique.length) {
|
|
73
80
|
throw new Error('attestor-trust-required');
|
|
74
81
|
}
|
|
75
|
-
return
|
|
82
|
+
return {
|
|
83
|
+
addresses: unique,
|
|
84
|
+
imageDigests: [...new Set(imageDigests)],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function resolveAttestorTeeAttestation(configured, registryImageDigests) {
|
|
88
|
+
if (!registryImageDigests.length) {
|
|
89
|
+
return configured;
|
|
90
|
+
}
|
|
91
|
+
const configuredDigests = configured?.expectedImageDigests;
|
|
92
|
+
if (configuredDigests?.length) {
|
|
93
|
+
const registry = new Set(registryImageDigests);
|
|
94
|
+
const expectedImageDigests = [...new Set(configuredDigests
|
|
95
|
+
.map((digest) => digest.trim().toLowerCase())
|
|
96
|
+
.filter((digest) => registry.has(digest)))];
|
|
97
|
+
if (!expectedImageDigests.length) {
|
|
98
|
+
throw new Error('attestor-image-trust-mismatch');
|
|
99
|
+
}
|
|
100
|
+
return { ...configured, expectedImageDigests };
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
...configured,
|
|
104
|
+
expectedImageDigests: registryImageDigests,
|
|
105
|
+
};
|
|
76
106
|
}
|
|
77
107
|
function assertVerifiedSignatures(proofs, trustedAttestors) {
|
|
78
108
|
for (const proof of proofs) {
|
package/lib/proof-hash.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HashRequirement,
|
|
1
|
+
import type { HashRequirement, ReclaimRequestProof } from './proof-types.ts';
|
|
2
2
|
export interface HttpProofParams {
|
|
3
3
|
url: string;
|
|
4
4
|
method: string;
|
|
@@ -27,9 +27,9 @@ export interface ProofRequestSpec extends HttpProofParams {
|
|
|
27
27
|
templateParams?: string[];
|
|
28
28
|
templateParamsMode?: 'separate' | 'merge';
|
|
29
29
|
}
|
|
30
|
-
/** Exact
|
|
30
|
+
/** Exact canonical HTTP-provider hashes, including optional matches. */
|
|
31
31
|
export declare function hashProofClaimParams(params: HttpProofParams): string[];
|
|
32
|
-
export declare function getHashFromProof(proof:
|
|
32
|
+
export declare function getHashFromProof(proof: ReclaimRequestProof, hasNoPii?: boolean): string[];
|
|
33
33
|
export declare function hashRequestSpec(request: ProofRequestSpec): HashRequirement;
|
|
34
|
-
export declare function hashRequirementsFromSpecs(requestData: ProofRequestSpec[], allowedInjectedRequestData: ProofRequestSpec[], proofs:
|
|
35
|
-
export declare function assertValidProofHashes(proofs:
|
|
34
|
+
export declare function hashRequirementsFromSpecs(requestData: ProofRequestSpec[], allowedInjectedRequestData: ProofRequestSpec[], proofs: ReclaimRequestProof[]): HashRequirement[];
|
|
35
|
+
export declare function assertValidProofHashes(proofs: ReclaimRequestProof[], requirements: Array<string | HashRequirement>, hasNoPii?: boolean): void;
|
package/lib/proof-hash.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { keccak_256 } from '@noble/hashes/sha3.js';
|
|
2
2
|
import { canonicalJson as canonical } from "./canonical.js";
|
|
3
3
|
import { bytesToHex } from "./encoding.js";
|
|
4
|
-
/** Exact
|
|
4
|
+
/** Exact canonical HTTP-provider hashes, including optional matches. */
|
|
5
5
|
export function hashProofClaimParams(params) {
|
|
6
6
|
return canonicalProofParams(params).map((serialized) => ('0x' + bytesToHex(keccak_256(new TextEncoder().encode(serialized)))));
|
|
7
7
|
}
|
package/lib/proof-recipe.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { components } from './types/openapi.gen.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ReclaimRequestProof } from './proof-types.ts';
|
|
3
3
|
type RequestSelection = components['schemas']['RequestSelection'];
|
|
4
4
|
type RequestSelectionTemplate = components['schemas']['RequestSelectionTemplate'];
|
|
5
5
|
/** Resolved Builder provider recipe returned for a verification session. */
|
|
@@ -11,8 +11,8 @@ export interface BuilderProofRecipe {
|
|
|
11
11
|
allowedJsRequests?: RequestSelectionTemplate[];
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* Derive the exact hash requirements consumed by
|
|
14
|
+
* Derive the exact hash requirements consumed by `verifyRequestProof` from a
|
|
15
15
|
* resolved Builder recipe. Builder's fixed requests are required once each.
|
|
16
16
|
*/
|
|
17
|
-
export declare function proofHashesFromBuilderRecipe(recipe: BuilderProofRecipe, proofs:
|
|
17
|
+
export declare function proofHashesFromBuilderRecipe(recipe: BuilderProofRecipe, proofs: ReclaimRequestProof[]): import("./proof-types.ts").HashRequirement[];
|
|
18
18
|
export {};
|
package/lib/proof-recipe.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { hashRequirementsFromSpecs, } from "./proof-hash.js";
|
|
2
2
|
/**
|
|
3
|
-
* Derive the exact hash requirements consumed by
|
|
3
|
+
* Derive the exact hash requirements consumed by `verifyRequestProof` from a
|
|
4
4
|
* resolved Builder recipe. Builder's fixed requests are required once each.
|
|
5
5
|
*/
|
|
6
6
|
export function proofHashesFromBuilderRecipe(recipe, proofs) {
|
package/lib/proof-types.d.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
/** Exact
|
|
2
|
-
|
|
1
|
+
/** Exact proof structure for one verified request, carried inside Builder
|
|
2
|
+
* result envelopes. Every Verification Client — the in-app SDK, the browser
|
|
3
|
+
* extension, portals, and Builder's own client — emits this shape. */
|
|
4
|
+
export interface ReclaimRequestProof {
|
|
3
5
|
identifier: string;
|
|
4
|
-
claimData:
|
|
6
|
+
claimData: RequestClaimData;
|
|
5
7
|
signatures: string[];
|
|
6
|
-
witnesses:
|
|
8
|
+
witnesses: RequestWitness[];
|
|
7
9
|
extractedParameterValues: unknown;
|
|
8
10
|
publicData?: unknown;
|
|
9
11
|
taskId?: number;
|
|
10
|
-
|
|
12
|
+
/** Client-specific legacy TEE data. Verification validates a supported
|
|
13
|
+
* representation only when TEE verification is requested. */
|
|
14
|
+
teeAttestation?: unknown;
|
|
11
15
|
}
|
|
12
|
-
export interface
|
|
16
|
+
export interface RequestClaimData {
|
|
13
17
|
provider: string;
|
|
14
18
|
parameters: string;
|
|
15
19
|
owner: string;
|
|
@@ -18,15 +22,38 @@ export interface LegacyClaimData {
|
|
|
18
22
|
identifier: string;
|
|
19
23
|
epoch: number;
|
|
20
24
|
}
|
|
21
|
-
export interface
|
|
25
|
+
export interface RequestWitness {
|
|
22
26
|
id: string;
|
|
23
27
|
url: string;
|
|
24
28
|
claimAttestation?: AttestorClaimAttestation;
|
|
25
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Which kind of attestation a witness carries.
|
|
32
|
+
*
|
|
33
|
+
* `embedded-attestor` — the in-app SDK and the browser extension. The attestor
|
|
34
|
+
* signs the claim and, on a TEE run, may also return its own
|
|
35
|
+
* `attestation_report`.
|
|
36
|
+
*
|
|
37
|
+
* `confidential-space` — portals. The browser runtime signs the claim inside a
|
|
38
|
+
* GCP Confidential Space and returns `tee_attestation`, bound to the claim
|
|
39
|
+
* through `context.attestationNonce`.
|
|
40
|
+
*/
|
|
41
|
+
export type ClaimAttestationType = 'embedded-attestor' | 'confidential-space';
|
|
26
42
|
export interface AttestorClaimAttestation {
|
|
43
|
+
type: ClaimAttestationType;
|
|
27
44
|
attestor_address: string;
|
|
28
45
|
claim_signature: string;
|
|
29
|
-
|
|
46
|
+
/** `embedded-attestor` only, and optional even then: the attestor's own GCP
|
|
47
|
+
* Confidential Space attestation (an RS256 JWT). Attestors in production
|
|
48
|
+
* sign claims without returning one, so a witness routinely carries only
|
|
49
|
+
* the address and the claim signature. */
|
|
50
|
+
attestation_report?: string;
|
|
51
|
+
/** `confidential-space` only: the same payload legacy proofs carry in the
|
|
52
|
+
* proof's top-level `teeAttestation`, and typed the same way. It comes
|
|
53
|
+
* from an external producer and is preserved verbatim, so callers validate
|
|
54
|
+
* it at runtime — `verifyTeeAttestation` does — rather than trusting a
|
|
55
|
+
* shape the wire does not guarantee. */
|
|
56
|
+
tee_attestation?: unknown;
|
|
30
57
|
}
|
|
31
58
|
export interface TeeAttestation {
|
|
32
59
|
proof_version?: 'v2' | 'v3';
|
package/lib/reclaim.d.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Declarative entry point for the consumer SDK. The ONLY config is the org
|
|
3
3
|
* secret (`rorg_…`) — it authenticates every call and identifies the org
|
|
4
|
-
* server-side.
|
|
5
|
-
*
|
|
6
|
-
* `results.decrypt`/`receive` (only when results arrive encrypted):
|
|
4
|
+
* server-side. Pass the optional organization ETH private key only to the
|
|
5
|
+
* operation that needs it:
|
|
7
6
|
*
|
|
8
|
-
* const reclaim =
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* const reclaim = ReclaimVerification.create({ orgSecret })
|
|
8
|
+
* const session = await reclaim.sessions.create({
|
|
9
|
+
* providers,
|
|
10
|
+
* context,
|
|
11
|
+
* orgEthPrivateKey, // optional TEE session binding
|
|
12
|
+
* })
|
|
14
13
|
* // …end-user completes session.verificationUrl…
|
|
15
14
|
* const outcome = await reclaim.results.receive(callbackBody, {
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* orgEthPrivateKey, // optional decryption and TEE proof verification
|
|
16
|
+
* reclaimSessionId: session.id,
|
|
18
17
|
* })
|
|
19
18
|
*
|
|
20
19
|
* Built by composition over the package's pure helpers (`decryptCallback`,
|
|
@@ -26,17 +25,9 @@ import { ReclaimClient } from './client.ts';
|
|
|
26
25
|
import { type DecryptionKeyInput } from './enckeys.ts';
|
|
27
26
|
import { type CallbackBody, type Jws, type VerifyResultFullOptions, type VerifyResultFullOutcome } from './result.ts';
|
|
28
27
|
import { type LegacyTeeNonceMode } from './tee-binding.ts';
|
|
29
|
-
type CallbackSubscription = components['schemas']['CallbackSubscription'];
|
|
30
28
|
type VerificationSession = components['schemas']['VerificationSession'];
|
|
31
29
|
type VerificationEvent = components['schemas']['VerificationEvent'];
|
|
32
30
|
type VerificationEventRecord = components['schemas']['VerificationEventRecord'];
|
|
33
|
-
type OrgKeypair = components['schemas']['OrgKeypair'];
|
|
34
|
-
/** Terminal lifecycle events selected by default for callback subscriptions. */
|
|
35
|
-
export declare const TERMINAL_EVENTS: readonly ["verification_success", "verification_rejected", "verification_error", "verification_cancelled", "session_expired"];
|
|
36
|
-
export interface RegisterCallbackInput {
|
|
37
|
-
callbackUrl: string;
|
|
38
|
-
events: VerificationEvent[];
|
|
39
|
-
}
|
|
40
31
|
export interface CreateSessionInput {
|
|
41
32
|
/** Providers to verify, in run order. The end-user proves each (one browser
|
|
42
33
|
* session) and one combined result is delivered; all are required. */
|
|
@@ -45,32 +36,34 @@ export interface CreateSessionInput {
|
|
|
45
36
|
version?: string;
|
|
46
37
|
}[];
|
|
47
38
|
context: Record<string, unknown>;
|
|
48
|
-
/** Exact registered Verification Client base URL.
|
|
39
|
+
/** Exact registered Verification Client base URL. Defaults to the Portal.
|
|
40
|
+
* It may contain a
|
|
49
41
|
* `{sessionId}` placeholder; Builder otherwise adds the session id as a
|
|
50
42
|
* query parameter. Open the returned `verificationUrl`, not this base
|
|
51
43
|
* URL. */
|
|
52
|
-
verificationClientUrl
|
|
53
|
-
/** Optional legacy-compatible TEE session binding. The
|
|
54
|
-
*
|
|
44
|
+
verificationClientUrl?: string;
|
|
45
|
+
/** Optional legacy-compatible TEE session binding. The organization's ETH
|
|
46
|
+
* private key never leaves this process.
|
|
55
47
|
* Session creation returns only after Builder stores the signed binding. */
|
|
56
|
-
|
|
48
|
+
orgEthPrivateKey?: string;
|
|
49
|
+
/** Override the legacy TEE nonce mode when binding a session. */
|
|
50
|
+
teeNonceMode?: LegacyTeeNonceMode;
|
|
51
|
+
/** Opt this session into diagnostic mode: more event detail, including
|
|
52
|
+
* personal data such as the claimant's IP addresses. Builder builds
|
|
53
|
+
* `verificationUrl` with `diag=1` for a diagnostic session — do not
|
|
54
|
+
* append `diag` to the URL directly, since Builder strips it and derives
|
|
55
|
+
* the parameter from this flag instead. Treat a diagnostic
|
|
56
|
+
* `verificationUrl` as sensitive. */
|
|
57
|
+
diagnostics?: boolean;
|
|
57
58
|
}
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
appSecret: string;
|
|
59
|
+
/** Input for explicitly binding a session's legacy-compatible TEE context. */
|
|
60
|
+
export interface BindSessionTeeNonceInput {
|
|
61
|
+
orgEthPrivateKey: string;
|
|
62
62
|
timestamp?: string;
|
|
63
63
|
/** `hash` is the default. Use `signature` only for an older Verification
|
|
64
64
|
* Client that expects the 65-byte EIP-191 nonce. */
|
|
65
|
-
|
|
65
|
+
teeNonceMode?: LegacyTeeNonceMode;
|
|
66
66
|
}
|
|
67
|
-
/** Input for `keypair.set`: the org's eth public key as uncompressed hex
|
|
68
|
-
* (`publicKey`, the form wallets/ethers emit) OR as a secp256k1 JWK
|
|
69
|
-
* (`publicKeyJwk`); keep the matching eth private key to decrypt results.
|
|
70
|
-
* `canEncryptResult` toggles ECIES encryption (default off). The two request
|
|
71
|
-
* shapes are the spec's `OrgKeypairRequest` union members, relaxed to optional
|
|
72
|
-
* so the SDK caller supplies just one key form. */
|
|
73
|
-
export type SetKeypairInput = Partial<components['schemas']['OrgKeypairHexRequest']> & Partial<components['schemas']['OrgKeypairJwkRequest']>;
|
|
74
67
|
export interface ReclaimConfig {
|
|
75
68
|
/** The org secret (`rorg_…`). Authenticates ALL API calls and identifies
|
|
76
69
|
* the org server-side. The only required config. */
|
|
@@ -82,62 +75,75 @@ export interface ReclaimConfig {
|
|
|
82
75
|
/** Extra headers merged into every request. */
|
|
83
76
|
headers?: Record<string, string>;
|
|
84
77
|
}
|
|
78
|
+
/** Serializable SDK configuration.
|
|
79
|
+
* Credentials and runtime hooks are omitted. */
|
|
80
|
+
export interface ReclaimVerificationState {
|
|
81
|
+
version: 1;
|
|
82
|
+
baseUrl: string;
|
|
83
|
+
}
|
|
84
|
+
/** Runtime-only values required to restore serialized SDK configuration. */
|
|
85
|
+
export type ImportReclaimVerificationConfig = Omit<ReclaimConfig, 'baseUrl'>;
|
|
85
86
|
/** Options for `results.receive` — the verification options plus an optional
|
|
86
87
|
* eth decryption key (the org's eth private key as `0x`-hex). The key is
|
|
87
88
|
* needed only when the delivery is an ECIES ciphertext. */
|
|
88
|
-
export type ReceiveOptions = VerifyResultFullOptions
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
export type ReceiveOptions = VerifyResultFullOptions;
|
|
90
|
+
/** A thin backend-side handle on a session's `verificationUrl` — see
|
|
91
|
+
* `reclaim.flow`. Not the browser launcher: this holds no device
|
|
92
|
+
* detection or launch mechanism, only the URL the browser needs. The
|
|
93
|
+
* browser-only `ReclaimFlow.from(session)` in
|
|
94
|
+
* `@reclaimprotocol/client/launch` is the counterpart that actually
|
|
95
|
+
* resolves how to open it. */
|
|
96
|
+
export interface SessionFlow {
|
|
97
|
+
/** `session.verificationUrl`. A `Promise` so backend code calling this
|
|
98
|
+
* doesn't need to special-case it against the browser `ReclaimFlow`'s
|
|
99
|
+
* `getUrl()`, which does real async work. */
|
|
100
|
+
getUrl(): Promise<string>;
|
|
101
|
+
readonly session: VerificationSession;
|
|
102
|
+
}
|
|
103
|
+
/** `reclaim.flow(session)` wraps a session already created via
|
|
104
|
+
* `sessions.create`/`sessions.get`; `reclaim.flow.create(input)` creates one
|
|
105
|
+
* and wraps it in the same step. */
|
|
106
|
+
export interface ReclaimFlowFactory {
|
|
107
|
+
(session: VerificationSession): SessionFlow;
|
|
108
|
+
create(input: CreateSessionInput): Promise<SessionFlow>;
|
|
109
|
+
}
|
|
110
|
+
export interface ReclaimVerification {
|
|
111
|
+
/** Serialize non-secret configuration. Credentials, headers, and custom
|
|
112
|
+
* fetch implementations are never included. */
|
|
113
|
+
export(): string;
|
|
92
114
|
/** Typed escape hatch: `reclaim.api('OperationId', args)` for any spec
|
|
93
115
|
* operation. */
|
|
94
116
|
api: ReclaimClient['call'];
|
|
95
117
|
sessions: {
|
|
96
118
|
/** Create a verification session. `verificationClientUrl` defaults to
|
|
97
|
-
* the
|
|
98
|
-
create(input:
|
|
119
|
+
* the Portal, `VerificationClient.portals`. */
|
|
120
|
+
create(input: CreateSessionInput): Promise<VerificationSession>;
|
|
99
121
|
/** Add the immutable legacy-compatible TEE context after session
|
|
100
122
|
* creation. Normally use
|
|
101
|
-
* `sessions.create({
|
|
123
|
+
* `sessions.create({ orgEthPrivateKey })`; this method
|
|
102
124
|
* supports retrying or explicitly orchestrating the two-step flow. */
|
|
103
|
-
bindTeeNonce(
|
|
104
|
-
get(
|
|
105
|
-
listEvents(
|
|
106
|
-
};
|
|
107
|
-
callbacks: {
|
|
108
|
-
/** Register a callback subscription (one-time setup). Delivery is scoped
|
|
109
|
-
* to the token's org; results are ECIES-encrypted to the org's eth key
|
|
110
|
-
* when `canEncryptResult` is enabled (see `keypair.set`), else plaintext.
|
|
111
|
-
* `events` defaults to all terminal lifecycle events. */
|
|
112
|
-
register(input: Partial<RegisterCallbackInput> & Pick<RegisterCallbackInput, 'callbackUrl'>): Promise<CallbackSubscription>;
|
|
113
|
-
list(): Promise<CallbackSubscription[]>;
|
|
114
|
-
remove(subscriptionId: string): Promise<void>;
|
|
115
|
-
};
|
|
116
|
-
keypair: {
|
|
117
|
-
/** Set/rotate org `orgId`'s single eth encryption keypair. When
|
|
118
|
-
* `canEncryptResult` is enabled, terminal results are delivered as an
|
|
119
|
-
* ECIES ciphertext encrypted to it. */
|
|
120
|
-
set(orgId: string, input: SetKeypairInput): Promise<OrgKeypair>;
|
|
121
|
-
/** Get org `orgId`'s encryption keypair, or `undefined` when none is set
|
|
122
|
-
* (the org is keyless ⇒ plaintext delivery). */
|
|
123
|
-
get(orgId: string): Promise<OrgKeypair | undefined>;
|
|
125
|
+
bindTeeNonce(reclaimSessionId: string, input: BindSessionTeeNonceInput): Promise<VerificationSession>;
|
|
126
|
+
get(reclaimSessionId: string): Promise<VerificationSession>;
|
|
127
|
+
listEvents(reclaimSessionId: string): Promise<VerificationEventRecord[]>;
|
|
124
128
|
};
|
|
125
129
|
results: {
|
|
126
130
|
/** Decrypt a callback body (ECIES ciphertext or plaintext JWS) to the
|
|
127
|
-
* signed JWS. Pass
|
|
128
|
-
*
|
|
129
|
-
decrypt(body: CallbackBody,
|
|
131
|
+
* signed JWS. Pass `orgEthPrivateKey` only when the delivery is
|
|
132
|
+
* encrypted. */
|
|
133
|
+
decrypt(body: CallbackBody, orgEthPrivateKey?: DecryptionKeyInput): Promise<Jws>;
|
|
130
134
|
/** Verify a decrypted JWS: JWKS discovery, ES256K signature,
|
|
131
|
-
* `reclaimSessionId`/`aud`, any legacy `exp`, and exact
|
|
135
|
+
* `reclaimSessionId`/`aud`, any legacy `exp`, and exact proofs. */
|
|
132
136
|
verify(jws: Jws, opts?: VerifyResultFullOptions): Promise<VerifyResultFullOutcome>;
|
|
133
137
|
/** Handle any callback delivery in one call — the 90% path. Branches on
|
|
134
138
|
* the envelope's `event`: a terminal event is decrypted (with
|
|
135
|
-
* `opts.
|
|
139
|
+
* `opts.orgEthPrivateKey` when encrypted) and verified into a `result`; a
|
|
136
140
|
* non-terminal event is returned as a plaintext (unsigned) `event`
|
|
137
141
|
* notification without decryption. (A raw JWE/JWS body with no envelope
|
|
138
142
|
* `event` is treated as a terminal result.) */
|
|
139
143
|
receive(body: CallbackBody, opts?: ReceiveOptions): Promise<ReceivedDelivery>;
|
|
140
144
|
};
|
|
145
|
+
/** `reclaim.flow(session)` — see `ReclaimFlowFactory`. */
|
|
146
|
+
flow: ReclaimFlowFactory;
|
|
141
147
|
}
|
|
142
148
|
/** Outcome of `results.receive` — a verified terminal result or a plaintext
|
|
143
149
|
* non-terminal progress notification. Branch on `kind`. */
|
|
@@ -149,5 +155,10 @@ export type ReceivedDelivery = {
|
|
|
149
155
|
event: VerificationEvent;
|
|
150
156
|
eventData: Record<string, unknown>;
|
|
151
157
|
};
|
|
152
|
-
export declare
|
|
158
|
+
export declare const ReclaimVerification: Readonly<{
|
|
159
|
+
create: typeof createReclaimVerification;
|
|
160
|
+
import: typeof importReclaimVerification;
|
|
161
|
+
}>;
|
|
162
|
+
declare function importReclaimVerification(serialized: string, config: ImportReclaimVerificationConfig): ReclaimVerification;
|
|
163
|
+
declare function createReclaimVerification(config: ReclaimConfig): ReclaimVerification;
|
|
153
164
|
export {};
|