Skip to content

Commit 9891bf2

Browse files
committed
docs: clarify response validation boundaries
Avoid implying Rouzer is a poor fit for any runtime response validation. The docs now distinguish server-boundary response validation from the intended model: response markers are type contracts, with runtime integrity checks placed where data enters server or client code.
1 parent 2c5236d commit 9891bf2

3 files changed

Lines changed: 25 additions & 14 deletions

File tree

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ Use Rouzer if:
2424

2525
- your server and client can import the same TypeScript route tree
2626
- you want Zod request validation on both sides of an HTTP boundary
27+
- response data is validated at data/client boundaries, not by re-checking every
28+
handler return
2729
- a Hattip-compatible handler fits your server runtime
2830
- you prefer named resource/action functions over a generated client class
2931

3032
Consider something else if:
3133

3234
- you need OpenAPI-first workflows, schema files, or generated clients for other
3335
languages
34-
- you need runtime response-body validation; `$type<T>()`, `$error<T>()`, and
35-
`ndjson.$type<T>()` are compile-time only
36+
- you want the router to validate every response body at the server boundary;
37+
`$type<T>()`, `$error<T>()`, and `ndjson.$type<T>()` are type contracts
3638
- you want a framework that owns controllers, data loading, rendering, and
3739
deployment adapters
3840
- you cannot use ESM or Zod v4+

docs/context.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ Use Rouzer when:
1717
- generated clients should stay close to route definitions instead of being
1818
produced by a separate OpenAPI build step
1919

20-
Rouzer is not a response validation library, an OpenAPI generator, or a complete
20+
Rouzer is not a server response validator, an OpenAPI generator, or a complete
2121
server framework. It focuses on typed route contracts, request validation,
22-
routing, and a small client wrapper.
22+
routing, and a small client wrapper. Response markers are type contracts; if
23+
response data comes from an untrusted source, validate it where it enters your
24+
server or client code instead of relying on the router to re-check handler
25+
returns.
2326

2427
## Core abstractions
2528

@@ -96,7 +99,9 @@ and server support.
9699

97100
`response: $type<T>()` is a TypeScript-only marker for JSON success payloads. It
98101
tells handlers and client action functions what payload type to expect, but
99-
Rouzer does not validate response bodies at runtime.
102+
Rouzer does not validate handler return values at the server boundary. Validate
103+
response data where it enters your system, such as an external API client,
104+
database decoder, or UI/client boundary, when runtime integrity is required.
100105

101106
Use a status-keyed response map when callers need to branch on declared statuses:
102107

@@ -496,8 +501,9 @@ await client.profiles.update({
496501

497502
## Constraints and gotchas
498503

499-
- `$type<T>()`, `$error<T>()`, and `ndjson.$type<T>()` are compile-time only and
500-
do not validate response payloads or streamed items.
504+
- `$type<T>()`, `$error<T>()`, and `ndjson.$type<T>()` are compile-time-only type
505+
contracts. Rouzer does not re-validate handler return values at the server
506+
boundary.
501507
- NDJSON support is for response streams; request bodies still use the existing
502508
JSON body schema path.
503509
- Declared `$error<T>()` responses are JSON responses. Use a custom `Response`

src/type.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import type { Unchecked, UncheckedError } from './common.js'
33
/**
44
* Create a compile-time-only marker for an action's JSON response payload type.
55
*
6-
* @remarks `$type<T>()` does not perform runtime validation. It lets Rouzer type
7-
* server handler return values and client action functions for HTTP actions
8-
* whose responses are expected to be JSON. Use it directly as `response` for one
9-
* JSON success shape, or as a success entry in a status-keyed response map.
6+
* @remarks `$type<T>()` does not validate handler return values at the server
7+
* boundary. It lets Rouzer type server handler return values and client action
8+
* functions for HTTP actions whose responses are expected to be JSON. Use it
9+
* directly as `response` for one JSON success shape, or as a success entry in a
10+
* status-keyed response map. Validate response data where it enters your server
11+
* or client code when runtime integrity is required.
1012
*
1113
* @example
1214
* ```ts
@@ -28,9 +30,10 @@ $type.symbol = Symbol()
2830
* Create a compile-time-only marker for a declared error response type.
2931
*
3032
* @remarks `$error<T>()` marks a non-success response branch in a status-keyed
31-
* response map. On the server, handlers use `ctx.error(status, body)` to return
32-
* declared errors. On the client, declared error responses resolve as
33-
* `[error, null, status]` tuple entries instead of rejecting the promise.
33+
* response map. It is a type contract, not a runtime validator. On the server,
34+
* handlers use `ctx.error(status, body)` to return declared errors. On the
35+
* client, declared error responses resolve as `[error, null, status]` tuple
36+
* entries instead of rejecting the promise.
3437
*
3538
* @example
3639
* ```ts

0 commit comments

Comments
 (0)