@aotter/mantle 0.1.0-alpha.7 → 0.1.0-alpha.8
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 +68 -30
- 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 +88 -45
- package/docs/adr/0001-four-atom-manifest-model.md +11 -3
- package/docs/adr/0007-ai-as-primary-author.md +3 -3
- package/docs/adr/0009-consumer-supplied-manifests.md +9 -4
- package/docs/adr/0011-adapter-port-spec.md +18 -4
- package/docs/adr/0014-auth-better-auth-and-multi-tenant-mcp.md +111 -6
- 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 +12 -10
- package/docs/api-mcp-authorization.md +21 -42
- package/docs/assets/mantle-admin-operations.png +0 -0
- package/docs/assets/mantle-hero.jpg +0 -0
- package/docs/auth-hosting-model.md +5 -5
- package/docs/cloudflare-low-level-composition.md +30 -18
- package/docs/deferred-lifecycle-queues.md +20 -38
- package/docs/design-atoms.md +31 -133
- package/docs/labels.md +1 -1
- package/docs/media-uploads.md +2 -2
- package/docs/migration-0.1.2.md +45 -0
- package/docs/performance-harness.md +4 -4
- package/docs/release-process.md +72 -22
- package/docs/sealed-pipeline-ownership.md +100 -0
- package/package.json +84 -14
- package/skills/README.md +38 -7
- package/skills/develop/SKILL.md +7 -5
- package/skills/install/SKILL.md +26 -25
- package/skills/media-gc/SKILL.md +6 -0
- package/skills/plugin/SKILL.md +1 -0
- package/skills/provision/SKILL.md +2 -0
- package/skills/theme/SKILL.md +1 -0
- 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 -226
- 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/design-atoms.md
CHANGED
|
@@ -25,7 +25,7 @@ primitives Postgres has shipped for 30 years.
|
|
|
25
25
|
|---|---|---|---|
|
|
26
26
|
| **`Schema`** | `CREATE TABLE` | no (manipulated via View / Procedure) | no |
|
|
27
27
|
| **`View`** | `CREATE VIEW` | **yes** (auto-mounted on its declared public/staff REST and MCP surface; see ADR-0012) | no |
|
|
28
|
-
| **`Procedure`** | `CREATE FUNCTION ... LANGUAGE plpgsql` | **no** (transport-agnostic; needs a `Trigger` to bind it) | **yes — handler ref to consumer's
|
|
28
|
+
| **`Procedure`** | `CREATE FUNCTION ... LANGUAGE plpgsql` | **no** (transport-agnostic; needs a `Trigger` to bind it) | **yes — handler ref to the consumer's registry** |
|
|
29
29
|
| **`Trigger`** | `CREATE TRIGGER` + route/tool binding | yes (the binding atom — turns Procedures into HTTP endpoints, MCP tools, and lifecycle hooks) | no |
|
|
30
30
|
|
|
31
31
|
The **read/write asymmetry is by design** and matches HTTP safe-vs-unsafe
|
|
@@ -45,15 +45,14 @@ these four plus your own TypeScript.
|
|
|
45
45
|
apiVersion: cms.mantle.aotter.net/v1
|
|
46
46
|
kind: Schema | View | Procedure | Trigger
|
|
47
47
|
metadata:
|
|
48
|
-
name: posts # required,
|
|
48
|
+
name: posts # required, non-empty, unique within its kind
|
|
49
49
|
spec:
|
|
50
50
|
... # kind-specific
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
There is **no `namespace` field**. Resource names are unique within
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
`tenant_id` column gated by RBAC, not in the SDK metadata layer.
|
|
53
|
+
There is **no manifest `namespace` field**. Resource names are unique within
|
|
54
|
+
their kind, so a Schema and View may share a name. SaaS multi-tenancy belongs
|
|
55
|
+
in the consumer's app layer, not in manifest metadata.
|
|
57
56
|
|
|
58
57
|
### Multi-doc YAML — keeping file count down
|
|
59
58
|
|
|
@@ -65,7 +64,7 @@ A logical feature commonly bundles a Procedure + a Trigger (and often a
|
|
|
65
64
|
Schema and a View). Put related atoms in one file separated by `---`:
|
|
66
65
|
|
|
67
66
|
```yaml
|
|
68
|
-
# manifests/
|
|
67
|
+
# manifests/contact.yml
|
|
69
68
|
apiVersion: cms.mantle.aotter.net/v1
|
|
70
69
|
kind: Procedure
|
|
71
70
|
metadata: { name: send-contact-message }
|
|
@@ -85,8 +84,9 @@ spec:
|
|
|
85
84
|
target: { procedure: send-contact-message }
|
|
86
85
|
```
|
|
87
86
|
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
Use one file or split features across files. Mantle reads every immediate
|
|
88
|
+
`.yaml` and `.yml` file in `./manifests` by default; `---` separates multiple
|
|
89
|
+
documents in one file.
|
|
90
90
|
|
|
91
91
|
## What each atom is for (v0.1 minimum essential grammar)
|
|
92
92
|
|
|
@@ -128,6 +128,10 @@ spec:
|
|
|
128
128
|
in the user's primary language (the install-time chosen locale); the
|
|
129
129
|
SPA shows this everywhere instead of `metadata.name`.
|
|
130
130
|
|
|
131
|
+
Schema titles and optional descriptions accept either a string or a locale
|
|
132
|
+
map such as `{ en: Products, "zh-TW": 商品 }`. Procedure titles and
|
|
133
|
+
descriptions and View titles use the same shape; all are optional.
|
|
134
|
+
|
|
131
135
|
**`spec.searchableFields`** — optional allowlist of top-level string
|
|
132
136
|
properties used by Admin and Staff MCP substring search. Entry id is always
|
|
133
137
|
searchable. This is separate from `indexes`; ordinary B-tree indexes do not
|
|
@@ -208,9 +212,9 @@ extensions. Three are part of `cms.mantle.aotter.net/v1`:
|
|
|
208
212
|
> See ADR-0002 for rationale — why this is a closed enum and not an
|
|
209
213
|
> open expression language.
|
|
210
214
|
|
|
211
|
-
Marks a property as **server-controlled**.
|
|
212
|
-
|
|
213
|
-
|
|
215
|
+
Marks a property as **server-controlled**. On create, the SDK overwrites any
|
|
216
|
+
caller value with the bound value; updates preserve the existing stamp. This
|
|
217
|
+
eliminates the entire
|
|
214
218
|
class of handler-side `userId: ctx.user.id` boilerplate, and gives
|
|
215
219
|
the dispatcher an authoritative "who/when" tag without trusting the
|
|
216
220
|
wire.
|
|
@@ -221,13 +225,11 @@ wire.
|
|
|
221
225
|
|---|---|---|
|
|
222
226
|
| `ctx.user` | UUID of the signed-in end-user (from session cookie); `null` if anonymous | row ownership: `authorId`, `submittedBy`, `creatorId` |
|
|
223
227
|
| `ctx.staff` | UUID of the staff member acting (when a staff session is active); `null` for end-user-only paths | audit trail: `approvedBy`, `moderatedBy`, `grantedBy` |
|
|
224
|
-
| `now` | Server timestamp at write (
|
|
228
|
+
| `now` | Server timestamp at write (Unix epoch milliseconds) | `createdAt`, `submittedAt`, `grantedAt` |
|
|
225
229
|
|
|
226
230
|
**v0.1 stamping behavior**:
|
|
227
231
|
- Stamped on `INSERT` only.
|
|
228
|
-
- Caller-supplied value:
|
|
229
|
-
effective input schema strips bound fields before checking caller
|
|
230
|
-
input, so callers can't accidentally send them.
|
|
232
|
+
- Caller-supplied create value: ignored and replaced by the server stamp.
|
|
231
233
|
- Visible in View output: yes, as ordinary columns. No special masking.
|
|
232
234
|
|
|
233
235
|
**Why a closed enum** (highest-leverage discipline in the spec): bind
|
|
@@ -241,9 +243,9 @@ named bounds the semantic surface forever.
|
|
|
241
243
|
properties:
|
|
242
244
|
title: { type: string, minLength: 1, maxLength: 200 }
|
|
243
245
|
authorId: { type: string, format: uuid, x-mantle-bind: ctx.user }
|
|
244
|
-
createdAt: { type:
|
|
246
|
+
createdAt: { type: integer, x-mcp-hint: timestamp-ms, x-mantle-bind: now }
|
|
245
247
|
# caller sends only: { title }
|
|
246
|
-
# SDK stamps: { title, authorId: <session UUID>, createdAt: <
|
|
248
|
+
# SDK stamps: { title, authorId: <session UUID>, createdAt: <epoch ms> }
|
|
247
249
|
```
|
|
248
250
|
|
|
249
251
|
#### `x-mantle-ref: <other-schema-name>` — cross-Schema reference
|
|
@@ -582,9 +584,8 @@ That split is intentional and load-bearing.
|
|
|
582
584
|
draft-2020-12 JSON Schema documents. This is what AI authors and
|
|
583
585
|
human authors write, what the admin UI feeds JSON Forms, and what
|
|
584
586
|
the OpenAPI emitter relays unchanged.
|
|
585
|
-
- **Runtime engine** = zod
|
|
586
|
-
package ships a JSON-Schema → zod converter
|
|
587
|
-
(`src/json-schema-zod.ts`); the runtime calls the converted zod
|
|
587
|
+
- **Runtime engine** = zod 4. The `@aotter/mantle-spec`
|
|
588
|
+
package ships a JSON-Schema → zod converter; the runtime calls the converted zod
|
|
588
589
|
schema on every Procedure invocation, View parameter parse, and
|
|
589
590
|
manifest boot check.
|
|
590
591
|
|
|
@@ -657,119 +658,16 @@ thing as a composition of the four; almost always it works.
|
|
|
657
658
|
> fold into JSON Schema inside `Schema` rather than becoming new
|
|
658
659
|
> kinds.
|
|
659
660
|
|
|
660
|
-
Postgres exposes ~25 object kinds total; an application developer
|
|
661
|
-
|
|
662
|
-
Cloudflare D1 / KV abstract away.
|
|
663
|
-
|
|
664
|
-
## Storage backend — D1 today, Postgres-via-Hyperdrive tomorrow
|
|
665
|
-
|
|
666
|
-
> See the `mantle-cloudflare` README for rationale — why D1 for
|
|
667
|
-
> v0.1 (no-CC OSS onboarding, platform-native), and the documented
|
|
668
|
-
> PG path.
|
|
669
|
-
|
|
670
|
-
### How `Schema` data is stored on D1 today
|
|
671
|
-
|
|
672
|
-
All collections share one `entries` table (defined by the
|
|
673
|
-
Cloudflare adapter's storage migrations in
|
|
674
|
-
`@aotter/mantle-cloudflare`):
|
|
675
|
-
|
|
676
|
-
```sql
|
|
677
|
-
CREATE TABLE entries (
|
|
678
|
-
id TEXT PRIMARY KEY,
|
|
679
|
-
collection TEXT NOT NULL, -- discriminator: 'posts', 'comments', ...
|
|
680
|
-
status TEXT NOT NULL, -- 'draft' / 'published' / ...
|
|
681
|
-
version INTEGER NOT NULL,
|
|
682
|
-
data TEXT NOT NULL, -- JSON blob: every Schema property (incl. locale, per ADR-0010)
|
|
683
|
-
created_at INTEGER NOT NULL,
|
|
684
|
-
updated_at INTEGER NOT NULL,
|
|
685
|
-
author_id TEXT REFERENCES users(id)
|
|
686
|
-
);
|
|
687
|
-
```
|
|
661
|
+
Postgres exposes ~25 object kinds total; an application developer typically
|
|
662
|
+
only writes 4–6 of them. The rest belong behind the selected storage adapter.
|
|
688
663
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
`uniqueIndexes` and ordered, non-unique `indexes` declarations compile
|
|
697
|
-
into affinity-correct virtual generated columns plus partial B-tree
|
|
698
|
-
indexes via the spec engine's DDL emitter (`@aotter/mantle-spec`).
|
|
699
|
-
Different collections coexist on the same table without colliding
|
|
700
|
-
because each generated-column expression is gated by `WHEN collection
|
|
701
|
-
= '<name>'`. See [Schema indexes on D1](schema-indexes.md) for the
|
|
702
|
-
grammar, leftmost-prefix rules, SQL helper, and query-plan examples.
|
|
703
|
-
|
|
704
|
-
### What works well on D1
|
|
705
|
-
|
|
706
|
-
- D1's SQLite has the **JSON1 extension built in**: `json_extract`,
|
|
707
|
-
`json_each`, `json_object`, `json_array`, `json_set`, `json_valid`,
|
|
708
|
-
plus `->` / `->>` operators.
|
|
709
|
-
- Reserved-column queries (`status = 'published'`, `ORDER BY
|
|
710
|
-
updated_at`) use native indexes — fast.
|
|
711
|
-
- `uniqueIndexes`- and `indexes`-declared paths use virtual columns +
|
|
712
|
-
partial indexes. Core-compiled Views and repository lookups reference
|
|
713
|
-
those columns instead of repeating `json_extract`.
|
|
714
|
-
|
|
715
|
-
### Where D1's JSON support has limits (vs Postgres)
|
|
716
|
-
|
|
717
|
-
| Concern | D1 / SQLite | Postgres |
|
|
718
|
-
|---|---|---|
|
|
719
|
-
| JSON storage | TEXT — re-parsed on every `json_extract` | JSONB — stored as compact binary; faster repeated extraction |
|
|
720
|
-
| Index any JSON path | must declare each path explicitly via virtual column + index | GIN index on JSONB indexes all paths automatically |
|
|
721
|
-
| Array containment | `EXISTS (SELECT 1 FROM json_each(...) WHERE value = ?)` — full scan unless indexed | `data @> ARRAY[x]` with GIN — native operator |
|
|
722
|
-
| Path operators | `->`, `->>` only | `->`, `->>`, `#>`, `#>>`, `@>`, `?`, `?|`, `?&` |
|
|
723
|
-
| `DEFAULT now()` | not at column level — SDK-stamped via `x-mantle-bind: now` | native column default |
|
|
724
|
-
| Foreign key on JSON path | not supported on `VIRTUAL` columns; needs `STORED` (extra space) | not natively, but B-tree on expression OK |
|
|
725
|
-
| Row-level security | none — SDK-side filter rewriting | native RLS policies |
|
|
726
|
-
| Multi-statement transactions | session API serializes; not true ACID across statements | full ACID transactions |
|
|
727
|
-
|
|
728
|
-
### Practical scale envelope on D1
|
|
729
|
-
|
|
730
|
-
- **Blog-scale (< 10k entries / collection)**: today's design is
|
|
731
|
-
comfortable. Anonymous public responses can hit version-local Workers
|
|
732
|
-
Cache before the Worker; origin misses use indexed D1 reads.
|
|
733
|
-
- **Mid-scale (10k – 100k entries)**: declare measured list/filter
|
|
734
|
-
access paths with ordered `indexes`.
|
|
735
|
-
- **Hard D1 limits**: 1 MB max row size; 5,000 rows per query result;
|
|
736
|
-
single-writer per database (concurrent writes serialize).
|
|
737
|
-
- **Cross-region read**: D1 is region-pinned; first origin hit from a
|
|
738
|
-
far region may pay replica latency. Eligible anonymous responses are
|
|
739
|
-
then served by version-local Workers Cache.
|
|
740
|
-
|
|
741
|
-
### Scale-up path: D1 → Postgres via Cloudflare Hyperdrive
|
|
742
|
-
|
|
743
|
-
Cloudflare does not run a first-party Postgres service. The supported
|
|
744
|
-
path when D1 limits bind is **Cloudflare Hyperdrive** (a connection
|
|
745
|
-
pooler + query-cache that lets a Worker connect to any external
|
|
746
|
-
Postgres at near-edge latency):
|
|
747
|
-
|
|
748
|
-
- **Neon** (serverless Postgres with scale-to-zero) — closest
|
|
749
|
-
ergonomic match; tightest CF integration.
|
|
750
|
-
- **Supabase** (PG + auth + storage) — works out of the box.
|
|
751
|
-
- **AWS RDS / Google Cloud SQL / Azure DB / self-hosted PG** — also
|
|
752
|
-
supported via Hyperdrive.
|
|
753
|
-
|
|
754
|
-
When this path is taken (post-v0.1; not implemented yet), the
|
|
755
|
-
**author-facing YAML stays unchanged**. The SDK's compile target swaps:
|
|
756
|
-
|
|
757
|
-
| What changes (SDK runtime) | Author impact |
|
|
758
|
-
|---|---|
|
|
759
|
-
| `data TEXT` → `data JSONB` | none |
|
|
760
|
-
| Virtual generated columns → optional (PG can use GIN) | author may stop declaring `indexes` if defaults suffice; the same YAML remains valid |
|
|
761
|
-
| `json_each` → array operators (`@>`, `&&`) | none — predicates stay declarative |
|
|
762
|
-
| SDK-stamped `now` → `DEFAULT now()` (optional) | none |
|
|
763
|
-
| SDK-side policy rewriting → native RLS (optional) | none |
|
|
764
|
-
|
|
765
|
-
Migration shape: `entries` table dumped from D1, restored to PG. Stay
|
|
766
|
-
single-table-with-discriminator (drop-in) or split into
|
|
767
|
-
table-per-collection (more PG-idiomatic, longer migration). Both shapes
|
|
768
|
-
remain valid `cms.mantle.aotter.net/v1` deployments.
|
|
769
|
-
|
|
770
|
-
**v0.1 commitment**: D1 only via the Cloudflare adapter. Hyperdrive +
|
|
771
|
-
PG is an upgrade route, not an implemented adapter. SDKs and starters target
|
|
772
|
-
D1 exclusively.
|
|
664
|
+
## Storage adapters
|
|
665
|
+
|
|
666
|
+
Manifests compile to semantic storage ports; they do not select a database.
|
|
667
|
+
Use the shared SQLite adapter for SQLite-compatible hosts, or implement the
|
|
668
|
+
same ports over PostgreSQL, MongoDB, or existing application repositories.
|
|
669
|
+
See the [adapter guide](adapter-guide.md); SQLite index lowering is documented
|
|
670
|
+
separately in [Schema indexes](schema-indexes.md).
|
|
773
671
|
|
|
774
672
|
## Detailed shipped grammar
|
|
775
673
|
|
package/docs/labels.md
CHANGED
|
@@ -26,7 +26,7 @@ For package README or package-local docs changes, prefer the package area label
|
|
|
26
26
|
|
|
27
27
|
| Label | Meaning |
|
|
28
28
|
|---|---|
|
|
29
|
-
| `area:runtime` | `packages/mantle-runtime` behavior, ports, use cases, dispatcher,
|
|
29
|
+
| `area:runtime` | `packages/mantle-runtime` behavior, ports, use cases, dispatcher, and MCP runtime. |
|
|
30
30
|
| `area:spec` | `packages/mantle-spec`, manifest parsing, validation, diagnostics, CLI, spec types. |
|
|
31
31
|
| `area:cf` | `packages/adapters/cloudflare`, Workers adapter, D1/KV/ASSETS wiring, Cloudflare deploy behavior. |
|
|
32
32
|
| `area:starters` | External `aotter/mantle-starters` integration, release fanout, and the local moved-starter stub. |
|
package/docs/media-uploads.md
CHANGED
|
@@ -78,7 +78,7 @@ wrangler secret put R2_SECRET_ACCESS_KEY
|
|
|
78
78
|
## `src/mantle/config.ts`
|
|
79
79
|
|
|
80
80
|
```ts
|
|
81
|
-
import { R2MediaStorage, type
|
|
81
|
+
import { R2MediaStorage, type MantleCloudflareConfig } from "@aotter/mantle/cloudflare";
|
|
82
82
|
import { AwsClient } from "aws4fetch";
|
|
83
83
|
|
|
84
84
|
export interface Env {
|
|
@@ -89,7 +89,7 @@ export interface Env {
|
|
|
89
89
|
readonly MEDIA_PUBLIC_URL_BASE?: string;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
function buildMediaStorage(env: Env):
|
|
92
|
+
function buildMediaStorage(env: Env): MantleCloudflareConfig["bindings"]["mediaStorage"] {
|
|
93
93
|
if (
|
|
94
94
|
!env.MEDIA_BUCKET ||
|
|
95
95
|
!env.R2_ACCOUNT_ID ||
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Migrating from 0.1.0-alpha.7 to 0.1.2
|
|
2
|
+
|
|
3
|
+
0.1.2 removes the temporary full-site compatibility stack. Mantle Core is now
|
|
4
|
+
an embeddable parse → link → compile → prepare → bind pipeline; Web, Admin,
|
|
5
|
+
Admin UI, Bun, Vercel, and Cloudflare are selected separately.
|
|
6
|
+
|
|
7
|
+
| alpha.7 | 0.1.2 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `parseManifests*` | `parseManifestSources({ sources })` |
|
|
10
|
+
| raw `Manifest[]` validation/runtime input | `ParsedManifestSet` → `LinkedManifestSet` → `RuntimePlan` |
|
|
11
|
+
| `createCmsRuntime({ manifests, db })` | `bootMantleRuntime({ plan, storage })`, or explicit prepare then `createMantleRuntime({ prepared })` |
|
|
12
|
+
| `CmsRuntime.db` / `entryReader` | keep the application DB handle; use `runtime.entries` for Mantle reads |
|
|
13
|
+
| generated `manifest`, `site.ts`, `types.d.ts` | generated `plan`, `createMantle`, `bindMantle`, and types in `mantle.ts` |
|
|
14
|
+
| `mantle introspect` | install `@aotter/mantle-spec` directly and run `mantle-spec introspect` |
|
|
15
|
+
| `mantle emit-types` | use `mantle generate`; for raw declarations, run `mantle-spec emit-types` |
|
|
16
|
+
| generated `.agent/skills/` | generated `.agents/skills/`; legacy user files are left untouched |
|
|
17
|
+
| `bindMantleSite` / string-keyed Views | `bindMantle(runtime)` and generated lower-camel properties |
|
|
18
|
+
| `createCmsRef` / `CmsConfig` | `createMantleRuntimeRef` / `MantleCloudflareConfig` |
|
|
19
|
+
| `mountServerEndpoints` | explicitly compose `mountRuntimeEndpoints` and optional `mountAdmin` |
|
|
20
|
+
|
|
21
|
+
Delete stale generated `site.ts` and `types.d.ts` files once, then run
|
|
22
|
+
`mantle generate`. Install only the optional package used by the host;
|
|
23
|
+
installing the umbrella alone now pulls only Spec and Runtime.
|
|
24
|
+
|
|
25
|
+
Intentional behavior changes:
|
|
26
|
+
|
|
27
|
+
- Generated-plan fingerprint or version mismatches fail immediately and ask
|
|
28
|
+
the developer to regenerate.
|
|
29
|
+
- Runtime HTTP trigger JSON bodies must be objects. Arrays and primitives are
|
|
30
|
+
rejected at the request boundary.
|
|
31
|
+
- Malformed percent-encoded paths are routing misses (`404`), not claimed
|
|
32
|
+
Mantle routes.
|
|
33
|
+
- Better Auth and every `@better-auth/*` package move together to 1.7.
|
|
34
|
+
`oauthProvider.validAudiences` becomes protected `resources`; MCP uses one
|
|
35
|
+
canonical `${PUBLIC_ORIGIN}/mcp` resource and CIMD client discovery.
|
|
36
|
+
- The Cloudflare adapter no longer requires `OAUTH_KV` or
|
|
37
|
+
`@cloudflare/workers-oauth-provider`. Old opaque tokens and KV registrations
|
|
38
|
+
cannot be migrated safely and must reconnect.
|
|
39
|
+
- Canonical plan ordering may change stable field/export order (including
|
|
40
|
+
Admin CSV columns) without changing field values.
|
|
41
|
+
|
|
42
|
+
This alpha changes the Better Auth D1 schema, including required account
|
|
43
|
+
issuer identity and OAuth resource/client tables. Reset and re-bootstrap a
|
|
44
|
+
pre-1.7 alpha auth database; do not guess an issuer backfill. Content tables
|
|
45
|
+
remain portable through the normal application migration/export path.
|
|
@@ -10,16 +10,16 @@ make a normal content/API/page change.
|
|
|
10
10
|
| Read or state | Owner | Notes |
|
|
11
11
|
|---|---|---|
|
|
12
12
|
| Entry get/list and public slug/data-field/published reads | `DatabaseEntryRepository` through `EntryRepository` / `EntryReader` | Schema-aware field resolution is shared here. |
|
|
13
|
-
| Manifest View execution | `ExecuteViewUseCase` + `
|
|
13
|
+
| Manifest View execution | `ExecuteViewUseCase` + prepared `ViewQueryExecutor` | Core owns authorization and request validation; selected storage lowers queries once and resolves declared Schema indexes. |
|
|
14
14
|
| Editable settings and code-owned locale/media policy | `DatabaseSiteConfigRepository` | Editable values and dynamic media tool policy are read fresh; boot-seeded locale policy may be memoized within the runtime instance. |
|
|
15
15
|
| Pending media uploads | `DatabasePendingUploadRepository` | Canonical, read-after-write D1 state; never publish-cache state. |
|
|
16
16
|
| Rendered HTML, Markdown, and `llms.txt` | Request-time render use cases plus the Cloudflare public-route cache policy | D1 is canonical; version-local Workers Cache stores anonymous HTTP responses. |
|
|
17
17
|
| D1 transport and optional query metrics | Cloudflare bindings | Bindings stay thin. Query/cache policy does not belong in a generic provider `BaseRepository`. |
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
The runtime exposes no raw database handle. Application and adapter code uses
|
|
20
|
+
the sealed plan, runtime use cases, `entries`, and `siteConfig`. An application may own
|
|
21
21
|
additional tables behind its own repository at the composition root, but it
|
|
22
|
-
must not query Mantle-owned tables
|
|
22
|
+
must not query Mantle-owned tables outside the selected storage adapter.
|
|
23
23
|
|
|
24
24
|
## Cache contract
|
|
25
25
|
|
package/docs/release-process.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Release process
|
|
2
2
|
|
|
3
|
-
Mantle
|
|
4
|
-
versions, Git tags, GitHub releases, and Starter tags are
|
|
5
|
-
bad release with the next version, never by replacing
|
|
3
|
+
Mantle remains prerelease software until the stable v0.1.0 gate closes.
|
|
4
|
+
Published package versions, Git tags, GitHub releases, and Starter tags are
|
|
5
|
+
immutable: repair a bad release with the next version, never by replacing
|
|
6
|
+
public state.
|
|
6
7
|
|
|
7
8
|
## Authority
|
|
8
9
|
|
|
@@ -15,10 +16,12 @@ The controller owns this order:
|
|
|
15
16
|
```text
|
|
16
17
|
Core source + exact-packed Starter gates
|
|
17
18
|
-> Core tag
|
|
18
|
-
-> npmjs + GitHub Packages
|
|
19
|
+
-> npmjs + GitHub Packages candidate packages (`mantle-release`)
|
|
19
20
|
-> Starter release worker
|
|
20
21
|
-> immutable Starter tag
|
|
21
22
|
-> public-registry Starter gate
|
|
23
|
+
-> clean-create + reviewed Landing compatibility gates
|
|
24
|
+
-> npmjs + GitHub Packages public channel promotion
|
|
22
25
|
-> Core GitHub Release
|
|
23
26
|
-> optional Landing worker
|
|
24
27
|
```
|
|
@@ -45,6 +48,34 @@ verdict expires when that SHA changes. After two patch rounds, a new
|
|
|
45
48
|
foundational blocker returns to the state table and the user for a scope
|
|
46
49
|
decision instead of starting another local redesign loop.
|
|
47
50
|
|
|
51
|
+
For the candidate-to-channel transition, the controller follows this finite
|
|
52
|
+
state table:
|
|
53
|
+
|
|
54
|
+
| Durable state | Permitted next mutation | Re-run behavior | Public channel |
|
|
55
|
+
|---|---|---|---|
|
|
56
|
+
| Source gated; version unused | Create the immutable Core tag | Existing tag must match or the run fails | Unchanged |
|
|
57
|
+
| Core tag exists; candidate packages incomplete | Publish and verify missing exact versions under `mantle-release` through each registry's sole publish step | Existing versions are verified and skipped | Unchanged |
|
|
58
|
+
| Candidate packages verified; Starter tag absent | Dispatch the pinned Starter release and wait | The Starter worker resumes or reports its matching no-op | Unchanged |
|
|
59
|
+
| Matching Starter tag exists | Validate its Core/base provenance; run the frozen Starter, clean-create, and Landing compatibility gates | Validation and gates repeat without mutation | Unchanged |
|
|
60
|
+
| All downstream consumer gates pass | Promote npmjs and GitHub Packages channel tags monotonically | Same version is a no-op; an older run preserves a newer tag | Candidate or newer version |
|
|
61
|
+
| Channels promoted or preserved newer | Create the Core GitHub Release | Existing matching release is a no-op | Candidate or newer version |
|
|
62
|
+
| Core GitHub Release exists | Dispatch Landing only when explicitly enabled | Landing remains untouched by default | Candidate or newer version |
|
|
63
|
+
|
|
64
|
+
Invariants:
|
|
65
|
+
|
|
66
|
+
- immutable package versions and Core/Starter tags must keep the requested
|
|
67
|
+
version, Core SHA, and pinned Starter SHA identity;
|
|
68
|
+
- public channel tags cannot move until the released Starter, clean-create, and
|
|
69
|
+
reviewed Landing compatibility gates pass;
|
|
70
|
+
- channel updates use the controller's monotonic promotion boundary, so an
|
|
71
|
+
older re-run cannot move a channel backward;
|
|
72
|
+
- the candidate version may be fetched explicitly or through the temporary
|
|
73
|
+
`mantle-release` tag before promotion, but is not the public channel default.
|
|
74
|
+
|
|
75
|
+
Non-goals: this transition does not change Starter worker ownership, add
|
|
76
|
+
rollback or unpublish behavior, or deploy Landing unless
|
|
77
|
+
`deploy_landing=true`.
|
|
78
|
+
|
|
48
79
|
## Branches and channels
|
|
49
80
|
|
|
50
81
|
- Feature and release PRs target `develop`.
|
|
@@ -88,18 +119,27 @@ gh api --method POST repos/aotter/mantle/releases/generate-notes \
|
|
|
88
119
|
--jq .body
|
|
89
120
|
```
|
|
90
121
|
|
|
91
|
-
The
|
|
122
|
+
The nine public packages publish in dependency order:
|
|
92
123
|
|
|
93
124
|
1. `@aotter/mantle-spec`
|
|
94
125
|
2. `@aotter/mantle-admin-ui`
|
|
95
126
|
3. `@aotter/mantle-runtime`
|
|
96
|
-
4. `@aotter/mantle-
|
|
97
|
-
5. `@aotter/mantle`
|
|
127
|
+
4. `@aotter/mantle-web`
|
|
128
|
+
5. `@aotter/mantle-admin`
|
|
129
|
+
6. `@aotter/mantle-bun`
|
|
130
|
+
7. `@aotter/mantle-vercel`
|
|
131
|
+
8. `@aotter/mantle-cloudflare`
|
|
132
|
+
9. `@aotter/mantle`
|
|
98
133
|
|
|
99
134
|
The umbrella package must contain its version-matched `docs/` and `skills/`
|
|
100
135
|
payload. No tarball may contain `workspace:*` dependencies, secrets, local
|
|
101
|
-
state, or workspace-only files. Starter
|
|
102
|
-
versioned `mantle-starters` repository
|
|
136
|
+
state, or workspace-only files. Starter content is still authored and released
|
|
137
|
+
from the versioned `mantle-starters` repository — Core owns no starter source.
|
|
138
|
+
Core's umbrella CLI is the canonical consumer of that release: `mantle create`
|
|
139
|
+
resolves the official immutable `v${packageVersion}` starter tag and renders it
|
|
140
|
+
through Core's shared provision module. A published Core version
|
|
141
|
+
therefore requires the matching starter tag to exist; see
|
|
142
|
+
[ADR-0018](adr/0018-core-starters-repository-boundary.md).
|
|
103
143
|
|
|
104
144
|
## Run the controller
|
|
105
145
|
|
|
@@ -114,16 +154,20 @@ Before creating the Core tag, the controller proves:
|
|
|
114
154
|
- the requested version matches every package, plugin, and marketplace ref;
|
|
115
155
|
- `pnpm check` passes;
|
|
116
156
|
- packed Core passes in the exact pinned Starter source;
|
|
117
|
-
- all
|
|
157
|
+
- all nine release tarballs exist;
|
|
118
158
|
- npm and cross-repository credentials are present and readable;
|
|
119
159
|
- a fresh version is unused across npmjs, GitHub Packages, and Starter tags;
|
|
120
160
|
- the pinned Starter commit is still the remote `develop` tip.
|
|
121
161
|
|
|
122
|
-
After
|
|
123
|
-
the locally packed tarball, rejects leaked
|
|
124
|
-
for the Starter tag, checks that tag's exact
|
|
125
|
-
frozen locks from the public registry, and
|
|
126
|
-
|
|
162
|
+
After candidate publication under `mantle-release`, it compares each public
|
|
163
|
+
registry integrity value with the locally packed tarball, rejects leaked
|
|
164
|
+
`workspace:*` dependencies, waits for the Starter tag, checks that tag's exact
|
|
165
|
+
Core/base provenance, installs its frozen locks from the public registry, and
|
|
166
|
+
reruns the Starter bundle gates. It then creates clean Blank and multilingual
|
|
167
|
+
Transaction projects through the registry candidate, frozen-installs and checks
|
|
168
|
+
both, and runs the reviewed Landing consumer against the exact packed candidate.
|
|
169
|
+
Only then does it promote the public npmjs and GitHub Packages channel tags and
|
|
170
|
+
create the Core GitHub Release.
|
|
127
171
|
|
|
128
172
|
## Idempotency and recovery
|
|
129
173
|
|
|
@@ -148,7 +192,7 @@ Core repository secrets:
|
|
|
148
192
|
|
|
149
193
|
| Secret | Minimum purpose |
|
|
150
194
|
|---|---|
|
|
151
|
-
| `NPM_TOKEN` | Publish the
|
|
195
|
+
| `NPM_TOKEN` | Publish the nine `@aotter/*` packages on npmjs. |
|
|
152
196
|
| `RELEASE_FANOUT_TOKEN` | Read and dispatch `aotter/mantle-starters`; also read and dispatch `aotter/mantle-landing` only when Landing is enabled. |
|
|
153
197
|
|
|
154
198
|
Core's job-scoped `GITHUB_TOKEN` creates the Core tag and release and mirrors
|
|
@@ -171,18 +215,24 @@ for p in \
|
|
|
171
215
|
@aotter/mantle-spec \
|
|
172
216
|
@aotter/mantle-admin-ui \
|
|
173
217
|
@aotter/mantle-runtime \
|
|
218
|
+
@aotter/mantle-web \
|
|
219
|
+
@aotter/mantle-admin \
|
|
220
|
+
@aotter/mantle-bun \
|
|
221
|
+
@aotter/mantle-vercel \
|
|
174
222
|
@aotter/mantle-cloudflare \
|
|
175
223
|
@aotter/mantle; do
|
|
176
224
|
npm view "$p@X.Y.Z" version dist.integrity dependencies --json
|
|
177
225
|
done
|
|
178
226
|
```
|
|
179
227
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
a
|
|
185
|
-
|
|
228
|
+
The controller already creates and checks clean Blank and multilingual
|
|
229
|
+
Transaction projects. For 0.1.2 release acceptance, give a coding agent with no
|
|
230
|
+
Mantle checkout or repository knowledge only the generated instructions and
|
|
231
|
+
confirm it reaches a running Worker. This is one manual clean-room acceptance,
|
|
232
|
+
not a nondeterministic CI framework. Confirm the generated project contains
|
|
233
|
+
version-matched repo-local Mantle skills and the expected typed runtime surface.
|
|
234
|
+
`blank` remains headless and contains no Kiwa; a typed Starter revision may
|
|
235
|
+
retain its replaceable offline UI palette, but runtime code must not import it.
|
|
186
236
|
|
|
187
237
|
If `deploy_landing=false`, also verify that no Landing release dispatch or
|
|
188
238
|
deployment was started.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Sealed pipeline ownership ledger
|
|
2
|
+
|
|
3
|
+
This is the migration evidence for ADR-0019 and epic #656. It records the
|
|
4
|
+
`v0.1.0-alpha.7` owners before code moves, the single target owner, and the
|
|
5
|
+
issue that must delete or delegate the old path.
|
|
6
|
+
|
|
7
|
+
## Rule ownership
|
|
8
|
+
|
|
9
|
+
| Behavior | Current owner(s) | Target owner | Migration |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| YAML document decode, empty documents, syntax errors, alias cap | `ManifestParser.parseOneStream` | Parse/decode in `mantle-spec` | #663 |
|
|
12
|
+
| Four-atom discrimination, envelope keys, primitive/enum shape | `ManifestParser` | Parse/normalize | #663 |
|
|
13
|
+
| Source identity and document location | Synthetic parser doc index plus `loadManifests`/`ManifestPathDiagnoser` reconstruction | `ManifestSourceSet` authored metadata | #663 |
|
|
14
|
+
| Schema atom-local shape, index/search/UI shape | Parser plus `ValidateManifestsUseCase` checkers | Parse/normalize | #663; old checks deleted in #673 |
|
|
15
|
+
| Defaults for localized/lifecycle/indexes/search/order | `IntrospectManifestsUseCase`, runtime lifecycle checks, and callers using `??` | Parse/normalize exactly once | #663, #667 |
|
|
16
|
+
| Duplicate names | `ValidateManifestsUseCase` | Link | #664 |
|
|
17
|
+
| Schema/View/Procedure/Trigger cross-references | `ValidateManifestsUseCase` and repeated boot checks | Link | #664 |
|
|
18
|
+
| Guard existence, self-reference, builtin/chain rules | Validate plus `ValidateBootUseCase` | Link | #664 |
|
|
19
|
+
| Locale/translates graph | `checkLocaleAndTranslates` in validate and boot | Link for manifest graph; Prepare for selected deployment locales | #664, #666 |
|
|
20
|
+
| Manifest-owned HTTP/MCP collisions | Validate plus boot | Link | #664 |
|
|
21
|
+
| Handler source/registry availability | Optional CLI source scan plus boot registry scan | Prepare | #666 |
|
|
22
|
+
| Optional Web/Admin/Auth path reservations | Fixed boot/Cloudflare prefix lists | Prepare selected capabilities only | #666, #669, #670 |
|
|
23
|
+
| Kind/name lookup maps | `ValidateManifestsUseCase`, `ValidateBootUseCase`, `createCmsRuntime`, adapters | Compile once into `RuntimePlan` | #665 |
|
|
24
|
+
| Authorization/guard descriptors | Raw manifests interpreted by validators, runtime use cases, and mounts | Compile plan; evaluate in Core invocation | #665, #667 |
|
|
25
|
+
| Trigger indices and Procedure descriptors | Runtime construction/use cases | Compile plan | #665 |
|
|
26
|
+
| Semantic fingerprint | Runtime boot from raw manifests | Compile plan | #665 |
|
|
27
|
+
| Declarative View resolution | `ViewSqlCompiler` during each `ExecuteViewUseCase` call | Compile logical plan once | #665 |
|
|
28
|
+
| SQLite/JSON1 View lowering and native `spec.sql` | `ViewSqlCompiler` plus `DatabaseDriver` invocation | Selected storage preparation | #666 |
|
|
29
|
+
| Canonical SQL migrations, indexes, schema SQL Views, readiness | `createCmsRuntime.bootInit` and runtime infrastructure | Prepare | #666 |
|
|
30
|
+
| Entry/media/site repositories | Runtime constructs `Database*Repository` from `DatabaseDriver` | Prepared semantic storage ports; media/config move with final owner | #666, #669, #670 |
|
|
31
|
+
| Content, View, Procedure, Trigger, lifecycle invocation | Runtime use cases over raw maps/driver | `MantleRuntime` over plan + semantic ports | #667 |
|
|
32
|
+
| Target authorization/admin bypass | Runtime plus adapter entry points | One Core invocation policy; adapter resolves caller only | #667 |
|
|
33
|
+
| Generated manifest module and TypeScript names | `packages/mantle/src/cli/generate.ts` + `EmitTypesUseCase` | Pure linked/plan projection and `bindMantle` | #668 |
|
|
34
|
+
| Admin asset copy during generation | `packages/mantle/src/cli/generate.ts` | Removed; Admin install/composition owns assets | #668, #670 |
|
|
35
|
+
| HTML/templates/public paths/Markdown/SEO/preview/`llms.txt`/sitemap | Runtime render services plus Cloudflare public routes | Optional `mantle-web` | #669 |
|
|
36
|
+
| Public request mapping and cache policy | `mountPublicRoutes` | Platform adapter using selected Web projection | #669 |
|
|
37
|
+
| Admin API/application/static assets | Optional `mantle-admin`; Cloudflare only binds auth/request context/assets | Optional `mantle-admin` + existing UI artifact | #670 |
|
|
38
|
+
| View/HTTP Trigger route transport | Combined Cloudflare mounts | Platform adapters over the same Core descriptors | #669–#672 |
|
|
39
|
+
| Bun SQLite/process lifecycle | `mantle-bun`; host owns server/database | `mantle-bun`; host owns server/database | #671 |
|
|
40
|
+
| Vercel function/durable-storage lifecycle | `mantle-vercel`; host owns handler/client | `mantle-vercel`; host owns handler/client | #672 |
|
|
41
|
+
| Legacy overloads, aliases, combined mounts, duplicate tests | Current public API plus temporary migration delegates | Deleted | #673 |
|
|
42
|
+
| Contributor/agent/release guidance | `AGENTS.md`, `CLAUDE.md`, `CONTRIBUTING.md`, two release skill copies | One tool-neutral authority and one release skill | #674 |
|
|
43
|
+
|
|
44
|
+
## Deletion evidence
|
|
45
|
+
|
|
46
|
+
All baseline production callers now consume `ParsedManifestSet`,
|
|
47
|
+
`LinkedManifestSet`, or `RuntimePlan` according to their pipeline stage.
|
|
48
|
+
`scripts/check-boundaries.mjs` fails if the removed runtime facade, generated
|
|
49
|
+
site API, raw parser facade, or combined Cloudflare route owner returns.
|
|
50
|
+
Parser-focused tests may inspect parser output, but runtime and platform tests
|
|
51
|
+
must compile and prepare the same sealed plan used by production.
|
|
52
|
+
|
|
53
|
+
## Consumer manifest corpus
|
|
54
|
+
|
|
55
|
+
The Core repository does not vendor every downstream manifest. That would
|
|
56
|
+
create a second source of truth. The reusable golden fixture under
|
|
57
|
+
`packages/mantle-spec/test/fixtures/pipeline-v0.1/` covers every shipped atom,
|
|
58
|
+
auth/guard references, all Trigger surfaces, multi-document YAML, empty
|
|
59
|
+
documents, aliases, unknown keys, malformed YAML, and deterministic
|
|
60
|
+
diagnostics.
|
|
61
|
+
|
|
62
|
+
Exact downstream sources and their gate authorities are pinned here. The public
|
|
63
|
+
Starter runs in Core CI and release preflight. Private consumers run the same
|
|
64
|
+
exact-tarball checker in their own repositories, so public Core PRs never
|
|
65
|
+
receive cross-repository credentials:
|
|
66
|
+
|
|
67
|
+
| Consumer | Revision | Gate authority | Manifest paths |
|
|
68
|
+
|---|---|---|---|
|
|
69
|
+
| `aotter/mantle-starters` | `157e8f49e1e25ae1c52c0115f0dd9e8b6017ef0e` | Core CI + release | `blank/manifests/site.yaml`; `overlays/{community,intake,presence,publication,reservation,transaction}/manifests/site.yaml`; `recipes/typed-web/manifests/site.yaml` |
|
|
70
|
+
| `aotter/mantle-landing` | `4381354dd25d5d94f4096cf3e55a4cb9eecbf3ad` | Landing CI + Core release | `manifests/site.yaml` |
|
|
71
|
+
| `aotter/mantle-platform` (Remote Mantle/control plane) | `3cc0d9ad6ee47b15f06c915c12f56fc4b9143f32` | Platform `exact-packed-core` | `manifests/platform.yaml` |
|
|
72
|
+
| Core i18n fixture | this repository | Core CI | `packages/mantle-spec/test/fixtures/i18n-parent-child/manifests/site.yaml` |
|
|
73
|
+
|
|
74
|
+
## Baseline gates
|
|
75
|
+
|
|
76
|
+
The alpha.7 baseline was captured from tag `v0.1.0-alpha.7` on 2026-08-16
|
|
77
|
+
with Node 22, pnpm 9, Wrangler local mode, and datasets of 100/10,000 rows:
|
|
78
|
+
|
|
79
|
+
| Route | p95 queries | p95 rows read | local p95 timing |
|
|
80
|
+
|---|---:|---:|---:|
|
|
81
|
+
| public View, 10k rows | 1 | 20 | 3.01 ms |
|
|
82
|
+
| public page miss, 10k rows | 2 | 5 | 3.92 ms |
|
|
83
|
+
| Admin list, 10k rows | 1 | 21–22 | 2.49–3.24 ms |
|
|
84
|
+
| Admin related detail, dense | 4 | 151 | 5.23 ms |
|
|
85
|
+
| public builtin create | 1 | 0 | 2.55 ms |
|
|
86
|
+
|
|
87
|
+
Wall-clock values are evidence, not a cross-machine budget. The normative
|
|
88
|
+
baseline is the existing `pnpm bench:wrangler` query/row gate: every gate must
|
|
89
|
+
remain true, unchanged revisions must perform no repeated preparation, and any
|
|
90
|
+
intentional budget change needs its own reviewed evidence.
|
|
91
|
+
|
|
92
|
+
Existing full-facade behavior is covered by Cloudflare authorization, Admin,
|
|
93
|
+
public-route/cache, View REST, HTTP Trigger, media, form, and facade tests.
|
|
94
|
+
Issues #669–#673 move those assertions to selected modules and exact packed
|
|
95
|
+
consumers; they do not duplicate the suite under new names.
|
|
96
|
+
|
|
97
|
+
Issue #674 leaves `CONTRIBUTING.md` plus accepted ADRs as the contributor
|
|
98
|
+
authority. `AGENTS.md`, `CLAUDE.md`, and the Claude release-skill entry are
|
|
99
|
+
small routers; `.agent/skills/mantle-release/SKILL.md` is the only maintainer
|
|
100
|
+
release procedure. Shipped `skills/*` remain separate consumer artifacts.
|