feat(svrs)!: decisión 2/3 — la barrera server-only vive en la PUERTA de cada motor, y la hace cumplir el build
Firmada por el autor (b54bb3ad0). La convención `*.server.ts` no existía en
CERO ficheros del repo; el alias `$svrs` resolvía libre hacia cliente y nada
habría detenido el import accidental que arrastra `node:crypto` —o un
secreto— al bundle del navegador. La violación no estaba ocurriendo; la
puerta no existía.
- Las ENTRADAS se renombran (`index.server.ts`, `testing.server.ts`) con
`git mv` para preservar historia, y el ALIAS absorbe el rename: ningún
consumidor cambia su import. Es la PUERTA, no cada habitación: el resto del
motor se queda como está.
- SvelteKit rompe el BUILD si un módulo `*.server.ts` entra en el grafo
cliente: barrera por construcción, del framework anfitrión, sin maquinaria
propia. `npm run build` VERDE (2m16s) es la prueba de que el grafo sigue
limpio tras el rename.
- El censo `server-boundary.test.ts` SE QUEDA como segunda capa (cubre lo que
SvelteKit no compila: node puro, scripts).
- La convención queda escrita como LEY DEL TIER en la doctrina de svrs.
Y una corrección de INSTRUMENTO que este rename destapó: `docs-check`
modelaba los alias como de UN segmento, así que declaró rota una importación
VÁLIDA (`$svrs/auth/testing`, que ahora es clave exacta del mapa) y puso rojo
el gate y con él el hook pre-push compartido. Ahora resuelve como resuelve
Vite —clave más larga primero—. El doc tenía razón y el instrumento estaba
mal: la clase que este corpus existe para cazar, aterrizando sobre el
cazador.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
alpha-0.1-background
parent
35d0005de4
commit
64ead84072
@ -0,0 +1,57 @@
|
||||
# svrs — the server-authoritative tier
|
||||
|
||||
`src/svrs/` holds the engines that own server authority: secrets, credential
|
||||
stores, `node:crypto`, runtime enforcement. Nothing in this tier is allowed to
|
||||
reach a browser bundle.
|
||||
|
||||
## Law of the tier: the GATE is a `*.server.ts` module
|
||||
|
||||
Each engine's **entry** — the file the alias points at — is named
|
||||
`*.server.ts`. Not each room of the engine: the door.
|
||||
|
||||
| Entry | Alias |
|
||||
| --------------------------------- | -------------------- |
|
||||
| `src/svrs/auth/index.server.ts` | `$svrs/auth` |
|
||||
| `src/svrs/auth/testing.server.ts` | `$svrs/auth/testing` |
|
||||
|
||||
The alias absorbs the name, so **no consumer import changes**: code still
|
||||
writes `from '$svrs/auth'`. The alias entries live in `vite.config.ts` (the
|
||||
source) and are mirrored in `svelte.config.js`; because they are prefix
|
||||
matches, the longer specifier must be listed first.
|
||||
|
||||
### Why the gate and not every room
|
||||
|
||||
`*.server.ts` is native to SvelteKit, and its guard is **transitive**. The
|
||||
plugin (`vite-plugin-sveltekit-guard`, `@sveltejs/kit/src/exports/vite/index.js`)
|
||||
tests `/.*\.server\..+/` against the basename of any module loaded in a
|
||||
non-SSR pass, then walks the import graph back to the route entrypoints and
|
||||
**fails the build** naming the chain. A client module three hops away from the
|
||||
gate is caught just as surely as one that imports it directly — so sealing the
|
||||
door seals every room behind it, including the `src/svrs/index.ts` barrel that
|
||||
re-exports `AuthServer`.
|
||||
|
||||
The barrier therefore costs no machinery of our own: the host framework
|
||||
enforces it at build time, which is the only moment that matters.
|
||||
|
||||
Two carve-outs are worth knowing, both by design:
|
||||
|
||||
- The guard skips `ssr === true` loads, so server code imports the gate freely.
|
||||
- The guard is disabled when `process.env.TEST === 'true'`, so Vitest is
|
||||
unaffected — which is exactly why the second layer below still exists.
|
||||
|
||||
## Second layer: the census
|
||||
|
||||
`src/svrs/auth/test/server-boundary.test.ts` walks `src/arts`, `src/uix` and
|
||||
`web` and fails on the first `$svrs/auth` import. It covers the contexts the
|
||||
SvelteKit guard cannot see: plain Node, scripts, and any consumer built
|
||||
outside a SvelteKit client pass. Keep both — they fail in different worlds.
|
||||
|
||||
## Engines
|
||||
|
||||
- [`auth/`](auth/README.md) — authentication authority. **Gated.**
|
||||
- [`perm/`](perm/README.md) — authorization authority.
|
||||
- [`cache/`](cache/README.md) — server cache authority.
|
||||
|
||||
`perm` and `cache` have not been gated yet; their entries are still plain
|
||||
`index.ts`. Extending the law to them is the same two-line move: rename the
|
||||
entry, add the alias.
|
||||
@ -1,3 +1,3 @@
|
||||
export * as AuthServer from './auth/index.ts';
|
||||
export * as AuthServer from './auth/index.server.ts';
|
||||
export * as CacheServer from './cache/index.ts';
|
||||
export * as PermServer from './perm/index.ts';
|
||||
|
||||
Loading…
Reference in new issue