@aotter/mantle 0.0.11-alpha.73 → 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,8 +13,8 @@ make a normal content/API/page change.
13
13
  | Manifest View execution | `ExecuteViewUseCase` + `ViewSqlCompiler` | The deliberate compiled-query exception; it still 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
- | Rendered HTML, Markdown, and `llms.txt` | `HtmlPublishOrchestrator` plus the Cloudflare public-route cache policy | Reproducible derivatives live in KV. Settings updates invalidate through a runtime use case. |
17
- | D1/KV transport and optional query metrics | Cloudflare bindings | Bindings stay thin. Query/cache policy does not belong in a generic provider `BaseRepository`. |
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
+ | 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
19
  `CmsRuntime.db` remains deprecated compatibility surface. New site code uses
20
20
  Manifests, runtime use cases, `entryReader`, and `siteConfig`. A site may own
@@ -24,16 +24,14 @@ must not query Mantle-owned tables through `runtime.db`.
24
24
  ## Cache contract
25
25
 
26
26
  - D1 is canonical for entries, site settings, media metadata, and pending
27
- uploads. KV contains only reproducible public artifacts.
28
- - A public KV hit checks the cache before loading full editable site settings.
29
- Locale policy is the small boot-seeded exception. A warm entry/page artifact
30
- therefore performs zero D1 queries.
31
- - A safe cache miss renders from canonical state and schedules KV write-back
32
- with the request execution context. It waits inline only when no execution
33
- context exists, such as a direct unit call.
34
- - Site-setting writes call the runtime settings use case, which completes
35
- public-artifact invalidation before reporting success. HTTP routes do not
36
- scan/delete KV prefixes themselves.
27
+ uploads. Core stores no rendered artifact copies.
28
+ - Public routes render canonical state and return
29
+ `Cache-Control: public, max-age=0, s-maxage=300`.
30
+ - Cloudflare Workers Cache checks eligible anonymous responses before invoking
31
+ the Worker. Cache keys are version-local, so a deploy starts with no stale
32
+ response from the previous Worker version.
33
+ - Site-setting and content writes only persist canonical state. They do not
34
+ wait for render work or scan/delete cache prefixes.
37
35
  - Do not cache every repository read. Cross-isolate correctness for editable
38
36
  data wins unless a read has a measured hot-path contract and explicit
39
37
  invalidation.
@@ -76,11 +74,12 @@ Timing always reports p50/p95/max. A test-only Worker wrapper may also return
76
74
  `x-mantle-query-count` and `x-mantle-rows-read`; those become distributions in
77
75
  the same report. Do not expose these diagnostic headers in production.
78
76
 
79
- Core CI runs `pnpm bench:wrangler` against real Wrangler-local D1, KV, Worker
80
- HTTP routing, View execution, and live page rendering. It compares 100 and
81
- 10,000 row fixtures, then samples page MISS and HIT separately. CI gates
82
- row-read scaling, endpoint query budgets, and zero-D1 warm hits, not absolute
83
- milliseconds.
77
+ Core CI runs `pnpm bench:wrangler` against real Wrangler-local D1, Worker HTTP
78
+ routing, View execution, and origin page rendering. It compares 100 and 10,000
79
+ row fixtures and gates row-read scaling plus endpoint query budgets, not
80
+ absolute milliseconds. Wrangler-local does not emulate the new entrypoint
81
+ Workers Cache, so cache hits are a deployment-level smoke check rather than a
82
+ fabricated local metric.
84
83
 
85
84
  ## Seven findings: measured disposition
86
85
 
@@ -89,12 +88,12 @@ diagnostic, while query/row counts are the stable assertions.
89
88
 
90
89
  | Finding | Disposition |
91
90
  |---|---|
92
- | Public KV hits read D1 first | Fixed. A 10,000-row warm page measured 0 queries / 0 rows read. |
91
+ | Public cache hits read D1 first | Removed from Worker code. Cloudflare's entrypoint Workers Cache runs before the Worker; Core has no inner render cache. |
93
92
  | Slug/locale reads bypass generated indexes | Fixed by the shared schema-aware entry-read boundary. A 10,000-row page MISS measured 2 queries / 5 rows read. |
94
93
  | OFFSET pagination | Accepted for the v0.1 bounded-result surfaces: every response is capped at 500 rows and public hot paths must stay shallow. Deep/export workloads require a purpose-shaped cursor API before they are declared hot. |
