Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions changelog/cli/0.10.51.md
Original file line number Diff line number Diff line change
@@ -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 `<link rel="stylesheet" href="/public/...">`
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)
134 changes: 134 additions & 0 deletions changelog/core/0.7.47.md
Original file line number Diff line number Diff line change
@@ -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 `<form action=${action}>` 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 `<form>` 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 `<form>`, `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
`<input type="image">` or `<input type="submit">`, 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 `/<TAB>/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 `<script>` that is a top-level node of a client-router swapped range was
never re-executed after a soft navigation.

- **a preserved permanent element keeps its descendant scripts** ([#1279](https://github.com/webjsdev/webjs/pull/1279)) [`8ceda3a4`](https://github.com/webjsdev/webjs/commit/8ceda3a4)
`data-webjs-permanent` preserves an element across a swap as the same live
DOM node, and the reconciler already treats that as a subtree guarantee. The
reactivation pass disagreed and re-emitted every script inside it.

- **make `repeat` / `guard` / `watch` / `until` commits atomic against a throw** ([#1232](https://github.com/webjsdev/webjs/pull/1232)) [`f426edd8`](https://github.com/webjsdev/webjs/commit/f426edd8)
Several client-renderer commit paths recorded their bookkeeping before the
DOM work that can throw, so a throw part-way through left the renderer's
state describing a DOM that was never built.

- **a throw while removing `repeat()` leftovers no longer strands the row** ([#1274](https://github.com/webjsdev/webjs/pull/1274)) [`982d5606`](https://github.com/webjsdev/webjs/commit/982d5606)
Rows already disposed and detached stayed registered in `state.map`.

- **a mid-commit throw no longer strands a row in a plain `.map()` array** ([#1284](https://github.com/webjsdev/webjs/pull/1284)) [`df2b6980`](https://github.com/webjsdev/webjs/commit/df2b6980)
`reconcileArray` accumulated its replacement slot list locally and committed
it only after the whole walk, so a throw part-way discarded the list.

- **a directive inside an `asyncAppend` chunk no longer escapes the error boundary** ([#1285](https://github.com/webjsdev/webjs/pull/1285)) [`cea65748`](https://github.com/webjsdev/webjs/commit/cea65748)
A `watch()` or `until()` nested inside a chunk committed by `asyncAppend` or
`asyncReplace` never got an error-boundary owner, so a throw from its commit
escaped the owning component.

- **hint the core runtime in the head so a pre-boot click is not a full page load** ([#1281](https://github.com/webjsdev/webjs/pull/1281)) [`74dd3ada`](https://github.com/webjsdev/webjs/commit/74dd3ada)
Links are clickable from first paint, but the boot is a module script, which
the HTML spec defers until parsing finishes, so a click inside that window is
a plain browser navigation. The runtime is now hinted in the head, which
shortens the window rather than pretending to close it.
12 changes: 12 additions & 0 deletions changelog/intellisense/0.5.5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
package: "@webjsdev/intellisense"
version: 0.5.5
date: 2026-08-06T07:41:39.644Z
commit_count: 1
---
## Features

- **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.
12 changes: 12 additions & 0 deletions changelog/mcp/0.1.11.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
package: "@webjsdev/mcp"
version: 0.1.11
date: 2026-08-06T07:41:39.687Z
commit_count: 1
---
## Features

- **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.
16 changes: 16 additions & 0 deletions changelog/nvim/0.2.4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
package: "webjs.nvim"
version: 0.2.4
date: 2026-08-06T07:41:39.725Z
commit_count: 1
npm: false
---
## Fixes

- **the vendored language service cannot drift from its manifest** ([#1248](https://github.com/webjsdev/webjs/pull/1248)) [`175bf443`](https://github.com/webjsdev/webjs/commit/175bf443)
The plugin ships a committed copy of `@webjsdev/intellisense`, and the drift
guard now compares that package's `package.json` in full rather than only its
sources, so a version bump or a description change that was not re-vendored
fails CI instead of shipping a plugin that misreports its own language
service version. Carries the refreshed manifest for
`@webjsdev/intellisense` 0.5.5.
Loading
Loading