@tinycloud/sdk-core 3.2.6-beta.4 → 3.3.0-beta.11

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
@@ -221,6 +221,7 @@ __export(index_exports, {
221
221
  SpaceService: () => SpaceService,
222
222
  StorageFullMonitor: () => import_sdk_services9.StorageFullMonitor,
223
223
  TC832_RESERVED_SCOPES: () => import_sdk_services9.TC832_RESERVED_SCOPES,
224
+ TERMINAL_DELEGATION_FACT: () => TERMINAL_DELEGATION_FACT,
224
225
  TINYCLOUD_ACCOUNT_SPACE_MANIFEST: () => import_bootstrap4.TINYCLOUD_ACCOUNT_SPACE_MANIFEST,
225
226
  TINYCLOUD_AGENTS_SPACE_MANIFEST: () => import_bootstrap4.TINYCLOUD_AGENTS_SPACE_MANIFEST,
226
227
  TINYCLOUD_APPLICATIONS_SPACE_MANIFEST: () => import_bootstrap4.TINYCLOUD_APPLICATIONS_SPACE_MANIFEST,
@@ -381,6 +382,7 @@ __export(index_exports, {
381
382
  makePkhSpaceId: () => makePkhSpaceId,
382
383
  makePublicSpaceId: () => makePublicSpaceId,
383
384
  manifestAbilitiesUnion: () => manifestAbilitiesUnion,
385
+ markDelegationTerminal: () => markDelegationTerminal,
384
386
  multiaddrToHttpUrl: () => multiaddrToHttpUrl,
385
387
  networkDiscoveryKey: () => import_sdk_services9.networkDiscoveryKey,
386
388
  normalizeDefaults: () => normalizeDefaults,
@@ -6917,6 +6919,8 @@ var DelegationManagerConfigSchema = import_zod4.z.object({
6917
6919
  (val) => val === void 0 || typeof val === "function",
6918
6920
  { message: "Expected an invokeAny function or undefined" }
6919
6921
  ).optional(),
6922
+ /** Optional owner-signed authorization for direct CID revocation */
6923
+ signOwnerRevocation: import_zod4.z.custom().optional(),
6920
6924
  /** Optional custom fetch implementation */
6921
6925
  fetch: import_zod4.z.unknown().refine(
6922
6926
  (val) => val === void 0 || typeof val === "function",
@@ -7056,6 +7060,7 @@ var DelegationManager = class {
7056
7060
  this.session = config.session;
7057
7061
  this.invoke = config.invoke;
7058
7062
  this.invokeAny = config.invokeAny;
7063
+ this.signOwnerRevocation = config.signOwnerRevocation;
7059
7064
  this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
7060
7065
  this.accountSpaceId = config.accountSpaceId;
7061
7066
  }
@@ -7198,6 +7203,9 @@ var DelegationManager = class {
7198
7203
  * Once revoked, the delegation can no longer be used to access resources.
7199
7204
  * This also invalidates any sub-delegations derived from this delegation.
7200
7205
  *
7206
+ * Explicit target-space or authority options keep the delegated session
7207
+ * signing path even when an owner signer is available.
7208
+ *
7201
7209
  * @param cid - The CID of the delegation to revoke
7202
7210
  * @returns Result indicating success or an error
7203
7211
  *
@@ -7220,29 +7228,35 @@ var DelegationManager = class {
7220
7228
  };
7221
7229
  }
7222
7230
  try {
7223
- if (!this.invokeAny) {
7231
+ const ownerSigner = options2?.targetSpaceId === void 0 && options2?.authorityCid === void 0 ? this.signOwnerRevocation : void 0;
7232
+ if (!ownerSigner && !this.invokeAny) {
7224
7233
  return {
7225
7234
  ok: false,
7226
7235
  error: createError(
7227
7236
  DelegationErrorCodes.NOT_INITIALIZED,
7228
- "Revocation requires an invokeAny function that can sign the target CID"
7237
+ "Revocation requires an owner signer or invokeAny function that can sign the target CID"
7229
7238
  )
7230
7239
  };
7231
7240
  }
7232
- const entry = {
7233
- resource: `urn:cid:${cid2}`,
7234
- ...options2?.targetSpaceId === void 0 ? {} : { spaceId: options2.targetSpaceId },
7235
- service: "delegation",
7236
- path: "",
7237
- action: DelegationAction.REVOKE
7238
- };
7239
- if (options2?.authorityCid !== void 0) {
7240
- Object.defineProperty(entry, "revokeAuthorityCid", {
7241
- value: options2.authorityCid,
7242
- enumerable: false
7243
- });
7241
+ let headers;
7242
+ if (ownerSigner) {
7243
+ headers = { Authorization: await ownerSigner(cid2) };
7244
+ } else {
7245
+ const entry = {
7246
+ resource: `urn:cid:${cid2}`,
7247
+ ...options2?.targetSpaceId === void 0 ? {} : { spaceId: options2.targetSpaceId },
7248
+ service: "delegation",
7249
+ path: "",
7250
+ action: DelegationAction.REVOKE
7251
+ };
7252
+ if (options2?.authorityCid !== void 0) {
7253
+ Object.defineProperty(entry, "revokeAuthorityCid", {
7254
+ value: options2.authorityCid,
7255
+ enumerable: false
7256
+ });
7257
+ }
7258
+ headers = this.invokeAny(this.session, [entry]);
7244
7259
  }
7245
- const headers = this.invokeAny(this.session, [entry]);
7246
7260
  const response = await this.fetchFn(`${this.host}/revoke`, {
7247
7261
  method: "POST",
7248
7262
  headers
@@ -9972,7 +9986,9 @@ function redactedCode(error) {
9972
9986
  if (error instanceof ShareConflict) return error.code;
9973
9987
  const code3 = error && typeof error === "object" && "code" in error ? error.code : void 0;
9974
9988
  if (typeof code3 !== "string") return "SHARE_INVALID";
9975
- if (code3 === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED || code3 === import_sdk_services3.ErrorCodes.KV_CONFLICT || code3 === "412") return "SHARE_CONFLICT";
9989
+ if (code3 === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED || code3 === "412") return "SHARE_CONFLICT";
9990
+ if (code3 === import_sdk_services3.ErrorCodes.NODE_BUSY || code3 === import_sdk_services3.ErrorCodes.REQUEST_TIMEOUT) return "SHARE_OFFLINE";
9991
+ if (code3 === import_sdk_services3.ErrorCodes.OUTCOME_UNKNOWN) return "SHARE_WRITE_FAILED";
9976
9992
  if (code3 === "KV_NOT_FOUND" || code3 === "NOT_FOUND" || code3 === "404") return "SHARE_NOT_FOUND";
9977
9993
  if (code3.includes("EXPIRED") || code3 === "expired") return "SHARE_EXPIRED";
9978
9994
  if (code3.includes("REVOK")) return "SHARE_REVOKED";
@@ -10211,7 +10227,7 @@ var ShareRecipientClient = class {
10211
10227
  if (portableDelegation !== void 0 && kv !== void 0) {
10212
10228
  const result2 = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
10213
10229
  if (!result2.ok) {
10214
- if (result2.error.code === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED || result2.error.code === import_sdk_services3.ErrorCodes.KV_CONFLICT) throw new ShareConflict(resolvedPath, result2.error.meta?.etag);
10230
+ if (result2.error.code === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED) throw new ShareConflict(resolvedPath, result2.error.meta?.etag);
10215
10231
  throw result2.error;
10216
10232
  }
10217
10233
  return { etag: result2.data.headers.etag };
@@ -10219,7 +10235,7 @@ var ShareRecipientClient = class {
10219
10235
  if (policySession !== void 0) return this.nativeSave(envelope, policySession, resolvedPath, bytes2, input);
10220
10236
  const result = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
10221
10237
  if (!result.ok) {
10222
- if (result.error.code === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED || result.error.code === import_sdk_services3.ErrorCodes.KV_CONFLICT) throw new ShareConflict(resolvedPath, result.error.meta?.etag);
10238
+ if (result.error.code === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED) throw new ShareConflict(resolvedPath, result.error.meta?.etag);
10223
10239
  throw result.error;
10224
10240
  }
10225
10241
  return { etag: result.data.headers.etag };
@@ -12780,6 +12796,37 @@ async function parseSignedSiweCacao(authorization, expectedCid) {
12780
12796
  return { cid: cid2, issuer, audience, attenuation, ...expiresAt === void 0 ? {} : { expiresAt } };
12781
12797
  }
12782
12798
 
12799
+ // src/delegations/terminal.ts
12800
+ var import_blake35 = require("@noble/hashes/blake3");
12801
+ var import_ed2551910 = require("@noble/curves/ed25519");
12802
+ var TERMINAL_DELEGATION_FACT = Object.freeze({
12803
+ "xyz.tinycloud.policy/delegationMode": "terminal"
12804
+ });
12805
+ function markDelegationTerminal(token, key) {
12806
+ const [headerSegment, payloadSegment, signatureSegment] = token.split(".");
12807
+ const decoder = new TextDecoder();
12808
+ const header = JSON.parse(decoder.decode(decodeBase64Url(headerSegment)));
12809
+ const payload = JSON.parse(decoder.decode(decodeBase64Url(payloadSegment)));
12810
+ if (signatureSegment === void 0 || header.alg !== "EdDSA" || key.kty !== "OKP" || key.crv !== "Ed25519" || !key.d) {
12811
+ throw new Error("terminal delegations require an Ed25519 session key");
12812
+ }
12813
+ const privateKey = decodeBase64Url(key.d);
12814
+ const signer = `did:key:${base58btc.encode(Uint8Array.of(237, 1, ...import_ed2551910.ed25519.getPublicKey(privateKey)))}`;
12815
+ if (typeof payload.iss !== "string" || payload.iss.split("#")[0] !== signer) {
12816
+ throw new Error("session key is not the delegation issuer");
12817
+ }
12818
+ const facts = payload.fct ?? [];
12819
+ if (!Array.isArray(facts)) throw new Error("delegation facts are not an array");
12820
+ const encoder = new TextEncoder();
12821
+ let delegation = token;
12822
+ if (!facts.some((fact) => fact?.["xyz.tinycloud.policy/delegationMode"] === "terminal")) {
12823
+ payload.fct = [...facts, { ...TERMINAL_DELEGATION_FACT }];
12824
+ const signingInput = `${headerSegment}.${encodeBase64Url(encoder.encode(JSON.stringify(payload)))}`;
12825
+ delegation = `${signingInput}.${encodeBase64Url(import_ed2551910.ed25519.sign(encoder.encode(signingInput), privateKey))}`;
12826
+ }
12827
+ return { delegation, cid: CID.createV1(85, create(30, (0, import_blake35.blake3)(encoder.encode(delegation)))).toString() };
12828
+ }
12829
+
12783
12830
  // src/networkId.ts
12784
12831
  var import_sdk_services4 = require("@tinycloud/sdk-services");
12785
12832
  function canonicalizeNetworkId(networkId) {
@@ -12842,7 +12889,16 @@ var PersistedSessionDataSchema = import_zod8.z.object({
12842
12889
  * for backward compatibility with sessions persisted before this field
12843
12890
  * existed — those restore and lazily re-resolve their hosts.
12844
12891
  */
12845
- tinycloudHosts: import_zod8.z.array(import_zod8.z.string()).optional()
12892
+ tinycloudHosts: import_zod8.z.array(import_zod8.z.string()).optional(),
12893
+ /**
12894
+ * Replica gate stamp from a fresh sign-in (`establishSessionStamp`). Restore validates it with
12895
+ * `restoreSessionStamp` and never re-establishes it. Absent for sessions persisted before
12896
+ * replication existed; restore treats that as `not_established`.
12897
+ */
12898
+ replicaStamp: import_zod8.z.object({
12899
+ incarnation: import_zod8.z.string().min(1),
12900
+ lifecycleEpoch: import_zod8.z.number().int().nonnegative()
12901
+ }).strict().optional()
12846
12902
  });
12847
12903
  var TinyCloudSessionSchema = import_zod8.z.object({
12848
12904
  /** User's Ethereum address */
@@ -18358,7 +18414,7 @@ function portForProtocol(protocol) {
18358
18414
  }
18359
18415
 
18360
18416
  // src/location.ts
18361
- var import_ed2551910 = require("@noble/curves/ed25519");
18417
+ var import_ed2551911 = require("@noble/curves/ed25519");
18362
18418
  var import_viem6 = require("viem");
18363
18419
  var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
18364
18420
  var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
@@ -19126,7 +19182,7 @@ function verifyDidKeySignature(did, payload, signature) {
19126
19182
  "did:key signature must be a base64url Ed25519 signature"
19127
19183
  );
19128
19184
  }
19129
- return import_ed2551910.ed25519.verify(
19185
+ return import_ed2551911.ed25519.verify(
19130
19186
  signatureBytes,
19131
19187
  new TextEncoder().encode(payload),
19132
19188
  publicKey
@@ -19134,7 +19190,7 @@ function verifyDidKeySignature(did, payload, signature) {
19134
19190
  }
19135
19191
  function verifyDidKeyEd25519Signature(did, payload, signature) {
19136
19192
  const publicKey = ed25519PublicKeyFromDidKey2(did);
19137
- return import_ed2551910.ed25519.verify(signature, payload, publicKey);
19193
+ return import_ed2551911.ed25519.verify(signature, payload, publicKey);
19138
19194
  }
19139
19195
  function ed25519PublicKeyFromDidKey2(did) {
19140
19196
  const identifier = did.slice("did:key:".length);