@aotter/mantle 0.1.3 → 0.1.5-alpha.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/README.md +20 -20
- package/dist/cli/generate-cloudflare.d.ts +7 -0
- package/dist/cli/generate-cloudflare.d.ts.map +1 -0
- package/dist/cli/generate-cloudflare.js +123 -0
- package/dist/cli/generate-cloudflare.js.map +1 -0
- package/dist/cli/generate-project.d.ts +25 -0
- package/dist/cli/generate-project.d.ts.map +1 -0
- package/dist/cli/generate-project.js +282 -0
- package/dist/cli/generate-project.js.map +1 -0
- package/dist/cli/generate-sites.d.ts +8 -0
- package/dist/cli/generate-sites.d.ts.map +1 -0
- package/dist/cli/generate-sites.js +273 -0
- package/dist/cli/generate-sites.js.map +1 -0
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +121 -10
- 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 +11 -11
- package/dist/cli/skills.js +1 -1
- package/dist/cli/skills.js.map +1 -1
- package/docs/adr/0001-four-atom-manifest-model.md +3 -2
- package/docs/adr/0013-agent-provisioned-consumer-projects.md +4 -4
- package/docs/adr/0016-site-semantic-layer.md +5 -4
- package/docs/adr/0018-core-starters-repository-boundary.md +1 -1
- package/docs/adr/0021-retire-starter-scaffolding.md +1 -1
- package/docs/adr/0026-progressive-generate.md +36 -0
- package/docs/adr/0027-scheduled-procedure-triggers.md +31 -0
- package/docs/adr/0028-schema-ttl-expiry.md +33 -0
- package/docs/adr/README.md +7 -4
- package/docs/agent-prompts.md +41 -78
- package/docs/assets/mantle-admin-developer.png +0 -0
- package/docs/examples/README.md +1 -1
- package/docs/examples/host-chatgpt-sites/README.md +29 -12
- package/docs/examples/host-chatgpt-sites/drizzle/0003_store_instance_id.sql +1 -0
- package/docs/examples/host-chatgpt-sites/drizzle/0004_mantle.sql +10 -0
- package/docs/examples/host-chatgpt-sites/drizzle/0005_mantle.sql +24 -0
- package/docs/examples/host-chatgpt-sites/drizzle/meta/_journal.json +1 -1
- package/docs/examples/host-chatgpt-sites/drizzle/meta/mantle-state.json +60 -0
- package/docs/examples/host-chatgpt-sites/package.json +1 -1
- package/docs/examples/host-chatgpt-sites/public/site.css +1 -1
- package/docs/examples/host-chatgpt-sites/scripts/build.mjs +2 -1
- package/docs/examples/host-chatgpt-sites/scripts/check.mjs +2 -0
- package/docs/examples/host-chatgpt-sites/scripts/migration.mjs +42 -8
- package/docs/examples/host-chatgpt-sites/src/chatgpt-auth.ts +9 -6
- package/docs/examples/host-chatgpt-sites/src/index.ts +1 -1
- package/docs/examples/host-chatgpt-sites/src/web.ts +1 -1
- package/docs/examples/host-local-admin-otp/package.json +2 -2
- package/docs/examples/host-minimal-worker/README.md +5 -5
- package/docs/examples/host-minimal-worker/package.json +2 -2
- package/docs/handbook/{sites → chatgpt-sites}/equipment-checkout.md +1 -1
- package/docs/handbook/chatgpt-sites/generated-app.md +84 -0
- package/docs/handbook/{sites → chatgpt-sites}/index.md +35 -13
- package/docs/handbook/cloudflare/authentication.md +19 -2
- package/docs/handbook/cloudflare/bindings.md +4 -11
- package/docs/handbook/cloudflare/chatgpt-sites.md +6 -6
- package/docs/handbook/cloudflare/conventional-worker.md +7 -3
- package/docs/handbook/cloudflare/deploy-and-operate.md +4 -3
- package/docs/handbook/cloudflare/media-r2.md +2 -2
- package/docs/handbook/concepts/four-atoms.md +1 -1
- package/docs/handbook/concepts/lifecycle-and-locales.md +1 -1
- package/docs/handbook/concepts/mcp-and-agents.md +24 -4
- package/docs/handbook/concepts/procedures-and-triggers.md +1 -1
- package/docs/handbook/concepts/runtime-and-adapters.md +8 -1
- package/docs/handbook/concepts/views.md +1 -1
- package/docs/handbook/guides/agent-setup.md +8 -7
- package/docs/handbook/navigation.json +7 -6
- package/docs/handbook/reference/diagnostics.md +5 -0
- package/docs/handbook/reference/procedure.md +52 -1
- package/docs/handbook/reference/schema.md +27 -1
- package/docs/handbook/reference/surface.md +3 -3
- package/docs/handbook/reference/trigger.md +21 -1
- package/docs/handbook/releases/index.md +81 -1
- package/docs/handbook/start/overview.md +6 -3
- package/docs/handbook/start/project-and-cli.md +103 -119
- package/docs/handbook/start/quickstart-admin.md +6 -4
- package/docs/handbook/start/quickstart-worker.md +17 -11
- package/docs/release-process.md +3 -2
- package/docs/sealed-pipeline-ownership.md +1 -1
- package/docs/skills/develop/SKILL.md +258 -0
- package/docs/skills/integrate/SKILL.md +60 -0
- package/docs/skills/media-gc/SKILL.md +85 -0
- package/docs/skills/plugin/SKILL.md +132 -0
- package/docs/skills/provision/SKILL.md +194 -0
- package/docs/skills/theme/SKILL.md +77 -0
- package/docs/skills/update/SKILL.md +51 -0
- package/docs/spec-only-host-adoption.md +1 -1
- package/package.json +19 -18
- package/skills/README.md +28 -21
- package/skills/develop/SKILL.md +16 -8
- package/skills/install/SKILL.md +103 -128
- package/skills/integrate/SKILL.md +60 -0
- package/skills/media-gc/SKILL.md +2 -2
- package/skills/plugin/SKILL.md +2 -2
- package/skills/provision/SKILL.md +3 -3
- package/skills/theme/SKILL.md +2 -2
- package/skills/update/SKILL.md +2 -2
- package/templates/chatgpt-sites/auth.ts +66 -0
- package/templates/chatgpt-sites/build.mjs +14 -0
- package/templates/chatgpt-sites/env.ts +1 -0
- package/templates/chatgpt-sites/mcp.ts +48 -0
- package/templates/chatgpt-sites/public-mcp.ts +29 -0
- package/templates/chatgpt-sites/smoke-local.mjs +20 -0
- package/skills/.keep +0 -0
- /package/docs/handbook/{sites → chatgpt-sites}/host-reference.md +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: integrate
|
|
3
|
+
description: Integrate Mantle into an existing application. Use when the application has its own code, routes, storage or deployment and the owner wants to add Mantle, replace part of it, or rebuild with Mantle while migrating frontend and data.
|
|
4
|
+
metadata:
|
|
5
|
+
source: "@aotter/mantle"
|
|
6
|
+
sourcePath: docs/skills/integrate/SKILL.md
|
|
7
|
+
applies_to: mantle grammar v0.1
|
|
8
|
+
projection: package
|
|
9
|
+
projectionReason: Existing-project migration is opt-in; a fresh generated app does not need this brief.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Integrate Mantle into an existing application
|
|
13
|
+
|
|
14
|
+
Work in the target application. Read its installed `@aotter/mantle` version,
|
|
15
|
+
CLI help and package-local docs before editing. If Mantle is absent, inspect
|
|
16
|
+
the application first, then install an exact SDK version only after choosing an
|
|
17
|
+
integration strategy. Use the installed version's contract; do not copy
|
|
18
|
+
`develop` branch examples into an older consumer.
|
|
19
|
+
|
|
20
|
+
## Inspect and decide
|
|
21
|
+
|
|
22
|
+
Map the actual entry points, router, frontend, auth, storage, data volume and
|
|
23
|
+
relationships, deployment pipeline, URLs, background jobs and existing tests.
|
|
24
|
+
Identify which behavior the owner wants Mantle to own and what must remain
|
|
25
|
+
stable. Compare three approaches using the application's evidence:
|
|
26
|
+
|
|
27
|
+
1. **Embed selectively:** keep the host and call Mantle's parser, Runtime or
|
|
28
|
+
selected surfaces through its documented package APIs. The host owns wiring.
|
|
29
|
+
2. **Replace incrementally:** move one bounded capability at a time. Define
|
|
30
|
+
where reads and writes go during coexistence and how each step is checked.
|
|
31
|
+
3. **Rebuild and migrate:** create a separate new Mantle application, port the
|
|
32
|
+
frontend and business behavior, and transform/import existing data. Prefer
|
|
33
|
+
this when adapting the old structure costs more than rebuilding. Preserve
|
|
34
|
+
relevant IDs, relations, URLs and identity semantics; rehearse the data
|
|
35
|
+
transfer before a production cutover.
|
|
36
|
+
|
|
37
|
+
Explain the chosen path and its concrete tradeoffs to the owner. A small
|
|
38
|
+
prototype or read-only inventory may resolve uncertainty. Do not run a generic
|
|
39
|
+
project converter or assume the current application's shape matches a
|
|
40
|
+
generated Cloudflare or ChatGPT Sites skeleton.
|
|
41
|
+
|
|
42
|
+
## Implement and verify
|
|
43
|
+
|
|
44
|
+
- For embedding, retain user-owned entry/config/build files. Use the installed
|
|
45
|
+
direct-authoring docs and CLI to validate manifests and emit bindings; wire
|
|
46
|
+
the selected Mantle capabilities into the existing host explicitly.
|
|
47
|
+
- For incremental replacement, establish a clear owner for each data write
|
|
48
|
+
and request route at every stage. Verify old and new behavior together.
|
|
49
|
+
- For rebuilding, generate in a **separate directory** with the installed
|
|
50
|
+
CLI, move frontend and handlers deliberately, and plan data mapping and
|
|
51
|
+
import separately. Review database migrations before application or cutover.
|
|
52
|
+
- Run the application's build and representative behavior checks for the
|
|
53
|
+
changed routes, auth and data. `mantle generate --check` checks generated
|
|
54
|
+
output against its declared selection; it cannot certify host integration.
|
|
55
|
+
For live data, record migration counts and a rollback or recovery path
|
|
56
|
+
appropriate to the project.
|
|
57
|
+
|
|
58
|
+
Leave existing data and deployment untouched until the requested migration
|
|
59
|
+
and release steps are ready. Report which capabilities Mantle now owns,
|
|
60
|
+
what was verified, and what remains for application deployment or cutover.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: media-gc
|
|
3
|
+
description: Audit and safely remove stale, uncommitted public media uploads from a Mantle Cloudflare R2 bucket. Use when a Mantle operator asks to inspect or clean orphan media objects left after create_media_upload without commit_media_upload.
|
|
4
|
+
metadata:
|
|
5
|
+
source: "@aotter/mantle"
|
|
6
|
+
sourcePath: docs/skills/media-gc/SKILL.md
|
|
7
|
+
applies_to: mantle grammar v0.1
|
|
8
|
+
projection: package
|
|
9
|
+
projectionReason: Destructive remote object deletion and Cloudflare-specific; opt-in only.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Mantle Media GC
|
|
13
|
+
|
|
14
|
+
Use the connected Cloudflare API. Audit by default; delete only the exact
|
|
15
|
+
objects approved by the user.
|
|
16
|
+
|
|
17
|
+
## Preflight
|
|
18
|
+
|
|
19
|
+
1. Read the project's Wrangler config and Mantle config. Resolve the R2 bucket
|
|
20
|
+
binding, bucket name, and declared public media purpose names.
|
|
21
|
+
2. Confirm the exact Cloudflare account and bucket. If either is ambiguous,
|
|
22
|
+
ask; never choose by name similarity.
|
|
23
|
+
3. Use the Cloudflare OpenAPI search before execution to resolve the current
|
|
24
|
+
R2 List Objects and Delete Objects endpoints. If the connected account lacks
|
|
25
|
+
access, stop. Do not create, request, or store credentials.
|
|
26
|
+
4. Stop when the project has no public R2 media binding or no declared purpose.
|
|
27
|
+
|
|
28
|
+
## Audit
|
|
29
|
+
|
|
30
|
+
For each declared purpose, list up to 1,000 objects per page under the exact
|
|
31
|
+
`<purpose>/` prefix. Use the API cursor until `is_truncated` is false.
|
|
32
|
+
|
|
33
|
+
An object is a deletion candidate only when all conditions hold:
|
|
34
|
+
|
|
35
|
+
- `last_modified` is more than 24 hours old;
|
|
36
|
+
- `custom_metadata.committedAt` is absent or empty;
|
|
37
|
+
- the key matches the exact Mantle layout
|
|
38
|
+
`<purpose>/<group>/(primary|alternate|fallback).(png|jpg|webp|avif|gif|svg)`,
|
|
39
|
+
where `<purpose>` is declared by this project and `<group>` contains only
|
|
40
|
+
letters, digits, `_`, or `-`.
|
|
41
|
+
|
|
42
|
+
Skip committed, unknown-prefix, unprefixed, malformed, or ambiguous objects.
|
|
43
|
+
Delete only an uncommitted variant, never its whole group.
|
|
44
|
+
|
|
45
|
+
Report the account, bucket, purpose prefixes, UTC cutoff, candidate object and
|
|
46
|
+
group counts, total bytes, skipped count, and a SHA-256 digest of the sorted
|
|
47
|
+
`key + etag` candidate set. Do not print object keys, upload group IDs,
|
|
48
|
+
filenames, public URLs, signed URLs, or secrets.
|
|
49
|
+
|
|
50
|
+
## Apply
|
|
51
|
+
|
|
52
|
+
1. Show the audit summary and get explicit confirmation for that exact account,
|
|
53
|
+
bucket, cutoff, count, byte total, and candidate-set digest.
|
|
54
|
+
2. Re-run the complete audit with the same UTC cutoff. If the candidate count,
|
|
55
|
+
bytes, or digest changed, stop and present the new audit for confirmation.
|
|
56
|
+
3. Call Delete Objects with JSON arrays of exact keys, at most 1,000 keys per
|
|
57
|
+
request. Never send the `prefix` query parameter: an empty prefix can empty
|
|
58
|
+
the bucket.
|
|
59
|
+
4. Do not automatically retry failed keys. Report safe API error codes and
|
|
60
|
+
counts; a later invocation can audit and retry what remains.
|
|
61
|
+
5. Re-list every inspected purpose prefix and report the remaining candidate
|
|
62
|
+
count and bytes.
|
|
63
|
+
|
|
64
|
+
## Don't
|
|
65
|
+
|
|
66
|
+
- Don't create a Worker, Cron Trigger, lifecycle rule, D1 table, or local script.
|
|
67
|
+
- Don't use prefix deletion or empty-bucket operations.
|
|
68
|
+
- Don't delete private-media buckets or objects outside declared purpose
|
|
69
|
+
prefixes.
|
|
70
|
+
- Don't treat missing pagination pages, metadata, or permissions as an empty
|
|
71
|
+
result.
|
|
72
|
+
|
|
73
|
+
## Diagnostics
|
|
74
|
+
|
|
75
|
+
| Symptom | Action |
|
|
76
|
+
|---|---|
|
|
77
|
+
| Multiple matching accounts or buckets | Stop and ask the user to select the exact target. |
|
|
78
|
+
| A page is truncated without a cursor | Stop; do not delete from a partial audit. |
|
|
79
|
+
| A candidate has an unexpected key or metadata shape | Skip it and include it only in the aggregate skipped count. |
|
|
80
|
+
| A delete request partially fails | Report safe error codes and leave the remaining objects for a later audit. |
|
|
81
|
+
|
|
82
|
+
## When You're Done
|
|
83
|
+
|
|
84
|
+
Return whether the run was audit-only or applied, the aggregate before/after
|
|
85
|
+
counts and bytes, and any safely redacted failures.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plugin
|
|
3
|
+
description: Discover, plan, apply, and verify Mantle marketplace plugins through the Core SDK contract. Use when the user wants to add an installable capability without hand-planning provisioning steps.
|
|
4
|
+
metadata:
|
|
5
|
+
source: "@aotter/mantle"
|
|
6
|
+
sourcePath: docs/skills/plugin/SKILL.md
|
|
7
|
+
applies_to: mantle grammar v0.1
|
|
8
|
+
projection: project
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Mantle Plugin
|
|
12
|
+
|
|
13
|
+
Mantle plugins are Core SDK capability packages. They are not application
|
|
14
|
+
scaffolds (retired in ADR-0021) and they are not provider provisioning scripts.
|
|
15
|
+
|
|
16
|
+
A plugin may contribute:
|
|
17
|
+
|
|
18
|
+
- manifests: `Schema`, `View`, `Procedure`, `Trigger`;
|
|
19
|
+
- handler source or handler registration notes;
|
|
20
|
+
- site defaults or media policy additions;
|
|
21
|
+
- expected HTTP, admin, and MCP surfaces;
|
|
22
|
+
- adapter capability requirements and provider setup notes.
|
|
23
|
+
|
|
24
|
+
## User Install Entry
|
|
25
|
+
|
|
26
|
+
The user-facing install path is:
|
|
27
|
+
|
|
28
|
+
```txt
|
|
29
|
+
Use repo-local mantle:plugin to install <plugin slug or recipe URL> in this repo.
|
|
30
|
+
Use repo-local mantle:plugin to update <plugin id> in this repo.
|
|
31
|
+
Use repo-local mantle:plugin to remove <plugin id> from this repo.
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
There is no `mantle plugin add` CLI yet. Do not invent one. Install from a
|
|
35
|
+
marketplace entry, plugin package, or recipe URL that declares enough data for
|
|
36
|
+
an agent to apply the capability deterministically.
|
|
37
|
+
|
|
38
|
+
A valid marketplace entry must include:
|
|
39
|
+
|
|
40
|
+
- plugin id, title, source, and version;
|
|
41
|
+
- supported Mantle version range;
|
|
42
|
+
- files, manifests, handlers, routes, MCP tools, and admin surfaces it adds;
|
|
43
|
+
- adapter capabilities and provider resources it requires;
|
|
44
|
+
- required env vars and secrets, without secret values;
|
|
45
|
+
- verification commands and expected surfaces.
|
|
46
|
+
|
|
47
|
+
If the marketplace page is only marketing copy or lacks an install recipe,
|
|
48
|
+
stop and ask for the recipe instead of guessing.
|
|
49
|
+
|
|
50
|
+
## First Read
|
|
51
|
+
|
|
52
|
+
1. `package.json` for Mantle version and adapter package.
|
|
53
|
+
2. The manifest directory selected by project scripts for current atom names
|
|
54
|
+
and route/tool collisions.
|
|
55
|
+
3. The actual host entry and its handler, template and port registrations;
|
|
56
|
+
`src/mantle/config.ts` and `src/mantle/handlers/` are conventions, not required paths.
|
|
57
|
+
4. `.mantle/plugins.json` and `.mantle/plugins.lock.json` if present.
|
|
58
|
+
5. `.mantle/launch-state.json` only as context, not as plugin authority.
|
|
59
|
+
|
|
60
|
+
Read version-matched contracts under `node_modules/@aotter/mantle/docs/`,
|
|
61
|
+
starting with `handbook/reference/features.md`. Plugin recipes cannot override
|
|
62
|
+
the installed grammar.
|
|
63
|
+
|
|
64
|
+
## Plan First
|
|
65
|
+
|
|
66
|
+
Before applying any plugin, produce a plan:
|
|
67
|
+
|
|
68
|
+
- files to add or change;
|
|
69
|
+
- atoms to add and their names;
|
|
70
|
+
- HTTP routes and MCP tools that will appear;
|
|
71
|
+
- required runtime ports;
|
|
72
|
+
- adapter-specific resources, env vars, and secrets;
|
|
73
|
+
- checks to run.
|
|
74
|
+
|
|
75
|
+
If the plugin needs a capability the current adapter does not expose, stop
|
|
76
|
+
with the missing capability instead of inventing provider steps.
|
|
77
|
+
|
|
78
|
+
## Apply
|
|
79
|
+
|
|
80
|
+
Apply the smallest deterministic diff. Do not run arbitrary install scripts
|
|
81
|
+
from a plugin package. Copy declared files, wire declared handlers, update the
|
|
82
|
+
plugin ledger, then validate.
|
|
83
|
+
|
|
84
|
+
Suggested ledger paths:
|
|
85
|
+
|
|
86
|
+
```txt
|
|
87
|
+
.mantle/plugins.json
|
|
88
|
+
.mantle/plugins.lock.json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Keep optional legacy launch files such as `.mantle/features.json` separate from
|
|
92
|
+
plugin state. They are not the Core plugin ledger.
|
|
93
|
+
|
|
94
|
+
## Update
|
|
95
|
+
|
|
96
|
+
Compare the installed lock entry against the marketplace entry or recipe URL.
|
|
97
|
+
Apply only the declared version diff, update `.mantle/plugins.lock.json`, then
|
|
98
|
+
run the same verification checks.
|
|
99
|
+
|
|
100
|
+
## Remove
|
|
101
|
+
|
|
102
|
+
Use the lock entry as the removal manifest. Delete only files and atoms owned
|
|
103
|
+
by that plugin, unwind handler registrations it added, remove its ledger entry,
|
|
104
|
+
then validate. If another plugin or local code depends on a removed atom, stop
|
|
105
|
+
and report the dependency instead of deleting through it.
|
|
106
|
+
|
|
107
|
+
## Verify
|
|
108
|
+
|
|
109
|
+
Use the project's validation and typecheck scripts when present. Regenerate
|
|
110
|
+
the plan after manifest changes before probing the running host:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pnpm exec mantle validate
|
|
114
|
+
pnpm exec mantle generate
|
|
115
|
+
pnpm exec mantle generate --check
|
|
116
|
+
# Run the project's TypeScript check and restart its local server.
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Then verify the plugin's declared surfaces:
|
|
120
|
+
|
|
121
|
+
- public Views via `GET /api/views/<name>`, staff Views via authenticated
|
|
122
|
+
Admin/staff MCP, and internal Views through the host binding;
|
|
123
|
+
- HTTP Trigger path for public writes;
|
|
124
|
+
- Staff/Public MCP `tools/list` for MCP Trigger or Schema-derived tools;
|
|
125
|
+
- adapter resource presence when the plugin requires optional ports.
|
|
126
|
+
|
|
127
|
+
## Don't
|
|
128
|
+
|
|
129
|
+
- Don't treat an application template as a plugin.
|
|
130
|
+
- Don't assume Cloudflare; inspect the active adapter and capability ports.
|
|
131
|
+
- Don't create a second skill namespace for host-specific plugins.
|
|
132
|
+
- Don't commit secrets. Provider secrets stay in the platform secret store.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: provision
|
|
3
|
+
description: Ship a Mantle project through its selected host, routing ChatGPT Sites to its integration guide and conventional Cloudflare Workers to production auth and provisioning.
|
|
4
|
+
metadata:
|
|
5
|
+
source: "@aotter/mantle"
|
|
6
|
+
sourcePath: docs/skills/provision/SKILL.md
|
|
7
|
+
applies_to: mantle grammar v0.1
|
|
8
|
+
projection: package
|
|
9
|
+
projectionReason: Platform-specific deploy that handles production secrets; opt-in only.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Provision a Mantle Project
|
|
13
|
+
|
|
14
|
+
Local cold start deliberately stops before this skill. Provision only after the
|
|
15
|
+
user asks to create remote resources or ship production. This flow is for
|
|
16
|
+
consumer-owned Cloudflare Workers. New direct-authored apps do not need Landing
|
|
17
|
+
artifacts (`.mantle/launch-state.json`, `.mantle/handoff.md`, or a hosted-auth
|
|
18
|
+
allocation). Treat any Landing handoff as **legacy/optional**. For a ChatGPT
|
|
19
|
+
Site, use the installed `docs/handbook/chatgpt-sites/index.md` integration guide and
|
|
20
|
+
the "Publish with Sites" steps in `docs/examples/host-chatgpt-sites/README.md`:
|
|
21
|
+
request D1 and R2 on the Site, set `PUBLIC_ORIGIN` and `OWNER_EMAIL` in Sites
|
|
22
|
+
settings, review the migration, then save and deploy a Sites version. Do not
|
|
23
|
+
run `wrangler deploy` or require R2 S3 credentials merely because Sites exposes
|
|
24
|
+
an R2 binding.
|
|
25
|
+
|
|
26
|
+
## Source of Truth
|
|
27
|
+
|
|
28
|
+
1. Read the actual provider config (`wrangler.jsonc` or `wrangler.toml`),
|
|
29
|
+
application entry and git remotes. Read legacy `.mantle/launch-state.json`
|
|
30
|
+
and `.mantle/handoff.md` only when present; they are optional leftovers from
|
|
31
|
+
Landing and must not be created as prerequisites for a new app.
|
|
32
|
+
2. Read installed `@aotter/mantle*` versions from `package.json`.
|
|
33
|
+
3. Use matching embedded docs under `node_modules/@aotter/mantle/docs/`.
|
|
34
|
+
4. Never infer provider authority from launch state. Confirm the active GitHub
|
|
35
|
+
and Cloudflare accounts before changing them.
|
|
36
|
+
|
|
37
|
+
Run the local gate first:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pnpm install --frozen-lockfile
|
|
41
|
+
pnpm validate
|
|
42
|
+
pnpm typecheck
|
|
43
|
+
git status --short
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Resume From Observed State
|
|
47
|
+
|
|
48
|
+
Do not branch on how the project was created. Verify these facts and skip
|
|
49
|
+
completed work:
|
|
50
|
+
|
|
51
|
+
1. `git remote get-url origin` confirms the GitHub repo.
|
|
52
|
+
2. An HTTPS `PUBLIC_ORIGIN` that responds confirms the Cloudflare deploy.
|
|
53
|
+
3. `/admin/sign-in` returning `503 setup_incomplete` means auth is not bound.
|
|
54
|
+
Use the recorded auth intent only to choose hosted or self-hosted setup;
|
|
55
|
+
live behavior is authoritative.
|
|
56
|
+
|
|
57
|
+
If there is no remote, confirm the target account, create a private repo,
|
|
58
|
+
commit, and push `main`. If there is no live Worker, confirm the Cloudflare
|
|
59
|
+
account, prefer an available connector, or use `pnpm exec wrangler login` with
|
|
60
|
+
the user's agreement, then run `pnpm deploy`.
|
|
61
|
+
|
|
62
|
+
Capture the live URL in `PUBLIC_ORIGIN` and `Public site:` in `AGENTS.md`, then
|
|
63
|
+
commit and push non-secret changes. Reuse any repo or Worker already created.
|
|
64
|
+
Do not recreate Landing artifacts for a new direct-authored app. Workers Builds
|
|
65
|
+
is optional after a direct deploy.
|
|
66
|
+
|
|
67
|
+
When the owner later adopts a custom domain, update `PUBLIC_ORIGIN` and the
|
|
68
|
+
provider's OAuth callback together, then redeploy. Do not patch `site_config`
|
|
69
|
+
directly; boot syncs its canonical origin from `PUBLIC_ORIGIN`.
|
|
70
|
+
|
|
71
|
+
## Choose Auth
|
|
72
|
+
|
|
73
|
+
- **Self-hosted email OTP:** use the application's production transactional-email sender. Replace `ConsoleEmailSender`; never deploy it.
|
|
74
|
+
- **Self-hosted GitHub OAuth — free fallback:** use when the application has no email provider. Configure the owner's per-site GitHub OAuth App and Worker secrets using the steps below.
|
|
75
|
+
- **Mantle hosted auth — paid, legacy/optional:** use only when a **legacy
|
|
76
|
+
Landing handoff** already records a hosted allocation and client
|
|
77
|
+
configuration. New direct-authored apps do not get this from Core. Mantle
|
|
78
|
+
Platform operates the identity provider; do not ask the user for a per-site
|
|
79
|
+
GitHub OAuth App.
|
|
80
|
+
|
|
81
|
+
Configure only the selected mode. Core deliberately rejects partial or mixed
|
|
82
|
+
hosted/self-managed bindings with `503 setup_incomplete`.
|
|
83
|
+
|
|
84
|
+
Do not claim that hosted auth can attach to an arbitrary local repo unless a
|
|
85
|
+
legacy Landing handoff already supplies that configuration.
|
|
86
|
+
|
|
87
|
+
For the exact boundary, read
|
|
88
|
+
`node_modules/@aotter/mantle/docs/auth-hosting-model.md`.
|
|
89
|
+
|
|
90
|
+
## Self-hosted email OTP
|
|
91
|
+
|
|
92
|
+
Keep the application's custom `createAuth()` factory, replace
|
|
93
|
+
`ConsoleEmailSender` with its production `EmailSender`, and retain
|
|
94
|
+
`bootstrapOwner: { match: "email", value: <owner email> }`. Store sender
|
|
95
|
+
credentials and `BETTER_AUTH_SECRET` as Worker secrets, put `PUBLIC_ORIGIN` in
|
|
96
|
+
non-secret vars, deploy, then verify that the owner receives an OTP at
|
|
97
|
+
`/admin/sign-in`. If there is no production email provider, use GitHub OAuth
|
|
98
|
+
below instead of deploying console delivery.
|
|
99
|
+
|
|
100
|
+
## Self-hosted GitHub OAuth
|
|
101
|
+
|
|
102
|
+
1. Ask the user to create a GitHub OAuth App:
|
|
103
|
+
|
|
104
|
+
- Homepage URL: `<worker-url>`
|
|
105
|
+
- Authorization callback URL: `<worker-url>/api/auth/callback/github`
|
|
106
|
+
- Device Flow: unchecked
|
|
107
|
+
|
|
108
|
+
2. Put non-secret values in `wrangler.toml`:
|
|
109
|
+
|
|
110
|
+
- `MANTLE_AUTH_MODE = "self-managed"`
|
|
111
|
+
- `PUBLIC_ORIGIN`
|
|
112
|
+
- `GITHUB_CLIENT_ID`
|
|
113
|
+
- `ADMIN_GITHUB_LOGIN`
|
|
114
|
+
- correct Worker `name`
|
|
115
|
+
|
|
116
|
+
Remove `MANTLE_HOSTED_AUTH_ISSUER` and `MANTLE_HOSTED_AUTH_CLIENT_ID` if they
|
|
117
|
+
were present for a hosted allocation.
|
|
118
|
+
|
|
119
|
+
3. Keep the Client Secret out of chat. Prefer a Cloudflare connector for
|
|
120
|
+
secrets; otherwise use hidden shell input:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
read -rsp "GitHub OAuth client secret: " MANTLE_GITHUB_CLIENT_SECRET && printf "\n"
|
|
124
|
+
printf '%s' "$MANTLE_GITHUB_CLIENT_SECRET" | pnpm exec wrangler secret put GITHUB_CLIENT_SECRET
|
|
125
|
+
openssl rand -hex 32 | pnpm exec wrangler secret put BETTER_AUTH_SECRET
|
|
126
|
+
unset MANTLE_GITHUB_CLIENT_SECRET
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Set `BETTER_AUTH_SECRET` once and preserve it. Rotating it invalidates existing
|
|
130
|
+
sessions.
|
|
131
|
+
|
|
132
|
+
4. Commit and push only non-secret config, then redeploy:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
git add wrangler.toml AGENTS.md
|
|
136
|
+
git commit -m "mantle: wire production auth"
|
|
137
|
+
git push
|
|
138
|
+
pnpm deploy
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Hosted Auth (legacy Landing)
|
|
142
|
+
|
|
143
|
+
Skip this section unless a legacy Landing handoff is already present. New
|
|
144
|
+
direct-authored apps use self-hosted email OTP or GitHub OAuth above.
|
|
145
|
+
|
|
146
|
+
Follow that handoff and its client configuration. Hosted configuration remains
|
|
147
|
+
in landing-managed Cloudflare Worker bindings. Verify:
|
|
148
|
+
|
|
149
|
+
- `MANTLE_AUTH_MODE = "hosted"`;
|
|
150
|
+
- `MANTLE_HOSTED_AUTH_ISSUER` is the HTTPS root issuer;
|
|
151
|
+
- `MANTLE_HOSTED_AUTH_CLIENT_ID` is the same-origin `/clients/<id>` URL;
|
|
152
|
+
- `PUBLIC_ORIGIN` and `ADMIN_GITHUB_LOGIN` are set;
|
|
153
|
+
- `BETTER_AUTH_SECRET` exists as a Worker secret;
|
|
154
|
+
- `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` are absent.
|
|
155
|
+
|
|
156
|
+
Hosted clients use PKCE and have no client secret. Do not write secrets into
|
|
157
|
+
`wrangler.toml`.
|
|
158
|
+
|
|
159
|
+
Verify that admin sign-in redirects to Mantle Hosted Auth and Staff MCP
|
|
160
|
+
authenticates, then skip the self-hosted flow.
|
|
161
|
+
|
|
162
|
+
## Smoke Test
|
|
163
|
+
|
|
164
|
+
- public home route;
|
|
165
|
+
- `/admin/sign-in`;
|
|
166
|
+
- selected admin sign-in path;
|
|
167
|
+
- `/mcp/staff` with an agent client when available;
|
|
168
|
+
- one type-specific core workflow.
|
|
169
|
+
|
|
170
|
+
Media uploads are optional. Configure R2 only when the owner asks for
|
|
171
|
+
staff-managed files; then read
|
|
172
|
+
`node_modules/@aotter/mantle/docs/handbook/cloudflare/media-r2.md`.
|
|
173
|
+
|
|
174
|
+
## Handoff
|
|
175
|
+
|
|
176
|
+
Return:
|
|
177
|
+
|
|
178
|
+
- public URL;
|
|
179
|
+
- admin sign-in URL;
|
|
180
|
+
- Staff MCP URL;
|
|
181
|
+
- operator setup URL:
|
|
182
|
+
`https://mantle.tools/connect?site=<url-encoded-worker-url>`;
|
|
183
|
+
- remote resources created or reused;
|
|
184
|
+
- auth mode and any intentionally deferred setup.
|
|
185
|
+
|
|
186
|
+
## Don't
|
|
187
|
+
|
|
188
|
+
- Don't create remote resources before the user asks to ship.
|
|
189
|
+
- Don't ask for a Cloudflare API token in the base flow.
|
|
190
|
+
- Don't commit provider secrets.
|
|
191
|
+
- Don't require R2 for first production.
|
|
192
|
+
- Don't invent a second provision orchestrator.
|
|
193
|
+
- Don't use `/admin/auth/github/callback`; the callback is
|
|
194
|
+
`/api/auth/callback/github`.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: theme
|
|
3
|
+
description: Apply brand and visual direction in a Mantle application using its repo-owned theme and UI contracts.
|
|
4
|
+
metadata:
|
|
5
|
+
source: "@aotter/mantle"
|
|
6
|
+
sourcePath: docs/skills/theme/SKILL.md
|
|
7
|
+
applies_to: mantle grammar v0.1
|
|
8
|
+
projection: project
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Mantle Theme
|
|
12
|
+
|
|
13
|
+
Theme work is project-owned source editing. Use the actual frontend and its
|
|
14
|
+
tokens/recipes; Core does not install a default home page or UI tree.
|
|
15
|
+
|
|
16
|
+
For requests to change the Admin console, first read installed
|
|
17
|
+
`node_modules/@aotter/mantle/docs/handbook/guides/admin-ui.md` and use the
|
|
18
|
+
develop skill. Labels, widgets, list columns, filters and actions may already
|
|
19
|
+
be manifest-driven. Visitor CSS does not style the prebuilt Admin SPA, and
|
|
20
|
+
`uiSchema` does not accept arbitrary CSS, components or layout keys.
|
|
21
|
+
|
|
22
|
+
## First Read
|
|
23
|
+
|
|
24
|
+
1. `.mantle/handoff.md` and `.mantle/recipes/` if present.
|
|
25
|
+
2. `styles/`, `components/`, `src/web/`, `src/theme*`, and UI-library config
|
|
26
|
+
if present.
|
|
27
|
+
3. A vendored UI palette's manifest and license, if present.
|
|
28
|
+
4. The manifest directory selected by project scripts to understand which
|
|
29
|
+
content shape drives the public UI.
|
|
30
|
+
|
|
31
|
+
## Ownership
|
|
32
|
+
|
|
33
|
+
- Use the actual token contract (for example `styles/globals.css`) when present.
|
|
34
|
+
Check its light/dark values before changing components.
|
|
35
|
+
- `components/` is the runtime-facing component surface when present.
|
|
36
|
+
`src/web/` is project-owned composition; put new sections there.
|
|
37
|
+
- `public/site-icon.svg` and `public/site-icon.png` are one site identity.
|
|
38
|
+
Keep both listed in the actual entry/config `siteDefaults.icons`: PNG first as
|
|
39
|
+
the 64x64 compatibility rendition, then SVG as the editable `any` size source.
|
|
40
|
+
The same list drives browser favicons, Admin chrome, and MCP
|
|
41
|
+
`serverInfo.icons`; do not edit generated files under `public/_mantle/`.
|
|
42
|
+
- If the project includes a vendored UI reference palette, treat it as
|
|
43
|
+
offline source material and provenance, not runtime source. Copy only a
|
|
44
|
+
needed primitive or block into the project's runtime directories, or
|
|
45
|
+
fork/wrap it under `src/web/sections/`; do not import the palette from
|
|
46
|
+
Worker or runtime code.
|
|
47
|
+
|
|
48
|
+
## Work
|
|
49
|
+
|
|
50
|
+
- Use existing tokens, CSS, components, and installed dependencies first.
|
|
51
|
+
- When replacing the site mark, regenerate PNG from the same SVG artwork so
|
|
52
|
+
every surface presents the same identity. Check it at the Admin's 28px slot
|
|
53
|
+
in both light and dark themes; a single high-contrast rendition is preferred
|
|
54
|
+
over theme-specific variants unless the artwork genuinely needs both.
|
|
55
|
+
- For a standard hero image, set the section's `image: { src, alt }`; use
|
|
56
|
+
`showImage: false` for text-only hero/content blocks. Put non-image media in
|
|
57
|
+
a project-owned section.
|
|
58
|
+
- Keep accessibility basics: semantic HTML, focus states, contrast, and
|
|
59
|
+
keyboard reachability. Against a non-default background, check
|
|
60
|
+
`--foreground-muted` and `--primary`, not only `--foreground`; keep normal
|
|
61
|
+
text at 4.5:1 or better.
|
|
62
|
+
- Do not require registry access for a project that already vendors UI source.
|
|
63
|
+
- Add UI dependencies only when existing source cannot cover the requested
|
|
64
|
+
change.
|
|
65
|
+
|
|
66
|
+
## Check
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pnpm validate
|
|
70
|
+
pnpm typecheck
|
|
71
|
+
pnpm dev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If utility classes changed, rebuild `styles/generated.css` with the project's
|
|
75
|
+
`build:styles`, `check`, or `dev` script. Remove routes/imports for replaced
|
|
76
|
+
assets or styles, then visually verify light/dark contrast and responsive
|
|
77
|
+
behavior before calling the work done.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: update
|
|
3
|
+
description: Review and upgrade Mantle SDK dependencies and project-local skills while preserving application source, provider identities and plugin lockfiles.
|
|
4
|
+
metadata:
|
|
5
|
+
source: "@aotter/mantle"
|
|
6
|
+
sourcePath: docs/skills/update/SKILL.md
|
|
7
|
+
applies_to: mantle grammar v0.1
|
|
8
|
+
projection: project
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Mantle Update
|
|
12
|
+
|
|
13
|
+
Upgrade SDK dependencies deliberately; never overwrite application-owned code.
|
|
14
|
+
The old Starter bundle comparison command `mantle update` is removed. This
|
|
15
|
+
skill remains the version-matched upgrade workflow, not a replacement CLI.
|
|
16
|
+
|
|
17
|
+
1. Inspect git status, package.json, lockfile, actual project scripts and
|
|
18
|
+
installed versions. Preserve unrelated local changes. Read plugin locks
|
|
19
|
+
and legacy `.mantle` metadata if present; they are context, not required.
|
|
20
|
+
2. Select an explicit target release and read that version's GitHub release
|
|
21
|
+
notes. Installed docs live under `node_modules/@aotter/mantle/docs/`;
|
|
22
|
+
`handbook/releases/index.md` is a stable-release index, so a prerelease
|
|
23
|
+
need not appear there. Do not use the old package's docs as the new API contract.
|
|
24
|
+
Do not resolve new Starter refs or compare the project to a baseline
|
|
25
|
+
template.
|
|
26
|
+
3. Update only selected `@aotter/mantle*` dependencies to the same exact target
|
|
27
|
+
version, preserving dependency sections. Use the package manager to update
|
|
28
|
+
the lockfile; inspect the dependency diff and required peer changes.
|
|
29
|
+
4. Remove scripts that invoke retired create/bundle-update commands. Keep all
|
|
30
|
+
application manifests, handlers, routes, theme, Worker/D1/KV names, origins,
|
|
31
|
+
provider bindings, secrets, and legacy metadata. Apply API migration edits
|
|
32
|
+
individually; do not copy the reference consumer over a real application.
|
|
33
|
+
5. Use the upgraded package to regenerate machine-owned bindings and project
|
|
34
|
+
its skills, then run the application's validation, types and tests:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
pnpm exec mantle generate
|
|
38
|
+
pnpm exec mantle generate --check
|
|
39
|
+
pnpm exec mantle skills
|
|
40
|
+
pnpm exec mantle skills --check
|
|
41
|
+
pnpm exec mantle validate
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Read the refreshed `mantle-develop` skill and the upgraded package's embedded
|
|
45
|
+
docs before continuing application edits.
|
|
46
|
+
|
|
47
|
+
Start the local application and test its actual routes, including configured
|
|
48
|
+
auth behavior. Review the final source/lockfile/generated diff; unexpected
|
|
49
|
+
provider or user-source changes block completion. Provider credentials must
|
|
50
|
+
never enter git or logs. Report exact old/new versions, checks, and remaining
|
|
51
|
+
migration work. A dependency update does not authorize a production deploy.
|
|
@@ -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.
|
|
9
|
+
This recipe targets `0.1.4`. Pin the package, record the tested version, and
|
|
10
10
|
rerun compatibility checks when upgrading.
|
|
11
11
|
|
|
12
12
|
## What stays with the host
|