From bc44ed9ebfddb716ca39d0806a0a9fe793b55a37 Mon Sep 17 00:00:00 2001 From: Vivek Date: Thu, 6 Aug 2026 13:16:40 +0530 Subject: [PATCH] chore: release core 0.7.47, server 0.8.59, cli 0.10.51 and five more Every tracked package carries unreleased work, so this clears the whole backlog rather than a slice of it: core, server, cli, mcp, ui, intellisense, and the two editor packages that ship outside npm. The headline is the bound-form write path (#1155, #1207). A form now binds its action directly, `
`, with `formaction=${importedAction}` on a submitter when one form's buttons run different actions. It works with JS off, and the renderers refuse every near-miss rather than emitting a form that posts nowhere. Two breaking changes ride along, both of them closing a hole rather than moving an API. The server HTML cache is now keyed by origin, because a page opting in with `export const revalidate` could be poisoned through `X-Forwarded-Host` (#1237), and `WEBJS_NO_TRUST_PROXY=1` now overrides `rateLimit({ trustProxy: true })` so the kill switch means one thing across the package (#1272). A third, in `@webjsdev/ui`, drops the framework detection the package could never honour (#1235). Also raises packages/server's declared `@webjsdev/core` range from ^0.7.46 to ^0.7.47. dev.js and the action dispatcher now import FORM_ACTION_FIELD, FORM_ACTION_ID_KEY, and setFormActionResolver statically, and no published core before 0.7.47 carries them, so the old range would let npm install a pair that dies at module load. The release PR is the only place that bump is legal. The generated notes were curated before committing: the two breaking entries carry hand-written migration notes, the form-binding epic's review commits are folded into the feature they hardened, the ui file is trimmed to the published surface (its nested website sub-app is not shipped), and test-harness and repo-hygiene commits are dropped. --- changelog/cli/0.10.51.md | 58 ++++++++ changelog/core/0.7.47.md | 134 +++++++++++++++++ changelog/intellisense/0.5.5.md | 12 ++ changelog/mcp/0.1.11.md | 12 ++ changelog/nvim/0.2.4.md | 16 +++ changelog/server/0.8.59.md | 135 ++++++++++++++++++ changelog/ui/0.3.11.md | 66 +++++++++ changelog/vscode/0.2.4.md | 16 +++ package-lock.json | 18 +-- packages/cli/package.json | 2 +- packages/core/package.json | 2 +- packages/editors/intellisense/package.json | 2 +- packages/editors/nvim/package.json | 2 +- .../@webjsdev/intellisense/package.json | 2 +- packages/editors/vscode/package.json | 2 +- packages/mcp/package.json | 2 +- packages/server/package.json | 4 +- packages/ui/package.json | 2 +- 18 files changed, 468 insertions(+), 19 deletions(-) create mode 100644 changelog/cli/0.10.51.md create mode 100644 changelog/core/0.7.47.md create mode 100644 changelog/intellisense/0.5.5.md create mode 100644 changelog/mcp/0.1.11.md create mode 100644 changelog/nvim/0.2.4.md create mode 100644 changelog/server/0.8.59.md create mode 100644 changelog/ui/0.3.11.md create mode 100644 changelog/vscode/0.2.4.md diff --git a/changelog/cli/0.10.51.md b/changelog/cli/0.10.51.md new file mode 100644 index 000000000..82cd4cc69 --- /dev/null +++ b/changelog/cli/0.10.51.md @@ -0,0 +1,58 @@ +--- +package: "@webjsdev/cli" +version: 0.10.51 +date: 2026-08-06T07:41:39.579Z +commit_count: 11 +--- +## Features + +- **`webjs doctor` severity is declarable per check in `webjs.doctor.gate`** ([#1296](https://github.com/webjsdev/webjs/pull/1296)) [`5d286600`](https://github.com/webjsdev/webjs/commit/5d286600) + The command was all-or-nothing: the default exit fails on a broken + toolchain, and `--strict` makes every warning fatal. A project can now map a + stable check code to `off` / `warn` / `error` in the `webjs` config block, so + CI gates the subset it cares about and stops treating every advisory as a + release blocker. `--json` carries each result's code and effective severity, + plus a `configErrors` key on the one path where a rejected `webjs.doctor` + config stops any check running. + +- **`webjs doctor` warns when a stylesheet link skips `asset()`** ([#1244](https://github.com/webjsdev/webjs/pull/1244)) [`060617ef`](https://github.com/webjsdev/webjs/commit/060617ef) + A page or layout that hand-writes `` + serves it at an unversioned url, so a CDN keeps the pre-deploy bytes for as + long as its TTL says. + +- **the scaffold gallery teaches the bound-form shape** [`a22a2995`](https://github.com/webjsdev/webjs/commit/a22a2995) + Every gallery form now binds an imported action instead of routing through a + per-page adapter, and the actions take the `FormData` directly. The todo + example keeps one intent-dispatching action because its rows carry two submit + buttons, which is the shape the `formaction` refusal points at. Extended for + submitters in [`e4177d95`](https://github.com/webjsdev/webjs/commit/e4177d95), + with the caching demo and the conventions doc brought along in + [`3838b10a`](https://github.com/webjsdev/webjs/commit/3838b10a) and + [`b306cd1e`](https://github.com/webjsdev/webjs/commit/b306cd1e). + +- **the npm description says what WebJs is** ([#1248](https://github.com/webjsdev/webjs/pull/1248)) [`175bf443`](https://github.com/webjsdev/webjs/commit/175bf443) + Registry metadata only. + +## Fixes + +- **validate the app name in `webjs create` before writing files** ([#1234](https://github.com/webjsdev/webjs/pull/1234)) [`fe9e58b0`](https://github.com/webjsdev/webjs/commit/fe9e58b0) + The name is not only the new directory. It is written verbatim into the + generated `package.json` `name` field and interpolated into generated source + as a template-literal value, so a name carrying a quote, a backtick, a `${`, + or a backslash emitted a file that failed to parse, and the failure surfaced + as a syntax error on the fresh app's first boot, far from its cause. The name + is now checked against the npm package-name rules before a single file is + written. Uppercase is accepted, since the scaffold's manifest is private. + +- **the scaffold's `components.json` matches what `webjs ui init` writes** ([#1235](https://github.com/webjsdev/webjs/pull/1235)) [`b0bc2742`](https://github.com/webjsdev/webjs/commit/b0bc2742) + `@webjsdev/ui` dropped project detection and moved its defaults to constants + in `init`, so `webjs create` now points at that single source. An app that + scaffolds and one that runs `webjs ui init` end up with the same config. + +- **point the scaffold auth test at the database `db:migrate` prepares** [`03662927`](https://github.com/webjsdev/webjs/commit/03662927) + It defaulted `DATABASE_URL` to `./dev.db` while `.env.example` and + `drizzle.config.ts` both use `db/dev.db`, so the signup flow found no users + table and skipped asking for `db:migrate`, and running `db:migrate` migrated + a different file, which made the skip permanent. + +- **update the scaffold's action tests for the new identity rules** [`18990a7b`](https://github.com/webjsdev/webjs/commit/18990a7b) diff --git a/changelog/core/0.7.47.md b/changelog/core/0.7.47.md new file mode 100644 index 000000000..6b32636b9 --- /dev/null +++ b/changelog/core/0.7.47.md @@ -0,0 +1,134 @@ +--- +package: "@webjsdev/core" +version: 0.7.47 +date: 2026-08-06T07:41:39.499Z +commit_count: 24 +--- +## Breaking + +- **`WEBJS_NO_TRUST_PROXY=1` now overrides `rateLimit({ trustProxy: true })`** ([#1272](https://github.com/webjsdev/webjs/pull/1272)) [`afc1170e`](https://github.com/webjsdev/webjs/commit/afc1170e) + The kill switch was honoured by every reader of the forwarded host and proto + (the URL rewrite, the HSTS scheme gate, the CSRF host resolution) but not by + `clientIp`. An operator who set the flag because their container is directly + exposed, and who also passed `rateLimit({ trustProxy: true })`, still bucketed + rate limits on a header any client can set, so a rotating `X-Forwarded-For` + gave every request its own bucket. The switch is now absolute across every + forwarded-header read. + + **Migration.** An app that sets both now buckets every visitor behind the + proxy onto one key. That combination was always a misconfiguration and is now + a visible one. On a genuinely proxied deploy, unset `WEBJS_NO_TRUST_PROXY`. + The contradiction warns once per process rather than throwing, because the + flag is read per request on the hot path and a throw would take a + misconfigured deploy down instead of degrading it. + +## Features + +- **bind a server action into `` and `formaction=${action}`** ([#1210](https://github.com/webjsdev/webjs/pull/1210)) [`429e35e3`](https://github.com/webjsdev/webjs/commit/429e35e3) + An unquoted `action=` hole on a `` is now a binding rather than a value. + Both renderers resolve the action's identity, omit the `action` attribute so + the form posts to the page's own url, supply `method="post"` and an enctype + where the template supplies neither, and emit one hidden `__webjs_action` + field carrying the identity. A form whose buttons run different actions binds + each on its submitter with `formaction=${action}`, where the identity rides + the pressed button's own name and value pair. This is the no-JS write path: + it works with JS off, and with JS the client router posts the same body to + the same url and applies the response in place. + + Every near-miss throws rather than producing a form that posts nowhere. The + renderers refuse a quoted `action="${fn}"`, an `action` hole on a tag other + than ``, `method="get"` or an unparseable enctype, a `.method` / + `.enctype` / `.encoding` property binding, a second `action` hole, a plain + `action="/url"` alongside the bound hole, a whitespace-padded `method`, and a + function that is not a `'use server'` export. On a submitter they refuse an + unbound enclosing form, a control that is not a submit control, an + `` or ``, a submitter carrying its + own `name` / `value` / `form` / static `formaction`, and the property + spellings of any of those. Where a renderer genuinely cannot tell whether the + enclosing form is bound (a component rendering its own template, a + `repeat()` row reconciled before its parent form exists) it binds rather than + refusing, so an ordinary per-row button is never rejected. + + The full rule set is invariant 12 in `AGENTS.md`. Landed across + [`d12c30db`](https://github.com/webjsdev/webjs/commit/d12c30db), + [`d4ab6f74`](https://github.com/webjsdev/webjs/commit/d4ab6f74), + [`e4177d95`](https://github.com/webjsdev/webjs/commit/e4177d95) and the + review fixes that hardened it: + [`595826ec`](https://github.com/webjsdev/webjs/commit/595826ec) validates a + bound form only after every part is committed, so an attribute written after + the action hole is seen; + [`f892f5e5`](https://github.com/webjsdev/webjs/commit/f892f5e5) drops a + failed render's pending binds instead of leaking them into the next one; + [`c09413c3`](https://github.com/webjsdev/webjs/commit/c09413c3), + [`65d23bb8`](https://github.com/webjsdev/webjs/commit/65d23bb8), + [`d7df9dd9`](https://github.com/webjsdev/webjs/commit/d7df9dd9) and + [`b148be61`](https://github.com/webjsdev/webjs/commit/b148be61) re-check the + form on every write path, including a removal, the boolean and property + branches, and the legacy `form.encoding` alias; and + [`573a2f5c`](https://github.com/webjsdev/webjs/commit/573a2f5c) keeps an + action's identity resolvable when it is defined in a linked workspace package + and re-exported through an in-app barrel. + +- **`webjs.doctor.gate` is typed on `WebjsConfig`** ([#1296](https://github.com/webjsdev/webjs/pull/1296)) [`5d286600`](https://github.com/webjsdev/webjs/commit/5d286600) + The config block gains a `doctor.gate` map from a stable doctor check code to + `off` / `warn` / `error`, so a project can declare which project-health checks + are fatal in CI. Typed in `webjs-config.d.ts` and exported from `index.d.ts`. + +- **`setHardNavigate()` routes the router's hard navigations through one seam** ([#1290](https://github.com/webjsdev/webjs/pull/1290)) [`92f34de1`](https://github.com/webjsdev/webjs/commit/92f34de1) + A hard navigation is unobservable from outside: `preventDefault` cancels a + default action rather than a script assignment, and `location.href` is + non-configurable on Chromium, Firefox, and WebKit, so its setter cannot be + redefined. Every hard navigation now goes through one indirection whose + default is byte-identical to the assignment it replaces, so production + behaviour is unchanged unless `setHardNavigate` is called. It exists so a + router degradation fails one test with its cause slug instead of aborting the + whole browser session. + +- **the npm description says what WebJs is** ([#1248](https://github.com/webjsdev/webjs/pull/1248)) [`175bf443`](https://github.com/webjsdev/webjs/commit/175bf443) + Registry metadata only. The package described what the package does without + ever saying what the project is, so a stranger landing on the npm page from a + search had no way to place it. + +## Fixes + +- **close an open redirect in `sameSiteRedirect`** [`b306cd1e`](https://github.com/webjsdev/webjs/commit/b306cd1e) + It rejected `//host` and `/\host` but accepted `//host`. The URL parser + removes tab, LF, and CR before parsing, so that value reached the redirect as + a protocol-relative url pointing off-site. + +- **stop a `reflect: true` prop stringifying a function into its attribute** ([#1231](https://github.com/webjsdev/webjs/pull/1231)) [`e303d57c`](https://github.com/webjsdev/webjs/commit/e303d57c) + The fall-through branch of `_reflectAttribute` ran `String(value)`, and + `String(fn)` is the function's source, so assigning an imported action to a + reflected prop wrote the whole function body into the DOM. + +- **reactivate a top-level script in a swapped range** ([#1236](https://github.com/webjsdev/webjs/pull/1236)) [`79c6e7e5`](https://github.com/webjsdev/webjs/commit/79c6e7e5) + A `