@tinycloud/cli 1.3.5-beta.6 → 1.3.5-beta.8

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.
@@ -2523,6 +2523,37 @@ var init_owner_did = __esm({
2523
2523
  }
2524
2524
  });
2525
2525
 
2526
+ // src/lib/caveat-refusal.ts
2527
+ import { recapCaveatsEqual } from "@tinycloud/sdk-core";
2528
+ function hasCaveatLimit(caveats) {
2529
+ if (caveats === void 0) return false;
2530
+ if (!Array.isArray(caveats)) return true;
2531
+ try {
2532
+ return !recapCaveatsEqual(caveats, void 0);
2533
+ } catch {
2534
+ return true;
2535
+ }
2536
+ }
2537
+ function assertNoCaveatLimits(permissions) {
2538
+ if (permissions === void 0) return;
2539
+ for (const permission of permissions) {
2540
+ if (permission === null || typeof permission !== "object" || !("caveats" in permission)) continue;
2541
+ if (hasCaveatLimit(permission.caveats)) {
2542
+ throw new CLIError(CAVEATS_UNSUPPORTED_CODE, CAVEATS_UNSUPPORTED_MESSAGE, ExitCode.USAGE_ERROR);
2543
+ }
2544
+ }
2545
+ }
2546
+ var CAVEATS_UNSUPPORTED_CODE, CAVEATS_UNSUPPORTED_MESSAGE;
2547
+ var init_caveat_refusal = __esm({
2548
+ "src/lib/caveat-refusal.ts"() {
2549
+ "use strict";
2550
+ init_constants();
2551
+ init_errors();
2552
+ CAVEATS_UNSUPPORTED_CODE = "CAVEATS_UNSUPPORTED";
2553
+ CAVEATS_UNSUPPORTED_MESSAGE = "A requested permission carries a limit (caveats), and OpenKey approval does not apply limits. Nothing was requested. Remove the limit from the permission and retry.";
2554
+ }
2555
+ });
2556
+
2526
2557
  // src/share/publishing-manifest.ts
