@tinycloud/node-sdk 2.11.0-beta.0 → 2.11.0-beta.3
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/{core-B_i2KfID.d.cts → core-DfcWH9i4.d.cts} +69 -15
- package/dist/{core-B_i2KfID.d.ts → core-DfcWH9i4.d.ts} +69 -15
- package/dist/core.cjs +173 -25
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +173 -25
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +173 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +173 -25
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignRequest, SignInOptions, Delegation, DelegatedResource, PermissionEntry, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, AccountService, RegisterOwnerSharePolicyParams, OwnerSharePolicyRegistrationReceipt, ShareDeliveryAuthorizationReceipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ResolvedDelegate, KeyProvider, JWK } from '@tinycloud/sdk-core';
|
|
1
|
+
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignRequest, SignInOptions, Delegation, DelegatedResource, PermissionEntry, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, INotificationHandler, IENSResolver, AccountService, RegisterOwnerSharePolicyParams, OwnerSharePolicyRegistrationReceipt, ShareDeliveryAuthorizationReceipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ResolvedDelegate, KeyProvider, JWK } from '@tinycloud/sdk-core';
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { InvokeFunction, InvokeAnyFunction } from '@tinycloud/sdk-services';
|
|
4
4
|
|
|
@@ -319,6 +319,12 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
319
319
|
private _address?;
|
|
320
320
|
private _chainId?;
|
|
321
321
|
private _nodeFeatures;
|
|
322
|
+
/**
|
|
323
|
+
* `nodeId` from the `GET /info` performed during sign-in/restore, tagged with
|
|
324
|
+
* the host it came from. Callers that need the node DID (encryption-network
|
|
325
|
+
* admin invocations) reuse this instead of re-fetching `/info`.
|
|
326
|
+
*/
|
|
327
|
+
private _nodeInfoIdentity?;
|
|
322
328
|
private _lastActivationSkippedSpaceIds;
|
|
323
329
|
constructor(config: NodeUserAuthorizationConfig);
|
|
324
330
|
/**
|
|
@@ -387,6 +393,13 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
387
393
|
private requireTinyCloudHosts;
|
|
388
394
|
private get primaryTinyCloudHost();
|
|
389
395
|
get nodeFeatures(): string[];
|
|
396
|
+
/**
|
|
397
|
+
* The node DID reported by `GET /info` for `host`, if the sign-in (or
|
|
398
|
+
* restore) that populated it targeted that same host. Returns `undefined`
|
|
399
|
+
* for any other host, and for nodes whose `/info` omits `nodeId`, so callers
|
|
400
|
+
* fall back to fetching it themselves rather than using a foreign node's DID.
|
|
401
|
+
*/
|
|
402
|
+
nodeIdForHost(host: string): string | undefined;
|
|
390
403
|
get lastActivationSkippedSpaceIds(): string[];
|
|
391
404
|
/**
|
|
392
405
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
@@ -856,19 +869,9 @@ type SecretReadResult = {
|
|
|
856
869
|
} | {
|
|
857
870
|
status: "invalid_payload";
|
|
858
871
|
};
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
readonly spaceId: string;
|
|
862
|
-
readonly path: string;
|
|
863
|
-
readonly actions: readonly string[];
|
|
864
|
-
readonly expiresAt: Date;
|
|
865
|
-
}
|
|
866
|
-
interface OwnerDelegationReceipt {
|
|
872
|
+
type CreateOwnerDelegationParams = CreateOwnerDelegationParams$1;
|
|
873
|
+
interface OwnerDelegationReceipt extends OwnerDelegationReceipt$1 {
|
|
867
874
|
readonly delegation: Delegation;
|
|
868
|
-
/** Exact signed DAG-CBOR bytes submitted in the Authorization header. */
|
|
869
|
-
readonly signedDagCbor: Uint8Array;
|
|
870
|
-
/** Locally derived by the node WASM implementation; this is delegation identity. */
|
|
871
|
-
readonly delegationCid: string;
|
|
872
875
|
readonly nodeReceipt: {
|
|
873
876
|
/** Raw /delegate response CID: a commit-event id, not delegation identity. */
|
|
874
877
|
readonly commitEventCid?: string;
|
|
@@ -997,6 +1000,21 @@ interface RuntimePermissionGrantOptions {
|
|
|
997
1000
|
/** Override expiry. ms-format string ("7d", "1h") or raw milliseconds. */
|
|
998
1001
|
expiry?: string | number;
|
|
999
1002
|
}
|
|
1003
|
+
interface EnsureEncryptionNetworkOptions {
|
|
1004
|
+
/**
|
|
1005
|
+
* Skip the `GET /encryption/networks/{id}` existence probe and go straight
|
|
1006
|
+
* to the create.
|
|
1007
|
+
*
|
|
1008
|
+
* The probe pays for itself only when the network already exists. On a
|
|
1009
|
+
* freshly bootstrapped account it is a guaranteed 404, so it costs a round
|
|
1010
|
+
* trip on the cold sign-in path and saves nothing. Creating without it is
|
|
1011
|
+
* safe: the server answers `409 Conflict` if the network is already there,
|
|
1012
|
+
* which {@link TinyCloudNode.createEncryptionNetwork} resolves by reading the
|
|
1013
|
+
* existing descriptor. Set this only when the caller knows the account was
|
|
1014
|
+
* just provisioned.
|
|
1015
|
+
*/
|
|
1016
|
+
assumeMissing?: boolean;
|
|
1017
|
+
}
|
|
1000
1018
|
/**
|
|
1001
1019
|
* High-level TinyCloud API for Node.js environments.
|
|
1002
1020
|
*
|
|
@@ -1054,6 +1072,12 @@ declare class TinyCloudNode {
|
|
|
1054
1072
|
* so this avoids re-parsing the recap on every registration.
|
|
1055
1073
|
*/
|
|
1056
1074
|
private _recapOperationsCache?;
|
|
1075
|
+
/**
|
|
1076
|
+
* Owned space ids this sign-in has already confirmed are hosted. Consulted by
|
|
1077
|
+
* {@link ensureOwnedSpaceHostedById}; cleared on every {@link signIn} because
|
|
1078
|
+
* hosting is confirmed against the session that was active at the time.
|
|
1079
|
+
*/
|
|
1080
|
+
private readonly confirmedHostedSpaceIds;
|
|
1057
1081
|
/**
|
|
1058
1082
|
* TinyCloudSession captured by {@link restoreSession} when there's no
|
|
1059
1083
|
* auth-layer signer available (session-only mode used by OpenKey-backed
|
|
@@ -1262,6 +1286,22 @@ declare class TinyCloudNode {
|
|
|
1262
1286
|
private withAccountRegistryRetry;
|
|
1263
1287
|
private requestedEncryptionNetworkIds;
|
|
1264
1288
|
private ensureRequestedEncryptionNetworks;
|
|
1289
|
+
/**
|
|
1290
|
+
* Ensure one of this user's owned spaces is hosted, at most once per space
|
|
1291
|
+
* per sign-in.
|
|
1292
|
+
*
|
|
1293
|
+
* Account bootstrap funnels six calls through here (via
|
|
1294
|
+
* `AccountService.ensureAccountSpaceHosted`), and each one re-submits
|
|
1295
|
+
* `activateSessionWithHost` with the *primary* session. That session's recap
|
|
1296
|
+
* covers only `default` and `secrets`, so the account space appears in
|
|
1297
|
+
* neither `activated` nor `skipped` and the guard below returns immediately
|
|
1298
|
+
* — the repeat calls cannot change the outcome, they only cost round trips.
|
|
1299
|
+
*
|
|
1300
|
+
* The memo is per sign-in ({@link confirmedHostedSpaceIds} is cleared in
|
|
1301
|
+
* `signIn`) and only records confirmed successes. A wrong skip is
|
|
1302
|
+
* self-revealing: the next write to the space fails immediately and loudly
|
|
1303
|
+
* with `404 Space not found`.
|
|
1304
|
+
*/
|
|
1265
1305
|
private ensureOwnedSpaceHostedById;
|
|
1266
1306
|
/**
|
|
1267
1307
|
* Host one of this user's owned spaces by name (e.g. `"applications"`).
|
|
@@ -1472,6 +1512,14 @@ declare class TinyCloudNode {
|
|
|
1472
1512
|
*/
|
|
1473
1513
|
private requireEncryptionSession;
|
|
1474
1514
|
private createEncryptionCrypto;
|
|
1515
|
+
/**
|
|
1516
|
+
* The node DID for {@link config.host}.
|
|
1517
|
+
*
|
|
1518
|
+
* Sign-in already performs `GET /info` for the protocol-version check, and
|
|
1519
|
+
* that response carries `nodeId`, so reuse it rather than fetching `/info` a
|
|
1520
|
+
* second time. Only a value recorded for this exact host qualifies; older
|
|
1521
|
+
* nodes that omit `nodeId` fall through to the fetch.
|
|
1522
|
+
*/
|
|
1475
1523
|
private fetchNodeId;
|
|
1476
1524
|
private signRawNetworkAuthorization;
|
|
1477
1525
|
private fetchEncryptionNetworkAt;
|
|
@@ -1596,7 +1644,13 @@ declare class TinyCloudNode {
|
|
|
1596
1644
|
get encryption(): IEncryptionService;
|
|
1597
1645
|
getEncryptionNetwork(nameOrNetworkId?: string): Promise<NetworkDescriptor | null>;
|
|
1598
1646
|
createEncryptionNetwork(name?: string): Promise<NetworkDescriptor>;
|
|
1599
|
-
|
|
1647
|
+
/**
|
|
1648
|
+
* Ensure an encryption network exists, creating it if necessary.
|
|
1649
|
+
*
|
|
1650
|
+
* @param nameOrNetworkId - Network name or full `urn:tinycloud:encryption:` id.
|
|
1651
|
+
* @param options - See {@link EnsureEncryptionNetworkOptions}.
|
|
1652
|
+
*/
|
|
1653
|
+
ensureEncryptionNetwork(nameOrNetworkId?: string, options?: EnsureEncryptionNetworkOptions): Promise<NetworkDescriptor>;
|
|
1600
1654
|
/**
|
|
1601
1655
|
* App-facing secrets API backed by the `secrets` space vault.
|
|
1602
1656
|
*/
|
|
@@ -2178,4 +2232,4 @@ declare class WasmKeyProvider implements KeyProvider {
|
|
|
2178
2232
|
*/
|
|
2179
2233
|
declare function createWasmKeyProvider(sessionManager: SessionManagerWithListing): WasmKeyProvider;
|
|
2180
2234
|
|
|
2181
|
-
export { type AuthDelegationArtifact as A, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, FileSessionStorage as F, MemorySessionStorage as M, type NodeEventEmitterStrategy as N, type OwnerDelegationReceipt as O, type PortableDelegation as P, type RestorableSession as R, type SecretPermissionHint as S, TinyCloudNode as T, UnsupportedSessionRestoreError as U, type ValidatedRuntimeDelegation as V, WasmKeyProvider as W, type AuthRequestArtifact as a, type DelegateToResult as b, DelegatedAccess as c, type DelegationAuthority as d, NodeUserAuthorization as e, type NodeUserAuthorizationConfig as f, type RuntimeDelegationActivator as g, type RuntimePermissionGrantOptions as h, type SecretReadInput as i, type SecretReadResult as j, type SignStrategy as k, type TinyCloudNodeConfig as l, type WasmKeyProviderConfig as m, activateValidatedRuntimeDelegation as n, createWasmKeyProvider as o, defaultSignStrategy as p, deserializeDelegation as q, grantAuthRequest as r, serializeDelegation as s };
|
|
2235
|
+
export { type AuthDelegationArtifact as A, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, type EnsureEncryptionNetworkOptions as E, FileSessionStorage as F, MemorySessionStorage as M, type NodeEventEmitterStrategy as N, type OwnerDelegationReceipt as O, type PortableDelegation as P, type RestorableSession as R, type SecretPermissionHint as S, TinyCloudNode as T, UnsupportedSessionRestoreError as U, type ValidatedRuntimeDelegation as V, WasmKeyProvider as W, type AuthRequestArtifact as a, type DelegateToResult as b, DelegatedAccess as c, type DelegationAuthority as d, NodeUserAuthorization as e, type NodeUserAuthorizationConfig as f, type RuntimeDelegationActivator as g, type RuntimePermissionGrantOptions as h, type SecretReadInput as i, type SecretReadResult as j, type SignStrategy as k, type TinyCloudNodeConfig as l, type WasmKeyProviderConfig as m, activateValidatedRuntimeDelegation as n, createWasmKeyProvider as o, defaultSignStrategy as p, deserializeDelegation as q, grantAuthRequest as r, serializeDelegation as s };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignRequest, SignInOptions, Delegation, DelegatedResource, PermissionEntry, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, AccountService, RegisterOwnerSharePolicyParams, OwnerSharePolicyRegistrationReceipt, ShareDeliveryAuthorizationReceipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ResolvedDelegate, KeyProvider, JWK } from '@tinycloud/sdk-core';
|
|
1
|
+
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignRequest, SignInOptions, Delegation, DelegatedResource, PermissionEntry, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, INotificationHandler, IENSResolver, AccountService, RegisterOwnerSharePolicyParams, OwnerSharePolicyRegistrationReceipt, ShareDeliveryAuthorizationReceipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ResolvedDelegate, KeyProvider, JWK } from '@tinycloud/sdk-core';
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { InvokeFunction, InvokeAnyFunction } from '@tinycloud/sdk-services';
|
|
4
4
|
|
|
@@ -319,6 +319,12 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
319
319
|
private _address?;
|
|
320
320
|
private _chainId?;
|
|
321
321
|
private _nodeFeatures;
|
|
322
|
+
/**
|
|
323
|
+
* `nodeId` from the `GET /info` performed during sign-in/restore, tagged with
|
|
324
|
+
* the host it came from. Callers that need the node DID (encryption-network
|
|
325
|
+
* admin invocations) reuse this instead of re-fetching `/info`.
|
|
326
|
+
*/
|
|
327
|
+
private _nodeInfoIdentity?;
|
|
322
328
|
private _lastActivationSkippedSpaceIds;
|
|
323
329
|
constructor(config: NodeUserAuthorizationConfig);
|
|
324
330
|
/**
|
|
@@ -387,6 +393,13 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
387
393
|
private requireTinyCloudHosts;
|
|
388
394
|
private get primaryTinyCloudHost();
|
|
389
395
|
get nodeFeatures(): string[];
|
|
396
|
+
/**
|
|
397
|
+
* The node DID reported by `GET /info` for `host`, if the sign-in (or
|
|
398
|
+
* restore) that populated it targeted that same host. Returns `undefined`
|
|
399
|
+
* for any other host, and for nodes whose `/info` omits `nodeId`, so callers
|
|
400
|
+
* fall back to fetching it themselves rather than using a foreign node's DID.
|
|
401
|
+
*/
|
|
402
|
+
nodeIdForHost(host: string): string | undefined;
|
|
390
403
|
get lastActivationSkippedSpaceIds(): string[];
|
|
391
404
|
/**
|
|
392
405
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
@@ -856,19 +869,9 @@ type SecretReadResult = {
|
|
|
856
869
|
} | {
|
|
857
870
|
status: "invalid_payload";
|
|
858
871
|
};
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
readonly spaceId: string;
|
|
862
|
-
readonly path: string;
|
|
863
|
-
readonly actions: readonly string[];
|
|
864
|
-
readonly expiresAt: Date;
|
|
865
|
-
}
|
|
866
|
-
interface OwnerDelegationReceipt {
|
|
872
|
+
type CreateOwnerDelegationParams = CreateOwnerDelegationParams$1;
|
|
873
|
+
interface OwnerDelegationReceipt extends OwnerDelegationReceipt$1 {
|
|
867
874
|
readonly delegation: Delegation;
|
|
868
|
-
/** Exact signed DAG-CBOR bytes submitted in the Authorization header. */
|
|
869
|
-
readonly signedDagCbor: Uint8Array;
|
|
870
|
-
/** Locally derived by the node WASM implementation; this is delegation identity. */
|
|
871
|
-
readonly delegationCid: string;
|
|
872
875
|
readonly nodeReceipt: {
|
|
873
876
|
/** Raw /delegate response CID: a commit-event id, not delegation identity. */
|
|
874
877
|
readonly commitEventCid?: string;
|
|
@@ -997,6 +1000,21 @@ interface RuntimePermissionGrantOptions {
|
|
|
997
1000
|
/** Override expiry. ms-format string ("7d", "1h") or raw milliseconds. */
|
|
998
1001
|
expiry?: string | number;
|
|
999
1002
|
}
|
|
1003
|
+
interface EnsureEncryptionNetworkOptions {
|
|
1004
|
+
/**
|
|
1005
|
+
* Skip the `GET /encryption/networks/{id}` existence probe and go straight
|
|
1006
|
+
* to the create.
|
|
1007
|
+
*
|
|
1008
|
+
* The probe pays for itself only when the network already exists. On a
|
|
1009
|
+
* freshly bootstrapped account it is a guaranteed 404, so it costs a round
|
|
1010
|
+
* trip on the cold sign-in path and saves nothing. Creating without it is
|
|
1011
|
+
* safe: the server answers `409 Conflict` if the network is already there,
|
|
1012
|
+
* which {@link TinyCloudNode.createEncryptionNetwork} resolves by reading the
|
|
1013
|
+
* existing descriptor. Set this only when the caller knows the account was
|
|
1014
|
+
* just provisioned.
|
|
1015
|
+
*/
|
|
1016
|
+
assumeMissing?: boolean;
|
|
1017
|
+
}
|
|
1000
1018
|
/**
|
|
1001
1019
|
* High-level TinyCloud API for Node.js environments.
|
|
1002
1020
|
*
|
|
@@ -1054,6 +1072,12 @@ declare class TinyCloudNode {
|
|
|
1054
1072
|
* so this avoids re-parsing the recap on every registration.
|
|
1055
1073
|
*/
|
|
1056
1074
|
private _recapOperationsCache?;
|
|
1075
|
+
/**
|
|
1076
|
+
* Owned space ids this sign-in has already confirmed are hosted. Consulted by
|
|
1077
|
+
* {@link ensureOwnedSpaceHostedById}; cleared on every {@link signIn} because
|
|
1078
|
+
* hosting is confirmed against the session that was active at the time.
|
|
1079
|
+
*/
|
|
1080
|
+
private readonly confirmedHostedSpaceIds;
|
|
1057
1081
|
/**
|
|
1058
1082
|
* TinyCloudSession captured by {@link restoreSession} when there's no
|
|
1059
1083
|
* auth-layer signer available (session-only mode used by OpenKey-backed
|
|
@@ -1262,6 +1286,22 @@ declare class TinyCloudNode {
|
|
|
1262
1286
|
private withAccountRegistryRetry;
|
|
1263
1287
|
private requestedEncryptionNetworkIds;
|
|
1264
1288
|
private ensureRequestedEncryptionNetworks;
|
|
1289
|
+
/**
|
|
1290
|
+
* Ensure one of this user's owned spaces is hosted, at most once per space
|
|
1291
|
+
* per sign-in.
|
|
1292
|
+
*
|
|
1293
|
+
* Account bootstrap funnels six calls through here (via
|
|
1294
|
+
* `AccountService.ensureAccountSpaceHosted`), and each one re-submits
|
|
1295
|
+
* `activateSessionWithHost` with the *primary* session. That session's recap
|
|
1296
|
+
* covers only `default` and `secrets`, so the account space appears in
|
|
1297
|
+
* neither `activated` nor `skipped` and the guard below returns immediately
|
|
1298
|
+
* — the repeat calls cannot change the outcome, they only cost round trips.
|
|
1299
|
+
*
|
|
1300
|
+
* The memo is per sign-in ({@link confirmedHostedSpaceIds} is cleared in
|
|
1301
|
+
* `signIn`) and only records confirmed successes. A wrong skip is
|
|
1302
|
+
* self-revealing: the next write to the space fails immediately and loudly
|
|
1303
|
+
* with `404 Space not found`.
|
|
1304
|
+
*/
|
|
1265
1305
|
private ensureOwnedSpaceHostedById;
|
|
1266
1306
|
/**
|
|
1267
1307
|
* Host one of this user's owned spaces by name (e.g. `"applications"`).
|
|
@@ -1472,6 +1512,14 @@ declare class TinyCloudNode {
|
|
|
1472
1512
|
*/
|
|
1473
1513
|
private requireEncryptionSession;
|
|
1474
1514
|
private createEncryptionCrypto;
|
|
1515
|
+
/**
|
|
1516
|
+
* The node DID for {@link config.host}.
|
|
1517
|
+
*
|
|
1518
|
+
* Sign-in already performs `GET /info` for the protocol-version check, and
|
|
1519
|
+
* that response carries `nodeId`, so reuse it rather than fetching `/info` a
|
|
1520
|
+
* second time. Only a value recorded for this exact host qualifies; older
|
|
1521
|
+
* nodes that omit `nodeId` fall through to the fetch.
|
|
1522
|
+
*/
|
|
1475
1523
|
private fetchNodeId;
|
|
1476
1524
|
private signRawNetworkAuthorization;
|
|
1477
1525
|
private fetchEncryptionNetworkAt;
|
|
@@ -1596,7 +1644,13 @@ declare class TinyCloudNode {
|
|
|
1596
1644
|
get encryption(): IEncryptionService;
|
|
1597
1645
|
getEncryptionNetwork(nameOrNetworkId?: string): Promise<NetworkDescriptor | null>;
|
|
1598
1646
|
createEncryptionNetwork(name?: string): Promise<NetworkDescriptor>;
|
|
1599
|
-
|
|
1647
|
+
/**
|
|
1648
|
+
* Ensure an encryption network exists, creating it if necessary.
|
|
1649
|
+
*
|
|
1650
|
+
* @param nameOrNetworkId - Network name or full `urn:tinycloud:encryption:` id.
|
|
1651
|
+
* @param options - See {@link EnsureEncryptionNetworkOptions}.
|
|
1652
|
+
*/
|
|
1653
|
+
ensureEncryptionNetwork(nameOrNetworkId?: string, options?: EnsureEncryptionNetworkOptions): Promise<NetworkDescriptor>;
|
|
1600
1654
|
/**
|
|
1601
1655
|
* App-facing secrets API backed by the `secrets` space vault.
|
|
1602
1656
|
*/
|
|
@@ -2178,4 +2232,4 @@ declare class WasmKeyProvider implements KeyProvider {
|
|
|
2178
2232
|
*/
|
|
2179
2233
|
declare function createWasmKeyProvider(sessionManager: SessionManagerWithListing): WasmKeyProvider;
|
|
2180
2234
|
|
|
2181
|
-
export { type AuthDelegationArtifact as A, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, FileSessionStorage as F, MemorySessionStorage as M, type NodeEventEmitterStrategy as N, type OwnerDelegationReceipt as O, type PortableDelegation as P, type RestorableSession as R, type SecretPermissionHint as S, TinyCloudNode as T, UnsupportedSessionRestoreError as U, type ValidatedRuntimeDelegation as V, WasmKeyProvider as W, type AuthRequestArtifact as a, type DelegateToResult as b, DelegatedAccess as c, type DelegationAuthority as d, NodeUserAuthorization as e, type NodeUserAuthorizationConfig as f, type RuntimeDelegationActivator as g, type RuntimePermissionGrantOptions as h, type SecretReadInput as i, type SecretReadResult as j, type SignStrategy as k, type TinyCloudNodeConfig as l, type WasmKeyProviderConfig as m, activateValidatedRuntimeDelegation as n, createWasmKeyProvider as o, defaultSignStrategy as p, deserializeDelegation as q, grantAuthRequest as r, serializeDelegation as s };
|
|
2235
|
+
export { type AuthDelegationArtifact as A, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, type EnsureEncryptionNetworkOptions as E, FileSessionStorage as F, MemorySessionStorage as M, type NodeEventEmitterStrategy as N, type OwnerDelegationReceipt as O, type PortableDelegation as P, type RestorableSession as R, type SecretPermissionHint as S, TinyCloudNode as T, UnsupportedSessionRestoreError as U, type ValidatedRuntimeDelegation as V, WasmKeyProvider as W, type AuthRequestArtifact as a, type DelegateToResult as b, DelegatedAccess as c, type DelegationAuthority as d, NodeUserAuthorization as e, type NodeUserAuthorizationConfig as f, type RuntimeDelegationActivator as g, type RuntimePermissionGrantOptions as h, type SecretReadInput as i, type SecretReadResult as j, type SignStrategy as k, type TinyCloudNodeConfig as l, type WasmKeyProviderConfig as m, activateValidatedRuntimeDelegation as n, createWasmKeyProvider as o, defaultSignStrategy as p, deserializeDelegation as q, grantAuthRequest as r, serializeDelegation as s };
|
package/dist/core.cjs
CHANGED
|
@@ -551,6 +551,15 @@ var NodeUserAuthorization = class {
|
|
|
551
551
|
get nodeFeatures() {
|
|
552
552
|
return this._nodeFeatures;
|
|
553
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* The node DID reported by `GET /info` for `host`, if the sign-in (or
|
|
556
|
+
* restore) that populated it targeted that same host. Returns `undefined`
|
|
557
|
+
* for any other host, and for nodes whose `/info` omits `nodeId`, so callers
|
|
558
|
+
* fall back to fetching it themselves rather than using a foreign node's DID.
|
|
559
|
+
*/
|
|
560
|
+
nodeIdForHost(host) {
|
|
561
|
+
return this._nodeInfoIdentity?.host === host ? this._nodeInfoIdentity.nodeId : void 0;
|
|
562
|
+
}
|
|
554
563
|
get lastActivationSkippedSpaceIds() {
|
|
555
564
|
return [...this._lastActivationSkippedSpaceIds];
|
|
556
565
|
}
|
|
@@ -1020,11 +1029,13 @@ var NodeUserAuthorization = class {
|
|
|
1020
1029
|
this._tinyCloudSession = tinyCloudSession;
|
|
1021
1030
|
this._address = address;
|
|
1022
1031
|
this._chainId = chainId;
|
|
1032
|
+
const infoHost = this.primaryTinyCloudHost;
|
|
1023
1033
|
const nodeInfo = await (0, import_sdk_core3.checkNodeInfo)(
|
|
1024
|
-
|
|
1034
|
+
infoHost,
|
|
1025
1035
|
this.wasm.protocolVersion()
|
|
1026
1036
|
);
|
|
1027
1037
|
this._nodeFeatures = nodeInfo.features;
|
|
1038
|
+
this._nodeInfoIdentity = nodeInfo.nodeId ? { host: infoHost, nodeId: nodeInfo.nodeId } : void 0;
|
|
1028
1039
|
for (const ext of this.extensions) {
|
|
1029
1040
|
if (ext.afterSignIn) {
|
|
1030
1041
|
await ext.afterSignIn(clientSession);
|
|
@@ -1190,11 +1201,13 @@ var NodeUserAuthorization = class {
|
|
|
1190
1201
|
this._tinyCloudSession = tinyCloudSession;
|
|
1191
1202
|
this._address = address;
|
|
1192
1203
|
this._chainId = chainId;
|
|
1204
|
+
const infoHost = this.primaryTinyCloudHost;
|
|
1193
1205
|
const nodeInfo = await (0, import_sdk_core3.checkNodeInfo)(
|
|
1194
|
-
|
|
1206
|
+
infoHost,
|
|
1195
1207
|
this.wasm.protocolVersion()
|
|
1196
1208
|
);
|
|
1197
1209
|
this._nodeFeatures = nodeInfo.features;
|
|
1210
|
+
this._nodeInfoIdentity = nodeInfo.nodeId ? { host: infoHost, nodeId: nodeInfo.nodeId } : void 0;
|
|
1198
1211
|
for (const ext of this.extensions) {
|
|
1199
1212
|
if (ext.afterSignIn) {
|
|
1200
1213
|
await ext.afterSignIn(clientSession);
|
|
@@ -1890,19 +1903,87 @@ function persistedExpiry(value) {
|
|
|
1890
1903
|
function sameInstant(left, right) {
|
|
1891
1904
|
return left.getTime() === right.getTime();
|
|
1892
1905
|
}
|
|
1893
|
-
function
|
|
1894
|
-
|
|
1906
|
+
function ownerDelegationPermissions(params) {
|
|
1907
|
+
const hasPermissions = Object.prototype.hasOwnProperty.call(params, "permissions");
|
|
1908
|
+
const hasLegacy = Object.prototype.hasOwnProperty.call(params, "path") || Object.prototype.hasOwnProperty.call(params, "actions");
|
|
1909
|
+
if (hasPermissions === hasLegacy) {
|
|
1910
|
+
throw new Error("Owner delegation requires exactly one authority shape: path/actions or permissions");
|
|
1911
|
+
}
|
|
1912
|
+
const permissions = [];
|
|
1913
|
+
if (hasPermissions) {
|
|
1914
|
+
if (!Array.isArray(params.permissions)) {
|
|
1915
|
+
throw new Error("Owner delegation permissions are invalid");
|
|
1916
|
+
}
|
|
1917
|
+
permissions.push(...params.permissions.map((permission) => ({
|
|
1918
|
+
service: permission.service,
|
|
1919
|
+
path: permission.path,
|
|
1920
|
+
actions: [...permission.actions]
|
|
1921
|
+
})));
|
|
1922
|
+
} else {
|
|
1923
|
+
if (typeof params.path !== "string" || !Array.isArray(params.actions)) {
|
|
1924
|
+
throw new Error("Owner delegation requires bounded capabilities");
|
|
1925
|
+
}
|
|
1926
|
+
const byService = /* @__PURE__ */ new Map();
|
|
1927
|
+
for (const action of params.actions) {
|
|
1928
|
+
if (typeof action !== "string") {
|
|
1929
|
+
throw new Error("Owner delegation capabilities are unsupported");
|
|
1930
|
+
}
|
|
1931
|
+
const slash = action.indexOf("/");
|
|
1932
|
+
const service = slash === -1 ? "" : action.slice(0, slash);
|
|
1933
|
+
if (import_sdk_core8.SERVICE_LONG_TO_SHORT[service] === void 0) {
|
|
1934
|
+
throw new Error("Owner delegation capabilities are unsupported");
|
|
1935
|
+
}
|
|
1936
|
+
const actions = byService.get(service) ?? [];
|
|
1937
|
+
actions.push(action);
|
|
1938
|
+
byService.set(service, actions);
|
|
1939
|
+
}
|
|
1940
|
+
for (const [service, actions] of byService) {
|
|
1941
|
+
permissions.push({ service, path: params.path, actions });
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
if (permissions.length === 0 || permissions.length > 16) {
|
|
1945
|
+
throw new Error("Owner delegation requires bounded capabilities");
|
|
1946
|
+
}
|
|
1947
|
+
const resources = /* @__PURE__ */ new Set();
|
|
1948
|
+
for (const permission of permissions) {
|
|
1949
|
+
if (typeof permission.service !== "string" || import_sdk_core8.SERVICE_LONG_TO_SHORT[permission.service] === void 0 || typeof permission.path !== "string" || permission.path.length === 0 || permission.path.trim() !== permission.path || /[\u0000-\u001f\u007f\\*]/.test(permission.path) || !Array.isArray(permission.actions) || permission.actions.length === 0 || permission.actions.length > 32) {
|
|
1950
|
+
throw new Error("Owner delegation requires bounded capabilities");
|
|
1951
|
+
}
|
|
1952
|
+
const resourceKey = `${permission.service}\0${permission.path}`;
|
|
1953
|
+
if (resources.has(resourceKey)) {
|
|
1954
|
+
throw new Error("Owner delegation permissions contain duplicate resources");
|
|
1955
|
+
}
|
|
1956
|
+
resources.add(resourceKey);
|
|
1957
|
+
const actions = /* @__PURE__ */ new Set();
|
|
1958
|
+
for (const action of permission.actions) {
|
|
1959
|
+
if (typeof action !== "string" || !action.startsWith(`${permission.service}/`) || action.length === permission.service.length + 1 || actions.has(action)) {
|
|
1960
|
+
throw new Error("Owner delegation capabilities are unsupported");
|
|
1961
|
+
}
|
|
1962
|
+
actions.add(action);
|
|
1963
|
+
}
|
|
1964
|
+
if (permission.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE) {
|
|
1965
|
+
try {
|
|
1966
|
+
(0, import_sdk_core8.parseNetworkId)(permission.path);
|
|
1967
|
+
} catch {
|
|
1968
|
+
throw new Error("Owner delegation encryption permission requires a canonical network URN");
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
return permissions;
|
|
1973
|
+
}
|
|
1974
|
+
function ownerPermissionsToAbilities(permissions) {
|
|
1895
1975
|
const abilities = {};
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
if (
|
|
1899
|
-
|
|
1900
|
-
|
|
1976
|
+
const rawAbilities = {};
|
|
1977
|
+
for (const permission of permissions) {
|
|
1978
|
+
if (permission.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE) {
|
|
1979
|
+
rawAbilities[permission.path] = [...permission.actions];
|
|
1980
|
+
continue;
|
|
1981
|
+
}
|
|
1982
|
+
const shortService = import_sdk_core8.SERVICE_LONG_TO_SHORT[permission.service];
|
|
1901
1983
|
abilities[shortService] ?? (abilities[shortService] = {});
|
|
1902
|
-
|
|
1903
|
-
abilities[shortService][path].push(action);
|
|
1984
|
+
abilities[shortService][permission.path] = [...permission.actions];
|
|
1904
1985
|
}
|
|
1905
|
-
return
|
|
1986
|
+
return { abilities, rawAbilities };
|
|
1906
1987
|
}
|
|
1907
1988
|
function base64UrlEncode(bytes) {
|
|
1908
1989
|
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
@@ -2020,6 +2101,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2020
2101
|
this._baseSecrets = /* @__PURE__ */ new Map();
|
|
2021
2102
|
this._secrets = /* @__PURE__ */ new Map();
|
|
2022
2103
|
this.runtimePermissionGrants = [];
|
|
2104
|
+
/**
|
|
2105
|
+
* Owned space ids this sign-in has already confirmed are hosted. Consulted by
|
|
2106
|
+
* {@link ensureOwnedSpaceHostedById}; cleared on every {@link signIn} because
|
|
2107
|
+
* hosting is confirmed against the session that was active at the time.
|
|
2108
|
+
*/
|
|
2109
|
+
this.confirmedHostedSpaceIds = /* @__PURE__ */ new Set();
|
|
2023
2110
|
/**
|
|
2024
2111
|
* True when the last signIn() detected an interactive signer and skipped
|
|
2025
2112
|
* client-side bootstrap. Apps can read this to know whether bootstrap was
|
|
@@ -2416,6 +2503,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2416
2503
|
this._spaceService = void 0;
|
|
2417
2504
|
this._serviceContext = void 0;
|
|
2418
2505
|
this.runtimePermissionGrants = [];
|
|
2506
|
+
this.confirmedHostedSpaceIds.clear();
|
|
2419
2507
|
await this.tc.signIn(options);
|
|
2420
2508
|
this.syncResolvedHostFromAuth();
|
|
2421
2509
|
const oldGraph = this._serviceGraph;
|
|
@@ -2598,14 +2686,18 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2598
2686
|
}
|
|
2599
2687
|
if (step.kind === "seed-applications") {
|
|
2600
2688
|
const registered = await this.account.applications.register(
|
|
2601
|
-
step.manifests.length > 0 ? [...step.manifests] : import_sdk_core8.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST
|
|
2689
|
+
step.manifests.length > 0 ? [...step.manifests] : import_sdk_core8.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
|
|
2690
|
+
// Bootstrap only runs on an account with no registry records, so the
|
|
2691
|
+
// manifest-hash pre-read is definitionally a miss. Skip it; the write
|
|
2692
|
+
// it guards is an INSERT OR REPLACE and is safe to repeat.
|
|
2693
|
+
{ assumeUnregistered: true }
|
|
2602
2694
|
);
|
|
2603
2695
|
if (!registered.ok) {
|
|
2604
2696
|
throw new Error(`Failed to seed bootstrap applications: ${registered.error.message}`);
|
|
2605
2697
|
}
|
|
2606
2698
|
}
|
|
2607
2699
|
if (step.kind === "encryption-network-create") {
|
|
2608
|
-
await this.ensureEncryptionNetwork(step.networkId);
|
|
2700
|
+
await this.ensureEncryptionNetwork(step.networkId, { assumeMissing: true });
|
|
2609
2701
|
}
|
|
2610
2702
|
if (step.kind === "secret-records-schema") {
|
|
2611
2703
|
const db = this.sqlForSpace(step.spaceId).db(step.database);
|
|
@@ -2884,6 +2976,22 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2884
2976
|
await this.ensureEncryptionNetwork(networkId);
|
|
2885
2977
|
}
|
|
2886
2978
|
}
|
|
2979
|
+
/**
|
|
2980
|
+
* Ensure one of this user's owned spaces is hosted, at most once per space
|
|
2981
|
+
* per sign-in.
|
|
2982
|
+
*
|
|
2983
|
+
* Account bootstrap funnels six calls through here (via
|
|
2984
|
+
* `AccountService.ensureAccountSpaceHosted`), and each one re-submits
|
|
2985
|
+
* `activateSessionWithHost` with the *primary* session. That session's recap
|
|
2986
|
+
* covers only `default` and `secrets`, so the account space appears in
|
|
2987
|
+
* neither `activated` nor `skipped` and the guard below returns immediately
|
|
2988
|
+
* — the repeat calls cannot change the outcome, they only cost round trips.
|
|
2989
|
+
*
|
|
2990
|
+
* The memo is per sign-in ({@link confirmedHostedSpaceIds} is cleared in
|
|
2991
|
+
* `signIn`) and only records confirmed successes. A wrong skip is
|
|
2992
|
+
* self-revealing: the next write to the space fails immediately and loudly
|
|
2993
|
+
* with `404 Space not found`.
|
|
2994
|
+
*/
|
|
2887
2995
|
async ensureOwnedSpaceHostedById(spaceId) {
|
|
2888
2996
|
if (!this.auth) {
|
|
2889
2997
|
throw new Error("Owned space hosting requires wallet mode");
|
|
@@ -2892,12 +3000,16 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2892
3000
|
if (!session) {
|
|
2893
3001
|
throw new Error("Owned space hosting requires an active session");
|
|
2894
3002
|
}
|
|
3003
|
+
if (this.confirmedHostedSpaceIds.has(spaceId)) {
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
2895
3006
|
const host = this.hosts[0] ?? this.config.host;
|
|
2896
3007
|
if (!host) {
|
|
2897
3008
|
throw new Error("Owned space hosting requires a TinyCloud host");
|
|
2898
3009
|
}
|
|
2899
3010
|
const activation = await (0, import_sdk_core8.activateSessionWithHost)(host, session.delegationHeader);
|
|
2900
3011
|
if (activation.success && !activation.skipped?.includes(spaceId)) {
|
|
3012
|
+
this.confirmedHostedSpaceIds.add(spaceId);
|
|
2901
3013
|
return;
|
|
2902
3014
|
}
|
|
2903
3015
|
if (!activation.success && activation.status !== 404) {
|
|
@@ -2916,6 +3028,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2916
3028
|
`Failed to activate session after creating owned space ${spaceId}: ${retry.error ?? "space was skipped"}`
|
|
2917
3029
|
);
|
|
2918
3030
|
}
|
|
3031
|
+
this.confirmedHostedSpaceIds.add(spaceId);
|
|
2919
3032
|
}
|
|
2920
3033
|
/**
|
|
2921
3034
|
* Host one of this user's owned spaces by name (e.g. `"applications"`).
|
|
@@ -3238,6 +3351,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3238
3351
|
this.tc = stagedGraph.core;
|
|
3239
3352
|
this._recapOperationsCache = stagedPrimary.cache;
|
|
3240
3353
|
this.runtimePermissionGrants = stagedPrimary.grants;
|
|
3354
|
+
this.confirmedHostedSpaceIds.clear();
|
|
3241
3355
|
if (this.auth) {
|
|
3242
3356
|
this.auth.installRestoredSession(stagedManager, stagedTcSession, [stagedHost]);
|
|
3243
3357
|
this._restoredTcSession = void 0;
|
|
@@ -3820,7 +3934,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3820
3934
|
verifyNodeSignature: (nodeId, message, signature) => (0, import_sdk_core8.verifyDidKeyEd25519Signature)(nodeId, message, signature)
|
|
3821
3935
|
};
|
|
3822
3936
|
}
|
|
3937
|
+
/**
|
|
3938
|
+
* The node DID for {@link config.host}.
|
|
3939
|
+
*
|
|
3940
|
+
* Sign-in already performs `GET /info` for the protocol-version check, and
|
|
3941
|
+
* that response carries `nodeId`, so reuse it rather than fetching `/info` a
|
|
3942
|
+
* second time. Only a value recorded for this exact host qualifies; older
|
|
3943
|
+
* nodes that omit `nodeId` fall through to the fetch.
|
|
3944
|
+
*/
|
|
3823
3945
|
async fetchNodeId() {
|
|
3946
|
+
const cached = this.auth?.nodeIdForHost(this.config.host);
|
|
3947
|
+
if (cached) return cached;
|
|
3824
3948
|
const response = await fetch(`${this.config.host}/info`);
|
|
3825
3949
|
if (!response.ok) {
|
|
3826
3950
|
throw new Error(`Failed to fetch node info: HTTP ${response.status}`);
|
|
@@ -4276,21 +4400,29 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4276
4400
|
async createOwnerDelegation(params, assertActive) {
|
|
4277
4401
|
const assertOwnerGraphActive = assertActive ?? this._serviceGraph.assertActive.bind(this._serviceGraph);
|
|
4278
4402
|
assertOwnerGraphActive();
|
|
4279
|
-
if (!params.delegateDid.startsWith("did:key:")
|
|
4403
|
+
if (!params.delegateDid.startsWith("did:key:")) {
|
|
4280
4404
|
throw new Error("Owner delegation requires an external did:key audience and bounded capabilities");
|
|
4281
4405
|
}
|
|
4406
|
+
const permissions = ownerDelegationPermissions(params);
|
|
4282
4407
|
const now = /* @__PURE__ */ new Date();
|
|
4283
|
-
if (params.expiresAt.getTime() <= now.getTime() || params.expiresAt.getTime() - now.getTime() > import_sdk_core8.EXPIRY.MAX_MS) {
|
|
4408
|
+
if (!(params.expiresAt instanceof Date) || params.expiresAt.getTime() <= now.getTime() || params.expiresAt.getTime() - now.getTime() > import_sdk_core8.EXPIRY.MAX_MS) {
|
|
4284
4409
|
throw new Error("Owner delegation expiry must be explicit, future, and within EXPIRY.MAX_MS");
|
|
4285
4410
|
}
|
|
4286
4411
|
if (!this.signer) throw new Error("Owner wallet signer is required");
|
|
4287
4412
|
const session = this.currentTinyCloudSession();
|
|
4288
4413
|
if (!session) throw new Error("Owner session is required");
|
|
4289
|
-
const
|
|
4290
|
-
|
|
4414
|
+
const ownerDid = (0, import_sdk_core8.pkhDid)(session.address, session.chainId);
|
|
4415
|
+
for (const permission of permissions) {
|
|
4416
|
+
if (permission.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE && !(0, import_sdk_core8.principalDidEquals)((0, import_sdk_core8.parseNetworkId)(permission.path).ownerDid, ownerDid)) {
|
|
4417
|
+
throw new Error("Owner delegation cannot grant a foreign encryption network");
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
const { abilities, rawAbilities } = ownerPermissionsToAbilities(permissions);
|
|
4421
|
+
const primary = permissions[0];
|
|
4291
4422
|
const host = this.config.host;
|
|
4292
4423
|
const prepared = this.wasmBindings.prepareSession({
|
|
4293
4424
|
abilities,
|
|
4425
|
+
...Object.keys(rawAbilities).length === 0 ? {} : { rawAbilities },
|
|
4294
4426
|
address: this.wasmBindings.ensureEip55(session.address),
|
|
4295
4427
|
chainId: session.chainId,
|
|
4296
4428
|
domain: this.siweDomain,
|
|
@@ -4310,10 +4442,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4310
4442
|
const delegation = {
|
|
4311
4443
|
cid: delegationSession.delegationCid,
|
|
4312
4444
|
delegateDID: params.delegateDid,
|
|
4313
|
-
delegatorDID:
|
|
4445
|
+
delegatorDID: ownerDid,
|
|
4314
4446
|
spaceId: params.spaceId,
|
|
4315
|
-
path:
|
|
4316
|
-
actions: [...
|
|
4447
|
+
path: primary.path,
|
|
4448
|
+
actions: [...primary.actions],
|
|
4317
4449
|
expiry: params.expiresAt,
|
|
4318
4450
|
isRevoked: false,
|
|
4319
4451
|
allowSubDelegation: true,
|
|
@@ -4324,6 +4456,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4324
4456
|
delegation,
|
|
4325
4457
|
signedDagCbor: decodeAuthorizationBytes(delegationSession.delegationHeader.Authorization),
|
|
4326
4458
|
delegationCid: delegationSession.delegationCid,
|
|
4459
|
+
permissions,
|
|
4327
4460
|
nodeReceipt: {
|
|
4328
4461
|
commitEventCid: activation.commitEventCid,
|
|
4329
4462
|
activated: activation.activated ?? [],
|
|
@@ -4583,6 +4716,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4583
4716
|
body
|
|
4584
4717
|
)
|
|
4585
4718
|
});
|
|
4719
|
+
if (response.status === 409) {
|
|
4720
|
+
const existing = await this.getEncryptionNetwork(networkId);
|
|
4721
|
+
if (existing) return existing;
|
|
4722
|
+
throw new Error(
|
|
4723
|
+
`Encryption network ${networkId} already exists but could not be read back`
|
|
4724
|
+
);
|
|
4725
|
+
}
|
|
4586
4726
|
if (!response.ok) {
|
|
4587
4727
|
throw new Error(
|
|
4588
4728
|
`Failed to create encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
|
|
@@ -4591,11 +4731,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4591
4731
|
const created = await response.json();
|
|
4592
4732
|
return created.descriptor;
|
|
4593
4733
|
}
|
|
4594
|
-
|
|
4734
|
+
/**
|
|
4735
|
+
* Ensure an encryption network exists, creating it if necessary.
|
|
4736
|
+
*
|
|
4737
|
+
* @param nameOrNetworkId - Network name or full `urn:tinycloud:encryption:` id.
|
|
4738
|
+
* @param options - See {@link EnsureEncryptionNetworkOptions}.
|
|
4739
|
+
*/
|
|
4740
|
+
async ensureEncryptionNetwork(nameOrNetworkId = DEFAULT_ENCRYPTION_NETWORK_NAME, options = {}) {
|
|
4595
4741
|
const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4742
|
+
if (!options.assumeMissing) {
|
|
4743
|
+
const existing = await this.getEncryptionNetwork(networkId);
|
|
4744
|
+
if (existing) {
|
|
4745
|
+
return existing;
|
|
4746
|
+
}
|
|
4599
4747
|
}
|
|
4600
4748
|
const parsed = (0, import_sdk_core8.parseNetworkId)(networkId);
|
|
4601
4749
|
if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
|