@tinycloud/node-sdk 2.11.0-beta.4 → 2.11.0-beta.7

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/index.cjs CHANGED
@@ -19043,7 +19043,9 @@ function base64UrlDecode(value) {
19043
19043
  return new Uint8Array(bytes);
19044
19044
  }
19045
19045
  async function signJwtInputWithJwk(signingInput, jwk) {
19046
- const bytes = new TextEncoder().encode(signingInput);
19046
+ return signBytesWithJwk(new TextEncoder().encode(signingInput), jwk);
19047
+ }
19048
+ async function signBytesWithJwk(bytes, jwk) {
19047
19049
  try {
19048
19050
  const subtle = globalThis.crypto?.subtle;
19049
19051
  if (!subtle) {
@@ -19140,7 +19142,10 @@ var _TinyCloudNode = class _TinyCloudNode {
19140
19142
  * Outcome of the last signIn()'s account-bootstrap attempt. `skipped` is
19141
19143
  * true when bootstrap did not complete (interactive signer, auto-sign
19142
19144
  * denied, or a bootstrap step failed); `reason` carries the cause so apps
19143
- * can surface a "finish account setup" call-to-action.
19145
+ * can surface a "finish account setup" call-to-action. `warnings` is
19146
+ * present when bootstrap completed, but one or more steps recovered from
19147
+ * an ambiguous failure (e.g. a KV batch write reconciled via per-space
19148
+ * fallback) — clean vs. recovered runs are otherwise byte-identical.
19144
19149
  */
19145
19150
  this._bootstrapStatus = {
19146
19151
  skipped: false
@@ -19581,7 +19586,13 @@ var _TinyCloudNode = class _TinyCloudNode {
19581
19586
  return false;
19582
19587
  }
19583
19588
  try {
19584
- await this.runAccountBootstrap(steps);
19589
+ const warnings = await this.runAccountBootstrap(steps);
19590
+ if (warnings.length > 0) {
19591
+ this._bootstrapStatus = { skipped: false, warnings };
19592
+ this.notificationHandler.warning(
19593
+ `Account bootstrap completed with warnings: ${warnings.map((w) => `${w.stepId} (${w.kind}: ${w.code})`).join("; ")}`
19594
+ );
19595
+ }
19585
19596
  } catch (err) {
19586
19597
  const reason = err instanceof Error ? err.message : String(err);
19587
19598
  this._bootstrapSkipped = true;
@@ -19630,6 +19641,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19630
19641
  const auth = this.auth;
19631
19642
  const sessions = /* @__PURE__ */ new Map();
19632
19643
  const rawAbilitiesBySpace = /* @__PURE__ */ new Map();
19644
+ const warnings = [];
19633
19645
  const primarySession = auth.tinyCloudSession;
19634
19646
  const defaultSpaceId = this.ownedSpaceId("default");
19635
19647
  const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === import_sdk_core7.BOOTSTRAP_SESSION_REQUESTS.default;
@@ -19691,20 +19703,29 @@ var _TinyCloudNode = class _TinyCloudNode {
19691
19703
  }
19692
19704
  }
19693
19705
  if (step.kind === "seed-spaces") {
19694
- for (const space of step.spaces) {
19695
- const registered = await this.account.spaces.register({
19706
+ const registered = await this.account.spaces.registerBatch(
19707
+ step.spaces.map((space) => ({
19696
19708
  spaceId: space.spaceId,
19697
19709
  name: space.name,
19698
19710
  ownerDid: this.did,
19699
19711
  type: "owned",
19700
19712
  permissions: ["*"],
19701
19713
  status: "active"
19714
+ }))
19715
+ );
19716
+ if (!registered.ok) {
19717
+ throw new Error(
19718
+ `Failed to seed account spaces: ${registered.error.message}`
19719
+ );
19720
+ }
19721
+ const batchError = registered.data.recoveredFromBatchError;
19722
+ if (batchError) {
19723
+ warnings.push({
19724
+ stepId: step.id,
19725
+ kind: "batch-write-reconciled",
19726
+ code: batchError.code,
19727
+ message: batchError.message
19702
19728
  });
19703
- if (!registered.ok) {
19704
- throw new Error(
19705
- `Failed to seed account space ${space.spaceId}: ${registered.error.message}`
19706
- );
19707
- }
19708
19729
  }
19709
19730
  }
19710
19731
  if (step.kind === "seed-applications") {
@@ -19740,6 +19761,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19740
19761
  }
19741
19762
  }
19742
19763
  }
19764
+ return warnings;
19743
19765
  }
19744
19766
  registerBootstrapRuntimeGrant(session, request, rawAbilities) {
19745
19767
  const operations = [];
@@ -20367,6 +20389,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20367
20389
  this._delegationManager = stagedGraph.delegationManager;
20368
20390
  this._spaceService = stagedGraph.spaceService;
20369
20391
  this._serviceGraph = stagedGraph.graph;
20392
+ this._activeServiceSession = serviceSession;
20370
20393
  this._baseSecrets = /* @__PURE__ */ new Map();
20371
20394
  this._secrets = /* @__PURE__ */ new Map();
20372
20395
  this._publicKV = void 0;
@@ -20684,6 +20707,28 @@ var _TinyCloudNode = class _TinyCloudNode {
20684
20707
  currentTinyCloudSession() {
20685
20708
  return this.auth?.tinyCloudSession ?? this._restoredTcSession;
20686
20709
  }
20710
+ /**
20711
+ * Mint a multi-capability invocation through the established session key.
20712
+ * Callers receive only the signed headers; session key material remains
20713
+ * owned by the session manager and is never part of the caller contract.
20714
+ */
20715
+ invokeAny(entries, facts) {
20716
+ const session = this.currentTinyCloudSession() ?? this._activeServiceSession;
20717
+ if (session === void 0) throw new Error("Not signed in. Call signIn() first.");
20718
+ return this._serviceGraph.invokeAny(session, entries, facts);
20719
+ }
20720
+ /** Sign protocol bytes with the established in-memory session key. */
20721
+ async signSessionBytes(bytes) {
20722
+ const session = this.currentTinyCloudSession() ?? this._activeServiceSession;
20723
+ if (session === void 0) throw new Error("Not signed in. Call signIn() first.");
20724
+ return signBytesWithJwk(bytes, session.jwk);
20725
+ }
20726
+ /** Bind a session-signed invocation to the canonical service audience. */
20727
+ async bindInvocationAudience(authorization, audience) {
20728
+ const session = this.currentTinyCloudSession() ?? this._activeServiceSession;
20729
+ if (session === void 0) throw new Error("Not signed in. Call signIn() first.");
20730
+ return rewriteInvocationAudience(authorization, audience, session.jwk);
20731
+ }
20687
20732
  /**
20688
20733
  * Connect a wallet to upgrade from session-only mode to wallet mode.
20689
20734
  *
@@ -20865,6 +20910,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20865
20910
  if (this._serviceContext) {
20866
20911
  const spaceScopedContext = this._serviceGraph.track(new import_sdk_core7.ServiceContext({
20867
20912
  invoke: this._serviceContext.invoke,
20913
+ invokeAny: this._serviceContext.invokeAny,
20868
20914
  fetch: this._serviceContext.fetch,
20869
20915
  hosts: this._serviceContext.hosts,
20870
20916
  telemetry: this.config.telemetry
@@ -21530,6 +21576,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21530
21576
  shareUrl: input.shareUrl,
21531
21577
  documentName: input.documentName,
21532
21578
  jti: base64UrlEncode(crypto.getRandomValues(new Uint8Array(16))),
21579
+ idempotencyKey: input.idempotencyKey,
21533
21580
  expiresAt: input.expiresAt
21534
21581
  };
21535
21582
  const requestBodyDigest = base64UrlEncode(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode((0, import_sdk_core7.canonicalizeEncryptionJson)(body)))));