run402 4.93.2 → 4.95.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/README.md +61 -59
- package/cli.mjs +40 -47
- package/core-dist/config.js +52 -18
- package/core-dist/control-plane-session.js +31 -6
- package/core-dist/keystore.js +7 -7
- package/core-dist/profiles.js +9 -7
- package/core-dist/{allowance-auth.js → wallet-auth.js} +15 -15
- package/{sdk/core-dist/allowance.js → core-dist/wallet.js} +20 -20
- package/{sdk/core-dist/write-auth-session.js → core-dist/write-approvals.js} +19 -19
- package/gitvault-surface.json +2 -2
- package/lib/admin.mjs +6 -6
- package/lib/agent.mjs +20 -18
- package/lib/ai.mjs +5 -5
- package/lib/approve.mjs +81 -0
- package/lib/apps.mjs +12 -12
- package/lib/archives.mjs +371 -8
- package/lib/argparse.mjs +5 -5
- package/lib/assets.mjs +14 -14
- package/lib/auth.mjs +34 -34
- package/lib/billing.mjs +6 -6
- package/lib/branches.mjs +7 -7
- package/lib/buzz-doctor.mjs +2 -2
- package/lib/buzz-notifications.mjs +5 -5
- package/lib/buzz.mjs +3 -3
- package/lib/buzz.test.mjs +1 -1
- package/lib/cache.mjs +1 -1
- package/lib/cdn.mjs +2 -2
- package/lib/ci.mjs +12 -12
- package/lib/claims.mjs +2 -2
- package/lib/cold-start.mjs +21 -21
- package/lib/command-manifest.mjs +55 -70
- package/lib/config.mjs +28 -28
- package/lib/contacts.mjs +16 -16
- package/lib/contracts.mjs +12 -12
- package/lib/credentials.mjs +33 -33
- package/lib/daemon-path.mjs +1 -1
- package/lib/delegates.mjs +14 -14
- package/lib/deliveries.mjs +6 -6
- package/lib/deploy-rehearse-discovery.test.mjs +7 -7
- package/lib/deploy-v2.mjs +241 -193
- package/lib/deploy.mjs +21 -53
- package/lib/dev.mjs +3 -3
- package/lib/doctor-source-scan.mjs +1 -1
- package/lib/doctor.mjs +63 -63
- package/lib/domains.mjs +27 -27
- package/lib/email.mjs +38 -38
- package/lib/errors.mjs +40 -24
- package/lib/escalations.mjs +5 -5
- package/lib/events.mjs +32 -25
- package/lib/feedback.mjs +12 -12
- package/lib/functions.mjs +34 -34
- package/lib/gitvault-daemon.mjs +1 -1
- package/lib/gitvault-scaffold.mjs +2 -2
- package/lib/gitvault.mjs +2 -2
- package/lib/grants.mjs +7 -7
- package/lib/image.mjs +10 -10
- package/lib/init.mjs +69 -69
- package/lib/jobs.mjs +15 -15
- package/lib/lightning-wallet.mjs +28 -28
- package/lib/live.mjs +1 -1
- package/lib/login.mjs +207 -0
- package/lib/logout.mjs +53 -0
- package/lib/logs.mjs +8 -8
- package/lib/messages.mjs +5 -5
- package/lib/next-actions.mjs +16 -16
- package/lib/org-context.mjs +13 -13
- package/lib/{org.mjs → orgs.mjs} +215 -167
- package/lib/pay.mjs +1 -1
- package/lib/projects.mjs +70 -84
- package/lib/redeem.mjs +7 -8
- package/lib/remote-helper-session.mjs +12 -12
- package/lib/repos.mjs +83 -83
- package/lib/rooms.mjs +105 -69
- package/lib/sdk-errors.mjs +10 -5
- package/lib/sdk.mjs +3 -3
- package/lib/secrets.mjs +13 -13
- package/lib/service.mjs +5 -5
- package/lib/session-proofs.mjs +21 -0
- package/lib/sign-in.mjs +296 -0
- package/lib/sites.mjs +22 -22
- package/lib/snapshots.mjs +10 -10
- package/lib/stats.mjs +2 -2
- package/lib/status.mjs +25 -25
- package/lib/subdomains.mjs +30 -30
- package/lib/subscriptions.mjs +10 -10
- package/lib/tier.mjs +29 -22
- package/lib/transfer.mjs +59 -86
- package/lib/up.mjs +14 -14
- package/lib/wallet-context.mjs +4 -4
- package/lib/wallet-context.test.mjs +3 -3
- package/lib/wallets.mjs +197 -32
- package/lib/webhook-secret.mjs +6 -6
- package/lib/webhooks.mjs +8 -8
- package/lib/whoami.mjs +102 -0
- package/package.json +1 -1
- package/sdk/core-dist/config.js +52 -18
- package/sdk/core-dist/control-plane-session.js +31 -6
- package/sdk/core-dist/keystore.js +7 -7
- package/sdk/core-dist/profiles.js +9 -7
- package/sdk/core-dist/{allowance-auth.js → wallet-auth.js} +15 -15
- package/{core-dist/allowance.js → sdk/core-dist/wallet.js} +20 -20
- package/{core-dist/write-auth-session.js → sdk/core-dist/write-approvals.js} +19 -19
- package/sdk/dist/actions.d.ts +4 -4
- package/sdk/dist/actions.d.ts.map +1 -1
- package/sdk/dist/app-up.d.ts +2 -2
- package/sdk/dist/app-up.d.ts.map +1 -1
- package/sdk/dist/config.d.ts +1 -2
- package/sdk/dist/config.d.ts.map +1 -1
- package/sdk/dist/config.js.map +1 -1
- package/sdk/dist/control-plane-credentials.d.ts +8 -8
- package/sdk/dist/control-plane-credentials.js +7 -7
- package/sdk/dist/credentials.d.ts +20 -20
- package/sdk/dist/credentials.d.ts.map +1 -1
- package/sdk/dist/credentials.js +1 -1
- package/sdk/dist/errors.d.ts +26 -28
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js +35 -38
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/index.d.ts +29 -16
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +30 -17
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/kernel.d.ts +1 -1
- package/sdk/dist/kernel.d.ts.map +1 -1
- package/sdk/dist/kernel.js +10 -9
- package/sdk/dist/kernel.js.map +1 -1
- package/sdk/dist/namespaces/admin.d.ts +52 -121
- package/sdk/dist/namespaces/admin.d.ts.map +1 -1
- package/sdk/dist/namespaces/admin.js +41 -45
- package/sdk/dist/namespaces/admin.js.map +1 -1
- package/sdk/dist/namespaces/agent.d.ts +2 -2
- package/sdk/dist/namespaces/agent.d.ts.map +1 -1
- package/sdk/dist/namespaces/agent.js +2 -2
- package/sdk/dist/namespaces/agent.js.map +1 -1
- package/sdk/dist/namespaces/ai.d.ts +2 -2
- package/sdk/dist/namespaces/ai.js +3 -3
- package/sdk/dist/namespaces/ai.js.map +1 -1
- package/sdk/dist/namespaces/assets.js +1 -1
- package/sdk/dist/namespaces/assets.js.map +1 -1
- package/sdk/dist/namespaces/billing.d.ts +6 -3
- package/sdk/dist/namespaces/billing.d.ts.map +1 -1
- package/sdk/dist/namespaces/billing.js.map +1 -1
- package/sdk/dist/namespaces/buzz-notifications.types.d.ts +1 -1
- package/sdk/dist/namespaces/buzz.d.ts +2 -2
- package/sdk/dist/namespaces/buzz.d.ts.map +1 -1
- package/sdk/dist/namespaces/buzz.js +2 -2
- package/sdk/dist/namespaces/buzz.js.map +1 -1
- package/sdk/dist/namespaces/buzz.types.d.ts +2 -2
- package/sdk/dist/namespaces/buzz.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/ci.js +3 -3
- package/sdk/dist/namespaces/ci.js.map +1 -1
- package/sdk/dist/namespaces/credentials.types.d.ts +1 -1
- package/sdk/dist/namespaces/deploy.d.ts +1 -1
- package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.js +31 -32
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +6 -6
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/domains.d.ts +10 -2
- package/sdk/dist/namespaces/domains.d.ts.map +1 -1
- package/sdk/dist/namespaces/domains.js +10 -5
- package/sdk/dist/namespaces/domains.js.map +1 -1
- package/sdk/dist/namespaces/errors.js +1 -1
- package/sdk/dist/namespaces/escalations.d.ts +1 -1
- package/sdk/dist/namespaces/escalations.js +1 -1
- package/sdk/dist/namespaces/escalations.types.d.ts +2 -2
- package/sdk/dist/namespaces/escalations.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/events.types.d.ts +1 -1
- package/sdk/dist/namespaces/functions.d.ts +1 -1
- package/sdk/dist/namespaces/functions.js +2 -2
- package/sdk/dist/namespaces/functions.js.map +1 -1
- package/sdk/dist/namespaces/gitvault.crypto.d.ts +1 -1
- package/sdk/dist/namespaces/gitvault.d.ts +26 -26
- package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
- package/sdk/dist/namespaces/gitvault.js +113 -113
- package/sdk/dist/namespaces/gitvault.js.map +1 -1
- package/sdk/dist/namespaces/me.d.ts +120 -0
- package/sdk/dist/namespaces/me.d.ts.map +1 -0
- package/sdk/dist/namespaces/me.js +34 -0
- package/sdk/dist/namespaces/me.js.map +1 -0
- package/sdk/dist/namespaces/org.d.ts +108 -6
- package/sdk/dist/namespaces/org.d.ts.map +1 -1
- package/sdk/dist/namespaces/org.js +63 -7
- package/sdk/dist/namespaces/org.js.map +1 -1
- package/sdk/dist/namespaces/org.types.d.ts +29 -9
- package/sdk/dist/namespaces/org.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/pay.js +3 -3
- package/sdk/dist/namespaces/pay.js.map +1 -1
- package/sdk/dist/namespaces/projects.d.ts +9 -9
- package/sdk/dist/namespaces/projects.js +15 -15
- package/sdk/dist/namespaces/projects.js.map +1 -1
- package/sdk/dist/namespaces/projects.types.d.ts +28 -12
- package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/rooms.d.ts +7 -7
- package/sdk/dist/namespaces/rooms.js +17 -17
- package/sdk/dist/namespaces/rooms.js.map +1 -1
- package/sdk/dist/namespaces/rooms.types.d.ts +9 -9
- package/sdk/dist/namespaces/rooms.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/service.d.ts +1 -1
- package/sdk/dist/namespaces/service.js +1 -1
- package/sdk/dist/namespaces/{operator-session.d.ts → session.d.ts} +135 -51
- package/sdk/dist/namespaces/session.d.ts.map +1 -0
- package/sdk/dist/namespaces/{operator-session.js → session.js} +118 -30
- package/sdk/dist/namespaces/session.js.map +1 -0
- package/sdk/dist/namespaces/subdomains.d.ts +5 -5
- package/sdk/dist/namespaces/subdomains.d.ts.map +1 -1
- package/sdk/dist/namespaces/subdomains.js +6 -6
- package/sdk/dist/namespaces/subdomains.js.map +1 -1
- package/sdk/dist/namespaces/tier.d.ts +44 -21
- package/sdk/dist/namespaces/tier.d.ts.map +1 -1
- package/sdk/dist/namespaces/tier.js +7 -7
- package/sdk/dist/namespaces/tier.js.map +1 -1
- package/sdk/dist/namespaces/transfers.d.ts +119 -85
- package/sdk/dist/namespaces/transfers.d.ts.map +1 -1
- package/sdk/dist/namespaces/transfers.js +31 -38
- package/sdk/dist/namespaces/transfers.js.map +1 -1
- package/sdk/dist/namespaces/vouchers.d.ts +9 -10
- package/sdk/dist/namespaces/vouchers.d.ts.map +1 -1
- package/sdk/dist/namespaces/vouchers.js +4 -5
- package/sdk/dist/namespaces/vouchers.js.map +1 -1
- package/sdk/dist/namespaces/wallets.d.ts +72 -3
- package/sdk/dist/namespaces/wallets.d.ts.map +1 -1
- package/sdk/dist/namespaces/wallets.js +141 -3
- package/sdk/dist/namespaces/wallets.js.map +1 -1
- package/sdk/dist/namespaces/write-approval.d.ts +101 -0
- package/sdk/dist/namespaces/write-approval.d.ts.map +1 -0
- package/sdk/dist/namespaces/write-approval.js +62 -0
- package/sdk/dist/namespaces/write-approval.js.map +1 -0
- package/sdk/dist/node/actions-node.d.ts +3 -3
- package/sdk/dist/node/actions-node.d.ts.map +1 -1
- package/sdk/dist/node/actions-node.js +44 -44
- package/sdk/dist/node/actions-node.js.map +1 -1
- package/sdk/dist/node/assets-node.js +6 -6
- package/sdk/dist/node/assets-node.js.map +1 -1
- package/sdk/dist/node/{bearer-claim-key.d.ts → bearer-redeem-key.d.ts} +12 -12
- package/sdk/dist/node/bearer-redeem-key.d.ts.map +1 -0
- package/sdk/dist/node/{bearer-claim-key.js → bearer-redeem-key.js} +21 -21
- package/sdk/dist/node/bearer-redeem-key.js.map +1 -0
- package/sdk/dist/node/ci.d.ts +1 -1
- package/sdk/dist/node/ci.d.ts.map +1 -1
- package/sdk/dist/node/ci.js +6 -6
- package/sdk/dist/node/ci.js.map +1 -1
- package/sdk/dist/node/credentials.d.ts +18 -17
- package/sdk/dist/node/credentials.d.ts.map +1 -1
- package/sdk/dist/node/credentials.js +29 -28
- package/sdk/dist/node/credentials.js.map +1 -1
- package/sdk/dist/node/deploy-manifest.d.ts +3 -5
- package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
- package/sdk/dist/node/deploy-manifest.js +3 -12
- package/sdk/dist/node/deploy-manifest.js.map +1 -1
- package/sdk/dist/node/funding-recovery.d.ts +1 -1
- package/sdk/dist/node/funding-recovery.d.ts.map +1 -1
- package/sdk/dist/node/funding-recovery.js +1 -1
- package/sdk/dist/node/funding-recovery.js.map +1 -1
- package/sdk/dist/node/gitvault-apply.d.ts +1 -1
- package/sdk/dist/node/gitvault-apply.d.ts.map +1 -1
- package/sdk/dist/node/gitvault-apply.js +1 -1
- package/sdk/dist/node/gitvault-apply.js.map +1 -1
- package/sdk/dist/node/gitvault-handoff.d.ts +22 -22
- package/sdk/dist/node/gitvault-handoff.d.ts.map +1 -1
- package/sdk/dist/node/gitvault-handoff.js +45 -45
- package/sdk/dist/node/gitvault-handoff.js.map +1 -1
- package/sdk/dist/node/gitvault-prewarm.js +7 -7
- package/sdk/dist/node/gitvault-prewarm.js.map +1 -1
- package/sdk/dist/node/gitvault-restore.d.ts +1 -1
- package/sdk/dist/node/gitvault-restore.js +1 -1
- package/sdk/dist/node/index.d.ts +16 -16
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +15 -15
- package/sdk/dist/node/index.js.map +1 -1
- package/sdk/dist/node/manifest-export.js +2 -2
- package/sdk/dist/node/manifest-export.js.map +1 -1
- package/sdk/dist/node/org-adopt.d.ts +49 -0
- package/sdk/dist/node/org-adopt.d.ts.map +1 -0
- package/sdk/dist/node/org-adopt.js +77 -0
- package/sdk/dist/node/org-adopt.js.map +1 -0
- package/sdk/dist/node/paid-fetch.d.ts +7 -7
- package/sdk/dist/node/paid-fetch.d.ts.map +1 -1
- package/sdk/dist/node/paid-fetch.js +54 -54
- package/sdk/dist/node/paid-fetch.js.map +1 -1
- package/sdk/dist/node/preflight.d.ts +1 -1
- package/sdk/dist/node/preflight.d.ts.map +1 -1
- package/sdk/dist/node/preflight.js +1 -1
- package/sdk/dist/node/preflight.js.map +1 -1
- package/sdk/dist/node/sites-node.js +1 -1
- package/sdk/dist/node/sites-node.js.map +1 -1
- package/sdk/dist/node/source-scan.d.ts +1 -1
- package/sdk/dist/node/source-scan.js +2 -2
- package/sdk/dist/node/source-scan.js.map +1 -1
- package/sdk/dist/scoped.d.ts +11 -11
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +5 -5
- package/sdk/dist/scoped.js.map +1 -1
- package/core-dist/operator-session.js +0 -154
- package/lib/allowance.mjs +0 -355
- package/lib/cloud.mjs +0 -256
- package/lib/core.mjs +0 -123
- package/lib/operator-proofs.mjs +0 -22
- package/lib/operator.mjs +0 -771
- package/sdk/core-dist/operator-session.js +0 -154
- package/sdk/dist/namespaces/allowance.d.ts +0 -79
- package/sdk/dist/namespaces/allowance.d.ts.map +0 -1
- package/sdk/dist/namespaces/allowance.js +0 -149
- package/sdk/dist/namespaces/allowance.js.map +0 -1
- package/sdk/dist/namespaces/operator-session.d.ts.map +0 -1
- package/sdk/dist/namespaces/operator-session.js.map +0 -1
- package/sdk/dist/namespaces/operator.d.ts +0 -359
- package/sdk/dist/namespaces/operator.d.ts.map +0 -1
- package/sdk/dist/namespaces/operator.js +0 -272
- package/sdk/dist/namespaces/operator.js.map +0 -1
- package/sdk/dist/node/bearer-claim-key.d.ts.map +0 -1
- package/sdk/dist/node/bearer-claim-key.js.map +0 -1
- package/sdk/dist/node/operator-claim.d.ts +0 -49
- package/sdk/dist/node/operator-claim.d.ts.map +0 -1
- package/sdk/dist/node/operator-claim.js +0 -77
- package/sdk/dist/node/operator-claim.js.map +0 -1
package/lib/deploy-v2.mjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `run402 deploy
|
|
3
|
-
*
|
|
2
|
+
* `run402 deploy` (the deploy itself) and its family — `rehearse`, `promote`,
|
|
3
|
+
* `resume`, `status`, `list`, `events`, `verify`, `resolve`, `releases` — CLI
|
|
4
|
+
* wrappers over the unified deploy primitive (`r.project(id).apply` and its
|
|
5
|
+
* sub-methods). `run402 up` does missing setup first and then runs this same
|
|
6
|
+
* deploy.
|
|
4
7
|
*
|
|
5
8
|
* Manifest format mirrors the MCP `deploy` tool's input schema:
|
|
6
9
|
* {
|
|
@@ -40,22 +43,42 @@ import {
|
|
|
40
43
|
} from "#sdk/node";
|
|
41
44
|
import { getSdk } from "./sdk.mjs";
|
|
42
45
|
import { reportSdkError, fail } from "./sdk-errors.mjs";
|
|
43
|
-
import { API,
|
|
46
|
+
import { API, walletAuthHeaders, getActiveProjectId, resolveProjectId, isCoreApiTarget, updateProject } from "./config.mjs";
|
|
44
47
|
import { delegateTokenFromEnv } from "#sdk/node";
|
|
45
48
|
import { flagValue, normalizeArgv } from "./argparse.mjs";
|
|
46
49
|
import { loadLiveControlPlaneSession } from "../core-dist/control-plane-session.js";
|
|
47
|
-
import { withAutoApprove } from "./
|
|
50
|
+
import { withAutoApprove } from "./sign-in.mjs";
|
|
48
51
|
import { editRequestAction, nextAction, retryAction } from "./next-actions.mjs";
|
|
49
52
|
import { createUpdateCheckScheduler, emitUpdateNotice } from "./update-check.mjs";
|
|
50
53
|
import { sdkStats, printVerboseStats } from "./stats.mjs";
|
|
51
54
|
|
|
52
|
-
const
|
|
55
|
+
const DEPLOY_HELP = `run402 deploy — Deploy a release from a manifest (the unified deploy primitive)
|
|
53
56
|
|
|
54
57
|
Usage:
|
|
55
|
-
run402 deploy
|
|
56
|
-
run402 deploy
|
|
57
|
-
run402 deploy
|
|
58
|
-
|
|
58
|
+
run402 deploy [--project <project_id>] [--check|--print-spec|--print-manifest|--plan|--require-plan <plan_id>] [--no-rehearse] [--quiet|--final-only] [--json]
|
|
59
|
+
run402 deploy --manifest <path> [--project <project_id>] [...same options]
|
|
60
|
+
run402 deploy --spec '<json>' [--project <project_id>] [...same options]
|
|
61
|
+
run402 deploy --dir <build-output> [--manifest <path>] [--project <project_id>]
|
|
62
|
+
cat spec.json | run402 deploy [--project <project_id>]
|
|
63
|
+
run402 deploy <subcommand> [options]
|
|
64
|
+
|
|
65
|
+
Without --manifest, --spec, --dir, or piped stdin, the manifest is discovered in
|
|
66
|
+
the current directory (run402.json, run402.deploy.json, app.json, or an
|
|
67
|
+
executable run402.deploy.{ts,mts,js,mjs}); when none is there the command fails
|
|
68
|
+
with MANIFEST_NOT_FOUND. \`run402 up\` does any missing setup (wallet, tier,
|
|
69
|
+
project, workspace link) and then runs this same deploy; \`run402 deploy\`
|
|
70
|
+
only deploys.
|
|
71
|
+
|
|
72
|
+
Subcommands:
|
|
73
|
+
rehearse <plan_id> Rehearse a persisted plan on a contained branch
|
|
74
|
+
promote <release_id> Point the live release at an existing release
|
|
75
|
+
resume <operation_id> Resume a stuck operation
|
|
76
|
+
status <operation_id> Fetch one deploy operation's snapshot
|
|
77
|
+
list [--project <project_id>] List recent deploy operations
|
|
78
|
+
events <operation_id> Fetch the event stream for an operation
|
|
79
|
+
verify <operation_id> Verify gateway and edge coherence
|
|
80
|
+
resolve <url> Explain what a public URL would serve
|
|
81
|
+
releases get|active|diff Inspect release inventory and diffs
|
|
59
82
|
|
|
60
83
|
Manifest format mirrors the MCP \`deploy\` tool's ReleaseSpec:
|
|
61
84
|
{
|
|
@@ -100,7 +123,7 @@ Options:
|
|
|
100
123
|
database/secrets/subdomains/i18n in the manifest while
|
|
101
124
|
the slice carries the build output. Requires
|
|
102
125
|
@run402/astro installed in the project.
|
|
103
|
-
--project <
|
|
126
|
+
--project <project_id> Override project_id from the manifest
|
|
104
127
|
--check Validate and normalize locally. No gateway calls or uploads.
|
|
105
128
|
--print-spec Advanced SDK-native inspection JSON, not authoring input.
|
|
106
129
|
--print-manifest Export snake_case authoring JSON relative to the original manifest
|
|
@@ -110,7 +133,7 @@ Options:
|
|
|
110
133
|
against a project with a live release is rehearsed on a contained
|
|
111
134
|
branch and committed only on a passing report (result.rehearsal);
|
|
112
135
|
a first deploy has nothing to protect and commits directly.
|
|
113
|
-
--require-plan <
|
|
136
|
+
--require-plan <plan_id> Deploy only if this reviewed plan still matches.
|
|
114
137
|
--json No-op compatibility flag; success output is always JSON.
|
|
115
138
|
--quiet Suppress per-event JSON-line stderr (final result still on stdout)
|
|
116
139
|
--final-only Alias for --quiet; final success/error envelope is still preserved
|
|
@@ -172,9 +195,9 @@ const EXECUTABLE_MANIFEST_EXTENSIONS = new Set([".ts", ".mts", ".cts", ".js", ".
|
|
|
172
195
|
const RESUME_HELP = `run402 deploy resume — Resume a stuck deploy operation
|
|
173
196
|
|
|
174
197
|
Usage:
|
|
175
|
-
run402 deploy resume <operation_id> [--project <
|
|
198
|
+
run402 deploy resume <operation_id> [--project <project_id>] [--quiet]
|
|
176
199
|
|
|
177
|
-
Used when a previous \`deploy
|
|
200
|
+
Used when a previous \`deploy\` ended in \`activation_pending\` or
|
|
178
201
|
\`schema_settling\` (e.g. transient gateway failure between SQL commit and
|
|
179
202
|
the pointer-swap activation). The gateway re-runs only the failed phase
|
|
180
203
|
forward — SQL is never replayed.
|
|
@@ -184,13 +207,25 @@ Output:
|
|
|
184
207
|
stderr: one JSON event per line (suppressed with --quiet)
|
|
185
208
|
`;
|
|
186
209
|
|
|
210
|
+
const STATUS_HELP = `run402 deploy status — Fetch one deploy operation's snapshot
|
|
211
|
+
|
|
212
|
+
Usage:
|
|
213
|
+
run402 deploy status <operation_id> [--project <project_id>]
|
|
214
|
+
|
|
215
|
+
Options:
|
|
216
|
+
--project <project_id> Project ID that owns the operation (default: active project)
|
|
217
|
+
|
|
218
|
+
Output:
|
|
219
|
+
stdout: { "operation_id": "op_...", "status": "...", "release_id": "rel_..." | null, "urls": {...} | null, ... }
|
|
220
|
+
`;
|
|
221
|
+
|
|
187
222
|
const LIST_HELP = `run402 deploy list — List recent deploy operations for a project
|
|
188
223
|
|
|
189
224
|
Usage:
|
|
190
|
-
run402 deploy list [--project <
|
|
225
|
+
run402 deploy list [--project <project_id>] [--limit <n>]
|
|
191
226
|
|
|
192
227
|
Options:
|
|
193
|
-
--project <
|
|
228
|
+
--project <project_id> Project ID to list operations for (default: active project)
|
|
194
229
|
--limit <n> Maximum number of operations to return
|
|
195
230
|
|
|
196
231
|
Output:
|
|
@@ -200,10 +235,10 @@ Output:
|
|
|
200
235
|
const EVENTS_HELP = `run402 deploy events — Fetch the recorded event stream for a deploy operation
|
|
201
236
|
|
|
202
237
|
Usage:
|
|
203
|
-
run402 deploy events <operation_id> [--project <
|
|
238
|
+
run402 deploy events <operation_id> [--project <project_id>]
|
|
204
239
|
|
|
205
240
|
Options:
|
|
206
|
-
--project <
|
|
241
|
+
--project <project_id> Project ID that owns the operation (default: active project)
|
|
207
242
|
|
|
208
243
|
Output:
|
|
209
244
|
stdout: { "events": [...] }
|
|
@@ -212,16 +247,16 @@ Output:
|
|
|
212
247
|
const VERIFY_HELP = `run402 deploy verify — Verify gateway and edge coherence
|
|
213
248
|
|
|
214
249
|
Usage:
|
|
215
|
-
run402 deploy verify <operation_id> [--project <
|
|
216
|
-
run402 deploy verify --operation <operation_id> [--project <
|
|
250
|
+
run402 deploy verify <operation_id> [--project <project_id>] [--wait] [--timeout <seconds>] [--json]
|
|
251
|
+
run402 deploy verify --operation <operation_id> [--project <project_id>] [--wait] [--timeout <seconds>] [--json]
|
|
217
252
|
|
|
218
253
|
Checks that the gateway's live release and the edge pointers observed by
|
|
219
254
|
Run402 agree for the deployment operation. Use --wait to poll until the report
|
|
220
255
|
is coherent or the timeout elapses.
|
|
221
256
|
|
|
222
257
|
Options:
|
|
223
|
-
--operation <
|
|
224
|
-
--project <
|
|
258
|
+
--operation <operation_id> Operation id to verify. Equivalent to the positional id.
|
|
259
|
+
--project <project_id> Project ID that owns the operation (default: active project)
|
|
225
260
|
--wait Poll until coherent or timeout
|
|
226
261
|
--timeout <seconds> Maximum wait time with --wait (default 60)
|
|
227
262
|
--json No-op compatibility flag; output is always JSON
|
|
@@ -236,10 +271,10 @@ Output:
|
|
|
236
271
|
stderr: one JSON poll progress line per attempt when --wait is set
|
|
237
272
|
`;
|
|
238
273
|
|
|
239
|
-
const REHEARSE_HELP = `run402 deploy rehearse — Run a plan on a contained branch (ADVANCED; rehearsal is automatic in up / deploy
|
|
274
|
+
const REHEARSE_HELP = `run402 deploy rehearse — Run a plan on a contained branch (ADVANCED; rehearsal is automatic in up / deploy)
|
|
240
275
|
|
|
241
276
|
Usage:
|
|
242
|
-
run402 deploy rehearse [<plan_id>] [--manifest <path>] [--project <
|
|
277
|
+
run402 deploy rehearse [<plan_id>] [--manifest <path>] [--project <project_id>] [--teardown on_pass|keep|always] [--json]
|
|
243
278
|
|
|
244
279
|
Options:
|
|
245
280
|
<plan_id> An already-persisted plan. Its bytes must be uploaded; when
|
|
@@ -254,18 +289,18 @@ Options:
|
|
|
254
289
|
the current directory the same way run402 up does.
|
|
255
290
|
--teardown <mode> on_pass (default: passed rehearsals delete their branch;
|
|
256
291
|
failed rehearsals keep it), keep, always.
|
|
257
|
-
--project <
|
|
292
|
+
--project <project_id> Project for write-approval metadata and project resolution.
|
|
258
293
|
|
|
259
294
|
Nothing is committed. The result carries the rehearsal report and the exact
|
|
260
|
-
bound commit command (run402 deploy
|
|
295
|
+
bound commit command (run402 deploy --require-plan <plan_id>).
|
|
261
296
|
`;
|
|
262
297
|
|
|
263
|
-
const
|
|
298
|
+
const RELEASES_HELP = `run402 deploy releases — Inspect deploy release inventory and diffs
|
|
264
299
|
|
|
265
300
|
Usage:
|
|
266
|
-
run402 deploy
|
|
267
|
-
run402 deploy
|
|
268
|
-
run402 deploy
|
|
301
|
+
run402 deploy releases get <release_id> [--project <project_id>] [--site-limit <n>]
|
|
302
|
+
run402 deploy releases active [--project <project_id>] [--site-limit <n>]
|
|
303
|
+
run402 deploy releases diff --from <empty|active|release_id> --to <active|release_id> [--project <project_id>] [--limit <n>]
|
|
269
304
|
|
|
270
305
|
Subcommands:
|
|
271
306
|
get Fetch the inventory for a specific release id
|
|
@@ -277,94 +312,83 @@ Output:
|
|
|
277
312
|
diff: { "diff": {...} } # includes route added/removed/changed diff buckets
|
|
278
313
|
`;
|
|
279
314
|
|
|
280
|
-
const
|
|
315
|
+
const RELEASES_GET_HELP = `run402 deploy releases get — Fetch a release inventory by id
|
|
281
316
|
|
|
282
317
|
Usage:
|
|
283
|
-
run402 deploy
|
|
318
|
+
run402 deploy releases get <release_id> [--project <project_id>] [--site-limit <n>]
|
|
284
319
|
|
|
285
320
|
Options:
|
|
286
|
-
--project <
|
|
321
|
+
--project <project_id> Project ID that owns the release (default: active project)
|
|
287
322
|
--site-limit <n> Maximum site path entries to include (gateway default: 5000)
|
|
288
323
|
|
|
289
324
|
Output:
|
|
290
325
|
stdout: { "release": {...} } # preserves full routes inventory and warnings
|
|
291
326
|
`;
|
|
292
327
|
|
|
293
|
-
const
|
|
328
|
+
const RELEASES_ACTIVE_HELP = `run402 deploy releases active — Fetch the active release inventory
|
|
294
329
|
|
|
295
330
|
Usage:
|
|
296
|
-
run402 deploy
|
|
331
|
+
run402 deploy releases active [--project <project_id>] [--site-limit <n>]
|
|
297
332
|
|
|
298
333
|
Options:
|
|
299
|
-
--project <
|
|
334
|
+
--project <project_id> Project ID to inspect (default: active project)
|
|
300
335
|
--site-limit <n> Maximum site path entries to include (gateway default: 5000)
|
|
301
336
|
|
|
302
337
|
Output:
|
|
303
338
|
stdout: { "release": {...} } # preserves full routes inventory and warnings
|
|
304
339
|
`;
|
|
305
340
|
|
|
306
|
-
const
|
|
341
|
+
const RELEASES_DIFF_HELP = `run402 deploy releases diff — Diff two release targets
|
|
307
342
|
|
|
308
343
|
Usage:
|
|
309
|
-
run402 deploy
|
|
344
|
+
run402 deploy releases diff --from <empty|active|release_id> --to <active|release_id> [--project <project_id>] [--limit <n>]
|
|
310
345
|
|
|
311
346
|
Options:
|
|
312
347
|
--from <target> Diff source: empty, active, or rel_...
|
|
313
348
|
--to <target> Diff target: active or rel_...
|
|
314
|
-
--project <
|
|
349
|
+
--project <project_id> Project ID to inspect (default: active project)
|
|
315
350
|
--limit <n> Maximum entries per site diff bucket (gateway default: 1000)
|
|
316
351
|
|
|
317
352
|
Output:
|
|
318
353
|
stdout: { "diff": {...} } # preserves routes.added/removed/changed
|
|
319
354
|
`;
|
|
320
355
|
|
|
321
|
-
const
|
|
356
|
+
const RESOLVE_HELP = `run402 deploy resolve — Explain what a Run402 public URL would serve
|
|
322
357
|
|
|
323
358
|
Usage:
|
|
324
|
-
run402 deploy
|
|
325
|
-
run402 deploy
|
|
359
|
+
run402 deploy resolve <url> [--project <project_id>] [--method GET]
|
|
360
|
+
run402 deploy resolve --url <url> [--project <project_id>] [--method GET]
|
|
361
|
+
run402 deploy resolve --host <host> [--path /x] [--project <project_id>] [--method GET]
|
|
326
362
|
|
|
327
|
-
|
|
363
|
+
Resolves how a project-owned Run402 subdomain or custom domain would answer
|
|
328
364
|
against the current live release. This is not an HTTP fetch, cache purge, or
|
|
329
365
|
CAS URL lookup. Query strings and fragments in URL input are ignored for route
|
|
330
366
|
resolution and reported in structured warnings.
|
|
331
367
|
|
|
332
368
|
Options:
|
|
333
|
-
--project <
|
|
334
|
-
--
|
|
335
|
-
|
|
336
|
-
Output:
|
|
337
|
-
stdout: { "would_serve": true|false, "diagnostic_status": 200|404|..., "match": "...", "summary": "...", "request": {...}, "warnings": [...], "resolution": {...}, "next_steps": [...] }
|
|
338
|
-
`;
|
|
339
|
-
|
|
340
|
-
const RESOLVE_HELP = `run402 deploy resolve — Low-level deploy URL diagnostics
|
|
341
|
-
|
|
342
|
-
Usage:
|
|
343
|
-
run402 deploy resolve --project <id> --url <url> [--method GET]
|
|
344
|
-
run402 deploy resolve --project <id> --host <host> [--path /x] [--method GET]
|
|
345
|
-
run402 deploy resolve --url <url> [--method GET] # uses active project
|
|
346
|
-
|
|
347
|
-
Options:
|
|
348
|
-
--project <id> Project ID for local apikey lookup (default: active project)
|
|
349
|
-
--url <url> Absolute HTTP(S) public URL to diagnose
|
|
369
|
+
--project <project_id> Project ID for local apikey lookup (default: active project)
|
|
370
|
+
--url <url> Absolute HTTP(S) public URL; same as the positional <url>
|
|
350
371
|
--host <host> Clean hostname without scheme/path/query/fragment
|
|
351
372
|
--path </path> Public URL path for host/path mode
|
|
352
|
-
--method <method> HTTP method to
|
|
373
|
+
--method <method> HTTP method to resolve (default: GET)
|
|
353
374
|
|
|
354
|
-
Do not combine --url with --host or --path.
|
|
375
|
+
Do not combine --url (or a positional URL) with --host or --path. Misses still
|
|
355
376
|
exit 0; inspect would_serve and diagnostic_status in the result payload.
|
|
377
|
+
|
|
378
|
+
Output:
|
|
379
|
+
stdout: { "would_serve": true|false, "diagnostic_status": 200|404|..., "match": "...", "summary": "...", "request": {...}, "warnings": [...], "resolution": {...}, "next_steps": [...] }
|
|
356
380
|
`;
|
|
357
381
|
|
|
358
382
|
export async function runDeployV2(sub, args) {
|
|
359
|
-
if (sub === "
|
|
383
|
+
if (sub === "deploy") return await deployCmd(args);
|
|
360
384
|
if (sub === "rehearse") return await rehearseCmd(args);
|
|
361
385
|
if (sub === "promote") return await promoteCmd(args);
|
|
362
386
|
if (sub === "resume") return await resumeCmd(args);
|
|
387
|
+
if (sub === "status") return await statusCmd(args);
|
|
363
388
|
if (sub === "list") return await listCmd(args);
|
|
364
389
|
if (sub === "events") return await eventsCmd(args);
|
|
365
390
|
if (sub === "verify") return await verifyCmd(args);
|
|
366
|
-
if (sub === "
|
|
367
|
-
if (sub === "diagnose") return await diagnoseCmd(args);
|
|
391
|
+
if (sub === "releases") return await releasesCmd(args);
|
|
368
392
|
if (sub === "resolve") return await resolveCmd(args);
|
|
369
393
|
fail({
|
|
370
394
|
code: "BAD_USAGE",
|
|
@@ -373,11 +397,11 @@ export async function runDeployV2(sub, args) {
|
|
|
373
397
|
});
|
|
374
398
|
}
|
|
375
399
|
|
|
376
|
-
const
|
|
400
|
+
const DEPLOY_MANIFEST_CANDIDATES = ["run402.json", "run402.deploy.json", "app.json", "run402.deploy.ts", "run402.deploy.mts", "run402.deploy.js", "run402.deploy.mjs"];
|
|
377
401
|
|
|
378
|
-
/** The manifest `deploy rehearse` would plan from in `dir`, discovered the way `up` does, or null. */
|
|
379
|
-
export function
|
|
380
|
-
for (const name of
|
|
402
|
+
/** The manifest `deploy` / `deploy rehearse` would plan from in `dir`, discovered the way `up` does, or null. */
|
|
403
|
+
export function discoverDeployManifest(dir = process.cwd()) {
|
|
404
|
+
for (const name of DEPLOY_MANIFEST_CANDIDATES) {
|
|
381
405
|
const candidate = resolve(dir, name);
|
|
382
406
|
if (existsSync(candidate)) return candidate;
|
|
383
407
|
}
|
|
@@ -438,13 +462,13 @@ async function rehearseCmd(rawArgs) {
|
|
|
438
462
|
positionals.push(arg);
|
|
439
463
|
}
|
|
440
464
|
if (positionals.length > 1) {
|
|
441
|
-
fail({ code: "BAD_USAGE", message: "Usage: run402 deploy rehearse [<plan_id>] [--manifest <path>] [--project <
|
|
465
|
+
fail({ code: "BAD_USAGE", message: "Usage: run402 deploy rehearse [<plan_id>] [--manifest <path>] [--project <project_id>] [--teardown on_pass|keep|always] [--json]" });
|
|
442
466
|
}
|
|
443
467
|
const givenPlanId = positionals[0] ?? null;
|
|
444
468
|
const explicitManifest = flagValue(args, "--manifest");
|
|
445
469
|
const manifestPath = explicitManifest
|
|
446
470
|
? (isAbsolute(explicitManifest) ? explicitManifest : resolve(process.cwd(), explicitManifest))
|
|
447
|
-
:
|
|
471
|
+
: discoverDeployManifest();
|
|
448
472
|
if (explicitManifest && !existsSync(manifestPath)) {
|
|
449
473
|
fail({ code: "BAD_USAGE", message: `Manifest not found: ${manifestPath}`, details: { flag: "--manifest", path: explicitManifest } });
|
|
450
474
|
}
|
|
@@ -452,7 +476,7 @@ async function rehearseCmd(rawArgs) {
|
|
|
452
476
|
fail({
|
|
453
477
|
code: "BAD_USAGE",
|
|
454
478
|
message: "Nothing to rehearse: pass a <plan_id>, or run from a directory with a manifest (run402.json, run402.deploy.json, app.json), or pass --manifest <path>.",
|
|
455
|
-
details: { searched:
|
|
479
|
+
details: { searched: DEPLOY_MANIFEST_CANDIDATES },
|
|
456
480
|
});
|
|
457
481
|
}
|
|
458
482
|
// When --teardown is absent, omit it from the request body entirely — the
|
|
@@ -466,7 +490,7 @@ async function rehearseCmd(rawArgs) {
|
|
|
466
490
|
// supports rehearsing with one (the route rejects only CI sessions).
|
|
467
491
|
// Rehearsal is the SAFE path; never make it the harder one.
|
|
468
492
|
if (!isCoreApiTarget() && !loadLiveControlPlaneSession() && !delegateTokenFromEnv()) {
|
|
469
|
-
|
|
493
|
+
walletAuthHeaders(`/apply/v1/plans/${givenPlanId ?? "_"}/rehearse`);
|
|
470
494
|
}
|
|
471
495
|
const sdk = getSdk();
|
|
472
496
|
const emit = makeStderrEventWriter(false);
|
|
@@ -482,14 +506,14 @@ async function rehearseCmd(rawArgs) {
|
|
|
482
506
|
});
|
|
483
507
|
const planId = planned.plan.plan_id;
|
|
484
508
|
if (!planId) {
|
|
485
|
-
fail({ code: "DRY_RUN_PLAN_NOT_COMMITTABLE", message: "Rehearsal requires a persisted plan_id, but the plan response did not include one.", details: { project_id: normalized.spec.
|
|
509
|
+
fail({ code: "DRY_RUN_PLAN_NOT_COMMITTABLE", message: "Rehearsal requires a persisted plan_id, but the plan response did not include one.", details: { project_id: normalized.spec.project_id } });
|
|
486
510
|
}
|
|
487
511
|
await sdk._applyEngine.upload(planned.plan, {
|
|
488
|
-
project: normalized.spec.
|
|
512
|
+
project: normalized.spec.project_id,
|
|
489
513
|
byteReaders: planned.byteReaders,
|
|
490
514
|
onEvent: emit,
|
|
491
515
|
});
|
|
492
|
-
return { planId, plan: planned.plan, projectId: normalized.spec.
|
|
516
|
+
return { planId, plan: planned.plan, projectId: normalized.spec.project_id };
|
|
493
517
|
}
|
|
494
518
|
|
|
495
519
|
try {
|
|
@@ -521,7 +545,7 @@ async function rehearseCmd(rawArgs) {
|
|
|
521
545
|
...(manifestPath ? { manifest_path: manifestPath } : {}),
|
|
522
546
|
...(replanned ? { replanned } : {}),
|
|
523
547
|
rehearsal,
|
|
524
|
-
commit_command: `run402 deploy
|
|
548
|
+
commit_command: `run402 deploy --require-plan ${planId}`,
|
|
525
549
|
}, null, 2));
|
|
526
550
|
if (rehearsal.report.status !== "passed") process.exit(1);
|
|
527
551
|
} catch (err) {
|
|
@@ -529,14 +553,14 @@ async function rehearseCmd(rawArgs) {
|
|
|
529
553
|
}
|
|
530
554
|
}
|
|
531
555
|
|
|
532
|
-
const PROMOTE_HELP = `run402 deploy promote —
|
|
556
|
+
const PROMOTE_HELP = `run402 deploy promote — Pointer-swap recovery (v1.58+)
|
|
533
557
|
|
|
534
558
|
Usage:
|
|
535
|
-
run402 deploy promote <
|
|
559
|
+
run402 deploy promote <release_id> [--project <project_id>] [--allow-warning <code>] [--allow-warnings] [--quiet]
|
|
536
560
|
|
|
537
561
|
Re-points the project's live release at an existing release row without
|
|
538
562
|
re-running the apply pipeline. Designed for "oops on a real project ID"
|
|
539
|
-
recovery — when an apply shipped content
|
|
563
|
+
recovery — when an apply shipped content you regret, promote
|
|
540
564
|
back to the prior release in seconds instead of re-deploying.
|
|
541
565
|
|
|
542
566
|
Promotable statuses: ready, active, superseded. Releases with status
|
|
@@ -569,9 +593,9 @@ The result's edge.state reports convergence and edge.verify_url is the direct,
|
|
|
569
593
|
operation-scoped HTTP verification endpoint.
|
|
570
594
|
|
|
571
595
|
Options:
|
|
572
|
-
<
|
|
596
|
+
<release_id> Required positional. The release to promote to.
|
|
573
597
|
Format: rel_*
|
|
574
|
-
--project <
|
|
598
|
+
--project <project_id> Project id. Falls back to active project, then
|
|
575
599
|
RUN402_PROJECT_ID env var.
|
|
576
600
|
--allow-warning <code> Acknowledge a specific blocking warning
|
|
577
601
|
(repeatable).
|
|
@@ -697,11 +721,11 @@ async function promoteCmd(args) {
|
|
|
697
721
|
emitDeployUpdateNotice("promote", args, { quiet: opts.quiet });
|
|
698
722
|
const projectId = opts.project ?? resolveProjectId(null);
|
|
699
723
|
|
|
700
|
-
// Preserve the aggressive early-exit when no
|
|
724
|
+
// Preserve the aggressive early-exit when no local wallet is configured
|
|
701
725
|
// — same as apply.
|
|
702
726
|
// A delegate holds `deploy` and the gateway accepts it on this route; refusing
|
|
703
727
|
// locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
|
|
704
|
-
if (!delegateTokenFromEnv())
|
|
728
|
+
if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/releases");
|
|
705
729
|
|
|
706
730
|
try {
|
|
707
731
|
// Call the engine directly (matches the pattern used by apply / resume
|
|
@@ -755,12 +779,12 @@ function makeStderrEventWriter(quiet) {
|
|
|
755
779
|
|
|
756
780
|
function emitDeployUpdateNotice(subcommand, args, { quiet = false } = {}) {
|
|
757
781
|
const scheduler = createUpdateCheckScheduler({
|
|
758
|
-
command: ["run402", "deploy", subcommand, ...args],
|
|
782
|
+
command: ["run402", "deploy", ...(subcommand ? [subcommand] : []), ...args],
|
|
759
783
|
});
|
|
760
784
|
emitUpdateNotice(scheduler.cachedNotice, { quiet });
|
|
761
785
|
}
|
|
762
786
|
|
|
763
|
-
function
|
|
787
|
+
function parseDeployArgs(args) {
|
|
764
788
|
const opts = {
|
|
765
789
|
manifest: null,
|
|
766
790
|
spec: null,
|
|
@@ -780,7 +804,7 @@ function parseApplyArgs(args) {
|
|
|
780
804
|
for (let i = 0; i < args.length; i++) {
|
|
781
805
|
const arg = args[i];
|
|
782
806
|
if (arg === "--help" || arg === "-h") {
|
|
783
|
-
console.log(
|
|
807
|
+
console.log(DEPLOY_HELP);
|
|
784
808
|
process.exit(0);
|
|
785
809
|
}
|
|
786
810
|
if (arg === "--manifest" || arg === "--spec" || arg === "--dir" || arg === "--project" || arg === "--allow-warning" || arg === "--require-plan" || arg === "--plan-fingerprint" || arg === "--teardown") {
|
|
@@ -844,13 +868,13 @@ function parseApplyArgs(args) {
|
|
|
844
868
|
if (typeof arg === "string" && arg.startsWith("-")) {
|
|
845
869
|
fail({
|
|
846
870
|
code: "BAD_USAGE",
|
|
847
|
-
message: `Unknown flag for deploy
|
|
871
|
+
message: `Unknown flag for deploy: ${arg}`,
|
|
848
872
|
details: { flag: arg, allowed_flags: allowedFlags },
|
|
849
873
|
});
|
|
850
874
|
}
|
|
851
875
|
fail({
|
|
852
876
|
code: "BAD_USAGE",
|
|
853
|
-
message: `Unexpected argument for deploy
|
|
877
|
+
message: `Unexpected argument for deploy: ${arg}`,
|
|
854
878
|
details: { argument: arg },
|
|
855
879
|
});
|
|
856
880
|
}
|
|
@@ -878,7 +902,7 @@ function setApplyMode(opts, mode, flag) {
|
|
|
878
902
|
if (opts.mode !== null) {
|
|
879
903
|
fail({
|
|
880
904
|
code: "BAD_USAGE",
|
|
881
|
-
message: "Choose only one execution mode for deploy
|
|
905
|
+
message: "Choose only one execution mode for deploy.",
|
|
882
906
|
details: { existing_mode: opts.mode, flag },
|
|
883
907
|
});
|
|
884
908
|
}
|
|
@@ -1052,7 +1076,7 @@ export function collectManifestSourceFiles(spec, baseDir) {
|
|
|
1052
1076
|
|
|
1053
1077
|
/**
|
|
1054
1078
|
* Persist an activated release's `deployment_id` into the local keystore.
|
|
1055
|
-
* `run402 subdomains
|
|
1079
|
+
* `run402 subdomains add` reads it as an optimization only — the gateway
|
|
1056
1080
|
* binds the live release without it — so this must never throw.
|
|
1057
1081
|
*/
|
|
1058
1082
|
export function rememberLastDeployment(projectId, deploymentId) {
|
|
@@ -1060,11 +1084,34 @@ export function rememberLastDeployment(projectId, deploymentId) {
|
|
|
1060
1084
|
try { updateProject(projectId, { last_deployment_id: deploymentId }); } catch { /* best-effort cache */ }
|
|
1061
1085
|
}
|
|
1062
1086
|
|
|
1063
|
-
async function
|
|
1064
|
-
const opts =
|
|
1065
|
-
const
|
|
1087
|
+
async function deployCmd(args) {
|
|
1088
|
+
const opts = parseDeployArgs(args);
|
|
1089
|
+
const stdinPresent = hasStdinSource();
|
|
1090
|
+
if (opts.manifest === null && opts.spec === null && opts.dir === null && !stdinPresent) {
|
|
1091
|
+
// Bare `run402 deploy`: the manifest is the one in the current directory,
|
|
1092
|
+
// discovered the way `up` discovers it. None there is a typed refusal,
|
|
1093
|
+
// never a help page — `deploy` is a verb.
|
|
1094
|
+
const discovered = discoverDeployManifest();
|
|
1095
|
+
if (!discovered) {
|
|
1096
|
+
fail({
|
|
1097
|
+
code: "MANIFEST_NOT_FOUND",
|
|
1098
|
+
message: `No deploy manifest found in ${process.cwd()}. Add run402.json, run402.deploy.json or app.json here, or pass --manifest <path>.`,
|
|
1099
|
+
details: { dir: process.cwd(), candidates: DEPLOY_MANIFEST_CANDIDATES },
|
|
1100
|
+
next_actions: [
|
|
1101
|
+
{
|
|
1102
|
+
type: "create_manifest",
|
|
1103
|
+
path: "run402.json",
|
|
1104
|
+
content: JSON.stringify({ site: { replace: { "index.html": { path: "index.html" } } } }, null, 2),
|
|
1105
|
+
why: "Write a deploy manifest, then re-run `run402 deploy`. This minimal site manifest deploys as-is; add database/functions/routes slices later.",
|
|
1106
|
+
},
|
|
1107
|
+
],
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
opts.manifest = discovered;
|
|
1111
|
+
}
|
|
1112
|
+
const { source, error: sourceError } = resolveApplySource(opts, stdinPresent);
|
|
1066
1113
|
if (sourceError) fail(sourceError);
|
|
1067
|
-
emitDeployUpdateNotice(
|
|
1114
|
+
emitDeployUpdateNotice(null, args, { quiet: opts.quiet });
|
|
1068
1115
|
|
|
1069
1116
|
let raw;
|
|
1070
1117
|
let manifestPath = null;
|
|
@@ -1121,11 +1168,11 @@ async function applyCmd(args) {
|
|
|
1121
1168
|
}
|
|
1122
1169
|
|
|
1123
1170
|
// Reject empty specs client-side. Without this guard,
|
|
1124
|
-
// `run402 deploy
|
|
1171
|
+
// `run402 deploy --spec '{}'` (and `--manifest <empty>`) would silently
|
|
1125
1172
|
// send an empty ReleaseSpec to /apply/v1/plans with no signal that nothing
|
|
1126
1173
|
// was deployed.
|
|
1127
1174
|
//
|
|
1128
|
-
// `deploy
|
|
1175
|
+
// `deploy` is v2-only — only meaningful keys are the v2 ReleaseSpec
|
|
1129
1176
|
// shape (database, site, functions, secrets, subdomains, domains).
|
|
1130
1177
|
// For object-typed sections the "container is non-empty" check isn't enough
|
|
1131
1178
|
// — `site:{replace:{}}` has one key but ships nothing. We recurse one level
|
|
@@ -1203,11 +1250,11 @@ async function applyCmd(args) {
|
|
|
1203
1250
|
target = await resolveDeploymentTarget({
|
|
1204
1251
|
appRoot: applicationScope.app_root,
|
|
1205
1252
|
manifestPath: manifestPath ?? undefined, projectId: opts.project || undefined, environmentProjectId: process.env.RUN402_PROJECT_ID || undefined,
|
|
1206
|
-
manifestProjectId: manifestProject || (releaseSpec.
|
|
1253
|
+
manifestProjectId: manifestProject || (releaseSpec.project_id === "prj_up_preflight_placeholder" ? undefined : releaseSpec.project_id),
|
|
1207
1254
|
targetKind: isCoreApiTarget() ? "core" : "cloud", apiBase: API,
|
|
1208
1255
|
allowUnresolved: opts.mode === "check" || opts.mode === "printSpec" || opts.mode === "printManifest",
|
|
1209
1256
|
});
|
|
1210
|
-
if (target.project_id) releaseSpec.
|
|
1257
|
+
if (target.project_id) releaseSpec.project_id = target.project_id;
|
|
1211
1258
|
} catch (err) { reportSdkError(err); }
|
|
1212
1259
|
const idempotencyKey = normalizedManifest.idempotencyKey;
|
|
1213
1260
|
|
|
@@ -1233,7 +1280,7 @@ async function applyCmd(args) {
|
|
|
1233
1280
|
ok: true,
|
|
1234
1281
|
mode: "check",
|
|
1235
1282
|
project_id: target.project_id,
|
|
1236
|
-
...describeLocalPreflight({ entryPoint: "deploy
|
|
1283
|
+
...describeLocalPreflight({ entryPoint: "deploy", appRoot: manifestPath ? dirname(manifestPath) : resolve(opts.dir || process.cwd()), manifestPath, authoring: normalizedManifest.manifest, spec: releaseSpec, target, apiBase: API }),
|
|
1237
1284
|
}, null, 2));
|
|
1238
1285
|
return;
|
|
1239
1286
|
}
|
|
@@ -1242,7 +1289,7 @@ async function applyCmd(args) {
|
|
|
1242
1289
|
return;
|
|
1243
1290
|
}
|
|
1244
1291
|
if (opts.mode === "printSpec") {
|
|
1245
|
-
console.log(JSON.stringify({ ...releaseSpec,
|
|
1292
|
+
console.log(JSON.stringify({ ...releaseSpec, project_id: target.project_id ?? undefined }, null, 2));
|
|
1246
1293
|
return;
|
|
1247
1294
|
}
|
|
1248
1295
|
|
|
@@ -1251,22 +1298,22 @@ async function applyCmd(args) {
|
|
|
1251
1298
|
const delegateToken = delegateTokenFromEnv();
|
|
1252
1299
|
if (useGithubActionsOidc) {
|
|
1253
1300
|
sdkOpts = {
|
|
1254
|
-
credentials: githubActionsCredentials({ projectId: releaseSpec.
|
|
1301
|
+
credentials: githubActionsCredentials({ projectId: releaseSpec.project_id, apiBase: API }),
|
|
1255
1302
|
disablePaidFetch: true,
|
|
1256
1303
|
};
|
|
1257
1304
|
} else if (delegateToken) {
|
|
1258
1305
|
// A delegate is a complete, self-contained deploy credential: the owner
|
|
1259
1306
|
// minted it with their wallet and handed it over, so this process needs no
|
|
1260
|
-
//
|
|
1307
|
+
// wallet of its own. Skipping the guard is the point — an agent that
|
|
1261
1308
|
// lost its local state (or never had a wallet) can still deploy. Paid fetch
|
|
1262
1309
|
// is disabled for the same reason it is under CI: a delegate authorizes
|
|
1263
1310
|
// deploys, not spending.
|
|
1264
1311
|
sdkOpts = { delegateToken, disablePaidFetch: true };
|
|
1265
1312
|
} else if (!isCoreApiTarget() && !loadLiveControlPlaneSession()) {
|
|
1266
|
-
// Aggressive early exit when no
|
|
1267
|
-
// wallet-less
|
|
1313
|
+
// Aggressive early exit when no local wallet is configured — unless a
|
|
1314
|
+
// wallet-less person is deploying via their sign-in session
|
|
1268
1315
|
// or the active target is a self-hosted Core Gateway.
|
|
1269
|
-
|
|
1316
|
+
walletAuthHeaders("/apply/v1/plans");
|
|
1270
1317
|
}
|
|
1271
1318
|
|
|
1272
1319
|
try {
|
|
@@ -1302,14 +1349,14 @@ async function applyCmd(args) {
|
|
|
1302
1349
|
target: isCoreApiTarget() ? "core" : "cloud",
|
|
1303
1350
|
...(opts.allowDirty ? { allowDirty: true } : {}),
|
|
1304
1351
|
// The `gitvault_commit` line is printed ALWAYS, and to stderr, so
|
|
1305
|
-
// `run402 deploy
|
|
1352
|
+
// `run402 deploy | jq` stays clean (the pipe contract).
|
|
1306
1353
|
onCommitLine: (line) => { if (!opts.quiet) process.stderr.write(`${line}\n`); },
|
|
1307
1354
|
}),
|
|
1308
1355
|
);
|
|
1309
|
-
// Cache the activated deployment id so `run402 subdomains
|
|
1356
|
+
// Cache the activated deployment id so `run402 subdomains add` can
|
|
1310
1357
|
// pass it as an optimization (the gateway defaults to the live release
|
|
1311
1358
|
// without it). Best-effort: a keystore hiccup never fails the deploy.
|
|
1312
|
-
rememberLastDeployment(releaseSpec.
|
|
1359
|
+
rememberLastDeployment(releaseSpec.project_id, outcome.deploy?.urls?.deployment_id);
|
|
1313
1360
|
if (!outcome.gitvault) {
|
|
1314
1361
|
console.log(JSON.stringify({ ...outcome.deploy, stats: sdkStats(sdk) }, null, 2));
|
|
1315
1362
|
printVerboseStats(opts.verbose, sdk);
|
|
@@ -1420,7 +1467,7 @@ const CI_DEPLOY_ERROR_GUIDANCE = {
|
|
|
1420
1467
|
hint: "The GitHub repository id in the OIDC token does not match the linked binding.",
|
|
1421
1468
|
next_actions: [
|
|
1422
1469
|
editRequestAction("run402 ci link github", "Re-link from the current repository."),
|
|
1423
|
-
editRequestAction("run402 ci link github --repository-id <
|
|
1470
|
+
editRequestAction("run402 ci link github --repository-id <repository_id>", "Pass the numeric GitHub repository id if automatic lookup fails."),
|
|
1424
1471
|
],
|
|
1425
1472
|
},
|
|
1426
1473
|
forbidden_spec_field: {
|
|
@@ -1435,14 +1482,14 @@ const CI_DEPLOY_ERROR_GUIDANCE = {
|
|
|
1435
1482
|
next_actions: [
|
|
1436
1483
|
editRequestAction("run402 ci link github --route-scope <pattern>", "Add a CI route scope for every exact or prefix path the workflow may deploy."),
|
|
1437
1484
|
nextAction("edit_request", { why: "Use exact scopes such as --route-scope /admin or prefix scopes such as --route-scope /api/*." }),
|
|
1438
|
-
editRequestAction("run402 deploy
|
|
1485
|
+
editRequestAction("run402 deploy", "Run route changes locally when they are outside the CI delegation."),
|
|
1439
1486
|
],
|
|
1440
1487
|
},
|
|
1441
1488
|
forbidden_plan: {
|
|
1442
1489
|
hint: "The gateway rejected this deploy plan for CI. Keep CI deploys to the allowed resources and re-link if policy changed.",
|
|
1443
1490
|
next_actions: [
|
|
1444
1491
|
nextAction("edit_request", { why: "Inspect the gateway error details for the rejected resource." }),
|
|
1445
|
-
editRequestAction("run402 deploy
|
|
1492
|
+
editRequestAction("run402 deploy", "Run operations outside the CI allowlist locally."),
|
|
1446
1493
|
],
|
|
1447
1494
|
},
|
|
1448
1495
|
payment_required: {
|
|
@@ -1456,7 +1503,7 @@ const CI_DEPLOY_ERROR_GUIDANCE = {
|
|
|
1456
1503
|
|
|
1457
1504
|
/**
|
|
1458
1505
|
* The gateway's envelope for gitvault deploy errors — `upgrade_client` first,
|
|
1459
|
-
* then `grandfather_policy` — is relayed untouched: `
|
|
1506
|
+
* then `grandfather_policy` — is relayed untouched: `deployCmd` deploys
|
|
1460
1507
|
* through `applyWithGitvault`, which declares `{capture_id,
|
|
1461
1508
|
* snapshot_oid_hmac}` at plan time and presents an activation token at
|
|
1462
1509
|
* commit, satisfying `gitvault_policy: required`, so no client-side rewrite
|
|
@@ -1493,8 +1540,8 @@ function enhanceDeployWarningError(err) {
|
|
|
1493
1540
|
? [code]
|
|
1494
1541
|
: [];
|
|
1495
1542
|
const allowWarningCommand = unacknowledgedCodes.length > 0
|
|
1496
|
-
? `run402 deploy
|
|
1497
|
-
: "run402 deploy
|
|
1543
|
+
? `run402 deploy ${unacknowledgedCodes.map((warningCode) => `--allow-warning ${warningCode}`).join(" ")}`
|
|
1544
|
+
: "run402 deploy --allow-warning <code>";
|
|
1498
1545
|
const allowWarningAction = editRequestAction(
|
|
1499
1546
|
allowWarningCommand,
|
|
1500
1547
|
unacknowledgedCodes.length > 0
|
|
@@ -1505,9 +1552,9 @@ function enhanceDeployWarningError(err) {
|
|
|
1505
1552
|
...(affected.length > 0
|
|
1506
1553
|
? [editRequestAction("run402 secrets set <project> <KEY> --stdin", `Set or inspect affected secrets: ${Array.from(new Set(affected)).join(", ")}`)]
|
|
1507
1554
|
: []),
|
|
1508
|
-
retryAction("run402 deploy
|
|
1555
|
+
retryAction("run402 deploy", "Retry after resolving warnings."),
|
|
1509
1556
|
allowWarningAction,
|
|
1510
|
-
editRequestAction("run402 deploy
|
|
1557
|
+
editRequestAction("run402 deploy --allow-warnings", "Use only when every warning was explicitly reviewed."),
|
|
1511
1558
|
];
|
|
1512
1559
|
enhanced.body = {
|
|
1513
1560
|
...existingBody,
|
|
@@ -1516,7 +1563,7 @@ function enhanceDeployWarningError(err) {
|
|
|
1516
1563
|
hint: existingBody.hint ||
|
|
1517
1564
|
routeGuidance?.hint ||
|
|
1518
1565
|
(code === "MISSING_REQUIRED_SECRET"
|
|
1519
|
-
? "Set the missing secret values with `run402 secrets set <project> <KEY> --stdin` or `--file <path>`, then retry deploy
|
|
1566
|
+
? "Set the missing secret values with `run402 secrets set <project> <KEY> --stdin` or `--file <path>`, then retry the deploy."
|
|
1520
1567
|
: "Review the plan warnings, then retry with --allow-warning <code> for reviewed warnings if you intentionally accept them."),
|
|
1521
1568
|
next_actions: Array.isArray(existingBody.next_actions) && existingBody.next_actions.length > 0
|
|
1522
1569
|
? existingBody.next_actions
|
|
@@ -1536,22 +1583,22 @@ const ROUTE_WARNING_GUIDANCE = {
|
|
|
1536
1583
|
nextAction("edit_request", { why: "Review application auth and authorization in the routed function." }),
|
|
1537
1584
|
nextAction("edit_request", { why: "Add CSRF protection for cookie-authenticated POST/PUT/PATCH/DELETE routes." }),
|
|
1538
1585
|
nextAction("edit_request", { why: "Implement CORS and OPTIONS explicitly when cross-origin callers are intended." }),
|
|
1539
|
-
retryAction("run402 deploy
|
|
1586
|
+
retryAction("run402 deploy --allow-warning <code>", "Acknowledge only the warning that has requires_confirmation: true, after review."),
|
|
1540
1587
|
],
|
|
1541
1588
|
},
|
|
1542
1589
|
ROUTE_TARGET_CARRIED_FORWARD: {
|
|
1543
1590
|
hint: "A carried-forward route still points at a base-release function target.",
|
|
1544
1591
|
next_actions: [
|
|
1545
|
-
editRequestAction("run402 deploy
|
|
1546
|
-
editRequestAction("run402 deploy
|
|
1592
|
+
editRequestAction("run402 deploy releases active", "Inspect the active release."),
|
|
1593
|
+
editRequestAction("run402 deploy --manifest <path>", "Deploy routes.replace if the target should change in this release."),
|
|
1547
1594
|
],
|
|
1548
1595
|
},
|
|
1549
1596
|
ROUTE_SHADOWS_STATIC_PATH: {
|
|
1550
1597
|
hint: "A dynamic route shadows a static site path.",
|
|
1551
1598
|
next_actions: [
|
|
1552
1599
|
nextAction("edit_request", { why: "Inspect the warning details for affected static paths." }),
|
|
1553
|
-
editRequestAction("run402 deploy
|
|
1554
|
-
retryAction("run402 deploy
|
|
1600
|
+
editRequestAction("run402 deploy releases active", "Inspect live routes."),
|
|
1601
|
+
retryAction("run402 deploy --allow-warnings", "Retry only when dynamic shadowing is intentional."),
|
|
1555
1602
|
],
|
|
1556
1603
|
},
|
|
1557
1604
|
WILDCARD_ROUTE_SHADOWS_STATIC_PATHS: {
|
|
@@ -1559,7 +1606,7 @@ const ROUTE_WARNING_GUIDANCE = {
|
|
|
1559
1606
|
next_actions: [
|
|
1560
1607
|
nextAction("edit_request", { why: "Review affected route/static path details." }),
|
|
1561
1608
|
nextAction("edit_request", { why: "Split exact routes or move static paths if the shadowing is accidental." }),
|
|
1562
|
-
retryAction("run402 deploy
|
|
1609
|
+
retryAction("run402 deploy --allow-warnings", "Retry only when the wildcard shadowing is intentional."),
|
|
1563
1610
|
],
|
|
1564
1611
|
},
|
|
1565
1612
|
METHOD_SPECIFIC_ROUTE_ALLOWS_GET_STATIC_FALLBACK: {
|
|
@@ -1575,7 +1622,7 @@ const ROUTE_WARNING_GUIDANCE = {
|
|
|
1575
1622
|
nextAction("edit_request", { why: "Add the mutation methods the routed function supports, such as POST." }),
|
|
1576
1623
|
nextAction("edit_request", { why: "Omit methods to allow every supported method when the route is an API surface." }),
|
|
1577
1624
|
nextAction("edit_request", { why: "Set acknowledge_readonly: true on an intentionally read-only GET/HEAD wildcard function route." }),
|
|
1578
|
-
retryAction("run402 deploy
|
|
1625
|
+
retryAction("run402 deploy --allow-warning WILDCARD_ROUTE_EXCLUDES_MUTATION_METHODS", "Use only as a reviewed CLI escape hatch."),
|
|
1579
1626
|
],
|
|
1580
1627
|
},
|
|
1581
1628
|
ROUTE_TABLE_NEAR_LIMIT: {
|
|
@@ -1674,7 +1721,7 @@ function rejectLegacySecretManifest(spec, details) {
|
|
|
1674
1721
|
if (Array.isArray(secrets) && secrets.length > 0) {
|
|
1675
1722
|
fail({
|
|
1676
1723
|
code: "UNSAFE_SECRET_MANIFEST",
|
|
1677
|
-
message: "Deploy manifests must not contain secret values.
|
|
1724
|
+
message: "Deploy manifests must not contain secret values. Secrets arrays are not a deploy manifest shape.",
|
|
1678
1725
|
hint: "Run `run402 secrets set <project> <KEY> --file <path>` first, then use `\"secrets\": { \"require\": [\"KEY\"] }` in the deploy manifest.",
|
|
1679
1726
|
details: { ...details, field: "secrets", legacy_shape: "array" },
|
|
1680
1727
|
});
|
|
@@ -1721,7 +1768,7 @@ async function resumeCmd(args) {
|
|
|
1721
1768
|
|
|
1722
1769
|
// A delegate holds `deploy` and the gateway accepts it on this route; refusing
|
|
1723
1770
|
// locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
|
|
1724
|
-
if (!delegateTokenFromEnv())
|
|
1771
|
+
if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/operations");
|
|
1725
1772
|
|
|
1726
1773
|
try {
|
|
1727
1774
|
const result = await getSdk({ disablePaidFetch: true })._applyEngine.resume(opts.operationId, {
|
|
@@ -1734,6 +1781,31 @@ async function resumeCmd(args) {
|
|
|
1734
1781
|
}
|
|
1735
1782
|
}
|
|
1736
1783
|
|
|
1784
|
+
async function statusCmd(args) {
|
|
1785
|
+
const parsed = parseDeploySubcommandArgs(args, {
|
|
1786
|
+
command: "deploy status",
|
|
1787
|
+
help: STATUS_HELP,
|
|
1788
|
+
valueFlags: ["--project"],
|
|
1789
|
+
});
|
|
1790
|
+
const [operationId] = expectPositionals(parsed.positionals, {
|
|
1791
|
+
command: "run402 deploy status <operation_id>",
|
|
1792
|
+
min: 1,
|
|
1793
|
+
max: 1,
|
|
1794
|
+
missing: "Missing <operation_id>.",
|
|
1795
|
+
});
|
|
1796
|
+
const project = resolveProjectId(parsed.flags["--project"] ?? null);
|
|
1797
|
+
// A delegate holds `deploy` and the gateway accepts it on this route; refusing
|
|
1798
|
+
// locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
|
|
1799
|
+
if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/operations");
|
|
1800
|
+
|
|
1801
|
+
try {
|
|
1802
|
+
const result = await getSdk()._applyEngine.status(operationId, { project });
|
|
1803
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1804
|
+
} catch (err) {
|
|
1805
|
+
reportSdkError(err);
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1737
1809
|
async function listCmd(args) {
|
|
1738
1810
|
const parsed = parseDeploySubcommandArgs(args, {
|
|
1739
1811
|
command: "deploy list",
|
|
@@ -1741,7 +1813,7 @@ async function listCmd(args) {
|
|
|
1741
1813
|
valueFlags: ["--project", "--limit"],
|
|
1742
1814
|
});
|
|
1743
1815
|
expectPositionals(parsed.positionals, {
|
|
1744
|
-
command: "run402 deploy list [--project <
|
|
1816
|
+
command: "run402 deploy list [--project <project_id>] [--limit <n>]",
|
|
1745
1817
|
max: 0,
|
|
1746
1818
|
});
|
|
1747
1819
|
const opts = {
|
|
@@ -1757,21 +1829,21 @@ async function listCmd(args) {
|
|
|
1757
1829
|
// ever widened, widen the ROUTE first, then this guard.
|
|
1758
1830
|
//
|
|
1759
1831
|
// The refusal is correct; the REMEDY must still be honest. Falling through
|
|
1760
|
-
// to
|
|
1832
|
+
// to NO_WALLET would tell a delegate holder to run `run402 init`, which
|
|
1761
1833
|
// is wrong for a credential that is wallet-less by design — the same
|
|
1762
1834
|
// misleading-remedy shape removed from the payment path in 4.11.2.
|
|
1763
1835
|
if (delegateTokenFromEnv()) {
|
|
1764
1836
|
fail({
|
|
1765
1837
|
code: "DELEGATE_SCOPE_INSUFFICIENT",
|
|
1766
1838
|
message: "Listing deploy operations is not available to a delegate.",
|
|
1767
|
-
hint: "Use `run402 deploy events <operation_id>` or `deploy verify <operation_id>` for a specific operation, which a delegate CAN read. A full listing needs the project apikey or the owner wallet.",
|
|
1839
|
+
hint: "Use `run402 deploy status <operation_id>`, `deploy events <operation_id>` or `deploy verify <operation_id>` for a specific operation, which a delegate CAN read. A full listing needs the project apikey or the owner wallet.",
|
|
1768
1840
|
details: { command: "deploy list", credential: "delegate", route: "GET /apply/v1/operations" },
|
|
1769
1841
|
next_actions: [
|
|
1770
|
-
{ type: "run_command", command: "run402 deploy
|
|
1842
|
+
{ type: "run_command", command: "run402 deploy status <operation_id>", why: "Per-operation reads are within a delegate's deploy scope." },
|
|
1771
1843
|
],
|
|
1772
1844
|
});
|
|
1773
1845
|
}
|
|
1774
|
-
|
|
1846
|
+
walletAuthHeaders("/apply/v1/operations");
|
|
1775
1847
|
|
|
1776
1848
|
try {
|
|
1777
1849
|
const sdkOpts = { project };
|
|
@@ -1800,7 +1872,7 @@ async function eventsCmd(args) {
|
|
|
1800
1872
|
const project = resolveProjectId(opts.project);
|
|
1801
1873
|
// A delegate holds `deploy` and the gateway accepts it on this route; refusing
|
|
1802
1874
|
// locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
|
|
1803
|
-
if (!delegateTokenFromEnv())
|
|
1875
|
+
if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/operations");
|
|
1804
1876
|
|
|
1805
1877
|
try {
|
|
1806
1878
|
const result = await getSdk()._applyEngine.events(opts.operationId, { project });
|
|
@@ -1818,7 +1890,7 @@ async function verifyCmd(args) {
|
|
|
1818
1890
|
booleanFlags: ["--wait", "--json"],
|
|
1819
1891
|
});
|
|
1820
1892
|
const positionals = expectPositionals(parsed.positionals, {
|
|
1821
|
-
command: "run402 deploy verify <operation_id> [--project <
|
|
1893
|
+
command: "run402 deploy verify <operation_id> [--project <project_id>] [--wait]",
|
|
1822
1894
|
max: 1,
|
|
1823
1895
|
});
|
|
1824
1896
|
const positionalOperationId = positionals[0] ?? null;
|
|
@@ -1835,7 +1907,7 @@ async function verifyCmd(args) {
|
|
|
1835
1907
|
fail({
|
|
1836
1908
|
code: "BAD_USAGE",
|
|
1837
1909
|
message: "Missing <operation_id>.",
|
|
1838
|
-
hint: "run402 deploy verify <operation_id> [--project <
|
|
1910
|
+
hint: "run402 deploy verify <operation_id> [--project <project_id>] [--wait]",
|
|
1839
1911
|
});
|
|
1840
1912
|
}
|
|
1841
1913
|
const project = resolveProjectId(parsed.flags["--project"] ?? null);
|
|
@@ -1846,7 +1918,7 @@ async function verifyCmd(args) {
|
|
|
1846
1918
|
|
|
1847
1919
|
// A delegate holds `deploy` and the gateway accepts it on this route; refusing
|
|
1848
1920
|
// locally would tell a wallet-less holder to run `run402 init` (see 4.11.2).
|
|
1849
|
-
if (!delegateTokenFromEnv())
|
|
1921
|
+
if (!delegateTokenFromEnv()) walletAuthHeaders("/apply/v1/operations");
|
|
1850
1922
|
|
|
1851
1923
|
try {
|
|
1852
1924
|
let result;
|
|
@@ -1906,30 +1978,30 @@ function summarizeEdgeCoherencePaths(paths) {
|
|
|
1906
1978
|
}));
|
|
1907
1979
|
}
|
|
1908
1980
|
|
|
1909
|
-
async function
|
|
1981
|
+
async function releasesCmd(args) {
|
|
1910
1982
|
const action = args[0];
|
|
1911
1983
|
if (!action || action === "--help" || action === "-h") {
|
|
1912
|
-
console.log(
|
|
1984
|
+
console.log(RELEASES_HELP);
|
|
1913
1985
|
process.exit(0);
|
|
1914
1986
|
}
|
|
1915
|
-
if (action === "get") return await
|
|
1916
|
-
if (action === "active") return await
|
|
1917
|
-
if (action === "diff") return await
|
|
1987
|
+
if (action === "get") return await releasesGetCmd(args.slice(1));
|
|
1988
|
+
if (action === "active") return await releasesActiveCmd(args.slice(1));
|
|
1989
|
+
if (action === "diff") return await releasesDiffCmd(args.slice(1));
|
|
1918
1990
|
fail({
|
|
1919
1991
|
code: "BAD_USAGE",
|
|
1920
|
-
message: `Unknown deploy
|
|
1992
|
+
message: `Unknown deploy releases subcommand: ${action}`,
|
|
1921
1993
|
details: { subcommand: action },
|
|
1922
1994
|
});
|
|
1923
1995
|
}
|
|
1924
1996
|
|
|
1925
|
-
async function
|
|
1997
|
+
async function releasesGetCmd(args) {
|
|
1926
1998
|
const parsed = parseDeploySubcommandArgs(args, {
|
|
1927
|
-
command: "deploy
|
|
1928
|
-
help:
|
|
1999
|
+
command: "deploy releases get",
|
|
2000
|
+
help: RELEASES_GET_HELP,
|
|
1929
2001
|
valueFlags: ["--project", "--site-limit"],
|
|
1930
2002
|
});
|
|
1931
2003
|
const [releaseId] = expectPositionals(parsed.positionals, {
|
|
1932
|
-
command: "run402 deploy
|
|
2004
|
+
command: "run402 deploy releases get <release_id>",
|
|
1933
2005
|
min: 1,
|
|
1934
2006
|
max: 1,
|
|
1935
2007
|
missing: "Missing <release_id>.",
|
|
@@ -1954,14 +2026,14 @@ async function releaseGetCmd(args) {
|
|
|
1954
2026
|
}
|
|
1955
2027
|
}
|
|
1956
2028
|
|
|
1957
|
-
async function
|
|
2029
|
+
async function releasesActiveCmd(args) {
|
|
1958
2030
|
const parsed = parseDeploySubcommandArgs(args, {
|
|
1959
|
-
command: "deploy
|
|
1960
|
-
help:
|
|
2031
|
+
command: "deploy releases active",
|
|
2032
|
+
help: RELEASES_ACTIVE_HELP,
|
|
1961
2033
|
valueFlags: ["--project", "--site-limit"],
|
|
1962
2034
|
});
|
|
1963
2035
|
expectPositionals(parsed.positionals, {
|
|
1964
|
-
command: "run402 deploy
|
|
2036
|
+
command: "run402 deploy releases active [--project <project_id>] [--site-limit <n>]",
|
|
1965
2037
|
max: 0,
|
|
1966
2038
|
});
|
|
1967
2039
|
const opts = {
|
|
@@ -1983,14 +2055,14 @@ async function releaseActiveCmd(args) {
|
|
|
1983
2055
|
}
|
|
1984
2056
|
}
|
|
1985
2057
|
|
|
1986
|
-
async function
|
|
2058
|
+
async function releasesDiffCmd(args) {
|
|
1987
2059
|
const parsed = parseDeploySubcommandArgs(args, {
|
|
1988
|
-
command: "deploy
|
|
1989
|
-
help:
|
|
2060
|
+
command: "deploy releases diff",
|
|
2061
|
+
help: RELEASES_DIFF_HELP,
|
|
1990
2062
|
valueFlags: ["--project", "--from", "--to", "--limit"],
|
|
1991
2063
|
});
|
|
1992
2064
|
expectPositionals(parsed.positionals, {
|
|
1993
|
-
command: "run402 deploy
|
|
2065
|
+
command: "run402 deploy releases diff --from <target> --to <target>",
|
|
1994
2066
|
max: 0,
|
|
1995
2067
|
});
|
|
1996
2068
|
const opts = {
|
|
@@ -2003,7 +2075,7 @@ async function releaseDiffCmd(args) {
|
|
|
2003
2075
|
fail({
|
|
2004
2076
|
code: "BAD_USAGE",
|
|
2005
2077
|
message: "Missing --from or --to release target.",
|
|
2006
|
-
hint: "run402 deploy
|
|
2078
|
+
hint: "run402 deploy releases diff --from empty --to active",
|
|
2007
2079
|
});
|
|
2008
2080
|
}
|
|
2009
2081
|
if (opts.to === "empty") {
|
|
@@ -2026,41 +2098,6 @@ async function releaseDiffCmd(args) {
|
|
|
2026
2098
|
}
|
|
2027
2099
|
}
|
|
2028
2100
|
|
|
2029
|
-
async function diagnoseCmd(args) {
|
|
2030
|
-
const opts = { project: null, url: null, method: "GET" };
|
|
2031
|
-
for (let i = 0; i < args.length; i++) {
|
|
2032
|
-
const arg = args[i];
|
|
2033
|
-
if (arg === "--help" || arg === "-h") { console.log(DIAGNOSE_HELP); process.exit(0); }
|
|
2034
|
-
if (arg === "--json") { continue; }
|
|
2035
|
-
if (arg === "--project" && args[i + 1]) { opts.project = args[++i]; continue; }
|
|
2036
|
-
if (arg === "--method" && args[i + 1]) { opts.method = args[++i]; continue; }
|
|
2037
|
-
if (arg?.startsWith("--project=")) { opts.project = arg.slice("--project=".length); continue; }
|
|
2038
|
-
if (arg?.startsWith("--method=")) { opts.method = arg.slice("--method=".length); continue; }
|
|
2039
|
-
if (arg?.startsWith("-")) {
|
|
2040
|
-
fail({ code: "BAD_USAGE", message: `Unknown flag for deploy diagnose: ${arg}`, details: { flag: arg } });
|
|
2041
|
-
}
|
|
2042
|
-
if (!opts.url) {
|
|
2043
|
-
opts.url = arg;
|
|
2044
|
-
continue;
|
|
2045
|
-
}
|
|
2046
|
-
fail({
|
|
2047
|
-
code: "BAD_USAGE",
|
|
2048
|
-
message: "deploy diagnose accepts exactly one URL argument.",
|
|
2049
|
-
hint: "run402 deploy diagnose --project prj_... https://example.com/path --method GET",
|
|
2050
|
-
});
|
|
2051
|
-
}
|
|
2052
|
-
if (!opts.url) {
|
|
2053
|
-
fail({
|
|
2054
|
-
code: "BAD_USAGE",
|
|
2055
|
-
message: "Missing <url>.",
|
|
2056
|
-
hint: "run402 deploy diagnose --project prj_... https://example.com/path --method GET",
|
|
2057
|
-
});
|
|
2058
|
-
}
|
|
2059
|
-
|
|
2060
|
-
const project = resolveProjectId(opts.project);
|
|
2061
|
-
await printResolveEnvelope({ project, url: opts.url, method: opts.method });
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
2101
|
async function resolveCmd(args) {
|
|
2065
2102
|
const opts = { project: null, url: null, host: null, path: null, method: "GET" };
|
|
2066
2103
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -2077,21 +2114,32 @@ async function resolveCmd(args) {
|
|
|
2077
2114
|
if (arg?.startsWith("--host=")) { opts.host = arg.slice("--host=".length); continue; }
|
|
2078
2115
|
if (arg?.startsWith("--path=")) { opts.path = arg.slice("--path=".length); continue; }
|
|
2079
2116
|
if (arg?.startsWith("--method=")) { opts.method = arg.slice("--method=".length); continue; }
|
|
2080
|
-
|
|
2117
|
+
if (arg?.startsWith("-")) {
|
|
2118
|
+
fail({ code: "BAD_USAGE", message: `Unknown flag for deploy resolve: ${arg}`, details: { flag: arg } });
|
|
2119
|
+
}
|
|
2120
|
+
if (opts.url) {
|
|
2121
|
+
fail({
|
|
2122
|
+
code: "BAD_USAGE",
|
|
2123
|
+
message: "deploy resolve accepts exactly one URL.",
|
|
2124
|
+
hint: "run402 deploy resolve https://example.com/path --project prj_... --method GET",
|
|
2125
|
+
details: { argument: arg, already_have: opts.url },
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
opts.url = arg;
|
|
2081
2129
|
}
|
|
2082
2130
|
|
|
2083
2131
|
if (opts.url && (opts.host || opts.path)) {
|
|
2084
2132
|
fail({
|
|
2085
2133
|
code: "BAD_USAGE",
|
|
2086
|
-
message: "Do not combine --url with --host or --path.",
|
|
2134
|
+
message: "Do not combine --url (or a positional URL) with --host or --path.",
|
|
2087
2135
|
details: { url: Boolean(opts.url), host: Boolean(opts.host), path: Boolean(opts.path) },
|
|
2088
2136
|
});
|
|
2089
2137
|
}
|
|
2090
2138
|
if (!opts.url && !opts.host) {
|
|
2091
2139
|
fail({
|
|
2092
2140
|
code: "BAD_USAGE",
|
|
2093
|
-
message: "Missing
|
|
2094
|
-
hint: "run402 deploy resolve
|
|
2141
|
+
message: "Missing <url>. Pass a URL, --url <url>, or --host <host> [--path /x].",
|
|
2142
|
+
hint: "run402 deploy resolve https://example.com/ --project prj_...",
|
|
2095
2143
|
});
|
|
2096
2144
|
}
|
|
2097
2145
|
|