docs: spec for the legacy, deprecated, and unused-config cleanup
All seven compatibility keys are dead configuration: traced every reference and none is read by any compiler, codegen, or runtime code. They are written into every generated config and ignored. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# Legacy, deprecated, and unused-config cleanup — Design
|
||||
|
||||
**Date:** 2026-08-19
|
||||
**Status:** Approved for implementation
|
||||
**Scope:** Remove the compatibility-flag surface, the `"legacy"` function runtime, dead migrations,
|
||||
and deprecated APIs — before the framework's first public release.
|
||||
|
||||
## Goal
|
||||
|
||||
WRNexus carries compatibility machinery for a public it does not yet have. Every branch of it is
|
||||
either switched off in the only apps that exist, or wired to nothing at all. Removing it now costs
|
||||
almost nothing; removing it after release costs a major version and other people's time.
|
||||
|
||||
## Why this is safe now
|
||||
|
||||
Two pieces of evidence, both verified rather than assumed:
|
||||
|
||||
**The only consumers already run without it**, which matters for the config files themselves even
|
||||
though the keys are inert. `D:\Company\wrnexus\apps\admin` and
|
||||
`D:\Company\wrnexus\apps\web` — both test projects, neither deployed — set every compatibility flag
|
||||
to `false` and `legacyDefaultRuntime: "current"`. They are already on the modern path; removing the
|
||||
flags means deleting the lines that say "off".
|
||||
|
||||
**None of the seven keys change any behaviour.** Verified by tracing every reference, not by
|
||||
reading the types. `legacyEmit`, `legacyEventProps`, `legacyComponentDiscovery`, `stringLayouts`,
|
||||
and `legacyDefaultRuntime` appear in exactly three places each: the type declaration in
|
||||
`config.ts`, the scaffolder in `create.ts`, and the insertion in `update.ts`. **No compiler,
|
||||
codegen, or runtime code reads any of them.** They are written into every generated config and then
|
||||
ignored.
|
||||
|
||||
The remaining two are the same story with more machinery. `resolveCompatibility` (`packages/styles/src/compatibility.ts`)
|
||||
produces a report — an effective date, a behaviour number, and advisory strings. Tracing every
|
||||
consumer: the `wrnexus compatibility` command prints it, and `config.ts` raises one validation error
|
||||
when the configured date is _newer_ than the CLI supports. **No compiler branch and no runtime
|
||||
behaviour reads `effectiveDate` or `effectiveBehaviour`.** The mechanism is scaffolding that was
|
||||
never connected.
|
||||
|
||||
### Non-goals
|
||||
|
||||
- **The legacy `api` block forms.** Bare-body blocks using `with ($data)`, and `api` entries inside
|
||||
`ssr {}` / `client {}`, are _replaced_ rather than deleted — that is the next spec's job. Removing
|
||||
them here would leave a gap with no working mechanism.
|
||||
- Adding any configuration key. This spec only removes them.
|
||||
- Changing any behaviour that is currently switched on.
|
||||
|
||||
## What gets removed
|
||||
|
||||
| Item | Where | Why it goes |
|
||||
| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- |
|
||||
| `compatibility: { legacyEmit, legacyEventProps, legacyComponentDiscovery, stringLayouts }` | `packages/styles/src/config.ts` (`CompatibilityConfig`) | Never read by any code |
|
||||
| `functions: { legacyDefaultRuntime }` | `packages/styles/src/config.ts` (`FunctionsConfig`) | Never read by any code |
|
||||
| `compatibilityDate` | `packages/styles/src/compatibility.ts` (`CompatibilityPolicy`) | Gates nothing |
|
||||
| `frameworkBehaviour` | same | Gates nothing |
|
||||
| `resolveCompatibility`, `CompatibilityReport`, `isCompatibilityDate`, `CURRENT_COMPATIBILITY_DATE`, `CURRENT_FRAMEWORK_BEHAVIOUR` | `packages/styles/src/compatibility.ts` | Whole module serves only the two dead keys |
|
||||
| `wrnexus compatibility <check\|explain\|upgrade>` | `packages/cli/src/compatibility-command.ts`, dispatch at `packages/cli/src/index.ts:295`, help text at `:75` | Reports on removed keys |
|
||||
| `"legacy"` variant of `FunctionRuntime` | `packages/syntax/src/v060.ts`, branches in `packages/compiler/src/client-codegen.ts` and `server-codegen.ts` | An unmarked function becomes `shared` (see below) |
|
||||
| Migrations below `0.8.0` | `packages/cli/src/update.ts` | 111 migrations reach back to `0.2.8`; no project exists below `0.8.x` |
|
||||
| Deprecated re-export shims | `packages/compiler/src/{parser,tokenizer,types}.ts` | Two lines each, re-exporting `@wrnexus/syntax` |
|
||||
| Deprecated `@wrnexus/auth` options | `engine.ts` (4 sites), `http/index.ts` (2), `plugin.ts` (2), `types.ts` (1) | See "Deprecated auth options" |
|
||||
|
||||
## The `"legacy"` function runtime
|
||||
|
||||
`FunctionRuntime` is `"legacy" | "client" | "server" | "shared"`. `"legacy"` is what an _unmarked_
|
||||
`function foo()` gets, and `legacyDefaultRuntime` decides how it behaves. Both codegens then test
|
||||
membership: `["legacy", "client", "shared"]` for the browser and `["legacy", "server", "shared"]`
|
||||
for the server — which is to say **an unmarked function is currently emitted into both bundles,
|
||||
exactly like `shared`.**
|
||||
|
||||
`legacyDefaultRuntime` looks like it should modulate this, but it is never read (above), so the
|
||||
mapping is unconditional: unmarked is always `"legacy"`, and `"legacy"` is always emitted to both
|
||||
bundles.
|
||||
|
||||
So the removal is mechanical: delete the `"legacy"` variant, and parse an unmarked function as
|
||||
`"shared"`. The emitted output for every existing unmarked function is unchanged, in every
|
||||
configuration. `FunctionRuntime`
|
||||
becomes `"client" | "server" | "shared"`, and the membership tests lose one element each.
|
||||
|
||||
This is the one item where behaviour could drift if done carelessly, so its test is explicit: an
|
||||
unmarked function must still appear in both the browser and server modules.
|
||||
|
||||
## Deprecated re-export shims
|
||||
|
||||
`packages/compiler/src/parser.ts`, `tokenizer.ts`, and `types.ts` are two-line files re-exporting
|
||||
`@wrnexus/syntax`. They are marked deprecated, but **`codegen.ts` and `native-codegen.ts` still
|
||||
import from them**, so deleting the files is not enough — those imports must be repointed at
|
||||
`@wrnexus/syntax` first. Removing the files without that step breaks the build.
|
||||
|
||||
## Deprecated auth options
|
||||
|
||||
`@wrnexus/auth` carries nine `@deprecated` markers in three groups:
|
||||
|
||||
- `onSignedIn` / `onSignedOut` aliases in `http/index.ts` and `plugin.ts`, superseded by
|
||||
`createAuthEngine({ onSignedIn })`
|
||||
- `onSuccessfulSignUp`'s misspelled alias in `types.ts`
|
||||
- Four RP-ID and origin options in `engine.ts`, superseded by values bound to the issued challenge
|
||||
|
||||
These are a different package from the compiler and config surface, and they are removable
|
||||
independently. They are included here because the instruction was to remove deprecated code, and
|
||||
splitting them into their own pass would mean two migrations of the same apps. If the auth surface
|
||||
should stay, drop this section — nothing else in the spec depends on it.
|
||||
|
||||
## Migration
|
||||
|
||||
`examples/basic-app` and both test apps need one pass each:
|
||||
|
||||
1. Delete `compatibility`, `functions`, `compatibilityDate`, and `frameworkBehaviour` from
|
||||
`wrnexus.config.ts` — seven lines per app.
|
||||
2. `packages/cli/src/create.ts` stops scaffolding those keys, so new apps get a shorter config.
|
||||
|
||||
No `.wrn` source changes. Nothing in this spec alters page syntax.
|
||||
|
||||
The removed `0.2.x`–`0.7.x` migrations mean a project below `0.8.0` can no longer be upgraded by
|
||||
`wrnexus update`. No such project exists, and rescuing one would be a manual job either way.
|
||||
|
||||
## Testing
|
||||
|
||||
- **The `"legacy"` runtime removal is behaviour-preserving**: an unmarked function still appears in
|
||||
both the browser and server modules. This is the assertion most worth writing, because it is the
|
||||
only removal that could silently change output.
|
||||
- **Config rejects the removed keys** rather than ignoring them, so a stale config fails loudly with
|
||||
a message naming the key. A silently-ignored key would leave someone believing a flag still
|
||||
applies.
|
||||
- **`create.ts` scaffolds a config without them**, asserted against the generated file.
|
||||
- **`wrnexus update` still runs** with the pre-`0.8.0` migrations gone, and reports correctly for an
|
||||
app already at the current version.
|
||||
- **`examples/basic-app` builds and its suite passes** after its config is trimmed — the end-to-end
|
||||
guard that nothing depended on the removed surface.
|
||||
- **The full gate** (`bun run check:production`) passes, including the editor bundles, which embed
|
||||
the compiler and must be rebuilt after `FunctionRuntime` changes.
|
||||
|
||||
## What we give up
|
||||
|
||||
Deleting `compatibilityDate` and `frameworkBehaviour` removes the standard escape hatch for changing
|
||||
a default after going public — the mechanism that lets an existing app keep old behaviour by pinning
|
||||
a date. Today it is wired to nothing, so it protects nobody, and an unused mechanism rots rather
|
||||
than matures. If a gate is needed later it can be reintroduced deliberately, against a real
|
||||
behaviour change, instead of being carried empty. This is a considered trade rather than a free
|
||||
deletion.
|
||||
Reference in New Issue
Block a user