commits
drop the per-package tsconfig.build.json files and let `tsgo` use the
default `tsconfig.json` (which already includes test and bench files).
this surfaces test/bench type errors at build time instead of letting
them rot silently. fixes the type errors that surfaced once the unified
build started seeing them: stale imports in the richtext-segmenter
bench, `number[]` buffers in the varint tests, internal-only car
helpers in the repo tests, and overbroad `unknown`/`Did` types in the
xrpc-server jwt-verifier tests.
publish artifacts are unchanged: every package now also excludes
`!dist/**/*.{test,bench}.*` via `package.json#files` so the compiled
test/bench output never ships.
explain that `input` is only populated for declared lex JSON bodies.
blob-input procedures get `undefined` here; the handler reads
`request.body` as a stream.
- add `nbf` (not-before) validation with configurable `clockLeeway`
(default 5s) on `exp`/`nbf`.
- add `maxAge` option (default 300s) that bounds how far `exp` may be in
the future and `iat` may be in the past, preventing long-lived tokens.
- add optional `replayStore` for nonce/replay protection. when set, tokens
must carry a `jti` claim and the store is consulted with
`{ iss, jti }` per verification; duplicates are rejected as
`NonceNotUnique`.
- collapse the verifier surface onto a single throwing
`verifyRequest(request, options)` method that parses the `Authorization`
header, verifies the bearer token, forwards `request.signal` (or
`options.signal`) to DID resolution, and throws `AuthRequiredError`
with a populated `WWW-Authenticate: Bearer` challenge on failure.
- align `AuthError.error` vocabulary with the atproto reference SDK:
`BadJwt` (was `MalformedJwt`), `DidResolutionFailed` (was
`UnresolvedDidDocument`), `InvalidAudience` (was `BadJwtAudience`);
new codes `MissingBearer`, `JwtNotYetValid`, `JwtTooOld`,
`NonceNotUnique`.
the router now calls `await ws.drain()` after every frame it sends so
adapters can gate on the outgoing send buffer. watermarks are
adapter-level concerns (platform-tuned), not router-level, so each
adapter accepts `highWaterMark` / `lowWaterMark` (default 250 KB / 50 KB)
via its factory options:
- Node (`ws`): polls `ws.bufferedAmount` until it drops below the low
watermark.
- Bun: same, using `ws.getBufferedAmount()`.
- Deno: same, using the native `WebSocket.bufferedAmount`.
- Cloudflare Workers: no-op; the runtime does not surface the outgoing
buffer.
without backpressure, a slow client on a high-throughput subscription
(e.g. firehose) could balloon memory in the adapter's send queue.
add `formatWWWAuthenticate()` for building RFC 7235 challenge headers from
`{ scheme, params?, token68? }` values. `AuthRequiredError` now accepts a
`wwwAuthenticate` option that auto-formats the header and appends
`access-control-expose-headers: www-authenticate` so browsers can read the
challenge from CORS responses.
separate "produce a response" from "observe an error for telemetry" so the
router doesn't conflate them. `handleException` continues to translate
thrown errors into responses; new `onError` / `onSocketError` hooks receive
`{ error, request }` for logging/metrics and are fire-and-forget. both
observers skip client-induced errors (aborted requests, `XRPCError`,
`XRPCSubscriptionError`), so they only fire for bugs worth investigating.
`handleSubscriptionException` is removed; its default-throw behaviour was
unhelpful (unhandled rejections inside an adapter's async context), and
the new `onSocketError` is the intended replacement.
when set, routes `/xrpc/_health` to the provided handler. this endpoint
is non-standard; callers opt in and own the response shape (status code,
body, headers). without the option, `_health` falls through to
`handleNotFound`.
HEAD is the spec-defined no-body GET. the runtime (Node adapter, Bun, Deno,
CF Workers) strips the response body per the Fetch API, so the router just
needs to dispatch it to the same handler as GET and return the same
`allow: GET, HEAD` in 405 responses.
consolidate on the standard `Error.message` field rather than a separate
`description`. response bodies continue to serialize as `{ error, message }`;
the `InvalidHttpMethod` error code is replaced by the spec-standard
`InvalidRequest` to keep the vocabulary minimal.
prepare for the audience/kid/lxm changes described in
https://github.com/bluesky-social/proposals/tree/main/0014-service-auth-revised
- replace `ServiceJwtVerifier.serviceDid` with `acceptAudiences` so a service
can accept both bare-DID and DID-with-service-fragment audiences during the
ecosystem transition
- widen jwt `aud` to accept `AtprotoAudience` in addition to a bare DID
- make the `kid` jwt header drive verification-method lookup in the issuer's
DID document (defaulting to `#atproto` when absent); still restricted to
`#atproto` for now, future kid support is non-breaking
- require `lxm` on both signing and verification paths, matching the spec's
"required for XRPC endpoint calls" direction
closes https://github.com/mary-ext/atcute/pull/73
closes https://github.com/mary-ext/atcute/issues/72
drop the per-package tsconfig.build.json files and let `tsgo` use the
default `tsconfig.json` (which already includes test and bench files).
this surfaces test/bench type errors at build time instead of letting
them rot silently. fixes the type errors that surfaced once the unified
build started seeing them: stale imports in the richtext-segmenter
bench, `number[]` buffers in the varint tests, internal-only car
helpers in the repo tests, and overbroad `unknown`/`Did` types in the
xrpc-server jwt-verifier tests.
publish artifacts are unchanged: every package now also excludes
`!dist/**/*.{test,bench}.*` via `package.json#files` so the compiled
test/bench output never ships.
- add `nbf` (not-before) validation with configurable `clockLeeway`
(default 5s) on `exp`/`nbf`.
- add `maxAge` option (default 300s) that bounds how far `exp` may be in
the future and `iat` may be in the past, preventing long-lived tokens.
- add optional `replayStore` for nonce/replay protection. when set, tokens
must carry a `jti` claim and the store is consulted with
`{ iss, jti }` per verification; duplicates are rejected as
`NonceNotUnique`.
- collapse the verifier surface onto a single throwing
`verifyRequest(request, options)` method that parses the `Authorization`
header, verifies the bearer token, forwards `request.signal` (or
`options.signal`) to DID resolution, and throws `AuthRequiredError`
with a populated `WWW-Authenticate: Bearer` challenge on failure.
- align `AuthError.error` vocabulary with the atproto reference SDK:
`BadJwt` (was `MalformedJwt`), `DidResolutionFailed` (was
`UnresolvedDidDocument`), `InvalidAudience` (was `BadJwtAudience`);
new codes `MissingBearer`, `JwtNotYetValid`, `JwtTooOld`,
`NonceNotUnique`.
the router now calls `await ws.drain()` after every frame it sends so
adapters can gate on the outgoing send buffer. watermarks are
adapter-level concerns (platform-tuned), not router-level, so each
adapter accepts `highWaterMark` / `lowWaterMark` (default 250 KB / 50 KB)
via its factory options:
- Node (`ws`): polls `ws.bufferedAmount` until it drops below the low
watermark.
- Bun: same, using `ws.getBufferedAmount()`.
- Deno: same, using the native `WebSocket.bufferedAmount`.
- Cloudflare Workers: no-op; the runtime does not surface the outgoing
buffer.
without backpressure, a slow client on a high-throughput subscription
(e.g. firehose) could balloon memory in the adapter's send queue.
add `formatWWWAuthenticate()` for building RFC 7235 challenge headers from
`{ scheme, params?, token68? }` values. `AuthRequiredError` now accepts a
`wwwAuthenticate` option that auto-formats the header and appends
`access-control-expose-headers: www-authenticate` so browsers can read the
challenge from CORS responses.
separate "produce a response" from "observe an error for telemetry" so the
router doesn't conflate them. `handleException` continues to translate
thrown errors into responses; new `onError` / `onSocketError` hooks receive
`{ error, request }` for logging/metrics and are fire-and-forget. both
observers skip client-induced errors (aborted requests, `XRPCError`,
`XRPCSubscriptionError`), so they only fire for bugs worth investigating.
`handleSubscriptionException` is removed; its default-throw behaviour was
unhelpful (unhandled rejections inside an adapter's async context), and
the new `onSocketError` is the intended replacement.
prepare for the audience/kid/lxm changes described in
https://github.com/bluesky-social/proposals/tree/main/0014-service-auth-revised
- replace `ServiceJwtVerifier.serviceDid` with `acceptAudiences` so a service
can accept both bare-DID and DID-with-service-fragment audiences during the
ecosystem transition
- widen jwt `aud` to accept `AtprotoAudience` in addition to a bare DID
- make the `kid` jwt header drive verification-method lookup in the issuer's
DID document (defaulting to `#atproto` when absent); still restricted to
`#atproto` for now, future kid support is non-breaking
- require `lxm` on both signing and verification paths, matching the spec's
"required for XRPC endpoint calls" direction