95
94
  | Admin substring search scans | Accepted only for the authenticated Admin collection browser, with a 500-row response cap. Large/search-heavy sites should add a purpose-shaped indexed View or dedicated search service; do not expose this scan publicly. |
96
95
  | Published list/sitemap/llms paths lack system indexes | Fixed with measured partial indexes for published global, locale, collection, and collection+locale ordering. The 100-row and 10,000-row API runs both measured 1 query / 20 rows read. |
97
- | Page MISS waits for KV write-back | Fixed. Reproducible artifacts write through `waitUntil`; regression coverage proves response completion does not await KV. |
96
+ | Page MISS waits for cache write-back | Removed. Origin rendering returns directly; Workers Cache owns response storage outside the Worker. |
98
97
  | Benchmark stops at fake in-process dispatch | Fixed by the Node planner and Wrangler-local Worker/API/page layers. The old dispatch microbenchmark remains a narrow CPU signal only. |
99
98
 
100
99
  The retained OFFSET and substring-search trade-offs are visible exceptions,
@@ -48,20 +48,23 @@ decision instead of starting another local redesign loop.
48
48
  ## Branches and channels
49
49
 
50
50
  - Feature and release PRs target `develop`.
51
- - Pre-v0.1 alphas release directly from the merged `develop` release commit.
51
+ - Alpha prereleases before stable v0.1.0 release directly from the merged
52
+ `develop` release commit.
52
53
  - Beta, RC, and stable promotion to `main` remains a deliberate human decision;
53
54
  it is not part of the alpha controller.
54
55
  - Alpha, beta, and RC GitHub releases are prereleases.
55
56
  - npm dist-tags follow the suffix: `alpha`, `beta`, `rc`, or `latest` for
56
57
  stable versions.
57
- - During the current `0.0.x-alpha` cadence, `latest` follows the current alpha
58
- while the `alpha` tag remains available.
58
+ - During the legacy `0.0.x-alpha` cadence, `latest` follows the current alpha.
59
+ The final `0.1.0-alpha.N` candidates advance only `alpha`; `latest` moves to
60
+ `0.1.0` after the stable gate passes.
59
61
 
60
62
  ## Release PR
61
63
 
62
64
  1. Fetch Core and Starter remotes and choose the next unused version.
63
- 2. Read `CHANGELOG.md` completely. Add a dated Keep-a-Changelog entry from the
64
- merged commits since the previous tag; do not add an `[Unreleased]` bucket.
65
+ 2. Preview GitHub's generated notes for the merged commits since the previous
66
+ tag. Correct PR titles and labels before release; do not duplicate the notes
67
+ in `CHANGELOG.md`. Label the release-only PR `skip-release-notes`.
65
68
  3. Set that exact version in every workspace package and in all four agent
66
69
  plugin manifests. Set `.agents/plugins/marketplace.json` to the immutable
67
70
  `v<version>` ref.
@@ -75,6 +78,16 @@ decision instead of starting another local redesign loop.
75
78
  packed-consumer gate. Review and merge a same-repository PR into `develop`;
76
79
  the controller rejects a direct-push release commit.
77
80
 
81
+ Preview the native notes before merging the release PR:
82
+
83
+ ```bash
84
+ gh api --method POST repos/aotter/mantle/releases/generate-notes \
85
+ -f tag_name=vX.Y.Z \
86
+ -f target_commitish="$(git rev-parse origin/develop)" \
87
+ -f previous_tag_name=vPREVIOUS \
88
+ --jq .body
89
+ ```
90
+
78
91
  The five public packages publish in dependency order:
79
92
 
80
93
  1. `@aotter/mantle-spec`
@@ -177,7 +190,7 @@ deployment was started.
177
190
  ## Fix-forward policy
178
191
 
179
192
  - Broken public package or Starter bundle: publish the next alpha and explain
180
- the re-spin in `CHANGELOG.md`.
193
+ the re-spin in the fix PR and generated GitHub Release notes.
181
194
  - Use `npm deprecate` to steer consumers away from a broken version.
182
195
  - Unpublish only for secrets, private files, or similarly severe exposure;
183
196
  npm versions cannot be reused and registry metadata may remain unavailable
@@ -11,7 +11,7 @@ kind: Schema
11
11
  metadata: { name: account-members }
