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
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@ Current truth lives in:
Historical changelog details remain available through git history and release
evidence.

## 0.42.0-alpha.4

- Hardening and recipes (TP-5, ADR-0120): the 0.42 line closes with
integration proof instead of new semantics.
- Validation recipes verified in CI: zod (`/register`) and valibot
(`/subscribe`) run inside fixture actions with 422/303 asserted in three
engines — `docs/integrations/validation.md`. better-auth and Drizzle
recipes are published as doc-level (honestly marked unverified):
`docs/integrations/better-auth.md`, `docs/integrations/drizzle.md`.
- The `create` starter gains a request-time `/contact` route exercising
the full loop (`rendering: 'dynamic'` + action + `data-open-enhance`),
so starter consumers get the loop out of the box.
- `PACKAGE_SURFACE.md` records the 0.42 line additions as unfrozen with
their freeze target.
- Performance baseline for 0.44: request-time render on the fixture is
cold 28.6ms, warm p50 1.58ms / p95 2.97ms
(`docs/release/v0.42.0-alpha.4-performance.json`).
- Fix (from alpha.3): the morph could replace an island whose light DOM
carried whitespace-only text around the DSD template, resetting its
state; the comparison now ignores whitespace-only text nodes, covered
by the survival matrix in three engines (42/42).

## 0.42.0-alpha.3

- Revalidation continuity (ADR-0120): enhanced forms (`data-open-enhance`)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Elements are the durable application contract; JSX and Basic Element are the
authoring layer; Declarative Shadow DOM is the default server representation;
interactive regions upgrade selectively.

Published package line: `0.42.0-alpha.3` (`v0.42.0-alpha.3`) — the stable five-package
Published package line: `0.42.0-alpha.4` (`v0.42.0-alpha.4`) — the stable five-package
release under ADR-0119's scoped interface freeze; the abandoned beta naming
is not an active line.

Expand Down
2 changes: 1 addition & 1 deletion README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Elements 是可长期保存的应用组件模型;JSX 与 Basic Element 是作者层;
Declarative Shadow DOM 是默认服务端表示;交互区域按需升级。

已发布包线为 `0.42.0-alpha.3`(`v0.42.0-alpha.3`)——ADR-0119 范围化接口冻结下的
已发布包线为 `0.42.0-alpha.4`(`v0.42.0-alpha.4`)——ADR-0119 范围化接口冻结下的
stable 五包版本;已放弃的 beta 命名不再是当前版本线。

