@interop/wallet-core 0.1.1 → 0.3.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 +27 -3
- package/dist/display/alignment.d.ts +49 -0
- package/dist/display/alignment.d.ts.map +1 -0
- package/dist/display/alignment.js +114 -0
- package/dist/display/alignment.js.map +1 -0
- package/dist/display/credentialName.d.ts +42 -0
- package/dist/display/credentialName.d.ts.map +1 -0
- package/dist/display/credentialName.js +106 -0
- package/dist/display/credentialName.js.map +1 -0
- package/dist/display/displayFields.d.ts +55 -0
- package/dist/display/displayFields.d.ts.map +1 -0
- package/dist/display/displayFields.js +136 -0
- package/dist/display/displayFields.js.map +1 -0
- package/dist/display/evidence.d.ts +44 -0
- package/dist/display/evidence.d.ts.map +1 -0
- package/dist/display/evidence.js +65 -0
- package/dist/display/evidence.js.map +1 -0
- package/dist/display/image.d.ts +18 -0
- package/dist/display/image.d.ts.map +1 -0
- package/dist/display/image.js +23 -0
- package/dist/display/image.js.map +1 -0
- package/dist/display/index.d.ts +38 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.js +32 -0
- package/dist/display/index.js.map +1 -0
- package/dist/display/issuer.d.ts +97 -0
- package/dist/display/issuer.d.ts.map +1 -0
- package/dist/display/issuer.js +126 -0
- package/dist/display/issuer.js.map +1 -0
- package/dist/display/obv3.d.ts +77 -0
- package/dist/display/obv3.d.ts.map +1 -0
- package/dist/display/obv3.js +127 -0
- package/dist/display/obv3.js.map +1 -0
- package/dist/display/parse.d.ts +62 -0
- package/dist/display/parse.d.ts.map +1 -0
- package/dist/display/parse.js +100 -0
- package/dist/display/parse.js.map +1 -0
- package/dist/display/subject.d.ts +75 -0
- package/dist/display/subject.d.ts.map +1 -0
- package/dist/display/subject.js +122 -0
- package/dist/display/subject.js.map +1 -0
- package/dist/display/text.d.ts +42 -0
- package/dist/display/text.d.ts.map +1 -0
- package/dist/display/text.js +62 -0
- package/dist/display/text.js.map +1 -0
- package/dist/display/types.d.ts +55 -0
- package/dist/display/types.d.ts.map +1 -0
- package/dist/display/types.js +41 -0
- package/dist/display/types.js.map +1 -0
- package/dist/display/validity.d.ts +51 -0
- package/dist/display/validity.d.ts.map +1 -0
- package/dist/display/validity.js +51 -0
- package/dist/display/validity.js.map +1 -0
- package/dist/display/verificationView.d.ts +101 -0
- package/dist/display/verificationView.d.ts.map +1 -0
- package/dist/display/verificationView.js +199 -0
- package/dist/display/verificationView.js.map +1 -0
- package/dist/identity/agents.d.ts +68 -0
- package/dist/identity/agents.d.ts.map +1 -0
- package/dist/identity/agents.js +95 -0
- package/dist/identity/agents.js.map +1 -0
- package/dist/identity/index.d.ts +20 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +19 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/keyResolver.d.ts +30 -0
- package/dist/identity/keyResolver.d.ts.map +1 -0
- package/dist/identity/keyResolver.js +25 -0
- package/dist/identity/keyResolver.js.map +1 -0
- package/dist/index.d.ts +14 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/request/classify.d.ts +112 -0
- package/dist/request/classify.d.ts.map +1 -0
- package/dist/request/classify.js +210 -0
- package/dist/request/classify.js.map +1 -0
- package/dist/request/composeVp.d.ts +52 -0
- package/dist/request/composeVp.d.ts.map +1 -0
- package/dist/request/composeVp.js +177 -0
- package/dist/request/composeVp.js.map +1 -0
- package/dist/request/exchangeClient.d.ts +165 -0
- package/dist/request/exchangeClient.d.ts.map +1 -0
- package/dist/request/exchangeClient.js +212 -0
- package/dist/request/exchangeClient.js.map +1 -0
- package/dist/request/index.d.ts +35 -0
- package/dist/request/index.d.ts.map +1 -0
- package/dist/request/index.js +35 -0
- package/dist/request/index.js.map +1 -0
- package/dist/request/interactionUrl.d.ts +53 -0
- package/dist/request/interactionUrl.d.ts.map +1 -0
- package/dist/request/interactionUrl.js +83 -0
- package/dist/request/interactionUrl.js.map +1 -0
- package/dist/request/matching.d.ts +69 -0
- package/dist/request/matching.d.ts.map +1 -0
- package/dist/request/matching.js +183 -0
- package/dist/request/matching.js.map +1 -0
- package/dist/request/parse.d.ts +68 -0
- package/dist/request/parse.d.ts.map +1 -0
- package/dist/request/parse.js +114 -0
- package/dist/request/parse.js.map +1 -0
- package/dist/request/presentationSuite.d.ts +71 -0
- package/dist/request/presentationSuite.d.ts.map +1 -0
- package/dist/request/presentationSuite.js +139 -0
- package/dist/request/presentationSuite.js.map +1 -0
- package/dist/request/processRequest.d.ts +48 -0
- package/dist/request/processRequest.d.ts.map +1 -0
- package/dist/request/processRequest.js +139 -0
- package/dist/request/processRequest.js.map +1 -0
- package/dist/request/types.d.ts +150 -0
- package/dist/request/types.d.ts.map +1 -0
- package/dist/request/types.js +2 -0
- package/dist/request/types.js.map +1 -0
- package/dist/sync/types.d.ts.map +1 -1
- package/package.json +31 -3
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Validity-period readers for both VC Data Model 1.0 (`issuanceDate` /
|
|
6
|
+
* `expirationDate`) and 2.0 (`validFrom` / `validUntil`). The library returns
|
|
7
|
+
* the raw ISO strings and a `Date` -- never a formatted string -- so each app
|
|
8
|
+
* applies its own locale formatting on top (the raw-values seam).
|
|
9
|
+
*
|
|
10
|
+
* Drift resolution: this is the union of DCW's `credentialValidityPeriod.ts`
|
|
11
|
+
* (which had `getIssuanceDate` / `getExpirationDate` / `isExpired` returning
|
|
12
|
+
* `undefined` when absent) and Freewallet's `formatDate.ts` (which had
|
|
13
|
+
* `getExpirationInstant` returning `Date | null`, plus an empty-string variant
|
|
14
|
+
* of `getExpirationDate`). DCW's `undefined` convention wins for the string
|
|
15
|
+
* getters; Freewallet's `''`-returning wrapper is trivially reproduced app-side
|
|
16
|
+
* as `getExpirationDate(vc) ?? ''`.
|
|
17
|
+
*/
|
|
18
|
+
import type { IVerifiableCredential } from '@interop/data-integrity-core';
|
|
19
|
+
/**
|
|
20
|
+
* The issuance instant as a raw ISO string: VC 2.0 `validFrom` preferred, else
|
|
21
|
+
* VC 1.0 `issuanceDate`, else `undefined`.
|
|
22
|
+
*
|
|
23
|
+
* @param credential {IVerifiableCredential}
|
|
24
|
+
* @returns {string | undefined}
|
|
25
|
+
*/
|
|
26
|
+
export declare function getIssuanceDate(credential: IVerifiableCredential): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* The expiration instant as a raw ISO string: VC 2.0 `validUntil` preferred,
|
|
29
|
+
* else VC 1.0 `expirationDate`, else `undefined`.
|
|
30
|
+
*
|
|
31
|
+
* @param credential {IVerifiableCredential}
|
|
32
|
+
* @returns {string | undefined}
|
|
33
|
+
*/
|
|
34
|
+
export declare function getExpirationDate(credential: IVerifiableCredential): string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* The expiration instant as a `Date`, or `null` when there is no expiration or
|
|
37
|
+
* it does not parse.
|
|
38
|
+
*
|
|
39
|
+
* @param credential {IVerifiableCredential}
|
|
40
|
+
* @returns {Date | null}
|
|
41
|
+
*/
|
|
42
|
+
export declare function getExpirationInstant(credential: IVerifiableCredential): Date | null;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the credential has an expiration date that is already in the past.
|
|
45
|
+
* A credential with no expiration is never expired.
|
|
46
|
+
*
|
|
47
|
+
* @param credential {IVerifiableCredential}
|
|
48
|
+
* @returns {boolean}
|
|
49
|
+
*/
|
|
50
|
+
export declare function isExpired(credential: IVerifiableCredential): boolean;
|
|
51
|
+
//# sourceMappingURL=validity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validity.d.ts","sourceRoot":"","sources":["../../src/display/validity.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAEzE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,qBAAqB,GAChC,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,qBAAqB,GAChC,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,qBAAqB,GAChC,IAAI,GAAG,IAAI,CAOb;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,qBAAqB,GAAG,OAAO,CAOpE"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The issuance instant as a raw ISO string: VC 2.0 `validFrom` preferred, else
|
|
3
|
+
* VC 1.0 `issuanceDate`, else `undefined`.
|
|
4
|
+
*
|
|
5
|
+
* @param credential {IVerifiableCredential}
|
|
6
|
+
* @returns {string | undefined}
|
|
7
|
+
*/
|
|
8
|
+
export function getIssuanceDate(credential) {
|
|
9
|
+
return credential.validFrom ?? credential.issuanceDate;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The expiration instant as a raw ISO string: VC 2.0 `validUntil` preferred,
|
|
13
|
+
* else VC 1.0 `expirationDate`, else `undefined`.
|
|
14
|
+
*
|
|
15
|
+
* @param credential {IVerifiableCredential}
|
|
16
|
+
* @returns {string | undefined}
|
|
17
|
+
*/
|
|
18
|
+
export function getExpirationDate(credential) {
|
|
19
|
+
return credential.validUntil ?? credential.expirationDate;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The expiration instant as a `Date`, or `null` when there is no expiration or
|
|
23
|
+
* it does not parse.
|
|
24
|
+
*
|
|
25
|
+
* @param credential {IVerifiableCredential}
|
|
26
|
+
* @returns {Date | null}
|
|
27
|
+
*/
|
|
28
|
+
export function getExpirationInstant(credential) {
|
|
29
|
+
const iso = getExpirationDate(credential);
|
|
30
|
+
if (!iso) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const d = new Date(iso);
|
|
34
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether the credential has an expiration date that is already in the past.
|
|
38
|
+
* A credential with no expiration is never expired.
|
|
39
|
+
*
|
|
40
|
+
* @param credential {IVerifiableCredential}
|
|
41
|
+
* @returns {boolean}
|
|
42
|
+
*/
|
|
43
|
+
export function isExpired(credential) {
|
|
44
|
+
const expiration = getExpirationDate(credential);
|
|
45
|
+
if (!expiration) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const t = Date.parse(String(expiration));
|
|
49
|
+
return !Number.isNaN(t) && t < Date.now();
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=validity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validity.js","sourceRoot":"","sources":["../../src/display/validity.ts"],"names":[],"mappings":"AAmBA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAiC;IAEjC,OAAO,UAAU,CAAC,SAAS,IAAI,UAAU,CAAC,YAAY,CAAA;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAiC;IAEjC,OAAO,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,cAAc,CAAA;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,UAAiC;IAEjC,MAAM,GAAG,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAA;IACzC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAA;IACvB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,UAAiC;IACzD,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAChD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAA;IACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Verification-to-UI derivation: pure readers over a `verifyCredential` result
|
|
6
|
+
* `log[]`. No conflict existed between the apps -- they read different things
|
|
7
|
+
* from the same log -- so both are extracted:
|
|
8
|
+
*
|
|
9
|
+
* - `buildVerificationChecklist` (Freewallet) builds the five-step
|
|
10
|
+
* supportedFormat / signature / issuer / revocation / expiration checklist,
|
|
11
|
+
* each `{ valid, message, status }`, plus the `getVerificationAggregateStatus`
|
|
12
|
+
* / `isFullyVerified` / `isExpiredOnly` / `hasVerificationWarning` rollups.
|
|
13
|
+
* - `issuerRecognizedByVerification` (backs DCW's `shouldDisableUrls`) reports
|
|
14
|
+
* whether the `registered_issuer` entry confirms a registry match.
|
|
15
|
+
*
|
|
16
|
+
* i18n stays OUT of the library: instead of Freewallet's injected `TFunction`
|
|
17
|
+
* or DCW's hardcoded English, `buildVerificationChecklist` takes an injected
|
|
18
|
+
* `labels` map keyed by {@link ChecklistMsgKey}. Each app supplies its own
|
|
19
|
+
* strings (Freewallet from `t(...)`, DCW its English literals).
|
|
20
|
+
*/
|
|
21
|
+
import type { IVerifiableCredential } from '@interop/data-integrity-core';
|
|
22
|
+
/** Per-step severity. */
|
|
23
|
+
export type VerificationStepStatus = 'positive' | 'warning' | 'negative';
|
|
24
|
+
/** One checklist step. */
|
|
25
|
+
export interface VerificationStep {
|
|
26
|
+
valid: boolean;
|
|
27
|
+
message: string;
|
|
28
|
+
status: VerificationStepStatus;
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
/** The five-step checklist, with `expiry` / `status` legacy aliases. */
|
|
32
|
+
export interface VerificationChecklist {
|
|
33
|
+
supportedFormat: VerificationStep;
|
|
34
|
+
signature: VerificationStep;
|
|
35
|
+
issuer: VerificationStep;
|
|
36
|
+
revocation: VerificationStep;
|
|
37
|
+
expiration: VerificationStep;
|
|
38
|
+
/** @deprecated Use `expiration`. */
|
|
39
|
+
expiry: VerificationStep;
|
|
40
|
+
/** @deprecated Use `revocation`. */
|
|
41
|
+
status: VerificationStep;
|
|
42
|
+
}
|
|
43
|
+
/** Rolled-up verification outcome. */
|
|
44
|
+
export type VerificationAggregateStatus = 'verified' | 'warning' | 'not_verified';
|
|
45
|
+
/** The message keys `buildVerificationChecklist` looks up in the `labels` map. */
|
|
46
|
+
export type ChecklistMsgKey = 'supportedFormatOk' | 'supportedFormatFail' | 'signatureOk' | 'signatureFail' | 'issuerOk' | 'issuerFail' | 'revocationOk' | 'revocationFail' | 'expirationOk' | 'expirationFail' | 'noExpiration';
|
|
47
|
+
/**
|
|
48
|
+
* Builds the five-step verification checklist from a raw `verifyCredential`
|
|
49
|
+
* payload, the credential, and an injected `labels` map.
|
|
50
|
+
*
|
|
51
|
+
* @param raw {Record<string, unknown>} the raw verify result
|
|
52
|
+
* @param credential {IVerifiableCredential}
|
|
53
|
+
* @param labels {Record<ChecklistMsgKey, string>} localized message strings
|
|
54
|
+
* @returns {VerificationChecklist}
|
|
55
|
+
*/
|
|
56
|
+
export declare function buildVerificationChecklist(raw: Record<string, unknown>, credential: IVerifiableCredential, labels: Record<ChecklistMsgKey, string>): VerificationChecklist;
|
|
57
|
+
/**
|
|
58
|
+
* Rolls the checklist up to a single status. Hard failures (bad signature /
|
|
59
|
+
* format / revocation) yield `'not_verified'`; a soft issue (unknown issuer or
|
|
60
|
+
* expired) yields `'warning'`; otherwise `'verified'`.
|
|
61
|
+
*
|
|
62
|
+
* @param result {VerificationChecklist | null}
|
|
63
|
+
* @returns {VerificationAggregateStatus | null}
|
|
64
|
+
*/
|
|
65
|
+
export declare function getVerificationAggregateStatus(result: VerificationChecklist | null): VerificationAggregateStatus | null;
|
|
66
|
+
/**
|
|
67
|
+
* Whether every check passed.
|
|
68
|
+
*
|
|
69
|
+
* @param result {VerificationChecklist | null}
|
|
70
|
+
* @returns {boolean}
|
|
71
|
+
*/
|
|
72
|
+
export declare function isFullyVerified(result: VerificationChecklist | null): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Whether the only failing check is expiration (everything else passed).
|
|
75
|
+
*
|
|
76
|
+
* @param result {VerificationChecklist | null}
|
|
77
|
+
* @returns {boolean}
|
|
78
|
+
*/
|
|
79
|
+
export declare function isExpiredOnly(result: VerificationChecklist | null): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Whether the aggregate status is a warning.
|
|
82
|
+
*
|
|
83
|
+
* @param result {VerificationChecklist | null}
|
|
84
|
+
* @returns {boolean}
|
|
85
|
+
*/
|
|
86
|
+
export declare function hasVerificationWarning(result: VerificationChecklist | null): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Whether verification confirms a registered issuer: the `registered_issuer`
|
|
89
|
+
* log entry is valid and (when present) its `matchingIssuers` is non-empty.
|
|
90
|
+
* Backs DCW's `shouldDisableUrls` (a one-line app wrapper:
|
|
91
|
+
* `!issuerRecognizedByVerification(log)`).
|
|
92
|
+
*
|
|
93
|
+
* @param log {Array<{ id: string; valid?: boolean; matchingIssuers?: unknown[] }> | undefined}
|
|
94
|
+
* @returns {boolean}
|
|
95
|
+
*/
|
|
96
|
+
export declare function issuerRecognizedByVerification(log?: Array<{
|
|
97
|
+
id: string;
|
|
98
|
+
valid?: boolean;
|
|
99
|
+
matchingIssuers?: unknown[];
|
|
100
|
+
}>): boolean;
|
|
101
|
+
//# sourceMappingURL=verificationView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verificationView.d.ts","sourceRoot":"","sources":["../../src/display/verificationView.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAIzE,yBAAyB;AACzB,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;AAExE,0BAA0B;AAC1B,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,sBAAsB,CAAA;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,wEAAwE;AACxE,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,gBAAgB,CAAA;IACjC,SAAS,EAAE,gBAAgB,CAAA;IAC3B,MAAM,EAAE,gBAAgB,CAAA;IACxB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,UAAU,EAAE,gBAAgB,CAAA;IAC5B,oCAAoC;IACpC,MAAM,EAAE,gBAAgB,CAAA;IACxB,oCAAoC;IACpC,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,sCAAsC;AACtC,MAAM,MAAM,2BAA2B,GACrC,UAAU,GAAG,SAAS,GAAG,cAAc,CAAA;AAEzC,kFAAkF;AAClF,MAAM,MAAM,eAAe,GACvB,mBAAmB,GACnB,qBAAqB,GACrB,aAAa,GACb,eAAe,GACf,UAAU,GACV,YAAY,GACZ,cAAc,GACd,gBAAgB,GAChB,cAAc,GACd,gBAAgB,GAChB,cAAc,CAAA;AAiKlB;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,UAAU,EAAE,qBAAqB,EACjC,MAAM,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,GACtC,qBAAqB,CA8BvB;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,qBAAqB,GAAG,IAAI,GACnC,2BAA2B,GAAG,IAAI,CAmBpC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAE7E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAW3E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,qBAAqB,GAAG,IAAI,GACnC,OAAO,CAET;AAED;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC5C,GAAG,CAAC,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,GACxE,OAAO,CAcT"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { getExpirationInstant } from './validity.js';
|
|
2
|
+
import { typeArray } from '@interop/data-integrity-core/guards';
|
|
3
|
+
const STEP_ID = {
|
|
4
|
+
validSignature: 'valid_signature',
|
|
5
|
+
expiration: 'expiration',
|
|
6
|
+
revocation: 'revocation_status',
|
|
7
|
+
registeredIssuer: 'registered_issuer'
|
|
8
|
+
};
|
|
9
|
+
const SUPPORTED_CREDENTIAL_TYPES = [
|
|
10
|
+
'VerifiableCredential',
|
|
11
|
+
'OpenBadgeCredential'
|
|
12
|
+
];
|
|
13
|
+
function getVerifyLogFromPayload(raw) {
|
|
14
|
+
const results = raw.results;
|
|
15
|
+
const logFromFirstResult = results?.[0]?.log;
|
|
16
|
+
if (Array.isArray(logFromFirstResult)) {
|
|
17
|
+
return logFromFirstResult;
|
|
18
|
+
}
|
|
19
|
+
const topLevelLog = raw.log;
|
|
20
|
+
if (Array.isArray(topLevelLog)) {
|
|
21
|
+
return topLevelLog;
|
|
22
|
+
}
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
function step(valid, message, severity, error) {
|
|
26
|
+
return {
|
|
27
|
+
valid,
|
|
28
|
+
message,
|
|
29
|
+
status: severity,
|
|
30
|
+
...(error ? { error } : {})
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function logValid(entry) {
|
|
34
|
+
if (!entry) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
return entry.valid === true && !entry.error;
|
|
38
|
+
}
|
|
39
|
+
function supportedFormatStep(credential, labels) {
|
|
40
|
+
const hasKnownType = typeArray(credential.type).some(type => SUPPORTED_CREDENTIAL_TYPES.includes(type));
|
|
41
|
+
return step(hasKnownType, hasKnownType ? labels.supportedFormatOk : labels.supportedFormatFail, hasKnownType ? 'positive' : 'negative');
|
|
42
|
+
}
|
|
43
|
+
function signatureStep(entry, labels) {
|
|
44
|
+
const valid = logValid(entry) ?? false;
|
|
45
|
+
return step(valid, valid ? labels.signatureOk : labels.signatureFail, valid ? 'positive' : 'negative', entry?.error?.message);
|
|
46
|
+
}
|
|
47
|
+
function issuerStep(entry, labels) {
|
|
48
|
+
const valid = logValid(entry) ?? false;
|
|
49
|
+
return step(valid, valid ? labels.issuerOk : labels.issuerFail, valid ? 'positive' : 'warning', entry?.error?.message);
|
|
50
|
+
}
|
|
51
|
+
function revocationStep(entry, credential, labels) {
|
|
52
|
+
if (!credential.credentialStatus && !entry) {
|
|
53
|
+
return step(true, labels.revocationOk, 'positive');
|
|
54
|
+
}
|
|
55
|
+
const valid = logValid(entry) ?? true;
|
|
56
|
+
return step(valid, valid ? labels.revocationOk : labels.revocationFail, valid ? 'positive' : 'negative', entry?.error?.message);
|
|
57
|
+
}
|
|
58
|
+
function expirationStep(entry, credential, labels) {
|
|
59
|
+
const exp = getExpirationInstant(credential);
|
|
60
|
+
const hasExpirationDate = exp != null;
|
|
61
|
+
if (!hasExpirationDate && !entry) {
|
|
62
|
+
return step(true, labels.noExpiration, 'positive');
|
|
63
|
+
}
|
|
64
|
+
if (entry) {
|
|
65
|
+
const valid = logValid(entry) ?? false;
|
|
66
|
+
return step(valid, valid ? labels.expirationOk : labels.expirationFail, valid ? 'positive' : 'warning', entry.error?.message);
|
|
67
|
+
}
|
|
68
|
+
const expired = exp.getTime() < Date.now();
|
|
69
|
+
return step(!expired, expired ? labels.expirationFail : labels.expirationOk, expired ? 'warning' : 'positive');
|
|
70
|
+
}
|
|
71
|
+
function withGlobalErr(stepValue, globalErr) {
|
|
72
|
+
if (stepValue.valid || !globalErr) {
|
|
73
|
+
return stepValue;
|
|
74
|
+
}
|
|
75
|
+
return { ...stepValue, error: stepValue.error ?? globalErr };
|
|
76
|
+
}
|
|
77
|
+
function attachLegacyAliases(checklist) {
|
|
78
|
+
return {
|
|
79
|
+
...checklist,
|
|
80
|
+
expiry: checklist.expiration,
|
|
81
|
+
status: checklist.revocation
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Builds the five-step verification checklist from a raw `verifyCredential`
|
|
86
|
+
* payload, the credential, and an injected `labels` map.
|
|
87
|
+
*
|
|
88
|
+
* @param raw {Record<string, unknown>} the raw verify result
|
|
89
|
+
* @param credential {IVerifiableCredential}
|
|
90
|
+
* @param labels {Record<ChecklistMsgKey, string>} localized message strings
|
|
91
|
+
* @returns {VerificationChecklist}
|
|
92
|
+
*/
|
|
93
|
+
export function buildVerificationChecklist(raw, credential, labels) {
|
|
94
|
+
const log = getVerifyLogFromPayload(raw);
|
|
95
|
+
const byId = (id) => log.find(line => line.id === id);
|
|
96
|
+
const resultsWithError = raw.results;
|
|
97
|
+
const globalErr = typeof resultsWithError?.[0]?.error?.message === 'string'
|
|
98
|
+
? resultsWithError[0].error.message
|
|
99
|
+
: undefined;
|
|
100
|
+
const checklist = {
|
|
101
|
+
supportedFormat: supportedFormatStep(credential, labels),
|
|
102
|
+
signature: signatureStep(byId(STEP_ID.validSignature), labels),
|
|
103
|
+
issuer: issuerStep(byId(STEP_ID.registeredIssuer), labels),
|
|
104
|
+
revocation: revocationStep(byId(STEP_ID.revocation), credential, labels),
|
|
105
|
+
expiration: expirationStep(byId(STEP_ID.expiration), credential, labels)
|
|
106
|
+
};
|
|
107
|
+
if (!globalErr) {
|
|
108
|
+
return attachLegacyAliases(checklist);
|
|
109
|
+
}
|
|
110
|
+
return attachLegacyAliases({
|
|
111
|
+
supportedFormat: withGlobalErr(checklist.supportedFormat, globalErr),
|
|
112
|
+
signature: withGlobalErr(checklist.signature, globalErr),
|
|
113
|
+
issuer: withGlobalErr(checklist.issuer, globalErr),
|
|
114
|
+
revocation: withGlobalErr(checklist.revocation, globalErr),
|
|
115
|
+
expiration: withGlobalErr(checklist.expiration, globalErr)
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Rolls the checklist up to a single status. Hard failures (bad signature /
|
|
120
|
+
* format / revocation) yield `'not_verified'`; a soft issue (unknown issuer or
|
|
121
|
+
* expired) yields `'warning'`; otherwise `'verified'`.
|
|
122
|
+
*
|
|
123
|
+
* @param result {VerificationChecklist | null}
|
|
124
|
+
* @returns {VerificationAggregateStatus | null}
|
|
125
|
+
*/
|
|
126
|
+
export function getVerificationAggregateStatus(result) {
|
|
127
|
+
if (!result) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
const hasFailure = !result.signature.valid ||
|
|
131
|
+
!result.supportedFormat.valid ||
|
|
132
|
+
!result.revocation.valid;
|
|
133
|
+
const hasWarning = !result.issuer.valid || !result.expiration.valid;
|
|
134
|
+
if (hasFailure) {
|
|
135
|
+
return 'not_verified';
|
|
136
|
+
}
|
|
137
|
+
if (hasWarning) {
|
|
138
|
+
return 'warning';
|
|
139
|
+
}
|
|
140
|
+
return 'verified';
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Whether every check passed.
|
|
144
|
+
*
|
|
145
|
+
* @param result {VerificationChecklist | null}
|
|
146
|
+
* @returns {boolean}
|
|
147
|
+
*/
|
|
148
|
+
export function isFullyVerified(result) {
|
|
149
|
+
return getVerificationAggregateStatus(result) === 'verified';
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Whether the only failing check is expiration (everything else passed).
|
|
153
|
+
*
|
|
154
|
+
* @param result {VerificationChecklist | null}
|
|
155
|
+
* @returns {boolean}
|
|
156
|
+
*/
|
|
157
|
+
export function isExpiredOnly(result) {
|
|
158
|
+
if (!result) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
return (result.signature.valid &&
|
|
162
|
+
result.supportedFormat.valid &&
|
|
163
|
+
result.issuer.valid &&
|
|
164
|
+
result.revocation.valid &&
|
|
165
|
+
!result.expiration.valid);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Whether the aggregate status is a warning.
|
|
169
|
+
*
|
|
170
|
+
* @param result {VerificationChecklist | null}
|
|
171
|
+
* @returns {boolean}
|
|
172
|
+
*/
|
|
173
|
+
export function hasVerificationWarning(result) {
|
|
174
|
+
return getVerificationAggregateStatus(result) === 'warning';
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Whether verification confirms a registered issuer: the `registered_issuer`
|
|
178
|
+
* log entry is valid and (when present) its `matchingIssuers` is non-empty.
|
|
179
|
+
* Backs DCW's `shouldDisableUrls` (a one-line app wrapper:
|
|
180
|
+
* `!issuerRecognizedByVerification(log)`).
|
|
181
|
+
*
|
|
182
|
+
* @param log {Array<{ id: string; valid?: boolean; matchingIssuers?: unknown[] }> | undefined}
|
|
183
|
+
* @returns {boolean}
|
|
184
|
+
*/
|
|
185
|
+
export function issuerRecognizedByVerification(log) {
|
|
186
|
+
if (!Array.isArray(log)) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
return log.some(entry => {
|
|
190
|
+
if (entry.id !== 'registered_issuer') {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
const { matchingIssuers } = entry;
|
|
194
|
+
return entry.valid && Array.isArray(matchingIssuers)
|
|
195
|
+
? matchingIssuers.length > 0
|
|
196
|
+
: Boolean(entry.valid);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=verificationView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verificationView.js","sourceRoot":"","sources":["../../src/display/verificationView.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* WAS identity derivation: controller secret / seed to the agent set a wallet
|
|
6
|
+
* profile operates with. Both wallet apps must derive byte-for-byte
|
|
7
|
+
* identically, so that supplying the same controller secret on any device
|
|
8
|
+
* joins the same WAS account/Space.
|
|
9
|
+
*
|
|
10
|
+
* The derivation: secret or 32-byte seed enters `CapabilityAgent` under the
|
|
11
|
+
* fixed `'bootstrap'` / `'boostrap-key'` names (the typo is load-bearing --
|
|
12
|
+
* every account's data identity derives through these exact strings, so they
|
|
13
|
+
* can never change without stranding existing wallets). The resulting Ed25519
|
|
14
|
+
* signing key backs a did:key DID, a `ZcapClient` for signing storage
|
|
15
|
+
* requests, and -- via did:key's encryption-key derivation (the Montgomery
|
|
16
|
+
* form of the signing key) -- the X25519 key agreement key (KAK) the EDV
|
|
17
|
+
* DocCipher encrypts and decrypts with. Everything is deterministic: a
|
|
18
|
+
* returning user, on any device, decrypts the same envelopes.
|
|
19
|
+
*/
|
|
20
|
+
import { CapabilityAgent } from '@interop/webkms-client';
|
|
21
|
+
import { ZcapClient } from '@interop/ezcap';
|
|
22
|
+
import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
|
|
23
|
+
/**
|
|
24
|
+
* The load-bearing `CapabilityAgent` derivation names (see the module doc:
|
|
25
|
+
* the typo in the key name can never be fixed without stranding wallets).
|
|
26
|
+
*/
|
|
27
|
+
export declare const BOOTSTRAP_HANDLE = "bootstrap";
|
|
28
|
+
export declare const BOOTSTRAP_KEY_NAME = "boostrap-key";
|
|
29
|
+
/**
|
|
30
|
+
* The agents derived from a controller secret or seed: the signing
|
|
31
|
+
* CapabilityAgent / did:key, a ZcapClient for signing storage requests, and
|
|
32
|
+
* the X25519 key agreement key (KAK) + resolver used by the EDV DocCipher.
|
|
33
|
+
*/
|
|
34
|
+
export interface ProfileAgents {
|
|
35
|
+
controllerDid: string;
|
|
36
|
+
keyAgent: CapabilityAgent;
|
|
37
|
+
zcapClient: ZcapClient;
|
|
38
|
+
keyAgreementKey: IKeyAgreementKey;
|
|
39
|
+
keyResolver: IKeyResolver;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Derives the WAS agents from an already-derived 32-byte seed, skipping the
|
|
43
|
+
* salted-hash step (`CapabilityAgent.fromSeed` semantics: a stored seed
|
|
44
|
+
* stands in for the original secret).
|
|
45
|
+
*
|
|
46
|
+
* @param options {object}
|
|
47
|
+
* @param options.seed {Uint8Array} the 32-byte seed
|
|
48
|
+
* @returns {Promise<ProfileAgents>}
|
|
49
|
+
*/
|
|
50
|
+
export declare function agentsFromSeed({ seed }: {
|
|
51
|
+
seed: Uint8Array;
|
|
52
|
+
}): Promise<ProfileAgents>;
|
|
53
|
+
/**
|
|
54
|
+
* Derives the WAS agents from a controller secret. **The secret is ALWAYS a
|
|
55
|
+
* string** (a passphrase, or the base64url TEXT of 32 random bytes -- never
|
|
56
|
+
* the decoded bytes): `CapabilityAgent.fromSecret`'s salted hash is
|
|
57
|
+
* type-sensitive, so a string and its UTF-8 bytes derive different keys.
|
|
58
|
+
* Passing a string keeps every secret typeable/scannable into a login form
|
|
59
|
+
* (the cross-wallet linking flow).
|
|
60
|
+
*
|
|
61
|
+
* @param options {object}
|
|
62
|
+
* @param options.secret {string} the controller secret (see above)
|
|
63
|
+
* @returns {Promise<ProfileAgents>}
|
|
64
|
+
*/
|
|
65
|
+
export declare function agentsFromSecret({ secret }: {
|
|
66
|
+
secret: string;
|
|
67
|
+
}): Promise<ProfileAgents>;
|
|
68
|
+
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/identity/agents.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,8BAA8B,CAAA;AAGrC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,cAAc,CAAA;AAC3C,eAAO,MAAM,kBAAkB,iBAAiB,CAAA;AAEhD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,eAAe,CAAA;IACzB,UAAU,EAAE,UAAU,CAAA;IACtB,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,EACnC,IAAI,EACL,EAAE;IACD,IAAI,EAAE,UAAU,CAAA;CACjB,GAAG,OAAO,CAAC,aAAa,CAAC,CAOzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,MAAM,EACP,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,aAAa,CAAC,CAOzB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* WAS identity derivation: controller secret / seed to the agent set a wallet
|
|
6
|
+
* profile operates with. Both wallet apps must derive byte-for-byte
|
|
7
|
+
* identically, so that supplying the same controller secret on any device
|
|
8
|
+
* joins the same WAS account/Space.
|
|
9
|
+
*
|
|
10
|
+
* The derivation: secret or 32-byte seed enters `CapabilityAgent` under the
|
|
11
|
+
* fixed `'bootstrap'` / `'boostrap-key'` names (the typo is load-bearing --
|
|
12
|
+
* every account's data identity derives through these exact strings, so they
|
|
13
|
+
* can never change without stranding existing wallets). The resulting Ed25519
|
|
14
|
+
* signing key backs a did:key DID, a `ZcapClient` for signing storage
|
|
15
|
+
* requests, and -- via did:key's encryption-key derivation (the Montgomery
|
|
16
|
+
* form of the signing key) -- the X25519 key agreement key (KAK) the EDV
|
|
17
|
+
* DocCipher encrypts and decrypts with. Everything is deterministic: a
|
|
18
|
+
* returning user, on any device, decrypts the same envelopes.
|
|
19
|
+
*/
|
|
20
|
+
import { CapabilityAgent } from '@interop/webkms-client';
|
|
21
|
+
import { Ed25519Signature2020 } from '@interop/ed25519-signature';
|
|
22
|
+
import { ZcapClient } from '@interop/ezcap';
|
|
23
|
+
import { X25519KeyAgreementKey2020 } from '@interop/x25519-key-agreement-key';
|
|
24
|
+
import { singleKeyResolver } from './keyResolver.js';
|
|
25
|
+
/**
|
|
26
|
+
* The load-bearing `CapabilityAgent` derivation names (see the module doc:
|
|
27
|
+
* the typo in the key name can never be fixed without stranding wallets).
|
|
28
|
+
*/
|
|
29
|
+
export const BOOTSTRAP_HANDLE = 'bootstrap';
|
|
30
|
+
export const BOOTSTRAP_KEY_NAME = 'boostrap-key';
|
|
31
|
+
/**
|
|
32
|
+
* Derives the WAS agents from an already-derived 32-byte seed, skipping the
|
|
33
|
+
* salted-hash step (`CapabilityAgent.fromSeed` semantics: a stored seed
|
|
34
|
+
* stands in for the original secret).
|
|
35
|
+
*
|
|
36
|
+
* @param options {object}
|
|
37
|
+
* @param options.seed {Uint8Array} the 32-byte seed
|
|
38
|
+
* @returns {Promise<ProfileAgents>}
|
|
39
|
+
*/
|
|
40
|
+
export async function agentsFromSeed({ seed }) {
|
|
41
|
+
const keyAgent = await CapabilityAgent.fromSeed({
|
|
42
|
+
seed,
|
|
43
|
+
handle: BOOTSTRAP_HANDLE,
|
|
44
|
+
keyName: BOOTSTRAP_KEY_NAME
|
|
45
|
+
});
|
|
46
|
+
return agentsFromKeyAgent({ keyAgent });
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Derives the WAS agents from a controller secret. **The secret is ALWAYS a
|
|
50
|
+
* string** (a passphrase, or the base64url TEXT of 32 random bytes -- never
|
|
51
|
+
* the decoded bytes): `CapabilityAgent.fromSecret`'s salted hash is
|
|
52
|
+
* type-sensitive, so a string and its UTF-8 bytes derive different keys.
|
|
53
|
+
* Passing a string keeps every secret typeable/scannable into a login form
|
|
54
|
+
* (the cross-wallet linking flow).
|
|
55
|
+
*
|
|
56
|
+
* @param options {object}
|
|
57
|
+
* @param options.secret {string} the controller secret (see above)
|
|
58
|
+
* @returns {Promise<ProfileAgents>}
|
|
59
|
+
*/
|
|
60
|
+
export async function agentsFromSecret({ secret }) {
|
|
61
|
+
const keyAgent = await CapabilityAgent.fromSecret({
|
|
62
|
+
secret,
|
|
63
|
+
handle: BOOTSTRAP_HANDLE,
|
|
64
|
+
keyName: BOOTSTRAP_KEY_NAME
|
|
65
|
+
});
|
|
66
|
+
return agentsFromKeyAgent({ keyAgent });
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The shared tail of both derivations: ZcapClient + KAK + resolver from the
|
|
70
|
+
* bootstrap CapabilityAgent.
|
|
71
|
+
*/
|
|
72
|
+
function agentsFromKeyAgent({ keyAgent }) {
|
|
73
|
+
const signer = keyAgent.getSigner();
|
|
74
|
+
const zcapClient = new ZcapClient({
|
|
75
|
+
SuiteClass: Ed25519Signature2020,
|
|
76
|
+
invocationSigner: signer,
|
|
77
|
+
// The root key also signs delegations (sharing grants, app capability
|
|
78
|
+
// grants).
|
|
79
|
+
delegationSigner: signer
|
|
80
|
+
});
|
|
81
|
+
const keyAgreementKey = X25519KeyAgreementKey2020.fromEd25519VerificationKey2020({
|
|
82
|
+
keyPair: keyAgent.getVerificationKeyPair()
|
|
83
|
+
});
|
|
84
|
+
const keyResolver = singleKeyResolver({ keyAgreementKey });
|
|
85
|
+
return {
|
|
86
|
+
controllerDid: keyAgent.id,
|
|
87
|
+
keyAgent,
|
|
88
|
+
zcapClient,
|
|
89
|
+
// `id` is always set on the KAK here (a controller was supplied at
|
|
90
|
+
// derivation), so it satisfies IKeyAgreementKey's required `id`.
|
|
91
|
+
keyAgreementKey: keyAgreementKey,
|
|
92
|
+
keyResolver
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/identity/agents.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAK7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEpD;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAA;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAAA;AAehD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EACnC,IAAI,EAGL;IACC,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC;QAC9C,IAAI;QACJ,MAAM,EAAE,gBAAgB;QACxB,OAAO,EAAE,kBAAkB;KAC5B,CAAC,CAAA;IACF,OAAO,kBAAkB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;AACzC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,MAAM,EAGP;IACC,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC;QAChD,MAAM;QACN,MAAM,EAAE,gBAAgB;QACxB,OAAO,EAAE,kBAAkB;KAC5B,CAAC,CAAA;IACF,OAAO,kBAAkB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;AACzC,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAAC,EAC1B,QAAQ,EAGT;IACC,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAA;IACnC,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC;QAChC,UAAU,EAAE,oBAAoB;QAChC,gBAAgB,EAAE,MAAM;QACxB,sEAAsE;QACtE,WAAW;QACX,gBAAgB,EAAE,MAAM;KACzB,CAAC,CAAA;IAEF,MAAM,eAAe,GACnB,yBAAyB,CAAC,8BAA8B,CAAC;QACvD,OAAO,EAAE,QAAQ,CAAC,sBAAsB,EAAE;KAC3C,CAAC,CAAA;IACJ,MAAM,WAAW,GAAG,iBAAiB,CAAC,EAAE,eAAe,EAAE,CAAC,CAAA;IAE1D,OAAO;QACL,aAAa,EAAE,QAAQ,CAAC,EAAE;QAC1B,QAAQ;QACR,UAAU;QACV,mEAAmE;QACnE,iEAAiE;QACjE,eAAe,EAAE,eAAmC;QACpD,WAAW;KACZ,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The `@interop/wallet-core/identity` subpath: the WAS identity derivation
|
|
6
|
+
* both wallet apps must perform byte-for-byte identically.
|
|
7
|
+
*
|
|
8
|
+
* - `agentsFromSecret` / `agentsFromSeed` -- controller secret or 32-byte seed
|
|
9
|
+
* to `ProfileAgents` (did:key CapabilityAgent, ZcapClient, X25519 KAK,
|
|
10
|
+
* single-key resolver) under the fixed bootstrap handle / key name.
|
|
11
|
+
* - `singleKeyResolver` -- the one-key `IKeyResolver` factory (also used by
|
|
12
|
+
* app-side derivations such as a keyring unlock identity).
|
|
13
|
+
*
|
|
14
|
+
* Kept out of the root export: this subpath pulls the webkms-client / ezcap /
|
|
15
|
+
* x25519 dependency graph (the same isolation pattern as `./request`).
|
|
16
|
+
*/
|
|
17
|
+
export { BOOTSTRAP_HANDLE, BOOTSTRAP_KEY_NAME, agentsFromSecret, agentsFromSeed } from './agents.js';
|
|
18
|
+
export type { ProfileAgents } from './agents.js';
|
|
19
|
+
export { singleKeyResolver } from './keyResolver.js';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACf,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The `@interop/wallet-core/identity` subpath: the WAS identity derivation
|
|
6
|
+
* both wallet apps must perform byte-for-byte identically.
|
|
7
|
+
*
|
|
8
|
+
* - `agentsFromSecret` / `agentsFromSeed` -- controller secret or 32-byte seed
|
|
9
|
+
* to `ProfileAgents` (did:key CapabilityAgent, ZcapClient, X25519 KAK,
|
|
10
|
+
* single-key resolver) under the fixed bootstrap handle / key name.
|
|
11
|
+
* - `singleKeyResolver` -- the one-key `IKeyResolver` factory (also used by
|
|
12
|
+
* app-side derivations such as a keyring unlock identity).
|
|
13
|
+
*
|
|
14
|
+
* Kept out of the root export: this subpath pulls the webkms-client / ezcap /
|
|
15
|
+
* x25519 dependency graph (the same isolation pattern as `./request`).
|
|
16
|
+
*/
|
|
17
|
+
export { BOOTSTRAP_HANDLE, BOOTSTRAP_KEY_NAME, agentsFromSecret, agentsFromSeed } from './agents.js';
|
|
18
|
+
export { singleKeyResolver } from './keyResolver.js';
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA"}
|