@tinycloud/sdk-services 2.2.1-beta.0 → 2.3.0-beta.5
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/dist/encryption/index.cjs +70 -27
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +25 -25
- package/dist/encryption/index.d.ts +25 -25
- package/dist/encryption/index.js +70 -27
- package/dist/encryption/index.js.map +1 -1
- package/dist/index.cjs +70 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +70 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -100,12 +100,12 @@ interface InlineEncryptedEnvelope {
|
|
|
100
100
|
/**
|
|
101
101
|
* Node-published network descriptor. The node DB is authoritative; a
|
|
102
102
|
* cached copy may also live under
|
|
103
|
-
* `.well-known/encryption/network/<name>` in the
|
|
103
|
+
* `.well-known/encryption/network/<name>` in the owner's account
|
|
104
104
|
* space (a discovery record only).
|
|
105
105
|
*/
|
|
106
106
|
interface NetworkDescriptor {
|
|
107
107
|
networkId: string;
|
|
108
|
-
|
|
108
|
+
ownerDid: string;
|
|
109
109
|
name: string;
|
|
110
110
|
members: ReadonlyArray<{
|
|
111
111
|
nodeId: string;
|
|
@@ -234,7 +234,7 @@ interface ReceiverKeySigner {
|
|
|
234
234
|
}
|
|
235
235
|
/** Capability proof material accompanying a decrypt invocation. */
|
|
236
236
|
interface DecryptCapabilityProof {
|
|
237
|
-
/** Delegation chain CIDs rooted at the network
|
|
237
|
+
/** Delegation chain CIDs rooted at the network owner DID. */
|
|
238
238
|
proofs: ReadonlyArray<string>;
|
|
239
239
|
/** Optional Authorization header value to use instead of building one. */
|
|
240
240
|
authorization?: string;
|
|
@@ -334,7 +334,7 @@ type CanonicalJson = Json;
|
|
|
334
334
|
* descriptor (`state`, `publicEncryptionKey`, `keyVersion`, ...).
|
|
335
335
|
* 2. If the node is unreachable, fall back to the cached discovery
|
|
336
336
|
* record at `.well-known/encryption/network/<name>` inside the
|
|
337
|
-
*
|
|
337
|
+
* owner's public space.
|
|
338
338
|
*
|
|
339
339
|
* The node DB is authoritative on conflict; cached records are
|
|
340
340
|
* advisory only.
|
|
@@ -351,16 +351,16 @@ interface NodeDescriptorFetcher {
|
|
|
351
351
|
}
|
|
352
352
|
interface WellKnownDescriptorFetcher {
|
|
353
353
|
/**
|
|
354
|
-
* Read the cached well-known descriptor by
|
|
354
|
+
* Read the cached well-known descriptor by owner DID + network name.
|
|
355
355
|
* Returns null if no record exists or the record is unreadable.
|
|
356
356
|
*/
|
|
357
|
-
fetchWellKnown(
|
|
357
|
+
fetchWellKnown(ownerDid: string, discoveryKey: string): Promise<NetworkDescriptor | null>;
|
|
358
358
|
}
|
|
359
359
|
interface DiscoverNetworkInput {
|
|
360
|
-
/** Either a networkId URN or a bare network name (paired with `
|
|
360
|
+
/** Either a networkId URN or a bare network name (paired with `ownerDid`). */
|
|
361
361
|
identifier: string;
|
|
362
362
|
/** Required when identifier is a bare name. */
|
|
363
|
-
|
|
363
|
+
ownerDid?: string;
|
|
364
364
|
node?: NodeDescriptorFetcher;
|
|
365
365
|
wellKnown?: WellKnownDescriptorFetcher;
|
|
366
366
|
}
|
|
@@ -368,7 +368,7 @@ interface DiscoverNetworkInput {
|
|
|
368
368
|
* Resolve a network descriptor. The node fetcher is preferred; the
|
|
369
369
|
* well-known fallback is used only on transport failure.
|
|
370
370
|
*
|
|
371
|
-
* The returned descriptor is sanity-checked: `networkId`, `
|
|
371
|
+
* The returned descriptor is sanity-checked: `networkId`, `ownerDid`,
|
|
372
372
|
* and `name` must agree with the URN, and the public key field must
|
|
373
373
|
* be non-empty.
|
|
374
374
|
*/
|
|
@@ -431,10 +431,10 @@ interface IEncryptionService extends IService {
|
|
|
431
431
|
*
|
|
432
432
|
* `identifier` may be either a full networkId URN
|
|
433
433
|
* (`urn:tinycloud:encryption:did:key:...:default`) or a bare network
|
|
434
|
-
* name. The bare name form requires the
|
|
435
|
-
* `
|
|
434
|
+
* name. The bare name form requires the owner DID to be supplied via
|
|
435
|
+
* `ownerDid`.
|
|
436
436
|
*/
|
|
437
|
-
discoverNetwork(identifier: string,
|
|
437
|
+
discoverNetwork(identifier: string, ownerDid?: string): Promise<Result<NetworkDescriptor, EncryptionError>>;
|
|
438
438
|
/**
|
|
439
439
|
* Encrypt plaintext to the network's public key locally. The result
|
|
440
440
|
* is an inline envelope ready to persist (KV/SQL).
|
|
@@ -447,7 +447,7 @@ interface IEncryptionService extends IService {
|
|
|
447
447
|
* decrypt invocation, POST it to the node, verify the signed
|
|
448
448
|
* response, open `wrappedKey`, and decrypt the payload locally.
|
|
449
449
|
*
|
|
450
|
-
* The capability proof must root at the network
|
|
450
|
+
* The capability proof must root at the network owner DID embedded
|
|
451
451
|
* in the envelope's networkId.
|
|
452
452
|
*/
|
|
453
453
|
decryptEnvelope(envelope: InlineEncryptedEnvelope, capabilityProof: DecryptCapabilityProof, options?: DecryptEnvelopeOptions): Promise<Result<Uint8Array, EncryptionError>>;
|
|
@@ -497,7 +497,7 @@ declare class EncryptionService extends BaseService implements IEncryptionServic
|
|
|
497
497
|
constructor(config: EncryptionServiceConfig);
|
|
498
498
|
get config(): EncryptionServiceConfig;
|
|
499
499
|
private get crypto();
|
|
500
|
-
discoverNetwork(identifier: string,
|
|
500
|
+
discoverNetwork(identifier: string, ownerDid?: string): Promise<Result<NetworkDescriptor, EncryptionError>>;
|
|
501
501
|
encryptToNetwork(networkId: string, plaintext: Uint8Array, options?: EncryptToNetworkOptions): Promise<Result<InlineEncryptedEnvelope, EncryptionError>>;
|
|
502
502
|
decryptEnvelope(envelope: InlineEncryptedEnvelope, capabilityProof: DecryptCapabilityProof, options?: DecryptEnvelopeOptions): Promise<Result<Uint8Array, EncryptionError>>;
|
|
503
503
|
}
|
|
@@ -505,27 +505,27 @@ declare class EncryptionService extends BaseService implements IEncryptionServic
|
|
|
505
505
|
/**
|
|
506
506
|
* TinyCloud encryption network identifiers.
|
|
507
507
|
*
|
|
508
|
-
* A network id is `urn:tinycloud:encryption:<
|
|
509
|
-
* `
|
|
508
|
+
* A network id is `urn:tinycloud:encryption:<ownerDid>:<network>` where
|
|
509
|
+
* `ownerDid` is the owner's DID and `network` is a
|
|
510
510
|
* non-empty label drawn from `[a-z0-9][a-z0-9-]*`.
|
|
511
511
|
*
|
|
512
|
-
* The embedded
|
|
512
|
+
* The embedded owner DID is the root authority for the network: any
|
|
513
513
|
* delegation chain ending in a `tinycloud.encryption/decrypt` grant on
|
|
514
|
-
* the network must root at this
|
|
514
|
+
* the network must root at this owner DID.
|
|
515
515
|
*/
|
|
516
516
|
interface ParsedNetworkId {
|
|
517
517
|
/** The full URN string. */
|
|
518
518
|
networkId: string;
|
|
519
|
-
/**
|
|
520
|
-
|
|
521
|
-
/** Network label (the suffix after the
|
|
519
|
+
/** Owner DID embedded in the URN (the network's root authority). */
|
|
520
|
+
ownerDid: string;
|
|
521
|
+
/** Network label (the suffix after the owner DID). */
|
|
522
522
|
name: string;
|
|
523
523
|
}
|
|
524
524
|
declare class NetworkIdError extends Error {
|
|
525
525
|
constructor(message: string);
|
|
526
526
|
}
|
|
527
527
|
/**
|
|
528
|
-
* Parse a network id string into its
|
|
528
|
+
* Parse a network id string into its owner DID and name components.
|
|
529
529
|
*
|
|
530
530
|
* Throws {@link NetworkIdError} when the input does not match
|
|
531
531
|
* `urn:tinycloud:encryption:<did>:<name>`, when the embedded DID is
|
|
@@ -533,17 +533,17 @@ declare class NetworkIdError extends Error {
|
|
|
533
533
|
*/
|
|
534
534
|
declare function parseNetworkId(networkId: string): ParsedNetworkId;
|
|
535
535
|
/**
|
|
536
|
-
* Construct a network id URN from
|
|
536
|
+
* Construct a network id URN from an owner DID and a network name.
|
|
537
537
|
* Validates inputs and throws {@link NetworkIdError} on bad shape.
|
|
538
538
|
*/
|
|
539
|
-
declare function buildNetworkId(
|
|
539
|
+
declare function buildNetworkId(ownerDid: string, name: string): string;
|
|
540
540
|
/**
|
|
541
541
|
* Returns true when {@link networkId} is a syntactically valid network URN.
|
|
542
542
|
*/
|
|
543
543
|
declare function isNetworkId(networkId: unknown): networkId is string;
|
|
544
544
|
/**
|
|
545
545
|
* Resolve the discovery key used to look up a network's descriptor under
|
|
546
|
-
*
|
|
546
|
+
* an owner's public account-space.
|
|
547
547
|
*
|
|
548
548
|
* Format: `.well-known/encryption/network/<name>`.
|
|
549
549
|
*/
|
|
@@ -100,12 +100,12 @@ interface InlineEncryptedEnvelope {
|
|
|
100
100
|
/**
|
|
101
101
|
* Node-published network descriptor. The node DB is authoritative; a
|
|
102
102
|
* cached copy may also live under
|
|
103
|
-
* `.well-known/encryption/network/<name>` in the
|
|
103
|
+
* `.well-known/encryption/network/<name>` in the owner's account
|
|
104
104
|
* space (a discovery record only).
|
|
105
105
|
*/
|
|
106
106
|
interface NetworkDescriptor {
|
|
107
107
|
networkId: string;
|
|
108
|
-
|
|
108
|
+
ownerDid: string;
|
|
109
109
|
name: string;
|
|
110
110
|
members: ReadonlyArray<{
|
|
111
111
|
nodeId: string;
|
|
@@ -234,7 +234,7 @@ interface ReceiverKeySigner {
|
|
|
234
234
|
}
|
|
235
235
|
/** Capability proof material accompanying a decrypt invocation. */
|
|
236
236
|
interface DecryptCapabilityProof {
|
|
237
|
-
/** Delegation chain CIDs rooted at the network
|
|
237
|
+
/** Delegation chain CIDs rooted at the network owner DID. */
|
|
238
238
|
proofs: ReadonlyArray<string>;
|
|
239
239
|
/** Optional Authorization header value to use instead of building one. */
|
|
240
240
|
authorization?: string;
|
|
@@ -334,7 +334,7 @@ type CanonicalJson = Json;
|
|
|
334
334
|
* descriptor (`state`, `publicEncryptionKey`, `keyVersion`, ...).
|
|
335
335
|
* 2. If the node is unreachable, fall back to the cached discovery
|
|
336
336
|
* record at `.well-known/encryption/network/<name>` inside the
|
|
337
|
-
*
|
|
337
|
+
* owner's public space.
|
|
338
338
|
*
|
|
339
339
|
* The node DB is authoritative on conflict; cached records are
|
|
340
340
|
* advisory only.
|
|
@@ -351,16 +351,16 @@ interface NodeDescriptorFetcher {
|
|
|
351
351
|
}
|
|
352
352
|
interface WellKnownDescriptorFetcher {
|
|
353
353
|
/**
|
|
354
|
-
* Read the cached well-known descriptor by
|
|
354
|
+
* Read the cached well-known descriptor by owner DID + network name.
|
|
355
355
|
* Returns null if no record exists or the record is unreadable.
|
|
356
356
|
*/
|
|
357
|
-
fetchWellKnown(
|
|
357
|
+
fetchWellKnown(ownerDid: string, discoveryKey: string): Promise<NetworkDescriptor | null>;
|
|
358
358
|
}
|
|
359
359
|
interface DiscoverNetworkInput {
|
|
360
|
-
/** Either a networkId URN or a bare network name (paired with `
|
|
360
|
+
/** Either a networkId URN or a bare network name (paired with `ownerDid`). */
|
|
361
361
|
identifier: string;
|
|
362
362
|
/** Required when identifier is a bare name. */
|
|
363
|
-
|
|
363
|
+
ownerDid?: string;
|
|
364
364
|
node?: NodeDescriptorFetcher;
|
|
365
365
|
wellKnown?: WellKnownDescriptorFetcher;
|
|
366
366
|
}
|
|
@@ -368,7 +368,7 @@ interface DiscoverNetworkInput {
|
|
|
368
368
|
* Resolve a network descriptor. The node fetcher is preferred; the
|
|
369
369
|
* well-known fallback is used only on transport failure.
|
|
370
370
|
*
|
|
371
|
-
* The returned descriptor is sanity-checked: `networkId`, `
|
|
371
|
+
* The returned descriptor is sanity-checked: `networkId`, `ownerDid`,
|
|
372
372
|
* and `name` must agree with the URN, and the public key field must
|
|
373
373
|
* be non-empty.
|
|
374
374
|
*/
|
|
@@ -431,10 +431,10 @@ interface IEncryptionService extends IService {
|
|
|
431
431
|
*
|
|
432
432
|
* `identifier` may be either a full networkId URN
|
|
433
433
|
* (`urn:tinycloud:encryption:did:key:...:default`) or a bare network
|
|
434
|
-
* name. The bare name form requires the
|
|
435
|
-
* `
|
|
434
|
+
* name. The bare name form requires the owner DID to be supplied via
|
|
435
|
+
* `ownerDid`.
|
|
436
436
|
*/
|
|
437
|
-
discoverNetwork(identifier: string,
|
|
437
|
+
discoverNetwork(identifier: string, ownerDid?: string): Promise<Result<NetworkDescriptor, EncryptionError>>;
|
|
438
438
|
/**
|
|
439
439
|
* Encrypt plaintext to the network's public key locally. The result
|
|
440
440
|
* is an inline envelope ready to persist (KV/SQL).
|
|
@@ -447,7 +447,7 @@ interface IEncryptionService extends IService {
|
|
|
447
447
|
* decrypt invocation, POST it to the node, verify the signed
|
|
448
448
|
* response, open `wrappedKey`, and decrypt the payload locally.
|
|
449
449
|
*
|
|
450
|
-
* The capability proof must root at the network
|
|
450
|
+
* The capability proof must root at the network owner DID embedded
|
|
451
451
|
* in the envelope's networkId.
|
|
452
452
|
*/
|
|
453
453
|
decryptEnvelope(envelope: InlineEncryptedEnvelope, capabilityProof: DecryptCapabilityProof, options?: DecryptEnvelopeOptions): Promise<Result<Uint8Array, EncryptionError>>;
|
|
@@ -497,7 +497,7 @@ declare class EncryptionService extends BaseService implements IEncryptionServic
|
|
|
497
497
|
constructor(config: EncryptionServiceConfig);
|
|
498
498
|
get config(): EncryptionServiceConfig;
|
|
499
499
|
private get crypto();
|
|
500
|
-
discoverNetwork(identifier: string,
|
|
500
|
+
discoverNetwork(identifier: string, ownerDid?: string): Promise<Result<NetworkDescriptor, EncryptionError>>;
|
|
501
501
|
encryptToNetwork(networkId: string, plaintext: Uint8Array, options?: EncryptToNetworkOptions): Promise<Result<InlineEncryptedEnvelope, EncryptionError>>;
|
|
502
502
|
decryptEnvelope(envelope: InlineEncryptedEnvelope, capabilityProof: DecryptCapabilityProof, options?: DecryptEnvelopeOptions): Promise<Result<Uint8Array, EncryptionError>>;
|
|
503
503
|
}
|
|
@@ -505,27 +505,27 @@ declare class EncryptionService extends BaseService implements IEncryptionServic
|
|
|
505
505
|
/**
|
|
506
506
|
* TinyCloud encryption network identifiers.
|
|
507
507
|
*
|
|
508
|
-
* A network id is `urn:tinycloud:encryption:<
|
|
509
|
-
* `
|
|
508
|
+
* A network id is `urn:tinycloud:encryption:<ownerDid>:<network>` where
|
|
509
|
+
* `ownerDid` is the owner's DID and `network` is a
|
|
510
510
|
* non-empty label drawn from `[a-z0-9][a-z0-9-]*`.
|
|
511
511
|
*
|
|
512
|
-
* The embedded
|
|
512
|
+
* The embedded owner DID is the root authority for the network: any
|
|
513
513
|
* delegation chain ending in a `tinycloud.encryption/decrypt` grant on
|
|
514
|
-
* the network must root at this
|
|
514
|
+
* the network must root at this owner DID.
|
|
515
515
|
*/
|
|
516
516
|
interface ParsedNetworkId {
|
|
517
517
|
/** The full URN string. */
|
|
518
518
|
networkId: string;
|
|
519
|
-
/**
|
|
520
|
-
|
|
521
|
-
/** Network label (the suffix after the
|
|
519
|
+
/** Owner DID embedded in the URN (the network's root authority). */
|
|
520
|
+
ownerDid: string;
|
|
521
|
+
/** Network label (the suffix after the owner DID). */
|
|
522
522
|
name: string;
|
|
523
523
|
}
|
|
524
524
|
declare class NetworkIdError extends Error {
|
|
525
525
|
constructor(message: string);
|
|
526
526
|
}
|
|
527
527
|
/**
|
|
528
|
-
* Parse a network id string into its
|
|
528
|
+
* Parse a network id string into its owner DID and name components.
|
|
529
529
|
*
|
|
530
530
|
* Throws {@link NetworkIdError} when the input does not match
|
|
531
531
|
* `urn:tinycloud:encryption:<did>:<name>`, when the embedded DID is
|
|
@@ -533,17 +533,17 @@ declare class NetworkIdError extends Error {
|
|
|
533
533
|
*/
|
|
534
534
|
declare function parseNetworkId(networkId: string): ParsedNetworkId;
|
|
535
535
|
/**
|
|
536
|
-
* Construct a network id URN from
|
|
536
|
+
* Construct a network id URN from an owner DID and a network name.
|
|
537
537
|
* Validates inputs and throws {@link NetworkIdError} on bad shape.
|
|
538
538
|
*/
|
|
539
|
-
declare function buildNetworkId(
|
|
539
|
+
declare function buildNetworkId(ownerDid: string, name: string): string;
|
|
540
540
|
/**
|
|
541
541
|
* Returns true when {@link networkId} is a syntactically valid network URN.
|
|
542
542
|
*/
|
|
543
543
|
declare function isNetworkId(networkId: unknown): networkId is string;
|
|
544
544
|
/**
|
|
545
545
|
* Resolve the discovery key used to look up a network's descriptor under
|
|
546
|
-
*
|
|
546
|
+
* an owner's public account-space.
|
|
547
547
|
*
|
|
548
548
|
* Format: `.well-known/encryption/network/<name>`.
|
|
549
549
|
*/
|
package/dist/encryption/index.js
CHANGED
|
@@ -387,6 +387,7 @@ function canonicalHashHex(sha256, value) {
|
|
|
387
387
|
// src/encryption/networkId.ts
|
|
388
388
|
var URN_PREFIX = "urn:tinycloud:encryption:";
|
|
389
389
|
var NETWORK_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
390
|
+
var PKH_EIP155_DID_RE = /^did:pkh:eip155:(\d+):(0x[a-fA-F0-9]{40})$/;
|
|
390
391
|
var NetworkIdError = class extends Error {
|
|
391
392
|
constructor(message) {
|
|
392
393
|
super(message);
|
|
@@ -406,20 +407,20 @@ function parseNetworkId(networkId) {
|
|
|
406
407
|
const lastColon = body.lastIndexOf(":");
|
|
407
408
|
if (lastColon <= 0 || lastColon === body.length - 1) {
|
|
408
409
|
throw new NetworkIdError(
|
|
409
|
-
`networkId missing
|
|
410
|
+
`networkId missing ownerDid or name segment (got ${JSON.stringify(networkId)})`
|
|
410
411
|
);
|
|
411
412
|
}
|
|
412
|
-
const
|
|
413
|
+
const ownerDid = body.slice(0, lastColon);
|
|
413
414
|
const name = body.slice(lastColon + 1);
|
|
414
|
-
if (!
|
|
415
|
+
if (!ownerDid.startsWith("did:")) {
|
|
415
416
|
throw new NetworkIdError(
|
|
416
|
-
`networkId
|
|
417
|
+
`networkId ownerDid must be a DID (got ${JSON.stringify(ownerDid)})`
|
|
417
418
|
);
|
|
418
419
|
}
|
|
419
|
-
const didParts =
|
|
420
|
+
const didParts = ownerDid.split(":");
|
|
420
421
|
if (didParts.length < 3 || didParts.some((p) => p.length === 0)) {
|
|
421
422
|
throw new NetworkIdError(
|
|
422
|
-
`networkId
|
|
423
|
+
`networkId ownerDid is not a well-formed DID (got ${JSON.stringify(ownerDid)})`
|
|
423
424
|
);
|
|
424
425
|
}
|
|
425
426
|
if (!NETWORK_NAME_RE.test(name)) {
|
|
@@ -427,18 +428,18 @@ function parseNetworkId(networkId) {
|
|
|
427
428
|
`networkId name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
428
429
|
);
|
|
429
430
|
}
|
|
430
|
-
return { networkId,
|
|
431
|
+
return { networkId, ownerDid, name };
|
|
431
432
|
}
|
|
432
|
-
function buildNetworkId(
|
|
433
|
-
if (typeof
|
|
434
|
-
throw new NetworkIdError("
|
|
433
|
+
function buildNetworkId(ownerDid, name) {
|
|
434
|
+
if (typeof ownerDid !== "string" || !ownerDid.startsWith("did:")) {
|
|
435
|
+
throw new NetworkIdError("ownerDid must be a DID");
|
|
435
436
|
}
|
|
436
437
|
if (typeof name !== "string" || !NETWORK_NAME_RE.test(name)) {
|
|
437
438
|
throw new NetworkIdError(
|
|
438
439
|
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
439
440
|
);
|
|
440
441
|
}
|
|
441
|
-
const networkId = `${URN_PREFIX}${
|
|
442
|
+
const networkId = `${URN_PREFIX}${ownerDid}:${name}`;
|
|
442
443
|
parseNetworkId(networkId);
|
|
443
444
|
return networkId;
|
|
444
445
|
}
|
|
@@ -453,6 +454,22 @@ function isNetworkId(networkId) {
|
|
|
453
454
|
return false;
|
|
454
455
|
}
|
|
455
456
|
}
|
|
457
|
+
function parsePkhOwnerDid(ownerDid) {
|
|
458
|
+
const match = ownerDid.match(PKH_EIP155_DID_RE);
|
|
459
|
+
if (!match) return null;
|
|
460
|
+
return {
|
|
461
|
+
chainId: match[1],
|
|
462
|
+
address: match[2].toLowerCase()
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
function ownerDidMatches(a, b) {
|
|
466
|
+
const aPkh = parsePkhOwnerDid(a);
|
|
467
|
+
const bPkh = parsePkhOwnerDid(b);
|
|
468
|
+
if (aPkh && bPkh) {
|
|
469
|
+
return aPkh.chainId === bPkh.chainId && aPkh.address === bPkh.address;
|
|
470
|
+
}
|
|
471
|
+
return a === b;
|
|
472
|
+
}
|
|
456
473
|
function networkDiscoveryKey(name) {
|
|
457
474
|
if (!NETWORK_NAME_RE.test(name)) {
|
|
458
475
|
throw new NetworkIdError(
|
|
@@ -515,27 +532,27 @@ function toError(error) {
|
|
|
515
532
|
// src/encryption/discovery.ts
|
|
516
533
|
async function discoverNetwork(input) {
|
|
517
534
|
let networkId;
|
|
518
|
-
let
|
|
535
|
+
let ownerDid;
|
|
519
536
|
let name;
|
|
520
537
|
try {
|
|
521
538
|
if (input.identifier.startsWith("urn:tinycloud:encryption:")) {
|
|
522
539
|
const parsed = parseNetworkId(input.identifier);
|
|
523
540
|
networkId = parsed.networkId;
|
|
524
|
-
|
|
541
|
+
ownerDid = parsed.ownerDid;
|
|
525
542
|
name = parsed.name;
|
|
526
543
|
} else {
|
|
527
|
-
if (input.
|
|
544
|
+
if (input.ownerDid === void 0) {
|
|
528
545
|
return {
|
|
529
546
|
ok: false,
|
|
530
547
|
error: encryptionError({
|
|
531
548
|
code: "INVALID_INPUT",
|
|
532
|
-
message: "discoverNetwork requires `
|
|
549
|
+
message: "discoverNetwork requires `ownerDid` when identifier is a bare network name"
|
|
533
550
|
})
|
|
534
551
|
};
|
|
535
552
|
}
|
|
536
|
-
networkId = `urn:tinycloud:encryption:${input.
|
|
553
|
+
networkId = `urn:tinycloud:encryption:${input.ownerDid}:${input.identifier}`;
|
|
537
554
|
const parsed = parseNetworkId(networkId);
|
|
538
|
-
|
|
555
|
+
ownerDid = parsed.ownerDid;
|
|
539
556
|
name = parsed.name;
|
|
540
557
|
}
|
|
541
558
|
} catch (err2) {
|
|
@@ -554,7 +571,7 @@ async function discoverNetwork(input) {
|
|
|
554
571
|
try {
|
|
555
572
|
const descriptor = await input.node.fetchByNetworkId(networkId);
|
|
556
573
|
if (descriptor !== null) {
|
|
557
|
-
const validated = validateDescriptor(descriptor, networkId,
|
|
574
|
+
const validated = validateDescriptor(descriptor, networkId, ownerDid, name);
|
|
558
575
|
if (!validated.ok) return validated;
|
|
559
576
|
return { ok: true, data: { descriptor: validated.data, source: "node" } };
|
|
560
577
|
}
|
|
@@ -564,11 +581,11 @@ async function discoverNetwork(input) {
|
|
|
564
581
|
if (input.wellKnown !== void 0) {
|
|
565
582
|
try {
|
|
566
583
|
const descriptor = await input.wellKnown.fetchWellKnown(
|
|
567
|
-
|
|
584
|
+
ownerDid,
|
|
568
585
|
networkDiscoveryKey(name)
|
|
569
586
|
);
|
|
570
587
|
if (descriptor !== null) {
|
|
571
|
-
const validated = validateDescriptor(descriptor, networkId,
|
|
588
|
+
const validated = validateDescriptor(descriptor, networkId, ownerDid, name);
|
|
572
589
|
if (!validated.ok) return validated;
|
|
573
590
|
return {
|
|
574
591
|
ok: true,
|
|
@@ -587,8 +604,20 @@ async function discoverNetwork(input) {
|
|
|
587
604
|
})
|
|
588
605
|
};
|
|
589
606
|
}
|
|
590
|
-
function validateDescriptor(descriptor, networkId,
|
|
591
|
-
|
|
607
|
+
function validateDescriptor(descriptor, networkId, ownerDid, name) {
|
|
608
|
+
let descriptorNetwork;
|
|
609
|
+
try {
|
|
610
|
+
descriptorNetwork = parseNetworkId(descriptor.networkId);
|
|
611
|
+
} catch (err2) {
|
|
612
|
+
return {
|
|
613
|
+
ok: false,
|
|
614
|
+
error: encryptionError({
|
|
615
|
+
code: "INVALID_NETWORK_ID",
|
|
616
|
+
message: `descriptor networkId is malformed: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
617
|
+
})
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
if (descriptorNetwork.name !== name || !ownerDidMatches(descriptorNetwork.ownerDid, ownerDid)) {
|
|
592
621
|
return {
|
|
593
622
|
ok: false,
|
|
594
623
|
error: encryptionError({
|
|
@@ -597,12 +626,13 @@ function validateDescriptor(descriptor, networkId, principal, name) {
|
|
|
597
626
|
})
|
|
598
627
|
};
|
|
599
628
|
}
|
|
600
|
-
|
|
629
|
+
const descriptorOwnerDid = descriptorOwner(descriptor);
|
|
630
|
+
if (descriptorOwnerDid === void 0 || !ownerDidMatches(descriptorOwnerDid, ownerDid) || !ownerDidMatches(descriptorOwnerDid, descriptorNetwork.ownerDid)) {
|
|
601
631
|
return {
|
|
602
632
|
ok: false,
|
|
603
633
|
error: encryptionError({
|
|
604
634
|
code: "INVALID_NETWORK_ID",
|
|
605
|
-
message: "descriptor
|
|
635
|
+
message: "descriptor ownerDid does not match networkId ownerDid"
|
|
606
636
|
})
|
|
607
637
|
};
|
|
608
638
|
}
|
|
@@ -624,7 +654,20 @@ function validateDescriptor(descriptor, networkId, principal, name) {
|
|
|
624
654
|
})
|
|
625
655
|
};
|
|
626
656
|
}
|
|
627
|
-
return {
|
|
657
|
+
return {
|
|
658
|
+
ok: true,
|
|
659
|
+
data: {
|
|
660
|
+
...descriptor,
|
|
661
|
+
ownerDid: descriptorOwnerDid
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
function descriptorOwner(descriptor) {
|
|
666
|
+
if (typeof descriptor.ownerDid === "string" && descriptor.ownerDid.length > 0) {
|
|
667
|
+
return descriptor.ownerDid;
|
|
668
|
+
}
|
|
669
|
+
const legacyDescriptor = descriptor;
|
|
670
|
+
return typeof legacyDescriptor.principal === "string" && legacyDescriptor.principal.length > 0 ? legacyDescriptor.principal : void 0;
|
|
628
671
|
}
|
|
629
672
|
function ensureNetworkUsableForDecrypt(descriptor) {
|
|
630
673
|
if (descriptor.state === "active" || descriptor.state === "rotating") {
|
|
@@ -1094,10 +1137,10 @@ var EncryptionService = class extends BaseService {
|
|
|
1094
1137
|
get crypto() {
|
|
1095
1138
|
return this._config.crypto;
|
|
1096
1139
|
}
|
|
1097
|
-
async discoverNetwork(identifier,
|
|
1140
|
+
async discoverNetwork(identifier, ownerDid) {
|
|
1098
1141
|
const result = await discoverNetwork({
|
|
1099
1142
|
identifier,
|
|
1100
|
-
...
|
|
1143
|
+
...ownerDid !== void 0 ? { ownerDid } : {},
|
|
1101
1144
|
...this._config.node !== void 0 ? { node: this._config.node } : {},
|
|
1102
1145
|
...this._config.wellKnown !== void 0 ? { wellKnown: this._config.wellKnown } : {}
|
|
1103
1146
|
});
|