@aotter/mantle 0.1.0-alpha.1 → 0.1.0-alpha.10
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 +105 -26
- package/dist/admin.d.ts +2 -0
- package/dist/admin.d.ts.map +1 -0
- package/dist/admin.js +2 -0
- package/dist/admin.js.map +1 -0
- package/dist/bun.d.ts +2 -0
- package/dist/bun.d.ts.map +1 -0
- package/dist/bun.js +2 -0
- package/dist/bun.js.map +1 -0
- package/dist/cli/create.d.ts +2 -0
- package/dist/cli/create.d.ts.map +1 -0
- package/dist/cli/create.js +243 -0
- package/dist/cli/create.js.map +1 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +101 -0
- package/dist/cli/generate.js.map +1 -0
- package/dist/cli/harness.d.ts +3 -0
- package/dist/cli/harness.d.ts.map +1 -0
- package/dist/{harness-cli.js → cli/harness.js} +13 -8
- package/dist/cli/harness.js.map +1 -0
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/{cli.js → cli/main.js} +6 -8
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/skills.d.ts +3 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/{skills.js → cli/skills.js} +51 -6
- package/dist/cli/skills.js.map +1 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/{update.js → cli/update.js} +72 -46
- package/dist/cli/update.js.map +1 -0
- package/dist/codegen/emitMantleModule.d.ts +16 -0
- package/dist/codegen/emitMantleModule.d.ts.map +1 -0
- package/dist/codegen/emitMantleModule.js +217 -0
- package/dist/codegen/emitMantleModule.js.map +1 -0
- package/dist/codegen.d.ts +2 -0
- package/dist/codegen.d.ts.map +1 -0
- package/dist/codegen.js +2 -0
- package/dist/codegen.js.map +1 -0
- package/dist/provision/renderProvisionBundle.d.ts +70 -0
- package/dist/provision/renderProvisionBundle.d.ts.map +1 -0
- package/dist/provision/renderProvisionBundle.js +367 -0
- package/dist/provision/renderProvisionBundle.js.map +1 -0
- package/dist/provision.d.ts +2 -0
- package/dist/provision.d.ts.map +1 -0
- package/dist/provision.js +2 -0
- package/dist/provision.js.map +1 -0
- package/dist/vercel-libsql.d.ts +2 -0
- package/dist/vercel-libsql.d.ts.map +1 -0
- package/dist/vercel-libsql.js +2 -0
- package/dist/vercel-libsql.js.map +1 -0
- package/dist/vercel.d.ts +2 -0
- package/dist/vercel.d.ts.map +1 -0
- package/dist/vercel.js +2 -0
- package/dist/vercel.js.map +1 -0
- package/dist/web.d.ts +2 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +2 -0
- package/dist/web.js.map +1 -0
- package/docs/adapter-guide.md +94 -47
- package/docs/adr/0001-four-atom-manifest-model.md +48 -307
- package/docs/adr/0002-closed-enums-for-bindings.md +6 -15
- package/docs/adr/0007-ai-as-primary-author.md +6 -4
- package/docs/adr/0008-structured-diagnostic-shape.md +2 -2
- package/docs/adr/0009-consumer-supplied-manifests.md +15 -9
- package/docs/adr/0010-locale-and-translates.md +13 -8
- package/docs/adr/0011-adapter-port-spec.md +29 -21
- package/docs/adr/0012-views-as-public-rest.md +5 -9
- package/docs/adr/0014-auth-better-auth-and-multi-tenant-mcp.md +124 -43
- package/docs/adr/0018-core-starters-repository-boundary.md +22 -1
- package/docs/adr/0019-sealed-manifest-runtime-pipeline.md +204 -0
- package/docs/adr/README.md +16 -14
- package/docs/api-mcp-authorization.md +28 -42
- package/docs/assets/mantle-admin-operations.png +0 -0
- package/docs/assets/mantle-hero.jpg +0 -0
- package/docs/auth-hosting-model.md +15 -11
- package/docs/cloudflare-low-level-composition.md +30 -18
- package/docs/deferred-lifecycle-queues.md +20 -38
- package/docs/design-atoms.md +155 -401
- package/docs/labels.md +5 -3
- package/docs/media-uploads.md +9 -2
- package/docs/migration-0.1.2.md +45 -0
- package/docs/performance-harness.md +7 -6
- package/docs/release-process.md +86 -25
- package/docs/schema-indexes.md +1 -1
- package/docs/sealed-pipeline-ownership.md +100 -0
- package/package.json +84 -14
- package/skills/README.md +39 -7
- package/skills/develop/SKILL.md +31 -17
- package/skills/install/SKILL.md +26 -25
- package/skills/media-gc/SKILL.md +85 -0
- package/skills/plugin/SKILL.md +2 -1
- package/skills/provision/SKILL.md +24 -2
- package/skills/theme/SKILL.md +11 -1
- package/skills/update/SKILL.md +1 -0
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/generate.d.ts.map +0 -1
- package/dist/generate.js +0 -181
- package/dist/generate.js.map +0 -1
- package/dist/harness-cli.d.ts +0 -3
- package/dist/harness-cli.d.ts.map +0 -1
- package/dist/harness-cli.js.map +0 -1
- package/dist/skills.d.ts +0 -2
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js.map +0 -1
- package/dist/update.d.ts.map +0 -1
- package/dist/update.js.map +0 -1
- /package/dist/{generate.d.ts → cli/generate.d.ts} +0 -0
- /package/dist/{update.d.ts → cli/update.d.ts} +0 -0
package/docs/adapter-guide.md
CHANGED
|
@@ -2,20 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
This guide is the fresh-developer entry point for implementing a new mantle platform adapter.
|
|
4
4
|
|
|
5
|
-
Read this with [ADR-
|
|
5
|
+
Read this with [ADR-0019](adr/0019-sealed-manifest-runtime-pipeline.md). The source of truth for TypeScript shapes is `packages/mantle-runtime/src/domain/port/`.
|
|
6
6
|
|
|
7
7
|
Adapter packages live under `packages/adapters/<platform>/` using a plural `adapters` bucket. The npm package names stay unchanged, for example `@aotter/mantle-cloudflare`. Keep adapters in this monorepo until the runtime/spec API is stable enough that coordinated releases across separate repositories would not create version skew for starters.
|
|
8
8
|
|
|
9
|
-
## Required
|
|
9
|
+
## Required storage boundary
|
|
10
10
|
|
|
11
|
-
A
|
|
11
|
+
A storage adapter prepares one `RuntimePlan` into semantic ports:
|
|
12
12
|
|
|
13
13
|
| Contract | Source | Cloudflare example |
|
|
14
14
|
|---|---|---|
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
15
|
+
| `MantleStorageAdapter` / `PreparedMantleStorage` | `packages/mantle-runtime/src/domain/port/MantleStorageAdapter.ts` | `SqliteMantleStorageAdapter` over `D1DatabaseDriver` |
|
|
16
|
+
| `EntryRepository & EntryReader` | Existing semantic content ports | `DatabaseEntryRepository` supplied by the SQLite adapter |
|
|
17
|
+
| `ViewQueryExecutor` | `packages/mantle-runtime/src/domain/port/ViewQueryExecutor.ts` | `SqliteViewQueryExecutor` |
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
`DatabaseDriver` is only the reusable SQLite/D1 implementation seam. A
|
|
20
|
+
PostgreSQL, MongoDB, or application-owned-table adapter implements the semantic
|
|
21
|
+
ports directly; it does not emulate D1 and needs no mapping DSL. Platform types
|
|
22
|
+
such as `D1Database`, Postgres pools, and Mongo clients remain in adapter code.
|
|
19
23
|
|
|
20
24
|
## Optional capabilities
|
|
21
25
|
|
|
@@ -26,7 +30,7 @@ Optional ports are enabled only when a feature needs them:
|
|
|
26
30
|
| `MediaStorage` | `packages/mantle-runtime/src/domain/port/MediaStorage.ts` | The adapter exposes admin/MCP media upload flows. |
|
|
27
31
|
| `DeferredHookDispatcher` | `packages/mantle-runtime/src/domain/port/DeferredHookDispatcher.ts` | The adapter wants at-least-once queue delivery for `after_*` lifecycle hooks. |
|
|
28
32
|
|
|
29
|
-
Test seams such as `Clock` and `IdGenerator` are injectable through `
|
|
33
|
+
Test seams such as `Clock` and `IdGenerator` are injectable through `createMantleRuntime`, but normal adapters do not need custom implementations.
|
|
30
34
|
|
|
31
35
|
Deferred delivery is an optional, versioned wire contract. Queue acceptance is
|
|
32
36
|
not atomic with the entry write; adapters must preserve the supplied event id,
|
|
@@ -35,37 +39,72 @@ to their retry mechanism, and document poison-message/DLQ behavior. See
|
|
|
35
39
|
[Deferred lifecycle hooks on Cloudflare Queues](deferred-lifecycle-queues.md)
|
|
36
40
|
for the reference implementation and exact guarantees.
|
|
37
41
|
|
|
38
|
-
##
|
|
42
|
+
## Storage preparation
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
Compile before deployment preparation, then pass only the sealed plan:
|
|
41
45
|
|
|
42
46
|
```ts
|
|
43
|
-
import {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
import {
|
|
48
|
+
bootMantleRuntime,
|
|
49
|
+
SqliteMantleStorageAdapter,
|
|
50
|
+
} from "@aotter/mantle-runtime";
|
|
51
|
+
|
|
52
|
+
const storage = new SqliteMantleStorageAdapter(db, siteDefaults);
|
|
53
|
+
const runtime = await bootMantleRuntime({
|
|
54
|
+
plan,
|
|
55
|
+
storage,
|
|
47
56
|
handlers,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
deferredHookDispatcher,
|
|
57
|
+
ports,
|
|
58
|
+
deployment: {
|
|
59
|
+
reservedHttpPathPrefixes: selectedCapabilities.flatMap(
|
|
60
|
+
(capability) => capability.reservedHttpPathPrefixes,
|
|
61
|
+
),
|
|
62
|
+
},
|
|
55
63
|
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`bootMantleRuntime` performs one attempt and derives Procedure readiness from
|
|
67
|
+
the supplied handlers. The platform adapter remains responsible for lazy boot,
|
|
68
|
+
promise caching, retry policy, and teardown.
|
|
56
69
|
|
|
57
|
-
|
|
70
|
+
Hosts that need work between preparation and binding may keep the same stages
|
|
71
|
+
public and explicit:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const prepared = await prepareDeployment(plan, storage, {
|
|
75
|
+
handlerNames: Object.keys(handlers ?? {}),
|
|
76
|
+
});
|
|
77
|
+
const runtime = createMantleRuntime({ prepared, handlers, ports });
|
|
58
78
|
```
|
|
59
79
|
|
|
60
|
-
|
|
80
|
+
The prepared revision carries its exact plan, but exposes both `plan` and
|
|
81
|
+
`storage`; it seals the pairing invariant rather than hiding low-level host
|
|
82
|
+
capabilities. Omit `handlerNames` only for a read-only embedding that never
|
|
83
|
+
dispatches Procedures.
|
|
61
84
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
85
|
+
The official SQLite adapter runs canonical migrations, defaults, indexes, and
|
|
86
|
+
schema-View reconciliation, and skips mutation for an unchanged revision. A
|
|
87
|
+
custom adapter owns its own preparation and returns application-owned semantic
|
|
88
|
+
ports. Unsupported native View dialects fail before the adapter mutates state.
|
|
89
|
+
|
|
90
|
+
### Bun embedding
|
|
91
|
+
|
|
92
|
+
`@aotter/mantle-bun` is the minimal SQLite reference: pass an application-owned
|
|
93
|
+
`bun:sqlite` `Database` and a compiled `RuntimePlan` to `createBunMantle()`.
|
|
94
|
+
Its `handle()` returns `null` for sibling routes and a Web-standard `Response`
|
|
95
|
+
for manifest-declared public Views and HTTP Triggers. The host owns
|
|
96
|
+
`Bun.serve`, database shutdown, authentication, and CSRF policy; the adapter
|
|
97
|
+
prepares the semantic revision once and retries only after failed preparation.
|
|
98
|
+
|
|
99
|
+
### Vercel Functions embedding
|
|
100
|
+
|
|
101
|
+
`@aotter/mantle-vercel` accepts a compiled plan plus any application-owned
|
|
102
|
+
`MantleStorageAdapter` and reuses the same public View/HTTP Trigger transport as
|
|
103
|
+
Bun. It maps deferred work to Vercel Functions `waitUntil` and otherwise leaves
|
|
104
|
+
the Web Handler, auth/CSRF, and route composition to the application. The
|
|
105
|
+
optional `/libsql` subpath adapts a caller-owned remote Turso/libSQL client to
|
|
106
|
+
the canonical SQLite chain; the default entry has no database-vendor policy.
|
|
107
|
+
Vercel's read-only filesystem and writable `/tmp` are never durable state.
|
|
69
108
|
|
|
70
109
|
## HTTP and MCP surfaces
|
|
71
110
|
|
|
@@ -73,9 +112,10 @@ The runtime is a library, not an HTTP server. A new adapter must mount equivalen
|
|
|
73
112
|
|
|
74
113
|
| Surface | Adapter responsibility | Cloudflare reference |
|
|
75
114
|
|---|---|---|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
115
|
+
| Runtime HTTP endpoints | Route HTTP Triggers and public View REST endpoints into runtime use cases. | `packages/adapters/cloudflare/src/mount/mountRuntimeEndpoints.ts` |
|
|
116
|
+
| Optional Admin | Supply session/request context and assets to `mantle-admin`; mount only when selected. | `packages/adapters/cloudflare/src/mount/mountAdmin.ts` |
|
|
117
|
+
| Auth endpoints | Own sign-in/session/OAuth metadata through the adapter's Better Auth implementation selected by Admin/OAuth surfaces. | `packages/adapters/cloudflare/src/auth/createAuth.ts` |
|
|
118
|
+
| MCP endpoints | Mount `/mcp/staff` and `/mcp` behind one canonical protected resource. The adapter verifies Better Auth JWTs, normalizes the caller, re-reads the staff D1 role, then dispatches JSON-RPC. | `packages/adapters/cloudflare/src/mount/mountMcp.ts`, `auth/createAuth.ts` |
|
|
79
119
|
|
|
80
120
|
Auth is not a runtime port. Per [ADR-0014](adr/0014-auth-better-auth-and-multi-tenant-mcp.md), the adapter owns Better Auth wiring and passes authenticated user/staff context into runtime dispatchers. Procedure handlers receive that data through `HandlerContext` in `packages/mantle-runtime/src/domain/model/HandlerContext.ts`.
|
|
81
121
|
|
|
@@ -93,7 +133,7 @@ Minimum HTTP behavior for a full adapter:
|
|
|
93
133
|
- Route manifest HTTP Triggers to `runtime.invokeProcedure`.
|
|
94
134
|
- Route `GET /api/views/<name>` to `runtime.executeView`.
|
|
95
135
|
- Mount admin content APIs with session/role checks before calling runtime content use cases.
|
|
96
|
-
- Serve
|
|
136
|
+
- Serve selected Admin SPA assets through `AdminAssetServer`, with an SPA catchall for client-side routes.
|
|
97
137
|
- Mount public render routes and markdown mirrors when the starter exposes public pages.
|
|
98
138
|
- Translate runtime diagnostics and validation failures into stable HTTP JSON responses instead of throwing raw errors.
|
|
99
139
|
- Evaluate target auth and dynamic guards through the runtime use cases; do
|
|
@@ -101,22 +141,27 @@ Minimum HTTP behavior for a full adapter:
|
|
|
101
141
|
|
|
102
142
|
For the Cloudflare adapter, public rendering requires three matching consumer
|
|
103
143
|
inputs: `mountPublicRoutes(...)` route declarations, a `TemplateRegistry`
|
|
104
|
-
passed through `
|
|
105
|
-
`
|
|
144
|
+
passed through `MantleCloudflareConfig.templates`, and a `publicPathResolver`
|
|
145
|
+
passed through `MantleCloudflareConfig.publicPathResolver`. Omitting public routes is valid for a headless
|
|
106
146
|
consumer; mounting every Schema automatically is not, because some collections
|
|
107
147
|
are private even when they contain a slug.
|
|
108
148
|
|
|
149
|
+
`TemplateRegistry` and `createPublicPathResolver` come from
|
|
150
|
+
`@aotter/mantle-web`. Other adapters can call `createMantleWeb(runtime)` and map
|
|
151
|
+
its document operations into their own routing and cache conventions.
|
|
152
|
+
|
|
109
153
|
### HTTP cache contract
|
|
110
154
|
|
|
111
|
-
The Cloudflare adapter is private by default. Consumers must
|
|
112
|
-
|
|
113
|
-
|
|
155
|
+
The Cloudflare adapter is private by default. Consumers must apply its final
|
|
156
|
+
cache policy after admin, auth, API, OAuth, MCP, application routes, redirects,
|
|
157
|
+
and errors.
|
|
114
158
|
Those responses receive `Cache-Control: private, no-store`; Cloudflare-specific
|
|
115
159
|
CDN cache overrides are removed.
|
|
116
160
|
|
|
117
161
|
`mountPublicRoutes(...)` renders canonical D1 state and opts only successful HTML, markdown,
|
|
118
162
|
`llms.txt`, and sitemap responses into the shared cache with
|
|
119
|
-
`Cache-Control: public, max-age=0, s-maxage=300
|
|
163
|
+
`Cache-Control: public, max-age=0, s-maxage=300` and the site-level
|
|
164
|
+
`Cache-Tag: mantle-public`. The top-level policy preserves
|
|
120
165
|
that opt-in only for anonymous `GET`/`HEAD` responses with status 200, explicit
|
|
121
166
|
shared freshness, no request `Cookie` or `Authorization`, and no response
|
|
122
167
|
`Set-Cookie`. It also varies public responses by `Cookie` and `Authorization`.
|
|
@@ -124,7 +169,10 @@ shared freshness, no request `Cookie` or `Authorization`, and no response
|
|
|
124
169
|
A starter-level Workers Cache may therefore store only responses that still
|
|
125
170
|
meet that exact public contract. It must bypass credentialed/cookie requests
|
|
126
171
|
and must never infer cacheability from a URL prefix. Cache entries remain
|
|
127
|
-
version-local; cross-version caching is outside this contract.
|
|
172
|
+
version-local; cross-version caching is outside this contract. Successful
|
|
173
|
+
publishing-content and site-setting mutations purge `mantle-public` through
|
|
174
|
+
Cloudflare's native cache API. Operational records and immutable assets do not
|
|
175
|
+
purge the public render cache.
|
|
128
176
|
|
|
129
177
|
Minimum auth/MCP behavior:
|
|
130
178
|
|
|
@@ -142,20 +190,19 @@ Minimum auth/MCP behavior:
|
|
|
142
190
|
|
|
143
191
|
## Static assets
|
|
144
192
|
|
|
145
|
-
`
|
|
193
|
+
`AdminAssetServer` belongs to optional `@aotter/mantle-admin`. Headless Core
|
|
194
|
+
storage preparation and binding do not accept or require a static asset port.
|
|
146
195
|
|
|
147
196
|
## Implementation checklist
|
|
148
197
|
|
|
149
|
-
- [ ] Implement `
|
|
150
|
-
- [ ]
|
|
151
|
-
- [ ] Compose `createCmsRuntime` with manifests, handlers, templates, site defaults, and required ports.
|
|
152
|
-
- [ ] Call `bootInit()` before serving CMS traffic.
|
|
198
|
+
- [ ] Implement `MantleStorageAdapter` returning existing semantic ports, or reuse `SqliteMantleStorageAdapter` with an already-owned handle.
|
|
199
|
+
- [ ] Call `bootMantleRuntime()` once per semantic revision, or explicitly prepare before binding.
|
|
153
200
|
- [ ] Mount HTTP Trigger and View REST surfaces.
|
|
154
201
|
- [ ] Mount admin/public render routes and admin SPA assets.
|
|
155
202
|
- [ ] Provide adapter-owned Better Auth wiring and session helpers.
|
|
156
203
|
- [ ] Normalize session/OAuth and any consumer credential seam into
|
|
157
204
|
`HandlerContext.auth`; never put raw credentials in runtime context.
|
|
158
|
-
- [ ] Mount `/mcp/staff` and `/mcp`
|
|
205
|
+
- [ ] Mount `/mcp/staff` and `/mcp` behind one resource-bound token verifier. Enforce the live staff role inside the apiHandler.
|
|
159
206
|
- [ ] Preserve the HTTP cache contract: private by default; explicit anonymous 200 `GET`/`HEAD` public opt-in only.
|
|
160
207
|
- [ ] Prove one guarded target has identical REST/MCP outcomes, including
|
|
161
208
|
mutable revocation on the next call.
|
|
@@ -170,4 +217,4 @@ Minimum auth/MCP behavior:
|
|
|
170
217
|
- Do not add API-key, personal-token, transaction, billing, or entitlement
|
|
171
218
|
repositories to Core. They are consumer state behind the adapter resolver
|
|
172
219
|
and guard Procedure.
|
|
173
|
-
- Do not
|
|
220
|
+
- Do not generalize `DatabaseDriver` for PostgreSQL/MongoDB or add a mapping DSL. Implement semantic ports; SQLite/D1 alone reuse the canonical SQL chain.
|