## 当前产品
Expand Down
19 changes: 15 additions & 4 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
"@shoelace-style/shoelace": "npm:@shoelace-style/shoelace@^2.19.0",
"@material/web/checkbox/checkbox.js": "npm:@material/web@^2.0.0/checkbox/checkbox.js",
"nitro": "npm:nitro@3.0.0",
"@rollup/plugin-terser": "npm:@rollup/plugin-terser@1.0.0"
"@rollup/plugin-terser": "npm:@rollup/plugin-terser@1.0.0",
"zod": "npm:zod@^3.25",
"valibot": "npm:valibot@^1.1"
},
"vendor": true,
"nodeModulesDir": "manual",
Expand Down Expand Up @@ -131,8 +133,12 @@
},
"lint": {
"rules": {
"tags": ["recommended"],
"exclude": ["no-sloppy-imports"]
"tags": [
"recommended"
],
"exclude": [
"no-sloppy-imports"
]
},
"exclude": [
"www/content/blog/",
Expand All @@ -145,7 +151,12 @@
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ES2022", "DOM", "DOM.Iterable", "deno.ns"],
"lib": [
"ES2022",
"DOM",
"DOM.Iterable",
"deno.ns"
],
"strict": true,
"skipLibCheck": true,
"jsx": "react-jsx",
Expand Down
20 changes: 18 additions & 2 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions docs/current/PACKAGE_SURFACE.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ semantics (0.42 WC Application Loop and 0.44 Production Runtime scope), the
internal in the map above. Post-freeze changes to the frozen surface require
a major-version ADR.

### 0.42 line additions (unfrozen until the 0.42.0 stable decision)

- `definePage({ renderIntent: { mode } })`: `'auto'`/`'static'`/`'dynamic'`
rendering modes; `'dynamic'` routes render per request through the
generated `dist/server/index.js` (0.42.0-alpha.1).
- Route-module `loader`/`action`/`actions` exports with the ADR-0120
protocol: `fail(status, data)` 422 re-render, 303 PRG, named actions via
`formaction='?/name'` (0.42.0-alpha.2).
- `ActionResult` / `ACTION_FETCH_HEADER` wire types and the
`data-open-enhance` / `data-open-preserve` / `data-open-region`
enhancement attributes with morph-based continuity (0.42.0-alpha.3).

- `@openelement/ui` supported subpaths: `open-badge`, `open-button`,
`open-callout`, `open-card`, `open-code-block`, `open-dialog`,
`open-dropdown`, `open-input`, `open-props-tokens`, `open-tabs`,
Expand Down
4 changes: 2 additions & 2 deletions docs/current/VERSION_PLAN.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# v0.42.0 — WC Application Loop release plan

> Current source package line: `v0.42.0-alpha.3`\
> Current npm registry line: `v0.42.0-alpha.3`\
> Current source package line: `v0.42.0-alpha.4`\
> Current npm registry line: `v0.42.0-alpha.4`\
> Active release target: `v0.41.1`\
> Planning release target: `v0.42.0` (WC Application Loop)\
> Next release line: `v0.43.0` (Universal WC SSR)\
Expand Down
4 changes: 2 additions & 2 deletions docs/governance/PROJECT_WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ complete because an issue, chat message, or SOP says it is complete. It is
complete only when the repository contains the decision, the execution package,
the implementation, and the gates that prove the claim.

Current execution anchor: published package line `v0.42.0-alpha.3`, completed
implementation anchor `v0.42.0-alpha.3`, and `0.42.0` WC Application Loop planning
Current execution anchor: published package line `v0.42.0-alpha.4`, completed
implementation anchor `v0.42.0-alpha.4`, and `0.42.0` WC Application Loop planning
under ADR-0120 and `docs/current/VERSION_PLAN.md`.
OpenElement is one Web Components-native,
static-first application framework: Basic Element is an authoring mode, not a
Expand Down
30 changes: 30 additions & 0 deletions docs/integrations/better-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Auth recipe (better-auth)

> Status: **doc-level, not CI-verified** — integration shape, not a tested
> artifact. It will move to verified status when a consumer reproduces it
> (0.42.x recipe follow-up).

openElement does not ship auth. The loop gives better-auth three honest
attachment points, all Web-standard:

1. **Session read in loaders**: a dynamic route's `loader({ request })`
gets the standard `Request`; pass its headers to better-auth's
`auth.api.getSession({ headers: request.headers })` and return the
session as loader data. Render signed-in vs signed-out in DSD.
2. **Auth endpoints**: mount better-auth's handler as an API route (or a
Nitro route) on the same deployment — it owns its URLs; the framework
does not proxy them.
3. **Actions**: in an action, use the session to authorize before
mutating; on failure `redirect('/login')` (303 by protocol) or
`fail(403, { error })` when the form should re-render with an error.

```ts
export async function loader({ request }: LoaderContext) {
const session = await auth.api.getSession({ headers: request.headers });
if (!session) redirect('/login');
return { user: session.user };
}
```

Sessions remain a 0.44 framework topic; until then the cookie/session
wiring is entirely better-auth's, which is the point of the recipe.
35 changes: 35 additions & 0 deletions docs/integrations/drizzle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Data recipe (Drizzle)

> Status: **doc-level, not CI-verified** — integration shape, not a tested
> artifact. It will move to verified status when a consumer reproduces it
> (0.42.x recipe follow-up).

openElement does not ship an ORM or a data layer. Drizzle (or any query
builder) runs inside loaders and actions, which are ordinary server
functions on a `rendering: 'dynamic'` route:

1. **Reads**: run queries in `loader`; return plain serializable data. The
page renders it in DSD at request time; pure-static routes keep using
build-time data instead.
2. **Writes**: run mutations in `action` after validation (see the
validation recipe). On conflict or constraint failure,
`return fail(422, { error })` to re-render with the echo; on success,
`redirect()` to the changed resource (303 PRG, revalidation re-runs the
loader for you).
3. **Connection**: create the client once at module scope of a small
`db.ts` and import it from routes. Connection secrets belong to the
deployment environment (`ctx.env`), never to the client bundle —
loaders/actions never ship to the browser.

```ts
// app/db.ts
export const db = drizzle(process.env.DATABASE_URL!);

// app/routes/posts.tsx
export async function loader() {
return { posts: await db.select().from(postsTable).limit(20) };
}
```

Transactions, pooling and migrations stay with Drizzle; the framework
owns only the route-to-interaction loop around them.
39 changes: 39 additions & 0 deletions docs/integrations/validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Validation recipe (zod / valibot)

> Status: **verified in CI** — both shapes are exercised end-to-end by the
> request-time fixture (`packages/adapter-vite/__fixtures__/request-time/`:
> `/register` with zod, `/subscribe` with valibot, 422/303 asserted in three
> engines).

The framework is deliberately validation-agnostic: an action receives the
standard `FormData`, and any schema library runs inside it. The contract is
the ADR-0120 protocol, not the library:

1. Parse `ctx.formData` with your schema.
2. On failure `return fail(422, { error, ...submittedValues })` — the page
re-renders with the message and the echo (no JavaScript required).
3. On success `redirect(...)` (or return data for the default 303 PRG).
4. Because a failed action may be re-run, validate first and mutate only
after validation passes.

```ts
import { definePage, fail, redirect, useActionData } from '@openelement/app';
import { z } from 'zod';

const schema = z.object({ email: z.string().email('a valid email is required') });

export function action(ctx: { formData: FormData }) {
const parsed = schema.safeParse({ email: String(ctx.formData.get('email') ?? '') });
if (!parsed.success) {
return fail(422, {
error: parsed.error.issues[0]?.message ?? 'invalid input',
email: String(ctx.formData.get('email') ?? ''),
});
}
redirect(`/register?welcome=${encodeURIComponent(parsed.data.email)}`);
}
```

valibot is interchangeable (`v.safeParse(schema, input)`); see the fixture
for both. The page reads the failure via `useActionData()`; mark the form
`data-open-enhance` to get the morph-based enhanced path for free.
33 changes: 33 additions & 0 deletions docs/release/v0.42.0-alpha.3.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# v0.42.0-alpha.3

## Revalidation continuity

The third alpha of the 0.42 line (ADR-0120): the enhanced submit no
longer reloads the world. `data-open-enhance` forms fetch the same HTML
the no-JavaScript path renders (303/422), morph it into place, and follow
the PRG target with `history.pushState`.

- **Island survival**: a hydrated island whose light-DOM surface is
unchanged in the incoming document keeps its shadow state (the DSD
template child is excluded from the comparison). Islands whose surface
changed are replaced; `data-open-preserve` exempts any subtree; the
island client script is never re-executed by a morph.
- **Named regions**: a `data-open-region` container limits the morph to
the matching region when present.
- The `ActionResult` JSON path remains for custom clients; the built-in
enhancement uses HTML morphing for continuity.

## Verification

- Survival matrix: a counter island at 3 survives both a 422 validation
morph and a PRG success morph; static/request-time mixed navigation —
Chromium, Firefox and WebKit, 36/36.
- Full release-tier gates green; npm `alpha`/`latest` at `0.42.0-alpha.3`;
post-publish consumer and third-party WC smoke.

## Migrating from alpha.2

Nothing required. Forms already marked `data-open-enhance` gain morphing
automatically; if you relied on the JSON `ActionResult` responses, they
are unchanged for `x-openelement-action` callers.

---

AutoFlow3 patch release evidence: `publish-existing-v0.42.0-alpha.3-2026-07-27T08-43-31-362Z`.

- Previous package line: `0.42.0-alpha.2`
Expand Down
15 changes: 15 additions & 0 deletions docs/release/v0.42.0-alpha.4-performance.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": "0.42.0-alpha.4",
"date": "2026-07-27T09:09:32.598Z",
"route": "/live (request-time, loader + DSD render)",
"cold": {
"ms": 28.64
},
"warm": {
"samples": 50,
"p50": 1.58,
"p95": 2.97,
"mean": 1.62
},
"note": "Buffered per-request DSD render via the generated dist/server entry on Deno.serve; the 0.44 stream/abort/timeout work compares against this."
}
6 changes: 3 additions & 3 deletions docs/roadmap/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Execution and release state follow the
[`Project Workflow`](../governance/PROJECT_WORKFLOW.md).

