@aotter/mantle 0.0.11-alpha.32 → 0.0.11-alpha.34
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
CHANGED
|
@@ -32,12 +32,13 @@ import { mountServerEndpoints } from "@aotter/mantle/cloudflare";
|
|
|
32
32
|
## Getting started
|
|
33
33
|
|
|
34
34
|
Recommended path: open the Mantle landing page, answer the launch
|
|
35
|
-
questions, sign in with GitHub
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
questions, and sign in with GitHub and Cloudflare. Landing provisions the
|
|
36
|
+
site server-side — it creates the private GitHub repo, commits a blank
|
|
37
|
+
deployable Mantle site, and connects the first Cloudflare deploy. Then
|
|
38
|
+
point your coding agent (Claude Code / Cursor / Codex) at the provisioned
|
|
39
|
+
repo to continue.
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
Starter source and provision bundles live in [`aotter/mantle-starters`](https://github.com/aotter/mantle-starters); launch starts from the blank base and the agent applies the selected type as a post-launch overlay. See `skills/install` in the [Mantle repo](https://github.com/aotter/mantle/tree/develop/skills/install) for how the agent continues a provisioned repo.
|
|
41
42
|
|
|
42
43
|
## Adapter targets
|
|
43
44
|
|
|
@@ -47,9 +47,9 @@ encode step to where it already runs in a real Node-like runtime:
|
|
|
47
47
|
- Scaffolders, ops scripts, the admin SPA's local helper, and MCP
|
|
48
48
|
agents (Claude Code, etc.) all execute in environments where
|
|
49
49
|
`sharp` works.
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
- The MCP client or operator tooling runs the agent-side image
|
|
51
|
+
processor: take a source file, produce the format set, call
|
|
52
|
+
`create_media_upload`, upload every variant, and call
|
|
53
53
|
`commit_media_upload`.
|
|
54
54
|
- The Worker only **enforces policy**: required mime set, per-mime
|
|
55
55
|
byte caps, suspicious-shape heuristic (modern format must not be
|
|
@@ -178,4 +178,4 @@ use case layer via the repository. The R2 adapter:
|
|
|
178
178
|
- `packages/mantle-runtime/src/infrastructure/persistence/DatabaseMediaAssetRepository.ts`
|
|
179
179
|
- `packages/mantle-spec/src/domain/model/SiteConfig.ts` (MediaPurposePolicy)
|
|
180
180
|
- `packages/adapters/cloudflare/src/bindings/R2MediaStorage.ts`
|
|
181
|
-
-
|
|
181
|
+
- MCP client / operator-side image processing tools
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aotter/mantle",
|
|
3
|
-
"version": "0.0.11-alpha.
|
|
3
|
+
"version": "0.0.11-alpha.34",
|
|
4
4
|
"description": "Umbrella entry for @aotter/mantle. Adopters install this one package and import from subpaths: /spec, /runtime, /cloudflare, /admin-ui. Sub-packages remain individually installable on npm for tooling / alt-adapter authors. The Netlify adapter ships as a private workspace stub in v0.1 — its subpath will be added when the impl lands in v0.2.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://mantle.tools/",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"README.md"
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@aotter/mantle-
|
|
51
|
-
"@aotter/mantle-
|
|
52
|
-
"@aotter/mantle-
|
|
53
|
-
"@aotter/mantle-
|
|
50
|
+
"@aotter/mantle-cloudflare": "0.0.11-alpha.34",
|
|
51
|
+
"@aotter/mantle-admin-ui": "0.0.11-alpha.34",
|
|
52
|
+
"@aotter/mantle-runtime": "0.0.11-alpha.34",
|
|
53
|
+
"@aotter/mantle-spec": "0.0.11-alpha.34"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"@cloudflare/workers-oauth-provider": "^0.7.0",
|
package/skills/README.md
CHANGED
|
@@ -4,10 +4,10 @@ Agent-readable skill briefs for consumers of `@aotter/mantle-*`. Discoverable by
|
|
|
4
4
|
|
|
5
5
|
| Skill | When to invoke |
|
|
6
6
|
|---|---|
|
|
7
|
-
| [`install`](install/SKILL.md) | User wants to start a
|
|
7
|
+
| [`install`](install/SKILL.md) | User wants to start or continue a Mantle site. Sites launch on [Mantle landing](https://mantle.tools), which provisions the GitHub repo and first Cloudflare deploy; this brief orients the agent to take over and continue the provisioned repo. |
|
|
8
8
|
| [`customize-design`](customize-design/SKILL.md) | User wants to rebrand or restyle a publication starter project. Walks the L1–L4 theme stack (tokens / extraCss+icons+i18n / Header+Footer / whole-template). |
|
|
9
9
|
| [`extend`](extend/SKILL.md) | User has an existing project and wants to add a Schema / View / Procedure / Trigger or wire a feature (contact form, search, newsletter signup). |
|
|
10
|
-
| [`provision`](provision/SKILL.md) | User wants
|
|
10
|
+
| [`provision`](provision/SKILL.md) | User wants production fully usable after a landing launch. Verify the Cloudflare deploy, wire per-site staff auth (GitHub OAuth App + Worker secrets), smoke test, and hand off the operator setup URL. |
|
|
11
11
|
|
|
12
12
|
The skills target `mantle@v0.1.0`. Each one names its assumed grammar version in the front-matter `applies_to:` field; future versions add a sibling SKILL.md or update the existing one.
|
|
13
13
|
|
package/skills/install/SKILL.md
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mantle install
|
|
3
|
-
description:
|
|
3
|
+
description: Orient and continue a Mantle site that Mantle landing has provisioned. Mantle sites launch on Mantle landing (mantle.tools), which creates the GitHub repo and the first Cloudflare deploy; the agent takes over the provisioned repo to complete the selected type, first pages, and content. Use when the user pasted a Mantle launch / after-launch context, opened a landing-provisioned repo, or wants to start a new Mantle site.
|
|
4
4
|
when_to_invoke: |
|
|
5
|
-
The user
|
|
5
|
+
The user wants a new Mantle site, pasted a Mantle landing launch / after-launch context, or opened a repo that Mantle landing provisioned and wants help continuing it.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# mantle install
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Mantle sites are launched on **Mantle landing** (`https://mantle.tools`),
|
|
11
|
+
not scaffolded locally. Landing asks the launch questions, then provisions
|
|
12
|
+
server-side: it creates the user's private GitHub repo, commits a blank
|
|
13
|
+
deployable Mantle site, and connects Cloudflare Workers CI for the first
|
|
14
|
+
deploy. Your job is to **continue that provisioned repo** — complete the
|
|
15
|
+
selected type, first pages, and content — not to scaffold from scratch.
|
|
11
16
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
4. You validate the generated repo, push it to the user's GitHub, then
|
|
18
|
-
continue with repo-local `mantle:provision`.
|
|
19
|
-
|
|
20
|
-
Do not rebuild the old interview harness in chat. If the user has no
|
|
21
|
-
landing-created launch command/session, send them back to Mantle landing
|
|
22
|
-
to create one. Manual flag-by-flag scaffolding is for maintainers
|
|
23
|
-
debugging the scaffolder, not the user-facing install UX.
|
|
17
|
+
There is no local scaffolder to run. The `create-mantle` CLI was retired
|
|
18
|
+
when provisioning moved into landing. If the user has not launched yet,
|
|
19
|
+
send them to `https://mantle.tools` to launch, then resume here once the
|
|
20
|
+
repo exists. Do not rebuild the old manual interview / prompt-composition
|
|
21
|
+
harness.
|
|
24
22
|
|
|
25
23
|
## Ground Truth
|
|
26
24
|
|
|
@@ -39,125 +37,62 @@ consumer project from these four atoms plus user TypeScript. Full grammar
|
|
|
39
37
|
reference:
|
|
40
38
|
<https://raw.githubusercontent.com/aotter/mantle/develop/docs/design-atoms.md>.
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
A landing-provisioned repo carries its launch context and ground truth in:
|
|
43
41
|
|
|
44
42
|
| Path | Contents |
|
|
45
43
|
|---|---|
|
|
44
|
+
| `.mantle/launch-state.json` | Non-secret launch choices: type, purpose, locales, repo, owner, suggested overlay |
|
|
45
|
+
| `.mantle/features.json` | Selected feature overlays and applied state |
|
|
46
|
+
| `.mantle/handoff.md` | The launch handoff note written for you |
|
|
46
47
|
| `manifests/*.yaml` | Schemas / Views / Procedures / Triggers |
|
|
47
48
|
| `src/mantleConfig.ts` | Site defaults, handler registration, runtime bindings |
|
|
48
49
|
| `src/handlers/` | Handler implementations |
|
|
49
|
-
| `src/.mantle/generated.*.ts` | Scaffolder-owned feature glue |
|
|
50
|
-
| `.mantle/features.json` | Selected feature overlays |
|
|
51
|
-
| `.mantle/launch-state.json` | Non-secret launch choices from landing |
|
|
52
50
|
| `AGENTS.md` | Cross-tool agent entry |
|
|
51
|
+
| `.agent/skills/` + `.claude/skills/` | Repo-local skills: `mantle:develop`, `mantle:overlay`, `mantle:theme`, `mantle:update` |
|
|
53
52
|
|
|
54
|
-
##
|
|
55
|
-
|
|
56
|
-
Use the launch-session fast path when the prompt contains either:
|
|
57
|
-
|
|
58
|
-
- a command shaped like `npx <tarball> launch --session <url-or-file>`;
|
|
59
|
-
- a command shaped like `npx <tarball> <archetype> ...` generated by
|
|
60
|
-
Mantle landing;
|
|
61
|
-
- a launch session URL/file plus instructions to run `create-mantle
|
|
62
|
-
launch`.
|
|
63
|
-
|
|
64
|
-
Landing already collected the launch-critical values. Treat those values
|
|
65
|
-
as user-authorized for scaffolding. Do not ask content, voice, repo, or
|
|
66
|
-
locale questions again before scaffold.
|
|
67
|
-
|
|
68
|
-
The launch session/command authorizes only initial scaffold values:
|
|
69
|
-
|
|
70
|
-
- project name;
|
|
71
|
-
- brand / site name;
|
|
72
|
-
- archetype;
|
|
73
|
-
- theme and selected feature overlays;
|
|
74
|
-
- locales and canonical locale;
|
|
75
|
-
- GitHub owner / admin login;
|
|
76
|
-
- install description and summary.
|
|
77
|
-
|
|
78
|
-
It does not authorize Cloudflare resources, provider billing, OAuth
|
|
79
|
-
secrets, custom domains, or production deploy.
|
|
80
|
-
|
|
81
|
-
## Preflight
|
|
82
|
-
|
|
83
|
-
Run these before creating files:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
node --version # need >= 22
|
|
87
|
-
pnpm --version # need >= 9
|
|
88
|
-
git --version
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Confirm the current working directory is the parent directory where the
|
|
92
|
-
new project should appear. If the child project directory already exists,
|
|
93
|
-
stop and ask the user whether to choose another empty directory. Do not
|
|
94
|
-
merge a fresh scaffold into an existing project.
|
|
95
|
-
|
|
96
|
-
## Scaffold
|
|
97
|
-
|
|
98
|
-
Run the launch command exactly as supplied. Do not rewrite values. Only
|
|
99
|
-
replace an obvious local file path if the user gave the file out of band.
|
|
53
|
+
## Take Over a Provisioned Repo
|
|
100
54
|
|
|
101
|
-
|
|
55
|
+
The repo was already created and deployed by landing. Continue it:
|
|
102
56
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
--brand "<brand>" \
|
|
111
|
-
--description "<description>" \
|
|
112
|
-
--locales "<locale[,locale]>" \
|
|
113
|
-
--github-owner <github-owner> \
|
|
114
|
-
--admin-github-login <admin-login> \
|
|
115
|
-
--summary "<summary>"
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
`create-mantle` validates the session before filesystem writes,
|
|
119
|
-
downloads the requested starter ref, merges `_common/` + `<archetype>/`
|
|
120
|
-
+ feature overlays + theme overlays, fills placeholders, runs
|
|
121
|
-
`git init`, runs `pnpm install`, writes `.mantle/launch-state.json`, and
|
|
122
|
-
prints RUN_NOTES JSON.
|
|
123
|
-
|
|
124
|
-
After it returns:
|
|
125
|
-
|
|
126
|
-
1. Read RUN_NOTES.
|
|
127
|
-
2. Read `.mantle/launch-state.json`.
|
|
128
|
-
3. Walk the ground-truth files above.
|
|
129
|
-
4. Continue with local validation.
|
|
130
|
-
|
|
131
|
-
## Local Validation
|
|
132
|
-
|
|
133
|
-
From the generated project root:
|
|
57
|
+
1. Confirm repository access through an available GitHub connector or MCP
|
|
58
|
+
tool. Use GitHub CLI only if it is already authenticated.
|
|
59
|
+
2. Clone or open the repo, then read `.mantle/launch-state.json`,
|
|
60
|
+
`.mantle/features.json`, and `.mantle/handoff.md`.
|
|
61
|
+
3. Inspect the four-atoms manifest, the type overlay notes, pages, and
|
|
62
|
+
seed data before changing code.
|
|
63
|
+
4. Validate locally before editing:
|
|
134
64
|
|
|
135
65
|
```bash
|
|
66
|
+
pnpm install --frozen-lockfile
|
|
136
67
|
pnpm validate
|
|
137
68
|
pnpm typecheck
|
|
138
|
-
if node -e "process.exit(require('./package.json').scripts?.test ? 0 : 1)"; then
|
|
139
|
-
pnpm test
|
|
140
|
-
else
|
|
141
|
-
echo "No pnpm test script; skipping."
|
|
142
|
-
fi
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Run deploy validation if the starter exposes it:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
if node -e "process.exit(require('./package.json').scripts?.['validate:deploy'] ? 0 : 1)"; then
|
|
149
|
-
pnpm validate:deploy
|
|
150
|
-
else
|
|
151
|
-
pnpm validate --phase deploy
|
|
152
|
-
fi
|
|
153
69
|
```
|
|
154
70
|
|
|
155
71
|
Diagnostics are structured JSON with `code` and `suggestion` fields.
|
|
156
72
|
Surface both verbatim when validation fails.
|
|
157
73
|
|
|
74
|
+
## Continue With Repo-Local Skills
|
|
75
|
+
|
|
76
|
+
The generated repo ships its own skills under `.agent/skills/` and
|
|
77
|
+
`.claude/skills/`. Hand off to the one that fits the work:
|
|
78
|
+
|
|
79
|
+
- **`mantle:overlay`** — apply the selected launch type as a small
|
|
80
|
+
post-launch overlay (first useful pages plus tiny seed data in the
|
|
81
|
+
user's language). This is the usual first step on a fresh blank launch.
|
|
82
|
+
- **`mantle:develop`** — manifest, runtime, content-model, layout,
|
|
83
|
+
bug-fix, and validation work on the site.
|
|
84
|
+
- **`mantle:theme`** — brand and visual direction via Mantle / Kiwa tokens
|
|
85
|
+
and source. There is no premade theme picker; visual direction is agent
|
|
86
|
+
work after launch.
|
|
87
|
+
- **`mantle:update`** — compare the repo against its upstream provision
|
|
88
|
+
bundle.
|
|
89
|
+
|
|
90
|
+
Remove the placeholder blank homepage once the selected type ships a real
|
|
91
|
+
homepage.
|
|
92
|
+
|
|
158
93
|
## Local Preview
|
|
159
94
|
|
|
160
|
-
|
|
95
|
+
To see the site locally before pushing:
|
|
161
96
|
|
|
162
97
|
```bash
|
|
163
98
|
[ -f .dev.vars.example ] && cp .dev.vars.example .dev.vars
|
|
@@ -165,64 +100,28 @@ openssl rand -hex 32
|
|
|
165
100
|
pnpm dev
|
|
166
101
|
```
|
|
167
102
|
|
|
168
|
-
Paste the generated random value into `.dev.vars` as
|
|
169
|
-
|
|
170
|
-
|
|
103
|
+
Paste the generated random value into `.dev.vars` as `BETTER_AUTH_SECRET`.
|
|
104
|
+
This secret is local only and must not be reused for production. Use
|
|
105
|
+
`localhost`, not `127.0.0.1`, in local examples. A fresh blank site may
|
|
106
|
+
return 404 on the public home route until the type overlay adds one; treat
|
|
107
|
+
that as an empty-site state, not a failure, when validation and admin
|
|
108
|
+
routes are alive.
|
|
171
109
|
|
|
172
|
-
|
|
173
|
-
because production content is not seeded yet. Treat that as an empty-site
|
|
174
|
-
state, not a failed install, when validation and admin routes are alive.
|
|
110
|
+
## Production
|
|
175
111
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
```bash
|
|
181
|
-
git status --short
|
|
182
|
-
git add .
|
|
183
|
-
git commit -m "mantle: deterministic scaffold"
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
Then continue in the same conversation with the repo-local provision
|
|
112
|
+
Landing already created the GitHub repo and the first Cloudflare deploy.
|
|
113
|
+
To finish production — verify the deploy, wire per-site staff auth, smoke
|
|
114
|
+
test, and hand off the operator setup URL — continue with the provision
|
|
187
115
|
skill:
|
|
188
|
-
|
|
189
|
-
```text
|
|
190
|
-
.agent/skills/mantle-provision/SKILL.md
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
The current provision shape is provider-first:
|
|
194
|
-
|
|
195
|
-
1. The agent creates/pushes the user's private GitHub repo.
|
|
196
|
-
2. The user creates the first Cloudflare Worker deploy from that GitHub
|
|
197
|
-
repo in Cloudflare Dashboard.
|
|
198
|
-
3. The user reports the Worker URL.
|
|
199
|
-
4. The user creates the per-site GitHub OAuth App.
|
|
200
|
-
5. The agent runs `pnpm run provision:up` to write non-secret config,
|
|
201
|
-
set Worker secrets with Wrangler, commit, push, redeploy, and smoke
|
|
202
|
-
test.
|
|
203
|
-
|
|
204
|
-
Do not stop at "here is a URL". Walk the provider steps with the user
|
|
205
|
-
until the deployed Worker, GitHub owner sign-in, and Staff MCP endpoint
|
|
206
|
-
are verified.
|
|
207
|
-
|
|
208
|
-
## Small Adjustments
|
|
209
|
-
|
|
210
|
-
Before provision, only make small deterministic edits that come directly
|
|
211
|
-
from the landing answers or the user's explicit request:
|
|
212
|
-
|
|
213
|
-
- delete an unused manifest;
|
|
214
|
-
- add one clearly requested field to an existing Schema;
|
|
215
|
-
- correct site defaults in `src/mantleConfig.ts`;
|
|
216
|
-
- fix a typo in `AGENTS.md`.
|
|
217
|
-
|
|
218
|
-
Run `pnpm validate` after every edit. Route larger feature work to
|
|
219
|
-
`mantle:development` after production provision.
|
|
116
|
+
<https://raw.githubusercontent.com/aotter/mantle/develop/skills/provision/SKILL.md>.
|
|
220
117
|
|
|
221
118
|
## Don't
|
|
222
119
|
|
|
223
|
-
- Don't
|
|
224
|
-
- Don't
|
|
225
|
-
- Don't
|
|
120
|
+
- Don't run or look for `create-mantle`; it was retired with provisioning v2.
|
|
121
|
+
- Don't rebuild the manual interview / prompt-composition harness.
|
|
122
|
+
- Don't scaffold a project from scratch locally; launch happens on landing.
|
|
123
|
+
- Don't block the first useful page on polishing prose or writing a site letter.
|
|
124
|
+
- Don't ask for a Cloudflare API token in the base flow.
|
|
226
125
|
- Don't commit provider secrets.
|
|
227
|
-
- Don't use `127.0.0.1` in OAuth callback examples; use `localhost`
|
|
228
|
-
|
|
126
|
+
- Don't use `127.0.0.1` in OAuth callback examples; use `localhost` locally
|
|
127
|
+
and the real Worker URL in production.
|
|
@@ -1,174 +1,128 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mantle provision
|
|
3
|
-
description: Finish production
|
|
3
|
+
description: Finish production for a Mantle site after Mantle landing has provisioned it. Landing already created the private GitHub repo and the first Cloudflare Worker deploy; this skill covers verifying that deploy, wiring per-site staff auth (GitHub OAuth App + Worker secrets), smoke testing, and handing off the operator setup URL.
|
|
4
4
|
when_to_invoke: |
|
|
5
|
-
|
|
5
|
+
Mantle landing has created the repo and the first Cloudflare deploy, the user wants production fully usable, and staff sign-in / MCP still needs wiring.
|
|
6
6
|
applies_to: mantle@v0.1.0
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Provision a Mantle Project
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
user
|
|
11
|
+
Provisioning is landing-driven. **Mantle landing is the executor for the
|
|
12
|
+
first deploy**: it creates the user's private GitHub repo, commits the
|
|
13
|
+
blank deployable site, connects Cloudflare Workers CI, and triggers the
|
|
14
|
+
first build. You pick up after that to make production fully usable.
|
|
13
15
|
|
|
14
|
-
The
|
|
16
|
+
The Worker boots before staff auth is configured — it serves public routes
|
|
17
|
+
and returns a clean `503 setup_incomplete` on auth-gated routes until the
|
|
18
|
+
GitHub OAuth App and Worker secrets are set. Your remaining job is to
|
|
19
|
+
finish that wiring, verify, and hand off.
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
resource provisioning for id-less bindings.
|
|
21
|
-
3. The user reports the deployed Worker URL back to the agent.
|
|
22
|
-
4. The user creates the per-site GitHub OAuth App.
|
|
23
|
-
5. The agent runs `pnpm run provision:up` to write non-secret config,
|
|
24
|
-
set Worker secrets through Wrangler, and update local handoff files.
|
|
25
|
-
|
|
26
|
-
Mantle landing is not the executor. It provides launch context and a
|
|
27
|
-
handoff; provider authority stays with the user and their coding agent.
|
|
28
|
-
|
|
29
|
-
Do deterministic work before interrupting the user. When provider UI is
|
|
30
|
-
required, give one exact browser task at a time: link, button path,
|
|
31
|
-
expected result, and what value the user should report back.
|
|
21
|
+
Keep provisioning boring: set the few secrets, commit non-secret config,
|
|
22
|
+
let Cloudflare CI redeploy. Do not re-create the repo, re-run the first
|
|
23
|
+
deploy, or resurrect a heavy `provision:up` orchestrator — both retired
|
|
24
|
+
with v2.
|
|
32
25
|
|
|
33
26
|
## End State
|
|
34
27
|
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
- `wrangler.toml`
|
|
28
|
+
- Cloudflare has deployed the Worker from the repo (landing's first build,
|
|
29
|
+
plus your redeploy after config).
|
|
30
|
+
- `wrangler.toml` carries `PUBLIC_ORIGIN`, `GITHUB_CLIENT_ID`,
|
|
38
31
|
`ADMIN_GITHUB_LOGIN`, and the correct Worker name.
|
|
39
|
-
- Worker secrets are set: `GITHUB_CLIENT_SECRET`,
|
|
40
|
-
|
|
32
|
+
- Worker secrets are set: `GITHUB_CLIENT_SECRET`, `BETTER_AUTH_SECRET`,
|
|
33
|
+
and any optional feature/provider secrets.
|
|
41
34
|
- `AGENTS.md` `Public site:` points at the deployed Worker URL.
|
|
42
|
-
- Staff MCP and browser admin sign-in
|
|
43
|
-
- Operator setup URL
|
|
35
|
+
- Staff MCP and browser admin sign-in work.
|
|
36
|
+
- Operator setup URL handed to the owner:
|
|
44
37
|
`https://mantle.tools/connect?site=<url-encoded-worker-url>`.
|
|
45
38
|
|
|
46
|
-
Provision does not seed production content. First real content is
|
|
47
|
-
|
|
39
|
+
Provision does not seed production content. First real content is created
|
|
40
|
+
after owner sign-in through Staff MCP / admin authoring.
|
|
48
41
|
|
|
49
42
|
## Principles
|
|
50
43
|
|
|
51
|
-
1. Use the user's accounts. The repo
|
|
52
|
-
|
|
53
|
-
2.
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
1. Use the user's accounts. The repo and Worker belong to the user's
|
|
45
|
+
GitHub and Cloudflare accounts.
|
|
46
|
+
2. No Cloudflare API token in the base flow. Prefer a Cloudflare MCP
|
|
47
|
+
connector for provider work; use `wrangler login` as a fallback after
|
|
48
|
+
the user agrees.
|
|
56
49
|
3. GitHub OAuth is per-site and user-owned. The callback URL is exactly
|
|
57
50
|
`<worker-url>/api/auth/callback/github`.
|
|
58
|
-
4. Launch state is context, not provider authority.
|
|
59
|
-
may supply owner, admin login, repo name,
|
|
60
|
-
and
|
|
61
|
-
|
|
62
|
-
5. `BETTER_AUTH_SECRET` is load-bearing.
|
|
63
|
-
rotating it invalidates
|
|
51
|
+
4. Launch state is context, not provider authority.
|
|
52
|
+
`.mantle/launch-state.json` may supply owner, admin login, repo name,
|
|
53
|
+
locales, and type. It does not authorize Cloudflare operations, OAuth
|
|
54
|
+
secrets, or custom domains.
|
|
55
|
+
5. `BETTER_AUTH_SECRET` is load-bearing. Set it once and preserve it;
|
|
56
|
+
rotating it invalidates every session.
|
|
64
57
|
|
|
65
58
|
## Flow
|
|
66
59
|
|
|
67
60
|
Run from the generated project root.
|
|
68
61
|
|
|
69
|
-
1.
|
|
62
|
+
1. Verify the landing deploy. Confirm Cloudflare Workers CI built and
|
|
63
|
+
deployed from GitHub, and capture the live `*.workers.dev` URL. The
|
|
64
|
+
public site should respond; auth-gated routes return `503
|
|
65
|
+
setup_incomplete` until step 4 — that is expected, not a failure.
|
|
66
|
+
|
|
67
|
+
2. Confirm the local repo is clean and valid before changing config:
|
|
70
68
|
|
|
71
69
|
```bash
|
|
72
70
|
pnpm install --frozen-lockfile
|
|
73
71
|
pnpm validate
|
|
74
72
|
pnpm typecheck
|
|
75
|
-
if node -e "process.exit(require('./package.json').scripts?.test ? 0 : 1)"; then
|
|
76
|
-
pnpm test
|
|
77
|
-
else
|
|
78
|
-
echo "No pnpm test script; skipping."
|
|
79
|
-
fi
|
|
80
73
|
git status --short
|
|
81
|
-
gh auth status
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
If GitHub CLI auth is missing or points at the wrong login, pause and
|
|
85
|
-
ask the user to switch/login before creating the repo.
|
|
86
|
-
|
|
87
|
-
2. Create a private GitHub repo in the selected owner, add the remote,
|
|
88
|
-
commit the scaffold, and push. Use the user's GitHub auth context.
|
|
89
|
-
|
|
90
|
-
3. Print the deterministic browser plan:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
pnpm run provision:plan
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
4. Hand the user directly to Cloudflare's Git import path:
|
|
97
|
-
|
|
98
|
-
```text
|
|
99
|
-
https://dash.cloudflare.com/?to=%2F%3Aaccount%2Fworkers-and-pages
|
|
100
74
|
```
|
|
101
75
|
|
|
102
|
-
Ask
|
|
103
|
-
name equal to `wrangler.toml` `name`, wait for deploy, and send back the
|
|
104
|
-
live `*.workers.dev` URL. Ask for the Worker name only if Cloudflare
|
|
105
|
-
forced a name different from the repo/project name.
|
|
106
|
-
|
|
107
|
-
5. After the Worker URL is known, print the worker-specific plan:
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
pnpm run provision:plan -- --worker-url <worker-url>
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Read only the values needed for the current project. Do not dump
|
|
114
|
-
internal notes or placeholder syntax onto a non-coder.
|
|
115
|
-
|
|
116
|
-
6. Ask the user to create the per-site GitHub OAuth App after the Worker
|
|
76
|
+
3. Ask the user to create the per-site GitHub OAuth App once the Worker
|
|
117
77
|
URL is known:
|
|
118
78
|
|
|
119
79
|
- Homepage URL: `<worker-url>`
|
|
120
80
|
- Authorization callback URL: `<worker-url>/api/auth/callback/github`
|
|
121
81
|
- Device Flow: unchecked
|
|
122
82
|
|
|
123
|
-
Ask for the Client ID in chat. Keep the Client Secret out of chat and
|
|
124
|
-
|
|
83
|
+
Ask for the Client ID in chat. Keep the Client Secret out of chat and pass
|
|
84
|
+
it through the hidden shell prompt below.
|
|
125
85
|
|
|
126
|
-
|
|
86
|
+
4. Write non-secret production config into `wrangler.toml`
|
|
87
|
+
(`PUBLIC_ORIGIN=<worker-url>`, `GITHUB_CLIENT_ID`, `ADMIN_GITHUB_LOGIN`,
|
|
88
|
+
and the correct Worker `name`), then set the Worker secrets. Prefer a
|
|
89
|
+
Cloudflare MCP connector; otherwise use Wrangler after the user agrees
|
|
90
|
+
to `wrangler login`:
|
|
127
91
|
|
|
128
92
|
```bash
|
|
129
93
|
pnpm exec wrangler login
|
|
130
|
-
read -rsp "GitHub OAuth client secret: " GITHUB_CLIENT_SECRET &&
|
|
131
|
-
|
|
94
|
+
read -rsp "GitHub OAuth client secret: " GITHUB_CLIENT_SECRET && printf "\n"
|
|
95
|
+
printf '%s' "$GITHUB_CLIENT_SECRET" | pnpm exec wrangler secret put GITHUB_CLIENT_SECRET
|
|
96
|
+
openssl rand -hex 32 | pnpm exec wrangler secret put BETTER_AUTH_SECRET
|
|
132
97
|
unset GITHUB_CLIENT_SECRET
|
|
133
98
|
```
|
|
134
99
|
|
|
135
|
-
|
|
100
|
+
Set `BETTER_AUTH_SECRET` only on the first run; reuse the existing value on
|
|
101
|
+
later runs.
|
|
102
|
+
|
|
103
|
+
5. Commit and push the non-secret config so Cloudflare CI redeploys:
|
|
136
104
|
|
|
137
105
|
```bash
|
|
138
|
-
git
|
|
139
|
-
git add wrangler.toml src/mantleConfig.ts AGENTS.md
|
|
106
|
+
git add wrangler.toml AGENTS.md
|
|
140
107
|
git commit -m "mantle: wire production provision"
|
|
141
108
|
git push
|
|
142
109
|
```
|
|
143
110
|
|
|
144
|
-
Wait for
|
|
145
|
-
|
|
146
|
-
|
|
111
|
+
Wait for Workers Builds to redeploy from the pushed commit. If the
|
|
112
|
+
dashboard build is unavailable, run `pnpm deploy` as a fallback and explain
|
|
113
|
+
that to the user.
|
|
147
114
|
|
|
148
|
-
|
|
115
|
+
6. Smoke test:
|
|
149
116
|
|
|
150
117
|
- public home route;
|
|
151
118
|
- `/admin/sign-in`;
|
|
152
119
|
- GitHub admin sign-in;
|
|
153
120
|
- `/mcp/staff` with an agent client when available;
|
|
154
|
-
- a
|
|
121
|
+
- a type-specific core workflow.
|
|
155
122
|
|
|
156
123
|
A fresh site may have no public home content yet. A 404 on the locale
|
|
157
124
|
homepage is acceptable only after the Worker boots, `/admin/sign-in`
|
|
158
|
-
loads, and auth/MCP boundaries behave correctly.
|
|
159
|
-
|
|
160
|
-
## Feature Overlays
|
|
161
|
-
|
|
162
|
-
If `.mantle/features.json` lists features, run the repo-local feature
|
|
163
|
-
overlay skill first:
|
|
164
|
-
|
|
165
|
-
```text
|
|
166
|
-
.agent/skills/mantle-feature-overlays/SKILL.md
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
Feature scripts are starter lifecycle scripts, not Mantle CLI commands.
|
|
170
|
-
Run them only when the feature is present and the user accepts any extra
|
|
171
|
-
provider/billing requirement.
|
|
125
|
+
loads, and auth / MCP boundaries behave correctly.
|
|
172
126
|
|
|
173
127
|
## Handoff
|
|
174
128
|
|
|
@@ -180,28 +134,31 @@ language:
|
|
|
180
134
|
- Staff MCP URL.
|
|
181
135
|
- Operator setup URL (`https://mantle.tools/connect?site=...`).
|
|
182
136
|
- What changed locally and what was committed.
|
|
183
|
-
- Any intentionally deferred feature setup.
|
|
137
|
+
- Any intentionally deferred feature / provider setup.
|
|
184
138
|
|
|
185
139
|
Point future agents at `AGENTS.md`, `.mantle/launch-state.json`, and the
|
|
186
|
-
repo-local `.agent/skills/` directory
|
|
140
|
+
repo-local `.agent/skills/` directory (`mantle:develop`, `mantle:overlay`,
|
|
141
|
+
`mantle:theme`, `mantle:update`).
|
|
187
142
|
|
|
188
143
|
## Diagnostics
|
|
189
144
|
|
|
190
145
|
| Symptom | Likely cause | Fix |
|
|
191
146
|
|---|---|---|
|
|
192
|
-
|
|
|
193
|
-
| `
|
|
194
|
-
| `wrangler secret put` targets wrong account | Wrangler logged into another Cloudflare account | Re-run `pnpm exec wrangler login` and confirm account. |
|
|
147
|
+
| Auth-gated routes return `503 setup_incomplete` | GitHub OAuth + secrets not wired yet | Expected before step 3-4; finish the OAuth App + secrets, then redeploy. |
|
|
148
|
+
| `wrangler secret put` targets the wrong account | Wrangler logged into another Cloudflare account | Re-run `pnpm exec wrangler login` and confirm the account. |
|
|
195
149
|
| GitHub OAuth callback mismatch | OAuth App callback URL is wrong | Set it exactly to `<worker-url>/api/auth/callback/github`. |
|
|
196
|
-
| Owner signs in but admin/MCP returns 403 | `ADMIN_GITHUB_LOGIN` does not match signed-in GitHub login |
|
|
197
|
-
| Worker boots but sessions fail after rerun | `BETTER_AUTH_SECRET` changed or was deleted | Restore the old secret if available; otherwise users must sign in again. |
|
|
150
|
+
| Owner signs in but admin / MCP returns 403 | `ADMIN_GITHUB_LOGIN` does not match the signed-in GitHub login | Fix the `ADMIN_GITHUB_LOGIN` value and redeploy. |
|
|
151
|
+
| Worker boots but sessions fail after a rerun | `BETTER_AUTH_SECRET` changed or was deleted | Restore the old secret if available; otherwise users must sign in again. |
|
|
198
152
|
|
|
199
153
|
## Don't
|
|
200
154
|
|
|
201
155
|
- Don't ask for a Cloudflare API token in the base first-run path.
|
|
202
|
-
- Don't create
|
|
156
|
+
- Don't re-create the repo or re-run the first deploy from the agent;
|
|
157
|
+
landing owns first provisioning.
|
|
158
|
+
- Don't resurrect `provision:up` / `provision:plan` as a second
|
|
159
|
+
provisioner; those scripts were retired with v2.
|
|
203
160
|
- Don't commit provider secrets.
|
|
204
|
-
- Don't use `127.0.0.1` in OAuth callback examples; use `localhost`
|
|
205
|
-
|
|
206
|
-
- Don't use `/admin/auth/github/callback`; the Better Auth callback path
|
|
207
|
-
|
|
161
|
+
- Don't use `127.0.0.1` in OAuth callback examples; use `localhost` locally
|
|
162
|
+
and the real Worker URL in production.
|
|
163
|
+
- Don't use `/admin/auth/github/callback`; the Better Auth callback path is
|
|
164
|
+
`/api/auth/callback/github`.
|