@aotter/mantle 0.1.2-alpha.6 → 0.1.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 +15 -10
- package/dist/cli/generate.d.ts +9 -0
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +40 -1
- 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 +37 -9
- package/dist/cli/main.js.map +1 -1
- package/docs/adapter-guide.md +6 -1
- package/docs/adr/adr-lite-845-frontend-client.md +38 -0
- package/docs/agent-prompts.md +91 -0
- package/docs/api-mcp-authorization.md +1 -1
- package/docs/auth-hosting-model.md +1 -1
- package/docs/examples/README.md +22 -0
- package/docs/examples/builtin-commerce.md +269 -0
- package/docs/examples/builtin-intake.md +143 -0
- package/docs/examples/builtin-legal-documents.md +189 -0
- package/docs/examples/builtin-procurement.md +241 -0
- package/docs/examples/builtin-publication.md +241 -0
- package/docs/examples/builtin-reservation.md +149 -0
- package/docs/examples/cf-primitives-commerce-inventory.md +809 -0
- package/docs/examples/cf-primitives-guarded-api.md +429 -0
- package/docs/examples/cf-primitives-intake-hooks.md +319 -0
- package/docs/examples/host-chatgpt-sites/.openai/hosting.json +1 -0
- package/docs/examples/host-chatgpt-sites/README.md +53 -0
- package/docs/examples/host-chatgpt-sites/drizzle/0000_sites_users.sql +8 -0
- package/docs/examples/host-chatgpt-sites/drizzle/0001_mantle.sql +294 -0
- package/docs/examples/host-chatgpt-sites/drizzle/0002_article_cover.sql +5 -0
- package/docs/examples/host-chatgpt-sites/drizzle/meta/_journal.json +1 -0
- package/docs/examples/host-chatgpt-sites/manifests/site.yaml +27 -0
- package/docs/examples/host-chatgpt-sites/package.json +1 -0
- package/docs/examples/host-chatgpt-sites/public/site.css +1 -0
- package/docs/examples/host-chatgpt-sites/scripts/build.mjs +12 -0
- package/docs/examples/host-chatgpt-sites/scripts/check.mjs +99 -0
- package/docs/examples/host-chatgpt-sites/scripts/migration.mjs +9 -0
- package/docs/examples/host-chatgpt-sites/src/chatgpt-auth.ts +63 -0
- package/docs/examples/host-chatgpt-sites/src/index.ts +46 -0
- package/docs/examples/host-chatgpt-sites/src/mcp.ts +49 -0
- package/docs/examples/host-chatgpt-sites/src/media.ts +109 -0
- package/docs/examples/host-chatgpt-sites/src/r2-lab.ts +38 -0
- package/docs/examples/host-chatgpt-sites/src/storage-fingerprint.json +1 -0
- package/docs/examples/host-chatgpt-sites/src/web.ts +35 -0
- package/docs/examples/host-chatgpt-sites/tsconfig.json +1 -0
- package/docs/examples/host-chatgpt-sites/wrangler.jsonc +10 -0
- package/docs/examples/host-local-admin-otp/.dev.vars.example +3 -0
- package/docs/examples/host-local-admin-otp/README.md +70 -0
- package/docs/examples/host-local-admin-otp/ensure-dev-vars.mjs +5 -0
- package/docs/examples/host-local-admin-otp/package.json +29 -0
- package/docs/examples/host-local-admin-otp/public/.gitkeep +1 -0
- package/docs/examples/host-local-admin-otp/smoke.mjs +141 -0
- package/docs/examples/host-local-admin-otp/src/index.ts +54 -0
- package/docs/examples/host-local-admin-otp/wrangler.jsonc +23 -0
- package/docs/examples/{minimal-worker → host-minimal-worker}/README.md +9 -5
- package/docs/examples/host-minimal-worker/manifests/site.yaml +25 -0
- package/docs/examples/{minimal-worker → host-minimal-worker}/package.json +3 -3
- package/docs/examples/host-minimal-worker/tsconfig.json +17 -0
- package/docs/handbook/cloudflare/authentication.md +17 -2
- package/docs/handbook/cloudflare/bindings.md +9 -7
- package/docs/handbook/cloudflare/chatgpt-sites.md +29 -0
- package/docs/handbook/cloudflare/conventional-worker.md +3 -3
- package/docs/handbook/cloudflare/deferred-hooks-queues.md +0 -1
- package/docs/handbook/cloudflare/deploy-and-operate.md +14 -20
- package/docs/handbook/cloudflare/media-r2.md +2 -2
- package/docs/handbook/cloudflare/public-web.md +1 -1
- package/docs/handbook/cloudflare/site-chrome.md +75 -0
- package/docs/handbook/concepts/authorization.md +2 -2
- package/docs/handbook/concepts/four-atoms.md +2 -2
- package/docs/handbook/concepts/lifecycle-and-locales.md +1 -1
- package/docs/handbook/concepts/mcp-and-agents.md +1 -1
- package/docs/handbook/concepts/procedures-and-triggers.md +1 -1
- package/docs/handbook/concepts/runtime-and-adapters.md +2 -2
- package/docs/handbook/concepts/views.md +2 -2
- package/docs/handbook/examples/commerce-transaction.md +4 -806
- package/docs/handbook/examples/commerce.md +11 -0
- package/docs/handbook/examples/guarded-api.md +3 -420
- package/docs/handbook/examples/hub.md +10 -0
- package/docs/handbook/examples/intake-form.md +6 -313
- package/docs/handbook/examples/intake-hooks.md +11 -0
- package/docs/handbook/examples/legal-documents.md +3 -211
- package/docs/handbook/examples/procurement-approvals.md +3 -233
- package/docs/handbook/examples/publication.md +3 -233
- package/docs/handbook/examples/reservation.md +3 -213
- package/docs/handbook/navigation.json +17 -2
- package/docs/handbook/reference/authorization.md +1 -1
- package/docs/handbook/reference/procedure.md +2 -2
- package/docs/handbook/reference/schema.md +3 -3
- package/docs/handbook/reference/site-config.md +5 -16
- package/docs/handbook/reference/surface.md +3 -7
- package/docs/handbook/sites/equipment-checkout.md +231 -0
- package/docs/handbook/sites/host-reference.md +113 -0
- package/docs/handbook/sites/index.md +111 -0
- package/docs/handbook/start/project-and-cli.md +22 -14
- package/docs/handbook/start/quickstart-admin.md +239 -0
- package/docs/handbook/start/quickstart-worker.md +22 -23
- package/docs/migration-0.1.2.md +26 -0
- package/docs/release-process.md +92 -7
- package/docs/sealed-pipeline-ownership.md +2 -2
- package/docs/spec-only-host-adoption.md +3 -4
- package/docs/transaction-patterns.md +2 -2
- package/package.json +15 -15
- package/skills/README.md +18 -2
- package/skills/develop/SKILL.md +32 -23
- package/skills/install/SKILL.md +50 -11
- package/skills/provision/SKILL.md +21 -5
- /package/docs/examples/{minimal-worker → host-local-admin-otp}/manifests/site.yaml +0 -0
- /package/docs/examples/{minimal-worker → host-local-admin-otp}/tsconfig.json +0 -0
- /package/docs/examples/{minimal-worker → host-minimal-worker}/smoke.mjs +0 -0
- /package/docs/examples/{minimal-worker → host-minimal-worker}/src/index.ts +0 -0
- /package/docs/examples/{minimal-worker → host-minimal-worker}/wrangler.jsonc +0 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Design a non-payment equipment checkout workflow with Mantle custom handlers, Sites identity and storage, and external Slack notifications."
|
|
3
|
+
---
|
|
4
|
+
# Equipment checkout and external notifications
|
|
5
|
+
|
|
6
|
+
**Turn a ChatGPT Site into an operational tool, with a Mantle-managed back
|
|
7
|
+
office and application-owned business rules.**
|
|
8
|
+
|
|
9
|
+
A production crew, school media room, or shared studio needs to know who has
|
|
10
|
+
each camera kit, who approved the loan, and when it should come back. A form
|
|
11
|
+
alone cannot prevent two people reserving the last kit. A notification alone
|
|
12
|
+
cannot enforce who may approve or return it.
|
|
13
|
+
|
|
14
|
+
This guide describes a non-payment application of the Sites integration:
|
|
15
|
+
members request equipment, staff approve and record handover, and a custom
|
|
16
|
+
handler notifies an equipment desk in Slack. There are no prices, deposits,
|
|
17
|
+
checkout charges, invoices, or payment-provider credentials.
|
|
18
|
+
|
|
19
|
+
**Status: implementation guide, not a shipped equipment app.** Start from the
|
|
20
|
+
[runnable article host reference](../../examples/host-chatgpt-sites/README.md).
|
|
21
|
+
That reference does not include these manifests, loan handlers, or a Slack
|
|
22
|
+
integration. The [verification boundary](#verification-boundary) distinguishes
|
|
23
|
+
the earlier deployment experiment from this proposed application.
|
|
24
|
+
|
|
25
|
+
## A useful first workflow
|
|
26
|
+
|
|
27
|
+
1. A member signs in with ChatGPT and requests a camera kit for tomorrow
|
|
28
|
+
afternoon. The server derives the borrower from the verified identity, not
|
|
29
|
+
a submitted user ID.
|
|
30
|
+
2. An owner or editor reviews the request in Mantle Admin. Approval claims the
|
|
31
|
+
kit for that time slot only if it is still available. A pending request does
|
|
32
|
+
not promise availability.
|
|
33
|
+
3. The approval commits, then the application attempts a Slack notification to
|
|
34
|
+
the equipment desk. The message identifies the request and links to the
|
|
35
|
+
authenticated Admin page; it contains no borrower email or private notes.
|
|
36
|
+
4. Staff record pickup and return. A return records condition and releases the
|
|
37
|
+
current checkout once. A damaged unit becomes unavailable for new claims.
|
|
38
|
+
5. Staff can inspect pending requests, reservations, checked-out equipment,
|
|
39
|
+
overdue returns, and notification failures in Admin Views.
|
|
40
|
+
|
|
41
|
+
Keep the first implementation bounded: identify individual kits, allow one kit
|
|
42
|
+
and one fixed half-day slot per request, and define slots in the team's chosen
|
|
43
|
+
time zone before storing UTC bounds. Multi-kit carts, arbitrary overlapping
|
|
44
|
+
intervals, recurring bookings and automated reminders are separate extensions.
|
|
45
|
+
An overdue checkout blocks physical handover to the next borrower even when a
|
|
46
|
+
future reservation exists; time passing is not evidence of a physical return.
|
|
47
|
+
|
|
48
|
+
## What Mantle owns, and what your application owns
|
|
49
|
+
|
|
50
|
+
| Surface | Contract |
|
|
51
|
+
|---|---|
|
|
52
|
+
| Equipment catalog | An `equipment` Schema with title, description and an R2 media asset reference. Use the runtime's content use cases for authoring. |
|
|
53
|
+
| Operational state | Application-owned D1 loan, unit-availability, reservation-claim and notification tables with reviewed migrations. Do not write Mantle-owned Schema tables directly. |
|
|
54
|
+
| Staff reports | Staff-only SQL Views over the application tables. SQL Views are specific to SQLite/D1, not a portable storage guarantee. |
|
|
55
|
+
| Business operations | Typed Procedures with `handler: { kind: ref, ref: ... }` for request, approval, rejection, pickup, return, cancellation and notification retry. |
|
|
56
|
+
| Staff controls | Explicit staff MCP Triggers expose appropriate Procedures to Admin operations/WebMCP; `requires.auth` checks owner/editor roles on every invocation. This does not mount remote staff OAuth MCP. |
|
|
57
|
+
| Member pages | Application routes show only the current member's requests and call the same runtime Procedure pipeline for mutations. |
|
|
58
|
+
| External integration | Application handler code calls a configured Slack incoming webhook with server-side credentials. Core needs no Slack-specific port or manifest kind. |
|
|
59
|
+
|
|
60
|
+
Keep approval, custody and delivery status separate. For example, a loan may
|
|
61
|
+
be `requested`, `approved`, `checked_out`, `returned`, `rejected` or `cancelled`,
|
|
62
|
+
while its notification is `pending`, `sent`, `failed`, `unknown` or
|
|
63
|
+
`not_configured`. A Slack failure must not turn an approved loan into a rejected
|
|
64
|
+
one. Do not expose generic CRUD for operational state transitions.
|
|
65
|
+
|
|
66
|
+
If you choose Mantle operational Schemas for query mirrors instead, declare
|
|
67
|
+
root `schema.readOnly: true`, maintain them through runtime use cases, and
|
|
68
|
+
define reconciliation with the authoritative reservation state. Do not add a
|
|
69
|
+
second writable authority just to obtain a sidebar entry; staff Views are
|
|
70
|
+
enough for the first implementation.
|
|
71
|
+
|
|
72
|
+
## Connect the custom handlers
|
|
73
|
+
|
|
74
|
+
Follow the existing [Procedure contract](../reference/procedure.md) and
|
|
75
|
+
[low-level host composition](../cloudflare/low-level-composition.md):
|
|
76
|
+
|
|
77
|
+
1. Author each Procedure's strict input/output schema and authorization
|
|
78
|
+
requirements. For example, `approve-loan` accepts a request ID and operation
|
|
79
|
+
ID, requires an owner/editor, and names `approveLoan` as its handler ref.
|
|
80
|
+
Resolve the kit, borrower, slot and current state from stored data.
|
|
81
|
+
2. Run `mantle generate`. Implement the resulting `MantleHandlers<Env>` map and
|
|
82
|
+
pass it as `handlers` to `bootMantleRuntime` alongside the sealed plan,
|
|
83
|
+
existing storage adapter and media port. A ref is a registration key, not a
|
|
84
|
+
file path or automatic route.
|
|
85
|
+
3. Mount member routes in the application. Bound and validate request bodies,
|
|
86
|
+
require the existing Sites session, check exact same-origin on browser
|
|
87
|
+
writes, and construct the runtime context from verified identity. Never
|
|
88
|
+
accept caller-supplied `staff`, role or borrower identity.
|
|
89
|
+
4. Invoke `bindMantle(runtime).procedures.<generatedName>(input, ctx)` and handle
|
|
90
|
+
its success/diagnostic result. Do not call the handler function directly.
|
|
91
|
+
A host-mounted route is an explicit entry point; the Procedure alone does
|
|
92
|
+
not install it. A manifest HTTP Trigger likewise needs the host's matching
|
|
93
|
+
transport mounting.
|
|
94
|
+
5. Expose only staff-appropriate operations through staff Triggers. Keep member
|
|
95
|
+
ownership checks inside handlers too: a role check alone does not prove
|
|
96
|
+
that the current member owns the request being cancelled or read.
|
|
97
|
+
|
|
98
|
+
See [Procedures and Triggers](../concepts/procedures-and-triggers.md) for
|
|
99
|
+
declarative transport binding. The Sites host still owns its router, auth and
|
|
100
|
+
external service configuration; Mantle owns validation, authorization and
|
|
101
|
+
dispatch through the sealed plan.
|
|
102
|
+
|
|
103
|
+
## Make reservations safe under retries and concurrency
|
|
104
|
+
|
|
105
|
+
Application storage must make approval and the claim for `(unitId, slotId)`
|
|
106
|
+
atomic. Use a database uniqueness constraint for the claim, not a browser
|
|
107
|
+
availability check followed by an unconditional write. When approval involves
|
|
108
|
+
several application-table statements, use a supported atomic D1 batch and
|
|
109
|
+
verify rollback on a conflicting claim. A conflict must not leave an approved
|
|
110
|
+
loan without its claim or a claim without its loan.
|
|
111
|
+
|
|
112
|
+
Bind every operation ID to its actor and complete business input. Replaying the
|
|
113
|
+
same input returns the prior result; reusing the ID for different input fails.
|
|
114
|
+
Guard transitions against the current state: repeated approval does not claim
|
|
115
|
+
twice, cancellation cannot silently undo checked-out equipment, and repeated
|
|
116
|
+
return cannot increase availability twice. Releasing a claim and changing loan
|
|
117
|
+
state must also commit atomically. Persist the audit record rather than deleting
|
|
118
|
+
the loan to make inventory appear available.
|
|
119
|
+
|
|
120
|
+
Re-check unit serviceability at approval and pickup. A catalog entry is
|
|
121
|
+
descriptive content, not the authoritative physical stock counter. Staff may
|
|
122
|
+
edit descriptions through Mantle without bypassing the reservation rules.
|
|
123
|
+
|
|
124
|
+
Do not infer this correctness from the catalog's CRUD tests. Include concurrent
|
|
125
|
+
approval, rollback and late-return scenarios in the application's own tests.
|
|
126
|
+
The earlier single-SKU stock experiment does not validate future time-slot
|
|
127
|
+
reservations.
|
|
128
|
+
|
|
129
|
+
## Call an external API without coupling it to approval
|
|
130
|
+
|
|
131
|
+
Start with a single administrator-configured Slack incoming webhook. An owner
|
|
132
|
+
chooses the destination channel and stores `SLACK_WEBHOOK_URL` as a Sites runtime
|
|
133
|
+
secret. It is not a manifest field, browser variable, member-supplied URL or
|
|
134
|
+
committed setting. Keep the URL and provider response details out of logs and
|
|
135
|
+
public diagnostics. Validate the configured HTTPS destination and do not follow
|
|
136
|
+
redirects to arbitrary hosts.
|
|
137
|
+
|
|
138
|
+
Slack accepts a server-side JSON POST. See its
|
|
139
|
+
[incoming webhook guide](https://docs.slack.dev/messaging/sending-messages-using-incoming-webhooks/)
|
|
140
|
+
for setup, response semantics and errors. The first integration sends a short
|
|
141
|
+
notification, not interactive Slack approval buttons. Those buttons would need
|
|
142
|
+
a separate authenticated callback design and a mapping to Mantle staff identity.
|
|
143
|
+
|
|
144
|
+
Commit a durable notification record in the **same application-owned D1
|
|
145
|
+
transaction** as approval, then attempt delivery with a bounded timeout. Claim
|
|
146
|
+
the record before sending so concurrent retries do not both send it. Record a
|
|
147
|
+
successful acknowledgement separately from the business result; an accepted
|
|
148
|
+
message does not prove a human read it.
|
|
149
|
+
|
|
150
|
+
Missing configuration is `not_configured`, not success. Definite provider
|
|
151
|
+
rejection is `failed`; a timeout or crash after sending may mean delivery is
|
|
152
|
+
`unknown`. Show these states and a staff-only retry action in Admin, including
|
|
153
|
+
recovery for an abandoned delivery claim. Retrying an unknown attempt may post
|
|
154
|
+
a duplicate: include the same notification ID and do not promise exactly-once
|
|
155
|
+
delivery. Never roll back the reservation because Slack is unavailable.
|
|
156
|
+
|
|
157
|
+
The first version attempts delivery after commit in the current request and
|
|
158
|
+
uses **manual staff retry**, not an assumed background scheduler. Sites Queue,
|
|
159
|
+
Durable Object and Cron support remains unverified here; `waitUntil` is not
|
|
160
|
+
durable delivery. Automated reminders require a separately verified host
|
|
161
|
+
capability, not a timer left running in a Worker.
|
|
162
|
+
|
|
163
|
+
## Verification boundary
|
|
164
|
+
|
|
165
|
+
The earlier deployed integration experiment established these narrower facts:
|
|
166
|
+
|
|
167
|
+
- Mantle custom handlers performed server-priced, idempotent single-SKU stock
|
|
168
|
+
operations on application-owned D1 tables, alongside the existing Admin/R2
|
|
169
|
+
content flow. Local regression tests covered concurrent oversell and replay.
|
|
170
|
+
- A browser form reached an external provider's **sandbox**, and its signed
|
|
171
|
+
server callback reached the published Site and updated a test record through
|
|
172
|
+
the runtime Procedure pipeline. This was not a Worker-originated Slack call.
|
|
173
|
+
- A migration containing SQLite triggers passed local D1 but failed Sites
|
|
174
|
+
deployment with `incomplete input: SQLITE_ERROR`. A trigger-free conditional
|
|
175
|
+
SQL/ledger version deployed successfully. This is a deployment observation,
|
|
176
|
+
not proof that all Sites deployments prohibit SQLite triggers.
|
|
177
|
+
|
|
178
|
+
The experiment is engineering evidence, **not a payment feature to adopt**.
|
|
179
|
+
[Sites' documented unsupported uses](https://learn.chatgpt.com/docs/sites#understand-limits-and-unsupported-uses)
|
|
180
|
+
include enabling financial transactions. Do not copy payment routes, merchant
|
|
181
|
+
credentials or payment terminology into this example, or infer permission for
|
|
182
|
+
live payments from successful sandbox transport.
|
|
183
|
+
|
|
184
|
+
Equipment reservations, Worker-to-Slack HTTPS delivery and its failure recovery
|
|
185
|
+
remain implementation and deployed acceptance work. They are not tested merely
|
|
186
|
+
because the underlying host composition or a different provider succeeded.
|
|
187
|
+
|
|
188
|
+
## Acceptance checklist for your application
|
|
189
|
+
|
|
190
|
+
- Preserve existing Site identity, audience, content and R2 objects. Follow the
|
|
191
|
+
[host reference](./host-reference.md) and its supported SDK installation path.
|
|
192
|
+
- Review additive migrations and the Mantle storage fingerprint; leave applied
|
|
193
|
+
migrations immutable. Test the actual Sites deploy, not only local D1.
|
|
194
|
+
- Verify member ownership, staff role revocation and cross-origin rejection.
|
|
195
|
+
Keep borrower records out of public Views, public MCP and static artifacts.
|
|
196
|
+
- Race two approvals for one unit/slot: exactly one succeeds. Verify a failed
|
|
197
|
+
batch leaves no partial approval, claim or notification record.
|
|
198
|
+
- Replay approve/cancel/return operations, including changed-input retries.
|
|
199
|
+
Check damaged units, overdue handover, and slot/time-zone boundaries.
|
|
200
|
+
- With the secret absent, show `not_configured`. With the configured test
|
|
201
|
+
channel, verify one actual deployed Worker-to-Slack notification and the
|
|
202
|
+
matching delivery record. Test rejection, timeout, abandoned claim and manual
|
|
203
|
+
retry without changing the loan's approved state.
|
|
204
|
+
- Walk through Admin's typed forms, staff Views and row operations with a real
|
|
205
|
+
second account. Browser WebMCP success is not remote OAuth MCP success.
|
|
206
|
+
|
|
207
|
+
## Ask your agent to build it
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
Extend my existing ChatGPT Site with Mantle equipment checkout. Read the matching
|
|
211
|
+
SDK's docs/handbook/sites/index.md, equipment-checkout.md and host-reference.md.
|
|
212
|
+
Preserve current content, audience and R2 media. This guide is a design, not an
|
|
213
|
+
installed app: implement and test the missing manifests, handlers and routes.
|
|
214
|
+
Start with one identified kit and one fixed half-day slot per request. Include
|
|
215
|
+
member-owned requests, staff approval/pickup/return, atomic reservation claims,
|
|
216
|
+
typed Admin operations, staff reports and an audit trail. Use a server-side
|
|
217
|
+
Slack webhook secret for minimal notifications, with durable delivery records
|
|
218
|
+
and manual retry. If no secret is configured, report that honestly. Do not
|
|
219
|
+
implement payments, remote staff OAuth, or assume DO/Queue/Cron availability.
|
|
220
|
+
Run the acceptance checklist and distinguish local, deployed and untested cases.
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Source
|
|
224
|
+
|
|
225
|
+
- [Sites integration](./index.md) and [host reference](./host-reference.md)
|
|
226
|
+
- [Runnable article host](../../examples/host-chatgpt-sites/README.md)
|
|
227
|
+
- [Procedure reference](../reference/procedure.md) and [authorization](../concepts/authorization.md)
|
|
228
|
+
- [Sealed runtime ownership](../../adr/0019-sealed-manifest-runtime-pipeline.md)
|
|
229
|
+
- [Schema storage and migrations](../../adr/0024-manifest-native-schema-tables.md)
|
|
230
|
+
- [Slack incoming webhooks](https://docs.slack.dev/messaging/sending-messages-using-incoming-webhooks/)
|
|
231
|
+
- [OpenAI Sites](https://learn.chatgpt.com/docs/sites)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Mantle on ChatGPT Sites: identity, D1, R2 media, public web, MCP boundaries, and deployment checks."
|
|
3
|
+
---
|
|
4
|
+
# ChatGPT Sites host reference
|
|
5
|
+
|
|
6
|
+
Start with [Mantle on ChatGPT Sites](./index.md) for the supported installation
|
|
7
|
+
path and your first publishing workflow. This reference explains how the
|
|
8
|
+
integration connects Sites hosting and sign-in to Mantle content, staff roles,
|
|
9
|
+
Admin, media, and public web. Keep the application outside the Mantle SDK
|
|
10
|
+
checkout and use matching SDK packages.
|
|
11
|
+
|
|
12
|
+
Start from the [runnable Sites host reference](../../examples/host-chatgpt-sites/README.md), then replace its **example** manifest with the user's business contract. It contains the matching D1 migrations/fingerprint, R2 upload adapter, local smoke test and build layout. Its browser-backed staff identity is not an OAuth resource-server credential.
|
|
13
|
+
|
|
14
|
+
## First deployment
|
|
15
|
+
|
|
16
|
+
1. Inspect the Site's actual hosting manifest and available bindings. Bind D1 before booting Mantle; create and apply the generated immutable D1 migration before publishing. Do not run DDL per request.
|
|
17
|
+
2. Compile the sealed plan (`mantle generate --check`, `mantle validate --phase deploy`) and bind `SqliteMantleStorageAdapter(new D1DatabaseDriver(env.DB), siteDefaults)`. Keep the generated storage fingerprint in sync with the migration.
|
|
18
|
+
3. If Admin is requested, mount `@aotter/mantle-admin` and its prebuilt assets. Use the trusted identity supplied by Sites **only after its ingress has stripped caller-supplied identity headers**. Map the stable per-Site user ID to a Mantle principal; use email only for owner bootstrap/invitation matching, not as a durable ID. Persist staff roles in D1 and re-read them for each privileged request. A Site Viewer is not automatically a Mantle editor.
|
|
19
|
+
4. If public pages are requested, compose `@aotter/mantle-web` over published-only queries. Verify anonymous article HTML, canonical/JSON-LD, Markdown, sitemap and `llms.txt`; a draft must remain 404. Do not assume a successful Admin boot implies a working homepage.
|
|
20
|
+
5. Publish through Sites, then verify the deployed version rather than only a local preview. Test owner, second account, role revocation, public/anonymous reads and every configured binding.
|
|
21
|
+
|
|
22
|
+
## Media with only an R2 binding
|
|
23
|
+
|
|
24
|
+
The `MediaStorage` port returns an HTTP `PUT` capability; it does **not** require a presigned S3 URL. An application with `env.MEDIA_BUCKET` can implement the port with `R2Bucket.put/head/get/delete` and return a same-origin upload URL. Bind that implementation as `ports.mediaStorage` **and** declare at least one `siteDefaults.media.purposes` policy; otherwise the Admin library and `create_media_upload` remain disabled.
|
|
25
|
+
|
|
26
|
+
The application must mount two routes alongside the port:
|
|
27
|
+
|
|
28
|
+
- `PUT /admin/media-upload/:group/:file`: check an authenticated editor-or-higher session, exact `Origin`, unexpired D1 pending-upload record, server-generated storage key, declared MIME and exact byte size before `R2Bucket.put`. Bound the request body by the policy limit. In Workers, a fixed-length `Uint8Array` is the conservative input to `put` when a streamed request body has unknown length. The port's `createUpload` must return this route as `uploadUrl` and the exact required `Content-Type` header.
|
|
29
|
+
- `GET /media/:purpose/:group/:file`: look up the committed `media_assets` row before `R2Bucket.get`, and serve only a listed variant with a safe MIME, `nosniff` and an intentional public cache policy. This is a **public** URL; it does not make private media safe.
|
|
30
|
+
|
|
31
|
+
The existing create → `PUT` each `uploadUrl` → commit flow works unchanged in Admin UI. Verify that an anonymous/cross-origin/expired/oversize `PUT` fails, that pre-commit public reads are 404, and that committed media resolves anonymously. A successful R2 binding read/write probe alone does not enable the library.
|
|
32
|
+
|
|
33
|
+
The browser route above uses the Sites session and therefore does **not** automatically work for a remote MCP client. For remote agent upload, either give the client a separately authenticated Worker `PUT` capability (with its own expiry and pending-record check) or choose the native `R2MediaStorage` direct-to-R2 path. Do not put image bytes in MCP JSON tool arguments. R2 bindings expose object operations, not S3 SigV4 presigning: direct-to-R2 presigned URLs require an R2 S3 endpoint and API key pair. Do not configure those credentials merely to make Admin UI upload work.
|
|
34
|
+
|
|
35
|
+
## Remote MCP is a separate gate
|
|
36
|
+
|
|
37
|
+
The reference exposes these separate surfaces:
|
|
38
|
+
|
|
39
|
+
| Surface | Authentication | Reference support |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| Admin WebMCP | Current browser Admin session and fresh Mantle staff role | Available within Admin. |
|
|
42
|
+
| Public MCP (reference path: `/api/mcp`) | Anonymous, read-only public Views | Manual HTTPS `initialize`, `tools/list`, and a published View call verified on the deployed integration. |
|
|
43
|
+
| Sites-session staff MCP (reference path: `/api/mcp/staff`) | Sites-injected identity plus a fresh Mantle staff role | Mounted and reported to Admin; not usable as a remote OAuth connector. |
|
|
44
|
+
| Remote staff OAuth MCP | OAuth bearer authorization and fresh Mantle staff role | Requires a separate integration. |
|
|
45
|
+
| Sites-managed connector registration | Sites MCP declaration and connection configuration | Unverified; do not guess a hosting manifest key. |
|
|
46
|
+
|
|
47
|
+
Try the conventional `/mcp` path first. If ChatGPT Sites does not route that
|
|
48
|
+
path to the application, mount the MCP handler at another application-owned
|
|
49
|
+
path and report the actual path through `mcpEndpoints`. For example:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
app.all("/agent/read", publicMcpHandler);
|
|
53
|
+
|
|
54
|
+
mountMantleAdmin(app, {
|
|
55
|
+
plan,
|
|
56
|
+
auth,
|
|
57
|
+
assets,
|
|
58
|
+
get,
|
|
59
|
+
mcpEndpoints: { public: "/agent/read", staff: "/agent/staff" },
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The reference encountered that condition and chose `/api/mcp` plus
|
|
64
|
+
`/api/mcp/staff`. It mounts both handlers and passes both paths through
|
|
65
|
+
`mcpEndpoints`, so Admin displays the routes that actually exist. These are
|
|
66
|
+
example fallback paths, not Mantle Core routes. Verify each chosen route with
|
|
67
|
+
`initialize`, `tools/list`, and a tool call after every Sites deployment.
|
|
68
|
+
|
|
69
|
+
The reference smoke test also checks that `/mcp` and `/mcp/staff` return 404.
|
|
70
|
+
The earlier deployment's root `/mcp` response is not evidence of a globally
|
|
71
|
+
reserved Sites path; another Sites deployment may route it differently.
|
|
72
|
+
|
|
73
|
+
Identity follows the same host-owned design. `@aotter/mantle-admin` exports
|
|
74
|
+
`AdminAuth`; the reference implements it using trusted Sites identity headers
|
|
75
|
+
and a D1 staff table. A host may implement the interface with another identity
|
|
76
|
+
system or wrap Mantle's Better Auth adapter. Core does not contain a ChatGPT
|
|
77
|
+
login implementation or require Better Auth for Sites.
|
|
78
|
+
|
|
79
|
+
A successful public MCP call verifies that endpoint, not ChatGPT connector
|
|
80
|
+
registration. A manually configured connector targets the HTTPS endpoint;
|
|
81
|
+
Sites-provisioned connection details (`get_site` with `include_mcp_connection`)
|
|
82
|
+
additionally require a deployed MCP declaration.
|
|
83
|
+
|
|
84
|
+
The reference's staff endpoint trusts only identity injected by the Sites
|
|
85
|
+
ingress, rejects ordinary members, and re-reads the Mantle role on every
|
|
86
|
+
request. Before exposing staff MCP to remote clients, implement a standard
|
|
87
|
+
OAuth authorization server or established provider, bearer verification, and
|
|
88
|
+
a fresh Mantle staff role check on each tool request. Verify OAuth protected-resource and
|
|
89
|
+
authorization metadata as JSON, a standards-compliant unauthenticated `401`
|
|
90
|
+
challenge, and authenticated `tools/list` plus a read-only call. A Sites browser
|
|
91
|
+
session or forwarded identity header is not an OAuth bearer token; a sign-in
|
|
92
|
+
HTML page returned to an OAuth JSON request is a failed integration.
|
|
93
|
+
|
|
94
|
+
## Capability boundaries
|
|
95
|
+
|
|
96
|
+
Native Cloudflare deployments can configure R2 public domains, S3 credentials, Queues, Durable Objects, KV and Cron independently. A Sites deployment should claim only the bindings its hosting manifest and deployed tests actually expose. `waitUntil` is not a durable queue. Keep missing primitives as explicit host limitations rather than adding fake Mantle ports.
|
|
97
|
+
|
|
98
|
+
See [native R2 direct upload](../cloudflare/media-r2.md), [authentication](../cloudflare/authentication.md), and [public web](../cloudflare/public-web.md).
|
|
99
|
+
|
|
100
|
+
For custom business rules and external API calls, see the
|
|
101
|
+
[equipment checkout guide](./equipment-checkout.md). It keeps transactional
|
|
102
|
+
application state separate from notification delivery and documents the
|
|
103
|
+
deployment experiment's limits. Sites' [unsupported uses](https://learn.chatgpt.com/docs/sites#understand-limits-and-unsupported-uses)
|
|
104
|
+
include financial transactions; a successful sandbox experiment is not support
|
|
105
|
+
for live payments.
|
|
106
|
+
|
|
107
|
+
## Source
|
|
108
|
+
|
|
109
|
+
- `MediaStorage` port and the media upload use case in `@aotter/mantle-runtime`
|
|
110
|
+
- [Cloudflare R2 Workers binding API](https://developers.cloudflare.com/r2/api/workers/workers-api-reference/)
|
|
111
|
+
- [Cloudflare R2 presigned URLs](https://developers.cloudflare.com/r2/api/s3/presigned-urls/)
|
|
112
|
+
- [OpenAI Sites](https://learn.chatgpt.com/docs/sites)
|
|
113
|
+
- [OpenAI MCP server authentication](https://developers.openai.com/plugins/build/auth)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Build with ChatGPT Sites. Manage content and publishing with Mantle."
|
|
3
|
+
---
|
|
4
|
+
# Mantle on ChatGPT Sites
|
|
5
|
+
|
|
6
|
+
**Build with ChatGPT Sites. Manage content and publishing with Mantle.**
|
|
7
|
+
|
|
8
|
+
Give your Site an editorial workflow: sign in, invite editors, upload a cover
|
|
9
|
+
image, save a draft, and publish an article. Mantle connects the Admin console,
|
|
10
|
+
public pages, and agent tools to the same content model, so your team can keep
|
|
11
|
+
the site current after the first build.
|
|
12
|
+
|
|
13
|
+
ChatGPT Sites is a first-class integration in Mantle's official documentation,
|
|
14
|
+
with a runnable reference and a repeatable verification flow maintained in this
|
|
15
|
+
repository. Sites owns hosting, visitor access, and ChatGPT sign-in; Mantle owns
|
|
16
|
+
the content model, staff roles, and publishing workflow. For platform access and
|
|
17
|
+
sharing options, see [OpenAI's Sites documentation](https://learn.chatgpt.com/docs/sites).
|
|
18
|
+
|
|
19
|
+
## What you get
|
|
20
|
+
|
|
21
|
+
| Capability | In the Mantle Sites reference |
|
|
22
|
+
|---|---|
|
|
23
|
+
| Content management | Admin for drafting, editing, publishing, and unpublishing articles stored in D1. |
|
|
24
|
+
| Staff access | ChatGPT sign-in with Mantle owner, editor, and contributor roles. Site visitor access grants no Mantle staff role. |
|
|
25
|
+
| Images | Admin uploads through the Site's R2 binding, with public URLs for committed images. No R2 S3 credentials required. |
|
|
26
|
+
| Public pages | Published article HTML and Markdown, cover images, canonical metadata, JSON-LD, sitemap, and `llms.txt`. |
|
|
27
|
+
| Agent access | Admin WebMCP, anonymous read-only public Views at `/api/mcp`, and Sites-session staff tools at `/api/mcp/staff`. |
|
|
28
|
+
|
|
29
|
+
Remote staff OAuth MCP and automatic ChatGPT connector registration are outside
|
|
30
|
+
the reference's current scope. Public media URLs are readable by anyone
|
|
31
|
+
who can reach the Site; this integration does not implement private media.
|
|
32
|
+
See the [host reference](./host-reference.md) for the exact trust and transport
|
|
33
|
+
boundaries.
|
|
34
|
+
|
|
35
|
+
## Start with the supported SDK
|
|
36
|
+
|
|
37
|
+
You need Node.js 22+, pnpm 9+, and Sites access with D1 and R2 available for your
|
|
38
|
+
project. Follow the reference's local build and smoke test before deployment.
|
|
39
|
+
Keep your application outside the SDK checkout. The included article schema is
|
|
40
|
+
a working example; adapt its fields and lifecycle to your team's content.
|
|
41
|
+
|
|
42
|
+
## Publish your first article
|
|
43
|
+
|
|
44
|
+
1. **Prepare the application.** Follow the
|
|
45
|
+
[runnable reference](../../examples/host-chatgpt-sites/README.md#install-and-run).
|
|
46
|
+
Its local test verifies content, roles, images, public pages, and MCP together.
|
|
47
|
+
2. **Connect Sites.** Follow [Publish with Sites](../../examples/host-chatgpt-sites/README.md#publish-with-sites)
|
|
48
|
+
to provision D1 and R2, set the production origin and first owner's email,
|
|
49
|
+
and review the database migrations. Save a version, then deploy it through
|
|
50
|
+
Sites for the intended audience.
|
|
51
|
+
3. **Sign in as the owner.** Open `/admin/sign-in` and use the configured owner's
|
|
52
|
+
ChatGPT account. Give a second account an editor role in Mantle when you want
|
|
53
|
+
someone else to manage content. Sites sharing and Mantle staff roles are
|
|
54
|
+
separate controls.
|
|
55
|
+
4. **Create a draft.** In Admin, create an article with a title, summary, and
|
|
56
|
+
Markdown body. Upload an image in the media library and select it as the
|
|
57
|
+
article's cover. The draft's public article URL should return 404.
|
|
58
|
+
5. **Publish and read.** Publish the article and open `/articles`. Follow its
|
|
59
|
+
link to check the body and cover, then open its `.md` version. For a public
|
|
60
|
+
Site, repeat this while signed out. A restricted Site still enforces its
|
|
61
|
+
audience settings before visitors reach these pages.
|
|
62
|
+
6. **Verify control.** Unpublish the article and confirm its detail page returns
|
|
63
|
+
404. Revoke the second account's staff role and verify it can no longer edit.
|
|
64
|
+
Published content and staff access should follow your changes immediately.
|
|
65
|
+
|
|
66
|
+
For later content edits, return to Mantle Admin. Changes to the application's
|
|
67
|
+
schema, code, or deployment settings follow the reference's migration and Sites
|
|
68
|
+
deployment workflow.
|
|
69
|
+
|
|
70
|
+
## Ask your agent to set it up
|
|
71
|
+
|
|
72
|
+
Install the Mantle agent plugin, or `@aotter/mantle` itself, then describe your
|
|
73
|
+
audience and content requirements:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
Build a content site with ChatGPT Sites and Mantle. Read
|
|
77
|
+
handbook/sites/index.md and examples/host-chatgpt-sites/README.md from the
|
|
78
|
+
installed Mantle docs, and follow that reference's install and run steps.
|
|
79
|
+
Adapt the article example to my content requirements. Include ChatGPT
|
|
80
|
+
sign-in, Mantle staff roles, cover uploads, and published article pages.
|
|
81
|
+
Run the local checks and show me a draft-to-publish walkthrough before
|
|
82
|
+
deploying through Sites. Keep remote staff OAuth MCP outside this scope.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For business rules beyond content, add: "use custom `ref` handlers and
|
|
86
|
+
application-owned tables as described in handbook/sites/equipment-checkout.md."
|
|
87
|
+
|
|
88
|
+
## Beyond content: operational workflows
|
|
89
|
+
|
|
90
|
+
Custom handlers can connect typed Mantle operations to application-owned
|
|
91
|
+
business rules and external services. See [Equipment checkout and external
|
|
92
|
+
notifications](./equipment-checkout.md) for a non-payment scenario: staff
|
|
93
|
+
approve equipment loans, atomically reserve a kit, and notify an equipment desk
|
|
94
|
+
in Slack without making approval depend on notification delivery.
|
|
95
|
+
|
|
96
|
+
This is an implementation guide and acceptance checklist, not an additional
|
|
97
|
+
feature installed by the article reference. It separates deployed integration
|
|
98
|
+
evidence from the equipment and Slack work still required in your application.
|
|
99
|
+
|
|
100
|
+
## Integration details
|
|
101
|
+
|
|
102
|
+
- [Host reference](./host-reference.md): identity, migrations, R2 routes, MCP, and deployment checks.
|
|
103
|
+
- [Equipment checkout](./equipment-checkout.md): custom business rules and external API delivery without payments.
|
|
104
|
+
- [Runnable application](../../examples/host-chatgpt-sites/README.md): installation, build artifacts, and smoke tests.
|
|
105
|
+
- [Conventional Cloudflare Worker](../cloudflare/conventional-worker.md): the separate path for a Worker you deploy directly.
|
|
106
|
+
|
|
107
|
+
## Source
|
|
108
|
+
|
|
109
|
+
- [Runnable Sites application](../../examples/host-chatgpt-sites/README.md)
|
|
110
|
+
- [Sites host reference](./host-reference.md)
|
|
111
|
+
- [OpenAI Sites documentation](https://learn.chatgpt.com/docs/sites)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: The files you own in a Mantle project, every mantle and mantle-harness command with its flags, the generated module, the daily check loop, and
|
|
2
|
+
description: The files you own in a Mantle project, every mantle and mantle-harness command with its flags, the generated module, the daily check loop, and version pins.
|
|
3
3
|
---
|
|
4
4
|
# Project layout and the CLI loop
|
|
5
5
|
|
|
6
|
-
This page describes a directly authored Mantle project: which files are yours, what the installed CLI does to them, and the loop you run before every commit.
|
|
6
|
+
This page describes a directly authored Mantle project: which files are yours, what the installed CLI does to them, and the loop you run before every commit. Surfaces are optional — take only what you need. [The minimal Worker](./quickstart-worker.md) is Spec + adapter without Admin. [Local Admin](./quickstart-admin.md) is the opt-in Dev UI path when humans need a console.
|
|
7
7
|
|
|
8
8
|
## You own the project
|
|
9
9
|
|
|
10
|
-
Core
|
|
10
|
+
Core is a manifest compiler and a runtime, not a project generator. You write `package.json`, the manifests, the Worker entry, handlers, TypeScript and provider configuration. `mantle generate` compiles what exists; it never initializes a missing project or invents a default Schema, frontend or home route.
|
|
11
11
|
|
|
12
12
|
```txt
|
|
13
13
|
my-service/
|
|
@@ -20,7 +20,7 @@ my-service/
|
|
|
20
20
|
├── src/
|
|
21
21
|
│ ├── index.ts createMantleWorker({ plan, extend })
|
|
22
22
|
│ └── mantle/handlers/ handler refs (a convention; any path under src/)
|
|
23
|
-
├── public/ ASSETS
|
|
23
|
+
├── public/ required ASSETS root when Admin is installed; generate writes public/_mantle/admin/
|
|
24
24
|
├── .mantle/generated/
|
|
25
25
|
│ └── mantle.ts written by mantle generate
|
|
26
26
|
├── .agents/skills/mantle-*/ written by mantle skills
|
|
@@ -33,7 +33,7 @@ The minimal Worker reference keeps `.mantle/`, `.agents/`, `.claude/`, `.wrangle
|
|
|
33
33
|
|
|
34
34
|
## The CLI
|
|
35
35
|
|
|
36
|
-
The umbrella package installs two binaries, `mantle` and `mantle-harness`. Run them through the package manager, for example `pnpm exec mantle generate`. Defaults shown are the pinned ones.
|
|
36
|
+
The umbrella package installs two binaries, `mantle` and `mantle-harness`. Run them through the package manager, for example `pnpm exec mantle generate`. Defaults shown are the pinned ones. Bare `mantle` / `mantle --help` prints a layered overview of optional surfaces (Minimal Spec + generate, Runtime / adapter, opt-in Admin). `generate --help` and `validate --help` stay on the compile path. After a successful `generate`, the CLI says Admin is opt-in: next steps when `@aotter/mantle-admin-ui` is installed, otherwise an API-only tip.
|
|
37
37
|
|
|
38
38
|
| Command | Flags | Does |
|
|
39
39
|
|---|---|---|
|
|
@@ -48,7 +48,15 @@ Advanced manifest primitives live in the `@aotter/mantle-spec` package's own `ma
|
|
|
48
48
|
|
|
49
49
|
### What `generate` does and does not do
|
|
50
50
|
|
|
51
|
-
`generate` reads the manifest directory, runs the same validation as `validate` (without the handler-source grep), links the set, and emits one `.mantle/generated/mantle.ts`. When `@aotter/mantle-admin-ui` is installed it also syncs the Admin SPA into `public/_mantle/admin/`, excluding the package's `server.*` exports; Core-only installs skip that copy. Any error diagnostic stops the run with exit 1.
|
|
51
|
+
`generate` reads the manifest directory, runs the same validation as `validate` (without the handler-source grep), links the set, and emits one `.mantle/generated/mantle.ts`. When `@aotter/mantle-admin-ui` is installed it also syncs the **prebuilt** Admin SPA into `public/_mantle/admin/`, excluding the package's `server.*` exports; Core-only installs skip that copy. Any error diagnostic stops the run with exit 1.
|
|
52
|
+
|
|
53
|
+
Do not Vite-build Admin unless you are developing `@aotter/mantle-admin-ui` itself. A Cloudflare project that serves Admin must declare Static Assets:
|
|
54
|
+
|
|
55
|
+
```jsonc
|
|
56
|
+
"assets": { "directory": "./public", "binding": "ASSETS" }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
That binding is a hard requirement. If `/admin` returns SPA `index.html` (`200`) while `/_mantle/admin/assets/*` is `404`, the page white-screens. Leave `/_mantle` out of `run_worker_first` so those files stay on the assets layer. `generate` warns when it syncs Admin and the local wrangler config has no `ASSETS` binding.
|
|
52
60
|
|
|
53
61
|
It does not project skills, update packages, change styling, provision providers, or deploy. It does not create manifests: a missing or empty `manifests/` directory is an error, not a prompt.
|
|
54
62
|
|
|
@@ -78,7 +86,7 @@ pnpm exec mantle-harness indexes --require-public --format text
|
|
|
78
86
|
pnpm exec wrangler dev --local
|
|
79
87
|
```
|
|
80
88
|
|
|
81
|
-
Run the harness after any change to a Schema index, View filter or ordering, or public route; declare the smallest ordered index the measured path needs and respect SQLite's leftmost-prefix rule. Before a deploy, run `mantle validate --phase deploy`. Probe at least one declared route on the local origin; a `200` from a public View does not prove Admin or MCP login works.
|
|
89
|
+
Run the harness after any change to a Schema index, View filter or ordering, or public route; declare the smallest ordered index the measured path needs and respect SQLite's leftmost-prefix rule. Before a deploy, run `mantle validate --phase deploy`. Probe at least one declared route on the local origin; a `200` from a public View does not prove Admin or MCP login works. When Admin is installed, also probe `/admin/sign-in` and one `/_mantle/admin/assets/*` URL — both must be `200`. HTML 200 with asset 404 is the white-screen class of bug.
|
|
82
90
|
|
|
83
91
|
## Connecting an agent
|
|
84
92
|
|
|
@@ -98,18 +106,18 @@ codex plugin add mantle@mantle
|
|
|
98
106
|
|
|
99
107
|
The projected `develop` skill tells the agent to read `package.json` for the installed version, the manifests and adapter config, and the docs under `node_modules/@aotter/mantle/docs/` before editing. To connect an MCP client to the running Worker, see [MCP and agents](../concepts/mcp-and-agents.md).
|
|
100
108
|
|
|
101
|
-
##
|
|
109
|
+
## Version pins
|
|
102
110
|
|
|
103
111
|
- Pin every `@aotter/mantle*` package to one exact version and move them together. Check that release's peer ranges when you move.
|
|
104
|
-
-
|
|
105
|
-
- The
|
|
106
|
-
- When
|
|
112
|
+
- This handbook describes the snapshot in this source tree. Use the docs that ship with the version in `package.json`, not a floating branch.
|
|
113
|
+
- The authoring CLI is `generate`, `validate`, `emit-openapi` and `skills`. `mantle-harness` is the measurement binary. There is no `create` / `update` happy path.
|
|
114
|
+
- When you change versions: pin the new exact version and refresh the lockfile; keep the Worker, D1, KV identity, origins, auth mode and secrets; then run `generate`, `generate --check`, `skills`, `skills --check`, `validate`, typecheck and tests before deploying.
|
|
107
115
|
|
|
108
116
|
## Source
|
|
109
117
|
- [`docs/direct-authoring.md`](../../../docs/direct-authoring.md)
|
|
110
|
-
- [`docs/
|
|
111
|
-
- [`docs/
|
|
112
|
-
- [`docs/examples/minimal-worker/.gitignore`](../../../docs/examples/minimal-worker/.gitignore)
|
|
118
|
+
- [`docs/examples/host-local-admin-otp/README.md`](../../../docs/examples/host-local-admin-otp/README.md)
|
|
119
|
+
- [`docs/examples/host-local-admin-otp/wrangler.jsonc`](../../../docs/examples/host-local-admin-otp/wrangler.jsonc)
|
|
120
|
+
- [`docs/examples/host-minimal-worker/.gitignore`](../../../docs/examples/host-minimal-worker/.gitignore)
|
|
113
121
|
- [`packages/mantle/README.md`](../../../packages/mantle/README.md)
|
|
114
122
|
- [`packages/mantle/src/cli/main.ts`](../../../packages/mantle/src/cli/main.ts)
|
|
115
123
|
- [`packages/mantle/src/cli/generate.ts`](../../../packages/mantle/src/cli/generate.ts)
|