@zerotal/arch 1.15.1 → 1.15.3

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/docs/about.md CHANGED
@@ -82,12 +82,11 @@ Add `FlowProvider`. The provider list is the feature manifest for your app.
82
82
  # in your project's parent directory
83
83
  bun create zerotal my-app # choose: API, Flow, React, Vue, or Minimal
84
84
  cd my-app
85
- cp .env.example .env # APP_KEY is pre-generated for you
86
85
  bun zt migrate # create the database schema (API template)
87
86
  bun zt dev # dev server + hot reload at http://localhost:3000
88
87
  ```
89
88
 
90
- The scaffolder writes a fresh `APP_KEY` into `.env.example` and installs
89
+ The scaffolder writes a fresh `APP_KEY` into `.env` and installs
91
90
  dependencies. Pick a template at the prompt:
92
91
 
93
92
  - **API** — JSON REST API (core + ORM + auth + validation + testing). The default.
package/docs/changelog.md CHANGED
@@ -27,6 +27,108 @@ the section for every version you cross and apply its migration notes, not only
27
27
  majors. [Releases and versioning](/docs/support-policy#releases-and-versioning) explains
28
28
  when that carve-out ends.
29
29
 
30
+ ## 1.15.3 — 2026-10-23
31
+
32
+ A patch for the first ten minutes with Zerotal. Scaffolding each starter, following its README
33
+ and running it, the way a newcomer would, turned up four things that did not work as written,
34
+ and a fifth where two guides told you to throw away your own key. All five are fixed here.
35
+
36
+ Nothing here breaks. Safe to take directly.
37
+
38
+ ### Fixed
39
+
40
+ - **A new app's README now says what it takes to run** (`create-zerotal`). The scaffolder
41
+ printed `bun zt migrate` (or `bun zt db:seed` for the admin starter) before `bun zt dev`,
42
+ while every README said `bun install` then `bun run dev`. The README is the copy that stays,
43
+ and following it on the API, Flow, React or Vue starter reached a running app with no `users`
44
+ table. Both are generated from one list now, so they cannot disagree again.
45
+
46
+ - **The admin starter answers `/`.** The dev server prints `http://localhost:3000`, and the app
47
+ had nothing there: a bare JSON `E_NOT_FOUND`, with no hint that the panel is at `/admin`. The
48
+ bare origin now redirects to it.
49
+
50
+ - **A new API starter passes `zt doctor`.** Its `config/app.ts` was a bare object where the other
51
+ five starters use `AppConfig`, which is what fills `allowedOrigins` from `url`. The doctor failed
52
+ an app with no code of its own, and told you to set a `url` that was already set. The config is
53
+ wrapped in `AppConfig` now, and reads `APP_KEY` the way the other starters do: it must be set.
54
+
55
+ - **The Flow and React starters create `users.remember_token`.** Their `User` uses
56
+ `Authenticatable`, but the migration did not create the column, so `zt doctor` failed between
57
+ `migrate` and the first dev boot, until the boot step added it. The migration creates it now.
58
+
59
+ - **[Getting Started](/docs/getting-started) and [About Zerotal](/docs/about) no longer tell you
60
+ to overwrite your key.** Both said to run `cp .env.example .env` and that the ready-made `APP_KEY` lives in
61
+ `.env.example`. The scaffolder writes the real key into `.env` and only a placeholder into the
62
+ example, so following them replaced a generated key with the placeholder. Both now describe
63
+ what the scaffolder writes.
64
+
65
+ ### Changed
66
+
67
+ - **New apps start on a tilde range.** `bun create zerotal` wrote `^X.Y.Z` into every new app's
68
+ `zerotal` and `@zerotal/*` dependencies. Under the [versioning scheme](/docs/upgrade#versioning)
69
+ a minor is where a break lands, so a caret let the app's next install cross one without anyone
70
+ reading its notes. It writes `~X.Y.Z` now, which takes every patch and stops at the minor.
71
+ Apps already scaffolded keep what they have; change `^` to `~` in their `package.json` to get
72
+ the same protection.
73
+
74
+ ## 1.15.2 — 2026-10-23
75
+
76
+ A patch, and if you run Bun 1.4.4 or later it is the one to take: that Bun stopped accepting the
77
+ way the ORM hands it SQL, so most of what the ORM sent to the database failed. Three smaller
78
+ faults ride with it, found running a live app on Zerotal, each of which that app had been
79
+ working round in its own code.
80
+
81
+ Nothing here breaks. Safe to take directly.
82
+
83
+ ### Fixed
84
+
85
+ - **The ORM runs on Bun 1.4.4** (`@zerotal/orm`, with `@zerotal/notifications` and
86
+ `@zerotal/testing`). Bun's `sql` function refuses a template object whose `raw` property
87
+ is enumerable — "so it is not a template object" — and the ORM built every statement it
88
+ assembled from a string that way: the string form of `DB.raw()`, the query builder,
89
+ schema and migration DDL, the `SAVEPOINT` a nested transaction issues, the validator's
90
+ `unique` and `exists` rules. 1.4.4 is the first Bun known to refuse it, and on that version
91
+ and later none of those statements ran. They now come from one helper that builds the
92
+ object the way the language does. An app on Bun 1.4.2 or earlier was never affected, and
93
+ nothing about its behaviour changes.
94
+
95
+ - **A production build ships React's production build** (`@zerotal/core`). The browser
96
+ build's defines stated `import.meta.env` but not `process.env.NODE_ENV`, which is the
97
+ switch React and most of npm read — and the bundler left that expression to whatever the
98
+ shell happened to have. An app that ran `inertia:build --production` without `NODE_ENV`
99
+ in its environment shipped React's development build: a 522 KB vendor chunk where 322 KB
100
+ would do, the DevTools notice in every visitor's console, and full hydration diffs. The
101
+ define now states `NODE_ENV` from the same flag, so the build no longer depends on the
102
+ shell it ran in.
103
+
104
+ - **`back()` works behind a proxy that terminates TLS** (`@zerotal/core`). A redirect back
105
+ to the previous page accepted a `Referer` only from the request's own origin. Behind a
106
+ reverse proxy the request reaches the app as `http://…` while every browser sends
107
+ `https://…`, so every `Referer` was refused and "back" was always `/`. That is not only
108
+ `ctx.back()`: `validate()`'s redirect on failure, `FormRequest`, the intended-URL helpers
109
+ and Flow all use the same check, so a form with one mistake in it sent the user to the
110
+ home page with its errors flashed to a page that never shows them. The origin of the
111
+ configured `app.url` now counts as the app's own as well. Every other site is still
112
+ refused, and with no `app.url` set the behaviour is exactly what it was.
113
+
114
+ - **`SmtpDriver` transfer-encodes text and HTML parts** (`@zerotal/notifications`). Both
115
+ went on the wire raw, with no `Content-Transfer-Encoding`. A body line over the 998-octet
116
+ limit of RFC 5322 was cut by a relay wherever the limit fell — a single-line HTML email
117
+ reached a customer reading "sup pliers" — and a non-ASCII body was sent as undeclared
118
+ 8-bit on a connection that never negotiates `8BITMIME`. A part that is plain ASCII with
119
+ lines of 78 characters or fewer is still sent as written, now declared `7bit`; anything
120
+ else is quoted-printable, which keeps ASCII readable where base64 would not. A test that
121
+ asserts on the raw bytes the driver sent will see the new header, and for a long or
122
+ non-ASCII body, encoded text to decode before comparing.
123
+
124
+ ### Changed
125
+
126
+ - **Three runtime dependencies move to newer minimums.** `alpinejs` and its seven plugins
127
+ (`@zerotal/flow`) are now `^3.17.4`, `@simplewebauthn/server` (`@zerotal/auth`) is now
128
+ `^13.3.3`, and `tailwind-merge` (`@zerotal/flow-ui`) is now `^3.7.0`. Each stays within
129
+ the major it was already on, and nothing in Zerotal's own API moves. The rest of the
130
+ weekly dependency update is development tooling and does not reach an installed app.
131
+
30
132
  ## 1.15.1 — 2026-09-13
31
133
 
32
134
  A patch, and its headline is an ORM bug as old as the option it breaks: a model keyed on
package/docs/database.md CHANGED
@@ -199,7 +199,7 @@ The `ManualTransaction` handle returned by `DB.beginTransaction()`:
199
199
  | `t.commit()` | Commit and release the transaction |
200
200
  | `t.rollback()` | Roll back and release the transaction |
201
201
 
202
- > **Warning** — Prefer `DB.transaction(callback)`. Manual transactions require careful error handling to avoid leaving connections open.
202
+ > **Warning** — Prefer `DB.transaction(callback)`. A handle you never commit or roll back keeps its connection inside the transaction: on SQLite every later transaction fails with "cannot start a transaction within a transaction", and on a pool it is a connection that never comes back. Settle the handle on every path. A `finally` that calls `t.rollback()` is safe after a commit, where it does nothing.
203
203
 
204
204
  ## Raw queries with DB
205
205
 
@@ -152,20 +152,17 @@ no manual registration.
152
152
 
153
153
  ## Environment setup
154
154
 
155
- The scaffolder generates `.env.example` with a ready-made `APP_KEY`. Copy it to
156
- `.env`:
157
-
158
- ```bash
159
- # in your project root
160
- cp .env.example .env
161
- ```
155
+ The scaffolder writes a `.env` with a freshly generated `APP_KEY`, so a new app boots
156
+ straight away; there is nothing to copy. `.env` is git-ignored. `.env.example` is the
157
+ copy you commit, and it holds placeholders on purpose: on another machine, copy it to
158
+ `.env` and run `bun zt key:generate` to fill the key in.
162
159
 
163
160
  ```ini
164
161
  # .env
165
162
  APP_ENV=development
166
- APP_KEY=base64:… # pre-generated; rotate with `bun zt key:generate`
163
+ APP_KEY=… # generated for you; rotate with `bun zt key:generate`
167
164
  DATABASE_URL=./database/db.sqlite
168
- SESSION_SECRET=change-me-in-production
165
+ SESSION_SECRET=… # API template: generated for you; set your own before deploying
169
166
  ```
170
167
 
171
168
  The database is configured with a single **`DATABASE_URL`** — SQLite uses a file
package/docs/upgrade.md CHANGED
@@ -40,6 +40,8 @@ something, and puts the work where it is useful: reading the notes for each mino
40
40
  > hold exactly where you put it — a release you have certified, a machine you cannot
41
41
  > re-test quickly — pin the exact version with no range operator at all.
42
42
 
43
+ > **Note** — `bun create zerotal` writes a tilde range into new apps for this reason. An app scaffolded earlier has a caret: change `^` to `~` in its `package.json` to get the same protection.
44
+
43
45
  > **Warning** — always upgrade the `@zerotal/*` packages together. Mixing versions across core, ORM, and feature packages leads to type and runtime mismatches.
44
46
 
45
47
  ## Upgrade steps
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerotal/arch",
3
- "version": "1.15.1",
3
+ "version": "1.15.3",
4
4
  "license": "MIT",
5
5
  "maturity": "stable",
6
6
  "private": false,
@@ -35,11 +35,11 @@
35
35
  "typecheck": "tsc --noEmit"
36
36
  },
37
37
  "dependencies": {
38
- "@zerotal/core": "1.15.1"
38
+ "@zerotal/core": "1.15.3"
39
39
  },
40
40
  "devDependencies": {
41
41
  "typescript": "^5.8.0",
42
- "@zerotal/orm": "1.15.1"
42
+ "@zerotal/orm": "1.15.3"
43
43
  },
44
44
  "description": "The Zerotal agent surface — an MCP server that hands coding agents the framework's machine-readable truth: exact API signatures, live routes and schema, version-matched docs, and `zt doctor`.",
45
45
  "keywords": [