@tinycloud/operations 0.3.4-beta.6 → 0.4.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.js CHANGED
@@ -6965,6 +6965,9 @@ function evaluateOperationAuthority(granted, required, resolveSpace2) {
6965
6965
  missing: canonicalizeCapabilities(missing)
6966
6966
  };
6967
6967
  }
6968
+ function delegationWithinRequest(requested, effective, resolveSpace2) {
6969
+ return requested.length > 0 && evaluateOperationAuthority(requested, canonicalizeCapabilities(effective), resolveSpace2).satisfied;
6970
+ }
6968
6971
  function isExactCapabilityMemberSubset(hinted, planned, resolveSpace2) {
6969
6972
  const canonicalHinted = canonicalizeOperationCapabilities(hinted, resolveSpace2);
6970
6973
  const canonicalPlanned = canonicalizeOperationCapabilities(planned, resolveSpace2);
@@ -7093,6 +7096,11 @@ import {
7093
7096
  } from "fs/promises";
7094
7097
  import { homedir } from "os";
7095
7098
  import { basename, dirname, isAbsolute, join, relative, resolve } from "path";
7099
+ function processWideContext(key) {
7100
+ var _a;
7101
+ const registry = globalThis;
7102
+ return registry[_a = Symbol.for(key)] ?? (registry[_a] = new AsyncLocalStorage());
7103
+ }
7096
7104
  function tinycloudHomePath() {
7097
7105
  const home = invocationStateRoot.getStore() ?? process.env.TC_HOME ?? process.env.HOME ?? process.env.USERPROFILE ?? homedir();
7098
7106
  return join(home, ".tinycloud");
@@ -7427,8 +7435,8 @@ var init_state = __esm({
7427
7435
  TEST_LOCK_CLAIMED_BARRIER_DIR = "TC_TEST_PROFILE_LOCK_CLAIMED_BARRIER_DIR";
7428
7436
  TEST_LOCK_FENCED_BARRIER_DIR = "TC_TEST_PROFILE_LOCK_FENCED_BARRIER_DIR";
7429
7437
  TEST_LOCK_VERIFIED_BARRIER_DIR = "TC_TEST_PROFILE_LOCK_VERIFIED_BARRIER_DIR";
7430
- invocationStateRoot = new AsyncLocalStorage();
7431
- heldProfileLocks = new AsyncLocalStorage();
7438
+ invocationStateRoot = processWideContext("tinycloud.operations.invocationStateRoot.v1");
7439
+ heldProfileLocks = processWideContext("tinycloud.operations.heldProfileLocks.v1");
7432
7440
  ProfileLockTimeoutError = class extends Error {
7433
7441
  constructor(profile, timeoutMs) {
7434
7442
  super(`Timed out waiting for the profile lock for "${profile}" after ${timeoutMs}ms.`);
@@ -7645,7 +7653,7 @@ function evaluateArtifactAuthority(granted, required, resolveSpace2) {
7645
7653
  function defaultRequestId(now) {
7646
7654
  return `req_${now.getTime().toString(36)}_${randomUUID2().replace(/-/g, "")}`;
7647
7655
  }
7648
- var THIRTY_DAYS_MS, PermissionEntrySchema, CommandSchema, LegacyPermissionRequestArtifactSchema, PortableDelegationSchema, PermissionRequestArtifactSchema, DelegationImportArtifactSchema;
7656
+ var THIRTY_DAYS_MS, PermissionEntrySchema, CommandSchema, LegacyPermissionRequestArtifactSchema, PortableDelegationSchema, PermissionRequestArtifactSchema, DelegationImportArtifactSchema, DelegationRequestBindingSchema;
7649
7657
  var init_artifacts = __esm({
7650
7658
  "src/artifacts.ts"() {
7651
7659
  "use strict";
@@ -7718,16 +7726,12 @@ var init_artifacts = __esm({
7718
7726
  expiry: z2.string().datetime({ offset: true }).optional(),
7719
7727
  prompted: z2.boolean().optional()
7720
7728
  }).strict();
7729
+ DelegationRequestBindingSchema = PermissionRequestArtifactSchema.pick({ requestId: true, requested: true }).strict();
7721
7730
  }
7722
7731
  });
7723
7732
 
7724
7733
  // src/secrets.ts
7725
- import {
7726
- canonicalizeAddress,
7727
- makePkhSpaceId,
7728
- parsePkhDid,
7729
- parseSpaceUri
7730
- } from "@tinycloud/node-sdk";
7734
+ import * as nodeSdk from "@tinycloud/node-sdk";
7731
7735
  function normalizeSecretsGetInput(input) {
7732
7736
  const reference = resolveSecretReference(input);
7733
7737
  return {
@@ -7783,18 +7787,18 @@ function resolveOperationSpace(space, node, ownerSpace) {
7783
7787
  if (resolved !== void 0) return canonicalizeSpaceUri(resolved);
7784
7788
  }
7785
7789
  const did = typeof candidate.did === "string" ? candidate.did : void 0;
7786
- const pkh = did === void 0 ? null : parsePkhDid(did);
7790
+ const pkh = did === void 0 ? null : nodeSdk.parsePkhDid(did);
7787
7791
  if (pkh === null) {
7788
7792
  throw invalidSecretInput();
7789
7793
  }
7790
- return makePkhSpaceId(pkh.address, pkh.chainId, space);
7794
+ return nodeSdk.makePkhSpaceId(pkh.address, pkh.chainId, space);
7791
7795
  }
7792
7796
  function ownedSpaceForName(ownerSpace, name) {
7793
- const parsed = parseSpaceUri(ownerSpace);
7797
+ const parsed = nodeSdk.parseSpaceUri(ownerSpace);
7794
7798
  if (parsed === null) return void 0;
7795
7799
  try {
7796
- const pkh = parsePkhDid(parsed.owner);
7797
- return pkh === null ? void 0 : makePkhSpaceId(pkh.address, pkh.chainId, name);
7800
+ const pkh = nodeSdk.parsePkhDid(parsed.owner);
7801
+ return pkh === null ? void 0 : nodeSdk.makePkhSpaceId(pkh.address, pkh.chainId, name);
7798
7802
  } catch {
7799
7803
  return void 0;
7800
7804
  }
@@ -7809,7 +7813,7 @@ function canonicalizeSpaceUri(space) {
7809
7813
  /^tinycloud:pkh:eip155:(\d+):(0x[0-9a-fA-F]{40}):([^:]+)$/
7810
7814
  );
7811
7815
  if (pkh !== null) {
7812
- return `tinycloud:pkh:eip155:${pkh[1]}:${canonicalizeAddress(pkh[2]).toLowerCase()}:${pkh[3]}`;
7816
+ return `tinycloud:pkh:eip155:${pkh[1]}:${nodeSdk.canonicalizeAddress(pkh[2]).toLowerCase()}:${pkh[3]}`;
7813
7817
  }
7814
7818
  return space;
7815
7819
  }
@@ -7862,7 +7866,7 @@ var init_secrets = __esm({
7862
7866
  });
7863
7867
 
7864
7868
  // src/operations/auth.ts
7865
- import * as nodeSdk from "@tinycloud/node-sdk";
7869
+ import * as nodeSdk2 from "@tinycloud/node-sdk";
7866
7870
  import { z as z3 } from "zod";
7867
7871
  async function requestExactAuthority(context, input) {
7868
7872
  const sessionDid = context.summary.sessionDid;
@@ -8007,7 +8011,7 @@ async function importRequestBoundDelegation(context, input) {
8007
8011
  };
8008
8012
  let activated;
8009
8013
  try {
8010
- activated = await nodeSdk.activateValidatedRuntimeDelegation(
8014
+ activated = await nodeSdk2.activateValidatedRuntimeDelegation(
8011
8015
  context.runtime.node,
8012
8016
  delegation,
8013
8017
  { host }
@@ -8023,11 +8027,7 @@ async function importRequestBoundDelegation(context, input) {
8023
8027
  context.runtime.node,
8024
8028
  context.summary.space
8025
8029
  );
8026
- if (request.requested.length === 0 || !evaluateOperationAuthority(
8027
- request.requested,
8028
- effectivePermissions,
8029
- resolveSpace2
8030
- ).satisfied) {
8030
+ if (!delegationWithinRequest(request.requested, effectivePermissions, resolveSpace2)) {
8031
8031
  return operationFailure(
8032
8032
  "DELEGATION_REJECTED",
8033
8033
  "The delegation exceeds the stored authority request."
@@ -8055,12 +8055,19 @@ async function importRequestBoundDelegation(context, input) {
8055
8055
  )
8056
8056
  };
8057
8057
  }
8058
- const alreadyPresent = records.some((entry) => delegationCid(entry) === activated.cid);
8058
+ const record = {
8059
+ delegation: activated.delegation,
8060
+ permissions: activated.effectivePermissions,
8061
+ authorityRequest: {
8062
+ requestId: request.requestId,
8063
+ requested: request.requested
8064
+ }
8065
+ };
8066
+ const position = records.findIndex((entry) => delegationCid(entry) === activated.cid);
8067
+ const alreadyPresent = position !== -1;
8068
+ const others = records.filter((entry) => delegationCid(entry) !== activated.cid);
8059
8069
  return {
8060
- records: alreadyPresent ? records : [...records, {
8061
- delegation: activated.delegation,
8062
- permissions: activated.effectivePermissions
8063
- }],
8070
+ records: alreadyPresent ? [...others.slice(0, position), record, ...others.slice(position)] : [...records, record],
8064
8071
  result: {
8065
8072
  status: "ok",
8066
8073
  output: {
@@ -9788,6 +9795,173 @@ ORDER BY type, name`;
9788
9795
  }
9789
9796
  });
9790
9797
 
9798
+ // src/delegation-binding.ts
9799
+ import { join as join2 } from "path";
9800
+ import * as nodeSdk3 from "@tinycloud/node-sdk";
9801
+ function bindingMigrationPath(profile) {
9802
+ return join2(profilePath(profile), "delegation-binding-migration.json");
9803
+ }
9804
+ function storedDelegationKind(entry) {
9805
+ if (!isRecord4(entry)) return "refused";
9806
+ const delegation = entry.delegation;
9807
+ if (!isRecord4(delegation)) return "refused";
9808
+ const header = delegation.delegationHeader;
9809
+ if (!isRecord4(header) || Object.keys(header).length !== 1 || !Object.prototype.hasOwnProperty.call(header, "Authorization") || typeof header.Authorization !== "string") {
9810
+ return "refused";
9811
+ }
9812
+ if ("siweProof" in delegation) return "signed-login";
9813
+ if (header.Authorization.includes(".")) return "compact";
9814
+ return "authorityRequest" in entry ? "refused" : "other";
9815
+ }
9816
+ function replayLimit(entry, migrated) {
9817
+ const kind = storedDelegationKind(entry);
9818
+ if (!isRecord4(entry) || kind !== "compact" && kind !== "signed-login") return void 0;
9819
+ const binding = DelegationRequestBindingSchema.safeParse(entry.authorityRequest);
9820
+ if (binding.success) return binding.data.requested;
9821
+ return !migrated && kind === "compact" && !("authorityRequest" in entry) ? "signed" : void 0;
9822
+ }
9823
+ function bindToSignedCapabilities(record, signed, source, recordedAt = (/* @__PURE__ */ new Date()).toISOString()) {
9824
+ return {
9825
+ ...record,
9826
+ authorityRequest: DelegationRequestBindingSchema.parse({
9827
+ requestId: `${REQUEST_ID_PREFIX[source]}:${record.delegation.cid}`,
9828
+ requested: structuredClone(signed)
9829
+ }),
9830
+ authorityRequestAudit: { source, recordedAt, note: BINDING_NOTES[source] }
9831
+ };
9832
+ }
9833
+ async function prepareStoredDelegationReplay(profile, node, options) {
9834
+ if (await bindingMigrationRecorded(profile)) return true;
9835
+ if (!options.migrate || !await holdsPersistedSession(profile, node)) return false;
9836
+ try {
9837
+ return await withProfileLock(profile, async () => {
9838
+ if (await bindingMigrationRecorded(profile)) return true;
9839
+ if (!await holdsPersistedSession(profile, node)) return false;
9840
+ const recordedAt = (/* @__PURE__ */ new Date()).toISOString();
9841
+ const bound = /* @__PURE__ */ new Map();
9842
+ const unbound = [];
9843
+ for (const entry of await readAdditionalDelegations(profile)) {
9844
+ if (!isRecord4(entry) || "authorityRequest" in entry || storedDelegationKind(entry) !== "compact") continue;
9845
+ const migrated = await migratedRecord(node, entry, options.host, recordedAt);
9846
+ if (migrated === void 0) unbound.push(String(storedCid(entry)));
9847
+ else bound.set(recordKey(entry), migrated);
9848
+ }
9849
+ if (bound.size > 0) {
9850
+ await updateProfileStore(profile, "additional-delegations", (records) => ({
9851
+ records: records.map((entry) => {
9852
+ const key = !isRecord4(entry) || "authorityRequest" in entry ? void 0 : recordKey(entry);
9853
+ return (key === void 0 ? void 0 : bound.get(key)) ?? entry;
9854
+ }),
9855
+ result: void 0
9856
+ }));
9857
+ }
9858
+ await writeJsonAtomic(bindingMigrationPath(profile), {
9859
+ formatVersion: 1,
9860
+ migratedAt: recordedAt,
9861
+ bound: [...bound.values()].map(storedCid),
9862
+ unbound
9863
+ });
9864
+ return true;
9865
+ }, { timeoutMs: MIGRATION_LOCK_TIMEOUT_MS });
9866
+ } catch {
9867
+ return false;
9868
+ }
9869
+ }
9870
+ async function holdsPersistedSession(profile, node) {
9871
+ try {
9872
+ const persisted = await readSession(profile);
9873
+ return typeof persisted?.verificationMethod === "string" && typeof node.sessionDid === "string" && persisted.verificationMethod.split("#", 1)[0] === node.sessionDid.split("#", 1)[0];
9874
+ } catch {
9875
+ return false;
9876
+ }
9877
+ }
9878
+ async function migratedRecord(node, entry, host, recordedAt) {
9879
+ const delegation = normalizeStoredDelegation(entry);
9880
+ if (delegation === void 0) return void 0;
9881
+ const signed = await signedCapabilities(node, delegation, host);
9882
+ if (signed === void 0) return void 0;
9883
+ try {
9884
+ return bindToSignedCapabilities({ ...entry, delegation: { ...entry.delegation, cid: delegation.cid } }, signed, "migration", recordedAt);
9885
+ } catch {
9886
+ return void 0;
9887
+ }
9888
+ }
9889
+ async function replayStoredDelegation(node, entry, options) {
9890
+ const delegation = normalizeStoredDelegation(entry);
9891
+ if (delegation === void 0 || delegation.expiry.getTime() <= Date.now()) return void 0;
9892
+ const limit = replayLimit(entry, options.migrated);
9893
+ if (limit === void 0) return void 0;
9894
+ const authorize = limit === "signed" ? () => true : (effective) => delegationWithinRequest(limit, effective, options.resolveSpace);
9895
+ try {
9896
+ return await nodeSdk3.activateValidatedRuntimeDelegation(node, delegation, { host: options.host, authorize });
9897
+ } catch {
9898
+ return void 0;
9899
+ }
9900
+ }
9901
+ async function bindingMigrationRecorded(profile) {
9902
+ try {
9903
+ return await readJson(bindingMigrationPath(profile)) !== null;
9904
+ } catch {
9905
+ return true;
9906
+ }
9907
+ }
9908
+ async function signedCapabilities(node, delegation, host) {
9909
+ let signed;
9910
+ try {
9911
+ await nodeSdk3.activateValidatedRuntimeDelegation(node, delegation, {
9912
+ // The transport host is not signed authority; check it at replay instead.
9913
+ host: delegation.host ?? host,
9914
+ authorize: (effective) => {
9915
+ signed = effective;
9916
+ return false;
9917
+ }
9918
+ });
9919
+ } catch {
9920
+ }
9921
+ return signed;
9922
+ }
9923
+ function normalizeStoredDelegation(entry) {
9924
+ if (!isRecord4(entry)) return void 0;
9925
+ const raw = entry.delegation;
9926
+ if (!isRecord4(raw) || !isRecord4(raw.delegationHeader)) return void 0;
9927
+ const expiry = raw.expiry instanceof Date ? raw.expiry : typeof raw.expiry === "string" ? new Date(raw.expiry) : void 0;
9928
+ if (expiry === void 0 || Number.isNaN(expiry.getTime()) || typeof raw.cid !== "string" || typeof raw.spaceId !== "string" || typeof raw.path !== "string" || !Array.isArray(raw.actions) || !raw.actions.every((action) => typeof action === "string") || typeof raw.delegateDID !== "string" || typeof raw.ownerAddress !== "string" || typeof raw.chainId !== "number" || typeof raw.delegationHeader.Authorization !== "string") {
9929
+ return void 0;
9930
+ }
9931
+ return { ...raw, expiry };
9932
+ }
9933
+ function storedCid(entry) {
9934
+ const cid = isRecord4(entry) && isRecord4(entry.delegation) ? entry.delegation.cid : void 0;
9935
+ return typeof cid === "string" ? cid : void 0;
9936
+ }
9937
+ function recordKey(entry) {
9938
+ const delegation = entry.delegation;
9939
+ if (!isRecord4(delegation) || !isRecord4(delegation.delegationHeader)) return void 0;
9940
+ return JSON.stringify([delegation.cid, delegation.delegationHeader.Authorization]);
9941
+ }
9942
+ function isRecord4(value) {
9943
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9944
+ }
9945
+ var REQUEST_ID_PREFIX, BINDING_NOTES, MIGRATION_LOCK_TIMEOUT_MS;
9946
+ var init_delegation_binding = __esm({
9947
+ "src/delegation-binding.ts"() {
9948
+ "use strict";
9949
+ init_artifacts();
9950
+ init_authority();
9951
+ init_state();
9952
+ init_secrets();
9953
+ REQUEST_ID_PREFIX = {
9954
+ migration: "migrated",
9955
+ "unbound-import": "unbound-import"
9956
+ };
9957
+ BINDING_NOTES = {
9958
+ migration: "Stored without a request binding before bindings were required. Bound at migration to exactly its own signed capabilities, so replay refuses any delegation in this record that exceeds them.",
9959
+ "unbound-import": "Imported by `tc auth import` without a stored request. Bound to exactly its own signed capabilities, so replay refuses any delegation in this record that exceeds them."
9960
+ };
9961
+ MIGRATION_LOCK_TIMEOUT_MS = 250;
9962
+ }
9963
+ });
9964
+
9791
9965
  // src/operations/status.ts
9792
9966
  import { z as z7 } from "zod";
9793
9967
  function createStatusDefinition(params) {
@@ -9844,7 +10018,7 @@ async function inspectPinnedProfileStatus(context, _input) {
9844
10018
  async function pinnedProfileExists(profile) {
9845
10019
  try {
9846
10020
  const storedProfile = await readProfile(profile);
9847
- return isRecord4(storedProfile);
10021
+ return isRecord5(storedProfile);
9848
10022
  } catch {
9849
10023
  return false;
9850
10024
  }
@@ -9855,16 +10029,18 @@ async function countLiveAdditionalDelegations(profile) {
9855
10029
  if (rawDelegations === null) return 0;
9856
10030
  if (!Array.isArray(rawDelegations)) throw new TypeError("Invalid additional delegation store.");
9857
10031
  const now = Date.now();
10032
+ const migrated = await bindingMigrationRecorded(profile);
9858
10033
  let count = 0;
9859
10034
  for (const entry of rawDelegations) {
10035
+ if (storedDelegationKind(entry) === "refused") continue;
9860
10036
  const expiry = storedDelegationExpiry(entry);
9861
- if (expiry.getTime() > now) count += 1;
10037
+ if (expiry.getTime() > now && replayLimit(entry, migrated) !== void 0) count += 1;
9862
10038
  }
9863
10039
  return count;
9864
10040
  }
9865
10041
  function summarizeSession(session) {
9866
10042
  if (session === null) return { present: false, expired: null, expiresAt: null };
9867
- if (!isRecord4(session)) throw new TypeError("Invalid session store.");
10043
+ if (!isRecord5(session)) throw new TypeError("Invalid session store.");
9868
10044
  const expiry = extractSessionExpiry(session);
9869
10045
  if (expiry === null) return { present: true, expired: null, expiresAt: null };
9870
10046
  return {
@@ -9874,7 +10050,7 @@ function summarizeSession(session) {
9874
10050
  };
9875
10051
  }
9876
10052
  function storedDelegationExpiry(entry) {
9877
- if (!isRecord4(entry) || !isRecord4(entry.delegation) || !("expiry" in entry.delegation)) {
10053
+ if (!isRecord5(entry) || !isRecord5(entry.delegation) || !("expiry" in entry.delegation)) {
9878
10054
  throw new TypeError("Invalid stored delegation.");
9879
10055
  }
9880
10056
  return parseExpiry(entry.delegation.expiry);
@@ -9903,13 +10079,14 @@ function profileNotFound(profile) {
9903
10079
  )
9904
10080
  };
9905
10081
  }
9906
- function isRecord4(value) {
10082
+ function isRecord5(value) {
9907
10083
  return typeof value === "object" && value !== null && !Array.isArray(value);
9908
10084
  }
9909
10085
  var StatusInputSchema, StatusOutputSchema, STATUS_POSTURES, STATUS_EXPOSURE, STATUS_SENSITIVITY, statusOperationDefinitions;
9910
10086
  var init_status = __esm({
9911
10087
  "src/operations/status.ts"() {
9912
10088
  "use strict";
10089
+ init_delegation_binding();
9913
10090
  init_errors();
9914
10091
  init_state();
9915
10092
  StatusInputSchema = z7.object({}).strict();
@@ -9932,7 +10109,9 @@ var init_status = __esm({
9932
10109
  expired: z7.boolean().nullable(),
9933
10110
  expiresAt: z7.string().datetime({ offset: true }).nullable()
9934
10111
  }).strict(),
9935
- liveAdditionalDelegationCount: z7.number().int().nonnegative()
10112
+ liveAdditionalDelegationCount: z7.number().int().nonnegative().describe(
10113
+ "Stored, unexpired delegations the replay rule accepts: compact-UCAN or signed-login records with a request binding, and unbound compact-UCAN records before the profile's one-time binding migration. Each is still validated, and checked against its binding, when a runtime installs it."
10114
+ )
9936
10115
  }).strict();
9937
10116
  STATUS_POSTURES = [
9938
10117
  "owner-openkey",
@@ -10086,9 +10265,9 @@ function isOperatorType(value) {
10086
10265
  return value === "human" || value === "agent";
10087
10266
  }
10088
10267
  function isStoredProfile(value) {
10089
- return isRecord5(value) && isNonEmptyString(value.name) && isNonEmptyString(value.host) && typeof value.chainId === "number" && Number.isFinite(value.chainId) && isNonEmptyString(value.spaceName) && isNonEmptyString(value.did) && isNonEmptyString(value.createdAt) && isOptionalNonEmptyString(value.sessionDid) && isOptionalNonEmptyString(value.ownerDid) && isOptionalNonEmptyString(value.spaceId) && isOptionalPosture(value.posture) && isOptionalOperatorType(value.operatorType) && isOptionalAuthMethod(value.authMethod) && isOptionalNonEmptyString(value.defaultSpace) && isOptionalNonEmptyString(value.privateKey) && isOptionalNonEmptyString(value.address) && isOptionalNonEmptyString(value.openkeyHost);
10268
+ return isRecord6(value) && isNonEmptyString(value.name) && isNonEmptyString(value.host) && typeof value.chainId === "number" && Number.isFinite(value.chainId) && isNonEmptyString(value.spaceName) && isNonEmptyString(value.did) && isNonEmptyString(value.createdAt) && isOptionalNonEmptyString(value.sessionDid) && isOptionalNonEmptyString(value.ownerDid) && isOptionalNonEmptyString(value.spaceId) && isOptionalPosture(value.posture) && isOptionalOperatorType(value.operatorType) && isOptionalAuthMethod(value.authMethod) && isOptionalNonEmptyString(value.defaultSpace) && isOptionalNonEmptyString(value.privateKey) && isOptionalNonEmptyString(value.address) && isOptionalNonEmptyString(value.openkeyHost);
10090
10269
  }
10091
- function isRecord5(value) {
10270
+ function isRecord6(value) {
10092
10271
  return typeof value === "object" && value !== null && !Array.isArray(value);
10093
10272
  }
10094
10273
  function isNonEmptyString(value) {
@@ -10129,7 +10308,7 @@ var runtime_exports = {};
10129
10308
  __export(runtime_exports, {
10130
10309
  createInvocationRuntime: () => createInvocationRuntime
10131
10310
  });
10132
- import * as nodeSdk2 from "@tinycloud/node-sdk";
10311
+ import * as nodeSdk4 from "@tinycloud/node-sdk";
10133
10312
  async function createInvocationRuntime(target, requirement = "authenticated") {
10134
10313
  const resolved = await resolveInvocationProfile(target);
10135
10314
  if (!resolved.ok) {
@@ -10146,14 +10325,12 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
10146
10325
  const profileName = summary.profile;
10147
10326
  try {
10148
10327
  const {
10149
- activateValidatedRuntimeDelegation: activateValidatedRuntimeDelegation2,
10150
10328
  TinyCloudNode: TinyCloudNodeConstructor
10151
- } = nodeSdk2;
10329
+ } = nodeSdk4;
10152
10330
  const explicitPrivateKeyOverride = typeof target.privateKey === "string";
10153
- const [session, key, additionalDelegations] = explicitPrivateKeyOverride ? [null, null, []] : await Promise.all([
10331
+ const [session, key] = explicitPrivateKeyOverride ? [null, null] : await Promise.all([
10154
10332
  readSession(profileName),
10155
- readJson(`${profilePath(profileName)}/key.json`),
10156
- readAdditionalDelegations(profileName)
10333
+ readJson(`${profilePath(profileName)}/key.json`)
10157
10334
  ]);
10158
10335
  const profile = resolved.profile;
10159
10336
  const actualPosture = resolvePosture(profile);
@@ -10200,19 +10377,26 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
10200
10377
  const livePrincipalDid = normalizeDid(node.did);
10201
10378
  const authenticatedSpace = explicitPrivateKeyOverride ? spaceForAuthenticatedPrincipal(livePrincipalDid) : void 0;
10202
10379
  const livePermissions = [...node.getVerifiedSessionCapabilities()];
10380
+ const resolveSpace2 = operationSpaceResolver(node, authenticatedSpace ?? summary.space);
10203
10381
  const seenCids = /* @__PURE__ */ new Set();
10204
- for (const entry of additionalDelegations) {
10205
- const delegation = normalizeStoredDelegation(entry);
10206
- if (delegation === void 0 || delegation.expiry.getTime() <= Date.now()) continue;
10207
- try {
10208
- const activated = await activateValidatedRuntimeDelegation2(node, delegation, {
10209
- host: summary.host
10382
+ if (!explicitPrivateKeyOverride) {
10383
+ const activator = node;
10384
+ const migrated = await prepareStoredDelegationReplay(profileName, activator, {
10385
+ host: summary.host,
10386
+ // Only the profile's own restored session; a local sign-in without
10387
+ // one uses a fresh session key the stored records do not address.
10388
+ migrate: activeSession !== void 0
10389
+ });
10390
+ for (const entry of await readAdditionalDelegations(profileName)) {
10391
+ const activated = await replayStoredDelegation(activator, entry, {
10392
+ host: summary.host,
10393
+ migrated,
10394
+ resolveSpace: resolveSpace2
10210
10395
  });
10211
- if (!seenCids.has(activated.cid)) {
10396
+ if (activated !== void 0 && !seenCids.has(activated.cid)) {
10212
10397
  seenCids.add(activated.cid);
10213
10398
  livePermissions.push(...activated.effectivePermissions);
10214
10399
  }
10215
- } catch {
10216
10400
  }
10217
10401
  }
10218
10402
  const runtime = {
@@ -10244,8 +10428,8 @@ async function createInvocationRuntime(target, requirement = "authenticated") {
10244
10428
  function spaceForAuthenticatedPrincipal(principal2) {
10245
10429
  if (principal2 === void 0) return void 0;
10246
10430
  try {
10247
- const pkh = nodeSdk2.parsePkhDid(principal2);
10248
- return pkh === null ? void 0 : nodeSdk2.makePkhSpaceId(pkh.address, pkh.chainId, "secrets");
10431
+ const pkh = nodeSdk4.parsePkhDid(principal2);
10432
+ return pkh === null ? void 0 : nodeSdk4.makePkhSpaceId(pkh.address, pkh.chainId, "secrets");
10249
10433
  } catch {
10250
10434
  return void 0;
10251
10435
  }
@@ -10253,7 +10437,7 @@ function spaceForAuthenticatedPrincipal(principal2) {
10253
10437
  function normalizeSession(session, key) {
10254
10438
  const header = session.delegationHeader;
10255
10439
  const jwk = hasPrivateParameter(session.jwk) ? session.jwk : key;
10256
- if (!isRecord6(header) || typeof header.Authorization !== "string" || typeof session.delegationCid !== "string" || typeof session.spaceId !== "string" || !hasPrivateParameter(jwk) || typeof session.verificationMethod !== "string") {
10440
+ if (!isRecord7(header) || typeof header.Authorization !== "string" || typeof session.delegationCid !== "string" || typeof session.spaceId !== "string" || !hasPrivateParameter(jwk) || typeof session.verificationMethod !== "string") {
10257
10441
  return void 0;
10258
10442
  }
10259
10443
  return {
@@ -10269,27 +10453,14 @@ function normalizeSession(session, key) {
10269
10453
  ...Array.isArray(session.tinycloudHosts) && session.tinycloudHosts.every((host) => typeof host === "string") ? { tinycloudHosts: session.tinycloudHosts } : {}
10270
10454
  };
10271
10455
  }
10272
- function normalizeStoredDelegation(entry) {
10273
- const raw = entry.delegation;
10274
- if (!isRecord6(raw) || !isRecord6(raw.delegationHeader)) return void 0;
10275
- const expiry = parseExpiry2(raw.expiry);
10276
- if (expiry === void 0 || typeof raw.cid !== "string" || typeof raw.spaceId !== "string" || typeof raw.path !== "string" || !Array.isArray(raw.actions) || !raw.actions.every((action) => typeof action === "string") || typeof raw.delegateDID !== "string" || typeof raw.ownerAddress !== "string" || typeof raw.chainId !== "number" || typeof raw.delegationHeader.Authorization !== "string") {
10277
- return void 0;
10278
- }
10279
- return { ...raw, expiry };
10280
- }
10281
- function parseExpiry2(value) {
10282
- const expiry = value instanceof Date ? value : typeof value === "string" ? new Date(value) : void 0;
10283
- return expiry !== void 0 && !Number.isNaN(expiry.getTime()) ? expiry : void 0;
10284
- }
10285
10456
  function hasPrivateParameter(value) {
10286
- return isRecord6(value) && typeof value.d === "string" && value.d.length > 0;
10457
+ return isRecord7(value) && typeof value.d === "string" && value.d.length > 0;
10287
10458
  }
10288
10459
  function normalizeDid(value) {
10289
10460
  if (typeof value !== "string" || value.length === 0) return void 0;
10290
10461
  return value.split("#", 1)[0];
10291
10462
  }
10292
- function isRecord6(value) {
10463
+ function isRecord7(value) {
10293
10464
  return typeof value === "object" && value !== null && !Array.isArray(value);
10294
10465
  }
10295
10466
  function failed(context, error) {
@@ -10308,7 +10479,9 @@ var init_runtime = __esm({
10308
10479
  init_authority();
10309
10480
  init_errors();
10310
10481
  init_profile();
10482
+ init_secrets();
10311
10483
  init_state();
10484
+ init_delegation_binding();
10312
10485
  }
10313
10486
  });
10314
10487