12
12
  spec:
13
13
  title: Account members
14
- lifecycle: none
14
+ lifecycle: operational
15
15
  schema:
16
16
  type: object
17
17
  properties:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aotter/mantle",
3
- "version": "0.0.11-alpha.73",
4
- "description": "Umbrella entry for @aotter/mantle. Adopters install this one package and import from subpaths: /spec, /runtime, /cloudflare, /admin-ui. Sub-packages remain individually installable on npm for tooling / alt-adapter authors. The Netlify adapter ships as a private workspace stub in v0.1 — its subpath will be added when the impl lands in v0.2.",
3
+ "version": "0.1.0-alpha.2",
4
+ "description": "Umbrella entry for @aotter/mantle. Adopters install this one package and import from subpaths: /spec, /runtime, /cloudflare, /admin-ui. Sub-packages remain individually installable on npm for tooling and adapter authors.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://mantle.tools/",
7
7
  "repository": {
@@ -55,24 +55,24 @@
55
55
  "README.md"
56
56
  ],
57
57
  "dependencies": {
58
- "@aotter/mantle-admin-ui": "0.0.11-alpha.73",
59
- "@aotter/mantle-cloudflare": "0.0.11-alpha.73",
60
- "@aotter/mantle-runtime": "0.0.11-alpha.73",
61
- "@aotter/mantle-spec": "0.0.11-alpha.73"
58
+ "@aotter/mantle-cloudflare": "0.1.0-alpha.2",
59
+ "@aotter/mantle-admin-ui": "0.1.0-alpha.2",
60
+ "@aotter/mantle-runtime": "0.1.0-alpha.2",
61
+ "@aotter/mantle-spec": "0.1.0-alpha.2"
62
62
  },
63
63
  "peerDependencies": {
64
- "@cloudflare/workers-oauth-provider": "^0.8.0",
64
+ "@cloudflare/workers-oauth-provider": "^0.8.2",
65
65
  "aws4fetch": "^1.0.20",
66
- "better-auth": "^1.6.23",
66
+ "better-auth": "^1.6.27",
67
67
  "hono": "^4.12.0",
68
68
  "zod": "^4.0.0"
69
69
  },
