@tinycloud/node-sdk 3.2.0-beta.2 → 3.2.0-beta.4
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-DjLtgeVT.d.cts → WasmKeyProvider-DjfRu9aL.d.cts} +162 -2
- package/dist/{core-DjLtgeVT.d.ts → WasmKeyProvider-DjfRu9aL.d.ts} +162 -2
- package/dist/authority-mTQEgN56.d.cts +97 -0
- package/dist/authority-mTQEgN56.d.ts +97 -0
- package/dist/core.cjs +1049 -443
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +13 -3
- package/dist/core.d.ts +13 -3
- package/dist/core.js +725 -115
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +2348 -494
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -4
- package/dist/index.d.ts +34 -4
- package/dist/index.js +1996 -128
- package/dist/index.js.map +1 -1
- package/dist/replication/authority.cjs +278 -0
- package/dist/replication/authority.cjs.map +1 -0
- package/dist/replication/authority.d.cts +3 -0
- package/dist/replication/authority.d.ts +3 -0
- package/dist/replication/authority.js +257 -0
- package/dist/replication/authority.js.map +1 -0
- package/dist/replication/runtime.cjs +224 -0
- package/dist/replication/runtime.cjs.map +1 -0
- package/dist/replication/runtime.d.cts +3 -0
- package/dist/replication/runtime.d.ts +3 -0
- package/dist/replication/runtime.js +189 -0
- package/dist/replication/runtime.js.map +1 -0
- package/dist/runtime-DyYwHW8j.d.cts +64 -0
- package/dist/runtime-DyYwHW8j.d.ts +64 -0
- package/package.json +25 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _tinycloud_sdk_core from '@tinycloud/sdk-core';
|
|
2
|
-
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignRequest, SpaceHostResult, SignInOptions, CapabilityPresentationEnvelopeV1, Delegation, DelegatedResource,
|
|
2
|
+
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ReplicationOptions, ClientSession, TinyCloudSession, PermissionEntry, Extension, SignRequest, SpaceHostResult, SignInOptions, CapabilityPresentationEnvelopeV1, Delegation, DelegatedResource, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, INotificationHandler, IENSResolver, KVReplicaStorage, AccountService, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate, KeyProvider, JWK } from '@tinycloud/sdk-core';
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
4
|
import { InvokeFunction, InvokeAnyFunction } from '@tinycloud/sdk-services';
|
|
5
5
|
|
|
@@ -242,6 +242,14 @@ interface NodeUserAuthorizationConfig {
|
|
|
242
242
|
capabilityRequest?: ComposedManifestRequest;
|
|
243
243
|
/** Include canonical account registry read/create-update/list permissions when composing `manifest` and plain sign-in. Default true. */
|
|
244
244
|
includeAccountRegistryPermissions?: boolean;
|
|
245
|
+
/**
|
|
246
|
+
* Replication sign-in augmentation (TC-858 §4.1): prefixes whose reads a
|
|
247
|
+
* local replica may serve. For each prefix the session request gains one
|
|
248
|
+
* `kv` entry `{get, sync}` on the primary space — but only where an
|
|
249
|
+
* unrestricted `get` covering it is already requested. Storage and
|
|
250
|
+
* scheduling never reach this layer.
|
|
251
|
+
*/
|
|
252
|
+
replication?: Pick<ReplicationOptions, "enabled" | "prefixes" | "allowSecrets">;
|
|
245
253
|
}
|
|
246
254
|
interface CreateBootstrapSessionOptions {
|
|
247
255
|
spaceId: string;
|
|
@@ -301,6 +309,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
301
309
|
private readonly expectedNodeDid?;
|
|
302
310
|
private readonly localNodeIdentityStore?;
|
|
303
311
|
private readonly enablePublicSpace;
|
|
312
|
+
private readonly replication?;
|
|
304
313
|
private readonly nonce?;
|
|
305
314
|
private readonly siweConfig?;
|
|
306
315
|
private readonly wasm;
|
|
@@ -430,6 +439,50 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
430
439
|
*/
|
|
431
440
|
private getCapabilityRequest;
|
|
432
441
|
private resolveSpaceName;
|
|
442
|
+
/**
|
|
443
|
+
* The plain-session primary abilities: `defaultActions` (the shared table)
|
|
444
|
+
* unless the primary space IS the account space, where account-registry
|
|
445
|
+
* permissions merge into a private clone so the shared table is never
|
|
446
|
+
* mutated. Shared between `resolveSignInCapabilities` and
|
|
447
|
+
* `signInPermissionInputs` so sign-in and `replicationSignInEntries`
|
|
448
|
+
* can't disagree (§4.6).
|
|
449
|
+
*/
|
|
450
|
+
private primaryActionsForSignIn;
|
|
451
|
+
/**
|
|
452
|
+
* The abilities a `spacePrefix: "secrets"` plain session actually requests
|
|
453
|
+
* for its primary space: the vault-secrets subtree only — the
|
|
454
|
+
* `defaultActions` root `get` is REPLACED, not merged (sign-in installs
|
|
455
|
+
* this map under the primary space id). Shared between
|
|
456
|
+
* `resolveSignInCapabilities` and `signInPermissionInputs` so the
|
|
457
|
+
* replication augmentation measures coverage against the effective
|
|
458
|
+
* pre-replication request, never the uninstalled `primaryActions` (§4.1).
|
|
459
|
+
*/
|
|
460
|
+
private secretsPrimaryAbilities;
|
|
461
|
+
/**
|
|
462
|
+
* The effective sign-in request as `PermissionEntry`s plus the resolved
|
|
463
|
+
* primary space id — the inputs to the replication augmentation (§4.1).
|
|
464
|
+
* `resolveSignInCapabilities` merges the augmented entries into its
|
|
465
|
+
* abilities; `replicationSignInEntries()` returns them verbatim, so the
|
|
466
|
+
* entries the SIWE recap carries and the restore check sees are the same.
|
|
467
|
+
*/
|
|
468
|
+
private signInPermissionInputs;
|
|
469
|
+
/**
|
|
470
|
+
* Merge replication augmentation entries into a space's abilities map
|
|
471
|
+
* without mutating shared tables (`defaultActions` may back the base map):
|
|
472
|
+
* the primary entry in `spaceAbilities` is replaced with a copy whose `kv`
|
|
473
|
+
* paths gain `get`/`sync`. Returns the merged map for `abilities`.
|
|
474
|
+
*/
|
|
475
|
+
private mergeReplicationEntries;
|
|
476
|
+
/**
|
|
477
|
+
* The replication entries this authorization's sign-in request carries
|
|
478
|
+
* for the signed-in or restored address (TC-858 §4.1/§4.6): the output of
|
|
479
|
+
* the same augmentation `resolveSignInCapabilities` runs — one
|
|
480
|
+
* `{tinycloud.kv, primarySpace, prefix, [get, sync]}` per configured
|
|
481
|
+
* prefix that already has an unrestricted covering `get` and passes the
|
|
482
|
+
* secrets opt-in gate. Empty when replication is off or no address is
|
|
483
|
+
* known. Pure.
|
|
484
|
+
*/
|
|
485
|
+
replicationSignInEntries(): PermissionEntry[];
|
|
433
486
|
private defaultEncryptionNetworkId;
|
|
434
487
|
private resolveSignInCapabilities;
|
|
435
488
|
/**
|
|
@@ -470,7 +523,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
470
523
|
* keeps its HTTP status (e.g. a typed 401/403) instead of collapsing to
|
|
471
524
|
* `false`.
|
|
472
525
|
*/
|
|
473
|
-
hostOwnedSpaceResult(spaceId: string, purpose?: SignRequest["purpose"]): Promise<SpaceHostResult>;
|
|
526
|
+
hostOwnedSpaceResult(spaceId: string, purpose?: SignRequest["purpose"], signal?: AbortSignal): Promise<SpaceHostResult>;
|
|
474
527
|
/**
|
|
475
528
|
* Ensure the user's space exists on the TinyCloud server.
|
|
476
529
|
* Creates the space if it doesn't exist and autoCreateSpace is enabled.
|
|
@@ -1197,6 +1250,11 @@ interface TinyCloudNodeConfig {
|
|
|
1197
1250
|
autoBootstrapAccount?: boolean;
|
|
1198
1251
|
/** Default-off service telemetry. */
|
|
1199
1252
|
telemetry?: TelemetryConfig;
|
|
1253
|
+
/** Optional read-through replica configuration; disabled unless explicitly enabled. */
|
|
1254
|
+
replication?: ReplicationOptions & {
|
|
1255
|
+
storage: KVReplicaStorage;
|
|
1256
|
+
mode?: "background" | "foreground";
|
|
1257
|
+
};
|
|
1200
1258
|
}
|
|
1201
1259
|
/**
|
|
1202
1260
|
* Options for {@link TinyCloudNode.delegateTo}.
|
|
@@ -1263,6 +1321,56 @@ interface EnsureEncryptionNetworkOptions {
|
|
|
1263
1321
|
*/
|
|
1264
1322
|
assumeMissing?: boolean;
|
|
1265
1323
|
}
|
|
1324
|
+
interface RuntimePermissionOperation {
|
|
1325
|
+
spaceId?: string;
|
|
1326
|
+
resource?: string;
|
|
1327
|
+
service: string;
|
|
1328
|
+
path: string;
|
|
1329
|
+
action: string;
|
|
1330
|
+
/** Exact signed ReCap attenuation for this action, if any. */
|
|
1331
|
+
caveats?: Record<string, unknown>[];
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* The parent `delegateTo` would sign under (TC-858 §4.3): the session's own
|
|
1335
|
+
* delegation CID on the session path, or the selected runtime grant's
|
|
1336
|
+
* session CID on the runtime path. Refusals classify why no authority can
|
|
1337
|
+
* be derived; `expiredAt`/`missing`/`granted`/`caveated` let `delegateTo`
|
|
1338
|
+
* reproduce its exact typed errors from the same decision.
|
|
1339
|
+
*/
|
|
1340
|
+
type DelegationPlan = {
|
|
1341
|
+
path: "session";
|
|
1342
|
+
parentCid: string;
|
|
1343
|
+
expiresAt: number;
|
|
1344
|
+
effectiveExpiration: Date;
|
|
1345
|
+
} | {
|
|
1346
|
+
path: "runtime";
|
|
1347
|
+
parentCid: string;
|
|
1348
|
+
expiresAt: number;
|
|
1349
|
+
effectiveExpiration: Date;
|
|
1350
|
+
grant: RuntimePermissionGrant;
|
|
1351
|
+
operations: RuntimePermissionOperation[];
|
|
1352
|
+
} | {
|
|
1353
|
+
refused: "NOT_COVERED" | "CAVEATED_AUTHORITY" | "SESSION_EXPIRING";
|
|
1354
|
+
expiredAt?: Date;
|
|
1355
|
+
missing?: PermissionEntry[];
|
|
1356
|
+
granted?: PermissionEntry[];
|
|
1357
|
+
caveated?: PermissionEntry[];
|
|
1358
|
+
};
|
|
1359
|
+
interface RuntimePermissionGrant {
|
|
1360
|
+
session: ServiceSession;
|
|
1361
|
+
delegation: PortableDelegation;
|
|
1362
|
+
operations: RuntimePermissionOperation[];
|
|
1363
|
+
expiresAt: Date;
|
|
1364
|
+
/**
|
|
1365
|
+
* Where this grant came from. Drives precedence in
|
|
1366
|
+
* {@link TinyCloudNode.findGrantForOperations} (a `"primary"` grant — the
|
|
1367
|
+
* synthetic representation of the base session's own recap — always
|
|
1368
|
+
* out-ranks other covering grants) and gates the public-surface guardrails
|
|
1369
|
+
* that must never surface the synthetic primary grant. Optional so existing
|
|
1370
|
+
* test constructors and older call sites remain valid.
|
|
1371
|
+
*/
|
|
1372
|
+
provenance?: "primary" | "bootstrap" | "delegated" | "runtime";
|
|
1373
|
+
}
|
|
1266
1374
|
/**
|
|
1267
1375
|
* High-level TinyCloud API for Node.js environments.
|
|
1268
1376
|
*
|
|
@@ -1314,6 +1422,11 @@ declare class TinyCloudNode {
|
|
|
1314
1422
|
private _serviceGraph;
|
|
1315
1423
|
private _serviceContext?;
|
|
1316
1424
|
private _kv?;
|
|
1425
|
+
private readonly replicationRuntime?;
|
|
1426
|
+
private replicationRuntimeInstance?;
|
|
1427
|
+
private replicationDelegateSession?;
|
|
1428
|
+
private replicationScopeError?;
|
|
1429
|
+
private readonly replicationControl?;
|
|
1317
1430
|
private _sql?;
|
|
1318
1431
|
private _duckdb?;
|
|
1319
1432
|
private _hooks?;
|
|
@@ -1351,6 +1464,8 @@ declare class TinyCloudNode {
|
|
|
1351
1464
|
private readonly confirmedHostedSpaceIds;
|
|
1352
1465
|
/** Serializes account-registry writes for the active node instance. */
|
|
1353
1466
|
private accountRegistryTail;
|
|
1467
|
+
/** Bounds best-effort registry work on the sign-in critical path. */
|
|
1468
|
+
private accountRegistryDeadlineMs;
|
|
1354
1469
|
private pendingAccountRegistrySync?;
|
|
1355
1470
|
/**
|
|
1356
1471
|
* TinyCloudSession captured by {@link restoreSession} when there's no
|
|
@@ -1569,6 +1684,7 @@ declare class TinyCloudNode {
|
|
|
1569
1684
|
*/
|
|
1570
1685
|
private registerPrimarySessionGrant;
|
|
1571
1686
|
private writeManifestRegistryRecords;
|
|
1687
|
+
private createAccountRegistryServices;
|
|
1572
1688
|
private scheduleAccountRegistrySync;
|
|
1573
1689
|
private enqueueAccountRegistryOperation;
|
|
1574
1690
|
/**
|
|
@@ -1823,6 +1939,7 @@ declare class TinyCloudNode {
|
|
|
1823
1939
|
* @internal
|
|
1824
1940
|
*/
|
|
1825
1941
|
private initializeServices;
|
|
1942
|
+
private attachReplicationKV;
|
|
1826
1943
|
private createSpaceScopedKVService;
|
|
1827
1944
|
getDefaultEncryptionNetworkId(name?: string): string;
|
|
1828
1945
|
getEncryptionNetworkIdForSpace(spaceId: string, name?: string): string;
|
|
@@ -2282,6 +2399,42 @@ declare class TinyCloudNode {
|
|
|
2282
2399
|
* delegation.
|
|
2283
2400
|
*/
|
|
2284
2401
|
delegateTo(did: string, permissions: PermissionEntry[], options?: DelegateToOptions): Promise<DelegateToResult>;
|
|
2402
|
+
/**
|
|
2403
|
+
* What `delegateTo` would select for `entries`, without signing or any
|
|
2404
|
+
* network call (TC-858 plan v3 §4.3): the session path when the signed
|
|
2405
|
+
* recap covers every entry, the runtime-grant path otherwise, or a
|
|
2406
|
+
* refusal. A refusal of `CAVEATED_AUTHORITY` means coverage exists only
|
|
2407
|
+
* through caveated branches, which the action-only WASM child-delegation
|
|
2408
|
+
* boundary cannot preserve — replication never derives authority through
|
|
2409
|
+
* them. `expiredAt`/`missing`/`granted`/`caveated` carry the payload
|
|
2410
|
+
* `delegateTo` turns back into its typed errors.
|
|
2411
|
+
* @internal
|
|
2412
|
+
*/
|
|
2413
|
+
private planDerivation;
|
|
2414
|
+
/**
|
|
2415
|
+
* The plan `delegateTo(device, entries)` would follow, as a pure lookup:
|
|
2416
|
+
* no WASM sign and no `POST /delegate`. Backs
|
|
2417
|
+
* `ReplicationAuthority.plan` (and `mint` inside it) so a predicted
|
|
2418
|
+
* parent and expiry can never disagree with what a mint would use (§4.3,
|
|
2419
|
+
* §4.4). Session expiry inside the 60 s margin refuses with
|
|
2420
|
+
* `SESSION_EXPIRING`; the same check delegateTo performs.
|
|
2421
|
+
* @internal
|
|
2422
|
+
*/
|
|
2423
|
+
planDelegation(entries: PermissionEntry[], options?: {
|
|
2424
|
+
expiry?: string | number;
|
|
2425
|
+
}): DelegationPlan;
|
|
2426
|
+
/**
|
|
2427
|
+
* The replication entries this node's sign-in request carries for the
|
|
2428
|
+
* current replication config and the signed-in or restored address: the
|
|
2429
|
+
* output of the same augmentation step `resolveSignInCapabilities` runs,
|
|
2430
|
+
* with the unrestricted-get and secrets gates applied (§4.1, §4.6).
|
|
2431
|
+
* Empty when replication is off or no address is known. Pure.
|
|
2432
|
+
*/
|
|
2433
|
+
replicationSignInEntries(): PermissionEntry[];
|
|
2434
|
+
private replicationAuthority;
|
|
2435
|
+
private bindReplicationRuntime;
|
|
2436
|
+
/** Stable control facade for this node's optional replication runtime. */
|
|
2437
|
+
get replication(): ReplicationControl | undefined;
|
|
2285
2438
|
/**
|
|
2286
2439
|
* Materialize one manifest-declared delegation using the current session key.
|
|
2287
2440
|
* Delivery is intentionally out of band; callers decide how to transmit the
|
|
@@ -2325,6 +2478,13 @@ declare class TinyCloudNode {
|
|
|
2325
2478
|
* it only accepts action maps, so reject the selected constrained branch.
|
|
2326
2479
|
*/
|
|
2327
2480
|
private assertRuntimeGrantCaveatsPreservable;
|
|
2481
|
+
/**
|
|
2482
|
+
* The entries of `grant` that cover a requested operation while carrying
|
|
2483
|
+
* caveats — the branches {@link assertRuntimeGrantCaveatsPreservable}
|
|
2484
|
+
* rejects and {@link planDerivation} classifies as `CAVEATED_AUTHORITY`.
|
|
2485
|
+
* Shared so the pure plan and the mint path can't disagree.
|
|
2486
|
+
*/
|
|
2487
|
+
private caveatedRuntimeGrantEntries;
|
|
2328
2488
|
/** Reject caveated parent branches before action-only child signing. */
|
|
2329
2489
|
private assertPortableDelegationCaveatsPreservable;
|
|
2330
2490
|
private shortServiceName;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _tinycloud_sdk_core from '@tinycloud/sdk-core';
|
|
2
|
-
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ClientSession, TinyCloudSession, Extension, SignRequest, SpaceHostResult, SignInOptions, CapabilityPresentationEnvelopeV1, Delegation, DelegatedResource,
|
|
2
|
+
import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ReplicationOptions, ClientSession, TinyCloudSession, PermissionEntry, Extension, SignRequest, SpaceHostResult, SignInOptions, CapabilityPresentationEnvelopeV1, Delegation, DelegatedResource, TelemetryConfig, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, INotificationHandler, IENSResolver, KVReplicaStorage, AccountService, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate, KeyProvider, JWK } from '@tinycloud/sdk-core';
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
4
|
import { InvokeFunction, InvokeAnyFunction } from '@tinycloud/sdk-services';
|
|
5
5
|
|
|
@@ -242,6 +242,14 @@ interface NodeUserAuthorizationConfig {
|
|
|
242
242
|
capabilityRequest?: ComposedManifestRequest;
|
|
243
243
|
/** Include canonical account registry read/create-update/list permissions when composing `manifest` and plain sign-in. Default true. */
|
|
244
244
|
includeAccountRegistryPermissions?: boolean;
|
|
245
|
+
/**
|
|
246
|
+
* Replication sign-in augmentation (TC-858 §4.1): prefixes whose reads a
|
|
247
|
+
* local replica may serve. For each prefix the session request gains one
|
|
248
|
+
* `kv` entry `{get, sync}` on the primary space — but only where an
|
|
249
|
+
* unrestricted `get` covering it is already requested. Storage and
|
|
250
|
+
* scheduling never reach this layer.
|
|
251
|
+
*/
|
|
252
|
+
replication?: Pick<ReplicationOptions, "enabled" | "prefixes" | "allowSecrets">;
|
|
245
253
|
}
|
|
246
254
|
interface CreateBootstrapSessionOptions {
|
|
247
255
|
spaceId: string;
|
|
@@ -301,6 +309,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
301
309
|
private readonly expectedNodeDid?;
|
|
302
310
|
private readonly localNodeIdentityStore?;
|
|
303
311
|
private readonly enablePublicSpace;
|
|
312
|
+
private readonly replication?;
|
|
304
313
|
private readonly nonce?;
|
|
305
314
|
private readonly siweConfig?;
|
|
306
315
|
private readonly wasm;
|
|
@@ -430,6 +439,50 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
430
439
|
*/
|
|
431
440
|
private getCapabilityRequest;
|
|
432
441
|
private resolveSpaceName;
|
|
442
|
+
/**
|
|
443
|
+
* The plain-session primary abilities: `defaultActions` (the shared table)
|
|
444
|
+
* unless the primary space IS the account space, where account-registry
|
|
445
|
+
* permissions merge into a private clone so the shared table is never
|
|
446
|
+
* mutated. Shared between `resolveSignInCapabilities` and
|
|
447
|
+
* `signInPermissionInputs` so sign-in and `replicationSignInEntries`
|
|
448
|
+
* can't disagree (§4.6).
|
|
449
|
+
*/
|
|
450
|
+
private primaryActionsForSignIn;
|
|
451
|
+
/**
|
|
452
|
+
* The abilities a `spacePrefix: "secrets"` plain session actually requests
|
|
453
|
+
* for its primary space: the vault-secrets subtree only — the
|
|
454
|
+
* `defaultActions` root `get` is REPLACED, not merged (sign-in installs
|
|
455
|
+
* this map under the primary space id). Shared between
|
|
456
|
+
* `resolveSignInCapabilities` and `signInPermissionInputs` so the
|
|
457
|
+
* replication augmentation measures coverage against the effective
|
|
458
|
+
* pre-replication request, never the uninstalled `primaryActions` (§4.1).
|
|
459
|
+
*/
|
|
460
|
+
private secretsPrimaryAbilities;
|
|
461
|
+
/**
|
|
462
|
+
* The effective sign-in request as `PermissionEntry`s plus the resolved
|
|
463
|
+
* primary space id — the inputs to the replication augmentation (§4.1).
|
|
464
|
+
* `resolveSignInCapabilities` merges the augmented entries into its
|
|
465
|
+
* abilities; `replicationSignInEntries()` returns them verbatim, so the
|
|
466
|
+
* entries the SIWE recap carries and the restore check sees are the same.
|
|
467
|
+
*/
|
|
468
|
+
private signInPermissionInputs;
|
|
469
|
+
/**
|
|
470
|
+
* Merge replication augmentation entries into a space's abilities map
|
|
471
|
+
* without mutating shared tables (`defaultActions` may back the base map):
|
|
472
|
+
* the primary entry in `spaceAbilities` is replaced with a copy whose `kv`
|
|
473
|
+
* paths gain `get`/`sync`. Returns the merged map for `abilities`.
|
|
474
|
+
*/
|
|
475
|
+
private mergeReplicationEntries;
|
|
476
|
+
/**
|
|
477
|
+
* The replication entries this authorization's sign-in request carries
|
|
478
|
+
* for the signed-in or restored address (TC-858 §4.1/§4.6): the output of
|
|
479
|
+
* the same augmentation `resolveSignInCapabilities` runs — one
|
|
480
|
+
* `{tinycloud.kv, primarySpace, prefix, [get, sync]}` per configured
|
|
481
|
+
* prefix that already has an unrestricted covering `get` and passes the
|
|
482
|
+
* secrets opt-in gate. Empty when replication is off or no address is
|
|
483
|
+
* known. Pure.
|
|
484
|
+
*/
|
|
485
|
+
replicationSignInEntries(): PermissionEntry[];
|
|
433
486
|
private defaultEncryptionNetworkId;
|
|
434
487
|
private resolveSignInCapabilities;
|
|
435
488
|
/**
|
|
@@ -470,7 +523,7 @@ declare class NodeUserAuthorization implements IUserAuthorization {
|
|
|
470
523
|
* keeps its HTTP status (e.g. a typed 401/403) instead of collapsing to
|
|
471
524
|
* `false`.
|
|
472
525
|
*/
|
|
473
|
-
hostOwnedSpaceResult(spaceId: string, purpose?: SignRequest["purpose"]): Promise<SpaceHostResult>;
|
|
526
|
+
hostOwnedSpaceResult(spaceId: string, purpose?: SignRequest["purpose"], signal?: AbortSignal): Promise<SpaceHostResult>;
|
|
474
527
|
/**
|
|
475
528
|
* Ensure the user's space exists on the TinyCloud server.
|
|
476
529
|
* Creates the space if it doesn't exist and autoCreateSpace is enabled.
|
|
@@ -1197,6 +1250,11 @@ interface TinyCloudNodeConfig {
|
|
|
1197
1250
|
autoBootstrapAccount?: boolean;
|
|
1198
1251
|
/** Default-off service telemetry. */
|
|
1199
1252
|
telemetry?: TelemetryConfig;
|
|
1253
|
+
/** Optional read-through replica configuration; disabled unless explicitly enabled. */
|
|
1254
|
+
replication?: ReplicationOptions & {
|
|
1255
|
+
storage: KVReplicaStorage;
|
|
1256
|
+
mode?: "background" | "foreground";
|
|
1257
|
+
};
|
|
1200
1258
|
}
|
|
1201
1259
|
/**
|
|
1202
1260
|
* Options for {@link TinyCloudNode.delegateTo}.
|
|
@@ -1263,6 +1321,56 @@ interface EnsureEncryptionNetworkOptions {
|
|
|
1263
1321
|
*/
|
|
1264
1322
|
assumeMissing?: boolean;
|
|
1265
1323
|
}
|
|
1324
|
+
interface RuntimePermissionOperation {
|
|
1325
|
+
spaceId?: string;
|
|
1326
|
+
resource?: string;
|
|
1327
|
+
service: string;
|
|
1328
|
+
path: string;
|
|
1329
|
+
action: string;
|
|
1330
|
+
/** Exact signed ReCap attenuation for this action, if any. */
|
|
1331
|
+
caveats?: Record<string, unknown>[];
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* The parent `delegateTo` would sign under (TC-858 §4.3): the session's own
|
|
1335
|
+
* delegation CID on the session path, or the selected runtime grant's
|
|
1336
|
+
* session CID on the runtime path. Refusals classify why no authority can
|
|
1337
|
+
* be derived; `expiredAt`/`missing`/`granted`/`caveated` let `delegateTo`
|
|
1338
|
+
* reproduce its exact typed errors from the same decision.
|
|
1339
|
+
*/
|
|
1340
|
+
type DelegationPlan = {
|
|
1341
|
+
path: "session";
|
|
1342
|
+
parentCid: string;
|
|
1343
|
+
expiresAt: number;
|
|
1344
|
+
effectiveExpiration: Date;
|
|
1345
|
+
} | {
|
|
1346
|
+
path: "runtime";
|
|
1347
|
+
parentCid: string;
|
|
1348
|
+
expiresAt: number;
|
|
1349
|
+
effectiveExpiration: Date;
|
|
1350
|
+
grant: RuntimePermissionGrant;
|
|
1351
|
+
operations: RuntimePermissionOperation[];
|
|
1352
|
+
} | {
|
|
1353
|
+
refused: "NOT_COVERED" | "CAVEATED_AUTHORITY" | "SESSION_EXPIRING";
|
|
1354
|
+
expiredAt?: Date;
|
|
1355
|
+
missing?: PermissionEntry[];
|
|
1356
|
+
granted?: PermissionEntry[];
|
|
1357
|
+
caveated?: PermissionEntry[];
|
|
1358
|
+
};
|
|
1359
|
+
interface RuntimePermissionGrant {
|
|
1360
|
+
session: ServiceSession;
|
|
1361
|
+
delegation: PortableDelegation;
|
|
1362
|
+
operations: RuntimePermissionOperation[];
|
|
1363
|
+
expiresAt: Date;
|
|
1364
|
+
/**
|
|
1365
|
+
* Where this grant came from. Drives precedence in
|
|
1366
|
+
* {@link TinyCloudNode.findGrantForOperations} (a `"primary"` grant — the
|
|
1367
|
+
* synthetic representation of the base session's own recap — always
|
|
1368
|
+
* out-ranks other covering grants) and gates the public-surface guardrails
|
|
1369
|
+
* that must never surface the synthetic primary grant. Optional so existing
|
|
1370
|
+
* test constructors and older call sites remain valid.
|
|
1371
|
+
*/
|
|
1372
|
+
provenance?: "primary" | "bootstrap" | "delegated" | "runtime";
|
|
1373
|
+
}
|
|
1266
1374
|
/**
|
|
1267
1375
|
* High-level TinyCloud API for Node.js environments.
|
|
1268
1376
|
*
|
|
@@ -1314,6 +1422,11 @@ declare class TinyCloudNode {
|
|
|
1314
1422
|
private _serviceGraph;
|
|
1315
1423
|
private _serviceContext?;
|
|
1316
1424
|
private _kv?;
|
|
1425
|
+
private readonly replicationRuntime?;
|
|
1426
|
+
private replicationRuntimeInstance?;
|
|
1427
|
+
private replicationDelegateSession?;
|
|
1428
|
+
private replicationScopeError?;
|
|
1429
|
+
private readonly replicationControl?;
|
|
1317
1430
|
private _sql?;
|
|
1318
1431
|
private _duckdb?;
|
|
1319
1432
|
private _hooks?;
|
|
@@ -1351,6 +1464,8 @@ declare class TinyCloudNode {
|
|
|
1351
1464
|
private readonly confirmedHostedSpaceIds;
|
|
1352
1465
|
/** Serializes account-registry writes for the active node instance. */
|
|
1353
1466
|
private accountRegistryTail;
|
|
1467
|
+
/** Bounds best-effort registry work on the sign-in critical path. */
|
|
1468
|
+
private accountRegistryDeadlineMs;
|
|
1354
1469
|
private pendingAccountRegistrySync?;
|
|
1355
1470
|
/**
|
|
1356
1471
|
* TinyCloudSession captured by {@link restoreSession} when there's no
|
|
@@ -1569,6 +1684,7 @@ declare class TinyCloudNode {
|
|
|
1569
1684
|
*/
|
|
1570
1685
|
private registerPrimarySessionGrant;
|
|
1571
1686
|
private writeManifestRegistryRecords;
|
|
1687
|
+
private createAccountRegistryServices;
|
|
1572
1688
|
private scheduleAccountRegistrySync;
|
|
1573
1689
|
private enqueueAccountRegistryOperation;
|
|
1574
1690
|
/**
|
|
@@ -1823,6 +1939,7 @@ declare class TinyCloudNode {
|
|
|
1823
1939
|
* @internal
|
|
1824
1940
|
*/
|
|
1825
1941
|
private initializeServices;
|
|
1942
|
+
private attachReplicationKV;
|
|
1826
1943
|
private createSpaceScopedKVService;
|
|
1827
1944
|
getDefaultEncryptionNetworkId(name?: string): string;
|
|
1828
1945
|
getEncryptionNetworkIdForSpace(spaceId: string, name?: string): string;
|
|
@@ -2282,6 +2399,42 @@ declare class TinyCloudNode {
|
|
|
2282
2399
|
* delegation.
|
|
2283
2400
|
*/
|
|
2284
2401
|
delegateTo(did: string, permissions: PermissionEntry[], options?: DelegateToOptions): Promise<DelegateToResult>;
|
|
2402
|
+
/**
|
|
2403
|
+
* What `delegateTo` would select for `entries`, without signing or any
|
|
2404
|
+
* network call (TC-858 plan v3 §4.3): the session path when the signed
|
|
2405
|
+
* recap covers every entry, the runtime-grant path otherwise, or a
|
|
2406
|
+
* refusal. A refusal of `CAVEATED_AUTHORITY` means coverage exists only
|
|
2407
|
+
* through caveated branches, which the action-only WASM child-delegation
|
|
2408
|
+
* boundary cannot preserve — replication never derives authority through
|
|
2409
|
+
* them. `expiredAt`/`missing`/`granted`/`caveated` carry the payload
|
|
2410
|
+
* `delegateTo` turns back into its typed errors.
|
|
2411
|
+
* @internal
|
|
2412
|
+
*/
|
|
2413
|
+
private planDerivation;
|
|
2414
|
+
/**
|
|
2415
|
+
* The plan `delegateTo(device, entries)` would follow, as a pure lookup:
|
|
2416
|
+
* no WASM sign and no `POST /delegate`. Backs
|
|
2417
|
+
* `ReplicationAuthority.plan` (and `mint` inside it) so a predicted
|
|
2418
|
+
* parent and expiry can never disagree with what a mint would use (§4.3,
|
|
2419
|
+
* §4.4). Session expiry inside the 60 s margin refuses with
|
|
2420
|
+
* `SESSION_EXPIRING`; the same check delegateTo performs.
|
|
2421
|
+
* @internal
|
|
2422
|
+
*/
|
|
2423
|
+
planDelegation(entries: PermissionEntry[], options?: {
|
|
2424
|
+
expiry?: string | number;
|
|
2425
|
+
}): DelegationPlan;
|
|
2426
|
+
/**
|
|
2427
|
+
* The replication entries this node's sign-in request carries for the
|
|
2428
|
+
* current replication config and the signed-in or restored address: the
|
|
2429
|
+
* output of the same augmentation step `resolveSignInCapabilities` runs,
|
|
2430
|
+
* with the unrestricted-get and secrets gates applied (§4.1, §4.6).
|
|
2431
|
+
* Empty when replication is off or no address is known. Pure.
|
|
2432
|
+
*/
|
|
2433
|
+
replicationSignInEntries(): PermissionEntry[];
|
|
2434
|
+
private replicationAuthority;
|
|
2435
|
+
private bindReplicationRuntime;
|
|
2436
|
+
/** Stable control facade for this node's optional replication runtime. */
|
|
2437
|
+
get replication(): ReplicationControl | undefined;
|
|
2285
2438
|
/**
|
|
2286
2439
|
* Materialize one manifest-declared delegation using the current session key.
|
|
2287
2440
|
* Delivery is intentionally out of band; callers decide how to transmit the
|
|
@@ -2325,6 +2478,13 @@ declare class TinyCloudNode {
|
|
|
2325
2478
|
* it only accepts action maps, so reject the selected constrained branch.
|
|
2326
2479
|
*/
|
|
2327
2480
|
private assertRuntimeGrantCaveatsPreservable;
|
|
2481
|
+
/**
|
|
2482
|
+
* The entries of `grant` that cover a requested operation while carrying
|
|
2483
|
+
* caveats — the branches {@link assertRuntimeGrantCaveatsPreservable}
|
|
2484
|
+
* rejects and {@link planDerivation} classifies as `CAVEATED_AUTHORITY`.
|
|
2485
|
+
* Shared so the pure plan and the mint path can't disagree.
|
|
2486
|
+
*/
|
|
2487
|
+
private caveatedRuntimeGrantEntries;
|
|
2328
2488
|
/** Reject caveated parent branches before action-only child signing. */
|
|
2329
2489
|
private assertPortableDelegationCaveatsPreservable;
|
|
2330
2490
|
private shortServiceName;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { PermissionEntry, ReplicationOptions as ReplicationOptions$1, TinyCloudSession } from '@tinycloud/sdk-core';
|
|
2
|
+
import { ReplicationOptions, AuthorityRefusal, ReplicationAuthority } from '@tinycloud/sdk-services';
|
|
3
|
+
|
|
4
|
+
/** Constructor-time validation; the space-dependent secrets check runs at sign-in and open. */
|
|
5
|
+
declare function assertValidReplicationConfig(replication: (ReplicationOptions & {
|
|
6
|
+
storage?: unknown;
|
|
7
|
+
}) | undefined): void;
|
|
8
|
+
|
|
9
|
+
declare function hasUnrestrictedGetCoverage(entries: readonly PermissionEntry[], spaceId: string, prefix: string): boolean;
|
|
10
|
+
declare function augmentSignInEntriesWithReplication(input: {
|
|
11
|
+
entries: readonly PermissionEntry[];
|
|
12
|
+
primarySpaceId: string;
|
|
13
|
+
replication?: Pick<ReplicationOptions$1, "prefixes" | "allowSecrets">;
|
|
14
|
+
}): PermissionEntry[];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Replication authority (TC-858, plan v3 §4).
|
|
18
|
+
*
|
|
19
|
+
* `ReplicationAuthority` answers, per configured prefix, whether this node's
|
|
20
|
+
* session can back a local replica: the session UCAN itself (delegate
|
|
21
|
+
* posture), a child UCAN minted through `delegateTo`, or nothing (the
|
|
22
|
+
* controller then reports `grant_missing` and reads from the network).
|
|
23
|
+
*
|
|
24
|
+
* The unrestricted-authority rule is enforced here, before any network work:
|
|
25
|
+
* a prefix covered only by a caveated `get`/`sync` refuses with
|
|
26
|
+
* `CAVEATED_AUTHORITY` — on the session path, the runtime-grant path, and on
|
|
27
|
+
* any reuse of an installed grant (the adapter marks every grant's
|
|
28
|
+
* `unconstrained` flag; the controller enforces it on reuse).
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Whether the signed `att` grants `ability` over the selected namespace, with
|
|
33
|
+
* each grant unrestricted (no caveats). A bare selector requires both its
|
|
34
|
+
* exact key and its slash descendants; a trailing-slash selector is one range.
|
|
35
|
+
*/
|
|
36
|
+
declare function ucanAttCovers(att: Record<string, Record<string, unknown>>, space: string, prefix: string, ability: string, options?: {
|
|
37
|
+
ignoreCaveats?: boolean;
|
|
38
|
+
}): boolean;
|
|
39
|
+
/** `unconstrained` for `ReplicaGrantInfo` (§2.1): get AND sync on the prefix carry no caveats. */
|
|
40
|
+
declare function ucanAttUnconstrainedFor(att: Record<string, Record<string, unknown>>, space: string, prefix: string): boolean;
|
|
41
|
+
interface DelegationPlanResult {
|
|
42
|
+
path: "session" | "runtime";
|
|
43
|
+
parentCid: string;
|
|
44
|
+
expiresAt: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The `TinyCloudNode` internals the authority needs. `planDelegation` is the
|
|
48
|
+
* pure extraction of `delegateTo`'s parent selection (§4.3), so `plan` and
|
|
49
|
+
* `mint` can never disagree about which parent or expiry a delegation gets.
|
|
50
|
+
*/
|
|
51
|
+
type ReplicationAuthoritySession = Pick<TinyCloudSession, "delegationHeader" | "delegationCid" | "spaceId" | "verificationMethod" | "jwk"> & Partial<Pick<TinyCloudSession, "siwe">>;
|
|
52
|
+
interface ReplicationAuthorityHost {
|
|
53
|
+
replicationSession(): ReplicationAuthoritySession | undefined;
|
|
54
|
+
/** The SIWE "Expiration Time" of the session — the delegateTo delegation cap. */
|
|
55
|
+
siweExpiration(siwe: string): Date | undefined;
|
|
56
|
+
planDelegation(entries: PermissionEntry[], options?: {
|
|
57
|
+
expiry?: string | number;
|
|
58
|
+
}): ({
|
|
59
|
+
grant?: unknown;
|
|
60
|
+
} & DelegationPlanResult) | AuthorityRefusal;
|
|
61
|
+
mintDelegation(deviceDid: string, entries: PermissionEntry[]): Promise<{
|
|
62
|
+
ucan: string;
|
|
63
|
+
expiresAt: number;
|
|
64
|
+
}>;
|
|
65
|
+
}
|
|
66
|
+
/** Milliseconds of validity a session or parent must have left for authority reuse (delegateTo's margin). */
|
|
67
|
+
declare const AUTHORITY_EXPIRY_MARGIN_MS = 60000;
|
|
68
|
+
/** Verify a compact session delegation before using any persisted space metadata. */
|
|
69
|
+
declare function replicationScopeFromSignedSession(input: {
|
|
70
|
+
delegationHeader: {
|
|
71
|
+
Authorization: string;
|
|
72
|
+
};
|
|
73
|
+
delegationCid: string;
|
|
74
|
+
verificationMethod: string;
|
|
75
|
+
persistedSpace: string;
|
|
76
|
+
}): {
|
|
77
|
+
space: string;
|
|
78
|
+
principal: string;
|
|
79
|
+
} | undefined;
|
|
80
|
+
declare function createReplicationAuthority(host: ReplicationAuthorityHost): ReplicationAuthority;
|
|
81
|
+
|
|
82
|
+
declare const __authority_AUTHORITY_EXPIRY_MARGIN_MS: typeof AUTHORITY_EXPIRY_MARGIN_MS;
|
|
83
|
+
type __authority_DelegationPlanResult = DelegationPlanResult;
|
|
84
|
+
type __authority_ReplicationAuthorityHost = ReplicationAuthorityHost;
|
|
85
|
+
type __authority_ReplicationAuthoritySession = ReplicationAuthoritySession;
|
|
86
|
+
declare const __authority_assertValidReplicationConfig: typeof assertValidReplicationConfig;
|
|
87
|
+
declare const __authority_augmentSignInEntriesWithReplication: typeof augmentSignInEntriesWithReplication;
|
|
88
|
+
declare const __authority_createReplicationAuthority: typeof createReplicationAuthority;
|
|
89
|
+
declare const __authority_hasUnrestrictedGetCoverage: typeof hasUnrestrictedGetCoverage;
|
|
90
|
+
declare const __authority_replicationScopeFromSignedSession: typeof replicationScopeFromSignedSession;
|
|
91
|
+
declare const __authority_ucanAttCovers: typeof ucanAttCovers;
|
|
92
|
+
declare const __authority_ucanAttUnconstrainedFor: typeof ucanAttUnconstrainedFor;
|
|
93
|
+
declare namespace __authority {
|
|
94
|
+
export { __authority_AUTHORITY_EXPIRY_MARGIN_MS as AUTHORITY_EXPIRY_MARGIN_MS, type __authority_DelegationPlanResult as DelegationPlanResult, type __authority_ReplicationAuthorityHost as ReplicationAuthorityHost, type __authority_ReplicationAuthoritySession as ReplicationAuthoritySession, __authority_assertValidReplicationConfig as assertValidReplicationConfig, __authority_augmentSignInEntriesWithReplication as augmentSignInEntriesWithReplication, __authority_createReplicationAuthority as createReplicationAuthority, __authority_hasUnrestrictedGetCoverage as hasUnrestrictedGetCoverage, __authority_replicationScopeFromSignedSession as replicationScopeFromSignedSession, __authority_ucanAttCovers as ucanAttCovers, __authority_ucanAttUnconstrainedFor as ucanAttUnconstrainedFor };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { AUTHORITY_EXPIRY_MARGIN_MS as A, type DelegationPlanResult as D, type ReplicationAuthorityHost as R, __authority as _, type ReplicationAuthoritySession as a, assertValidReplicationConfig as b, augmentSignInEntriesWithReplication as c, createReplicationAuthority as d, ucanAttUnconstrainedFor as e, hasUnrestrictedGetCoverage as h, replicationScopeFromSignedSession as r, ucanAttCovers as u };
|