@m-kopa/launchpad-cli 0.26.1 → 0.27.1
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/CHANGELOG.md +77 -0
- package/dist/auth/flow.d.ts +7 -3
- package/dist/auth/flow.d.ts.map +1 -1
- package/dist/auth/gateway-flow.d.ts +76 -0
- package/dist/auth/gateway-flow.d.ts.map +1 -0
- package/dist/auth/session.d.ts +35 -2
- package/dist/auth/session.d.ts.map +1 -1
- package/dist/cli.js +401 -103
- package/dist/commands/login.d.ts +10 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/logout.d.ts +7 -0
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +2 -2
- package/skills/launchpad-content-pr/SKILL.md +146 -124
- package/skills/launchpad-deploy/SKILL.md +153 -67
- package/skills/launchpad-deploy-status/SKILL.md +136 -36
- package/skills/launchpad-destroy/SKILL.md +163 -65
- package/skills/launchpad-onboard/SKILL.md +43 -14
- package/skills/launchpad-status/SKILL.md +119 -25
package/dist/commands/login.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import { login } from "../auth/flow.js";
|
|
2
|
+
import { gatewayLogin } from "../auth/gateway-flow.js";
|
|
1
3
|
import type { Command } from "../dispatcher.js";
|
|
4
|
+
/** Injectable seams so the dual-path order, fallback messaging and
|
|
5
|
+
* kill-switch are testable without a live browser or network. The
|
|
6
|
+
* production command wires the real flows. */
|
|
7
|
+
export interface LoginCommandDeps {
|
|
8
|
+
readonly gatewayLogin: typeof gatewayLogin;
|
|
9
|
+
readonly legacyLogin: typeof login;
|
|
10
|
+
}
|
|
2
11
|
export declare const loginCommand: Command;
|
|
12
|
+
export declare function makeLoginCommand(deps?: LoginCommandDeps): Command;
|
|
3
13
|
//# sourceMappingURL=login.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAmB,MAAM,kBAAkB,CAAC;AAEjE;;+CAE+C;AAC/C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,YAAY,EAAE,OAAO,YAAY,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,OAAO,KAAK,CAAC;CACpC;AAID,eAAO,MAAM,YAAY,EAAE,OAA4B,CAAC;AAExD,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,gBAA4B,GAAG,OAAO,CAM5E"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { revokeGatewaySession } from "../auth/gateway-flow.js";
|
|
1
2
|
import type { Command } from "../dispatcher.js";
|
|
3
|
+
/** Injectable seam so the server-side revoke (and its offline
|
|
4
|
+
* failure path) is testable without a live gateway. */
|
|
5
|
+
export interface LogoutCommandDeps {
|
|
6
|
+
readonly revoke: typeof revokeGatewaySession;
|
|
7
|
+
}
|
|
2
8
|
export declare const logoutCommand: Command;
|
|
9
|
+
export declare function makeLogoutCommand(deps?: LogoutCommandDeps): Command;
|
|
3
10
|
//# sourceMappingURL=logout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAmB,MAAM,kBAAkB,CAAC;AAEjE;wDACwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,OAAO,oBAAoB,CAAC;CAC9C;AAID,eAAO,MAAM,aAAa,EAAE,OAA6B,CAAC;AAE1D,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,iBAA6B,GAAG,OAAO,CAM9E"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/** Production bot URL (Cloudflare Workers `*.workers.dev` host). */
|
|
2
2
|
export declare const DEFAULT_BOT_URL = "https://launchpad-portal-bot.mkopa-launchpad.workers.dev";
|
|
3
|
+
/** Production auth gateway — the issuer of the cli-session credential
|
|
4
|
+
* (`launchpad login`'s default front-channel, ADR 0026). Endpoints
|
|
5
|
+
* are FIXED paths on this host (no discovery). Override with
|
|
6
|
+
* `LAUNCHPAD_AUTH_GATEWAY_URL` for tests / preview gateways. */
|
|
7
|
+
export declare const DEFAULT_AUTH_GATEWAY_URL = "https://auth.launchpad.m-kopa.us";
|
|
3
8
|
export interface CliConfig {
|
|
4
9
|
readonly botUrl: string;
|
|
10
|
+
/** Base URL of the auth gateway minting cli-session credentials. */
|
|
11
|
+
readonly authGatewayUrl: string;
|
|
12
|
+
/** Kill-switch: `LAUNCHPAD_AUTH_LEGACY=1` forces `launchpad login`
|
|
13
|
+
* onto the legacy Cloudflare Access flow, skipping the gateway
|
|
14
|
+
* entirely (dual-auth window escape hatch — AC-WINDOW). */
|
|
15
|
+
readonly authLegacy: boolean;
|
|
5
16
|
readonly sessionPath: string;
|
|
6
17
|
readonly cacheDir: string;
|
|
7
18
|
readonly stateDir: string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAkDA,oEAAoE;AACpE,eAAO,MAAM,eAAe,6DACgC,CAAC;AAE7D;;;iEAGiE;AACjE,eAAO,MAAM,wBAAwB,qCAAqC,CAAC;AAE3E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;gEAE4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,SAAS,CA2B1E"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "0.
|
|
1
|
+
export declare const CLI_VERSION = "0.27.1";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m-kopa/launchpad-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.1",
|
|
4
4
|
"description": "Launchpad CLI — clone / deploy / review / merge against Launchpad-managed apps. Talks to the portal-bot endpoints (SCOPE-M-760 / T4).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"homepage": "https://github.com/M-KOPA/launchpad-platform/tree/main/packages/launchpad-cli#readme",
|
|
29
29
|
"license": "UNLICENSED",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"esbuild": "0.
|
|
31
|
+
"esbuild": "0.28.1",
|
|
32
32
|
"yaml": "2.9.0",
|
|
33
33
|
"zod": "4.4.3"
|
|
34
34
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: launchpad-content-pr
|
|
3
|
-
description: Push a content change to a Launchpad app via `launchpad deploy` and verify it shipped via `launchpad status`. Covers the post-first-deploy iteration loop (edit → deploy → verify)
|
|
4
|
-
version: 0.
|
|
3
|
+
description: Push a content change to a Launchpad app via `launchpad deploy` and verify it shipped via `launchpad status`. Covers the post-first-deploy iteration loop (edit → deploy → verify) — subsequent deploys commit directly to the app repo's main and the Pages build runs asynchronously, so verification is its own step. Use when someone says "push a content change", "ship an update", "/launchpad-content-pr", "verify my deploy", or after `/launchpad-deploy` reports `done` and they want to follow up with an edit.
|
|
4
|
+
version: 0.27.1
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
<!-- BEGIN shell-contract (managed by scripts/sync-skill-contract.sh — edit skills/_partials/shell-contract.md) -->
|
|
@@ -33,17 +33,23 @@ esac
|
|
|
33
33
|
Push a content change to an already-provisioned Launchpad app, then
|
|
34
34
|
verify it shipped.
|
|
35
35
|
|
|
36
|
+
The slash-command name is historical: subsequent deploys do **not**
|
|
37
|
+
open a content PR any more. The bot commits the bundle **directly to
|
|
38
|
+
the app repo's `main`** and Cloudflare Pages builds from that commit
|
|
39
|
+
asynchronously — so "ship" and "verify" are two separate steps, and
|
|
40
|
+
this skill covers both.
|
|
41
|
+
|
|
36
42
|
Under Model A the first deploy and the first content are the same
|
|
37
43
|
event — `launchpad init` + `launchpad deploy` from the user's CWD
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
stages the working tree with the provisioning run: the workflow's
|
|
45
|
+
`content_seeded` stage commits it straight onto the app repo's
|
|
46
|
+
`main`, the bot waits for the Cloudflare Pages deployment to come up
|
|
47
|
+
green (`deployment_verified`), and the lifecycle flips to `live`.
|
|
48
|
+
There is no separate "now push content" step.
|
|
42
49
|
|
|
43
50
|
This skill is therefore the **iteration** companion to
|
|
44
51
|
`/launchpad-deploy`: once an app is live, how do you ship the next
|
|
45
|
-
change
|
|
46
|
-
pre-flight (the rules the bot enforces server-side on every bundle).
|
|
52
|
+
change — and how do you know it's actually serving.
|
|
47
53
|
|
|
48
54
|
## Pre-flight
|
|
49
55
|
|
|
@@ -65,7 +71,10 @@ Look for the slug in the `live` lifecycle bucket. If it's in
|
|
|
65
71
|
`provisioning` / `failed` / `destroying` / `destroyed`, the
|
|
66
72
|
iteration loop is not the right tool — route to
|
|
67
73
|
`/launchpad-deploy-status` (in-flight) or `/launchpad-destroy`
|
|
68
|
-
(teardown) instead.
|
|
74
|
+
(teardown) instead. If it shows `failed` but the app is actually
|
|
75
|
+
serving (e.g. a verification timed out after the real deploy
|
|
76
|
+
succeeded), `launchpad recover <slug>` reconciles the record against
|
|
77
|
+
live Cloudflare state.
|
|
69
78
|
|
|
70
79
|
## Edit and ship
|
|
71
80
|
|
|
@@ -75,92 +84,84 @@ The iteration loop is two verbs:
|
|
|
75
84
|
# 1. Edit your working tree.
|
|
76
85
|
|
|
77
86
|
# 2. Ship it.
|
|
78
|
-
launchpad deploy
|
|
87
|
+
launchpad deploy
|
|
79
88
|
```
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
What happens:
|
|
91
|
+
|
|
92
|
+
- The CLI bundles the CWD with a **pure-FS walker** (no `git`
|
|
93
|
+
needed) honouring `.gitignore` plus a default-ignore set; symlinks
|
|
94
|
+
are never followed. The bundle is gzipped and uploaded to the bot.
|
|
95
|
+
- The bot runs its server-side gates (next section), then commits
|
|
96
|
+
the bundle **directly to `main`** on `launchpad-app-<slug>` via
|
|
97
|
+
the Git Data API — you are the commit author, the bot is the
|
|
98
|
+
committer. No PR, no merge step.
|
|
99
|
+
- The CLI returns at the bot's 202 ack — `✓ Bundle accepted —
|
|
100
|
+
committed as <sha>`, then "Committed; build pending". It does
|
|
101
|
+
**not** wait for the Pages build: a successful deploy is **not** a
|
|
102
|
+
live app yet — the build runs asynchronously and can fail after
|
|
103
|
+
the commit lands. Always confirm with `launchpad status`.
|
|
104
|
+
|
|
105
|
+
Flags worth knowing:
|
|
106
|
+
|
|
107
|
+
- The slug comes from `./launchpad.yaml` (`metadata.slug` /
|
|
108
|
+
`metadata.name`). On this path `--slug` does **not** override it —
|
|
109
|
+
it only overrides directory-name inference on the legacy clone
|
|
110
|
+
flow (no local manifest).
|
|
111
|
+
- **`--message`** is sent as a forward-compat header on the legacy
|
|
112
|
+
path only, and **the bot currently ignores it**. Don't rely on it
|
|
113
|
+
for change logs or audit trails.
|
|
114
|
+
- **`--file`** is valid only with `--dry-run` / `--apply`
|
|
115
|
+
(manifest-driven modes), not with a content deploy.
|
|
97
116
|
|
|
98
117
|
Exit codes:
|
|
99
118
|
|
|
100
|
-
- **0** —
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
pm2
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
The bot's secret-scan + build-command policy rejects bundles where
|
|
148
|
-
the source tree contains:
|
|
149
|
-
|
|
150
|
-
- `process.env.X` / `process.env['X']` reads — switch to `c.env.*`
|
|
151
|
-
bindings.
|
|
152
|
-
- `setInterval` / `setTimeout` daemons — Workers do not run between
|
|
153
|
-
requests; use Cron Triggers for periodic work.
|
|
154
|
-
- High-signal secret patterns (AWS access keys, GitHub PATs / OAuth
|
|
155
|
-
/ app tokens, Slack tokens, SSH/RSA/EC/PGP keys, generic
|
|
156
|
-
`api_key` shapes). These never belong in a bundle — push them
|
|
157
|
-
through `launchpad secrets push` instead.
|
|
158
|
-
|
|
159
|
-
### `react+api` requires `nodejs_compat`
|
|
160
|
-
|
|
161
|
-
The bot checks that `wrangler.toml` declares
|
|
162
|
-
`compatibility_flags = ["nodejs_compat"]` for any `react+api` app
|
|
163
|
-
(ADR-0011 carve-out).
|
|
119
|
+
- **0** — bundle accepted and committed (or "nothing to deploy"
|
|
120
|
+
when `main` already matches the bundle). This is **not** proof the
|
|
121
|
+
app is live — verify with `launchpad status`.
|
|
122
|
+
- **non-zero** — gate rejections are rendered with per-file detail
|
|
123
|
+
on stderr; fix the bundle and re-run. For provisioning-phase
|
|
124
|
+
failures see `/launchpad-deploy-status <slug>`.
|
|
125
|
+
|
|
126
|
+
## What the bot enforces on every bundle
|
|
127
|
+
|
|
128
|
+
The canonical gate list and caps live in `/launchpad-deploy
|
|
129
|
+
§ Constants (single source of truth)`. In user-visible terms, every
|
|
130
|
+
upload passes:
|
|
131
|
+
|
|
132
|
+
- **Bundle policy** — file-count / bundle-size / per-file-size caps,
|
|
133
|
+
symlink and path-traversal/absolute-path rejection, and auth-file
|
|
134
|
+
rules (`.github/workflows`, CODEOWNERS, `.npmrc`/`.yarnrc`
|
|
135
|
+
carrying auth tokens, `.git/`).
|
|
136
|
+
- **Secret scan** — high-signal secret patterns (AWS access keys,
|
|
137
|
+
GitHub PATs / OAuth / app tokens, Slack tokens, SSH/RSA/EC/PGP
|
|
138
|
+
private keys, generic `api_key` shapes). These never belong in a
|
|
139
|
+
bundle — push them through `launchpad secrets push` instead.
|
|
140
|
+
- **Build-command allowlist** — `build.command` must match the
|
|
141
|
+
bot's allowlist.
|
|
142
|
+
- **App boundary (CLI-side, before upload)** — files outside
|
|
143
|
+
`app.root` / `app.include` are stripped with a warning, and
|
|
144
|
+
key/cert-shaped files (`*.pem`, `*.key`, `id_rsa*`, `*.p12`) are
|
|
145
|
+
denied client-side.
|
|
146
|
+
|
|
147
|
+
Gates are **delta-judged** (ADR 0025): they evaluate what your
|
|
148
|
+
deploy *changes* relative to `main`, not everything the workspace
|
|
149
|
+
contains. A pre-existing violation already live on `main` becomes a
|
|
150
|
+
non-blocking **standing exception** — recorded by the bot and
|
|
151
|
+
surfaced by both `launchpad deploy` and `launchpad status` (the bot
|
|
152
|
+
serves the inventory at `GET /apps/<slug>/exceptions`). So "my old
|
|
153
|
+
violation didn't block this deploy" is by design, not a missed gate.
|
|
154
|
+
|
|
155
|
+
There is **no** server-side scan of `package.json` dependencies,
|
|
156
|
+
top-level files, or source patterns. Express/Koa-style servers,
|
|
157
|
+
native DB drivers (`pg`, `better-sqlite3`, …), `dotenv`, and
|
|
158
|
+
pm2/Docker artefacts are not rejected at deploy time — they simply
|
|
159
|
+
won't run on the Cloudflare Pages + Workers runtime and fail at
|
|
160
|
+
build or runtime instead. Likewise `react+api`'s
|
|
161
|
+
`compatibility_flags = ["nodejs_compat"]` in `wrangler.toml`
|
|
162
|
+
(ADR-0011) is **required but not validated** — a missing flag fails
|
|
163
|
+
at runtime. Treat the stack-constraints table in `/launchpad-deploy`
|
|
164
|
+
as advisory architecture guidance, not an enforced gate.
|
|
164
165
|
|
|
165
166
|
### Verifying locally before you ship
|
|
166
167
|
|
|
@@ -172,34 +173,47 @@ launchpad validate
|
|
|
172
173
|
launchpad plan
|
|
173
174
|
```
|
|
174
175
|
|
|
175
|
-
|
|
176
|
-
|
|
176
|
+
Both are offline by default (no bot). `launchpad validate
|
|
177
|
+
--strict-groups` opts in to an online check that resolves
|
|
178
|
+
`access.allowed_entra_group` (needs a session).
|
|
177
179
|
|
|
178
|
-
## Verify
|
|
180
|
+
## Verify the deploy
|
|
179
181
|
|
|
180
182
|
```bash
|
|
181
183
|
launchpad status <slug>
|
|
182
184
|
```
|
|
183
185
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
-
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
`launchpad status` reports manifest drift **and** the live
|
|
187
|
+
Cloudflare Pages build truth — last deployment, what triggered it,
|
|
188
|
+
build outcome, and a failure-log excerpt when the build broke. (See
|
|
189
|
+
`/launchpad-status` for the full state list.) What you're looking
|
|
190
|
+
for after a deploy:
|
|
191
|
+
|
|
192
|
+
- **`live, in sync`** with `last deployment: build success` — your
|
|
193
|
+
commit landed and the build is serving. You're done.
|
|
194
|
+
- **`last deployment: build FAILED at stage "<stage>"`** (+ log
|
|
195
|
+
excerpt) — the commit landed but the build broke; the previous
|
|
196
|
+
successful deployment is still serving. Fix the cause and re-run
|
|
197
|
+
`launchpad deploy`.
|
|
198
|
+
- **`build IN PROGRESS`** — re-run `launchpad status` shortly to
|
|
199
|
+
confirm the outcome.
|
|
200
|
+
- **`drift: <fields>`** — your local manifest diverges from what's
|
|
190
201
|
deployed. Either re-run `launchpad deploy` to ship the local, or
|
|
191
202
|
`launchpad pull <slug> --out launchpad.yaml` to bring the local
|
|
192
203
|
into line with deployed.
|
|
193
|
-
-
|
|
194
|
-
|
|
195
|
-
|
|
204
|
+
- **provisioning / failed / destroy states** — route to
|
|
205
|
+
`/launchpad-deploy-status` or `/launchpad-destroy`.
|
|
206
|
+
|
|
207
|
+
Do not declare a change shipped until `status` shows the build
|
|
208
|
+
outcome for your commit.
|
|
196
209
|
|
|
197
210
|
You can also point a browser at `https://<slug>.launchpad.m-kopa.us`
|
|
198
|
-
once status reports
|
|
199
|
-
for a gateway-fronted app (the default, `auth: gateway`)
|
|
200
|
-
redirect to the Entra-OIDC gateway (Microsoft sign-in) on
|
|
201
|
-
request; for an `auth: access` app expect a redirect to
|
|
202
|
-
`*.cloudflareaccess.com`. Either way you land on your app after
|
|
211
|
+
once status reports the build green. An SSO gate sits in front of
|
|
212
|
+
the app: for a gateway-fronted app (the default, `auth: gateway`)
|
|
213
|
+
expect a redirect to the Entra-OIDC gateway (Microsoft sign-in) on
|
|
214
|
+
the first request; for an `auth: access` app expect a redirect to
|
|
215
|
+
`*.cloudflareaccess.com`. Either way you land on your app after
|
|
216
|
+
sign-in.
|
|
203
217
|
|
|
204
218
|
If the URL serves the wrong thing:
|
|
205
219
|
|
|
@@ -218,16 +232,23 @@ If the URL serves the wrong thing:
|
|
|
218
232
|
Once you've shipped first content, the daily-use verbs are:
|
|
219
233
|
|
|
220
234
|
- **`launchpad status`** (`/launchpad-status`) — is my local
|
|
221
|
-
`launchpad.yaml` in sync with what's deployed
|
|
235
|
+
`launchpad.yaml` in sync with what's deployed, and did the last
|
|
236
|
+
build succeed?
|
|
222
237
|
- **`launchpad pull <slug>`** (`/launchpad-status`) — read the
|
|
223
238
|
currently-deployed `launchpad.yaml`.
|
|
224
|
-
- **`launchpad deploy`** —
|
|
225
|
-
|
|
239
|
+
- **`launchpad deploy`** — bundle the working tree; the bot commits
|
|
240
|
+
it directly to the app repo's `main`.
|
|
226
241
|
- **`launchpad envvars`** — list / set / remove non-secret
|
|
227
242
|
production env vars.
|
|
228
|
-
- **`launchpad secrets
|
|
229
|
-
|
|
230
|
-
|
|
243
|
+
- **`launchpad secrets template`** — emit `.env.example` from the
|
|
244
|
+
manifest's secret bindings.
|
|
245
|
+
- **`launchpad secrets push`** — push secret values from `.env`
|
|
246
|
+
(never via git).
|
|
247
|
+
- **`launchpad secrets status`** — names-only PRESENT/MISSING audit
|
|
248
|
+
per binding.
|
|
249
|
+
- **`launchpad logs --slug <slug>`** — recent Cloudflare Pages
|
|
250
|
+
deployment history (default 10 entries, max 25 via `--lines`).
|
|
251
|
+
Note: the slug is flag-only, not positional.
|
|
231
252
|
- **`launchpad rollback`** — revert manifest to a prior git SHA +
|
|
232
253
|
re-apply.
|
|
233
254
|
|
|
@@ -237,17 +258,18 @@ Once you've shipped first content, the daily-use verbs are:
|
|
|
237
258
|
skill. Every step is a `launchpad` verb. External users without
|
|
238
259
|
M-KOPA GitHub access need this skill to work end-to-end on the
|
|
239
260
|
CLI alone.
|
|
240
|
-
- Do **not** open
|
|
241
|
-
bot
|
|
242
|
-
bypasses the bundle
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
- Do **not**
|
|
249
|
-
|
|
250
|
-
|
|
261
|
+
- Do **not** push commits or open PRs by hand against the app repo.
|
|
262
|
+
The bot commits through a ruleset bypass it alone holds, and a
|
|
263
|
+
hand-rolled change bypasses the bundle policy, secret-scan,
|
|
264
|
+
build-command gates, and the standing-exception ledger. Use
|
|
265
|
+
`launchpad deploy`.
|
|
266
|
+
- Do **not** treat exit 0 from `launchpad deploy` as "live". The
|
|
267
|
+
commit landed, but the Pages build runs asynchronously and can
|
|
268
|
+
fail afterwards — always verify with `launchpad status`.
|
|
269
|
+
- Do **not** re-implement the server-side gates locally.
|
|
270
|
+
`launchpad validate` plus the CLI's own app-boundary pre-flight
|
|
271
|
+
cover the local half; the bot enforces the rest server-side and
|
|
272
|
+
renders violations verbatim — surface them and let the user fix
|
|
251
273
|
the bundle.
|
|
252
274
|
- Do **not** edit `launchpad.yaml`'s `production_env:` block to
|
|
253
275
|
contain secret values. That block is non-secret by contract;
|