70
70
  "devDependencies": {
71
- "@cloudflare/workers-oauth-provider": "^0.8.0",
71
+ "@cloudflare/workers-oauth-provider": "^0.8.2",
72
72
  "@types/node": "^26",
73
73
  "aws4fetch": "^1.0.20",
74
- "better-auth": "^1.6.23",
75
- "hono": "^4.12.30",
74
+ "better-auth": "^1.6.27",
75
+ "hono": "^4.12.34",
76
76
  "typescript": "^6.0.3",
77
77
  "vitest": "^4.1.10",
78
78
  "zod": "^4.4.2"
@@ -16,7 +16,7 @@ docs govern runtime/API behavior.
16
16
  ## First Read
17
17
 
18
18
  1. `package.json` for the installed `@aotter/mantle*` versions.
19
- 2. `manifests/`, the active adapter config, and `src/auth.ts` when present. If the project is older, check `src/mantleConfig.ts`.
19
+ 2. `manifests/site.yaml`, the active adapter config, and `src/auth.ts` when present. If the project is older, check `src/mantleConfig.ts`.
20
20
  3. The active `.mantle/overlays/<type>/seed.json`, when present; generated
21
21
  homepages commonly import visible copy and form structure from it.
22
22
  4. Optional local context: `.mantle/launch-state.json`, `.mantle/handoff.md`,
@@ -82,9 +82,12 @@ the atoms cannot express the behavior.
82
82
  `Procedure.spec.input` before the seed/form. Keep public mutation inputs
83
83
  `additionalProperties: false`; otherwise JSON Schema's default may strip an
84
84
  undeclared field while returning success.
85
- - Use `lifecycle: none` for submissions, inquiries, orders, and other
85
+ - Use `lifecycle: operational` for submissions, inquiries, orders, and other
86
86
  Procedure-created operational records that staff inspect or correct. Reserve
87
- `simple` for content a person stages and publishes.
87
+ `publishing` for content a person stages and publishes.
88
+ - Lifecycle `before_update` / `after_update` hooks also fire for unpublish,
89
+ archive, and every other status transition whose target is not `published`;
90
+ do not use them for edit-only work.
88
91
  - When a form's fixed option values change, update the stored Schema and public
89
92
  Procedure input `enum` together. Keep translated labels in the page seed;
90
93
  Admin and Staff MCP derive their typed controls from the manifest values.
@@ -98,18 +101,23 @@ the atoms cannot express the behavior.
98
101
 
99
102
  - `data.locale` is reserved for `localized: true` Schemas. A non-localized
100
103
  Schema must use a domain field such as `replyLocale`.
104
+ - Use a standalone localized Schema only for independent locale rows. For
105
+ versions of one entity, use a non-localized parent plus a localized child
106
+ with `translates: { parent, on }`. The child must own at least one field
107
+ besides `locale` and the join field.
101
108
  - Parallel locale blocks must keep field names, option values, step IDs, and
102
109
  result keys identical; translate display strings only.
103
- - `siteDefaults.locales` is code-owned and boot-synced. Brand, title,
104
- description, and origin are seeded once, then changed through site settings.
110
+ - `siteDefaults.origin` and `siteDefaults.locales` are code-owned and
111
+ boot-synced. Brand, title, and description seed once, then change through
112
+ site settings.
105
113
  - When changing an existing collection from `[slug]` to `[slug, locale]`,
106
114
  boot with a Mantle version that reconciles obsolete unique indexes and test
107
115
  the same slug in two locales. Do not patch D1 manually.
108
116
 
109
117
  ## Adapter Boundary
110
118
 
111
- The runtime is adapter-neutral. Required runtime ports are `DatabaseDriver`,
112
- `KvCache`, and `AssetServer`. Optional feature ports, such as `MediaStorage`
119
+ The runtime is adapter-neutral. Required runtime ports are `DatabaseDriver`
120
+ and `AssetServer`. Optional feature ports, such as `MediaStorage`
113
121
  or `DeferredHookDispatcher`, are enabled only when the current adapter wires
114
122
  them.
115
123
 
@@ -203,7 +211,8 @@ cache.
203
211
 
204
212
  ## Rules
205
213
 
206
- - Prefer manifest YAML for content model changes.
214
+ - Put all content model changes in `manifests/site.yaml`; other manifest
215
+ filenames are rejected.
207
216
  - Use a generated overlay `seed.json` for the auth-free local first page when
208
217
  it is already imported by `src/web/content/*`.
209
218
  - Add TypeScript only for handlers, rendering, adapter wiring, or real behavior.
@@ -49,7 +49,7 @@ stop and ask for the recipe instead of guessing.
49
49
  ## First Read
50
50
 
51
51
  1. `package.json` for Mantle version and adapter package.
52
- 2. `manifests/` for current atom names and route/tool collisions.
52
+ 2. `manifests/site.yaml` for current atom names and route/tool collisions.
53
53
  3. `src/mantle/config.ts` and `src/mantle/handlers/` for registered handlers, templates, and optional ports. Older projects may use `src/mantleConfig.ts`.
54
54
  4. `.mantle/plugins.json` and `.mantle/plugins.lock.json` if present.
55
55
  5. `.mantle/launch-state.json` only as context, not as plugin authority.
@@ -50,6 +50,10 @@ Capture the live URL in `PUBLIC_ORIGIN` and `Public site:` in `AGENTS.md`, then
50
50
  commit and push non-secret changes. Reuse any repo or Worker already created
51
51
  by landing. Workers Builds is optional after a direct deploy.
52
52
 
53
+ When the owner later adopts a custom domain, update `PUBLIC_ORIGIN` and the
54
+ provider's OAuth callback together, then redeploy. Do not patch `site_config`
55
+ directly; boot syncs its canonical origin from `PUBLIC_ORIGIN`.
56
+
53
57
  ## Choose Auth
54
58
 
55
59
  - **Self-hosted — free:** configure the owner's per-site GitHub OAuth App and
@@ -18,7 +18,7 @@ tokens, or recipes, but the skill contract is Core-owned.
18
18
  2. `styles/`, `components/`, `src/web/`, `src/theme*`, and UI-library config
19
19
  if present.
20
20
  3. A vendored UI palette's manifest and license, if present.
21
- 4. `manifests/` to understand which content shape drives the public UI.
21
+ 4. `manifests/site.yaml` to understand which content shape drives the public UI.
22
22
 
23
23
  ## Ownership
24
24