2527
2558
  function sharePublishingPermissions() {
2528
2559
  return SHARE_PUBLISHING_MANIFEST.permissions.map((permission) => ({
@@ -2815,6 +2846,7 @@ async function loadPermissionRequest(source, profile) {
2815
2846
  async function loadManifestPermissions(source, profile, options = {}) {
2816
2847
  const raw = await loadManifestText(source);
2817
2848
  const manifest = JSON.parse(raw);
2849
+ if (Array.isArray(manifest.permissions)) assertNoCaveatLimits(manifest.permissions);
2818
2850
  if (options.device && typeof manifest.app_id === "string" && (manifest.secrets !== void 0 || manifest.space === "secrets" || typeof manifest.space === "string" && manifest.space.endsWith(":secrets") || Array.isArray(manifest.permissions) && manifest.permissions.some((entry) => entry !== null && typeof entry === "object" && normalizeService(String(entry.service ?? "")) === "tinycloud.encryption"))) {
2819
2851
  throw new CLIError("DEVICE_AUTH_UNSUPPORTED_SCOPE", "--device cannot authorize tinycloud.encryption or the secrets space. Use browser or --paste login.", ExitCode.USAGE_ERROR);
2820
2852
  }
@@ -3030,6 +3062,7 @@ var init_permissions = __esm({
3030
3062
  init_space();
3031
3063
  init_raw_encryption();
3032
3064
  init_owner_did();
3065
+ init_caveat_refusal();
3033
3066
  init_publishing_manifest();
3034
3067
  init_types();
3035
3068
  }
@@ -30423,6 +30456,7 @@ init_types();
30423
30456
  // src/auth/browser-auth.ts
30424
30457
  init_constants();
30425
30458
  init_errors();
30459
+ init_caveat_refusal();
30426
30460
  init_formatter();
30427
30461
  import { createServer } from "http";
30428
30462
  import { randomBytes as randomBytes3 } from "crypto";
@@ -30451,6 +30485,7 @@ function publicJwkForDelegation(jwk) {
30451
30485
  return publicJwk;
30452
30486
  }
30453
30487
  async function startAuthFlow(did, options = {}) {
30488
+ assertNoCaveatLimits(options.permissions);
30454
30489
  if (options.paste) {
30455
30490
  return pasteFlow(did, options);
30456
30491
  }
@@ -30466,6 +30501,7 @@ async function startAuthFlow(did, options = {}) {
30466
30501
  }
30467
30502
  }
30468
30503
  function buildAuthUrl(did, options = {}) {
30504
+ assertNoCaveatLimits(options.permissions);
30469
30505
  const params = new URLSearchParams();
30470
30506
  params.set("did", did);
30471
30507
  if (options.callback) {
@@ -30772,6 +30808,7 @@ function loginCancelled() {
30772
30808
  // src/auth/device-auth.ts
30773
30809
  init_constants();
30774
30810
  init_errors();
30811
+ init_caveat_refusal();
30775
30812
  import {
30776
30813
  createDecipheriv,
30777
30814
  createECDH,
@@ -30899,6 +30936,7 @@ init_space();
30899
30936
  init_manifest();
30900
30937
  init_raw_encryption();
30901
30938
  init_owner_did();
30939
+ init_caveat_refusal();
30902
30940
  var CAPABILITIES_READ = "tinycloud.capabilities/read";
30903
30941
  var CLOCK_SKEW_MS = 3e4;
30904
30942
  var SIGNED_RECAP = "signed-recap";
@@ -31090,9 +31128,11 @@ function validateLoginPermissions(permissions) {
31090
31128
  }
31091
31129
  }
31092
31130
  function scopedLoginPermissions(permissions) {
31131
+ assertNoCaveatLimits(permissions);
31093
31132
  return withCapabilitiesRead(permissions, permissions.find((p) => !isRawEncryptionPermission(p)).space ?? "");
31094
31133
  }
31095
31134
  function grantRequestPermissions(group, anchorSpace) {
31135
+ assertNoCaveatLimits(group);
31096
31136
  const request2 = group.map((p) => isRawEncryptionPermission(p) ? { ...p, space: ENCRYPTION_MANIFEST_SPACE, path: canonicalNetworkUrn(p.path) } : p);
31097
31137
  const capabilitySpace = request2.find(
31098
31138
  (permission) => !isRawEncryptionPermission(permission) && !isRawCidRevocationPermission(permission)
@@ -31592,6 +31632,7 @@ function writeApprovalPrompt(prompt) {
31592
31632
  );
31593
31633
  }
31594
31634
  async function acquireDeviceDelegation(input) {
31635
+ assertNoCaveatLimits(input.permissions);
31595
31636
  validateLoginPermissions(input.permissions);
31596
31637
  if (input.permissions.some((permission) => permission.service === "tinycloud.encryption" || permission.space === "secrets" || permission.space?.startsWith("tinycloud:") && permission.space.endsWith(":secrets"))) {
31597
31638
  throw new CLIError(
@@ -31901,6 +31942,7 @@ async function ensureSpaceSetup(ctx, delegation, permissions) {
31901
31942
  }
31902
31943
 
31903
31944
  // src/commands/auth.ts
31945
+ init_caveat_refusal();
31904
31946
  init_raw_encryption();
31905
31947
  init_owner_did();
31906
31948
 
@@ -33805,6 +33847,7 @@ ${appsAgentScopeNotice(preset.mode, preset.appIds)}
33805
33847
  await emitPermissionRequestArtifact(artifact, options2.emit);
33806
33848
  return;
33807
33849
  }
33850
+ if (profile.authMethod === "openkey" || options2.device) assertNoCaveatLimits(requested);
33808
33851
  const node = await ensureAuthenticated(ctx);
33809
33852
  if (node.hasRuntimePermissions(requested)) {
33810
33853
  outputJson({ changed: false, missing: [], added: [] });
@@ -34094,6 +34137,7 @@ ${appsAgentScopeNotice(preset.mode, preset.appIds)}
34094
34137
  const requested = finalizeSigningEntries(
34095
34138
  await resolvePermissionSpaces(entriesForSigning(parsed.requested), ctx.profile)
34096
34139
  );
34140
+ if (profile.authMethod === "openkey") assertNoCaveatLimits(requested);
34097
34141
  const [applications] = await resolvePermissionSpaces(
34098
34142
  [{ service: "tinycloud.kv", space: APPS_AGENT_SPACE, path: "", actions: ["tinycloud.kv/get"] }],
34099
34143
  ctx.profile
@@ -34539,6 +34583,7 @@ async function activateAndStoreOpenKeyGrants(profileName2, host, node, grants, s
34539
34583
  });
34540
34584
  }
34541
34585
  async function acquireOpenKeyApproval(params) {
34586
+ assertNoCaveatLimits(params.requested);
34542
34587
  if (params.requested.some(isRawCidRevocationPermission)) {
34543
34588
  throw new CLIError(
34544
34589
  "RAW_RECAP_RESOURCE_UNSUPPORTED",
@@ -34595,6 +34640,7 @@ async function nodeFromOpenKeyApproval(host, session) {
34595
34640
  }
34596
34641
  async function ensureDelegationAuthority(params) {
34597
34642
  if (!params.force && params.node.hasRuntimePermissions(params.requested)) return void 0;
34643
+ if (params.profile.authMethod === "openkey") assertNoCaveatLimits(params.requested);
34598
34644
  if (!params.consentAlreadyGiven && (params.persist === false || params.profile.authMethod !== "openkey")) {
34599
34645
  await requirePermissionConsent(params.requested, params.yes);
34600
34646
  }
@@ -35112,6 +35158,7 @@ function writeReplicationSecretsWarning() {
35112
35158
  }
35113
35159
  async function refreshPreparedOpenKeySession(params) {
35114
35160
  const { profileName: profileName2, host, profile, snapshot, options, replication, permissions, expectedOwner, expiry } = params;
35161
+ assertNoCaveatLimits(permissions);
35115
35162
  const storedOwner = snapshot.session && snapshot.key && profile.sessionDid ? verifySignedSession(snapshot.session, snapshot.key, profile.sessionDid).ownerDid : void 0;
35116
35163
  const owner = options.expectedOwner ? canonicalOwnerDid(options.expectedOwner) : storedOwner;
35117
35164
  if (!owner || !permissions) {