# 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 ` | `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. These are **our own superseded options**, not an out-of-date dependency — there is no newer version to move to, only newer options we already added. Removing them means deleting the old aliases and moving the few call sites that still use them. | Group | Where | Replacement | Still used? | | --------------------------------------------------------------------- | ---------------------------- | ------------------------------------------- | ----------------------------------------------------------- | | `onSignedIn` / `onSignedOut` on HTTP route options and plugin options | `http/index.ts`, `plugin.ts` | the same names on `createAuthEngine({ … })` | only `packages/auth/test/http.test.ts` and `plugin.test.ts` | | `onSuccessfullSignUp` (misspelled alias) | `types.ts` | `onSuccessfulSignUp` | nowhere — zero references | | `rpId` / `origin` on passkey verification | `engine.ts` (4 sites) | values bound to the issued challenge | `packages/auth/test/engine.test.ts` | Two things this table settles: - **The recommended form is already in use.** `examples/auth-showcase/app/lib/auth.ts` passes `onSignedIn` / `onSignedOut` to `createAuthEngine`, which is the _current_ API. The deprecated members are the same names on different option objects, so the example needs no change. - **Neither test app uses any of them.** Nothing in `D:\Company\wrnexuspps` references these options. So the blast radius is three test files inside `packages/auth`, which are exercising the deprecated paths and are updated or removed alongside them. The `rpId` / `origin` options are already ignored at runtime — verification uses the values bound to the issued challenge — so removing them changes no behaviour, only the shape of the call. ## 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.