@aotter/mantle 0.2.0-alpha.8 → 0.2.0-alpha.9
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 +17 -0
- package/dist/auth/adapter.js +9 -6
- package/dist/auth/routes.js +3 -2
- package/dist/build/compiler.js +1 -1
- package/dist/infrastructure/bundle.js +16 -3
- package/dist/infrastructure/generate.js +9 -1
- package/dist/infrastructure/generateAuth.js +51 -0
- package/dist/infrastructure/wrangler.js +19 -4
- package/dist/kernel/binds.d.ts +0 -3
- package/dist/kernel/contracts.d.ts +1 -1
- package/dist/kernel/contracts.js +4 -4
- package/dist/kernel/dialect/common.d.ts +0 -1
- package/dist/kernel/driver/postgres.js +3 -2
- package/dist/kernel/mcp-apps.js +1 -1
- package/dist/kernel/mcp-handler.js +1 -1
- package/dist/kernel/mcp.d.ts +5 -1
- package/dist/kernel/mcp.js +2 -1
- package/dist/kernel/scalars.js +3 -2
- package/dist/kernel/web-index.js +40 -0
- package/dist/kernel/web.js +3 -37
- package/dist/usecase/publishing.js +1 -1
- package/dist/usecase/site.js +0 -1
- package/dist/usecase/validation.js +8 -0
- package/docs/examples/README.md +1 -1
- package/docs/examples/app-shell/README.md +6 -2
- package/docs/examples/app-shell/package.json +3 -3
- package/docs/examples/app-shell/src/auth.ts +3 -2
- package/docs/examples/app-shell/src/service.ts +2 -2
- package/docs/examples/club-events/manifests/club-events.yaml +7 -0
- package/docs/examples/club-events/src/handlers.ts +1 -1
- package/docs/examples/purchasing/manifests/purchasing.yaml +16 -0
- package/docs/examples/purchasing/src/handlers.ts +1 -1
- package/docs/handbook/cloudflare/authentication.md +21 -4
- package/docs/handbook/cloudflare/chatgpt-sites.md +4 -2
- package/docs/handbook/cloudflare/deploy-and-operate.md +24 -1
- package/docs/handbook/cloudflare/media-r2.md +2 -3
- package/docs/handbook/cloudflare/service-entry.md +14 -4
- package/docs/handbook/concepts/runtime-and-adapters.md +1 -1
- package/docs/handbook/examples/hub.md +1 -1
- package/docs/handbook/guides/agent-setup.md +4 -4
- package/docs/handbook/guides/agent-workflow-acceptance.md +222 -0
- package/docs/handbook/guides/mcp-apps.md +78 -1
- package/docs/handbook/guides/native-admin.md +4 -0
- package/docs/handbook/guides/oauth.md +58 -0
- package/docs/handbook/guides/typed-queries.md +35 -0
- package/docs/handbook/reference/procedure.md +1 -1
- package/docs/handbook/reference/surface.md +6 -2
- package/docs/handbook/reference/trigger.md +9 -0
- package/docs/handbook/releases/index.md +3 -3
- package/docs/handbook/start/project-and-cli.md +9 -1
- package/docs/skills/develop/SKILL.md +43 -16
- package/docs/skills/integrate/SKILL.md +4 -9
- package/docs/skills/provision/SKILL.md +15 -12
- package/docs/skills/update/SKILL.md +19 -18
- package/package.json +2 -2
- package/skills/README.md +1 -1
- package/skills/mantle/SKILL.md +35 -13
- package/skills/mantle/references/local-testing.md +5 -0
- package/skills/mantle/references/website.md +6 -4
- package/docs/skills/develop/mcp-app.md +0 -39
- package/skills/.keep +0 -0
|
@@ -58,6 +58,15 @@ unchanged. A POST registration whose redirect URIs are all HTTP localhost,
|
|
|
58
58
|
127.0.0.1 or [::1] becomes `application_type: "native"` when omitted; explicit
|
|
59
59
|
types and mixed/external callbacks stay under the SDK's validation.
|
|
60
60
|
|
|
61
|
+
With the optional Admin UI selected, use `consentPage:
|
|
62
|
+
"/admin/oauth/consent"`, as in `docs/examples/app-shell/src/auth.ts`, and keep
|
|
63
|
+
`adminShell` mounted in the service entry. That page uses mantle-ui's `AuthCard`,
|
|
64
|
+
cards and sign-in buttons; it loads the verified request from
|
|
65
|
+
`/oauth/consent/data` and posts the original signed payload to `/oauth/consent`.
|
|
66
|
+
The UI displays the client, callback origin, requested scopes and background
|
|
67
|
+
access explanation. Keep Core's script-free `/oauth/consent` HTML as the
|
|
68
|
+
adapter-neutral fallback, not as the reference application's styled page.
|
|
69
|
+
|
|
61
70
|
`/oauth/consent` and `/oauth/consents` serve escaped, script-free English or zh-TW
|
|
62
71
|
HTML. Their `/data` routes serve the 0.2 UI JSON shapes. Consent approval and
|
|
63
72
|
`POST /oauth/consents/revoke` require a live cookie session and same-origin
|
|
@@ -84,6 +93,55 @@ Grant lifetime follows Better Auth. Better Auth issues a refresh token only when
|
|
|
84
93
|
the grant includes `offline_access`; a client registered for `authorization_code`
|
|
85
94
|
may use `refresh_token` too, so registering only `authorization_code` does not
|
|
86
95
|
prevent long-lived grants.
|
|
96
|
+
CIMD is the primary client-discovery path; dynamic client registration (DCR)
|
|
97
|
+
remains available for older MCP clients. Both paths require the client to request
|
|
98
|
+
`offline_access` and the user to consent before a renewable grant is issued.
|
|
99
|
+
The DCR registration defaults below apply only to that compatibility path.
|
|
100
|
+
|
|
101
|
+
For renewable MCP connections, the examples set both `scopes` and
|
|
102
|
+
`clientRegistrationDefaultScopes` to `["mcp", "offline_access"]`, so a dynamically
|
|
103
|
+
registered client that omits `scope` is registered for `mcp offline_access`. The
|
|
104
|
+
client must request those registered scopes during authorization and the user must
|
|
105
|
+
consent to background access. If the client explicitly requests only `mcp`, OAuth
|
|
106
|
+
must not add a scope the user did not consent to: the resulting grant is bound to
|
|
107
|
+
the browser session and has no refresh token. The client must request
|
|
108
|
+
`offline_access`, or the user must reconnect and authorize it, to gain renewable
|
|
109
|
+
access. Declaring the `refresh_token` grant type alone is insufficient.
|
|
110
|
+
`offline_access` belongs in authorization-server metadata, not in the protected
|
|
111
|
+
resource's required scope floor; resource metadata continues to advertise `mcp`.
|
|
112
|
+
|
|
113
|
+
For renewable connections, the app-shell's MCP handler also supplies an explicit
|
|
114
|
+
OAuth linking hint:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
const handleMcp = mcp({
|
|
118
|
+
db: (env: Env) => env.DB,
|
|
119
|
+
caller: resolveRequestCaller,
|
|
120
|
+
authorizationScopes: ["offline_access"],
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`authorizationScopes` adds scopes to the standard `WWW-Authenticate` challenge
|
|
125
|
+
when the caller is unauthenticated. With the default `requiredScopes`, that
|
|
126
|
+
challenge requests `mcp offline_access`. It does **not** change the API scope
|
|
127
|
+
floor, add scopes to a valid token, issue tokens or modify an already-signed
|
|
128
|
+
authorization request. An existing valid `mcp`-only token can still call a tool
|
|
129
|
+
that only requires `mcp`. The application must independently permit
|
|
130
|
+
`offline_access` in its provider and the user must explicitly consent.
|
|
131
|
+
Verify the actual requested scopes, refresh-token issuance and post-expiry
|
|
132
|
+
rotation in the intended client. Do not put `offline_access` in the resource's
|
|
133
|
+
required scope floor or silently add it after consent.
|
|
134
|
+
|
|
135
|
+
For an existing connection granted only `mcp`, deploy the allowed-scope change,
|
|
136
|
+
refresh the client's discovery/registration metadata, then reconnect or reauthorize
|
|
137
|
+
once with `offline_access` and obtain updated consent. Allowing a scope does not
|
|
138
|
+
add it to a stored consent. Do not edit consent rows, prolong access-token TTLs or
|
|
139
|
+
disable grant checks to avoid that step. Verify a refresh token was issued and
|
|
140
|
+
that the client can rotate it and resume MCP after access expiry; a successful
|
|
141
|
+
initial `tools/list` does not prove renewable authorization. The reference service's
|
|
142
|
+
local smoke exercises issuance, refresh after website sign-out, rotation retry
|
|
143
|
+
and revocation using real OAuth endpoints and a disposable D1.
|
|
144
|
+
|
|
87
145
|
Without `offline_access` the grant is bound to the browser session: its tokens
|
|
88
146
|
stop working when that session expires or the user signs out. A refresh that
|
|
89
147
|
narrows the scope to drop `offline_access` after the session ends returns
|
|
@@ -90,3 +90,38 @@ Interactive `transaction(async tx => …)` exists on bun:sqlite and PostgreSQL,
|
|
|
90
90
|
Ref handlers receive `{ caller, db, store }` bound to the same Caller and transaction. Implement the generated `Handlers` interface and pass it to `store(db, caller, { handlers })`. Direct Procedure modules expose SQL Procedures; ref Procedures are reached through the bound Store or selected surfaces.
|
|
91
91
|
|
|
92
92
|
See [native execution](native-execution.md) for values and write outcomes and [migrations](../concepts/runtime-and-adapters.md#schema-installation-and-migrations) before changing a Schema.
|
|
93
|
+
|
|
94
|
+
## Prefer Store-backed ref Procedures for simple writes
|
|
95
|
+
|
|
96
|
+
For a single-entity create or partial update, prefer a declared `ref` Procedure
|
|
97
|
+
whose handler awaits its caller-bound `ctx.store.collection(...).insert(...)`
|
|
98
|
+
or `.update(id, allowedPatch, { lock: expectedVersion })`. Keep the Procedure's
|
|
99
|
+
`requires` and generated validation at its invocation boundary: Store enforces
|
|
100
|
+
row policy, but does not substitute for operation authorization. Do not invoke
|
|
101
|
+
a handler directly from a route and accidentally bypass those checks.
|
|
102
|
+
|
|
103
|
+
Insert/update returns the actual written native row. Inside a transaction,
|
|
104
|
+
that result is provisional until the outer transaction commits; later failure
|
|
105
|
+
can still roll it back. Report committed success or emit external effects only
|
|
106
|
+
after that transaction succeeds. Return an explicit
|
|
107
|
+
allowlist of useful business fields, its backend `id` and returned `version`;
|
|
108
|
+
do not spread the entire row, echo the submitted version, calculate a new
|
|
109
|
+
version instead of reading the result, or add a generic receipt adapter. These
|
|
110
|
+
ref results are app-owned: declare their output schema and make any required
|
|
111
|
+
native-to-wire conversion explicit at the boundary.
|
|
112
|
+
|
|
113
|
+
Patch only permitted fields. Omitted fields remain unchanged; define whether
|
|
114
|
+
explicit null clears a nullable field or is invalid. Do not expand a partial
|
|
115
|
+
request into a full replacement with defaults for unseen fields. A stale lock
|
|
116
|
+
is a conflict; preserve intent and reconcile/review rather than silently
|
|
117
|
+
refreshing the lock and retrying.
|
|
118
|
+
|
|
119
|
+
Use SQL Procedures when conditions or related effects must commit together:
|
|
120
|
+
for example, creating an order while decrementing stock under a CHECK, a state
|
|
121
|
+
transition guarded by an atomic WHERE, or an additive restock upsert. A
|
|
122
|
+
pre-read in TypeScript followed by an unguarded write is not equivalent.
|
|
123
|
+
Store `batch` is atomic for known writes; a D1 batch step cannot consume a prior
|
|
124
|
+
step's returned ID. D1 has no interactive transaction callback, so retain the
|
|
125
|
+
supported SQL program or another existing native atomic boundary for that case.
|
|
126
|
+
The [MCP design audit](agent-workflow-acceptance.md) applies these choices before
|
|
127
|
+
implementation and separates them from independent end-user acceptance.
|
|
@@ -4,7 +4,7 @@ A Procedure requires `input`, `output` JSON Schemas and a `handler` containing S
|
|
|
4
4
|
|
|
5
5
|
SQL uses declared Schemas, `input.<name>`, `auth.uid()` and native expressions accepted by the selected compiler dialect. Compiler policy supplies scope and system fields. Do not assign scope, version, status, published_at, timestamps or author columns yourself. Publishing writes use generated transitions. `restrict` narrows the rows the statements read and write, as on a [View](view.md#restrict); it is refused on ref handlers.
|
|
6
6
|
|
|
7
|
-
A row-classified INSERT/UPDATE/DELETE (one that targets a single row, e.g. `WHERE id = input.id`) must affect one row. Use `WHERE id = input.id AND version = input.expectedVersion` for explicit OCC. Set operations, including UPDATE with a subquery and `INSERT ... SELECT`, may affect zero rows without an error: check the returned rows when zero means failure. A unique clash, a failed Schema `checks` constraint (
|
|
7
|
+
A row-classified INSERT/UPDATE/DELETE (one that targets a single row, e.g. `WHERE id = input.id`) must affect one row. Use `WHERE id = input.id AND version = input.expectedVersion` for explicit OCC. Set operations, including UPDATE with a subquery and `INSERT ... SELECT`, may affect zero rows without an error: check the returned rows when zero means failure. A unique clash, a failed Schema `checks` constraint or a failed row assertion is `CONFLICT` (409); statements run atomically. A check failure keeps that code and its existing `A check of the Schema failed` message, and sets `ContractError.fields` to `{ kind: "check", schema, check }`; `check` is the expression on SQLite/D1 and the generated constraint name on PostgreSQL. Results are raw `{ results }`, not runtime-validated authored outputs. RETURNING uses SQL output names; quote an explicit alias to preserve declared case (`RETURNING reqStatus AS "reqStatus"`). Generation warns about unaliased direct fields whose declared name differs from storage.
|
|
8
8
|
|
|
9
9
|
A row-classified UPDATE/DELETE on an excluded or missing id affects zero rows and returns HTTP 409 (`CONFLICT`), just like a stale version; reads return not found. Native Admin's visible-row pre-read returns 404 for excluded/missing ids.
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
snake-cased View names on each declared surface, and snake-cased Procedure
|
|
14
14
|
names per MCP Trigger. Its SDK loads only through a request-time dynamic import.
|
|
15
15
|
- HTTP/MCP Triggers declare exposure only. `mantle generate` refuses schedule
|
|
16
|
-
and lifecycle Triggers;
|
|
16
|
+
and lifecycle Triggers; host scheduling is a separate capability.
|
|
17
17
|
- Native Admin retains selected 0.2 paths and the console contracts; see
|
|
18
18
|
[Native Admin](../guides/native-admin.md) for app-mounted
|
|
19
19
|
`adminBindings()` and `entries(bindings.schemas, bindings.adapter)`.
|
|
@@ -25,6 +25,8 @@ challenges, JSON-RPC, web rendering, keyset paging) lives in the package's
|
|
|
25
25
|
`rest`, `mcp`, `web`, `paging` and `validation` kernel modules, so a runtime fix
|
|
26
26
|
ships as a package update instead of a regeneration.
|
|
27
27
|
|
|
28
|
+
Procedure surface selection follows the [HTTP/MCP pairing default and deliberate asymmetry exception](trigger.md); no surface is implied.
|
|
29
|
+
|
|
28
30
|
The generated `validation/views/<name>.ts` and
|
|
29
31
|
`validation/procedures/<name>.ts` export `validate(unknown)`. View validators
|
|
30
32
|
also export `query(URLSearchParams)` returning `{ input, limit?, cursor? }`.
|
|
@@ -219,7 +221,9 @@ must also mount Better Auth's `/.well-known/oauth-protected-resource/mcp`
|
|
|
219
221
|
metadata route. Auth challenges point to that route. Presented bearer credentials
|
|
220
222
|
need the `mcp` scope; cookie sessions use the same-origin mutation checks.
|
|
221
223
|
|
|
222
|
-
Generation emits `mcp.ts` only for a non-internal View or MCP Trigger.
|
|
224
|
+
Generation emits `mcp.ts` only for a non-internal View or MCP Trigger. Omitting
|
|
225
|
+
MCP remains a deliberate asymmetric choice; an HTTP-only Procedure still generates
|
|
226
|
+
successfully with the warning described in [Trigger](trigger.md). These
|
|
223
227
|
surfaces typecheck without the optional `@modelcontextprotocol/server` peer;
|
|
224
228
|
install the exact version declared in the installed SDK's `peerDependencies`.
|
|
225
229
|
The peer loads by dynamic import on the first matching `/mcp` request; if
|
|
@@ -24,12 +24,21 @@ metadata: { name: close-ticket-http }
|
|
|
24
24
|
spec:
|
|
25
25
|
source: { kind: http, method: POST, path: '/api/tickets/{id}/close' }
|
|
26
26
|
target: { procedure: close-ticket }
|
|
27
|
+
---
|
|
28
|
+
apiVersion: cms.mantle.aotter.net/v2
|
|
29
|
+
kind: Trigger
|
|
30
|
+
metadata: { name: close-ticket-mcp }
|
|
31
|
+
spec:
|
|
32
|
+
source: { kind: mcp, surface: admin }
|
|
33
|
+
target: { procedure: close-ticket }
|
|
27
34
|
```
|
|
28
35
|
|
|
29
36
|
The target names a declared Procedure. `http` sources use POST/PUT/PATCH/DELETE and an `/api/` path. Path parameters bind to corresponding declared input fields and override JSON-body values. The generated REST module retains the Procedure's authorization and validates boundary input.
|
|
30
37
|
|
|
31
38
|
An MCP source is `{ kind: mcp, surface: public }` or admin. The selected MCP module exposes the Procedure as a snake-case tool with its description, [tool hints](procedure.md#mcp-tool-hints) and requires checks.
|
|
32
39
|
|
|
40
|
+
By default, pair every HTTP Trigger with an MCP Trigger so the same operation is reachable by the user's AI. `mantle generate` warns when a Procedure has HTTP exposure but no MCP exposure, suggesting `surface: admin` for an admin-only Procedure and `public` otherwise. Triggers still decide every Procedure surface: intentional asymmetric exposure is allowed and generation succeeds.
|
|
41
|
+
|
|
33
42
|
Lifecycle and schedule sources are rejected at generation with `GENERATE_UNSUPPORTED`, including disabled schedules. Use an app-owned handler or scheduler. For signed webhooks, verify the original raw Request in the app and call a generated Procedure with validated input; do not route it through a JSON boundary before signature verification.
|
|
34
43
|
|
|
35
44
|
## Input rules
|
|
@@ -17,10 +17,10 @@ Pin every package you use to the same exact version and upgrade them together.
|
|
|
17
17
|
|
|
18
18
|
## 0.2.0 — in preparation
|
|
19
19
|
|
|
20
|
-
### Upgrading to 0.2.0-alpha.
|
|
20
|
+
### Upgrading to 0.2.0-alpha.9
|
|
21
21
|
|
|
22
22
|
Pin every selected `@aotter/mantle`, `@aotter/mantle-ui` and
|
|
23
|
-
`@aotter/mantle-admin` dependency to `0.2.0-alpha.
|
|
23
|
+
`@aotter/mantle-admin` dependency to `0.2.0-alpha.9`, refresh the lockfile,
|
|
24
24
|
then regenerate and check the application's owned artifacts. Keep existing
|
|
25
25
|
production migrations application-owned; generated initial DDL is for an empty
|
|
26
26
|
database. This alpha includes breaking Admin authoring and paging changes.
|
|
@@ -112,7 +112,7 @@ Existing alpha.6 applications require a source migration:
|
|
|
112
112
|
application code. Review [authorization and Caller wiring](../concepts/runtime-and-adapters.md)
|
|
113
113
|
and regenerate all owned artifacts before running `generate --check`.
|
|
114
114
|
|
|
115
|
-
The [reference Worker](https://github.com/aotter/mantle/tree/v0.2.0-alpha.
|
|
115
|
+
The [reference Worker](https://github.com/aotter/mantle/tree/v0.2.0-alpha.9/docs/examples/reference-service) and
|
|
116
116
|
[app shell](../../examples/app-shell/) demonstrate the current composition.
|
|
117
117
|
The following earlier-alpha notes are historical; the current handbook and
|
|
118
118
|
the native migration above supersede their runtime and CLI instructions.
|
|
@@ -12,6 +12,14 @@ description: Generation targets, CLI options and ownership of native application
|
|
|
12
12
|
| `wrangler.jsonc` | App configuration; generator maintains selected split-build keys |
|
|
13
13
|
| `dist/` | Disposable bundle output (`dist/worker`, `dist/client`); do not commit |
|
|
14
14
|
|
|
15
|
+
## Accept user-facing work
|
|
16
|
+
|
|
17
|
+
Before reporting any user-facing deliverable as done, run the installed
|
|
18
|
+
version's [independent acceptance
|
|
19
|
+
flow](../guides/agent-workflow-acceptance.md) with a fresh agent on the surface
|
|
20
|
+
its user uses. For MCP work, also run that guide's design audit before choosing
|
|
21
|
+
tool names or writing manifests/handlers.
|
|
22
|
+
|
|
15
23
|
## Commands
|
|
16
24
|
|
|
17
25
|
```sh
|
|
@@ -37,7 +45,7 @@ Other handles may adapt to the same [structural driver contracts](../guides/adap
|
|
|
37
45
|
| `--wrangler <path>` | Existing JSONC/JSON/TOML config; default finds one or creates `wrangler.jsonc`. TOML receives manual-edit instructions. |
|
|
38
46
|
| `--entry <path>` | Worker source entry; default `src/worker.ts`. |
|
|
39
47
|
| `--outdir <path>` | Bundle output; default `dist`. The Worker goes to `<outdir>/worker`. Keep separate from source/generated files. |
|
|
40
|
-
| `--assets <path>` | With `--admin`: the static assets directory `mantle bundle` builds Admin into (`<assets>/admin`); default `<outdir>/client`. Written to Wrangler's `assets.directory`, and to the build command when not the default. |
|
|
48
|
+
| `--assets <path>` | With `--admin`: the static assets directory `mantle bundle` builds Admin into (`<assets>/admin`); default `<outdir>/client`. Written to Wrangler's `assets.directory`, and to the build command when not the default. New assets blocks default to `ASSETS`, Worker-first routing and no HTML rewriting; existing blocks keep their binding/routing. |
|
|
41
49
|
|
|
42
50
|
## Outputs
|
|
43
51
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: develop
|
|
3
|
-
description: Work on an existing Mantle 0.2 project — manifests, SQL Views and Procedures, ref handlers, the service entry, surfaces, identity and
|
|
3
|
+
description: Work on an existing Mantle 0.2 project — manifests, SQL Views and Procedures, ref handlers, the service entry, surfaces, identity, MCP tool design and independent acceptance — using the installed package's contract.
|
|
4
4
|
metadata:
|
|
5
5
|
source: "@aotter/mantle"
|
|
6
6
|
sourcePath: docs/skills/develop/SKILL.md
|
|
@@ -12,28 +12,48 @@ metadata:
|
|
|
12
12
|
|
|
13
13
|
## Workflow
|
|
14
14
|
|
|
15
|
-
Read the installed SDK README
|
|
15
|
+
Read the installed SDK README, then follow the version-matched [project and CLI
|
|
16
|
+
workflow](../../handbook/start/project-and-cli.md) before editing.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
resources; Better Auth’s admin plugin `adminRoles` defines the admin layer (default `["admin"]`); `ctx.admin` takes no role list ([authorization](../../handbook/cloudflare/authentication.md)).
|
|
22
|
-
|
|
23
|
-
Use the native Store/query/surface entries and app-owned fetch from the service composition guide.
|
|
18
|
+
Use the native Store/query/surface entries and app-owned fetch from the [service
|
|
19
|
+
composition guide](../../handbook/cloudflare/service-entry.md).
|
|
20
|
+
Pair every HTTP Trigger with an MCP Trigger by default; see [Trigger](../../handbook/reference/trigger.md)
|
|
21
|
+
for the generate warning and deliberate asymmetry exception.
|
|
24
22
|
Keep optional modules out of unused entry imports and auth dynamically loaded.
|
|
25
23
|
Run actual public/member/admin HTTP, MCP and UI scenarios; verify stored state,
|
|
26
24
|
visibility, OCC and restart persistence, not just a 200 response.
|
|
25
|
+
Before reporting any user-facing work as done, follow the [independent
|
|
26
|
+
acceptance guide](../../handbook/guides/agent-workflow-acceptance.md): run it
|
|
27
|
+
with a fresh agent on the surface its user uses. This is not limited to MCP; if
|
|
28
|
+
it was not run, say so explicitly and report the work as UNVERIFIED rather than
|
|
29
|
+
done. For MCP workflows, also run the guide's design audit before implementing
|
|
30
|
+
tools.
|
|
27
31
|
|
|
28
|
-
For native Admin, read the [current guide](../../handbook/guides/native-admin.md)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
use
|
|
32
|
+
For native Admin, read the [current guide](../../handbook/guides/native-admin.md):
|
|
33
|
+
the app builds Admin with `mantle bundle`. To customise pages, slots, hooks or
|
|
34
|
+
MCP-host-safe components, follow [Customising Admin](../../handbook/guides/native-admin.md#customising-admin).
|
|
35
|
+
Keep matching SDK, Admin and UI versions. Ref handlers retain caller-bound
|
|
36
|
+
`ctx.store`; generic Admin reads use shared generated View templates and writes
|
|
37
|
+
use native Procedure fragments.
|
|
34
38
|
Check actual member/Admin OTP, private scope/TTL/translation visibility, paging,
|
|
35
39
|
statistics, safe/exact OCC and no automatic retry after unknown 503 outcomes.
|
|
36
40
|
|
|
41
|
+
For application-owned MCP App entries and host checks, follow the [MCP Apps
|
|
42
|
+
guide](../../handbook/guides/mcp-apps.md).
|
|
43
|
+
|
|
44
|
+
Build a custom frontend with `App` from `@modelcontextprotocol/ext-apps`: register
|
|
45
|
+
`ontoolinput`/`ontoolresult` before `connect()`, and use `callServerTool` for
|
|
46
|
+
host-proxied calls. Keep protocol negotiation and message routing in the official
|
|
47
|
+
client; importing its types while writing a second `postMessage` bridge is
|
|
48
|
+
insufficient.
|
|
49
|
+
|
|
50
|
+
For Admin UI upgrades, follow the installed handbook's
|
|
51
|
+
[retained-page recipe](../../handbook/guides/mcp-apps.md#keep-old-conversations-working-after-an-upgrade).
|
|
52
|
+
Keep deployed snapshots in source/artifact storage and pass `previous` to
|
|
53
|
+
`adminMcpApps`; verify old conversations after a changed UI build without host
|
|
54
|
+
tool refresh, reconnection or cache clearing. Keep tool contracts compatible
|
|
55
|
+
through the declared retention window.
|
|
56
|
+
|
|
37
57
|
|
|
38
58
|
Place admin MCP Procedures in Admin deliberately: `spec.uiSchema.collectionAction:
|
|
39
59
|
<schema-name>` adds a collection-header action; `spec.target: { schema, id,
|
|
@@ -51,10 +71,17 @@ The runtime never creates, alters or checks tables. Boot and requests run no DDL
|
|
|
51
71
|
|
|
52
72
|
For the first install, apply generated `schema.sql`, including selected auth/site DDL, to an empty database. Apply selected seed SQL explicitly.
|
|
53
73
|
|
|
54
|
-
For every later schema change, the application's coding agent diffs the regenerated `schema.sql`, writes a migration with the host's native tool (`wrangler d1 migrations` or the app's PostgreSQL migration tool), rehearses it on a copy, and applies it before deploying the new code.
|
|
74
|
+
For every later schema change, the application's coding agent diffs the regenerated `schema.sql`, writes a migration with the host's native tool (`wrangler d1 migrations` or the app's PostgreSQL migration tool), rehearses it on a copy, and applies it before deploying the new code.
|
|
55
75
|
|
|
56
76
|
Destructive changes and type changes need explicit data migration. Mantle drops nothing. Initial `schema.sql` is not an upgrade script.
|
|
57
77
|
|
|
58
78
|
## Data paths
|
|
59
79
|
|
|
60
80
|
Writes use Store `insert` / `update` / `delete`, `batch`, `transaction`, or declared Procedures. Never use raw SQL writes: they bypass scope, TTL, publishing and system-column rules. For reads beyond an id lookup or simple AND filter (joins, aggregates, OR, reuse), declare an internal View so the SQL is reviewable and typed. Store `findById`, `find` and `first` remain suitable for handler lookups and embedding in an existing app. Ref handlers receive `ctx.store` bound to the same Caller and transaction.
|
|
81
|
+
|
|
82
|
+
For simple creates/partial updates, prefer Store-backed ref Procedures; keep
|
|
83
|
+
Procedure `requires`/generated input checks, use only allowed patch fields and
|
|
84
|
+
return safe business fields with the actual returned ID/version. Preserve
|
|
85
|
+
omitted fields and document null semantics. Retain SQL for atomic conditional
|
|
86
|
+
or related writes; D1 batches cannot consume an earlier result. Follow the
|
|
87
|
+
[Store write guidance](../../handbook/guides/typed-queries.md#prefer-store-backed-ref-procedures-for-simple-writes).
|
|
@@ -12,13 +12,8 @@ metadata:
|
|
|
12
12
|
|
|
13
13
|
## Workflow
|
|
14
14
|
|
|
15
|
-
Read the installed SDK README
|
|
16
|
-
|
|
17
|
-
Follow the installed [native generation and service workflow](../../handbook/cloudflare/service-entry.md)
|
|
18
|
-
with its [native contract](../../handbook/guides/native-execution.md) and [supported declarations](../../handbook/reference/features.md). Commit
|
|
19
|
-
all generated output, run the same generation command with `--check`, and keep
|
|
20
|
-
bundle `dist/` untracked. The app owns its verified Caller, handlers and native
|
|
21
|
-
resources; Better Auth’s admin plugin `adminRoles` defines the admin layer (default `["admin"]`); `ctx.admin` takes no role list ([authorization](../../handbook/cloudflare/authentication.md)).
|
|
15
|
+
Read the installed SDK README, then follow the version-matched [project and CLI
|
|
16
|
+
workflow](../../handbook/start/project-and-cli.md) before editing.
|
|
22
17
|
|
|
23
18
|
Keep the application router, database/pool, identity and frontend. Replace
|
|
24
19
|
Core consumers explicitly and compose only selected generated entries. Resolve
|
|
@@ -30,8 +25,8 @@ the configured OAuth resource row (see [OAuth](../../handbook/guides/oauth.md)).
|
|
|
30
25
|
Verify cutover with actual app tests.
|
|
31
26
|
|
|
32
27
|
Preserve the app router, verified identity and native resources. For selected
|
|
33
|
-
Admin
|
|
34
|
-
|
|
28
|
+
Admin, follow the [native guide](../../handbook/guides/native-admin.md) for its
|
|
29
|
+
application-built bundle and service composition.
|
|
35
30
|
Do not import old `/spec`, `/core` or runtime surface APIs. Review data/role
|
|
36
31
|
migrations explicitly; full cross-target int64 parity and automated transfer
|
|
37
32
|
are not this release's upgrade contract.
|
|
@@ -13,13 +13,8 @@ metadata:
|
|
|
13
13
|
|
|
14
14
|
## Workflow
|
|
15
15
|
|
|
16
|
-
Read the installed SDK README
|
|
17
|
-
|
|
18
|
-
Follow the installed [native generation and service workflow](../../handbook/cloudflare/service-entry.md)
|
|
19
|
-
with its [native contract](../../handbook/guides/native-execution.md) and [supported declarations](../../handbook/reference/features.md). Commit
|
|
20
|
-
all generated output, run the same generation command with `--check`, and keep
|
|
21
|
-
bundle `dist/` untracked. The app owns its verified Caller, handlers and native
|
|
22
|
-
resources; Better Auth’s admin plugin `adminRoles` defines the admin layer (default `["admin"]`); `ctx.admin` takes no role list ([authorization](../../handbook/cloudflare/authentication.md)).
|
|
16
|
+
Read the installed SDK README, then follow the version-matched [project and CLI
|
|
17
|
+
workflow](../../handbook/start/project-and-cli.md) before editing.
|
|
23
18
|
|
|
24
19
|
Deploy/create resources only within the user's authorization; reuse configured
|
|
25
20
|
host resources. Apply reviewed and rehearsed migrations before routing traffic;
|
|
@@ -30,12 +25,20 @@ as in [Workers assets and secrets](../../handbook/cloudflare/service-entry.md#wo
|
|
|
30
25
|
Keep the Workers [public-fetch flags](../../handbook/cloudflare/deploy-and-operate.md#public-fetch-routing),
|
|
31
26
|
including environment overrides; verify deployed MCP with a real OAuth bearer
|
|
32
27
|
(`initialize` and `tools/list`), not only a browser session cookie.
|
|
28
|
+
For MCP Apps, also follow [deployed host acceptance](../../handbook/guides/mcp-apps.md#verify-a-deployed-app-in-chatgpt):
|
|
29
|
+
compare the current resource URI and visibly verify a newly invoked render tool.
|
|
30
|
+
Archive deployed Admin pages using the guide's `previous` recipe and carry them
|
|
31
|
+
through clean builds. Test the same old conversation after changing the UI build,
|
|
32
|
+
without reconnecting, refreshing host tools or clearing caches. A deliberate tool
|
|
33
|
+
contract change has its own migration/host rediscovery step. OAuth renewal, `tools/call` success and a
|
|
34
|
+
local official-host replay do not establish that the deployed App rendered.
|
|
33
35
|
Bun uses native Database/SQL, an app server and scheduler. Verify admin sign-in
|
|
34
36
|
(role admin), denied access, public reads, a persisted write, MCP and selected UI.
|
|
35
37
|
Report artifact/resources/checks and keep rollback artifacts.
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
For ChatGPT Sites, follow [Mantle on ChatGPT Sites](../../handbook/cloudflare/chatgpt-sites.md).
|
|
40
|
+
|
|
41
|
+
The app builds Admin with `mantle bundle`; serve it as [Native
|
|
42
|
+
Admin](../../handbook/guides/native-admin.md) describes. Verify both member and
|
|
43
|
+
admin OTP/UI flows. Deployment of an authorized application does not authorize
|
|
44
|
+
SDK publication; a workspace preview remains a preview.
|
|
@@ -12,24 +12,25 @@ metadata:
|
|
|
12
12
|
|
|
13
13
|
## Workflow
|
|
14
14
|
|
|
15
|
-
Read the installed SDK README
|
|
15
|
+
Read the installed SDK README, then follow the version-matched [project and CLI
|
|
16
|
+
workflow](../../handbook/start/project-and-cli.md) before editing.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
resources; Better Auth’s admin plugin `adminRoles` defines the admin layer (default `["admin"]`); `ctx.admin` takes no role list ([authorization](../../handbook/cloudflare/authentication.md)).
|
|
18
|
+
For 0.1.x, follow [Upgrade 0.1 to 0.2](../../upgrade-0.1-to-0.2.md): give the
|
|
19
|
+
0.2 service a new database and move data by export and import; never boot 0.2
|
|
20
|
+
against a 0.1.x database. Between 0.2 versions, apply reviewed migrations
|
|
21
|
+
rehearsed on a copy.
|
|
22
22
|
|
|
23
|
-
Pin exact target SDK/peer versions and read its release notes and Admin
|
|
24
|
-
|
|
25
|
-
a package-only update.
|
|
26
|
-
|
|
27
|
-
migrations on a copy. Initial schema.sql never
|
|
28
|
-
tables. Verify auth/Admin/MCP/REST, locks and
|
|
23
|
+
Pin exact target SDK/peer versions and read its release notes and Admin build
|
|
24
|
+
instructions. Core-to-native replaces app imports/wiring; it is not
|
|
25
|
+
a package-only update. For 0.2-to-0.2 updates, preserve users, sessions, content
|
|
26
|
+
and application code; review emitted SQL/policy diffs and rehearse explicit
|
|
27
|
+
data-preserving schema/auth/role migrations on a copy. Initial schema.sql never
|
|
28
|
+
authorizes rebuilding production tables. Verify auth/Admin/MCP/REST, locks and
|
|
29
|
+
persistence before authorized cutover.
|
|
29
30
|
|
|
30
|
-
Follow [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
Follow [Customising Admin](../../handbook/guides/native-admin.md#customising-admin)
|
|
32
|
+
for the current application-built Admin; old UI subpaths have no compatibility
|
|
33
|
+
aliases. Pin only actually published versions, or explicitly use a matching
|
|
34
|
+
workspace preview. Recheck member and Admin OTP, all affected native routes,
|
|
35
|
+
private field visibility, OCC and unknown outcomes. Do not publish a package as
|
|
36
|
+
part of an application dependency update.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aotter/mantle",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"engines": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
}
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@modelcontextprotocol/client": "2.
|
|
95
|
+
"@modelcontextprotocol/client": "2.2.0",
|
|
96
96
|
"@modelcontextprotocol/server": "2.2.0",
|
|
97
97
|
"@better-auth/core": "1.7.7",
|
|
98
98
|
"@better-auth/oauth-provider": "1.7.7",
|
package/skills/README.md
CHANGED
|
@@ -27,7 +27,7 @@ release tag as the application's SDK; alpha releases on `develop` can be newer
|
|
|
27
27
|
than the default `main` branch. For a skill-only installation:
|
|
28
28
|
|
|
29
29
|
```sh
|
|
30
|
-
npx skills add https://github.com/aotter/mantle/tree/v0.2.0-alpha.
|
|
30
|
+
npx skills add https://github.com/aotter/mantle/tree/v0.2.0-alpha.9 --skill mantle
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
The explicit skill name excludes repository maintainer skills. The manifests
|
package/skills/mantle/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mantle
|
|
3
|
-
description: Create or
|
|
3
|
+
description: Create, continue, test or deploy a Mantle application using installed @aotter/mantle docs, including manifests, SQL Views and Procedures, MCP tools, app-built Admin, mantle generate and Mantle upgrades.
|
|
4
4
|
metadata:
|
|
5
5
|
source: "@aotter/mantle"
|
|
6
6
|
sourcePath: skills/mantle/SKILL.md
|
|
@@ -21,10 +21,29 @@ checkout, or any online copy.
|
|
|
21
21
|
|
|
22
22
|
Work in the user's application, outside the SDK checkout. Read package.json, the lockfile, installed SDK README and node_modules/@aotter/mantle/docs/. Those files define the exact version's contract. Preserve existing identity, handles, routes and resources.
|
|
23
23
|
|
|
24
|
+
## Choose the installed package skill
|
|
25
|
+
|
|
26
|
+
- Read `node_modules/@aotter/mantle/docs/skills/develop/SKILL.md` to change an existing project's manifests, SQL, handlers, service entry or surfaces.
|
|
27
|
+
- Read `node_modules/@aotter/mantle/docs/skills/integrate/SKILL.md` to add Mantle to an application with existing code, users or data.
|
|
28
|
+
- Read `node_modules/@aotter/mantle/docs/skills/update/SKILL.md` to upgrade Mantle, including from 0.1.x.
|
|
29
|
+
- Read `node_modules/@aotter/mantle/docs/skills/provision/SKILL.md` only for an authorized production deployment.
|
|
30
|
+
- Read `node_modules/@aotter/mantle/docs/skills/media-gc/SKILL.md` only to audit or remove stale uncommitted media uploads.
|
|
31
|
+
|
|
24
32
|
For a new project, install an exact published SDK version with matching selected Admin/UI packages. Node must be 22.22 or newer. Add TypeScript and target types; Workers also need Wrangler. `node_modules/@aotter/mantle/docs/examples/app-shell/package.json` lists the Wrangler, TypeScript and type-package versions this release is tested with. Optional auth/MCP peers use the installed SDK's package.json versions. Read the installed handbook's start/project-and-cli.md before choosing a target.
|
|
25
33
|
|
|
26
34
|
For a new Cloudflare app, copy `node_modules/@aotter/mantle/docs/examples/app-shell/` first, then the closest example from `docs/examples/README.md` on top of it, and edit from there: manifests, `src/handlers.ts`, `src/routes.ts`, `src/schedule.ts`, `smoke.mjs`. Search for `AGENT:` to find what the app must fill in; the example pages are unstyled on purpose, so styling them is part of that work. Before reporting done, resolve each `AGENT:` or name the ones you left. Keep the two roles `admin` and `user` unless the user asks for more.
|
|
27
35
|
|
|
36
|
+
Before reporting any user-facing work as done, follow the installed
|
|
37
|
+
`node_modules/@aotter/mantle/docs/handbook/guides/agent-workflow-acceptance.md`:
|
|
38
|
+
run independent acceptance with a fresh agent on the surface its user uses.
|
|
39
|
+
This is not limited to MCP; if it was not run, say so explicitly and report the
|
|
40
|
+
work as UNVERIFIED rather than done. For MCP workflows, also run the guide's
|
|
41
|
+
design audit before implementing tools. This workflow practice applies to every
|
|
42
|
+
installed SDK version: if its guide is older or MCP-scoped, apply its fresh-agent
|
|
43
|
+
round loop to the user-facing surface actually built. If an older installed
|
|
44
|
+
version lacks this guide, record the missing guidance and preserve that version's
|
|
45
|
+
contract; do not silently upgrade or substitute checkout/online docs.
|
|
46
|
+
|
|
28
47
|
For existing older applications, use their installed docs until the user requests an upgrade. For partial adoption read node_modules/@aotter/mantle/docs/skills/integrate/SKILL.md.
|
|
29
48
|
|
|
30
49
|
## Generated native applications
|
|
@@ -44,16 +63,16 @@ cookieCache `{enabled:true,maxAge:60,refreshCache:false,version:"read-60-v1"}` a
|
|
|
44
63
|
no KV. Bump version when enabling/changing the policy; writes, Admin, consent,
|
|
45
64
|
unknown/ref/media calls stay fresh. Read the installed auth docs before MCP caching.
|
|
46
65
|
|
|
47
|
-
Use the workflow **generate →
|
|
66
|
+
Use the workflow **generate → implement listed handlers → check**. In an app
|
|
67
|
+
copied from the installed app shell, its scripts are the canonical commands:
|
|
48
68
|
|
|
49
69
|
```sh
|
|
50
|
-
pnpm
|
|
51
|
-
pnpm
|
|
52
|
-
pnpm exec mantle generate cloudflare-d1 generated manifests/*.yaml --check
|
|
70
|
+
pnpm generate
|
|
71
|
+
pnpm check
|
|
53
72
|
```
|
|
54
|
-
|
|
73
|
+
Implement every printed `Handlers` key
|
|
55
74
|
and pass the implementations at `store(db, caller, { handlers })` (and selected
|
|
56
|
-
surface options).
|
|
75
|
+
surface options).
|
|
57
76
|
Generated Store metadata initializes on its first use, once per module. Bind
|
|
58
77
|
`store(db, caller, options?)` for the current request; never reuse one caller's
|
|
59
78
|
bound Store for another caller.
|
|
@@ -78,12 +97,12 @@ Resolve conflicts by merging manifests/options and regenerating. Add the printed
|
|
|
78
97
|
`.gitattributes` line and run the same generate command with `--check` in CI.
|
|
79
98
|
Compose the app-owned `fetch` using `docs/handbook/cloudflare/service-entry.md`: auth/consent, Admin,
|
|
80
99
|
MCP, REST behind one request-local origin-checked resolver; keep heavy auth dynamic.
|
|
100
|
+
Pair every HTTP Trigger with an MCP Trigger by default; see `docs/handbook/reference/trigger.md` for the generate warning and deliberate asymmetry exception.
|
|
81
101
|
|
|
82
102
|
For selected native Admin, follow the version-matched
|
|
83
|
-
`docs/handbook/guides/native-admin.md`: select `--admin` (or `admin: true`),
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
shared UI kit.
|
|
103
|
+
`docs/handbook/guides/native-admin.md`: select `--admin` (or `admin: true`), then
|
|
104
|
+
build and serve the application-owned Admin with `mantle bundle` as that guide
|
|
105
|
+
describes.
|
|
87
106
|
Admin reads share generated whitelisted native View templates, writes use native
|
|
88
107
|
Procedure fragments and generated checks. Ref operations retain typed `ctx.store`
|
|
89
108
|
at request time. Verify member/frontend and admin/Admin OTP, tenant/privacy/TTL,
|
|
@@ -128,8 +147,11 @@ To add Mantle to an application that has its own code, users and data, read
|
|
|
128
147
|
`node_modules/@aotter/mantle/docs/skills/integrate/SKILL.md` first.
|
|
129
148
|
|
|
130
149
|
Report the project path, the exact Mantle version, what you changed, the checks
|
|
131
|
-
you ran with their results,
|
|
150
|
+
you ran with their results, the independent acceptance verdict (CONVERGED / NOT
|
|
151
|
+
CONVERGED / BLOCKED / UNVERIFIED), and anything left for the user.
|
|
132
152
|
|
|
133
153
|
## Data paths
|
|
134
154
|
|
|
135
|
-
|
|
155
|
+
Follow the installed `docs/handbook/guides/typed-queries.md` for Store,
|
|
156
|
+
Procedure and View data paths; the service composition guide owns request-local
|
|
157
|
+
Caller binding.
|
|
@@ -13,3 +13,8 @@ Better Auth limits each email-OTP path to 3 requests/minute per IP; `authHardeni
|
|
|
13
13
|
- For selected remote MCP, use the installed `docs/examples/app-shell/smoke-kit.mjs` `assertMcpDiscovery(endpoint, { tools, headers })` in the application's smoke scenario. Derive `tools` from the generated `mcp.ts` exports, or the pure static `developerConsole.interfaces.callable` in generated `admin-descriptors.ts`; filter to the selected surface and explicitly select the expected permitted subset when application authorization narrows it. Include app-composed tools when present. Do not count `describe.targets` or reconstruct authorization rules in the harness. Assert initialized discovery and all `tools/list` pages; a 404, HTML 200, protocol error or missing expected tools must fail. Keep anonymous/member denial assertions separate. Discovery never needs a business-write `tools/call`.
|
|
14
14
|
- Supply test credentials from the application's normal authorized sign-in/test setup (the smoke kit's console OTP sign-in is valid). The discovery assertion only receives credentials: it must not acquire credentials itself, scrape other sessions or manufacture authority. Report local cookie-session discovery, OAuth Bearer/client integration and browser WebMCP as separate evidence. Cookie or WebMCP success does not prove remote OAuth/ChatGPT wiring; missing credentials leave that case unverified, not passed. Do not enable remote routes or OAuth merely to make acceptance pass.
|
|
15
15
|
- Record commands and passed/failed/blocked cases for the exact commit. Fix failures before source admission; rerun relevant checks after changing source. Packing does not run these checks and an agent's checklist is not server build attestation.
|
|
16
|
+
|
|
17
|
+
Independent acceptance for every user-facing workflow follows the installed
|
|
18
|
+
`docs/handbook/guides/agent-workflow-acceptance.md`. Scripted smoke is separate
|
|
19
|
+
evidence; browser or host rendering is the acceptance surface for UI and MCP App
|
|
20
|
+
deliverables.
|
|
@@ -7,8 +7,8 @@ selected host's frontend kit before choosing APIs. Native applications use
|
|
|
7
7
|
their installed `docs/handbook/guides/native-admin.md` and the
|
|
8
8
|
[web contract](web.md).
|
|
9
9
|
|
|
10
|
-
- For self-hosted applications,
|
|
11
|
-
|
|
10
|
+
- For self-hosted applications, build Admin with `mantle bundle` and serve it as
|
|
11
|
+
the installed `docs/handbook/guides/native-admin.md` describes. The application
|
|
12
12
|
owns auth, OTP delivery and verified Caller wiring; use a console/test sender
|
|
13
13
|
locally and configure production email for deployment. If a host already
|
|
14
14
|
supplies identity/Admin, reuse its explicit contract and reserved routes.
|
|
@@ -38,8 +38,10 @@ Follow the [local HTTP acceptance](local-testing.md) before reporting local
|
|
|
38
38
|
readiness: inspect HTML without JavaScript, check metadata/sitemap and anonymous
|
|
39
39
|
draft/permission refusal, and exercise OTP and editing with isolated synthetic
|
|
40
40
|
accounts. Local readiness does not require publication, a hosted tenant or a
|
|
41
|
-
candidate preview.
|
|
42
|
-
|
|
41
|
+
candidate preview. Scripted local acceptance does not replace the installed
|
|
42
|
+
independent acceptance guide, which is required before reporting the pages done.
|
|
43
|
+
Report production email, public origin and real object-store upload/commit checks
|
|
44
|
+
separately when local capabilities cannot exercise them.
|
|
43
45
|
|
|
44
46
|
For an explicitly requested deployment, use the selected host's native workflow
|
|
45
47
|
and any preview it provides. Verify disabled preview capabilities on an already
|