> Source of truth for forward product planning.\
> Published package line: `v0.42.0-alpha.3`.\
> Active execution target: `v0.42.0-alpha.3`.\
> Published package line: `v0.42.0-alpha.4`.\
> Active execution target: `v0.42.0-alpha.4`.\
> Current implementation state: five-package convergence is published;
> alpha.17 closed the first audit remediation, alpha.18 completed the
> second audit sweep (ADR-0117), and alpha.19 completed the third (ADR-0118).\
Expand Down Expand Up @@ -116,7 +116,7 @@ making the standard Custom Element contract span both layers. See the official

## Current release state

`0.42.0-alpha.3` is the published package line. npm beta.1 through beta.3 are
`0.42.0-alpha.4` is the published package line. npm beta.1 through beta.3 are
immutable partial artifacts and remain withdrawn from the active release story.
The planned beta name was cancelled so the version label honestly reflects
that breaking architecture and interface changes are still allowed.
Expand Down
6 changes: 3 additions & 3 deletions docs/status/STATUS.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# OpenElement Status

> Updated: 2026-07-27\
> Repository package line: `v0.42.0-alpha.3`\
> npm registry line: `v0.42.0-alpha.3`\
> Active release target: `v0.42.0-alpha.3`\
> Repository package line: `v0.42.0-alpha.4`\
> npm registry line: `v0.42.0-alpha.4`\
> Active release target: `v0.42.0-alpha.4`\
> Next release line: `v0.42.0`\
> Product graph: five packages\
> Current maturity stage: stable (0.41.x)
Expand Down
Loading
Loading