@tinycloud/sdk-core 3.8.0-beta.2 → 3.8.0-beta.21

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.
@@ -426,6 +426,7 @@ interface UnifiedContentSource {
426
426
  readonly kvResource: string;
427
427
  readonly selector: UnifiedResourceSelector;
428
428
  readonly encryptionNetwork: string;
429
+ readonly encryptionKeyPath?: string;
429
430
  readonly encryptedSymmetricKeyDigestHex: string;
430
431
  readonly keyVersion: number;
431
432
  readonly mode: "mutable" | "immutable";
@@ -426,6 +426,7 @@ interface UnifiedContentSource {
426
426
  readonly kvResource: string;
427
427
  readonly selector: UnifiedResourceSelector;
428
428
  readonly encryptionNetwork: string;
429
+ readonly encryptionKeyPath?: string;
429
430
  readonly encryptedSymmetricKeyDigestHex: string;
430
431
  readonly keyVersion: number;
431
432
  readonly mode: "mutable" | "immutable";
@@ -189,7 +189,11 @@ var DelegationErrorCodes = {
189
189
  KV_SERVICE_UNAVAILABLE: "KV_SERVICE_UNAVAILABLE",
190
190
  DATA_FETCH_FAILED: "DATA_FETCH_FAILED",
191
191
  VALIDATION_ERROR: "VALIDATION_ERROR",
192
- UNSUPPORTED_OPERATION: "UNSUPPORTED_OPERATION"
192
+ UNSUPPORTED_OPERATION: "UNSUPPORTED_OPERATION",
193
+ /** The node answered 503: the delegation chain is too deep to evaluate right now. Retry later. */
194
+ CHAIN_TOO_DEEP: "CHAIN_TOO_DEEP",
195
+ /** The node answered 400 "invalid delegation query cursor": malformed, foreign or from another filter. Start the listing again without it. */
196
+ INVALID_CURSOR: "INVALID_CURSOR"
193
197
  };
194
198
  var DelegationSchema = import_zod.z.object({
195
199
  /** Content identifier (CID) of the delegation */
@@ -266,7 +270,7 @@ var AccountDelegationPageSchema = import_zod.z.object({
266
270
  nextCursor: import_zod.z.string().optional()
267
271
  }).strict();
268
272
  var AccountDelegationQueryOptionsSchema = import_zod.z.object({
269
- direction: import_zod.z.enum(["granted", "received", "all"]).optional(),
273
+ direction: import_zod.z.enum(["granted", "received", "all", "issued"]).optional(),
270
274
  status: import_zod.z.enum(["active", "pending", "expired", "revoked", "ancestor_revoked"]).optional(),
271
275
  space: import_zod.z.string().trim().min(1).optional(),
272
276
  limit: import_zod.z.number().int().min(1).max(100).optional(),
@@ -452,6 +456,8 @@ var DelegationManagerConfigSchema = import_zod.z.object({
452
456
  ).optional(),
453
457
  /** Optional owner-signed authorization for direct CID revocation */
454
458
  signOwnerRevocation: import_zod.z.custom().optional(),
459
+ /** Optional signer for proofless invocations by the session's own did:key (issued-delegation list and revoke) */
460
+ sessionInvocationSigner: import_zod.z.custom().optional(),
455
461
  /** Optional custom fetch implementation */
456
462
  fetch: import_zod.z.unknown().refine(
457
463
  (val) => val === void 0 || typeof val === "function",
@@ -547,7 +553,7 @@ var CreateDelegationWasmResultSchema = import_zod.z.object({
547
553
  resources: import_zod.z.array(DelegatedResourceSchema)
548
554
  });
549
555
 
550
- // src/delegations/DelegationManager.ts
556
+ // src/delegations/shared.ts
551
557
  var DelegationAction = {
552
558
  REVOKE: "tinycloud.delegation/revoke",
553
559
  STATUS: "tinycloud.delegation/status",
@@ -564,6 +570,8 @@ function createError(code3, message, cause, meta) {
564
570
  meta
565
571
  };
566
572
  }
573
+
574
+ // src/delegations/DelegationManager.ts
567
575
  async function readInvokedJson(response, action) {
568
576
  const text = await response.text();
569
577
  if (text.trim() === "") {
@@ -586,11 +594,13 @@ var DelegationManager = class {
586
594
  * @param config - Configuration including hosts, session, and invoke function
587
595
  */
588
596
  constructor(config) {
597
+ this.issuedState = { issuedQuerySupported: false };
589
598
  this.hosts = config.hosts;
590
599
  this.session = config.session;
591
600
  this.invoke = config.invoke;
592
601
  this.invokeAny = config.invokeAny;
593
602
  this.signOwnerRevocation = config.signOwnerRevocation;
603
+ this.sessionInvocationSigner = config.sessionInvocationSigner;
594
604
  this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
595
605
  this.accountSpaceId = config.accountSpaceId;
596
606
  }
@@ -813,8 +823,14 @@ var DelegationManager = class {
813
823
  };
814
824
  }
815
825
  }
816
- /** Query lifecycle-complete delegation history for the authenticated account. */
817
- async query(options = {}) {
826
+ /**
827
+ * Query lifecycle-complete delegation history for the authenticated account.
828
+ *
829
+ * `scope.spaces` lists the spaces to sign `tinycloud.delegation/list` for, in order. Omitted, the
830
+ * account space is tried, then the session's own space. A caller that knows which of them the session
831
+ * holds passes only those; an empty list sends nothing and answers PERMISSION_DENIED.
832
+ */
833
+ async query(options = {}, scope = {}) {
818
834
  const validated = AccountDelegationQueryOptionsSchema.safeParse(options);
819
835
  if (!validated.success) {
820
836
  return {
@@ -827,6 +843,7 @@ var DelegationManager = class {
827
843
  )
828
844
  };
829
845
  }
846
+ if (validated.data.direction === "issued") return this.queryIssued(validated.data);
830
847
  if (!this.invokeAny) {
831
848
  return {
832
849
  ok: false,
@@ -848,7 +865,7 @@ var DelegationManager = class {
848
865
  }
849
866
  try {
850
867
  let response;
851
- for (const spaceId of /* @__PURE__ */ new Set([accountSpaceId, this.session.spaceId])) {
868
+ for (const spaceId of new Set(scope.spaces ?? [accountSpaceId, this.session.spaceId])) {
852
869
  const headers = Object.fromEntries(new Headers(this.invokeAny(this.session, [{
853
870
  spaceId,
854
871
  service: "delegation",
@@ -908,6 +925,45 @@ var DelegationManager = class {
908
925
  };
909
926
  }
910
927
  }
928
+ /** The state the lazily loaded issued-delegation module reads and updates. */
929
+ issuedContext() {
930
+ return {
931
+ host: this.host,
932
+ fetchFn: this.fetchFn,
933
+ sessionInvocationSigner: this.sessionInvocationSigner,
934
+ state: this.issuedState
935
+ };
936
+ }
937
+ /**
938
+ * Lists the delegations this session's own key issued (`direction: "issued"`).
939
+ * The implementation loads on first use.
940
+ */
941
+ async queryIssued(options) {
942
+ const issued = await import("@tinycloud/sdk-core/delegations/issued");
943
+ return issued.queryIssued(this.issuedContext(), options);
944
+ }
945
+ /**
946
+ * Every delegation this session's key issued, following `nextCursor` until
947
+ * it is absent. `maxItems` stops early once that many are collected;
948
+ * `untilCid` stops after the page that contains that delegation. Items come
949
+ * in CID order (each carries `issuedAt`). The implementation loads on first use.
950
+ */
951
+ async queryAllIssued(options = {}) {
952
+ const issued = await import("@tinycloud/sdk-core/delegations/issued");
953
+ return issued.queryAllIssued((page) => this.query(page), options);
954
+ }
955
+ /**
956
+ * Revokes a delegation this session's key issued, with no proof: a UCAN
957
+ * signed by the session's own did:key carrying `urn:cid:<cid>` and
958
+ * `tinycloud.delegation/revoke`. Revoking a delegation that is already revoked
959
+ * succeeds. A refusal (the key is not the delegator) carries the node's
960
+ * message; 503 means the chain is too deep right now, retry later.
961
+ * The implementation loads on first use.
962
+ */
963
+ async revokeIssued(cid2) {
964
+ const issued = await import("@tinycloud/sdk-core/delegations/issued");
965
+ return issued.revokeIssued(this.issuedContext(), cid2);
966
+ }
911
967
  /**
912
968
  * Gets the full delegation chain for a given delegation.
913
969
  *
@@ -1245,6 +1301,7 @@ function validateSharingServiceConfig(data) {
1245
1301
  var import_ms = __toESM(require("ms"), 1);
1246
1302
  var import_bootstrap = require("@tinycloud/bootstrap");
1247
1303
  var import_sdk_services = require("@tinycloud/sdk-services");
1304
+ var import_resource = require("@tinycloud/sdk-services/encryption/resource");
1248
1305
  var SERVICE_SHORT_TO_LONG = Object.freeze({
1249
1306
  kv: "tinycloud.kv",
1250
1307
  space: "tinycloud.space",
@@ -1260,6 +1317,9 @@ var SERVICE_LONG_TO_SHORT = Object.freeze(
1260
1317
  Object.entries(SERVICE_SHORT_TO_LONG).map(([s, l]) => [l, s])
1261
1318
  )
1262
1319
  );
1320
+ var KEY_SEGMENT = "[a-z0-9][a-z0-9._-]{0,63}";
1321
+ var KEY_APP_ID = new RegExp(`^${KEY_SEGMENT}$`);
1322
+ var KEY_PATH = new RegExp(`^${KEY_SEGMENT}(?:/${KEY_SEGMENT}){2,7}$`);
1263
1323
 
1264
1324
  // src/identity.ts
1265
1325
  var import_viem = require("viem");
@@ -1326,6 +1386,7 @@ function principalDid(didUrl) {
1326
1386
  }
1327
1387
 
1328
1388
  // src/capabilities.ts
1389
+ var import_resource2 = require("@tinycloud/sdk-services/encryption/resource");
1329
1390
  var CaveatedDelegationUnsupportedError = class extends Error {
1330
1391
  constructor(entries) {
1331
1392
  super(
@@ -2551,7 +2612,7 @@ var hashes = { ...sha2_browser_exports, ...identity_exports2 };
2551
2612
  var import_ed255194 = require("@noble/curves/ed25519");
2552
2613
 
2553
2614
  // src/delegations/ShareRecipientClient.ts
2554
- var import_sdk_services3 = require("@tinycloud/sdk-services");
2615
+ var import_sdk_services4 = require("@tinycloud/sdk-services");
2555
2616
  var import_ed255193 = require("@noble/curves/ed25519");
2556
2617
  var import_sha2564 = require("@noble/hashes/sha256");
2557
2618
 
@@ -3632,6 +3693,7 @@ var import_sha2563 = require("@noble/hashes/sha256");
3632
3693
  var import_blake32 = require("@noble/hashes/blake3");
3633
3694
  var import_ed255192 = require("@noble/curves/ed25519");
3634
3695
  var import_zod4 = require("zod");
3696
+ var import_sdk_services3 = require("@tinycloud/sdk-services");
3635
3697
 
3636
3698
  // src/policy/errors.ts
3637
3699
  var SignedObjectProfileError = class extends Error {
@@ -4178,9 +4240,9 @@ function redactedCode(error) {
4178
4240
  if (error instanceof ShareConflict) return error.code;
4179
4241
  const code3 = error && typeof error === "object" && "code" in error ? error.code : void 0;
4180
4242
  if (typeof code3 !== "string") return "SHARE_INVALID";
4181
- if (code3 === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED || code3 === "412") return "SHARE_CONFLICT";
4182
- if (code3 === import_sdk_services3.ErrorCodes.NODE_BUSY || code3 === import_sdk_services3.ErrorCodes.REQUEST_TIMEOUT) return "SHARE_OFFLINE";
4183
- if (code3 === import_sdk_services3.ErrorCodes.OUTCOME_UNKNOWN) return "SHARE_WRITE_FAILED";
4243
+ if (code3 === import_sdk_services4.ErrorCodes.KV_PRECONDITION_FAILED || code3 === "412") return "SHARE_CONFLICT";
4244
+ if (code3 === import_sdk_services4.ErrorCodes.NODE_BUSY || code3 === import_sdk_services4.ErrorCodes.REQUEST_TIMEOUT) return "SHARE_OFFLINE";
4245
+ if (code3 === import_sdk_services4.ErrorCodes.OUTCOME_UNKNOWN) return "SHARE_WRITE_FAILED";
4184
4246
  if (code3 === "KV_NOT_FOUND" || code3 === "NOT_FOUND" || code3 === "404") return "SHARE_NOT_FOUND";
4185
4247
  if (code3.includes("EXPIRED") || code3 === "expired") return "SHARE_EXPIRED";
4186
4248
  if (code3.includes("REVOK")) return "SHARE_REVOKED";
@@ -4419,7 +4481,7 @@ var ShareRecipientClient = class {
4419
4481
  if (portableDelegation !== void 0 && kv !== void 0) {
4420
4482
  const result2 = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
4421
4483
  if (!result2.ok) {
4422
- if (result2.error.code === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED) throw new ShareConflict(resolvedPath, result2.error.meta?.etag);
4484
+ if (result2.error.code === import_sdk_services4.ErrorCodes.KV_PRECONDITION_FAILED) throw new ShareConflict(resolvedPath, result2.error.meta?.etag);
4423
4485
  throw result2.error;
4424
4486
  }
4425
4487
  return { etag: result2.data.headers.etag };
@@ -4427,7 +4489,7 @@ var ShareRecipientClient = class {
4427
4489
  if (policySession !== void 0) return this.nativeSave(envelope, policySession, resolvedPath, bytes2, input);
4428
4490
  const result = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
4429
4491
  if (!result.ok) {
4430
- if (result.error.code === import_sdk_services3.ErrorCodes.KV_PRECONDITION_FAILED) throw new ShareConflict(resolvedPath, result.error.meta?.etag);
4492
+ if (result.error.code === import_sdk_services4.ErrorCodes.KV_PRECONDITION_FAILED) throw new ShareConflict(resolvedPath, result.error.meta?.etag);
4431
4493
  throw result.error;
4432
4494
  }
4433
4495
  return { etag: result.data.headers.etag };
@@ -4511,8 +4573,8 @@ var ShareRecipientClient = class {
4511
4573
  if (this.options.createKVService !== void 0) {
4512
4574
  return this.options.createKVService({ hosts: [origin], session, invoke, fetch: this.fetchFn });
4513
4575
  }
4514
- const context = new import_sdk_services3.ServiceContext({ hosts: [origin], session, invoke, fetch: this.fetchFn });
4515
- const service = new import_sdk_services3.KVService({ prefix: "" });
4576
+ const context = new import_sdk_services4.ServiceContext({ hosts: [origin], session, invoke, fetch: this.fetchFn });
4577
+ const service = new import_sdk_services4.KVService({ prefix: "" });
4516
4578
  context.registerService("kv", service);
4517
4579
  service.initialize(context);
4518
4580
  return service;