@tinycloud/node-sdk 3.11.0 → 3.12.0-beta.1
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/NodeUserAuthorization-BtoDI9in.d.cts +900 -0
- package/dist/NodeUserAuthorization-BtoDI9in.d.ts +900 -0
- package/dist/{TinyCloudNode-BlNcvo1c.d.ts → TinyCloudNode-C24728N_.d.cts} +30 -874
- package/dist/{TinyCloudNode-CnVaWnAX.d.cts → TinyCloudNode-DLrINr98.d.ts} +30 -874
- package/dist/{WasmKeyProvider-BKCPRC-c.d.cts → WasmKeyProvider-OA0LqmTg.d.cts} +2 -0
- package/dist/{WasmKeyProvider-BKCPRC-c.d.ts → WasmKeyProvider-OA0LqmTg.d.ts} +2 -0
- package/dist/{authority-DHIk5QvV.d.ts → authority-BQN2Z3st.d.ts} +1 -1
- package/dist/{authority-B2SLx27M.d.cts → authority-DDdheOL6.d.cts} +1 -1
- package/dist/core.cjs +179 -100
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +6 -5
- package/dist/core.d.ts +6 -5
- package/dist/core.js +180 -101
- package/dist/core.js.map +1 -1
- package/dist/credentials-core.d.cts +1 -1
- package/dist/credentials-core.d.ts +1 -1
- package/dist/credentials.d.cts +1 -1
- package/dist/credentials.d.ts +1 -1
- package/dist/{delegation-Ckc3UETl.d.cts → delegation-BQbAuKad.d.cts} +1 -1
- package/dist/{delegation-Ckc3UETl.d.ts → delegation-BQbAuKad.d.ts} +1 -1
- package/dist/encryption-keys.d.cts +3 -2
- package/dist/encryption-keys.d.ts +3 -2
- package/dist/index.cjs +179 -100
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +180 -101
- package/dist/index.js.map +1 -1
- package/dist/replication/authority.d.cts +4 -3
- package/dist/replication/authority.d.ts +4 -3
- package/dist/space-hosting.cjs +141 -0
- package/dist/space-hosting.cjs.map +1 -0
- package/dist/space-hosting.d.cts +69 -0
- package/dist/space-hosting.d.ts +69 -0
- package/dist/space-hosting.js +115 -0
- package/dist/space-hosting.js.map +1 -0
- package/package.json +11 -1
|
@@ -1,880 +1,10 @@
|
|
|
1
1
|
import * as _tinycloud_sdk_core from '@tinycloud/sdk-core';
|
|
2
|
-
import {
|
|
2
|
+
import { TinyCloudSession, TelemetryConfig, ServiceContext, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, Delegation, IWasmBindings, ISigner, StorageFullEvent, IStorageService, RegistryPolicy, RegistrySequenceStore, OnNodeNotFound, LocalNodeIdentityStore, ISessionStorage, INotificationHandler, IENSResolver, ISpaceCreationHandler, SiweConfig, Manifest, ComposedManifestRequest, RetryPolicy, ReplicationOptions, KVReplicaStorage, PermissionEntry, AccountService, SignInOptions, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate } from '@tinycloud/sdk-core';
|
|
3
3
|
import { ReplicaPurgeFailedEvent, ReplicaSessionStamp } from '@tinycloud/sdk-services/kv/replication';
|
|
4
4
|
import { InvokeFunction, InvokeAnyFunction, FetchFunction, RequestSink, RequestLogReader } from '@tinycloud/sdk-services';
|
|
5
5
|
import { NamedKeyClient } from '@tinycloud/sdk-services/encryption/named-keys';
|
|
6
|
-
import {
|
|
7
|
-
import { P as PortableDelegation, S as SessionGrantProof,
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Node.js-specific SignStrategy types for TinyCloud authorization.
|
|
11
|
-
*
|
|
12
|
-
* This module re-exports common types from sdk-core and provides
|
|
13
|
-
* Node.js-specific implementations (e.g., NodeEventEmitterStrategy
|
|
14
|
-
* using Node's EventEmitter instead of browser EventTarget).
|
|
15
|
-
*
|
|
16
|
-
* @packageDocumentation
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Node.js event emitter strategy: emits sign requests as events.
|
|
21
|
-
*
|
|
22
|
-
* Uses Node.js EventEmitter for compatibility with Node.js applications.
|
|
23
|
-
* For browser environments, use the EventEmitterStrategy from sdk-core
|
|
24
|
-
* which uses EventTarget.
|
|
25
|
-
*
|
|
26
|
-
* Events emitted:
|
|
27
|
-
* - 'sign-request': When a sign request is received
|
|
28
|
-
*
|
|
29
|
-
* Use cases:
|
|
30
|
-
* - Async approval workflows in Node.js
|
|
31
|
-
* - External signing services
|
|
32
|
-
* - Multi-step authorization flows
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```typescript
|
|
36
|
-
* const emitter = new EventEmitter();
|
|
37
|
-
* const strategy: NodeEventEmitterStrategy = { type: 'event-emitter', emitter };
|
|
38
|
-
*
|
|
39
|
-
* emitter.on('sign-request', async (req, respond) => {
|
|
40
|
-
* const approved = await externalApprovalService.check(req);
|
|
41
|
-
* respond({ approved, signature: approved ? await sign(req.message) : undefined });
|
|
42
|
-
* });
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
interface NodeEventEmitterStrategy {
|
|
46
|
-
type: "event-emitter";
|
|
47
|
-
emitter: EventEmitter;
|
|
48
|
-
/** Timeout in milliseconds for waiting on event response (default: 60000) */
|
|
49
|
-
timeout?: number;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Node.js sign strategy union type.
|
|
53
|
-
*
|
|
54
|
-
* Determines how sign requests are handled in NodeUserAuthorization.
|
|
55
|
-
* Uses Node.js EventEmitter for the event-emitter strategy.
|
|
56
|
-
*/
|
|
57
|
-
type SignStrategy = AutoSignStrategy | AutoRejectStrategy | CallbackStrategy | NodeEventEmitterStrategy;
|
|
58
|
-
/**
|
|
59
|
-
* Default sign strategy is auto-sign for convenience.
|
|
60
|
-
* This is the Node.js-specific version typed with SignStrategy.
|
|
61
|
-
*/
|
|
62
|
-
declare const defaultSignStrategy: SignStrategy;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Structural shape of the OpenKey SDK's `authorizeTinyCloud()` method.
|
|
66
|
-
* Callers pass any object that conforms to this shape — typically an
|
|
67
|
-
* `OpenKey` instance from `@openkey/sdk` — without either package
|
|
68
|
-
* needing to import from the other.
|
|
69
|
-
*/
|
|
70
|
-
interface OpenKeyAuthorizeTinyCloud {
|
|
71
|
-
authorizeTinyCloud(request: {
|
|
72
|
-
protocolVersion: 1;
|
|
73
|
-
siwe: string;
|
|
74
|
-
keyId?: string;
|
|
75
|
-
jwk?: Record<string, unknown>;
|
|
76
|
-
host?: string;
|
|
77
|
-
/**
|
|
78
|
-
* Display-only presentation envelope. Forwarded to the OpenKey
|
|
79
|
-
* widget review UI. The envelope MUST NEVER expand authority — the
|
|
80
|
-
* ReCap payload remains the sole gate — and the widget/server
|
|
81
|
-
* validates and size-bounds it before use.
|
|
82
|
-
*/
|
|
83
|
-
presentation?: CapabilityPresentationEnvelopeV1;
|
|
84
|
-
/**
|
|
85
|
-
* Ask OpenKey to let the user change the session expiry in the approval.
|
|
86
|
-
* Sent only when true. `@openkey/sdk` >= 0.13.0 (beta: 0.13.0-beta.0)
|
|
87
|
-
* forwards it; 0.12.x ignores it.
|
|
88
|
-
*/
|
|
89
|
-
expiryChangeable?: boolean;
|
|
90
|
-
}, opts?: {
|
|
91
|
-
mode?: "iframe" | "popup" | "redirect";
|
|
92
|
-
}): Promise<{
|
|
93
|
-
protocolVersion: 1;
|
|
94
|
-
address: string;
|
|
95
|
-
signature: string;
|
|
96
|
-
signedMessage: string;
|
|
97
|
-
selectedActionKeys: string[];
|
|
98
|
-
permissions: Array<{
|
|
99
|
-
service: string;
|
|
100
|
-
space: string;
|
|
101
|
-
path: string;
|
|
102
|
-
actions: string[];
|
|
103
|
-
}>;
|
|
104
|
-
}>;
|
|
105
|
-
}
|
|
106
|
-
interface OpenKeyBridgeInput {
|
|
107
|
-
protocolVersion: 1;
|
|
108
|
-
siwe: string;
|
|
109
|
-
jwk: Record<string, unknown>;
|
|
110
|
-
/** SDK-prepared session-key DID, for local handoff consistency only; not an OpenKey request field. */
|
|
111
|
-
readonly verificationMethod: string;
|
|
112
|
-
host?: string;
|
|
113
|
-
/** Optional keyId hint the caller wants OpenKey to bind to. */
|
|
114
|
-
keyId?: string;
|
|
115
|
-
/**
|
|
116
|
-
* Optional presentation envelope built by `NodeUserAuthorization`
|
|
117
|
-
* from its `_manifest`. Passed through to `authorizeTinyCloud` so the
|
|
118
|
-
* widget can render honest provenance labels and the OpenKey server
|
|
119
|
-
* can origin-bind the browser origin against the app's well-known
|
|
120
|
-
* manifest. Display-only.
|
|
121
|
-
*/
|
|
122
|
-
presentation?: CapabilityPresentationEnvelopeV1;
|
|
123
|
-
/**
|
|
124
|
-
* Ask OpenKey to let the user change the session expiry. Forwarded only
|
|
125
|
-
* when true. The SDK accepts a changed expiry only for a request that
|
|
126
|
-
* carried this flag, and then uses the SIGNED expiry.
|
|
127
|
-
*/
|
|
128
|
-
expiryChangeable?: boolean;
|
|
129
|
-
}
|
|
130
|
-
type NodeUserAuthorizationAuthorizeFn = (input: OpenKeyBridgeInput) => Promise<{
|
|
131
|
-
protocolVersion: 1;
|
|
132
|
-
address: string;
|
|
133
|
-
signature: string;
|
|
134
|
-
signedMessage: string;
|
|
135
|
-
selectedActionKeys: string[];
|
|
136
|
-
permissions: Array<{
|
|
137
|
-
service: string;
|
|
138
|
-
space: string;
|
|
139
|
-
path: string;
|
|
140
|
-
actions: string[];
|
|
141
|
-
}>;
|
|
142
|
-
}>;
|
|
143
|
-
/**
|
|
144
|
-
* Wire a concrete OpenKey-shaped SDK object into the `authorizeFn`
|
|
145
|
-
* `NodeUserAuthorization.signInWithOpenKey` expects. Rejects any
|
|
146
|
-
* response that does not carry the canonical rich-result shape so
|
|
147
|
-
* wire drift shows up at the bridge boundary rather than deep inside
|
|
148
|
-
* `signInWithOpenKeyResult`.
|
|
149
|
-
*
|
|
150
|
-
* @example
|
|
151
|
-
* ```ts
|
|
152
|
-
* import { OpenKey } from '@openkey/sdk';
|
|
153
|
-
* import { wireOpenKeyAuthorize } from '@tinycloud/node-sdk';
|
|
154
|
-
* const openkey = new OpenKey({ appName: 'my-app' });
|
|
155
|
-
* await openkey.connect();
|
|
156
|
-
* const authorize = wireOpenKeyAuthorize(openkey);
|
|
157
|
-
* const clientSession = await nodeAuth.signInWithOpenKey(authorize);
|
|
158
|
-
* ```
|
|
159
|
-
*/
|
|
160
|
-
declare function wireOpenKeyAuthorize(openkey: OpenKeyAuthorizeTinyCloud, opts?: {
|
|
161
|
-
mode?: "iframe" | "popup" | "redirect";
|
|
162
|
-
}): NodeUserAuthorizationAuthorizeFn;
|
|
163
|
-
|
|
164
|
-
type OpenKeyAuthorizeInput = OpenKeyBridgeInput;
|
|
165
|
-
/** SIWE and session key prepared before an OpenKey approval click. */
|
|
166
|
-
interface PreparedOpenKeyAuthorization {
|
|
167
|
-
readonly request: OpenKeyAuthorizeInput;
|
|
168
|
-
readonly prepared: PreparedOpenKeySession;
|
|
169
|
-
readonly keyId: string;
|
|
170
|
-
readonly jwk: Record<string, unknown>;
|
|
171
|
-
readonly address: string;
|
|
172
|
-
readonly chainId: number;
|
|
173
|
-
readonly generation: number;
|
|
174
|
-
readonly createdAt: number;
|
|
175
|
-
/** The app-level maximum for a changed signed expiry, if one was given. In memory only; never sent or persisted. */
|
|
176
|
-
readonly maxExpiresAt?: OpenKeyMaxExpiresAt;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* A latest acceptable signed expiry: epoch MILLISECONDS, a `Date`, or a function returning either. A function is read
|
|
180
|
-
* when the OpenKey result arrives, not when the request is prepared.
|
|
181
|
-
*/
|
|
182
|
-
type OpenKeyMaxExpiresAt = number | Date | (() => number | Date);
|
|
183
|
-
type OpenKeyAuthorizationResultV1 = Awaited<ReturnType<NodeUserAuthorizationAuthorizeFn>>;
|
|
184
|
-
type PreparedOpenKeySession = {
|
|
185
|
-
siwe: string;
|
|
186
|
-
jwk: Record<string, unknown>;
|
|
187
|
-
spaceId: string;
|
|
188
|
-
verificationMethod: string;
|
|
189
|
-
};
|
|
190
|
-
/**
|
|
191
|
-
* Configuration for NodeUserAuthorization.
|
|
192
|
-
*/
|
|
193
|
-
interface NodeUserAuthorizationConfig {
|
|
194
|
-
/** The signer used for signing messages */
|
|
195
|
-
signer: ISigner;
|
|
196
|
-
/** Sign strategy for handling sign requests */
|
|
197
|
-
signStrategy?: SignStrategy;
|
|
198
|
-
/** Session storage implementation */
|
|
199
|
-
sessionStorage?: ISessionStorage;
|
|
200
|
-
/** Domain for SIWE messages */
|
|
201
|
-
domain: string;
|
|
202
|
-
/** URI for SIWE messages (default: domain) */
|
|
203
|
-
uri?: string;
|
|
204
|
-
/** Statement included in SIWE messages */
|
|
205
|
-
statement?: string;
|
|
206
|
-
/** Space prefix for new sessions */
|
|
207
|
-
spacePrefix?: string;
|
|
208
|
-
/** Default actions for sessions */
|
|
209
|
-
defaultActions?: Record<string, Record<string, string[]>>;
|
|
210
|
-
/** Session expiration time in milliseconds (default: 30 days, `EXPIRY.SESSION_MS`) */
|
|
211
|
-
sessionExpirationMs?: number;
|
|
212
|
-
/** Automatically create space if it doesn't exist (default: false) */
|
|
213
|
-
autoCreateSpace?: boolean;
|
|
214
|
-
/** Custom space creation handler. If provided, takes precedence over autoCreateSpace. */
|
|
215
|
-
spaceCreationHandler?: ISpaceCreationHandler;
|
|
216
|
-
/** Explicit TinyCloud server endpoints. When omitted, signIn resolves the user's host. */
|
|
217
|
-
tinycloudHosts?: string[];
|
|
218
|
-
/** TinyCloud location registry URL. Default: https://registry.tinycloud.xyz. */
|
|
219
|
-
tinycloudRegistryUrl?: string | null;
|
|
220
|
-
/**
|
|
221
|
-
* Fallback TinyCloud hosts. Default: hosted TinyCloud node. Used only by the
|
|
222
|
-
* default `registryPolicy` ("legacy-fallback"), whose silent fallback is
|
|
223
|
-
* deprecated and will be removed in a future major release.
|
|
224
|
-
*/
|
|
225
|
-
tinycloudFallbackHosts?: string[] | null;
|
|
226
|
-
/**
|
|
227
|
-
* How sign-in uses the location registry when no host is configured.
|
|
228
|
-
*
|
|
229
|
-
* - `"legacy-fallback"` (default, deprecated): a registry miss or failure
|
|
230
|
-
* silently uses `tinycloudFallbackHosts`, with a one-time warning.
|
|
231
|
-
* - `"fail-closed"`: sign-in acts on the registry verdict for the signer
|
|
232
|
-
* address. Registered owners go to their listed hosts, unregistered owners
|
|
233
|
-
* to `newUserHost`, and an unavailable registry is
|
|
234
|
-
* `RegistryUnavailableError`, never a new account. Automatic space
|
|
235
|
-
* creation is refused on a host the owner's record does not list
|
|
236
|
-
* (`NodeRegistryEntryExistsError`) or when the registry gives no verdict
|
|
237
|
-
* (`RegistryUnavailableError`).
|
|
238
|
-
*/
|
|
239
|
-
registryPolicy?: RegistryPolicy;
|
|
240
|
-
/**
|
|
241
|
-
* `fail-closed` only: host for owners with no registry record (and only
|
|
242
|
-
* them). Default https://node.tinycloud.xyz. `null` refuses them with
|
|
243
|
-
* `NodeNotFoundError`.
|
|
244
|
-
*/
|
|
245
|
-
newUserHost?: string | null;
|
|
246
|
-
/**
|
|
247
|
-
* `fail-closed` only: chain ID of the v1 registry subject, which is built
|
|
248
|
-
* from the signer address, never the session chain. Default 1.
|
|
249
|
-
*/
|
|
250
|
-
registryChainId?: number;
|
|
251
|
-
/** `fail-closed` only: highest registry sequence seen per owner. Default: in-memory. */
|
|
252
|
-
registrySequenceStore?: RegistrySequenceStore;
|
|
253
|
-
/**
|
|
254
|
-
* `fail-closed` only: called when sign-in resolves no host
|
|
255
|
-
* (`NodeNotFoundError` or `RegistryUnavailableError`) to retry, use another
|
|
256
|
-
* host (not identity-checked; it persists with the session), or abort.
|
|
257
|
-
* Without it, sign-in throws the error.
|
|
258
|
-
*/
|
|
259
|
-
onNodeNotFound?: OnNodeNotFound;
|
|
260
|
-
/** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
|
|
261
|
-
autoDiscoverLocalNode?: boolean;
|
|
262
|
-
/** Local loopback node URL to probe. Omit to avoid probing loopback. */
|
|
263
|
-
localNodeUrl?: string;
|
|
264
|
-
/** Known `*.local.tinycloud.link` subdomain name, probed directly. */
|
|
265
|
-
localLinkName?: string;
|
|
266
|
-
/** Expected local node DID. A locally-discovered node whose DID differs is rejected. */
|
|
267
|
-
expectedNodeDid?: string;
|
|
268
|
-
/** Pin store for trust-on-first-use local node identity verification. Defaults to an in-memory store. */
|
|
269
|
-
localNodeIdentityStore?: LocalNodeIdentityStore;
|
|
270
|
-
/** Whether to include public space capabilities in the session (default: true) */
|
|
271
|
-
enablePublicSpace?: boolean;
|
|
272
|
-
/** WASM bindings for cryptographic operations. Required. */
|
|
273
|
-
wasmBindings: IWasmBindings;
|
|
274
|
-
/** Existing session manager to share with a higher-level SDK client. */
|
|
275
|
-
sessionManager?: ISessionManager;
|
|
276
|
-
/**
|
|
277
|
-
* SIWE nonce override. If omitted, the WASM layer generates a random nonce.
|
|
278
|
-
* If `siweConfig.nonce` is also provided, `siweConfig.nonce` wins.
|
|
279
|
-
*/
|
|
280
|
-
nonce?: string;
|
|
281
|
-
/** Optional SIWE configuration overrides (e.g., nonce for server-provided nonces) */
|
|
282
|
-
siweConfig?: SiweConfig;
|
|
283
|
-
/**
|
|
284
|
-
* App manifest used to drive the SIWE recap at sign-in.
|
|
285
|
-
*
|
|
286
|
-
* When set, `signIn` resolves the manifest (via
|
|
287
|
-
* {@link resolveManifest}), unions the app's own permissions with
|
|
288
|
-
* every `delegations[*].permissions` list, converts to the WASM
|
|
289
|
-
* abilities shape, and uses that map as the session's granted
|
|
290
|
-
* capabilities — *instead* of `defaultActions`.
|
|
291
|
-
*
|
|
292
|
-
* This is what makes manifest-declared pre-delegations usable: the
|
|
293
|
-
* session key's recap covers both the app's runtime needs and the
|
|
294
|
-
* downstream delegation targets, so `delegateTo` can issue the
|
|
295
|
-
* sub-delegation via the session-key UCAN path without a wallet
|
|
296
|
-
* prompt.
|
|
297
|
-
*
|
|
298
|
-
* When omitted, `signIn` falls back to `defaultActions` for
|
|
299
|
-
* backwards compatibility.
|
|
300
|
-
*/
|
|
301
|
-
manifest?: Manifest | Manifest[];
|
|
302
|
-
/** Pre-composed manifest request. Takes precedence over `manifest`. */
|
|
303
|
-
capabilityRequest?: ComposedManifestRequest;
|
|
304
|
-
/** Include canonical account registry read/create-update/list permissions when composing `manifest` and plain sign-in. Default true. */
|
|
305
|
-
includeAccountRegistryPermissions?: boolean;
|
|
306
|
-
/**
|
|
307
|
-
* Replication sign-in augmentation (TC-858 §4.1): prefixes whose reads a
|
|
308
|
-
* local replica may serve. For each prefix the session request gains one
|
|
309
|
-
* `kv` entry `{get, sync}` on the primary space — but only where an
|
|
310
|
-
* unrestricted `get` covering it is already requested. Storage and
|
|
311
|
-
* scheduling never reach this layer.
|
|
312
|
-
*/
|
|
313
|
-
replication?: Pick<ReplicationOptions, "enabled" | "prefixes" | "allowSecrets" | "syncScope">;
|
|
314
|
-
/** Extra top-level resource URIs and their abilities added to the sign-in ReCap (e.g. named-key prefixes). */
|
|
315
|
-
additionalRawAbilities?: Record<string, string[]>;
|
|
316
|
-
/**
|
|
317
|
-
* Mints the replica session stamp on each fresh sign-in (TC-858 §4). Returns
|
|
318
|
-
* `undefined` when replication is off, so the persisted session carries no stamp.
|
|
319
|
-
*/
|
|
320
|
-
establishReplicaStamp?: (session: TinyCloudSession) => Promise<PersistedSessionData["replicaStamp"]>;
|
|
321
|
-
}
|
|
322
|
-
interface CreateBootstrapSessionOptions {
|
|
323
|
-
spaceId: string;
|
|
324
|
-
capabilityRequest: ComposedManifestRequest;
|
|
325
|
-
rawAbilities?: Record<string, string[]>;
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Node.js implementation of IUserAuthorization.
|
|
329
|
-
*
|
|
330
|
-
* Supports multiple sign strategies for different use cases:
|
|
331
|
-
* - auto-sign: Automatically approve all sign requests (trusted backends)
|
|
332
|
-
* - auto-reject: Reject all sign requests (read-only mode)
|
|
333
|
-
* - callback: Delegate to a custom callback function (CLI prompts)
|
|
334
|
-
* - event-emitter: Emit sign requests as events (async workflows)
|
|
335
|
-
*
|
|
336
|
-
* @example
|
|
337
|
-
* ```typescript
|
|
338
|
-
* // Auto-sign for backend services
|
|
339
|
-
* const auth = new NodeUserAuthorization({
|
|
340
|
-
* signer: new PrivateKeySigner(process.env.PRIVATE_KEY),
|
|
341
|
-
* signStrategy: { type: 'auto-sign' },
|
|
342
|
-
* domain: 'api.myapp.com',
|
|
343
|
-
* });
|
|
344
|
-
*
|
|
345
|
-
* // Callback for CLI prompts
|
|
346
|
-
* const auth = new NodeUserAuthorization({
|
|
347
|
-
* signer,
|
|
348
|
-
* signStrategy: {
|
|
349
|
-
* type: 'callback',
|
|
350
|
-
* handler: async (req) => {
|
|
351
|
-
* const approved = await promptUser(`Sign for ${req.address}?`);
|
|
352
|
-
* return { approved };
|
|
353
|
-
* }
|
|
354
|
-
* },
|
|
355
|
-
* domain: 'cli.myapp.com',
|
|
356
|
-
* });
|
|
357
|
-
* ```
|
|
358
|
-
*/
|
|
359
|
-
declare class NodeUserAuthorization implements IUserAuthorization {
|
|
360
|
-
private readonly signer;
|
|
361
|
-
private readonly signStrategy;
|
|
362
|
-
private readonly sessionStorage;
|
|
363
|
-
private readonly domain;
|
|
364
|
-
private readonly uri;
|
|
365
|
-
private readonly statement?;
|
|
366
|
-
private readonly spacePrefix;
|
|
367
|
-
private readonly defaultActions;
|
|
368
|
-
private readonly sessionExpirationMs;
|
|
369
|
-
private readonly autoCreateSpace;
|
|
370
|
-
private readonly spaceCreationHandler?;
|
|
371
|
-
private tinycloudHosts?;
|
|
372
|
-
private readonly tinycloudRegistryUrl?;
|
|
373
|
-
private readonly tinycloudFallbackHosts?;
|
|
374
|
-
private readonly registryPolicy?;
|
|
375
|
-
private readonly newUserHost?;
|
|
376
|
-
private readonly registryChainId?;
|
|
377
|
-
private readonly registrySequenceStore;
|
|
378
|
-
private readonly onNodeNotFound?;
|
|
379
|
-
/** Verdict from the last `fail-closed` host resolution, reused by {@link assertMayCreateSpace}. */
|
|
380
|
-
private registryVerdict?;
|
|
381
|
-
private readonly autoDiscoverLocalNode?;
|
|
382
|
-
private readonly localNodeUrl?;
|
|
383
|
-
private readonly localLinkName?;
|
|
384
|
-
private readonly expectedNodeDid?;
|
|
385
|
-
private readonly localNodeIdentityStore?;
|
|
386
|
-
private readonly enablePublicSpace;
|
|
387
|
-
private readonly replication?;
|
|
388
|
-
private readonly additionalRawAbilities?;
|
|
389
|
-
private readonly establishReplicaStamp?;
|
|
390
|
-
private readonly nonce?;
|
|
391
|
-
private readonly siweConfig?;
|
|
392
|
-
private readonly wasm;
|
|
393
|
-
/**
|
|
394
|
-
* Stored manifest, if one was provided at construction time. Used by
|
|
395
|
-
* {@link signIn} to derive the session's granted capabilities instead
|
|
396
|
-
* of falling back to {@link defaultActions}.
|
|
397
|
-
*/
|
|
398
|
-
private _manifest?;
|
|
399
|
-
private _capabilityRequest?;
|
|
400
|
-
private readonly includeAccountRegistryPermissions;
|
|
401
|
-
private sessionManager;
|
|
402
|
-
private activeSessionKeyId;
|
|
403
|
-
private preparedSessionCounter;
|
|
404
|
-
/** Incremented by resetSession; a sign-in started earlier publishes nothing. */
|
|
405
|
-
private sessionGeneration;
|
|
406
|
-
/**
|
|
407
|
-
* Sign-in saves run one at a time, in order, each together with its own
|
|
408
|
-
* cancellation cleanup, so no later write can land between the two.
|
|
409
|
-
*/
|
|
410
|
-
private persistenceQueue;
|
|
411
|
-
private extensions;
|
|
412
|
-
private _session?;
|
|
413
|
-
private _tinyCloudSession?;
|
|
414
|
-
private _address?;
|
|
415
|
-
private _chainId?;
|
|
416
|
-
private _nodeFeatures;
|
|
417
|
-
private _nodeFeaturesKnown;
|
|
418
|
-
/**
|
|
419
|
-
* `nodeId` from the `GET /info` performed during sign-in/restore, tagged with
|
|
420
|
-
* the host it came from. Callers that need the node DID (encryption-network
|
|
421
|
-
* admin invocations) reuse this instead of re-fetching `/info`.
|
|
422
|
-
*/
|
|
423
|
-
private _nodeInfoIdentity?;
|
|
424
|
-
private _lastActivationSkippedSpaceIds;
|
|
425
|
-
/**
|
|
426
|
-
* Spaces the sign-in activation reported hosted. Only the first POST of a
|
|
427
|
-
* delegation lists them: the node answers a repeat with empty lists.
|
|
428
|
-
*/
|
|
429
|
-
private _lastActivationActivatedSpaceIds;
|
|
430
|
-
constructor(config: NodeUserAuthorizationConfig);
|
|
431
|
-
/**
|
|
432
|
-
* Return the manifest currently driving sign-in behavior, or
|
|
433
|
-
* `undefined` if none is set. Used by TinyCloudWeb/TinyCloudNode
|
|
434
|
-
* internals to surface the manifest for requestPermissions flows
|
|
435
|
-
* without forcing the caller to track it separately.
|
|
436
|
-
*/
|
|
437
|
-
get manifest(): Manifest | Manifest[] | undefined;
|
|
438
|
-
get capabilityRequest(): ComposedManifestRequest | undefined;
|
|
439
|
-
get hosts(): string[];
|
|
440
|
-
/**
|
|
441
|
-
* Install or replace the stored manifest. Takes effect on the next
|
|
442
|
-
* `signIn()` call — the current session (if any) is not touched.
|
|
443
|
-
*/
|
|
444
|
-
setManifest(manifest: Manifest | Manifest[] | undefined): void;
|
|
445
|
-
setCapabilityRequest(request: ComposedManifestRequest | undefined): void;
|
|
446
|
-
/**
|
|
447
|
-
* The current active session (web-core compatible).
|
|
448
|
-
*/
|
|
449
|
-
get session(): ClientSession | undefined;
|
|
450
|
-
/**
|
|
451
|
-
* The current TinyCloud session with full delegation data.
|
|
452
|
-
* Includes spaceId, delegationHeader, and delegationCid.
|
|
453
|
-
*/
|
|
454
|
-
get tinyCloudSession(): TinyCloudSession | undefined;
|
|
455
|
-
/**
|
|
456
|
-
* Rehydrate the auth-layer session from previously-persisted delegation
|
|
457
|
-
* data. Used by {@link TinyCloudNode.restoreSession} so that downstream
|
|
458
|
-
* surfaces that read from `tinyCloudSession` (notably
|
|
459
|
-
* `grantRuntimePermissions`, which extracts the SIWE expiry from it) work
|
|
460
|
-
* without re-running the full sign-in flow.
|
|
461
|
-
*
|
|
462
|
-
* Caller must supply the same fields that `signIn` would have written —
|
|
463
|
-
* `siwe` is the load-bearing one because `extractSiweExpiration` returns
|
|
464
|
-
* undefined for missing SIWEs and the SDK then treats the session as
|
|
465
|
-
* expired-at-epoch-zero.
|
|
466
|
-
*
|
|
467
|
-
* @param hosts - The TinyCloud hosts this session was created against,
|
|
468
|
-
* as persisted in {@link PersistedSessionData.tinycloudHosts}. When
|
|
469
|
-
* present (and non-empty) they are adopted directly so the restored
|
|
470
|
-
* session resolves to the same node as the original sign-in without
|
|
471
|
-
* re-running registry/fallback resolution. When absent (old session)
|
|
472
|
-
* hosts are resolved lazily on the first host-needing call via
|
|
473
|
-
* {@link ensureTinyCloudHosts}.
|
|
474
|
-
*/
|
|
475
|
-
setRestoredTinyCloudSession(session: TinyCloudSession, hosts?: string[]): void;
|
|
476
|
-
/**
|
|
477
|
-
* @internal End the session: adopt a fresh session manager whose active key
|
|
478
|
-
* is `sessionKeyId`, and return to the constructed state.
|
|
479
|
-
*/
|
|
480
|
-
resetSession(sessionManager: ISessionManager, sessionKeyId: string, hosts?: string[]): void;
|
|
481
|
-
/** Throws when the session was reset (signed out) after `generation` was read. */
|
|
482
|
-
private assertSignInCurrent;
|
|
483
|
-
/** Runs `task` after every earlier queued persistence task has settled. */
|
|
484
|
-
private enqueuePersistence;
|
|
485
|
-
/** @internal Atomically adopt the state staged by TinyCloudNode.restoreSession. */
|
|
486
|
-
installRestoredSession(sessionManager: ISessionManager, session: TinyCloudSession | undefined, hosts?: string[], nodeFeatures?: string[]): void;
|
|
487
|
-
/**
|
|
488
|
-
* Ensure `tinycloudHosts` are resolved before a host-needing call.
|
|
489
|
-
*
|
|
490
|
-
* Fresh sign-in resolves hosts up front; a restored session may not have
|
|
491
|
-
* (old persisted sessions predate {@link PersistedSessionData.tinycloudHosts}).
|
|
492
|
-
* This guard makes a restored session resolve the node exactly like a fresh
|
|
493
|
-
* sign-in — persisted hosts are preferred (already set by
|
|
494
|
-
* {@link setRestoredTinyCloudSession}), otherwise the registry/fallback
|
|
495
|
-
* resolution runs lazily here. Idempotent: {@link resolveTinyCloudHostsForSignIn}
|
|
496
|
-
* early-returns when hosts are already set.
|
|
497
|
-
*
|
|
498
|
-
* Throws if hosts are unset and the restored session has no address/chainId
|
|
499
|
-
* to resolve from — a real failure that must surface, not be masked.
|
|
500
|
-
*/
|
|
501
|
-
ensureTinyCloudHosts(): Promise<void>;
|
|
502
|
-
private resolveTinyCloudHostsForSignIn;
|
|
503
|
-
/**
|
|
504
|
-
* Space-creation guard (TC-1443). Under `registryPolicy: "fail-closed"`,
|
|
505
|
-
* throws unless the owner's registry verdict allows a space on the primary
|
|
506
|
-
* host: `NodeRegistryEntryExistsError` when the owner's record does not
|
|
507
|
-
* list it, `RegistryUnavailableError` when the registry gives no
|
|
508
|
-
* verdict. Reuses this session's sign-in verdict unless it was
|
|
509
|
-
* `unavailable`, else looks it up now (explicit-host apps). Under the
|
|
510
|
-
* default policy it returns at once and performs no lookup.
|
|
511
|
-
*/
|
|
512
|
-
assertMayCreateSpace(): Promise<void>;
|
|
513
|
-
private requireTinyCloudHosts;
|
|
514
|
-
private get primaryTinyCloudHost();
|
|
515
|
-
get nodeFeatures(): string[];
|
|
516
|
-
get nodeFeaturesKnown(): boolean;
|
|
517
|
-
refreshNodeInfo(): Promise<void>;
|
|
518
|
-
/**
|
|
519
|
-
* The node DID reported by `GET /info` for `host`, if the sign-in (or
|
|
520
|
-
* restore) that populated it targeted that same host. Returns `undefined`
|
|
521
|
-
* for any other host, and for nodes whose `/info` omits `nodeId`, so callers
|
|
522
|
-
* fall back to fetching it themselves rather than using a foreign node's DID.
|
|
523
|
-
*/
|
|
524
|
-
nodeIdForHost(host: string): string | undefined;
|
|
525
|
-
get lastActivationSkippedSpaceIds(): string[];
|
|
526
|
-
get lastActivationActivatedSpaceIds(): string[];
|
|
527
|
-
/**
|
|
528
|
-
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
529
|
-
* see at sign-in time.
|
|
530
|
-
*
|
|
531
|
-
* When a manifest is installed, we resolve it and union together:
|
|
532
|
-
* - the app's own `resources` (what it needs at runtime)
|
|
533
|
-
* - every `additionalDelegates[*].permissions` list (what it will
|
|
534
|
-
* re-delegate to other DIDs post sign-in)
|
|
535
|
-
*
|
|
536
|
-
* into the short-service / path / full-URN-actions shape the WASM
|
|
537
|
-
* layer expects. This is the key invariant that lets
|
|
538
|
-
* {@link TinyCloudNode.delegateTo} issue manifest-declared
|
|
539
|
-
* delegations via the session key (no wallet prompt): the session's
|
|
540
|
-
* own recap already covers every action those delegations need.
|
|
541
|
-
*
|
|
542
|
-
* When no manifest is installed, we fall back to the
|
|
543
|
-
* {@link defaultActions} table so existing callers see no change.
|
|
544
|
-
*
|
|
545
|
-
* This is a pure function of `this._manifest` + `this.defaultActions`
|
|
546
|
-
* — the manifest resolution performs no I/O and throws a
|
|
547
|
-
* {@link ManifestValidationError} on structural problems (missing
|
|
548
|
-
* id/name, unparseable expiry, etc), which will surface at sign-in
|
|
549
|
-
* rather than being silently swallowed.
|
|
550
|
-
*
|
|
551
|
-
* @internal
|
|
552
|
-
*/
|
|
553
|
-
private getCapabilityRequest;
|
|
554
|
-
private refreshNamedKeyFeatureForSignIn;
|
|
555
|
-
/** Manifest key paths that this sign-in cannot grant. */
|
|
556
|
-
get unavailableKeyPaths(): string[];
|
|
557
|
-
private resolveSpaceName;
|
|
558
|
-
/**
|
|
559
|
-
* The plain-session primary abilities: `defaultActions` (the shared table)
|
|
560
|
-
* unless the primary space IS the account space, where account-registry
|
|
561
|
-
* permissions merge into a private clone so the shared table is never
|
|
562
|
-
* mutated. Shared between `resolveSignInCapabilities` and
|
|
563
|
-
* `signInPermissionInputs` so sign-in and `replicationSignInEntries`
|
|
564
|
-
* can't disagree (§4.6).
|
|
565
|
-
*/
|
|
566
|
-
private primaryActionsForSignIn;
|
|
567
|
-
/**
|
|
568
|
-
* The abilities a `spacePrefix: "secrets"` plain session actually requests
|
|
569
|
-
* for its primary space: the vault-secrets subtree only — the
|
|
570
|
-
* `defaultActions` root `get` is REPLACED, not merged (sign-in installs
|
|
571
|
-
* this map under the primary space id). Shared between
|
|
572
|
-
* `resolveSignInCapabilities` and `signInPermissionInputs` so the
|
|
573
|
-
* replication augmentation measures coverage against the effective
|
|
574
|
-
* pre-replication request, never the uninstalled `primaryActions` (§4.1).
|
|
575
|
-
*/
|
|
576
|
-
private secretsPrimaryAbilities;
|
|
577
|
-
/**
|
|
578
|
-
* The effective sign-in request as `PermissionEntry`s plus the resolved
|
|
579
|
-
* primary space id — the inputs to the replication augmentation (§4.1).
|
|
580
|
-
* `resolveSignInCapabilities` merges the augmented entries into its
|
|
581
|
-
* abilities; `replicationSignInEntries()` returns them verbatim, so the
|
|
582
|
-
* entries the SIWE recap carries and the restore check sees are the same.
|
|
583
|
-
*/
|
|
584
|
-
private signInPermissionInputs;
|
|
585
|
-
/**
|
|
586
|
-
* Merge replication augmentation entries into a space's abilities map
|
|
587
|
-
* without mutating shared tables (`defaultActions` may back the base map):
|
|
588
|
-
* the primary entry in `spaceAbilities` is replaced with a copy whose `kv`
|
|
589
|
-
* paths gain `get`/`sync`. Returns the merged map for `abilities`.
|
|
590
|
-
*/
|
|
591
|
-
private mergeReplicationEntries;
|
|
592
|
-
/**
|
|
593
|
-
* The replication entries this authorization's sign-in request carries
|
|
594
|
-
* for the signed-in or restored address (TC-858 §4.1/§4.6): the output of
|
|
595
|
-
* the same augmentation `resolveSignInCapabilities` runs — one
|
|
596
|
-
* `{tinycloud.kv, primarySpace, prefix, [get, sync]}` per configured
|
|
597
|
-
* prefix that already has an unrestricted covering `get` and passes the
|
|
598
|
-
* secrets opt-in gate. Empty when replication is off or no address is
|
|
599
|
-
* known. Pure.
|
|
600
|
-
*/
|
|
601
|
-
replicationSignInEntries(): PermissionEntry[];
|
|
602
|
-
private defaultEncryptionNetworkId;
|
|
603
|
-
/** Sign-in capabilities plus the caller's additional top-level resource abilities. */
|
|
604
|
-
private resolveSignInCapabilities;
|
|
605
|
-
private resolveBaseSignInCapabilities;
|
|
606
|
-
/**
|
|
607
|
-
* Build SIWE overrides from the top-level nonce and siweConfig.
|
|
608
|
-
* - Top-level `nonce` is seeded first so `siweConfig.nonce` wins if both are set.
|
|
609
|
-
* - resources are inserted after WASM preparation, before the final ReCap
|
|
610
|
-
* - uri triggers a warning (overwriting delegation target)
|
|
611
|
-
* - all other fields override directly
|
|
612
|
-
* - per-call nonce overrides siweConfig.nonce when provided
|
|
613
|
-
*/
|
|
614
|
-
private buildSiweOverrides;
|
|
615
|
-
private prepareSessionWithResources;
|
|
616
|
-
/**
|
|
617
|
-
* Add an extension to the authorization flow.
|
|
618
|
-
*/
|
|
619
|
-
extend(extension: Extension): void;
|
|
620
|
-
/**
|
|
621
|
-
* Get the space ID for the current session.
|
|
622
|
-
*/
|
|
623
|
-
getSpaceId(): string | undefined;
|
|
624
|
-
/**
|
|
625
|
-
* Create the space on the TinyCloud server (host delegation).
|
|
626
|
-
* This registers the user as the owner of the space.
|
|
627
|
-
*/
|
|
628
|
-
private hostSpace;
|
|
629
|
-
/**
|
|
630
|
-
* Create a specific space on the server via host delegation.
|
|
631
|
-
* Used for lazy creation of additional spaces (e.g., public).
|
|
632
|
-
*/
|
|
633
|
-
hostPublicSpace(spaceId: string): Promise<boolean>;
|
|
634
|
-
/**
|
|
635
|
-
* Create a specific owned space on the server via host delegation.
|
|
636
|
-
* Used by manifest registry setup for the account space.
|
|
637
|
-
*/
|
|
638
|
-
hostOwnedSpace(spaceId: string, purpose?: SignRequest["purpose"]): Promise<boolean>;
|
|
639
|
-
/**
|
|
640
|
-
* {@link hostOwnedSpace} with the full host-delegation result, so a failure
|
|
641
|
-
* keeps its HTTP status (e.g. a typed 401/403) instead of collapsing to
|
|
642
|
-
* `false`.
|
|
643
|
-
*/
|
|
644
|
-
hostOwnedSpaceResult(spaceId: string, purpose?: SignRequest["purpose"], signal?: AbortSignal): Promise<SpaceHostResult>;
|
|
645
|
-
/**
|
|
646
|
-
* Ensure the user's space exists on the TinyCloud server.
|
|
647
|
-
* Creates the space if it doesn't exist and autoCreateSpace is enabled.
|
|
648
|
-
* If autoCreateSpace is false and space doesn't exist, silently returns
|
|
649
|
-
* (user may be using delegations to access other spaces).
|
|
650
|
-
*
|
|
651
|
-
* @throws Error if space creation fails
|
|
652
|
-
*/
|
|
653
|
-
ensureSpaceExists(): Promise<void>;
|
|
654
|
-
/** {@link assertMayCreateSpace}, reporting a refusal to the creation handler before rethrowing it. */
|
|
655
|
-
private guardSpaceCreation;
|
|
656
|
-
private recordActivationSkippedSpaces;
|
|
657
|
-
createBootstrapSession(options: CreateBootstrapSessionOptions): Promise<TinyCloudSession>;
|
|
658
|
-
/**
|
|
659
|
-
* When a session that starts at `now` ends. Refused with a dated message when
|
|
660
|
-
* the configured lifetime reaches past what a sign-in message can carry,
|
|
661
|
-
* instead of the bare `RangeError` or WASM parse error `toISOString()` and
|
|
662
|
-
* `prepareSession` would otherwise give.
|
|
663
|
-
*/
|
|
664
|
-
private sessionExpiryFrom;
|
|
665
|
-
private persistedData;
|
|
666
|
-
/**
|
|
667
|
-
* Sign in and create a new session.
|
|
668
|
-
*
|
|
669
|
-
* This follows the correct SIWE-ReCap flow:
|
|
670
|
-
* 1. Create session key and get JWK
|
|
671
|
-
* 2. Call prepareSession() which generates the SIWE with ReCap capabilities
|
|
672
|
-
* 3. Sign the SIWE string from prepareSession
|
|
673
|
-
* 4. Call completeSessionSetup() with the prepared session + signature
|
|
674
|
-
*
|
|
675
|
-
* @param options - Optional per-call SIWE overrides for this sign-in only
|
|
676
|
-
*/
|
|
677
|
-
signIn(options?: SignInOptions): Promise<ClientSession>;
|
|
678
|
-
/**
|
|
679
|
-
* Sign out and clear the current session.
|
|
680
|
-
*/
|
|
681
|
-
signOut(): Promise<void>;
|
|
682
|
-
/**
|
|
683
|
-
* Get the current wallet/signer address.
|
|
684
|
-
*/
|
|
685
|
-
address(): string | undefined;
|
|
686
|
-
/**
|
|
687
|
-
* Get the current chain ID.
|
|
688
|
-
*/
|
|
689
|
-
chainId(): number | undefined;
|
|
690
|
-
/**
|
|
691
|
-
* Sign a message with the connected signer.
|
|
692
|
-
*/
|
|
693
|
-
signMessage(message: string, purpose?: SignRequest["purpose"]): Promise<string>;
|
|
694
|
-
/**
|
|
695
|
-
* Prepare a session for external signing.
|
|
696
|
-
*
|
|
697
|
-
* Use this method when you need to sign the SIWE message externally (e.g., via
|
|
698
|
-
* a hardware wallet, multi-sig, or external service). After obtaining the signature,
|
|
699
|
-
* call `signInWithPreparedSession()` to complete the sign-in.
|
|
700
|
-
*
|
|
701
|
-
* @example
|
|
702
|
-
* ```typescript
|
|
703
|
-
* const { prepared, keyId, jwk } = await auth.prepareSessionForSigning();
|
|
704
|
-
* const signature = await externalSigner.signMessage(prepared.siwe);
|
|
705
|
-
* const session = await auth.signInWithPreparedSession(prepared, signature, keyId, jwk);
|
|
706
|
-
* ```
|
|
707
|
-
*/
|
|
708
|
-
prepareSessionForSigning(): Promise<{
|
|
709
|
-
prepared: {
|
|
710
|
-
siwe: string;
|
|
711
|
-
jwk: Record<string, unknown>;
|
|
712
|
-
spaceId: string;
|
|
713
|
-
verificationMethod: string;
|
|
714
|
-
};
|
|
715
|
-
keyId: string;
|
|
716
|
-
jwk: Record<string, unknown>;
|
|
717
|
-
address: string;
|
|
718
|
-
chainId: number;
|
|
719
|
-
}>;
|
|
720
|
-
/**
|
|
721
|
-
* Complete sign-in with a prepared session and signature.
|
|
722
|
-
*
|
|
723
|
-
* Use this method after obtaining a signature for the SIWE message from
|
|
724
|
-
* `prepareSessionForSigning()`. The signature MUST be over `prepared.siwe`.
|
|
725
|
-
*
|
|
726
|
-
* @param prepared - The prepared session from `prepareSessionForSigning()`
|
|
727
|
-
* @param signature - The signature over `prepared.siwe`
|
|
728
|
-
* @param keyId - The session key ID from `prepareSessionForSigning()`
|
|
729
|
-
* @param jwk - The JWK from `prepareSessionForSigning()`
|
|
730
|
-
*/
|
|
731
|
-
signInWithPreparedSession(prepared: {
|
|
732
|
-
siwe: string;
|
|
733
|
-
jwk: Record<string, unknown>;
|
|
734
|
-
spaceId: string;
|
|
735
|
-
verificationMethod: string;
|
|
736
|
-
}, signature: string, keyId: string, jwk: Record<string, unknown>): Promise<ClientSession>;
|
|
737
|
-
/**
|
|
738
|
-
* End-to-end sign-in via OpenKey `authorizeTinyCloud()` (Sol CRITICAL-4).
|
|
739
|
-
*
|
|
740
|
-
* This is the production entry point that wires
|
|
741
|
-
* {@link prepareSessionForSigning} → OpenKey `authorizeTinyCloud()` →
|
|
742
|
-
* {@link signInWithOpenKeyResult} into one call. Consumers pass in a
|
|
743
|
-
* caller-provided `authorizeFn` (typically a thin wrapper around
|
|
744
|
-
* `openkey.authorizeTinyCloud()`) so this method has no direct
|
|
745
|
-
* dependency on the OpenKey SDK — it works with any transport that
|
|
746
|
-
* conforms to the versioned protocol.
|
|
747
|
-
*
|
|
748
|
-
* The `authorizeFn` MUST:
|
|
749
|
-
* 1. Send the prepared SIWE bytes to OpenKey.
|
|
750
|
-
* 2. Return the exact `TinyCloudAuthorizationResultV1` shape (with
|
|
751
|
-
* `signedMessage` — the bytes the signature actually verifies
|
|
752
|
-
* against — plus `selectedActionKeys` and `permissions`).
|
|
753
|
-
*
|
|
754
|
-
* NodeUserAuthorization then completes the session with `signedMessage`
|
|
755
|
-
* (never the prepared bytes), verifying the signature, the immutable
|
|
756
|
-
* SIWE fields, and every subset invariant enforced by
|
|
757
|
-
* {@link signInWithOpenKeyResult}. This preserves the exact-byte
|
|
758
|
-
* guarantee: if the user did NOT narrow, the returned `signedMessage`
|
|
759
|
-
* equals the prepared SIWE byte-for-byte; if the user narrowed, only
|
|
760
|
-
* the ReCap block differs and every immutable header field survives.
|
|
761
|
-
*
|
|
762
|
-
* Legacy exact-byte {@link signIn} callers are unaffected — this method
|
|
763
|
-
* is opt-in.
|
|
764
|
-
*
|
|
765
|
-
* @param authorizeFn Callback that invokes the versioned OpenKey
|
|
766
|
-
* `authorizeTinyCloud()` protocol and returns the result. Receives
|
|
767
|
-
* the prepared SIWE bytes plus a `host` hint the widget should bind
|
|
768
|
-
* into its /authorize-sign-prepare context.
|
|
769
|
-
* @param options Optional overrides for the OpenKey request.
|
|
770
|
-
*/
|
|
771
|
-
signInWithOpenKey(authorizeFn: NodeUserAuthorizationAuthorizeFn, options?: {
|
|
772
|
-
host?: string;
|
|
773
|
-
openkeyKeyId?: string;
|
|
774
|
-
/** Caller-supplied display reason, not signed authority. */
|
|
775
|
-
reason?: string;
|
|
776
|
-
/**
|
|
777
|
-
* Let the user change the session expiry in the OpenKey approval. Sent
|
|
778
|
-
* to OpenKey as `expiryChangeable: true` (`@openkey/sdk` >= 0.13.0
|
|
779
|
-
* (beta: 0.13.0-beta.0) forwards it; 0.12.x ignores it). The SIGNED
|
|
780
|
-
* expiry is then the session's expiry.
|
|
781
|
-
*/
|
|
782
|
-
expiryChangeable?: boolean;
|
|
783
|
-
/**
|
|
784
|
-
* The latest signed expiry the caller will accept, used only with `expiryChangeable`: a signed expiry beyond it
|
|
785
|
-
* is refused before any session is built, stored or activated. Epoch MILLISECONDS or a `Date`; a function is
|
|
786
|
-
* called when the result arrives (so a slow approval does not count against it) and returns either. It is not
|
|
787
|
-
* sent to OpenKey and not persisted. It limits a CHANGED expiry only: an expiry equal to the one this SDK
|
|
788
|
-
* requested is accepted, so keep the configured session lifetime within the maximum.
|
|
789
|
-
*/
|
|
790
|
-
maxExpiresAt?: OpenKeyMaxExpiresAt;
|
|
791
|
-
/**
|
|
792
|
-
* Supply another candidate without regenerating the SIWE or session key.
|
|
793
|
-
* Called only after transport or pre-commit verification rejects a result.
|
|
794
|
-
* Return null to cancel; activation errors are never signing retries.
|
|
795
|
-
*/
|
|
796
|
-
retryResult?: (error: Error, originalRequest: OpenKeyAuthorizeInput, attempt: number) => Promise<OpenKeyAuthorizationResultV1 | null>;
|
|
797
|
-
}): Promise<ClientSession>;
|
|
798
|
-
/** Finish address, host and SIWE preparation before an approval click. */
|
|
799
|
-
prepareOpenKeySignIn(options?: Parameters<NodeUserAuthorization["signInWithOpenKey"]>[1]): Promise<PreparedOpenKeyAuthorization>;
|
|
800
|
-
/** Complete a prepared approval. The caller starts authorization before awaiting this method. */
|
|
801
|
-
completeOpenKeySignIn(pending: PreparedOpenKeyAuthorization, authorization: Promise<OpenKeyAuthorizationResultV1>, options?: Parameters<NodeUserAuthorization["signInWithOpenKey"]>[1]): Promise<ClientSession>;
|
|
802
|
-
/**
|
|
803
|
-
* Build a `CapabilityPresentationEnvelopeV1` from `this._manifest`. The
|
|
804
|
-
* envelope is display-only — the OpenKey widget renders it under an
|
|
805
|
-
* honest trust label, and the server /authorize-sign-prepare route
|
|
806
|
-
* decides whether to upgrade the label to `origin-bound` by fetching
|
|
807
|
-
* the well-known manifest and comparing its digest to
|
|
808
|
-
* `manifestDigest`.
|
|
809
|
-
*
|
|
810
|
-
* Returns `undefined` when no manifest is set — the widget renders as
|
|
811
|
-
* "no manifest supplied" (unsigned).
|
|
812
|
-
*
|
|
813
|
-
* The digest is a deterministic SHA-256 over canonical JSON of the
|
|
814
|
-
* first manifest payload; OpenKey parses the fetched well-known manifest
|
|
815
|
-
* and applies the same canonicalization before comparing digests.
|
|
816
|
-
*/
|
|
817
|
-
private buildPresentationEnvelope;
|
|
818
|
-
/**
|
|
819
|
-
* Complete sign-in with a versioned OpenKey authorization result.
|
|
820
|
-
*
|
|
821
|
-
* Where `signInWithPreparedSession` completes with a signature over the
|
|
822
|
-
* ORIGINAL prepared SIWE, this method completes with the SIWE bytes the
|
|
823
|
-
* OpenKey widget actually presented and signed (`signedMessage`). It
|
|
824
|
-
* exists because the versioned authorizeTinyCloud protocol lets the user
|
|
825
|
-
* narrow capabilities; the returned bytes may differ from the original
|
|
826
|
-
* request and are the only ones the signature actually verifies against.
|
|
827
|
-
*
|
|
828
|
-
* The `result` parameter is validated at the trust boundary via
|
|
829
|
-
* `validateAuthorizationResultV1` (in sdk-core). Callers should validate
|
|
830
|
-
* BEFORE calling this method so unknown/missing fields are rejected
|
|
831
|
-
* before any session state is created.
|
|
832
|
-
*
|
|
833
|
-
* Validation performed here (defence-in-depth: even a "valid" v1 payload
|
|
834
|
-
* must clear these checks before any session state is created):
|
|
835
|
-
* 1. `result.address` matches the local signer's address.
|
|
836
|
-
* 2. `result.signature` recovers to `result.address` when verified against
|
|
837
|
-
* `result.signedMessage`.
|
|
838
|
-
* 3. Every immutable SIWE header field (domain, address, URI, version,
|
|
839
|
-
* chainId, nonce, issuedAt) in the original prepared SIWE is preserved
|
|
840
|
-
* byte-for-byte in `result.signedMessage`. `statement` is NOT in this
|
|
841
|
-
* list because the WASM renders it from the ReCap contents; it MUST
|
|
842
|
-
* change when the ReCap is narrowed.
|
|
843
|
-
* 4. Every capability in `result.signedMessage`'s ReCap block was present
|
|
844
|
-
* in the original prepared SIWE — narrowing OK, broadening rejected.
|
|
845
|
-
* 5. Every `result.selectedActionKeys` entry corresponds to a
|
|
846
|
-
* (resource, action) pair in the returned SIWE.
|
|
847
|
-
*
|
|
848
|
-
* `options.expiryChangeable` is true only when the request sent to OpenKey
|
|
849
|
-
* carried `expiryChangeable: true`. Then (and only then) the signed
|
|
850
|
-
* `Expiration Time` may differ from the prepared one and is the expiry the
|
|
851
|
-
* session is built with; the changed expiry must pass
|
|
852
|
-
* `checkChangedExpiration` and every other field in (3) must still match.
|
|
853
|
-
* Without it, any expiry difference is refused as in (3).
|
|
854
|
-
*/
|
|
855
|
-
signInWithOpenKeyResult(result: OpenKeyAuthorizationResultV1, prepared: PreparedOpenKeySession, keyId: string, jwk: Record<string, unknown>, options?: {
|
|
856
|
-
expiryChangeable?: boolean;
|
|
857
|
-
maxExpiresAt?: OpenKeyMaxExpiresAt;
|
|
858
|
-
}): Promise<ClientSession>;
|
|
859
|
-
/** Validate a candidate without activating a network session, so paste retries reuse one preparation. */
|
|
860
|
-
private verifyOpenKeyResult;
|
|
861
|
-
/**
|
|
862
|
-
* Clear persisted session data.
|
|
863
|
-
*/
|
|
864
|
-
clearPersistedSession(address?: string): Promise<void>;
|
|
865
|
-
/**
|
|
866
|
-
* Check if a session is persisted for an address.
|
|
867
|
-
*/
|
|
868
|
-
isSessionPersisted(address: string): boolean;
|
|
869
|
-
/**
|
|
870
|
-
* Request a signature based on the configured strategy.
|
|
871
|
-
*/
|
|
872
|
-
private requestSignature;
|
|
873
|
-
/**
|
|
874
|
-
* Request signature via event emitter with timeout.
|
|
875
|
-
*/
|
|
876
|
-
private requestSignatureViaEmitter;
|
|
877
|
-
}
|
|
6
|
+
import { S as SpaceHosting, c as SignStrategy, a as NodeUserAuthorization, P as PreparedOpenKeyAuthorization } from './NodeUserAuthorization-BtoDI9in.cjs';
|
|
7
|
+
import { P as PortableDelegation, S as SessionGrantProof, e as VerifiedSessionGrant } from './delegation-BQbAuKad.cjs';
|
|
878
8
|
|
|
879
9
|
/**
|
|
880
10
|
* The handles needed to rehydrate this delegation activation in a fresh
|
|
@@ -1417,6 +547,8 @@ declare class TinyCloudNode {
|
|
|
1417
547
|
* hosting is confirmed against the session that was active at the time.
|
|
1418
548
|
*/
|
|
1419
549
|
private readonly confirmedHostedSpaceIds;
|
|
550
|
+
/** The primary space's hosting answer when no authorization layer holds it (a session-only restore). */
|
|
551
|
+
private _restoredSpaceHosting;
|
|
1420
552
|
/**
|
|
1421
553
|
* Owned space ids known to be hosted for the current session: the sign-in
|
|
1422
554
|
* activation listed them as `activated`, or this session hosted them. Unlike
|
|
@@ -1549,6 +681,30 @@ declare class TinyCloudNode {
|
|
|
1549
681
|
*/
|
|
1550
682
|
get storage(): IStorageService;
|
|
1551
683
|
private readStorageStatus;
|
|
684
|
+
/**
|
|
685
|
+
* Whether the TinyCloud node hosts the primary space (the default) or a named
|
|
686
|
+
* or full-id space: `"hosted"`, `"not-hosted"`, or `"unknown"` when the node
|
|
687
|
+
* cannot say.
|
|
688
|
+
*
|
|
689
|
+
* Sends one authorized read the session already holds on that space (a kv
|
|
690
|
+
* list under a granted prefix, else kv metadata, `tinycloud.space/info`, or
|
|
691
|
+
* a kv get of a key that does not exist), signed for that space. A session
|
|
692
|
+
* with no such read sends nothing and answers `unknown`. A 401/403 registers
|
|
693
|
+
* the session delegation with the node once and asks again once. Network
|
|
694
|
+
* failures, 5xx and a 5 s timeout answer `unknown`; this never throws.
|
|
695
|
+
*
|
|
696
|
+
* `hosted` is remembered for the session and `not-hosted` never is. The
|
|
697
|
+
* answer for the primary space is also what {@link spaceHosting} reports; a
|
|
698
|
+
* `unknown` answer leaves the previous one in place.
|
|
699
|
+
*/
|
|
700
|
+
checkSpaceHosting(space?: string): Promise<SpaceHosting>;
|
|
701
|
+
/**
|
|
702
|
+
* The node's last answer for the primary space: recorded at sign-in from the
|
|
703
|
+
* activation, or by {@link checkSpaceHosting}. `unknown` after a restore until
|
|
704
|
+
* something asks.
|
|
705
|
+
*/
|
|
706
|
+
get spaceHosting(): SpaceHosting;
|
|
707
|
+
private probeSpaceHosting;
|
|
1552
708
|
private get nodeFeatures();
|
|
1553
709
|
private get replicationNodeFeatures();
|
|
1554
710
|
/** SIWE domain — uses config override or defaults to app.tinycloud.xyz */
|
|
@@ -2817,4 +1973,4 @@ declare class TinyCloudNode {
|
|
|
2817
1973
|
}): Promise<PortableDelegation>;
|
|
2818
1974
|
}
|
|
2819
1975
|
|
|
2820
|
-
export { ACCEPTED_MARKER_VERSIONS as A, type BootstrapWarning as B, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, type EnsureEncryptionNetworkOptions as E, InvalidRestoredSessionError as I, type
|
|
1976
|
+
export { ACCEPTED_MARKER_VERSIONS as A, type BootstrapWarning as B, type CreateOwnerDelegationParams as C, type DelegateToOptions as D, type EnsureEncryptionNetworkOptions as E, InvalidRestoredSessionError as I, type OwnerDelegationReceipt as O, type RuntimePermissionGrantOptions as R, type SecretPermissionHint as S, TinyCloudNode as T, type UnifiedOwnerRootInput as U, type DelegateToResult as a, DelegatedAccess as b, type SecretReadInput as c, type SecretReadResult as d, type TinyCloudNodeConfig as e, type UnifiedOwnerRootReceipt as f, UnsupportedSessionRestoreError as g, BOOTSTRAP_COMPLETION_MARKER_KEY as h, BOOTSTRAP_COMPLETION_MARKER_VERSION as i, type BootstrapCompletionMarker as j, type RestorableSession as k };
|