@interop/wallet-core 0.23.0 → 0.24.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 +33 -18
- package/dist/clients/revocation.d.ts +3 -6
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/revocation.js +5 -9
- package/dist/clients/revocation.js.map +1 -1
- package/dist/clients/rosterPolicy.d.ts +11 -17
- package/dist/clients/rosterPolicy.d.ts.map +1 -1
- package/dist/clients/rosterPolicy.js +22 -27
- package/dist/clients/rosterPolicy.js.map +1 -1
- package/dist/enrollment/enrollment.d.ts +2 -2
- package/dist/enrollment/enrollment.d.ts.map +1 -1
- package/dist/enrollment/enrollment.js +15 -10
- package/dist/enrollment/enrollment.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/keys/index.d.ts +11 -8
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +11 -8
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/rosterLogStore.d.ts +34 -0
- package/dist/keys/rosterLogStore.d.ts.map +1 -0
- package/dist/keys/rosterLogStore.js +110 -0
- package/dist/keys/rosterLogStore.js.map +1 -0
- package/dist/keys/rosterStore.d.ts +18 -4
- package/dist/keys/rosterStore.d.ts.map +1 -1
- package/dist/keys/rosterStore.js +35 -16
- package/dist/keys/rosterStore.js.map +1 -1
- package/dist/keys/userKeyCascade.d.ts +1 -1
- package/dist/keys/userKeyCascade.js +1 -1
- package/dist/keys/userKeyRoster.d.ts +50 -97
- package/dist/keys/userKeyRoster.d.ts.map +1 -1
- package/dist/keys/userKeyRoster.js +44 -145
- package/dist/keys/userKeyRoster.js.map +1 -1
- package/dist/request/appKey.d.ts +254 -0
- package/dist/request/appKey.d.ts.map +1 -0
- package/dist/request/appKey.js +498 -0
- package/dist/request/appKey.js.map +1 -0
- package/dist/request/classify.d.ts +54 -3
- package/dist/request/classify.d.ts.map +1 -1
- package/dist/request/classify.js +106 -0
- package/dist/request/classify.js.map +1 -1
- package/dist/request/index.d.ts +4 -0
- package/dist/request/index.d.ts.map +1 -1
- package/dist/request/index.js +4 -0
- package/dist/request/index.js.map +1 -1
- package/dist/request/processRequest.d.ts.map +1 -1
- package/dist/request/processRequest.js +15 -6
- package/dist/request/processRequest.js.map +1 -1
- package/dist/request/types.d.ts +45 -2
- package/dist/request/types.d.ts.map +1 -1
- package/dist/resourceLog/append.d.ts +103 -0
- package/dist/resourceLog/append.d.ts.map +1 -0
- package/dist/resourceLog/append.js +190 -0
- package/dist/resourceLog/append.js.map +1 -0
- package/dist/resourceLog/controller.d.ts +57 -0
- package/dist/resourceLog/controller.d.ts.map +1 -0
- package/dist/resourceLog/controller.js +81 -0
- package/dist/resourceLog/controller.js.map +1 -0
- package/dist/resourceLog/entry.d.ts +68 -0
- package/dist/resourceLog/entry.d.ts.map +1 -0
- package/dist/resourceLog/entry.js +167 -0
- package/dist/resourceLog/entry.js.map +1 -0
- package/dist/resourceLog/errors.d.ts +75 -0
- package/dist/resourceLog/errors.d.ts.map +1 -0
- package/dist/resourceLog/errors.js +76 -0
- package/dist/resourceLog/errors.js.map +1 -0
- package/dist/resourceLog/index.d.ts +23 -0
- package/dist/resourceLog/index.d.ts.map +1 -0
- package/dist/resourceLog/index.js +23 -0
- package/dist/resourceLog/index.js.map +1 -0
- package/dist/resourceLog/pin.d.ts +44 -0
- package/dist/resourceLog/pin.d.ts.map +1 -0
- package/dist/resourceLog/pin.js +32 -0
- package/dist/resourceLog/pin.js.map +1 -0
- package/dist/resourceLog/verify.d.ts +89 -0
- package/dist/resourceLog/verify.d.ts.map +1 -0
- package/dist/resourceLog/verify.js +434 -0
- package/dist/resourceLog/verify.js.map +1 -0
- package/dist/space/collections.d.ts +14 -11
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +14 -11
- package/dist/space/collections.js.map +1 -1
- package/dist/space/index.d.ts +2 -2
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +2 -2
- package/dist/space/index.js.map +1 -1
- package/dist/webvh/didWeb.d.ts +4 -6
- package/dist/webvh/didWeb.d.ts.map +1 -1
- package/dist/webvh/didWeb.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +1 -2
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +1 -6
- package/dist/webvh/didWebvh.js.map +1 -1
- package/package.json +10 -4
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The controller-document view a resource-log verifier authorizes against:
|
|
6
|
+
* the profile's root of authority, resolved and verified by the reader
|
|
7
|
+
* independently of the host serving the log. The interface is the seam --
|
|
8
|
+
* verification consumes only the account DID, the ordered controller-log
|
|
9
|
+
* version list, and per-version `assertionMethod` membership -- and the
|
|
10
|
+
* did:webvh adapter builds it from an already-verified account log (the
|
|
11
|
+
* `verifyAccountLog` output), answering anchored-version lookups from that
|
|
12
|
+
* verified history rather than from any wire fetch. Handing the verifier a
|
|
13
|
+
* view instead of a resolver is what enforces the profile's rule that
|
|
14
|
+
* controller-document material never comes from the channel the log came
|
|
15
|
+
* from.
|
|
16
|
+
*/
|
|
17
|
+
import { type DIDLog } from '@interop/did-method-webvh';
|
|
18
|
+
/**
|
|
19
|
+
* What log verification consumes of the independently verified controller
|
|
20
|
+
* document: the DID the entry proofs must sign under, the verified controller
|
|
21
|
+
* log's `versionId` list in order (empty for an unversioned static
|
|
22
|
+
* controller, degrading every anchor rule to current-document verification),
|
|
23
|
+
* and the set of `assertionMethod` key multibases at a given version --
|
|
24
|
+
* membership there is the whole authorization rule, so `keyAgreement`-only
|
|
25
|
+
* recovery keys and `authentication`-only convenience keys are excluded
|
|
26
|
+
* structurally.
|
|
27
|
+
*/
|
|
28
|
+
export interface ResourceLogController {
|
|
29
|
+
did: string;
|
|
30
|
+
versionIds: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the `assertionMethod` public-key multibases at a controller-log
|
|
33
|
+
* version (`undefined`: the current document, the unversioned-controller
|
|
34
|
+
* degradation).
|
|
35
|
+
*
|
|
36
|
+
* @param [versionId] {string}
|
|
37
|
+
* @returns {Promise<Set<string>>}
|
|
38
|
+
*/
|
|
39
|
+
assertionKeysAt(versionId?: string): Promise<Set<string>>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Builds the controller view over an already-verified did:webvh account log
|
|
43
|
+
* (the `verifyAccountLog` output -- callers never hand this a log they have
|
|
44
|
+
* not verified against the account pointer). Anchored-version lookups
|
|
45
|
+
* re-resolve the held log at that version and are memoized: controller logs
|
|
46
|
+
* are tens of entries and anchors cluster on few versions.
|
|
47
|
+
*
|
|
48
|
+
* @param options {object}
|
|
49
|
+
* @param options.did {string} the account's did:webvh, as verified
|
|
50
|
+
* @param options.log {DIDLog} the verified account log
|
|
51
|
+
* @returns {ResourceLogController}
|
|
52
|
+
*/
|
|
53
|
+
export declare function webvhResourceLogController({ did, log }: {
|
|
54
|
+
did: string;
|
|
55
|
+
log: DIDLog;
|
|
56
|
+
}): ResourceLogController;
|
|
57
|
+
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/resourceLog/controller.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,EAAqB,KAAK,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAG1E;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB;;;;;;;OAOG;IACH,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;CAC1D;AAmCD;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,GAAG,EACH,GAAG,EACJ,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,qBAAqB,CAkCxB"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The controller-document view a resource-log verifier authorizes against:
|
|
6
|
+
* the profile's root of authority, resolved and verified by the reader
|
|
7
|
+
* independently of the host serving the log. The interface is the seam --
|
|
8
|
+
* verification consumes only the account DID, the ordered controller-log
|
|
9
|
+
* version list, and per-version `assertionMethod` membership -- and the
|
|
10
|
+
* did:webvh adapter builds it from an already-verified account log (the
|
|
11
|
+
* `verifyAccountLog` output), answering anchored-version lookups from that
|
|
12
|
+
* verified history rather than from any wire fetch. Handing the verifier a
|
|
13
|
+
* view instead of a resolver is what enforces the profile's rule that
|
|
14
|
+
* controller-document material never comes from the channel the log came
|
|
15
|
+
* from.
|
|
16
|
+
*/
|
|
17
|
+
import { resolveDIDFromLog } from '@interop/did-method-webvh';
|
|
18
|
+
import { ResourceLogIntegrityError } from './errors.js';
|
|
19
|
+
/**
|
|
20
|
+
* Collects a document's `assertionMethod` key multibases: embedded
|
|
21
|
+
* verification methods verbatim, string references resolved against
|
|
22
|
+
* `verificationMethod`.
|
|
23
|
+
*
|
|
24
|
+
* @param doc {AssertionDocument}
|
|
25
|
+
* @returns {Set<string>}
|
|
26
|
+
*/
|
|
27
|
+
function assertionKeysOf(doc) {
|
|
28
|
+
const byId = new Map();
|
|
29
|
+
for (const method of doc.verificationMethod ?? []) {
|
|
30
|
+
if (typeof method?.id === 'string') {
|
|
31
|
+
byId.set(method.id, method);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const keys = new Set();
|
|
35
|
+
for (const entry of doc.assertionMethod ?? []) {
|
|
36
|
+
const method = typeof entry === 'string' ? byId.get(entry) : entry;
|
|
37
|
+
if (method && typeof method.publicKeyMultibase === 'string') {
|
|
38
|
+
keys.add(method.publicKeyMultibase);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return keys;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Builds the controller view over an already-verified did:webvh account log
|
|
45
|
+
* (the `verifyAccountLog` output -- callers never hand this a log they have
|
|
46
|
+
* not verified against the account pointer). Anchored-version lookups
|
|
47
|
+
* re-resolve the held log at that version and are memoized: controller logs
|
|
48
|
+
* are tens of entries and anchors cluster on few versions.
|
|
49
|
+
*
|
|
50
|
+
* @param options {object}
|
|
51
|
+
* @param options.did {string} the account's did:webvh, as verified
|
|
52
|
+
* @param options.log {DIDLog} the verified account log
|
|
53
|
+
* @returns {ResourceLogController}
|
|
54
|
+
*/
|
|
55
|
+
export function webvhResourceLogController({ did, log }) {
|
|
56
|
+
const versionIds = log.map(entry => entry.versionId);
|
|
57
|
+
const memo = new Map();
|
|
58
|
+
async function resolveAssertionKeys(versionId) {
|
|
59
|
+
const resolved = await resolveDIDFromLog(log, versionId === undefined ? {} : { versionId });
|
|
60
|
+
if (resolved.meta.error || !resolved.doc) {
|
|
61
|
+
throw new ResourceLogIntegrityError(`The controller document did not resolve at version ` +
|
|
62
|
+
`"${versionId ?? '<head>'}" (${resolved.meta.error ?? 'no document returned'}).`);
|
|
63
|
+
}
|
|
64
|
+
return assertionKeysOf(resolved.doc);
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
did,
|
|
68
|
+
versionIds,
|
|
69
|
+
assertionKeysAt(versionId) {
|
|
70
|
+
const key = versionId ?? '';
|
|
71
|
+
let pending = memo.get(key);
|
|
72
|
+
if (!pending) {
|
|
73
|
+
pending = resolveAssertionKeys(versionId);
|
|
74
|
+
memo.set(key, pending);
|
|
75
|
+
pending.catch(() => memo.delete(key));
|
|
76
|
+
}
|
|
77
|
+
return pending;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/resourceLog/controller.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,iBAAiB,EAAe,MAAM,2BAA2B,CAAA;AAC1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAkCvD;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,GAAsB;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAA2C,CAAA;IAC/D,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,kBAAkB,IAAI,EAAE,EAAE,CAAC;QAClD,IAAI,OAAO,MAAM,EAAE,EAAE,KAAK,QAAQ,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,eAAe,IAAI,EAAE,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;QAClE,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,kBAAkB,KAAK,QAAQ,EAAE,CAAC;YAC5D,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAA;QACrC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,0BAA0B,CAAC,EACzC,GAAG,EACH,GAAG,EAIJ;IACC,MAAM,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAgC,CAAA;IACpD,KAAK,UAAU,oBAAoB,CACjC,SAAkB;QAElB,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CACtC,GAAG,EACH,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAC7C,CAAA;QACD,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;YACzC,MAAM,IAAI,yBAAyB,CACjC,qDAAqD;gBACnD,IAAI,SAAS,IAAI,QAAQ,MACvB,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,sBACzB,IAAI,CACP,CAAA;QACH,CAAC;QACD,OAAO,eAAe,CAAC,QAAQ,CAAC,GAAwB,CAAC,CAAA;IAC3D,CAAC;IACD,OAAO;QACL,GAAG;QACH,UAAU;QACV,eAAe,CAAC,SAAkB;YAChC,MAAM,GAAG,GAAG,SAAS,IAAI,EAAE,CAAA;YAC3B,IAAI,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAA;gBACzC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;gBACtB,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;YACvC,CAAC;YACD,OAAO,OAAO,CAAA;QAChB,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ResourceLogEntry } from '@interop/was-client/log';
|
|
2
|
+
import type { ResourceLogController } from './controller.js';
|
|
3
|
+
/**
|
|
4
|
+
* The writer's signing seam: its enrolled Ed25519 signing key's multibase
|
|
5
|
+
* (the fragment of its verification method in the controller document) and a
|
|
6
|
+
* raw detached-signature hook over it. The multibase names the key in the
|
|
7
|
+
* proof's `verificationMethod`; membership under `assertionMethod` at the
|
|
8
|
+
* anchored version is what authorizes the append.
|
|
9
|
+
*/
|
|
10
|
+
export interface ResourceLogSigner {
|
|
11
|
+
keyMultibase: string;
|
|
12
|
+
sign(input: {
|
|
13
|
+
data: Uint8Array;
|
|
14
|
+
}): Promise<Uint8Array>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Builds and signs a genesis entry by the profile's two-pass SCID procedure:
|
|
18
|
+
* the preliminary entry carries the `{SCID}` placeholder as `versionId` and
|
|
19
|
+
* `parameters.scid`, its hash is the SCID, and the final entry substitutes it
|
|
20
|
+
* back in before the ordinary entry hash is computed (`versionId` input
|
|
21
|
+
* value: the SCID).
|
|
22
|
+
*
|
|
23
|
+
* @param options {object}
|
|
24
|
+
* @param options.state {ResourceLogEntry['state']} the full initial state
|
|
25
|
+
* (with its `type`)
|
|
26
|
+
* @param options.method {string} the format identifier
|
|
27
|
+
* (`WAS_RESOURCE_LOG_METHOD`)
|
|
28
|
+
* @param options.controller {ResourceLogController} the verified controller
|
|
29
|
+
* view -- the anchor source
|
|
30
|
+
* @param options.signer {ResourceLogSigner}
|
|
31
|
+
* @param [options.previousLog] {object} handover successors only: the prior
|
|
32
|
+
* log's SCID and the `versionId` of its terminal entry's predecessor
|
|
33
|
+
* @param [options.versionTime] {string} RFC3339 UTC; defaults to now
|
|
34
|
+
* @returns {Promise<ResourceLogEntry>}
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildResourceLogGenesis({ state, method, controller, signer, previousLog, versionTime }: {
|
|
37
|
+
state: ResourceLogEntry['state'];
|
|
38
|
+
method: string;
|
|
39
|
+
controller: ResourceLogController;
|
|
40
|
+
signer: ResourceLogSigner;
|
|
41
|
+
previousLog?: {
|
|
42
|
+
scid: string;
|
|
43
|
+
head: string;
|
|
44
|
+
};
|
|
45
|
+
versionTime?: string;
|
|
46
|
+
}): Promise<ResourceLogEntry>;
|
|
47
|
+
/**
|
|
48
|
+
* Builds and signs the next ordinary entry against a verified head: full
|
|
49
|
+
* state, empty `parameters`, hash chained off the head's `versionId`, proof
|
|
50
|
+
* anchored at the controller's verified head. Callers hold a verified head
|
|
51
|
+
* by construction (an entry is never built on an unverified one).
|
|
52
|
+
*
|
|
53
|
+
* @param options {object}
|
|
54
|
+
* @param options.head {ResourceLogEntry} the verified head entry
|
|
55
|
+
* @param options.state {ResourceLogEntry['state']} the full next state
|
|
56
|
+
* @param options.controller {ResourceLogController}
|
|
57
|
+
* @param options.signer {ResourceLogSigner}
|
|
58
|
+
* @param [options.versionTime] {string} RFC3339 UTC; defaults to now
|
|
59
|
+
* @returns {Promise<ResourceLogEntry>}
|
|
60
|
+
*/
|
|
61
|
+
export declare function buildResourceLogEntry({ head, state, controller, signer, versionTime }: {
|
|
62
|
+
head: ResourceLogEntry;
|
|
63
|
+
state: ResourceLogEntry['state'];
|
|
64
|
+
controller: ResourceLogController;
|
|
65
|
+
signer: ResourceLogSigner;
|
|
66
|
+
versionTime?: string;
|
|
67
|
+
}): Promise<ResourceLogEntry>;
|
|
68
|
+
//# sourceMappingURL=entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/resourceLog/entry.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;CACvD;AAqFD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,uBAAuB,CAAC,EAC5C,KAAK,EACL,MAAM,EACN,UAAU,EACV,MAAM,EACN,WAAW,EACX,WAAW,EACZ,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,qBAAqB,CAAA;IACjC,MAAM,EAAE,iBAAiB,CAAA;IACzB,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CAAC,EAC1C,IAAI,EACJ,KAAK,EACL,UAAU,EACV,MAAM,EACN,WAAW,EACZ,EAAE;IACD,IAAI,EAAE,gBAAgB,CAAA;IACtB,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAChC,UAAU,EAAE,qBAAqB,CAAA;IACjC,MAAM,EAAE,iBAAiB,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0B5B"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Resource-log entry construction: the two-pass SCID genesis build and the
|
|
6
|
+
* ordinary next-entry build, both signed under the writer's enrolled Ed25519
|
|
7
|
+
* key with the entry anchor riding as a `versionId` DID parameter on the
|
|
8
|
+
* proof's `verificationMethod` -- the writer anchors at the head of the
|
|
9
|
+
* controller document as it last verified it. All hashing and proof
|
|
10
|
+
* construction comes from the did:webvh log kernel; nothing is re-derived
|
|
11
|
+
* here.
|
|
12
|
+
*/
|
|
13
|
+
import { buildVersionId, createDataIntegrityProofTemplate, deriveHash, parseAndValidateVersionId, SCID_PLACEHOLDER, signDataIntegrityProof, signerFromExternalKey } from '@interop/did-method-webvh';
|
|
14
|
+
/**
|
|
15
|
+
* The writer's anchored verification-method DID URL: the controller DID, the
|
|
16
|
+
* anchor at the controller's verified head as a `versionId` DID parameter
|
|
17
|
+
* (omitted for an unversioned controller), and the signing key's multibase as
|
|
18
|
+
* the fragment.
|
|
19
|
+
*
|
|
20
|
+
* @param options {object}
|
|
21
|
+
* @param options.controller {ResourceLogController}
|
|
22
|
+
* @param options.keyMultibase {string}
|
|
23
|
+
* @returns {string}
|
|
24
|
+
*/
|
|
25
|
+
function anchoredVerificationMethod({ controller, keyMultibase }) {
|
|
26
|
+
const anchor = controller.versionIds[controller.versionIds.length - 1];
|
|
27
|
+
const query = anchor === undefined ? '' : `?versionId=${anchor}`;
|
|
28
|
+
return `${controller.did}${query}#${keyMultibase}`;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Refuses a state document the profile forbids in an entry: one without a
|
|
32
|
+
* `type` schema identifier, or one carrying the projection-only `history`
|
|
33
|
+
* member.
|
|
34
|
+
*
|
|
35
|
+
* @param state {ResourceLogEntry['state']}
|
|
36
|
+
*/
|
|
37
|
+
function checkState(state) {
|
|
38
|
+
if (typeof state.type !== 'string') {
|
|
39
|
+
throw new Error('A resource log entry state must carry a type schema identifier.');
|
|
40
|
+
}
|
|
41
|
+
if ('history' in state) {
|
|
42
|
+
throw new Error('A resource log entry state must not carry a history member (the ' +
|
|
43
|
+
'profile reserves that member name).');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Signs a fully version-identified entry under the profile's fixed proof
|
|
48
|
+
* shape.
|
|
49
|
+
*
|
|
50
|
+
* @param options {object}
|
|
51
|
+
* @param options.entry {object} the entry, `proof` absent
|
|
52
|
+
* @param options.signer {ResourceLogSigner}
|
|
53
|
+
* @param options.verificationMethod {string} the anchored DID URL
|
|
54
|
+
* @param options.created {string} the proof timestamp
|
|
55
|
+
* @returns {Promise<ResourceLogEntry>}
|
|
56
|
+
*/
|
|
57
|
+
async function signEntry({ entry, signer, verificationMethod, created }) {
|
|
58
|
+
const proofTemplate = createDataIntegrityProofTemplate({
|
|
59
|
+
verificationMethod,
|
|
60
|
+
created
|
|
61
|
+
});
|
|
62
|
+
const proof = await signDataIntegrityProof(entry, proofTemplate, signerFromExternalKey({
|
|
63
|
+
publicKeyMultibase: signer.keyMultibase,
|
|
64
|
+
sign: signer.sign
|
|
65
|
+
}));
|
|
66
|
+
// The kernel's proof type keeps proofPurpose as the full union; the
|
|
67
|
+
// template fixed it to the profile's assertionMethod shape.
|
|
68
|
+
return { ...entry, proof: [proof] };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Builds and signs a genesis entry by the profile's two-pass SCID procedure:
|
|
72
|
+
* the preliminary entry carries the `{SCID}` placeholder as `versionId` and
|
|
73
|
+
* `parameters.scid`, its hash is the SCID, and the final entry substitutes it
|
|
74
|
+
* back in before the ordinary entry hash is computed (`versionId` input
|
|
75
|
+
* value: the SCID).
|
|
76
|
+
*
|
|
77
|
+
* @param options {object}
|
|
78
|
+
* @param options.state {ResourceLogEntry['state']} the full initial state
|
|
79
|
+
* (with its `type`)
|
|
80
|
+
* @param options.method {string} the format identifier
|
|
81
|
+
* (`WAS_RESOURCE_LOG_METHOD`)
|
|
82
|
+
* @param options.controller {ResourceLogController} the verified controller
|
|
83
|
+
* view -- the anchor source
|
|
84
|
+
* @param options.signer {ResourceLogSigner}
|
|
85
|
+
* @param [options.previousLog] {object} handover successors only: the prior
|
|
86
|
+
* log's SCID and the `versionId` of its terminal entry's predecessor
|
|
87
|
+
* @param [options.versionTime] {string} RFC3339 UTC; defaults to now
|
|
88
|
+
* @returns {Promise<ResourceLogEntry>}
|
|
89
|
+
*/
|
|
90
|
+
export async function buildResourceLogGenesis({ state, method, controller, signer, previousLog, versionTime }) {
|
|
91
|
+
checkState(state);
|
|
92
|
+
const time = versionTime ?? new Date().toISOString();
|
|
93
|
+
const parametersOf = (scid) => ({
|
|
94
|
+
method,
|
|
95
|
+
scid,
|
|
96
|
+
...(previousLog === undefined ? {} : { previousLog })
|
|
97
|
+
});
|
|
98
|
+
const scid = await deriveHash({
|
|
99
|
+
versionId: SCID_PLACEHOLDER,
|
|
100
|
+
versionTime: time,
|
|
101
|
+
parameters: parametersOf(SCID_PLACEHOLDER),
|
|
102
|
+
state
|
|
103
|
+
});
|
|
104
|
+
const parameters = parametersOf(scid);
|
|
105
|
+
const entryHash = await deriveHash({
|
|
106
|
+
versionId: scid,
|
|
107
|
+
versionTime: time,
|
|
108
|
+
parameters,
|
|
109
|
+
state
|
|
110
|
+
});
|
|
111
|
+
return signEntry({
|
|
112
|
+
entry: {
|
|
113
|
+
versionId: buildVersionId(1, entryHash),
|
|
114
|
+
versionTime: time,
|
|
115
|
+
parameters,
|
|
116
|
+
state
|
|
117
|
+
},
|
|
118
|
+
signer,
|
|
119
|
+
verificationMethod: anchoredVerificationMethod({
|
|
120
|
+
controller,
|
|
121
|
+
keyMultibase: signer.keyMultibase
|
|
122
|
+
}),
|
|
123
|
+
created: time
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Builds and signs the next ordinary entry against a verified head: full
|
|
128
|
+
* state, empty `parameters`, hash chained off the head's `versionId`, proof
|
|
129
|
+
* anchored at the controller's verified head. Callers hold a verified head
|
|
130
|
+
* by construction (an entry is never built on an unverified one).
|
|
131
|
+
*
|
|
132
|
+
* @param options {object}
|
|
133
|
+
* @param options.head {ResourceLogEntry} the verified head entry
|
|
134
|
+
* @param options.state {ResourceLogEntry['state']} the full next state
|
|
135
|
+
* @param options.controller {ResourceLogController}
|
|
136
|
+
* @param options.signer {ResourceLogSigner}
|
|
137
|
+
* @param [options.versionTime] {string} RFC3339 UTC; defaults to now
|
|
138
|
+
* @returns {Promise<ResourceLogEntry>}
|
|
139
|
+
*/
|
|
140
|
+
export async function buildResourceLogEntry({ head, state, controller, signer, versionTime }) {
|
|
141
|
+
checkState(state);
|
|
142
|
+
const time = versionTime ?? new Date().toISOString();
|
|
143
|
+
const headOrdinal = Number.parseInt(head.versionId, 10);
|
|
144
|
+
const ordinal = headOrdinal + 1;
|
|
145
|
+
parseAndValidateVersionId(head.versionId, headOrdinal);
|
|
146
|
+
const entryHash = await deriveHash({
|
|
147
|
+
versionId: head.versionId,
|
|
148
|
+
versionTime: time,
|
|
149
|
+
parameters: {},
|
|
150
|
+
state
|
|
151
|
+
});
|
|
152
|
+
return signEntry({
|
|
153
|
+
entry: {
|
|
154
|
+
versionId: buildVersionId(ordinal, entryHash),
|
|
155
|
+
versionTime: time,
|
|
156
|
+
parameters: {},
|
|
157
|
+
state
|
|
158
|
+
},
|
|
159
|
+
signer,
|
|
160
|
+
verificationMethod: anchoredVerificationMethod({
|
|
161
|
+
controller,
|
|
162
|
+
keyMultibase: signer.keyMultibase
|
|
163
|
+
}),
|
|
164
|
+
created: time
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/resourceLog/entry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The resource-log refusal taxonomy, carried over from the roster's WC-1
|
|
6
|
+
* detached-signature design onto the log design. Two adversarial classes plus
|
|
7
|
+
* one lifecycle refusal:
|
|
8
|
+
*
|
|
9
|
+
* - {@link ResourceLogIntegrityError} -- fabrication: the served log fails
|
|
10
|
+
* verification on its own terms (parse shape, SCID, chain hashes, proofs,
|
|
11
|
+
* or the external-authorization rule). Whoever produced it could not make a
|
|
12
|
+
* log the account's clients would have made.
|
|
13
|
+
* - {@link ResourceLogContinuityError} -- a served log that verifies but
|
|
14
|
+
* conflicts with what this client has already accepted: a rollback behind
|
|
15
|
+
* the chain-head pin, a fork off the pinned history, or an SCID/method
|
|
16
|
+
* switch outside a verified handover. The log may be internally consistent;
|
|
17
|
+
* it is not the continuation of the history this client pinned.
|
|
18
|
+
* - {@link ResourceLogClosedError} -- an append refused because the verified
|
|
19
|
+
* head is a terminal handover entry. Not an attack: the log's own authors
|
|
20
|
+
* closed it, and a verifier of this profile must refuse to extend a closed
|
|
21
|
+
* log even though nothing currently emits terminal entries.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* A served log failed verification: malformed entries, a non-verifying SCID,
|
|
25
|
+
* a broken hash chain, a failing proof, or a signer the controller document
|
|
26
|
+
* does not back at the entry's anchored version. Fabrication-class: refused
|
|
27
|
+
* as something no enrolled client produced.
|
|
28
|
+
*/
|
|
29
|
+
export declare class ResourceLogIntegrityError extends Error {
|
|
30
|
+
constructor(message: string, options?: {
|
|
31
|
+
cause?: unknown;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A served log conflicts with this client's chain-head pin: `rollback` (the
|
|
36
|
+
* served head is behind the pinned head -- possibly replication lag; the pin
|
|
37
|
+
* is never regressed and the caller may retry), `fork` (the served log
|
|
38
|
+
* diverges from the pinned history -- both logs are transferable evidence of
|
|
39
|
+
* equivocation, so the served entries ride along), `scid-switch` /
|
|
40
|
+
* `method-switch` (a different log identity or format under the pinned
|
|
41
|
+
* location, outside a verified handover).
|
|
42
|
+
*/
|
|
43
|
+
export declare class ResourceLogContinuityError extends Error {
|
|
44
|
+
reason: 'rollback' | 'fork' | 'scid-switch' | 'method-switch';
|
|
45
|
+
pinnedHead: string;
|
|
46
|
+
/**
|
|
47
|
+
* On a `fork`, the full served log retained as evidence: every entry is
|
|
48
|
+
* signed, so a conflicting pair of logs under one SCID is transferable,
|
|
49
|
+
* independently verifiable proof of equivocation.
|
|
50
|
+
*/
|
|
51
|
+
servedEntries?: unknown[];
|
|
52
|
+
constructor({ reason, pinnedHead, servedEntries }: {
|
|
53
|
+
reason: 'rollback' | 'fork' | 'scid-switch' | 'method-switch';
|
|
54
|
+
pinnedHead: string;
|
|
55
|
+
servedEntries?: unknown[];
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* An append was refused because the log's verified head is a terminal
|
|
60
|
+
* handover entry: the log is closed and names a successor, and this profile
|
|
61
|
+
* forbids extending a history its authors have closed.
|
|
62
|
+
*/
|
|
63
|
+
export declare class ResourceLogClosedError extends Error {
|
|
64
|
+
nextLog: {
|
|
65
|
+
method: string;
|
|
66
|
+
scid: string;
|
|
67
|
+
};
|
|
68
|
+
constructor({ nextLog }: {
|
|
69
|
+
nextLog: {
|
|
70
|
+
method: string;
|
|
71
|
+
scid: string;
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/resourceLog/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;GAKG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI3D;AAED;;;;;;;;GAQG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,eAAe,CAAA;IAC7D,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,EAAE,CAAA;gBACb,EACV,MAAM,EACN,UAAU,EACV,aAAa,EACd,EAAE;QACD,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,eAAe,CAAA;QAC7D,UAAU,EAAE,MAAM,CAAA;QAClB,aAAa,CAAC,EAAE,OAAO,EAAE,CAAA;KAC1B;CAUF;AAED;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;gBAC7B,EAAE,OAAO,EAAE,EAAE;QAAE,OAAO,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE;CAQvE"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The resource-log refusal taxonomy, carried over from the roster's WC-1
|
|
6
|
+
* detached-signature design onto the log design. Two adversarial classes plus
|
|
7
|
+
* one lifecycle refusal:
|
|
8
|
+
*
|
|
9
|
+
* - {@link ResourceLogIntegrityError} -- fabrication: the served log fails
|
|
10
|
+
* verification on its own terms (parse shape, SCID, chain hashes, proofs,
|
|
11
|
+
* or the external-authorization rule). Whoever produced it could not make a
|
|
12
|
+
* log the account's clients would have made.
|
|
13
|
+
* - {@link ResourceLogContinuityError} -- a served log that verifies but
|
|
14
|
+
* conflicts with what this client has already accepted: a rollback behind
|
|
15
|
+
* the chain-head pin, a fork off the pinned history, or an SCID/method
|
|
16
|
+
* switch outside a verified handover. The log may be internally consistent;
|
|
17
|
+
* it is not the continuation of the history this client pinned.
|
|
18
|
+
* - {@link ResourceLogClosedError} -- an append refused because the verified
|
|
19
|
+
* head is a terminal handover entry. Not an attack: the log's own authors
|
|
20
|
+
* closed it, and a verifier of this profile must refuse to extend a closed
|
|
21
|
+
* log even though nothing currently emits terminal entries.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* A served log failed verification: malformed entries, a non-verifying SCID,
|
|
25
|
+
* a broken hash chain, a failing proof, or a signer the controller document
|
|
26
|
+
* does not back at the entry's anchored version. Fabrication-class: refused
|
|
27
|
+
* as something no enrolled client produced.
|
|
28
|
+
*/
|
|
29
|
+
export class ResourceLogIntegrityError extends Error {
|
|
30
|
+
constructor(message, options) {
|
|
31
|
+
super(message, options);
|
|
32
|
+
this.name = 'ResourceLogIntegrityError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A served log conflicts with this client's chain-head pin: `rollback` (the
|
|
37
|
+
* served head is behind the pinned head -- possibly replication lag; the pin
|
|
38
|
+
* is never regressed and the caller may retry), `fork` (the served log
|
|
39
|
+
* diverges from the pinned history -- both logs are transferable evidence of
|
|
40
|
+
* equivocation, so the served entries ride along), `scid-switch` /
|
|
41
|
+
* `method-switch` (a different log identity or format under the pinned
|
|
42
|
+
* location, outside a verified handover).
|
|
43
|
+
*/
|
|
44
|
+
export class ResourceLogContinuityError extends Error {
|
|
45
|
+
reason;
|
|
46
|
+
pinnedHead;
|
|
47
|
+
/**
|
|
48
|
+
* On a `fork`, the full served log retained as evidence: every entry is
|
|
49
|
+
* signed, so a conflicting pair of logs under one SCID is transferable,
|
|
50
|
+
* independently verifiable proof of equivocation.
|
|
51
|
+
*/
|
|
52
|
+
servedEntries;
|
|
53
|
+
constructor({ reason, pinnedHead, servedEntries }) {
|
|
54
|
+
super(`The served resource log is not a continuation of the pinned history ` +
|
|
55
|
+
`(${reason}; pinned head ${pinnedHead}).`);
|
|
56
|
+
this.name = 'ResourceLogContinuityError';
|
|
57
|
+
this.reason = reason;
|
|
58
|
+
this.pinnedHead = pinnedHead;
|
|
59
|
+
this.servedEntries = servedEntries;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* An append was refused because the log's verified head is a terminal
|
|
64
|
+
* handover entry: the log is closed and names a successor, and this profile
|
|
65
|
+
* forbids extending a history its authors have closed.
|
|
66
|
+
*/
|
|
67
|
+
export class ResourceLogClosedError extends Error {
|
|
68
|
+
nextLog;
|
|
69
|
+
constructor({ nextLog }) {
|
|
70
|
+
super('The resource log is closed by a terminal handover entry; appends must ' +
|
|
71
|
+
'go to its successor log.');
|
|
72
|
+
this.name = 'ResourceLogClosedError';
|
|
73
|
+
this.nextLog = nextLog;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/resourceLog/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;GAKG;AACH,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAA;IACzC,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,MAAM,CAAuD;IAC7D,UAAU,CAAQ;IAClB;;;;OAIG;IACH,aAAa,CAAY;IACzB,YAAY,EACV,MAAM,EACN,UAAU,EACV,aAAa,EAKd;QACC,KAAK,CACH,sEAAsE;YACpE,IAAI,MAAM,iBAAiB,UAAU,IAAI,CAC5C,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAA;QACxC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;IACpC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,OAAO,CAAkC;IACzC,YAAY,EAAE,OAAO,EAAiD;QACpE,KAAK,CACH,wEAAwE;YACtE,0BAA0B,CAC7B,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAA;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The `@interop/wallet-core/resourceLog` entry: the client side of the
|
|
6
|
+
* Resource Log Profile (App Connect spec `#resource-log-profile`) -- full
|
|
7
|
+
* chain verification against an adversarial host (parse shape, SCID and
|
|
8
|
+
* entry-hash recomputation, entry proofs, the external-authorization rule
|
|
9
|
+
* against the independently verified did:webvh controller document, terminal
|
|
10
|
+
* entries), the chain-head pin with its continuity rules, and the append path
|
|
11
|
+
* (verified-head build, CAS with rebase-and-retry, read-back confirmation).
|
|
12
|
+
* Transport (JSON Lines, the store seam, the projection write) lives in
|
|
13
|
+
* `@interop/was-client/log`; the hashing and proof kernel in
|
|
14
|
+
* `@interop/did-method-webvh`. Kept out of the root export: this subpath
|
|
15
|
+
* pulls the did:webvh and ed25519 dependency graph.
|
|
16
|
+
*/
|
|
17
|
+
export { webvhResourceLogController, type ResourceLogController } from './controller.js';
|
|
18
|
+
export { ResourceLogClosedError, ResourceLogContinuityError, ResourceLogIntegrityError } from './errors.js';
|
|
19
|
+
export { buildResourceLogEntry, buildResourceLogGenesis, type ResourceLogSigner } from './entry.js';
|
|
20
|
+
export { memoryResourceLogPinStore, type ResourceLogHeadPin, type ResourceLogPinStore } from './pin.js';
|
|
21
|
+
export { isTerminalResourceLogEntry, verifyResourceLog, verifyResourceLogHandover, type VerifiedResourceLog } from './verify.js';
|
|
22
|
+
export { appendResourceLog, createResourceLog, readResourceLog } from './append.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resourceLog/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,0BAA0B,EAC1B,KAAK,qBAAqB,EAC3B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,yBAAyB,EACzB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,0BAA0B,EAC1B,iBAAiB,EACjB,yBAAyB,EACzB,KAAK,mBAAmB,EACzB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The `@interop/wallet-core/resourceLog` entry: the client side of the
|
|
6
|
+
* Resource Log Profile (App Connect spec `#resource-log-profile`) -- full
|
|
7
|
+
* chain verification against an adversarial host (parse shape, SCID and
|
|
8
|
+
* entry-hash recomputation, entry proofs, the external-authorization rule
|
|
9
|
+
* against the independently verified did:webvh controller document, terminal
|
|
10
|
+
* entries), the chain-head pin with its continuity rules, and the append path
|
|
11
|
+
* (verified-head build, CAS with rebase-and-retry, read-back confirmation).
|
|
12
|
+
* Transport (JSON Lines, the store seam, the projection write) lives in
|
|
13
|
+
* `@interop/was-client/log`; the hashing and proof kernel in
|
|
14
|
+
* `@interop/did-method-webvh`. Kept out of the root export: this subpath
|
|
15
|
+
* pulls the did:webvh and ed25519 dependency graph.
|
|
16
|
+
*/
|
|
17
|
+
export { webvhResourceLogController } from './controller.js';
|
|
18
|
+
export { ResourceLogClosedError, ResourceLogContinuityError, ResourceLogIntegrityError } from './errors.js';
|
|
19
|
+
export { buildResourceLogEntry, buildResourceLogGenesis } from './entry.js';
|
|
20
|
+
export { memoryResourceLogPinStore } from './pin.js';
|
|
21
|
+
export { isTerminalResourceLogEntry, verifyResourceLog, verifyResourceLogHandover } from './verify.js';
|
|
22
|
+
export { appendResourceLog, createResourceLog, readResourceLog } from './append.js';
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resourceLog/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,0BAA0B,EAE3B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EAC1B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EAExB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,yBAAyB,EAG1B,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,0BAA0B,EAC1B,iBAAiB,EACjB,yBAAyB,EAE1B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EAChB,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The chain-head pin: the client-local durable record of a resource log's
|
|
6
|
+
* verified identity and latest verified head, kept per log beside the app's
|
|
7
|
+
* other continuity pins (the account pointer, the roster epoch pin). The pin
|
|
8
|
+
* is what turns one-shot verification into continuity: a served log whose
|
|
9
|
+
* SCID or method differs from the pin outside a verified handover, or whose
|
|
10
|
+
* history is not a descendant of the pinned head, is refused instead of
|
|
11
|
+
* adopted. Storage is the app's concern (freewallet: beside its other pins in
|
|
12
|
+
* localStorage; DCW: a table row), so only the seam lives here, plus an
|
|
13
|
+
* in-memory implementation for tests and single-session use.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* One log's pin: the format identifier from the genesis `parameters.method`,
|
|
17
|
+
* the SCID, and the `versionId` of the latest verified head. Established at
|
|
18
|
+
* first contact (trust-on-first-use of the log's identity), advanced only
|
|
19
|
+
* after a full verification whose head is the pinned head or a descendant,
|
|
20
|
+
* and replaced wholesale only across a verified handover.
|
|
21
|
+
*/
|
|
22
|
+
export interface ResourceLogHeadPin {
|
|
23
|
+
method: string;
|
|
24
|
+
scid: string;
|
|
25
|
+
head: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Where a client keeps its chain-head pins, one record per log. `read`
|
|
29
|
+
* resolves `null` before first contact. Writes happen only on the two legal
|
|
30
|
+
* transitions (advance after full verification, replace across a verified
|
|
31
|
+
* handover) -- the verifier never regresses a pin.
|
|
32
|
+
*/
|
|
33
|
+
export interface ResourceLogPinStore {
|
|
34
|
+
read(): Promise<ResourceLogHeadPin | null>;
|
|
35
|
+
write(pin: ResourceLogHeadPin): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* An in-memory pin store: continuity within one session only. Tests use it
|
|
39
|
+
* as the seam's reference implementation; apps persist for real.
|
|
40
|
+
*
|
|
41
|
+
* @returns {ResourceLogPinStore}
|
|
42
|
+
*/
|
|
43
|
+
export declare function memoryResourceLogPinStore(): ResourceLogPinStore;
|
|
44
|
+
//# sourceMappingURL=pin.d.ts.map
|