@supacloud/cli 0.80.0 → 0.81.0

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
@@ -179093,10 +179093,11 @@ function resolveSupaCloudContext(env = process.env, cwd = process.cwd(), selecti
179093
179093
  var ACTION_POLICY = {
179094
179094
  deploy: { write: ["deploy"] },
179095
179095
  applications: {
179096
- read: ["list_releases", "get_release", "get_runtime", "get_deployment_evidence", "get_configuration", "get_rollback_snapshot", "get_history", "get_deploy_plan", "logs", "get_preview_plan"],
179096
+ read: ["list_releases", "get_release", "get_runtime", "get_deployment_evidence", "get_configuration", "get_release_transfer_plan", "get_promotion_plan", "get_rollback_snapshot", "get_history", "get_deploy_plan", "logs", "get_preview_plan"],
179097
179097
  write: [
179098
179098
  "upload_release",
179099
179099
  "put_configuration",
179100
+ "transfer_release",
179100
179101
  "activate_release",
179101
179102
  "deploy_release",
179102
179103
  "rollback_release",
@@ -179178,7 +179179,7 @@ var ACTION_POLICY = {
179178
179179
  scheduled_functions: { read: ["list", "get"], write: ["create", "update", "delete"] },
179179
179180
  mutations: { read: ["status"] },
179180
179181
  release: {
179181
- read: ["logical_backup_list", "postgrest_status"],
179182
+ read: ["logical_backup_list", "logical_backup_status", "postgrest_status"],
179182
179183
  local: ["scope_inspect", "scope_rebind", "scope_create"],
179183
179184
  write: ["logical_backup_create", "logical_backup_restore", "postgrest_restart", "release_canary_fixture_stage_replay", "release_canary_fixture_disable_replay"]
179184
179185
  },
@@ -179201,8 +179202,8 @@ var ACTION_POLICY = {
179201
179202
  ai: { local: ["show_skill", "install_skill"] },
179202
179203
  app: {
179203
179204
  local: ["init", "generate", "dev", "watch", "verify-plan", "compile", "check", "graph", "explain", "export-tools", "context", "doctor", "fix", "plan", "build"],
179204
- read: ["status", "logs", "rollback-plan", "history", "deploy-plan", "diff", "preview-plan"],
179205
- write: ["upload", "configure", "deploy", "rollback", "reconcile", "retire", "preview", "previews", "preview-status", "preview-cleanup"]
179205
+ read: ["status", "logs", "transfer-plan", "promote-plan", "rollback-plan", "history", "deploy-plan", "diff", "preview-plan"],
179206
+ write: ["upload", "configure", "transfer", "deploy", "rollback", "reconcile", "retire", "preview", "previews", "preview-status", "preview-cleanup"]
179206
179207
  },
179207
179208
  db: {
179208
179209
  local: ["context", "lint", "explain", "diff", "role_sql"],
@@ -180419,6 +180420,52 @@ function parseApplicationActivationHistory(value) {
180419
180420
  }
180420
180421
  return structuredClone(value);
180421
180422
  }
180423
+ // node_modules/@supacloud/delivery/src/application-release-transfer.ts
180424
+ var projectRef = String2({ pattern: "^[A-Za-z0-9_-]{1,20}$" });
180425
+ var source = _Object_({
180426
+ project_ref: projectRef,
180427
+ release_id: ApplicationReleaseIdSchema,
180428
+ manifest_sha256: ApplicationReleaseIdSchema
180429
+ }, { additionalProperties: false });
180430
+ var identity = {
180431
+ project_ref: projectRef,
180432
+ application_id: ApplicationIdSchema,
180433
+ source,
180434
+ candidate_release_id: ApplicationReleaseIdSchema
180435
+ };
180436
+ var ApplicationReleaseTransferPlanSchema = _Object_({
180437
+ schema: Literal("supacloud.application-release-transfer-plan.v1"),
180438
+ ...identity,
180439
+ action: Union([Literal("materialize"), Literal("no-op")]),
180440
+ execution_performed: Literal(false)
180441
+ }, { additionalProperties: false });
180442
+ var ApplicationReleaseTransferResultSchema = _Object_({
180443
+ schema: Literal("supacloud.application-release-transfer-result.v1"),
180444
+ ...identity,
180445
+ release: ApplicationReleaseRecordSchema,
180446
+ activation_performed: Literal(false)
180447
+ }, { additionalProperties: false });
180448
+ function assertIdentity(value) {
180449
+ if (value.source.release_id !== applicationReleaseId(value.source.project_ref, value.application_id, value.source.manifest_sha256) || value.candidate_release_id !== applicationReleaseId(value.project_ref, value.application_id, value.source.manifest_sha256)) {
180450
+ throw new Error("Invalid application release transfer identity");
180451
+ }
180452
+ }
180453
+ function parseApplicationReleaseTransferPlan(candidate) {
180454
+ if (!Check2(ApplicationReleaseTransferPlanSchema, candidate))
180455
+ throw new Error("Invalid application release transfer plan");
180456
+ assertIdentity(candidate);
180457
+ return candidate;
180458
+ }
180459
+ function parseApplicationReleaseTransferResult(candidate) {
180460
+ if (!Check2(ApplicationReleaseTransferResultSchema, candidate))
180461
+ throw new Error("Invalid application release transfer result");
180462
+ assertIdentity(candidate);
180463
+ const release = parseApplicationReleaseRecord(candidate.release);
180464
+ if (release.project_ref !== candidate.project_ref || release.application_id !== candidate.application_id || release.release_id !== candidate.candidate_release_id || release.manifest_sha256 !== candidate.source.manifest_sha256) {
180465
+ throw new Error("Invalid application release transfer result");
180466
+ }
180467
+ return candidate;
180468
+ }
180422
180469
  // node_modules/@supacloud/delivery/src/deployment-evidence.ts
180423
180470
  var closed3 = { additionalProperties: false };
180424
180471
  var sha256 = String2({ pattern: "^[a-f0-9]{64}$" });
@@ -180544,6 +180591,116 @@ function parseDeploymentEvidence(value) {
180544
180591
  }
180545
180592
  return structuredClone(value);
180546
180593
  }
180594
+ // node_modules/@supacloud/delivery/src/application-promotion.ts
180595
+ var closed4 = { additionalProperties: false };
180596
+ var projectRef2 = String2({ pattern: "^[a-z0-9-]{1,20}$" });
180597
+ var sha2562 = ApplicationReleaseIdSchema;
180598
+ var nullableActivation = Union([ApplicationActivationIdSchema, Null()]);
180599
+ var nullableDigest = Union([sha2562, Null()]);
180600
+ var observation = {
180601
+ activation_id: nullableActivation,
180602
+ receipt_confirmed: Boolean2(),
180603
+ ready: Boolean2(),
180604
+ smoke_verified: Boolean2(),
180605
+ evidence_sha256: nullableDigest,
180606
+ migration_ledger_digest: nullableDigest
180607
+ };
180608
+ var blocker = [
180609
+ "SOURCE_NOT_ACTIVE",
180610
+ "SOURCE_RECEIPT_UNCONFIRMED",
180611
+ "SOURCE_NOT_READY",
180612
+ "SOURCE_SMOKE_UNVERIFIED",
180613
+ "TARGET_CONFIGURATION_MISSING",
180614
+ "TARGET_CONFIGURATION_MISMATCH",
180615
+ "MIGRATION_PENDING",
180616
+ "MIGRATION_CONFLICT",
180617
+ "OPERATOR_PROVISIONING_REQUIRED",
180618
+ "BACKUP_REQUIRED"
180619
+ ];
180620
+ var ApplicationPromotionPlanSchema = _Object_({
180621
+ schema: Literal("supacloud.application-promotion-plan.v1"),
180622
+ project_ref: projectRef2,
180623
+ application_id: ApplicationIdSchema,
180624
+ environment_id: ApplicationIdSchema,
180625
+ manifest_sha256: sha2562,
180626
+ plan_sha256: sha2562,
180627
+ source: _Object_({
180628
+ project_ref: projectRef2,
180629
+ environment_id: ApplicationIdSchema,
180630
+ release_id: sha2562,
180631
+ ...observation
180632
+ }, closed4),
180633
+ target: _Object_({
180634
+ candidate_release_id: sha2562,
180635
+ current_release_id: Union([sha2562, Null()]),
180636
+ artifact_action: Union([Literal("materialize"), Literal("reuse")]),
180637
+ configuration_id: Union([ApplicationConfigurationIdSchema, Null()]),
180638
+ configuration: Union([ApplicationConfigurationViewSchema, Null()]),
180639
+ ...observation
180640
+ }, closed4),
180641
+ migrations: _Object_({
180642
+ ledger_digest: sha2562,
180643
+ ledger_compatible: Boolean2(),
180644
+ project_migrations_applied: Boolean2(),
180645
+ pending_versions: _Array_(String2({ pattern: "^\\d{1,20}$" }), { maxItems: 4096, uniqueItems: true }),
180646
+ operator_provisioning_required: Boolean2()
180647
+ }, closed4),
180648
+ backup: _Object_({
180649
+ required: Boolean2(),
180650
+ confirmed: Literal(false)
180651
+ }, closed4),
180652
+ action: Union([Literal("promote"), Literal("no-op"), Literal("blocked")]),
180653
+ blockers: _Array_(Enum([...blocker]), {
180654
+ maxItems: blocker.length,
180655
+ uniqueItems: true
180656
+ }),
180657
+ steps: _Array_(String2({ minLength: 1, maxLength: 64 }), { maxItems: 8, uniqueItems: true }),
180658
+ execution_performed: Literal(false),
180659
+ data_recovery: Literal("separate-required")
180660
+ }, closed4);
180661
+ function applicationPromotionPlanDigest(value) {
180662
+ return digest(canonical(value));
180663
+ }
180664
+ function applicationPromotionAction(value) {
180665
+ if (value.blockers.length > 0)
180666
+ return "blocked";
180667
+ return value.target.artifact_action === "reuse" && value.target.current_release_id === value.target.candidate_release_id && value.target.configuration !== null && value.target.activation_id !== null && value.target.receipt_confirmed && value.target.ready && value.target.smoke_verified && value.migrations.project_migrations_applied && !value.migrations.operator_provisioning_required && (!value.backup.required || value.backup.confirmed) ? "no-op" : "promote";
180668
+ }
180669
+ function applicationPromotionSteps(value) {
180670
+ if (value.action === "no-op")
180671
+ return [];
180672
+ return [
180673
+ ...value.blockers.some((code) => code.startsWith("SOURCE_")) ? ["verify-source"] : [],
180674
+ ...value.blockers.some((code) => code.startsWith("TARGET_CONFIGURATION_")) ? ["bind-target-configuration"] : [],
180675
+ ...value.blockers.includes("MIGRATION_CONFLICT") ? ["resolve-migration-conflicts"] : [],
180676
+ ...!value.backup.required || value.backup.confirmed ? [] : ["backup"],
180677
+ ...value.migrations.project_migrations_applied ? [] : ["review-and-apply-migrations"],
180678
+ ...value.migrations.operator_provisioning_required ? ["verify-operator-provisioning"] : [],
180679
+ ...value.action === "promote" ? [
180680
+ ...value.target.artifact_action === "materialize" ? ["transfer"] : [],
180681
+ "activate-with-cas",
180682
+ "verify-runtime-and-smoke"
180683
+ ] : []
180684
+ ];
180685
+ }
180686
+ function parseApplicationPromotionPlan(value) {
180687
+ if (!Check2(ApplicationPromotionPlanSchema, value))
180688
+ throw new Error("Invalid application promotion plan");
180689
+ const { plan_sha256: _planSha256, ...content } = value;
180690
+ if (value.migrations.project_migrations_applied && (!value.migrations.ledger_compatible || value.migrations.pending_versions.length > 0) || !value.source.activation_id && (value.source.ready || value.source.receipt_confirmed || value.source.smoke_verified) || !value.target.activation_id && (value.target.ready || value.target.receipt_confirmed || value.target.smoke_verified) || !value.blockers.length && (!value.source.ready || !value.source.receipt_confirmed || !value.source.smoke_verified || !value.source.activation_id || !value.target.configuration || !value.migrations.ledger_compatible)) {
180691
+ throw new Error("Invalid application promotion prerequisites");
180692
+ }
180693
+ if (value.backup.required !== !value.migrations.project_migrations_applied || [value.source, value.target].some((observation) => observation.smoke_verified && (observation.evidence_sha256 === null || observation.migration_ledger_digest === null)) || value.target.smoke_verified && value.target.migration_ledger_digest !== value.migrations.ledger_digest) {
180694
+ throw new Error("Invalid application promotion migration binding");
180695
+ }
180696
+ if (value.source.release_id !== applicationReleaseId(value.source.project_ref, value.application_id, value.manifest_sha256) || value.target.candidate_release_id !== applicationReleaseId(value.project_ref, value.application_id, value.manifest_sha256) || value.action !== applicationPromotionAction(content) || canonical(value.steps) !== canonical(applicationPromotionSteps(content)) || value.plan_sha256 !== applicationPromotionPlanDigest(content) || value.target.configuration !== null && (() => {
180697
+ const configuration = parseApplicationConfigurationView(value.target.configuration);
180698
+ return configuration.project_ref !== value.project_ref || configuration.application_id !== value.application_id || configuration.environment_id !== value.environment_id || configuration.configuration_id !== value.target.configuration_id;
180699
+ })()) {
180700
+ throw new Error("Invalid application promotion plan identity");
180701
+ }
180702
+ return structuredClone(value);
180703
+ }
180547
180704
  // node_modules/@supacloud/delivery/src/application-runtime-identity.ts
180548
180705
  var ApplicationRuntimeIdentitySchema = _Object_({
180549
180706
  schema: Literal("supacloud.application-runtime.v1"),
@@ -181551,7 +181708,7 @@ ALTER TABLE supacloud_commands.execution_receipts
181551
181708
  DROP COLUMN IF EXISTS recovery_attempts;
181552
181709
  `;
181553
181710
  var MAX_MIGRATION_VERSION = 9223372036854775807n;
181554
- function sha2562(value) {
181711
+ function sha2563(value) {
181555
181712
  return createHash22("sha256").update(value).digest("hex");
181556
181713
  }
181557
181714
  function normalizedSql(value) {
@@ -181620,7 +181777,7 @@ function planMigrationRebase(migrations, options, baselineSql) {
181620
181777
  file: migration.file,
181621
181778
  version: migration.version,
181622
181779
  name: migration.name,
181623
- sha256: sha2562(normalizedSql(migration.sql))
181780
+ sha256: sha2563(normalizedSql(migration.sql))
181624
181781
  }));
181625
181782
  return {
181626
181783
  version: 1,
@@ -181630,8 +181787,8 @@ function planMigrationRebase(migrations, options, baselineSql) {
181630
181787
  baselineMigration,
181631
181788
  retainedMigrations: retained.map((migration) => migration.file),
181632
181789
  archivedMigrations: archived.map((migration) => migration.file),
181633
- sourceHistorySha256: sha2562(JSON.stringify(sourceHistory)),
181634
- baselineSha256: sha2562(normalizedBaseline),
181790
+ sourceHistorySha256: sha2563(JSON.stringify(sourceHistory)),
181791
+ baselineSha256: sha2563(normalizedBaseline),
181635
181792
  warnings: [
181636
181793
  "The baseline must come from a schema-only snapshot of the verified target database.",
181637
181794
  "Data backfills, reference data and non-replayable side effects need a separate review.",
@@ -181667,7 +181824,7 @@ async function rebaseMigrations(options) {
181667
181824
  file: migration.file,
181668
181825
  version: migration.version,
181669
181826
  name: migration.name,
181670
- sha256: sha2562(normalizedSql(migration.sql))
181827
+ sha256: sha2563(normalizedSql(migration.sql))
181671
181828
  }))
181672
181829
  }, null, 2) + `
181673
181830
  `);
@@ -184569,7 +184726,7 @@ function clientId(value) {
184569
184726
  }
184570
184727
  return value;
184571
184728
  }
184572
- function projectRef(value) {
184729
+ function projectRef3(value) {
184573
184730
  if (typeof value !== "string" || !value.trim())
184574
184731
  throw new Error("'ref' is required");
184575
184732
  return projectRefPathSegment(value.trim(), "OAuth client");
@@ -184721,7 +184878,7 @@ function registerOAuthClientTools(server2, http) {
184721
184878
  client_id: optional(String2(), "[get/delete] Exact release-canary public OAuth client ID"),
184722
184879
  redirect_uri: optional(String2(), "[create/delete] Exact HTTPS or port-bound RFC 8252 loopback callback")
184723
184880
  }, async ({ action, ref, client_id, redirect_uri }) => {
184724
- const targetRef = projectRef(ref);
184881
+ const targetRef = projectRef3(ref);
184725
184882
  if (action === "list")
184726
184883
  return listReleaseCanaryClients(http, targetRef);
184727
184884
  if (action === "get")
@@ -187394,6 +187551,64 @@ var ApplicationActivationRetirementResultSchema2 = ApplicationActivationRetireme
187394
187551
  var ApplicationRollbackSnapshotSchema2 = ApplicationRollbackSnapshotSchema;
187395
187552
  var ApplicationActivationHistoryCursorSchema2 = ApplicationActivationHistoryCursorSchema;
187396
187553
 
187554
+ // src/shared/tools/application-release-transfer.ts
187555
+ async function applicationReleaseTransfer(http, input, project) {
187556
+ const operation = `applications.${input.action}`;
187557
+ const identity = {
187558
+ project_ref: input.ref,
187559
+ application_id: input.id,
187560
+ source_ref: input.sourceRef,
187561
+ source_release_id: input.sourceReleaseId
187562
+ };
187563
+ const path = `/v1/projects/${project}/applications/${encodeURIComponent(input.id)}`;
187564
+ const query = new URLSearchParams({ source_ref: input.sourceRef, source_release_id: input.sourceReleaseId });
187565
+ const response = await http.get(`${path}/release-transfer-plan?${query}`, { maxJsonBytes: 65536, responseTimeoutMs: 30000 });
187566
+ if (!response.ok)
187567
+ return releaseControlFailure(operation, "HTTP_ERROR", response.transportError ? null : response.status, identity);
187568
+ let plan;
187569
+ try {
187570
+ if (response.status !== 200)
187571
+ throw new Error;
187572
+ plan = parseApplicationReleaseTransferPlan(response.data);
187573
+ if (plan.project_ref !== input.ref || plan.application_id !== input.id || plan.source.project_ref !== input.sourceRef || plan.source.release_id !== input.sourceReleaseId)
187574
+ throw new Error;
187575
+ } catch {
187576
+ return releaseControlFailure(operation, "INVALID_RESPONSE", response.status, identity);
187577
+ }
187578
+ if (input.action === "get_release_transfer_plan")
187579
+ return releaseControlSuccess(operation, { ...identity, plan });
187580
+ const safeIdentity = {
187581
+ ...identity,
187582
+ release_id: plan.candidate_release_id,
187583
+ manifest_sha256: plan.source.manifest_sha256
187584
+ };
187585
+ if (plan.action === "no-op")
187586
+ return releaseControlSuccess(operation, {
187587
+ ...safeIdentity,
187588
+ no_op: true,
187589
+ execution_performed: false,
187590
+ activation_performed: false,
187591
+ plan
187592
+ });
187593
+ const result = await http.postReleaseMutation(`${path}/release-transfers`, {
187594
+ source_ref: input.sourceRef,
187595
+ source_release_id: input.sourceReleaseId,
187596
+ expected_manifest_sha256: plan.source.manifest_sha256
187597
+ }, { timeoutMs: 120000 });
187598
+ if (!result.ok)
187599
+ return releaseControlMutationFailure(operation, result, safeIdentity);
187600
+ try {
187601
+ if (result.status !== 200)
187602
+ throw new Error;
187603
+ const receipt = parseApplicationReleaseTransferResult(result.data);
187604
+ if (receipt.project_ref !== input.ref || receipt.application_id !== input.id || receipt.source.project_ref !== input.sourceRef || receipt.source.release_id !== input.sourceReleaseId || receipt.candidate_release_id !== plan.candidate_release_id || receipt.source.manifest_sha256 !== plan.source.manifest_sha256)
187605
+ throw new Error;
187606
+ return releaseControlSuccess(operation, { ...safeIdentity, no_op: false, transfer: receipt });
187607
+ } catch {
187608
+ return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.status, safeIdentity);
187609
+ }
187610
+ }
187611
+
187397
187612
  // src/shared/tools/application-preview-tools.ts
187398
187613
  var APPLICATION_PREVIEW_ACTIONS = [
187399
187614
  "get_preview_plan",
@@ -187732,6 +187947,9 @@ var APPLICATION_TOOL_SCHEMA = {
187732
187947
  "put_configuration",
187733
187948
  "get_deploy_plan",
187734
187949
  "deploy_release",
187950
+ "get_release_transfer_plan",
187951
+ "transfer_release",
187952
+ "get_promotion_plan",
187735
187953
  "activate_release",
187736
187954
  "rollback_release",
187737
187955
  "get_rollback_snapshot",
@@ -187750,6 +187968,9 @@ var APPLICATION_TOOL_SCHEMA = {
187750
187968
  configuration_path: optional(String2(), "[put_configuration] Local configuration write JSON including revision and expected revision"),
187751
187969
  manifest_path: optional(String2(), "[upload_release] Local delivery.manifest.json"),
187752
187970
  release_id: optional(ApplicationReleaseIdSchema2, "[get_release/get_deploy_plan/deploy_release/activate_release/reconcile_activation/rollback_release] Immutable application release ID; platform selects previous for default rollback"),
187971
+ source_ref: optional(String2({ pattern: "^[A-Za-z0-9_-]{1,20}$" }), "[get_release_transfer_plan/transfer_release] Source project ref"),
187972
+ source_release_id: optional(ApplicationReleaseIdSchema2, "[get_release_transfer_plan/transfer_release] Source immutable release ID"),
187973
+ source_environment_id: optional(ApplicationIdSchema2, "[get_promotion_plan] Source environment"),
187753
187974
  cursor: optional(Union([ApplicationReleaseIdSchema2, ApplicationActivationHistoryCursorSchema2]), "[list_releases/get_history] Returned page cursor"),
187754
187975
  limit: optional(Integer({ minimum: 1, maximum: 100 }), "[list_releases/get_history] Page size, default 50/20"),
187755
187976
  offset: optional(Integer({ minimum: 0, maximum: 1e6 }), "[logs] Result offset"),
@@ -188045,6 +188266,52 @@ function registerApplicationTools(server2, http) {
188045
188266
  throw new Error("Invalid application ID");
188046
188267
  const path = `/v1/projects/${project}/applications/${encodeURIComponent(id)}/releases`;
188047
188268
  const operation = `applications.${action}`;
188269
+ if (action === "get_promotion_plan") {
188270
+ const environmentId = text(args, "environment_id");
188271
+ const sourceRef = text(args, "source_ref"), sourceEnvironmentId = text(args, "source_environment_id");
188272
+ const sourceReleaseId = text(args, "source_release_id");
188273
+ if (!/^[a-z0-9-]{1,20}$/.test(sourceRef) || !Check2(ApplicationReleaseIdSchema2, sourceReleaseId) || !Check2(ApplicationIdSchema2, environmentId) || !Check2(ApplicationIdSchema2, sourceEnvironmentId)) {
188274
+ throw new Error("Invalid promotion environment");
188275
+ }
188276
+ const query = new URLSearchParams({
188277
+ source_ref: sourceRef,
188278
+ source_environment_id: sourceEnvironmentId,
188279
+ source_release_id: sourceReleaseId
188280
+ });
188281
+ if (typeof args["configuration_id"] === "string")
188282
+ query.set("configuration_id", args["configuration_id"]);
188283
+ const result = await http.get(`/v1/projects/${project}/applications/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}/promotion-plan?${query}`, { maxJsonBytes: 262144, responseTimeoutMs: 30000 });
188284
+ const identity = {
188285
+ project_ref: ref,
188286
+ application_id: id,
188287
+ environment_id: environmentId,
188288
+ source_ref: sourceRef,
188289
+ source_environment_id: sourceEnvironmentId,
188290
+ source_release_id: sourceReleaseId
188291
+ };
188292
+ if (!result.ok)
188293
+ return releaseControlFailure(operation, "HTTP_ERROR", result.status, identity);
188294
+ try {
188295
+ if (result.status !== 200)
188296
+ throw new Error;
188297
+ const plan = parseApplicationPromotionPlan(result.data);
188298
+ if (plan.project_ref !== ref || plan.application_id !== id || plan.environment_id !== environmentId || plan.source.project_ref !== sourceRef || plan.source.environment_id !== sourceEnvironmentId || plan.source.release_id !== sourceReleaseId || args["configuration_id"] !== undefined && plan.target.configuration_id !== args["configuration_id"]) {
188299
+ throw new Error;
188300
+ }
188301
+ return releaseControlSuccess(operation, { ...identity, plan });
188302
+ } catch {
188303
+ return releaseControlFailure(operation, "INVALID_RESPONSE", result.status, identity);
188304
+ }
188305
+ }
188306
+ if (action === "get_release_transfer_plan" || action === "transfer_release") {
188307
+ return applicationReleaseTransfer(http, {
188308
+ action,
188309
+ ref,
188310
+ id,
188311
+ sourceRef: text(args, "source_ref"),
188312
+ sourceReleaseId: text(args, "source_release_id")
188313
+ }, project);
188314
+ }
188048
188315
  if (action === "get_deploy_plan") {
188049
188316
  const observed = await readDeployPlan(http, args, project);
188050
188317
  return observed.failure ?? releaseControlSuccess(operation, { ...observed.identity, plan: observed.plan });
@@ -194299,6 +194566,9 @@ async function applyScaffoldWrites(plan) {
194299
194566
  // src/shared/tools/app-tools.ts
194300
194567
  var REMOTE_APP_ACTIONS = {
194301
194568
  upload: "upload_release",
194569
+ "transfer-plan": "get_release_transfer_plan",
194570
+ "promote-plan": "get_promotion_plan",
194571
+ transfer: "transfer_release",
194302
194572
  configure: "put_configuration",
194303
194573
  deploy: "deploy_release",
194304
194574
  "deploy-plan": "get_deploy_plan",
@@ -194317,15 +194587,18 @@ var REMOTE_APP_ACTIONS = {
194317
194587
  "preview-cleanup": "cleanup_preview"
194318
194588
  };
194319
194589
  var REMOTE_APP_DESCRIPTIONS = {
194320
- ref: "[upload/configure/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Project ref (defaults to context)",
194321
- id: "[upload/configure/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Application ID",
194322
- environment_id: "[configure/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Environment ID",
194323
- configuration_id: "[deploy/deploy-plan/diff/rollback/preview] Required for deployment/preview; platform selects for default rollback",
194590
+ ref: "[upload/configure/transfer-plan/transfer/promote-plan/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Project ref (defaults to context)",
194591
+ id: "[upload/configure/transfer-plan/transfer/promote-plan/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Application ID",
194592
+ environment_id: "[configure/promote-plan/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Target environment ID",
194593
+ configuration_id: "[promote-plan/deploy/deploy-plan/diff/rollback/preview] Immutable target configuration revision; required for deployment/preview; platform selects for default rollback",
194324
194594
  activation_id: "[deploy/rollback/reconcile/retire] Stable activation ID; auto-generated for deploy/rollback if omitted",
194325
194595
  expected_activation_id: "[deploy/rollback] Auto-selected from verified state; supply with activation_id for an exact retry",
194326
194596
  configuration_path: "[configure] Configuration write JSON including revision and expected revision",
194327
194597
  manifest_path: "[upload] Local delivery.manifest.json",
194328
194598
  release_id: "[deploy/deploy-plan/diff/rollback/reconcile/preview-plan/preview] Required for deployment/preview; defaults to journal-selected previous for rollback",
194599
+ source_ref: "[transfer-plan/transfer/promote-plan] Source project ref",
194600
+ source_release_id: "[transfer-plan/transfer/promote-plan] Source immutable release ID",
194601
+ source_environment_id: "[promote-plan] Source environment ID",
194329
194602
  preview_id: "[preview-status/preview-cleanup] Preview receipt ID",
194330
194603
  branch_ref: "[preview-plan] Proposed branch ref; preview assigns its own",
194331
194604
  branch_name: "[preview] Branch display name",
@@ -195233,6 +195506,30 @@ async function runDelivery(args) {
195233
195506
  const result = await buildDeliveryProject(options, loaded.delivery);
195234
195507
  return textResult(JSON.stringify(result, null, 2), !result.ok);
195235
195508
  }
195509
+ function formatReleaseTransfer(result) {
195510
+ if (result.isError)
195511
+ return result;
195512
+ try {
195513
+ const payload = JSON.parse(result.content[0]?.text ?? "");
195514
+ if (!payload || typeof payload !== "object" || !("ok" in payload) || payload.ok !== true)
195515
+ return result;
195516
+ const plan = "plan" in payload ? parseApplicationReleaseTransferPlan(payload.plan) : null;
195517
+ const receipt = !plan && "transfer" in payload ? parseApplicationReleaseTransferResult(payload.transfer) : null;
195518
+ const data = plan ?? receipt;
195519
+ if (!data)
195520
+ return result;
195521
+ return textResult([
195522
+ `${data.project_ref}/${data.application_id}: ${plan ? plan.action === "no-op" ? "No changes" : "Transfer required" : "Artifact transferred"}`,
195523
+ `Source: ${data.source.project_ref} / ${data.source.release_id}`,
195524
+ `Target release: ${data.candidate_release_id}`,
195525
+ `Manifest: ${data.source.manifest_sha256}`,
195526
+ "Activation: not performed"
195527
+ ].join(`
195528
+ `));
195529
+ } catch {
195530
+ return result;
195531
+ }
195532
+ }
195236
195533
  var historyReceiptSchema = _Object_({
195237
195534
  schema: Literal(RELEASE_CONTROL_RESPONSE_SCHEMA),
195238
195535
  ok: Literal(true),
@@ -195318,9 +195615,11 @@ async function runAppTool(request, options = {}) {
195318
195615
  if (request.database_url !== undefined && request.action !== "dev" && request.action !== "watch") {
195319
195616
  throw new ScaffoldError("SCAFFOLD_OPTION_INVALID", "--database-url applies only to app dev --profile integration");
195320
195617
  }
195321
- if (request.json !== undefined && (request.action !== "history" || request.json !== true || request.format === "text")) {
195322
- throw new Error("--json applies only to app history and cannot be combined with --format text");
195618
+ if (request.json !== undefined && request.action !== "history" && request.action !== "transfer-plan" && request.action !== "transfer" && request.action !== "promote-plan") {
195619
+ throw new Error("--json applies only to app history, transfer-plan, transfer or promote-plan");
195323
195620
  }
195621
+ if (request.json !== undefined && request.format === "text")
195622
+ throw new Error("--json and --format text cannot be combined");
195324
195623
  if (Object.hasOwn(REMOTE_APP_ACTIONS, request.action)) {
195325
195624
  const delegate = options.getApplications?.();
195326
195625
  if (!delegate)
@@ -195337,7 +195636,24 @@ async function runAppTool(request, options = {}) {
195337
195636
  if (request.action === "history" && format !== "json" && json !== true) {
195338
195637
  return historyText(result, request, args.ref);
195339
195638
  }
195340
- return (request.action === "deploy-plan" || request.action === "diff") && format !== "json" ? formatRemoteDeployPlan(result) : result;
195639
+ if ((request.action === "deploy-plan" || request.action === "diff") && format !== "json") {
195640
+ return formatRemoteDeployPlan(result);
195641
+ }
195642
+ if (request.action === "promote-plan" && !result.isError && format !== "json" && !json) {
195643
+ const payload = JSON.parse(result.content[0]?.text ?? "");
195644
+ if (!payload || typeof payload !== "object" || !("plan" in payload))
195645
+ return result;
195646
+ const plan = parseApplicationPromotionPlan(payload.plan);
195647
+ return textResult([
195648
+ `${plan.project_ref}/${plan.application_id}/${plan.environment_id}: ${plan.action}`,
195649
+ `Source: ${plan.source.project_ref}/${plan.source.environment_id}`,
195650
+ ...plan.blockers.length ? [`Blocked: ${plan.blockers.join(", ")}`] : [],
195651
+ ...plan.steps.length ? [`Next: ${plan.steps.join(" -> ")}`] : [],
195652
+ "Execution: not performed"
195653
+ ].join(`
195654
+ `));
195655
+ }
195656
+ return (request.action === "transfer-plan" || request.action === "transfer") && format !== "json" && !json ? formatReleaseTransfer(result) : result;
195341
195657
  }
195342
195658
  switch (request.action) {
195343
195659
  case "verify-plan": {
@@ -195411,6 +195727,9 @@ function registerAppTools(server2, options = {}) {
195411
195727
  "build",
195412
195728
  "upload",
195413
195729
  "configure",
195730
+ "transfer-plan",
195731
+ "transfer",
195732
+ "promote-plan",
195414
195733
  "deploy",
195415
195734
  "deploy-plan",
195416
195735
  "diff",
@@ -195426,7 +195745,7 @@ function registerAppTools(server2, options = {}) {
195426
195745
  "previews",
195427
195746
  "preview-status",
195428
195747
  "preview-cleanup"
195429
- ]), "App action; local plan is topology-only, deploy-plan/diff observe remote state, deploy skips verified no-op, rollback never downgrades schema"),
195748
+ ]), "App action; transfer reuses a verified release without build or activation; local plan is topology-only, deploy-plan/diff observe remote state, deploy skips verified no-op, rollback never downgrades schema"),
195430
195749
  kind: optional(stringEnum(["module", "command", "query", "controller", "job", "contract", "resource"]), "[generate] Scaffold kind"),
195431
195750
  template: optional(stringEnum(["minimal", "http", "command", "edge"]), "[init] Minimal application by default; explicit http/command/edge recipes"),
195432
195751
  name: optional(String2(), "[init/generate] Project or object name"),
@@ -195441,8 +195760,8 @@ function registerAppTools(server2, options = {}) {
195441
195760
  include: optional(String2(), "[dev/compile/check] Comma-separated glob patterns for source files"),
195442
195761
  out_dir: optional(String2(), "[dev/compile/plan/build/export-tools] Output directory (default: configured outDir)"),
195443
195762
  strict: optional(Boolean2(), "[dev/compile/check] Promote warnings to errors"),
195444
- format: optional(stringEnum(["text", "json"]), "[dev/generate/compile/check/plan/deploy-plan/diff/history/graph/export-tools] Output format (default: text)"),
195445
- json: optional(Literal(true), "[history] Return the validated JSON receipt"),
195763
+ format: optional(stringEnum(["text", "json"]), "[dev/generate/compile/check/plan/deploy-plan/diff/history/promote-plan/graph/export-tools] Output format (default: text)"),
195764
+ json: optional(Boolean2(), "[history/transfer-plan/transfer/promote-plan] Preserve or return the full machine-readable receipt"),
195446
195765
  profile: optional(stringEnum(["fast", "integration"]), "[dev] Run dev or dev:integration; integration verifies an explicit loopback database"),
195447
195766
  once: optional(Boolean2(), "[dev] Validate and report once without watching"),
195448
195767
  watch: optional(Boolean2(), "[dev] Watch for changes (default: true; --once disables)"),
@@ -196883,7 +197202,8 @@ function validProjectRef(ref) {
196883
197202
  return SAFE_PROJECT_REF.test(ref);
196884
197203
  }
196885
197204
  function backupBelongsToProject(backupId, projectRef) {
196886
- return BACKUP_ID.test(backupId) && backupId.startsWith(`logical-full_${projectRef}_`);
197205
+ const prefix = `logical-full_${projectRef}_`;
197206
+ return BACKUP_ID.test(backupId) && backupId.startsWith(prefix) && /^[a-f0-9]{32}$/.test(backupId.slice(prefix.length));
196887
197207
  }
196888
197208
  function verifiedBackup(value, projectRef) {
196889
197209
  if (!isRecord6(value) || typeof value.backup_id !== "string" || !backupBelongsToProject(value.backup_id, projectRef) || value.project_ref !== projectRef || typeof value.database !== "string" || !SAFE_DATABASE.test(value.database) || value.kind !== "logical-full" || !canonicalTimestamp4(value.created_at) || !canonicalTimestamp4(value.completed_at) || new Date(value.completed_at).valueOf() < new Date(value.created_at).valueOf() || typeof value.bytes !== "number" || !Number.isSafeInteger(value.bytes) || value.bytes <= 0 || typeof value.sha256 !== "string" || !SHA256.test(value.sha256))
@@ -196922,16 +197242,11 @@ function publicBackup(backup) {
196922
197242
  function equalBackup(left, right) {
196923
197243
  return left.backup_id === right.backup_id && left.project_ref === right.project_ref && left.database === right.database && left.kind === right.kind && left.created_at === right.created_at && left.completed_at === right.completed_at && left.bytes === right.bytes && left.sha256 === right.sha256;
196924
197244
  }
196925
- function newlyCreatedBackup(before, after) {
196926
- const afterById = new Map(after.map((backup) => [backup.backup_id, backup]));
196927
- for (const previous of before) {
196928
- const current = afterById.get(previous.backup_id);
196929
- if (!current || !equalBackup(previous, current))
196930
- return null;
197245
+ function requiredBackupId(value, projectRef) {
197246
+ if (typeof value !== "string" || !backupBelongsToProject(value, projectRef)) {
197247
+ throw new Error("'backup_id' must identify a logical-full backup for 'ref'");
196931
197248
  }
196932
- const known = new Set(before.map((backup) => backup.backup_id));
196933
- const additions = after.filter((backup) => !known.has(backup.backup_id));
196934
- return additions.length === 1 ? additions[0] : null;
197249
+ return value;
196935
197250
  }
196936
197251
  function restoreRequest(projectRef, backupId, expectedSha256, restoreConfirmation) {
196937
197252
  if (typeof backupId !== "string" || !backupBelongsToProject(backupId, projectRef)) {
@@ -196957,11 +197272,27 @@ function httpFailure(operation, response) {
196957
197272
  }
196958
197273
  return releaseControlFailure(operation, "HTTP_ERROR", response.transportError ? null : response.status);
196959
197274
  }
196960
- function mutationFailure(operation, response) {
196961
- if (response.responseReadError || response.transportError || response.status === 408 || response.status >= 500) {
196962
- return releaseControlFailure(operation, "OUTCOME_UNKNOWN", response.transportError ? null : response.status);
197275
+ function mutationOutcomeUnknown(response) {
197276
+ return Boolean(response.responseReadError || response.transportError || response.status === 408 || response.status >= 500 || response.status >= 200 && response.status < 300 && response.status !== 200);
197277
+ }
197278
+ function mutationFailure(operation, response, safeState = {}) {
197279
+ if (mutationOutcomeUnknown(response)) {
197280
+ return releaseControlFailure(operation, "OUTCOME_UNKNOWN", response.transportError ? null : response.status, safeState);
196963
197281
  }
196964
- return releaseControlFailure(operation, "HTTP_ERROR", response.status);
197282
+ return releaseControlFailure(operation, "HTTP_ERROR", response.status, safeState);
197283
+ }
197284
+ async function readBackup(http, projectRef, backupId) {
197285
+ let response;
197286
+ try {
197287
+ response = await http.get(`${endpoint(projectRef)}/database/backups/logical/${backupId}`, {
197288
+ maxJsonBytes: MUTATION_MAX_BYTES,
197289
+ responseTimeoutMs: RELEASE_READ_RESPONSE_TIMEOUT_MS
197290
+ });
197291
+ } catch {
197292
+ response = { ok: false, status: 0, data: null, transportError: true };
197293
+ }
197294
+ const candidate = response.ok && response.status === 200 && isRecord6(response.data) ? verifiedBackup(response.data.backup, projectRef) : null;
197295
+ return { response, backup: candidate?.backup_id === backupId ? candidate : null };
196965
197296
  }
196966
197297
  async function readInventory(http, projectRef) {
196967
197298
  const response = await http.get(`${endpoint(projectRef)}/database/backups/logical`, {
@@ -197374,6 +197705,7 @@ function registerReleaseTools(server2, http, options = {}) {
197374
197705
  const localActions = ["scope_inspect", "scope_rebind", "scope_create"];
197375
197706
  const remoteActions = [
197376
197707
  "logical_backup_list",
197708
+ "logical_backup_status",
197377
197709
  "logical_backup_create",
197378
197710
  "logical_backup_restore",
197379
197711
  "postgrest_status",
@@ -197396,7 +197728,7 @@ function registerReleaseTools(server2, http, options = {}) {
197396
197728
  web: optional(Boolean2(), "[scope_create] Whether web assets are included in release scope"),
197397
197729
  dry_run: optional(Boolean2(), "[scope_rebind] Perform calculation and validation without writing files"),
197398
197730
  cwd: optional(String2(), "[scope_inspect/scope_rebind/scope_create] Base directory for relative file and git resolution"),
197399
- backup_id: optional(String2(), "[logical_backup_restore] Exact verified logical-full backup ID from the selected project inventory"),
197731
+ backup_id: optional(String2(), "[logical_backup_create/status/restore] Stable project-bound backup ID; create generates one when omitted"),
197400
197732
  expected_sha256: optional(String2(), "[logical_backup_restore] Exact lowercase SHA-256 from the selected project inventory"),
197401
197733
  restore_confirmation: optional(String2(), "[logical_backup_restore] Exact RESTORE_PROJECT:<ref>:<backup_id>:<sha256> confirmation"),
197402
197734
  subject: optional(String2(), "[release_canary_fixture_stage_replay/disable_replay] Exact central subject UUID"),
@@ -197441,28 +197773,47 @@ function registerReleaseTools(server2, http, options = {}) {
197441
197773
  });
197442
197774
  }
197443
197775
  if (action === "logical_backup_create") {
197444
- const before = await readInventory(http, projectRef);
197445
- const beforeFailure = readInventoryFailure("release.logical_backup.create", before);
197446
- if (beforeFailure)
197447
- return beforeFailure;
197448
- const mutation = await http.postReleaseMutation(`${endpoint(projectRef)}/database/backups/logical`, {}, {
197449
- timeoutMs: BACKUP_TIMEOUT_MS
197450
- });
197451
- const after = await readInventory(http, projectRef);
197776
+ const backupId = requiredBackupId(backup_id ?? `logical-full_${projectRef}_${crypto.randomUUID().replaceAll("-", "")}`, projectRef);
197777
+ const state = { project_ref: projectRef, backup_id: backupId };
197778
+ let mutation;
197779
+ try {
197780
+ mutation = await http.postReleaseMutation(`${endpoint(projectRef)}/database/backups/logical`, { backup_id: backupId }, { timeoutMs: BACKUP_TIMEOUT_MS });
197781
+ } catch {
197782
+ mutation = { ok: false, status: 0, data: null, transportError: true };
197783
+ }
197452
197784
  if (!mutation.ok || mutation.status !== 200) {
197453
- return mutationFailure("release.logical_backup.create", mutation);
197785
+ if (mutationOutcomeUnknown(mutation)) {
197786
+ const observed = await readBackup(http, projectRef, backupId);
197787
+ if (observed.backup)
197788
+ return releaseControlFailure("release.logical_backup.create", "OUTCOME_UNKNOWN", mutation.transportError ? null : mutation.status, {
197789
+ ...state,
197790
+ backup: publicBackup(observed.backup),
197791
+ backup_verified: true,
197792
+ creation_confirmed: false
197793
+ });
197794
+ }
197795
+ return mutationFailure("release.logical_backup.create", mutation, state);
197454
197796
  }
197455
197797
  const responseBackup = isRecord6(mutation.data) ? verifiedBackup(mutation.data.backup, projectRef) : null;
197456
- const afterFailure = readInventoryFailure("release.logical_backup.create", after);
197457
- const addedBackup = after.inventory && newlyCreatedBackup(before.inventory, after.inventory);
197458
- if (!responseBackup || afterFailure || !addedBackup || !equalBackup(responseBackup, addedBackup)) {
197459
- return releaseControlFailure("release.logical_backup.create", "OUTCOME_UNKNOWN", mutation.status);
197798
+ const after = await readBackup(http, projectRef, backupId);
197799
+ if (!responseBackup || responseBackup.backup_id !== backupId || !after.backup || !equalBackup(responseBackup, after.backup)) {
197800
+ return releaseControlFailure("release.logical_backup.create", "OUTCOME_UNKNOWN", mutation.status, state);
197460
197801
  }
197461
197802
  return releaseControlSuccess("release.logical_backup.create", {
197462
- project_ref: projectRef,
197463
- backup: publicBackup(addedBackup)
197803
+ ...state,
197804
+ backup: publicBackup(after.backup)
197464
197805
  });
197465
197806
  }
197807
+ if (action === "logical_backup_status") {
197808
+ const backupId = requiredBackupId(backup_id, projectRef);
197809
+ const read = await readBackup(http, projectRef, backupId);
197810
+ const state = { project_ref: projectRef, backup_id: backupId };
197811
+ if (!read.response.ok || read.response.status !== 200) {
197812
+ const code = read.response.responseReadError || read.response.status >= 200 && read.response.status < 300 ? "INVALID_RESPONSE" : "HTTP_ERROR";
197813
+ return releaseControlFailure("release.logical_backup.status", code, read.response.transportError ? null : read.response.status, state);
197814
+ }
197815
+ return read.backup ? releaseControlSuccess("release.logical_backup.status", { ...state, backup: publicBackup(read.backup) }) : releaseControlFailure("release.logical_backup.status", "INVALID_RESPONSE", read.response.status, state);
197816
+ }
197466
197817
  if (action === "logical_backup_restore") {
197467
197818
  const request = restoreRequest(projectRef, backup_id, expected_sha256, restore_confirmation);
197468
197819
  const before = await readInventory(http, projectRef);
@@ -198994,7 +199345,7 @@ function registerRemoteDevTools(server2, options = {}) {
198994
199345
  // package.json
198995
199346
  var package_default = {
198996
199347
  name: "@supacloud/cli",
198997
- version: "0.80.0",
199348
+ version: "0.81.0",
198998
199349
  description: "Project-scoped CLI for SupaCloud users",
198999
199350
  type: "module",
199000
199351
  main: "./dist/index.js",
@@ -199046,14 +199397,14 @@ var package_default = {
199046
199397
  },
199047
199398
  dependencies: {
199048
199399
  "@supacloud/compiler": "^0.43.0",
199049
- "@supacloud/delivery": "0.10.0",
199400
+ "@supacloud/delivery": "0.11.0",
199050
199401
  "@supacloud/db": "0.16.0",
199051
199402
  fflate: "^0.8.3",
199052
199403
  typebox: "1.3.34"
199053
199404
  },
199054
199405
  overrides: {
199055
199406
  "@supacloud/contracts": "0.8.0",
199056
- "@supacloud/delivery": "0.10.0",
199407
+ "@supacloud/delivery": "0.11.0",
199057
199408
  "@graphql-tools/utils": "^12.0.3"
199058
199409
  },
199059
199410
  devDependencies: {
@@ -199274,6 +199625,7 @@ EXAMPLES
199274
199625
  ${preferredCommand} project logs --log_type database
199275
199626
  ${preferredCommand} project task_stats
199276
199627
  ${preferredCommand} release logical_backup_create --ref abc123
199628
+ ${preferredCommand} release logical_backup_status --ref abc123 --backup_id <backup_id>
199277
199629
  ${preferredCommand} release logical_backup_restore --ref abc123 --backup_id <backup_id> --expected_sha256 <sha256> --restore_confirmation RESTORE_PROJECT:abc123:<backup_id>:<sha256>
199278
199630
  ${preferredCommand} release postgrest_status --ref abc123
199279
199631
  ${preferredCommand} release postgrest_restart --ref abc123
@@ -199318,6 +199670,7 @@ EXAMPLES
199318
199670
  ${preferredCommand} app diff --ref abc123 --id orders --environment_id test --release_id <sha256> --configuration_id <uuid>
199319
199671
  ${preferredCommand} app deploy --ref abc123 --id orders --environment_id test --release_id <sha256> --configuration_id <uuid>
199320
199672
  ${preferredCommand} app status --ref abc123 --id orders --environment_id test
199673
+ ${preferredCommand} --env production app promote-plan --id orders --environment_id production --source_ref staging --source_environment_id staging --source_release_id <sha256>
199321
199674
  ${preferredCommand} app preview-plan --ref abc123 --id orders --environment_id test --release_id <sha256> --branch_ref preview-orders
199322
199675
  ${preferredCommand} app preview --ref abc123 --id orders --environment_id test --release_id <sha256> --configuration_id <uuid> --ttl_seconds 3600 --wait
199323
199676
  ${preferredCommand} app previews --ref abc123 --id orders --environment_id test
@@ -2,6 +2,9 @@ import { type ToolServer } from "../tool-server";
2
2
  import { type AppManifest } from "./app-tool-export";
3
3
  declare const REMOTE_APP_ACTIONS: {
4
4
  readonly upload: "upload_release";
5
+ readonly "transfer-plan": "get_release_transfer_plan";
6
+ readonly "promote-plan": "get_promotion_plan";
7
+ readonly transfer: "transfer_release";
5
8
  readonly configure: "put_configuration";
6
9
  readonly deploy: "deploy_release";
7
10
  readonly "deploy-plan": "get_deploy_plan";
@@ -38,6 +41,9 @@ export interface AppToolArguments {
38
41
  configuration_path?: string;
39
42
  manifest_path?: string;
40
43
  release_id?: string;
44
+ source_ref?: string;
45
+ source_release_id?: string;
46
+ source_environment_id?: string;
41
47
  cursor?: string;
42
48
  limit?: number;
43
49
  preview_id?: string;
@@ -62,7 +68,7 @@ export interface AppToolArguments {
62
68
  out_dir?: string;
63
69
  strict?: boolean;
64
70
  format?: "text" | "json";
65
- json?: true;
71
+ json?: boolean;
66
72
  target?: string;
67
73
  fix?: string;
68
74
  write?: boolean;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { HttpTransport } from "../transports/http";
2
+ export declare function applicationReleaseTransfer(http: HttpTransport, input: {
3
+ action: "get_release_transfer_plan" | "transfer_release";
4
+ ref: string;
5
+ id: string;
6
+ sourceRef: string;
7
+ sourceReleaseId: string;
8
+ }, project: string): Promise<import("./release-control-response").ReleaseControlToolResponse>;
@@ -9,7 +9,7 @@ export declare const APPLICATION_TOOL_SCHEMA: {
9
9
  ttl_seconds: Type.TOptional<Type.TInteger>;
10
10
  wait: Type.TOptional<Type.TBoolean>;
11
11
  timeout_seconds: Type.TOptional<Type.TInteger>;
12
- action: Type.TEnum<("list_releases" | "get_release" | "upload_release" | "activate_release" | "logs" | "get_runtime" | "get_deployment_evidence" | "get_configuration" | "get_rollback_snapshot" | "get_history" | "get_deploy_plan" | "get_preview_plan" | "put_configuration" | "deploy_release" | "rollback_release" | "reconcile_activation" | "retire_activation" | "create_preview" | "list_previews" | "get_preview" | "cleanup_preview")[]>;
12
+ action: Type.TEnum<("list_releases" | "get_release" | "upload_release" | "activate_release" | "logs" | "get_runtime" | "get_deployment_evidence" | "get_configuration" | "get_release_transfer_plan" | "get_promotion_plan" | "get_rollback_snapshot" | "get_history" | "get_deploy_plan" | "get_preview_plan" | "put_configuration" | "transfer_release" | "deploy_release" | "rollback_release" | "reconcile_activation" | "retire_activation" | "create_preview" | "list_previews" | "get_preview" | "cleanup_preview")[]>;
13
13
  ref: Type.TString;
14
14
  id: Type.TString;
15
15
  environment_id: Type.TOptional<Type.TString>;
@@ -19,6 +19,9 @@ export declare const APPLICATION_TOOL_SCHEMA: {
19
19
  configuration_path: Type.TOptional<Type.TString>;
20
20
  manifest_path: Type.TOptional<Type.TString>;
21
21
  release_id: Type.TOptional<Type.TString>;
22
+ source_ref: Type.TOptional<Type.TString>;
23
+ source_release_id: Type.TOptional<Type.TString>;
24
+ source_environment_id: Type.TOptional<Type.TString>;
22
25
  cursor: Type.TOptional<Type.TUnion<[Type.TString, Type.TString]>>;
23
26
  limit: Type.TOptional<Type.TInteger>;
24
27
  offset: Type.TOptional<Type.TInteger>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/cli",
3
- "version": "0.80.0",
3
+ "version": "0.81.0",
4
4
  "description": "Project-scoped CLI for SupaCloud users",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,14 +52,14 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@supacloud/compiler": "^0.43.0",
55
- "@supacloud/delivery": "0.10.0",
55
+ "@supacloud/delivery": "0.11.0",
56
56
  "@supacloud/db": "0.16.0",
57
57
  "fflate": "^0.8.3",
58
58
  "typebox": "1.3.34"
59
59
  },
60
60
  "overrides": {
61
61
  "@supacloud/contracts": "0.8.0",
62
- "@supacloud/delivery": "0.10.0",
62
+ "@supacloud/delivery": "0.11.0",
63
63
  "@graphql-tools/utils": "^12.0.3"
64
64
  },
65
65
  "devDependencies": {