@aotter/mantle 0.1.2 → 0.1.3-alpha.2
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 +36 -13
- package/dist/auth.d.ts +2 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +2 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +3 -0
- package/dist/cli/generate.js.map +1 -1
- package/dist/cli/main.d.ts +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +5 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +3 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/codegen/emitMantleModule.d.ts.map +1 -1
- package/dist/codegen/emitMantleModule.js +38 -2
- package/dist/codegen/emitMantleModule.js.map +1 -1
- package/docs/adr/0014-auth-better-auth-and-multi-tenant-mcp.md +109 -2
- package/docs/agent-prompts.md +38 -29
- package/docs/auth-hosting-model.md +1 -1
- package/docs/examples/host-local-admin-otp/README.md +10 -0
- package/docs/handbook/cloudflare/authentication.md +44 -3
- package/docs/handbook/concepts/mcp-and-agents.md +10 -5
- package/docs/handbook/navigation.json +8 -2
- package/docs/handbook/reference/diagnostics.md +5 -1
- package/docs/handbook/reference/manifest.md +1 -1
- package/docs/handbook/reference/procedure.md +1 -0
- package/docs/handbook/reference/surface.md +6 -4
- package/docs/handbook/reference/trigger.md +1 -1
- package/docs/handbook/releases/index.md +75 -0
- package/docs/handbook/start/project-and-cli.md +15 -4
- package/docs/handbook/start/quickstart-admin.md +20 -209
- package/docs/labels.md +3 -3
- package/docs/migration-0.1.2.md +10 -126
- package/docs/release-process.md +80 -39
- package/docs/spec-only-host-adoption.md +1 -1
- package/package.json +25 -16
- package/skills/README.md +21 -15
- package/skills/install/SKILL.md +5 -5
- package/skills/plugin/SKILL.md +6 -6
- package/skills/provision/SKILL.md +27 -17
- package/skills/update/SKILL.md +4 -3
|
@@ -1,227 +1,38 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Open local Admin in one shot:
|
|
2
|
+
description: "Open local Admin in one shot: follow the official OTP example, bind ASSETS, sign in with email OTP from wrangler logs, land in the Dev UI."
|
|
3
3
|
---
|
|
4
4
|
# Quickstart: local Admin
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Admin is **opt-in**: use it when humans need a Dev UI. A complete Mantle
|
|
7
|
+
service does not require this surface. The default embed path — Spec + Worker
|
|
8
|
+
without Admin — is [Quickstart: a minimal Worker](./quickstart-worker.md).
|
|
7
9
|
|
|
8
|
-
The
|
|
10
|
+
The procedural source of truth is the official example:
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
**[`docs/examples/host-local-admin-otp/README.md`](../../examples/host-local-admin-otp/README.md)**
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
An agent interviews the human for one value before writing files: the bootstrap owner email. The example uses `owner@example.com`.
|
|
17
|
-
|
|
18
|
-
## 1. `package.json`
|
|
19
|
-
|
|
20
|
-
Install every `@aotter/mantle*` package from the `latest` dist-tag. Admin needs both `@aotter/mantle-admin` and `@aotter/mantle-admin-ui` plus the Cloudflare adapter peers.
|
|
21
|
-
|
|
22
|
-
```json
|
|
23
|
-
{
|
|
24
|
-
"name": "mantle-local-admin-otp",
|
|
25
|
-
"private": true,
|
|
26
|
-
"type": "module",
|
|
27
|
-
"scripts": {
|
|
28
|
-
"generate": "mantle generate",
|
|
29
|
-
"validate": "mantle validate",
|
|
30
|
-
"typecheck": "tsc --noEmit",
|
|
31
|
-
"predev": "node ensure-dev-vars.mjs",
|
|
32
|
-
"dev": "wrangler dev --local --ip 127.0.0.1 --port 8787"
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@aotter/mantle": "latest",
|
|
36
|
-
"@aotter/mantle-admin": "latest",
|
|
37
|
-
"@aotter/mantle-admin-ui": "latest",
|
|
38
|
-
"@aotter/mantle-cloudflare": "latest",
|
|
39
|
-
"better-auth": "1.7.2",
|
|
40
|
-
"hono": "^4.13.3",
|
|
41
|
-
"zod": "^4.5.4",
|
|
42
|
-
"aws4fetch": "^1.0.20"
|
|
43
|
-
},
|
|
44
|
-
"devDependencies": {
|
|
45
|
-
"@cloudflare/workers-types": "^5.20260907.1",
|
|
46
|
-
"typescript": "^6.0.3",
|
|
47
|
-
"wrangler": "^4.125.0"
|
|
48
|
-
},
|
|
49
|
-
"packageManager": "pnpm@9.15.0"
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Add a `tsconfig.json` that includes the generated module:
|
|
54
|
-
|
|
55
|
-
```json
|
|
56
|
-
{
|
|
57
|
-
"compilerOptions": {
|
|
58
|
-
"target": "ES2022",
|
|
59
|
-
"module": "ESNext",
|
|
60
|
-
"moduleResolution": "bundler",
|
|
61
|
-
"strict": true,
|
|
62
|
-
"noEmit": true,
|
|
63
|
-
"skipLibCheck": true,
|
|
64
|
-
"types": ["@cloudflare/workers-types"]
|
|
65
|
-
},
|
|
66
|
-
"include": ["src/**/*.ts", ".mantle/generated/**/*.ts"]
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
`ensure-dev-vars.mjs` copies the example vars on first `pnpm dev`:
|
|
71
|
-
|
|
72
|
-
```js
|
|
73
|
-
import { copyFileSync, existsSync } from "node:fs";
|
|
74
|
-
if (!existsSync(".dev.vars")) copyFileSync(".dev.vars.example", ".dev.vars");
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## 2. `.dev.vars.example`
|
|
78
|
-
|
|
79
|
-
```sh
|
|
80
|
-
PUBLIC_ORIGIN=http://127.0.0.1:8787
|
|
81
|
-
BETTER_AUTH_SECRET=local-admin-otp-dev-secret-do-not-use-in-prod
|
|
82
|
-
ADMIN_EMAIL=owner@example.com
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Copy it to `.dev.vars` (the `predev` script does this). Never commit `.dev.vars`. `pnpm dev` binds `127.0.0.1:8787` so wrangler's Ready-on origin matches this `PUBLIC_ORIGIN`. A mismatch makes Better Auth reject OTP with `INVALID_ORIGIN`.
|
|
86
|
-
|
|
87
|
-
## 3. `manifests/site.yaml`
|
|
88
|
-
|
|
89
|
-
One publishing Schema and one public View. `mantle generate` never invents a Schema; this notes model is example business data. `cache` is valid in this snapshot's grammar.
|
|
90
|
-
|
|
91
|
-
```yaml
|
|
92
|
-
apiVersion: cms.mantle.aotter.net/v1
|
|
93
|
-
kind: Schema
|
|
94
|
-
metadata:
|
|
95
|
-
name: notes
|
|
96
|
-
spec:
|
|
97
|
-
title: Notes
|
|
98
|
-
schema:
|
|
99
|
-
type: object
|
|
100
|
-
required: [title]
|
|
101
|
-
properties:
|
|
102
|
-
title: { type: string }
|
|
103
|
-
lifecycle: publishing
|
|
104
|
-
---
|
|
105
|
-
apiVersion: cms.mantle.aotter.net/v1
|
|
106
|
-
kind: View
|
|
107
|
-
metadata:
|
|
108
|
-
name: published-notes
|
|
109
|
-
spec:
|
|
110
|
-
surface: public
|
|
111
|
-
from: notes
|
|
112
|
-
cache: { sharedMaxAge: 3600 }
|
|
113
|
-
fields: [id, title]
|
|
114
|
-
filter:
|
|
115
|
-
eq: { field: status, value: published }
|
|
116
|
-
limit: 20
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Use the docs that ship with the pinned version. A newer handbook page is not a contract for an older install.
|
|
120
|
-
|
|
121
|
-
## 4. `src/index.ts`
|
|
122
|
-
|
|
123
|
-
Replace conventional GitHub Auth construction with local email OTP. Core still owns `/admin` and `/api/auth/*`.
|
|
124
|
-
|
|
125
|
-
```ts
|
|
126
|
-
import {
|
|
127
|
-
ConsoleEmailSender,
|
|
128
|
-
createAuth,
|
|
129
|
-
createMantleWorker,
|
|
130
|
-
type MantleCloudflareEnv,
|
|
131
|
-
} from "@aotter/mantle/cloudflare";
|
|
132
|
-
import { plan } from "../.mantle/generated/mantle.js";
|
|
133
|
-
|
|
134
|
-
export interface Env extends MantleCloudflareEnv {
|
|
135
|
-
readonly ASSETS: Fetcher;
|
|
136
|
-
readonly BETTER_AUTH_SECRET: string;
|
|
137
|
-
readonly ADMIN_EMAIL: string;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const sender = new ConsoleEmailSender();
|
|
141
|
-
|
|
142
|
-
export default createMantleWorker<Env>({
|
|
143
|
-
plan,
|
|
144
|
-
cacheScope: "local-admin-otp",
|
|
145
|
-
siteDefaults: (env) => ({
|
|
146
|
-
brand: "Local Admin",
|
|
147
|
-
title: "Local Admin",
|
|
148
|
-
origin: env.PUBLIC_ORIGIN?.replace(/\/+$/, "") ?? "http://127.0.0.1:8787",
|
|
149
|
-
}),
|
|
150
|
-
auth: (env) => {
|
|
151
|
-
const origin = env.PUBLIC_ORIGIN?.replace(/\/+$/, "") ?? "http://127.0.0.1:8787";
|
|
152
|
-
return createAuth({
|
|
153
|
-
database: env.DB,
|
|
154
|
-
baseURL: origin,
|
|
155
|
-
secret: env.BETTER_AUTH_SECRET,
|
|
156
|
-
methods: [{ kind: "email-otp", sender }],
|
|
157
|
-
bootstrapOwner: { match: "email", value: env.ADMIN_EMAIL },
|
|
158
|
-
oauthProvider: {
|
|
159
|
-
loginPage: "/admin/sign-in",
|
|
160
|
-
consentPage: "/oauth/consent",
|
|
161
|
-
scopes: ["mcp"],
|
|
162
|
-
mcpResource: `${origin}/mcp`,
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
},
|
|
166
|
-
});
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
`ConsoleEmailSender` writes the OTP to wrangler logs. It is the local human path. Do not wire it in production.
|
|
170
|
-
|
|
171
|
-
## 5. `wrangler.jsonc`
|
|
172
|
-
|
|
173
|
-
Admin requires Static Assets. This is not optional.
|
|
174
|
-
|
|
175
|
-
```jsonc
|
|
176
|
-
{
|
|
177
|
-
"$schema": "node_modules/wrangler/config-schema.json",
|
|
178
|
-
"name": "mantle-local-admin-otp",
|
|
179
|
-
"main": "src/index.ts",
|
|
180
|
-
"compatibility_date": "2026-09-08",
|
|
181
|
-
"compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
|
|
182
|
-
"assets": { "directory": "./public", "binding": "ASSETS" },
|
|
183
|
-
"d1_databases": [
|
|
184
|
-
{ "binding": "DB", "database_name": "mantle-local-admin-otp" }
|
|
185
|
-
]
|
|
186
|
-
}
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
Keep a `public/` directory (empty is fine). `generate` writes `public/_mantle/admin/` into it. Do not put `/_mantle` in `run_worker_first`: those files must be served by the assets layer. A Worker-first catch-all without asset fallthrough is the white-screen class of bug — `/admin` returns SPA HTML `200` while `/_mantle/admin/assets/*` is `404`.
|
|
190
|
-
|
|
191
|
-
## 6. Install, generate, run
|
|
14
|
+
Copy that directory outside the SDK checkout (or author the same files from
|
|
15
|
+
it). Interview the human for one value before writing files: the bootstrap
|
|
16
|
+
owner email. The example uses `owner@example.com`. Then:
|
|
192
17
|
|
|
193
18
|
```sh
|
|
194
19
|
pnpm install && pnpm generate && pnpm dev
|
|
195
20
|
```
|
|
196
21
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
## 7. Sign in
|
|
202
|
-
|
|
203
|
-
```sh
|
|
204
|
-
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8787/admin/sign-in
|
|
205
|
-
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8787/_mantle/admin/index.html
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
Both are `200`. Open `/admin/sign-in`, submit the bootstrap owner email, then read the wrangler log:
|
|
209
|
-
|
|
210
|
-
```text
|
|
211
|
-
[ConsoleEmailSender] auth.email-otp.sign-in → owner@example.com (en)
|
|
212
|
-
subject: Your Mantle sign-in code: 123456
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
Enter the code. The first matching sign-in is promoted to `owner` and the Admin shell loads.
|
|
216
|
-
|
|
217
|
-
If the page is blank, fetch an asset URL from the HTML. A `404` there means `ASSETS` is missing or `run_worker_first` swallowed `/_mantle`. That is not a missing `vite build`.
|
|
22
|
+
Open the wrangler Ready-on URL (`http://127.0.0.1:8787/admin/sign-in`), submit
|
|
23
|
+
the owner email, and read the OTP from wrangler logs. `mantle generate` syncs
|
|
24
|
+
the prebuilt Admin SPA; do not Vite-build Admin.
|
|
218
25
|
|
|
219
|
-
|
|
26
|
+
Traps (documented on the example):
|
|
220
27
|
|
|
221
|
-
-
|
|
222
|
-
- `
|
|
28
|
+
- Prefer `127.0.0.1` over `localhost` (`INVALID_ORIGIN`).
|
|
29
|
+
- `pnpm check` / smoke rewrites `.dev.vars` to a smoke-only port — restore it
|
|
30
|
+
from `.dev.vars.example` before `pnpm dev`.
|
|
223
31
|
|
|
224
|
-
|
|
32
|
+
Install every `@aotter/mantle*` package from the `latest` dist-tag; see
|
|
33
|
+
[Versions](../reference/surface.md#versions). Admin needs both
|
|
34
|
+
`@aotter/mantle-admin` and `@aotter/mantle-admin-ui`, wrangler `ASSETS` on
|
|
35
|
+
`./public`, and `createAuth` email-otp + `ConsoleEmailSender`.
|
|
225
36
|
|
|
226
37
|
## Next steps
|
|
227
38
|
|
package/docs/labels.md
CHANGED
|
@@ -29,12 +29,12 @@ For package README or package-local docs changes, prefer the package area label
|
|
|
29
29
|
| `area:runtime` | `packages/mantle-runtime` behavior, ports, use cases, dispatcher, and MCP runtime. |
|
|
30
30
|
| `area:spec` | `packages/mantle-spec`, manifest parsing, validation, diagnostics, CLI, spec types. |
|
|
31
31
|
| `area:cf` | `packages/adapters/cloudflare`, Workers adapter, D1/KV/ASSETS wiring, Cloudflare deploy behavior. |
|
|
32
|
-
| `area:starters` | Legacy `aotter/mantle-starters` source and retirement migration. |
|
|
33
32
|
| `area:skills` | `skills/*` agent briefs and install/extend/provision workflows. |
|
|
34
33
|
| `area:admin-ui` | `packages/mantle-admin-ui` React admin SPA. |
|
|
35
34
|
| `area:docs` | Repo-wide human docs, governance docs, ADR text, release docs, root README content, and cross-cutting documentation work. |
|
|
36
35
|
| `area:adapter` | Adapter boundary work spanning Cloudflare or future adapters. |
|
|
37
36
|
| `area:ci` | GitHub Actions, dependency automation, and repository checks. |
|
|
37
|
+
| `area:starters` | **Legacy only.** Retired `aotter/mantle-starters` source and migration notes. Do not use for new Core work. |
|
|
38
38
|
|
|
39
39
|
## Release and review gates
|
|
40
40
|
|
|
@@ -45,7 +45,7 @@ For package README or package-local docs changes, prefer the package area label
|
|
|
45
45
|
| `breaking-change` | Semver-relevant breaking change. | Generated release notes must call it out. | The change is redesigned to be non-breaking. |
|
|
46
46
|
| `skip-release-notes` | Release bookkeeping with no user-facing change. | Excluded from generated GitHub Release notes. | The PR contains a user-facing change. |
|
|
47
47
|
| `needs-adr` | Architecture, trust boundary, package boundary, or long-lived decision needs an ADR or ADR-lite proposal. | Do not merge implementation until the decision is captured. | ADR/proposal lands or maintainer confirms an existing ADR covers it. |
|
|
48
|
-
| `needs-grammar-revise` | Manifest grammar or closed-enum change. | Requires grammar-revise round before code/types
|
|
48
|
+
| `needs-grammar-revise` | Manifest grammar or closed-enum change. | Requires grammar-revise round before code/types change. | Grammar decision lands or the change no longer affects grammar. |
|
|
49
49
|
| `needs-discussion` | Not converged enough for implementation. | Do not start coding from this issue. | Closing criteria are met and scope is concrete. |
|
|
50
50
|
|
|
51
51
|
## Creating missing labels
|
|
@@ -56,12 +56,12 @@ Use these commands from a checked-out repo:
|
|
|
56
56
|
gh label create "area:runtime" --description "Runtime package, ports, use cases, dispatcher, render, MCP runtime" --color "1d76db"
|
|
57
57
|
gh label create "area:spec" --description "Spec package, manifest parsing, validation, diagnostics, CLI, types" --color "1d76db"
|
|
58
58
|
gh label create "area:cf" --description "Cloudflare Workers adapter and bindings" --color "1d76db"
|
|
59
|
-
gh label create "area:starters" --description "Starter templates and starter validation" --color "1d76db"
|
|
60
59
|
gh label create "area:skills" --description "Agent Skills and install/extend/provision workflows" --color "1d76db"
|
|
61
60
|
gh label create "area:admin-ui" --description "React admin UI" --color "1d76db"
|
|
62
61
|
gh label create "area:docs" --description "Documentation and governance" --color "1d76db"
|
|
63
62
|
gh label create "area:adapter" --description "Adapter boundary and future adapter work" --color "1d76db"
|
|
64
63
|
gh label create "area:ci" --description "CI, dependency automation, and repository checks" --color "1d76db"
|
|
64
|
+
gh label create "area:starters" --description "Legacy only: retired mantle-starters source and migration" --color "cfd3d7"
|
|
65
65
|
gh label create "breaking-change" --description "Semver-relevant breaking change" --color "b60205"
|
|
66
66
|
gh label create "skip-release-notes" --description "Release bookkeeping only; omit from generated GitHub notes" --color "ededed"
|
|
67
67
|
gh label create "needs-adr" --description "Requires an ADR or ADR-lite decision before merge" --color "d93f0b"
|
package/docs/migration-0.1.2.md
CHANGED
|
@@ -1,129 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Upgrading to 0.1.2
|
|
2
2
|
|
|
3
|
-
0.1.
|
|
4
|
-
|
|
5
|
-
that version requires no migration. No stable 0.1.0 release is planned.
|
|
3
|
+
0.1.2 is the first stable release and the first public one. There is no earlier
|
|
4
|
+
stable to upgrade from and no migration to perform.
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
scaffold commands. `generate`, `validate`, `emit-openapi` and `skills` remain.
|
|
10
|
-
Generation and runtime Web rendering retain their existing responsibilities.
|
|
6
|
+
What it contains, what it requires and what it does not yet cover is in
|
|
7
|
+
[Releases](handbook/releases/index.md).
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
the lockfile through the package manager. Review required peer upgrades.
|
|
18
|
-
3. Remove scripts invoking the retired scaffolder/bundle updater. If application
|
|
19
|
-
code imports the provision renderer, remain on alpha.17 until that host's
|
|
20
|
-
provisioning design is migrated explicitly; do not replace it with a
|
|
21
|
-
handwritten remote-code loader.
|
|
22
|
-
4. Retain application source and all Worker/D1/KV identity, origins, auth mode,
|
|
23
|
-
secrets and legacy `.mantle` metadata. Those files are not templates to
|
|
24
|
-
replace or evidence that new Starter tags must exist.
|
|
25
|
-
5. Run the installed `mantle generate`, `generate --check`, `skills`,
|
|
26
|
-
`skills --check`, `validate`, and the project's TypeScript/tests. Test local
|
|
27
|
-
routes and configured authorization before considering deployment.
|
|
28
|
-
|
|
29
|
-
## Native Schema-table storage reset
|
|
30
|
-
|
|
31
|
-
The 0.1.2 pre-beta line replaces the generic `entries` JSON table with one
|
|
32
|
-
native SQLite/D1 table per Manifest Schema. Mantle's row envelope uses
|
|
33
|
-
`_mantle_id`, `_mantle_status`, `_mantle_version`, `_mantle_author_id`,
|
|
34
|
-
`_mantle_created_at`, and `_mantle_updated_at`; authored fields keep their exact
|
|
35
|
-
names as native columns. The old generated columns, projection views and
|
|
36
|
-
compatibility repository were removed.
|
|
37
|
-
|
|
38
|
-
This is intentionally a storage-format break before beta. Reset and
|
|
39
|
-
re-bootstrap development or internal-alpha content databases that contain the
|
|
40
|
-
old `entries` layout. Move required data manually outside Mantle and Control;
|
|
41
|
-
there is no product migration workflow for this unreleased format. Automatic
|
|
42
|
-
artifacts cover initial and additive changes only. Removed columns and tables
|
|
43
|
-
remain physically present so the previous Worker can still run. Renames, type
|
|
44
|
-
changes, data transforms, and any `uniqueIndexes` tuple change require the same
|
|
45
|
-
manual rebuild. The pre-beta Cloud
|
|
46
|
-
path does not accept or execute destructive SQL.
|
|
47
|
-
|
|
48
|
-
Row APIs are now Schema-qualified. `EntryRepository.get` and
|
|
49
|
-
`EntryReader.readById` accept `{ collection, id }`; Admin entry detail and
|
|
50
|
-
mutation routes require `?collection=<schema>`, and generic MCP entry tools
|
|
51
|
-
require `collection`. Generated `entries.<schema>` bindings supply it for you.
|
|
52
|
-
|
|
53
|
-
A new project follows [direct authoring](direct-authoring.md). Templates and
|
|
54
|
-
provider setup are not hidden inside `generate`. Future Builder/landing-next
|
|
55
|
-
provisioning is a separate decision; this change does not migrate those hosts.
|
|
56
|
-
|
|
57
|
-
## Site chrome: GA4 and Meta Pixel leave siteConfig
|
|
58
|
-
|
|
59
|
-
`SiteConfig.ga4MeasurementId`, `SiteConfig.facebookPixelId`, and their
|
|
60
|
-
`SiteDefaults` seed equivalents are removed. The Admin UI no longer has
|
|
61
|
-
Analytics fields for them, the Runtime site-settings use case no longer
|
|
62
|
-
accepts them, and the Web HTML renderer no longer injects the gtag or Pixel
|
|
63
|
-
base snippet into rendered storefront HTML. This applies to every 0.1.2
|
|
64
|
-
prerelease; it is not staged behind a flag.
|
|
65
|
-
|
|
66
|
-
Core's `siteConfig` remains deployment identity only (locales, brand, title,
|
|
67
|
-
description, origin, icons, media); tracking and verification tags are host
|
|
68
|
-
chrome because frontends are plural and Core cannot assume one `</head>` to
|
|
69
|
-
rewrite. See [Why Core does not inject](handbook/cloudflare/site-chrome.md#why-core-does-not-inject).
|
|
70
|
-
|
|
71
|
-
To keep GA4 or Meta Pixel across the upgrade:
|
|
72
|
-
|
|
73
|
-
1. Read the existing `ga4MeasurementId` / `facebookPixelId` values from the
|
|
74
|
-
pre-upgrade site settings (Admin API or KV/D1 `SiteConfigRepository`
|
|
75
|
-
directly) before removing the old columns/fields.
|
|
76
|
-
2. Move the tag injection into host chrome following
|
|
77
|
-
[Cloudflare-first install > Analytics](handbook/cloudflare/site-chrome.md#analytics):
|
|
78
|
-
render the snippet in the host's own document/layout, not through Core.
|
|
79
|
-
3. Drop the old fields from any locally stored site-settings payloads; the
|
|
80
|
-
Runtime `SiteConfig` type no longer declares them, so a TypeScript build
|
|
81
|
-
against the new types is what surfaces a leftover reference.
|
|
82
|
-
|
|
83
|
-
## Earlier alpha.7 compatibility changes
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
0.1.2 removes the temporary full-site compatibility stack. Mantle Core is now
|
|
87
|
-
an embeddable parse → link → compile → prepare → bind pipeline; Web, Admin,
|
|
88
|
-
Admin UI, Bun, Vercel, and Cloudflare are selected separately.
|
|
89
|
-
|
|
90
|
-
| alpha.7 | 0.1.2 |
|
|
91
|
-
|---|---|
|
|
92
|
-
| `parseManifests*` | `parseManifestSources({ sources })` |
|
|
93
|
-
| raw `Manifest[]` validation/runtime input | `ParsedManifestSet` → `LinkedManifestSet` → `RuntimePlan` |
|
|
94
|
-
| `createCmsRuntime({ manifests, db })` | `bootMantleRuntime({ plan, storage })`, or explicit prepare then `createMantleRuntime({ prepared })` |
|
|
95
|
-
| `CmsRuntime.db` / `entryReader` | keep the application DB handle; use `runtime.entries` for Mantle reads |
|
|
96
|
-
| generated `manifest`, `site.ts`, `types.d.ts` | generated `plan`, `createMantle`, `bindMantle`, and types in `mantle.ts` |
|
|
97
|
-
| `mantle introspect` | install `@aotter/mantle-spec` directly and run `mantle-spec introspect` |
|
|
98
|
-
| `mantle emit-types` | use `mantle generate`; for raw declarations, run `mantle-spec emit-types` |
|
|
99
|
-
| generated `.agent/skills/` | generated `.agents/skills/`; legacy user files are left untouched |
|
|
100
|
-
| `bindMantleSite` / string-keyed Views | `bindMantle(runtime)` and generated lower-camel properties |
|
|
101
|
-
| `createCmsRef` / `CmsConfig` | `createMantleRuntimeRef` / `MantleCloudflareConfig` |
|
|
102
|
-
| `mountServerEndpoints` | explicitly compose `mountRuntimeEndpoints` and optional `mountAdmin` |
|
|
103
|
-
|
|
104
|
-
Delete stale generated `site.ts` and `types.d.ts` files once, then run
|
|
105
|
-
`mantle generate`. Install only the optional package used by the host;
|
|
106
|
-
installing the umbrella alone now pulls only Spec and Runtime.
|
|
107
|
-
|
|
108
|
-
Intentional behavior changes:
|
|
109
|
-
|
|
110
|
-
- Generated-plan fingerprint or version mismatches fail immediately and ask
|
|
111
|
-
the developer to regenerate.
|
|
112
|
-
- Runtime HTTP trigger JSON bodies must be objects. Arrays and primitives are
|
|
113
|
-
rejected at the request boundary.
|
|
114
|
-
- Malformed percent-encoded paths are routing misses (`404`), not claimed
|
|
115
|
-
Mantle routes.
|
|
116
|
-
- Better Auth and every `@better-auth/*` package move together to 1.7.
|
|
117
|
-
`oauthProvider.validAudiences` becomes protected `resources`; MCP uses one
|
|
118
|
-
canonical `${PUBLIC_ORIGIN}/mcp` resource and CIMD client discovery.
|
|
119
|
-
- The Cloudflare adapter no longer requires `OAUTH_KV` or
|
|
120
|
-
`@cloudflare/workers-oauth-provider`. Old opaque tokens and KV registrations
|
|
121
|
-
cannot be migrated safely and must reconnect.
|
|
122
|
-
- Canonical plan ordering may change stable field/export order (including
|
|
123
|
-
Admin CSV columns) without changing field values.
|
|
124
|
-
|
|
125
|
-
This alpha changes the Better Auth D1 schema, including required account
|
|
126
|
-
issuer identity and OAuth resource/client tables. Reset and re-bootstrap a
|
|
127
|
-
pre-1.7 alpha auth database; do not guess an issuer backfill. Reset old generic
|
|
128
|
-
content storage as described above and move required data manually outside
|
|
129
|
-
Mantle.
|
|
9
|
+
Every version before 0.1.2 was an internal prerelease. If you are holding a
|
|
10
|
+
database created by one of those, `LEGACY_STORAGE_RESET_REQUIRED` means it
|
|
11
|
+
predates native Schema tables: rebuild it rather than migrating it. Move any
|
|
12
|
+
data you need out of Mantle by hand first — there is no product migration for
|
|
13
|
+
that unreleased storage format.
|
package/docs/release-process.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Release process
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
How a version reaches npm. What each shipped stable contains is
|
|
4
|
+
[Releases](handbook/releases/index.md); this document is the procedure only.
|
|
5
|
+
A release has no Starter/Landing checkout, tag, dispatch, credential or
|
|
6
|
+
deployment dependency.
|
|
7
7
|
|
|
8
8
|
## Authority and state transitions
|
|
9
9
|
|
|
@@ -15,9 +15,9 @@ No task implicitly authorizes publication; no manual package/tag writer exists.
|
|
|
15
15
|
|---|---|---|
|
|
16
16
|
| Reviewed source; unused version | Core source/packed-consumer gates, then immutable Core tag | Exact canonical merged PR SHA and version required |
|
|
17
17
|
| Tag exists; registry candidates partial | Existing npm/GPR publication steps | Verify existing artifact identity; publish missing versions only |
|
|
18
|
-
| Registry candidates verified | Public-registry reference consumer gate | No mutation; failure leaves public channels unchanged |
|
|
19
|
-
| Consumer passes |
|
|
20
|
-
| Channels promoted
|
|
18
|
+
| Registry candidates verified | Public-registry reference consumer gate | No mutation; failure leaves public channels and `mantle-release` unchanged |
|
|
19
|
+
| Consumer passes | That registry's promote step: monotonic channel add, then `dist-tag rm` of `mantle-release` only | Same version is a no-op; older runs cannot move a channel backward. Removal runs only after that package's promote loop, and only when `mantle-release` points at this version. A missing tag is a no-op. A tag pointing at another version is left for that version's promote step. `alpha` / `beta` / `rc` / `latest` are never removed |
|
|
20
|
+
| Channels promoted or preserved, and the temp tag cleared or left | GitHub release step | Existing release identity or fail |
|
|
21
21
|
|
|
22
22
|
The public-registry gate uses a disposable copy of the directly authored
|
|
23
23
|
`docs/examples/host-minimal-worker` reference, installs the exact candidate, then
|
|
@@ -39,9 +39,41 @@ foundational blocker returns to the state table and the user for a scope
|
|
|
39
39
|
decision instead of starting another local redesign loop.
|
|
40
40
|
|
|
41
41
|
Invariants: immutable versions/tags retain their identity; registry integrity
|
|
42
|
-
and the published-consumer gate precede public channel promotion
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
and the published-consumer gate precede public channel promotion and any
|
|
43
|
+
removal of `mantle-release` by the release controller; retries cannot move
|
|
44
|
+
channels backward. No downstream mutation, unpublish or rollback is
|
|
45
|
+
introduced. The runnable release-order check guards these transitions.
|
|
46
|
+
|
|
47
|
+
Mutation boundaries during a release: `Publish to npmjs` and `Mirror to
|
|
48
|
+
GitHub Packages` may attach `mantle-release` while publishing a version.
|
|
49
|
+
`Promote npmjs channel tags` is the only release step that moves npmjs
|
|
50
|
+
channels or removes that tag for the version being released. `Promote
|
|
51
|
+
GitHub Packages channel tags` is the only release step that does the same
|
|
52
|
+
for GitHub Packages. Recovery of a partial release reruns that same
|
|
53
|
+
controller and version. It does not call the cleanup workflow.
|
|
54
|
+
|
|
55
|
+
The cleanup workflow is a separate writer for one case the controller
|
|
56
|
+
cannot cover: a release commit that predates temp-tag removal still leaves
|
|
57
|
+
`mantle-release` behind, and a personal npm token that is `read-write` on
|
|
58
|
+
`npm access` can still receive 403 on dist-tag DELETE.
|
|
59
|
+
`.github/workflows/remove-mantle-release-dist-tag.yml` uses the Actions
|
|
60
|
+
`NPM_TOKEN` and `GITHUB_TOKEN`. It is not a release controller and not a
|
|
61
|
+
recovery path.
|
|
62
|
+
|
|
63
|
+
| State | Sole next writer | Retry / invariant |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| Leftover `mantle-release` after `alpha`, `beta`, `rc`, or `latest` already points at that version | `remove-mantle-release-dist-tag`, only when `confirm` is `remove-mantle-release` | Missing tag is a no-op. Only `mantle-release` is removed. Before and after dist-tags are printed and compared; every other tag is unchanged |
|
|
66
|
+
| `mantle-release` points at a version no consumer channel has | No deletion | The job fails and leaves the tag. Channel moves stay on the release promote step |
|
|
67
|
+
| Confirm string is anything else | No registry call | The job fails before reading or editing tags |
|
|
68
|
+
|
|
69
|
+
It shares the `release-controller` concurrency group with
|
|
70
|
+
`cancel-in-progress: false`, so it waits out an in-progress release instead
|
|
71
|
+
of deleting `mantle-release` between publish and channel promotion. After
|
|
72
|
+
this file is on `develop`:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
gh workflow run remove-mantle-release-dist-tag --ref develop -f confirm=remove-mantle-release
|
|
76
|
+
```
|
|
45
77
|
|
|
46
78
|
## Branches and channels
|
|
47
79
|
|
|
@@ -56,14 +88,17 @@ is introduced. The runnable release-order check guards these transitions.
|
|
|
56
88
|
`develop`, anything else means `main`. It refuses a commit that is not that
|
|
57
89
|
branch's tip or not the merge commit of exactly one PR into that branch.
|
|
58
90
|
`scripts/release-tag-order.mjs` rejects any other prerelease identifier.
|
|
59
|
-
- `develop`
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
91
|
+
- `develop` is where every change integrates first, so it is the base for all
|
|
92
|
+
work despite `main` being the repository's default branch on GitHub. `main`
|
|
93
|
+
changes only through promotion PRs and hotfix PRs (below); it is never pushed
|
|
94
|
+
directly, rebased or force-updated. Both branches share one ruleset: PR, one
|
|
95
|
+
approval, resolved threads and a current-base `Typecheck + tests` check.
|
|
96
|
+
- Stable is the only release that moves `latest`. A prerelease channel keeps
|
|
97
|
+
its last version when a later stable publishes.
|
|
98
|
+
- Publish uses `--tag mantle-release`, so publication does not move
|
|
99
|
+
`alpha`, `beta`, `rc`, or `latest`. After the public-registry consumer
|
|
100
|
+
gate, each registry's promote step moves the real channel and then removes
|
|
101
|
+
`mantle-release` when that tag points at this version.
|
|
67
102
|
|
|
68
103
|
## Prepare and run
|
|
69
104
|
|
|
@@ -84,7 +119,8 @@ is introduced. The runnable release-order check guards these transitions.
|
|
|
84
119
|
```
|
|
85
120
|
|
|
86
121
|
3. Review API compatibility and migration instructions for actual consumers.
|
|
87
|
-
Frozen legacy consumers stay on
|
|
122
|
+
Frozen legacy consumers stay on their pinned version; do not make them
|
|
123
|
+
follow new Core.
|
|
88
124
|
4. Run `pnpm check`, including exact packed Worker, optional products, Bun,
|
|
89
125
|
Vercel, skills, release invariants, types and tests. Inspect the umbrella
|
|
90
126
|
docs/skills payload: no workspace dependencies, secrets or local state.
|
|
@@ -94,7 +130,7 @@ is introduced. The runnable release-order check guards these transitions.
|
|
|
94
130
|
stable, continue with the promotion below. The controller refuses an
|
|
95
131
|
untagged source that is no longer the expected branch tip.
|
|
96
132
|
|
|
97
|
-
The
|
|
133
|
+
The eleven public packages remain in dependency order:
|
|
98
134
|
|
|
99
135
|
1. @aotter/mantle-spec
|
|
100
136
|
2. @aotter/mantle-admin-ui
|
|
@@ -102,10 +138,11 @@ The ten public packages remain in dependency order:
|
|
|
102
138
|
4. @aotter/mantle-indexeddb
|
|
103
139
|
5. @aotter/mantle-web
|
|
104
140
|
6. @aotter/mantle-admin
|
|
105
|
-
7. @aotter/mantle-
|
|
106
|
-
8. @aotter/mantle-
|
|
107
|
-
9. @aotter/mantle-
|
|
108
|
-
10. @aotter/mantle
|
|
141
|
+
7. @aotter/mantle-auth
|
|
142
|
+
8. @aotter/mantle-bun
|
|
143
|
+
9. @aotter/mantle-vercel
|
|
144
|
+
10. @aotter/mantle-cloudflare
|
|
145
|
+
11. @aotter/mantle
|
|
109
146
|
|
|
110
147
|
## Promote to main (beta, RC, stable)
|
|
111
148
|
|
|
@@ -113,9 +150,9 @@ Every non-alpha release is the version PR above, one promotion PR and one
|
|
|
113
150
|
dispatch. The version PR still merges into `develop`, so `develop` always
|
|
114
151
|
contains what `main` publishes and promotions never conflict.
|
|
115
152
|
|
|
116
|
-
1. Stable only: the release-gate issue
|
|
117
|
-
|
|
118
|
-
|
|
153
|
+
1. Stable only: the version's release-gate issue records owner acceptance.
|
|
154
|
+
Every gate item passes with linked evidence or is explicitly deferred
|
|
155
|
+
there, and no `release-gate` issue stays open against the version.
|
|
119
156
|
Beta and RC need the gate defined, not passed.
|
|
120
157
|
2. Merge the version PR into `develop` with a merge commit; note its SHA.
|
|
121
158
|
3. Pin the promotion head at that SHA so later `develop` merges cannot ride
|
|
@@ -148,18 +185,20 @@ the next promotion. Branch from `main`, include the version bump, PR into
|
|
|
148
185
|
and resolve version files in favour of `develop`. Until that lands, the next
|
|
149
186
|
promotion conflicts on the version files.
|
|
150
187
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
body is not an immutable artifact; the tag and packages are.
|
|
188
|
+
GitHub generates notes from the immediately previous tag, which for a stable
|
|
189
|
+
is usually its own last RC. To cover the whole line instead, regenerate from
|
|
190
|
+
the previous stable and edit the release body after the run. The body is not
|
|
191
|
+
an immutable artifact; the tag and packages are.
|
|
156
192
|
|
|
157
193
|
```sh
|
|
158
194
|
gh api repos/aotter/mantle/releases/generate-notes \
|
|
159
|
-
-f tag_name=
|
|
160
|
-
gh release edit
|
|
195
|
+
-f tag_name=v<version> -f previous_tag_name=v<previous stable> --jq .body > notes.md
|
|
196
|
+
gh release edit v<version> --notes-file notes.md
|
|
161
197
|
```
|
|
162
198
|
|
|
199
|
+
Add the version's entry to [Releases](handbook/releases/index.md) in the same
|
|
200
|
+
pass, so the handbook and the GitHub release describe the same thing.
|
|
201
|
+
|
|
163
202
|
After publication, move docs/examples that were pinned to a packed checkout
|
|
164
203
|
back to registry installation with an updated lockfile, and close the gate
|
|
165
204
|
issue with the run link and completion evidence.
|
|
@@ -171,12 +210,14 @@ tag/release and mirrors GitHub Packages. No cross-repository fanout token is
|
|
|
171
210
|
needed. Before tagging, verify credentials and new-version absence on both
|
|
172
211
|
registries. Existing artifacts on retry must have matching integrity.
|
|
173
212
|
|
|
174
|
-
Completion requires the Core tag SHA, all
|
|
213
|
+
Completion requires the Core tag SHA, all eleven npmjs/GPR packages, exact
|
|
175
214
|
integrity, no workspace dependencies, a passing public-registry Worker gate,
|
|
176
|
-
correct channel tags
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
215
|
+
correct channel tags, no `mantle-release` tag left on this version, and the
|
|
216
|
+
GitHub release. Retain run links and gate evidence.
|
|
217
|
+
This does not prove stable production soak or upgrade safety; the version's
|
|
218
|
+
release-gate issue owns those acceptance requirements. An agent acceptance run
|
|
219
|
+
uses only the version-matched authoring instructions, not an SDK checkout or
|
|
220
|
+
generated site.
|
|
180
221
|
|
|
181
222
|
## Recovery
|
|
182
223
|
|
|
@@ -6,7 +6,7 @@ Runtime. This Spec-only path is allowed by
|
|
|
6
6
|
[ADR-0019](adr/0019-sealed-manifest-runtime-pipeline.md), not a new adapter,
|
|
7
7
|
manifest grammar, or fork of Core.
|
|
8
8
|
|
|
9
|
-
This recipe targets `0.1.2`. Pin the package, record the tested version, and
|
|
9
|
+
This recipe targets `0.1.3-alpha.2`. Pin the package, record the tested version, and
|
|
10
10
|
rerun compatibility checks when upgrading.
|
|
11
11
|
|
|
12
12
|
## What stays with the host
|