Skip to content

@btravstack/http-server


@btravstack/http-server / index

index ​

Classes ​

AuthenticatorUnavailable ​

Defined in: packages/http-server/src/auth.ts:31

Authentication cannot decide because its dependency is unavailable. Carries no credential details.

Extends ​

  • TaggedErrorInstance<"AuthenticatorUnavailable", { }>

Constructors ​

Constructor ​
ts
new AuthenticatorUnavailable(args): AuthenticatorUnavailable;

Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386

Parameters ​
ParameterType
argsvoid
Returns ​

AuthenticatorUnavailable

Inherited from ​

TaggedError("AuthenticatorUnavailable").constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
_tagreadonly"AuthenticatorUnavailable"TaggedError("AuthenticatorUnavailable")._tagnode_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363
cause?publicunknownTaggedError("AuthenticatorUnavailable").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstringTaggedError("AuthenticatorUnavailable").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("AuthenticatorUnavailable").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstringTaggedError("AuthenticatorUnavailable").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

CredentialRefused ​

Defined in: packages/http-server/src/auth.ts:28

A credential the caller presented was refused — a capability URL whose signature does not verify, or that has expired. Distinct from Unauthenticated because a login cannot help: the walk answers it as UnderScoped, 403, unless another requirement accepts the caller. Carries nothing, for Unauthenticated's reason.

Extends ​

  • TaggedErrorInstance<"CredentialRefused", { }>

Constructors ​

Constructor ​
ts
new CredentialRefused(args): CredentialRefused;

Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386

Parameters ​
ParameterType
argsvoid
Returns ​

CredentialRefused

Inherited from ​

TaggedError("CredentialRefused").constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
_tagreadonly"CredentialRefused"TaggedError("CredentialRefused")._tagnode_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363
cause?publicunknownTaggedError("CredentialRefused").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstringTaggedError("CredentialRefused").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("CredentialRefused").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstringTaggedError("CredentialRefused").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

HttpChallenges ​

Defined in: packages/http-server/src/protected-resource.ts:56

The challenges a 401 carries, one member per composed surface. Protected resources also identify their metadata for typed Bearer scope refusals. httpServer contributes the empty member that keeps the set from being the empty dependency di refuses; an empty challenge is dropped, so a graph composing no protected resource sends no header.

A set port for CookieSchemes' reason: the runtime never sees what the root provides beside it, so the header is a fact about the graph.

Extends ​

Constructors ​

Constructor ​
ts
new HttpChallenges(): HttpChallenges;

Defined in: packages/di/dist/index.d.mts:29

Returns ​

HttpChallenges

Inherited from ​

Port.many("HttpChallenges")<HttpChallenge | HttpRequestChallenge>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
[ID]readonly"HttpChallenges"Port.many("HttpChallenges").[ID]packages/di/dist/index.d.mts:11
[MANY]readonlytruePort.many("HttpChallenges").[MANY]packages/di/dist/index.d.mts:30
[SERVICE]readonlyreadonly ( | HttpChallenge | HttpRequestChallenge)[]Port.many("HttpChallenges").[SERVICE]packages/di/dist/index.d.mts:12
manystatic readonlytruePort.many("HttpChallenges").manypackages/di/dist/index.d.mts:33
portIdstatic readonly"HttpChallenges"Port.many("HttpChallenges").portIdpackages/di/dist/index.d.mts:32

HttpConfig ​

Defined in: packages/http-server/src/http-config.ts:10

What the transport is bound and configured with, as a service: the starter binds it from PORT (default 3000; 0 lets the OS pick), HOST (default 0.0.0.0), HTTP_BODY_LIMIT, HTTP_STREAM_BODY_LIMIT, HTTP_CORS_ORIGIN, HTTP_COMPRESSION, HTTP_HEADERS_TIMEOUT_MS and HTTP_REQUEST_TIMEOUT_MS, each pinned by the matching option, and anything else in the graph may read it.

Extends ​

  • PortInstance<"HttpConfig", { bodyLimit: number; compression: boolean; corsOrigin: string; headersTimeoutMs: number; hostname: string; port: number; requestTimeoutMs: number; streamBodyLimit: number; }>

Constructors ​

Constructor ​
ts
new HttpConfig(): HttpConfig;

Defined in: packages/di/dist/index.d.mts:15

Returns ​

HttpConfig

Inherited from ​

Port("HttpConfig")<{ readonly port: number; readonly hostname: string; /** The largest request body a procedure reads, in bytes; `0` is unbounded. */ readonly bodyLimit: number; /** * The largest request body a route reads as a stream, in bytes; `0` is * unbounded. Counted while the body streams, never buffered. */ readonly streamBodyLimit: number; /** Comma-separated allowed origins, or `*`. Empty is "the deployment said nothing". */ readonly corsOrigin: string; readonly compression: boolean; /** * How long a client may take to send a request's headers, in ms; the listener * answers `408` past it. As configured: a value above `requestTimeoutMs` is held * to it by the listener, so the effective bound is the smaller of the two. */ readonly headersTimeoutMs: number; /** How long a client may take to send a whole request, headers and body, in ms; `408` past it. */ readonly requestTimeoutMs: number; }>.constructor

Properties ​

PropertyModifierTypeDescriptionInherited fromDefined in
[ID]readonly"HttpConfig"-Port("HttpConfig").[ID]packages/di/dist/index.d.mts:11
[SERVICE]readonlyobject-Port("HttpConfig").[SERVICE]packages/di/dist/index.d.mts:12
[SERVICE].bodyLimitreadonlynumberThe largest request body a procedure reads, in bytes; 0 is unbounded.-packages/http-server/src/http-config.ts:14
[SERVICE].compressionreadonlyboolean--packages/http-server/src/http-config.ts:22
[SERVICE].corsOriginreadonlystringComma-separated allowed origins, or *. Empty is "the deployment said nothing".-packages/http-server/src/http-config.ts:21
[SERVICE].headersTimeoutMsreadonlynumberHow long a client may take to send a request's headers, in ms; the listener answers 408 past it. As configured: a value above requestTimeoutMs is held to it by the listener, so the effective bound is the smaller of the two.-packages/http-server/src/http-config.ts:28
[SERVICE].hostnamereadonlystring--packages/http-server/src/http-config.ts:12
[SERVICE].portreadonlynumber--packages/http-server/src/http-config.ts:11
[SERVICE].requestTimeoutMsreadonlynumberHow long a client may take to send a whole request, headers and body, in ms; 408 past it.-packages/http-server/src/http-config.ts:30
[SERVICE].streamBodyLimitreadonlynumberThe largest request body a route reads as a stream, in bytes; 0 is unbounded. Counted while the body streams, never buffered.-packages/http-server/src/http-config.ts:19
portIdstatic readonly"HttpConfig"-Port("HttpConfig").portIdpackages/di/dist/index.d.mts:16

HttpHandler ​

Defined in: packages/http-server/src/handler.ts:56

The HTTP surface as a SET port: every protocol served in this process contributes one member, and the runtime routes each request to the one whose prefix matches longest.

A set port rather than the single function it used to be, because HTTP is one transport carrying several protocols — oRPC here, GraphQL and htmx fragments beside it — while a graph holds exactly one runtime. They cannot be three runtimes; they are three answerers under one.

The runtime reaches them through Runtime.resolves rather than through di, because a member contributed by a SIBLING module is not visible from inside this one: start gates that the composition root exports this port, and HttpModule adds it to exports so an application never lists it.

Extends ​

  • PortInstance<"HttpHandler", readonly HttpAnswerer[]> & object

Constructors ​

Constructor ​
ts
new HttpHandler(): HttpHandler;

Defined in: packages/di/dist/index.d.mts:29

Returns ​

HttpHandler

Inherited from ​

Port.many("HttpHandler")<HttpAnswerer>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
[ID]readonly"HttpHandler"Port.many("HttpHandler").[ID]packages/di/dist/index.d.mts:11
[MANY]readonlytruePort.many("HttpHandler").[MANY]packages/di/dist/index.d.mts:30
[SERVICE]readonlyreadonly HttpAnswerer[]Port.many("HttpHandler").[SERVICE]packages/di/dist/index.d.mts:12
manystatic readonlytrueHttpChallenges.manypackages/di/dist/index.d.mts:33
portIdstatic readonly"HttpHandler"Port.many("HttpHandler").portIdpackages/di/dist/index.d.mts:32

HttpRequestMetadata ​

Defined in: packages/http-server/src/request-metadata.ts:10

Non-authentication metadata pinned to one HTTP request unit. Headers are an immutable snapshot; the signal is the runtime's cancellation signal. Values are untrusted input: decoding and authorization remain application policy.

Extends ​

  • PortInstance<"HttpRequestMetadata", { headers: Readonly<Record<string, string | readonly string[] | undefined>>; method: string | undefined; signal: AbortSignal; url: string | undefined; }>

Constructors ​

Constructor ​
ts
new HttpRequestMetadata(): HttpRequestMetadata;

Defined in: packages/di/dist/index.d.mts:15

Returns ​

HttpRequestMetadata

Inherited from ​

Port("HttpRequestMetadata")<{ readonly headers: Readonly<Record<string, string | readonly string[] | undefined>>; readonly method: string | undefined; readonly url: string | undefined; readonly signal: AbortSignal; }>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
[ID]readonly"HttpRequestMetadata"Port("HttpRequestMetadata").[ID]packages/di/dist/index.d.mts:11
[SERVICE]readonlyobjectPort("HttpRequestMetadata").[SERVICE]packages/di/dist/index.d.mts:12
[SERVICE].headersreadonlyReadonly<Record<string, string | readonly string[] | undefined>>-packages/http-server/src/request-metadata.ts:11
[SERVICE].methodreadonlystring | undefined-packages/http-server/src/request-metadata.ts:12
[SERVICE].signalreadonlyAbortSignal-packages/http-server/src/request-metadata.ts:14
[SERVICE].urlreadonlystring | undefined-packages/http-server/src/request-metadata.ts:13
portIdstatic readonly"HttpRequestMetadata"Port("HttpRequestMetadata").portIdpackages/di/dist/index.d.mts:16

HttpRuntime ​

Defined in: packages/http-server/src/http-runtime.ts:138

The runtime's port: what the starter provides, and what HttpModule and GraphqlModule export for start to boot.

It resolves HttpHandler, which is why a root exporting it is now part of start's gate: the answerers are contributed by sibling modules — oRPC here, a fragment or GraphQL answerer beside it — so they are not visible from inside this module and have to be read out of the application context.

Extends ​

Constructors ​

Constructor ​
ts
new HttpRuntime(): HttpRuntime;

Defined in: packages/di/dist/index.d.mts:15

Returns ​

HttpRuntime

Inherited from ​

RuntimePort<Runtime<typeof HttpHandler, HttpInfo>>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
[ID]readonly"Runtime"RuntimePort.[ID]packages/di/dist/index.d.mts:11
[SERVICE]readonlyRuntimeRuntimePort.[SERVICE]packages/di/dist/index.d.mts:12
portIdstatic readonly"Runtime"RuntimePort.portIdpackages/di/dist/index.d.mts:16

ProtectedResource ​

Defined in: packages/http-server/src/protected-resource.ts:212

What protectedResource was configured with, once the boot has checked it.

Extends ​

  • PortInstance<"HttpProtectedResource", { authorizationServers: readonly string[]; metadata: string; resource: string; }>

Constructors ​

Constructor ​
ts
new ProtectedResource(): ProtectedResource;

Defined in: packages/di/dist/index.d.mts:15

Returns ​

ProtectedResource

Inherited from ​

Port("HttpProtectedResource")<{ /** The resource identifier: the `aud` its tokens are minted for (RFC 8707). */ readonly resource: string; readonly authorizationServers: readonly string[]; /** Where the metadata document is served, as a client is told to fetch it. */ readonly metadata: string; }>.constructor

Properties ​

PropertyModifierTypeDescriptionInherited fromDefined in
[ID]readonly"HttpProtectedResource"-Port("HttpProtectedResource").[ID]packages/di/dist/index.d.mts:11
[SERVICE]readonlyobject-Port("HttpProtectedResource").[SERVICE]packages/di/dist/index.d.mts:12
[SERVICE].authorizationServersreadonlyreadonly string[]--packages/http-server/src/protected-resource.ts:215
[SERVICE].metadatareadonlystringWhere the metadata document is served, as a client is told to fetch it.-packages/http-server/src/protected-resource.ts:217
[SERVICE].resourcereadonlystringThe resource identifier: the aud its tokens are minted for (RFC 8707).-packages/http-server/src/protected-resource.ts:214
portIdstatic readonly"HttpProtectedResource"-Port("HttpProtectedResource").portIdpackages/di/dist/index.d.mts:16

ProtectedResourcePerHost ​

Defined in: packages/http-server/src/protected-resource.ts:475

What protectedResourcePerHost was configured with, once the boot has checked it.

Extends ​

  • PortInstance<"HttpProtectedResourcePerHost", { authorizationServers: readonly string[]; path: string; }>

Constructors ​

Constructor ​
ts
new ProtectedResourcePerHost(): ProtectedResourcePerHost;

Defined in: packages/di/dist/index.d.mts:15

Returns ​

ProtectedResourcePerHost

Inherited from ​

Port("HttpProtectedResourcePerHost")<{ /** The resource's path on every served host, as the URL parser spells it. */ readonly path: string; readonly authorizationServers: readonly string[]; }>.constructor

Properties ​

PropertyModifierTypeDescriptionInherited fromDefined in
[ID]readonly"HttpProtectedResourcePerHost"-Port("HttpProtectedResourcePerHost").[ID]packages/di/dist/index.d.mts:11
[SERVICE]readonlyobject-Port("HttpProtectedResourcePerHost").[SERVICE]packages/di/dist/index.d.mts:12
[SERVICE].authorizationServersreadonlyreadonly string[]--packages/http-server/src/protected-resource.ts:478
[SERVICE].pathreadonlystringThe resource's path on every served host, as the URL parser spells it.-packages/http-server/src/protected-resource.ts:477
portIdstatic readonly"HttpProtectedResourcePerHost"-Port("HttpProtectedResourcePerHost").portIdpackages/di/dist/index.d.mts:16

ServedHosts ​

Defined in: packages/http-server/src/protected-resource.ts:470

Whether this deployment serves a host — usually a domain a tenant verified, kept in the application's own data. Asked with the host as the URL parser spells it: lowercase, punycode, the scheme's default port dropped and any other port kept (tenant-a.example, localhost:3000), and the request unit's signal, aborted once the unit settles — a client that left included — so a query can be cancelled.

Extends ​

  • PortInstance<"HttpServedHosts", (host, signal) => AsyncResult<boolean, never>>

Constructors ​

Constructor ​
ts
new ServedHosts(): ServedHosts;

Defined in: packages/di/dist/index.d.mts:15

Returns ​

ServedHosts

Inherited from ​

Port("HttpServedHosts")<(host: string, signal: AbortSignal) => AsyncResult<boolean, never>>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
[ID]readonly"HttpServedHosts"Port("HttpServedHosts").[ID]packages/di/dist/index.d.mts:11
[SERVICE]readonly(host, signal) => AsyncResult<boolean, never>Port("HttpServedHosts").[SERVICE]packages/di/dist/index.d.mts:12
portIdstatic readonly"HttpServedHosts"Port("HttpServedHosts").portIdpackages/di/dist/index.d.mts:16

Unauthenticated ​

Defined in: packages/http-server/src/auth.ts:19

A caller was refused. Carries nothing: the starter surfaces no reason — a rejected caller gets an UNAUTHORIZED and oRPC's default message — so a payload here would be write-only.

An authenticator that wants to record why reports it to Observers before returning this — jwtAuthenticator is the worked case, and note WHAT it records: a refusal its DEPENDENCY caused, never one the caller's credential caused. A line per refused credential is how a scanner writes an application's logs for it.

Extends ​

  • TaggedErrorInstance<"Unauthenticated", { }>

Constructors ​

Constructor ​
ts
new Unauthenticated(args): Unauthenticated;

Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386

Parameters ​
ParameterType
argsvoid
Returns ​

Unauthenticated

Inherited from ​

TaggedError("Unauthenticated").constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
_tagreadonly"Unauthenticated"TaggedError("Unauthenticated")._tagnode_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363
cause?publicunknownTaggedError("Unauthenticated").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstringTaggedError("Unauthenticated").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("Unauthenticated").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstringTaggedError("Unauthenticated").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

UnderScoped ​

Defined in: packages/http-server/src/auth.ts:39

A credential was valid but lacks one or more scopes the endpoint declared, or a scheme refused a credential the caller presented (CredentialRefused). Distinct from Unauthenticated because the answers differ: an anonymous caller gets 401, a refused one 403.

Extends ​

  • TaggedErrorInstance<"UnderScoped", { }>

Constructors ​

Constructor ​
ts
new UnderScoped(scopes?): UnderScoped;

Defined in: packages/http-server/src/auth.ts:43

Parameters ​
ParameterType
scopes?readonly string[]
Returns ​

UnderScoped

Overrides ​

TaggedError("UnderScoped").constructor

Properties ​

PropertyModifierTypeDescriptionInherited fromDefined in
_tagreadonly"UnderScoped"-TaggedError("UnderScoped")._tagnode_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363
cause?publicunknown-TaggedError("UnderScoped").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstring-TaggedError("UnderScoped").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstring-TaggedError("UnderScoped").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
scopesreadonlyreadonly string[] | undefinedOne sufficient Bearer alternative, in declaration order; absent for other credentials.-packages/http-server/src/auth.ts:41
stack?publicstring-TaggedError("UnderScoped").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Type Aliases ​

ApiKey ​

ts
type ApiKey<P> = object;

Defined in: packages/http-server/src/api-key.ts:16

One issued key, and what presenting it makes the caller.

scopes is the only place a scope is written: the scheme's vocabulary is the union of what its keys grant, inferred rather than declared a second time as a type argument. A vocabulary stated separately could name a scope no key grants, which passes ScopeGate and then refuses every caller with a permanent 403 — the failure that gate exists to catch, one layer up.

Type Parameters ​

Type Parameter
P

Properties ​

PropertyModifierTypeDescriptionDefined in
keyreadonlystring-packages/http-server/src/api-key.ts:17
principalreadonlyP-packages/http-server/src/api-key.ts:18
scopes?readonlyreadonly string[]What this key grants, checked against the endpoint's declared scopes by the existing 403 path.packages/http-server/src/api-key.ts:20

ApiKeyOptions ​

ts
type ApiKeyOptions<P, Keys> = object;

Defined in: packages/http-server/src/api-key.ts:23

Type Parameters ​

Type Parameter
P
Keys extends readonly ApiKey<P>[]

Properties ​

PropertyModifierTypeDescriptionDefined in
header?readonlystringWhich header carries the key. Default x-api-key.packages/http-server/src/api-key.ts:25
keysreadonlyKeys-packages/http-server/src/api-key.ts:26

Authenticator ​

ts
type Authenticator<P, Scope, N, E> = object;

Defined in: packages/http-server/src/auth.ts:205

What HttpAuthenticator hands back: a description defineHttp binds to a port once the scheme name is known, carrying its principal and scope types so the registry can be inferred rather than declared.

Type Parameters ​

Type ParameterDefault type
P-
Scope extends string-
N-
Enever

Properties ​

PropertyModifierTypeDescriptionDefined in
cookie?readonlytrueSet by a scheme that resolves a caller from a cookie, which is what makes a deployment a CSRF target: defineHttp turns it into a CookieSchemes member, and the HTTP runtime's csrf default is "any member". Absent on a scheme reading a header, where ambient authority is not in play.packages/http-server/src/auth.ts:218
errorreadonlyE-packages/http-server/src/auth.ts:210
needsreadonlyN-packages/http-server/src/auth.ts:209
optionsreadonlyunknown-packages/http-server/src/auth.ts:206
principalreadonlyP-packages/http-server/src/auth.ts:207
scopereadonlyScope-packages/http-server/src/auth.ts:208

Authenticators ​

ts
type Authenticators = Readonly<Record<string, Authenticator<unknown, string, unknown, unknown>>>;

Defined in: packages/http-server/src/define-auth.ts:13

The authenticators an application declares, keyed by scheme name.


AuthenticatorService ​

ts
type AuthenticatorService<P, Scope> = ((headers, query) => AsyncResult<Granted<P, Scope>, 
  | Unauthenticated
  | CredentialRefused
  | AuthenticatorUnavailable>) & object;

Defined in: packages/http-server/src/auth.ts:116

Headers and the URL's query, not the request: an authenticator has no business reading a body, and the narrower arguments are what keep it testable without a socket. The query carries a credential a browser follows as a plain link — a capability URL's signed grant — where no header can.

Type Parameters ​

Type ParameterDefault type
P-
Scope extends stringnever

Type Declaration ​

NameTypeDescriptionDefined in
bearer?trueVerifies an RFC 6750 Bearer credential from Authorization.packages/http-server/src/auth.ts:124

Grant ​

ts
type Grant<P, Scope> = object;

Defined in: packages/http-server/src/auth.ts:62

The scoped answer, and the reason granted() is mandatory rather than advisory: the brand is what tells it from an identity that merely happens to carry a scopes field.

Type Parameters ​

Type Parameter
P
Scope extends string

Properties ​

PropertyModifierTypeDefined in
[GRANT]readonlytruepackages/http-server/src/auth.ts:65
identityreadonlyPpackages/http-server/src/auth.ts:63
scopesreadonlyreadonly Scope[]packages/http-server/src/auth.ts:64

Granted ​

ts
type Granted<P, Scope> = [Scope] extends [never] ? P : Grant<P, Scope>;

Defined in: packages/http-server/src/auth.ts:74

What an authenticator hands back. A scheme with no scope vocabulary returns the identity bare — byte-for-byte what applications write today — and one with a vocabulary reports what the credential actually granted, so the starter can compare it against what the endpoint declared.

Type Parameters ​

Type Parameter
P
Scope extends string

HttpAnswerer ​

ts
type HttpAnswerer = object;

Defined in: packages/http-server/src/handler.ts:25

One protocol's answer to HTTP, mounted under prefix.

Everything the client receives must be written from inside handle — the unit stays open until the response completes, so there is no way to be late. It returns PromiseLike<unknown> rather than void: the package needs to know when the handler is finished so it can answer a request the handler declined, and a void-returning handler writing asynchronously would draw a premature 404 over a response still in flight. unknown because oRPC's handle resolves { matched: boolean }; the value is never the unit's result, and the runtime reads "did you answer?" off the response rather than off this — which is what lets an answerer be written against node:http alone.

host is how an answerer opens the unit's scope for a request it handles — host.fork(module, seed), once, for a request this answerer is about to answer. The runtime's own 404 never forks: only an answerer that claims a request does.

Properties ​

PropertyModifierTypeDescriptionDefined in
handlereadonly(request, response, signal, host) => PromiseLike<unknown>-packages/http-server/src/handler.ts:33
prefixreadonly`/${string}`Where this answerer is mounted. It owns every path at or under it, and a request is routed to the LONGEST prefix that matches — so / may host a fragment answerer while /rpc hosts oRPC, and nesting is expected rather than refused. Two answerers on one prefix is a startup failure.packages/http-server/src/handler.ts:32

HttpAuth ​

ts
type HttpAuth<A> = object;

Defined in: packages/http-server/src/define-auth.ts:33

Shared authentication registry consumed by any HTTP answerer.

Type Parameters ​

Type Parameter
A extends Authenticators

Properties ​

PropertyModifierTypeDefined in
authenticatorsreadonlyApackages/http-server/src/define-auth.ts:34
principalsreadonlyPrincipals<A>packages/http-server/src/define-auth.ts:36
providersreadonlyreadonly SchemeProviders<A>[]packages/http-server/src/define-auth.ts:35

HttpChallenge ​

ts
type HttpChallenge = object;

Defined in: packages/http-server/src/protected-resource.ts:24

A WWW-Authenticate challenge, and the request whose refusals carry it: its scheme, host, path and query, as sent.

Properties ​

PropertyModifierTypeDescriptionDefined in
resourceMetadata?readonlystringMetadata URL for typed Bearer scope refusals, set by protectedResource().packages/http-server/src/protected-resource.ts:28
targetreadonlystring-packages/http-server/src/protected-resource.ts:25
valuereadonlystring-packages/http-server/src/protected-resource.ts:26

HttpInfo ​

ts
type HttpInfo = object;

Defined in: packages/http-server/src/http-runtime.ts:38

What the runtime publishes once it is listening, read back through RunningApp.runtimeInfo().

Properties ​

PropertyModifierTypeDefined in
portreadonlynumberpackages/http-server/src/http-runtime.ts:38

HttpOptions ​

ts
type HttpOptions = object;

Defined in: packages/http-server/src/http-runtime.ts:51

The HTTP transport's options: orpc()'s own — where the router is mounted, and the transport policy — plus what a caller pins on the socket instead of reading it from the environment. Declared as one intersection so each option is spelled ONCE across the surfaces that take it (orpc(), HttpModule, GraphqlModule), which is what the six-concerns claim drifted against when they were three parallel records.

The router itself is not an option — it is the provider the composition root supplies on the starter's router port, which this module needs.

Properties ​

PropertyModifierTypeDescriptionDefined in
bodyLimit?readonlynumber | false-packages/http-server/src/http-runtime.ts:53
compression?readonlyboolean | object-packages/http-server/src/http-runtime.ts:62
cors?readonlyboolean | object-packages/http-server/src/http-runtime.ts:52
csrf?readonlyboolean-packages/http-server/src/http-runtime.ts:63
headersTimeoutMs?readonlynumberPins HttpConfig.headersTimeoutMs instead of reading HTTP_HEADERS_TIMEOUT_MS (default DEFAULT_HEADERS_TIMEOUT_MS): how long a client may take to send a request's headers before the listener answers 408 and closes the socket — the slow-header attack's bound.packages/http-server/src/http-runtime.ts:74
hostname?readonlystringPins HttpConfig.hostname instead of reading HOST.packages/http-server/src/http-runtime.ts:67
port?readonlynumberPins HttpConfig.port instead of reading PORT.packages/http-server/src/http-runtime.ts:65
requestTimeoutMs?readonlynumberPins HttpConfig.requestTimeoutMs instead of reading HTTP_REQUEST_TIMEOUT_MS (default DEFAULT_REQUEST_TIMEOUT_MS): how long a client may take to send a WHOLE request, body included. It bounds what the client sends, never the response, so a long-lived event stream is not cut by it.packages/http-server/src/http-runtime.ts:82
securityHeaders?readonlyboolean | Readonly<Record<string, string>>Headers set on every response, before dispatch. true (default) applies DEFAULT_SECURITY_HEADERS; false disables the feature; a record replaces the defaults outright. Not a config field, deliberately: a deployment that can silently turn x-frame-options off is a footgun the other policies are not.packages/http-server/src/http-runtime.ts:91
streamBodyLimit?readonlynumber | falsePins HttpConfig.streamBodyLimit instead of reading HTTP_STREAM_BODY_LIMIT (default DEFAULT_STREAM_BODY_LIMIT): the largest body an oRPC route reads as a stream (requestBodyHint: "octet-stream"), in bytes, counted as it arrives; false pins the unbounded 0. Every other body stays under bodyLimit.packages/http-server/src/http-runtime.ts:61
unit?readonlyReadonly<Record<string, AnyUnitModule>>The unit module each KIND binds: anonymous for a request no leaf asked to authenticate, else the scheme that resolved the caller. The answerers fork the one that matches — seeded, for a scheme, with that scheme's principal — as the request is taken, and tear it down when the unit closes, after the response is flushed. A kind that binds no module of its own falls back to anonymous, so binding that one alone keeps forking on every leaf.packages/http-server/src/http-runtime.ts:100

HttpRequestChallenge ​

ts
type HttpRequestChallenge = object;

Defined in: packages/http-server/src/protected-resource.ts:38

A challenge whose target depends on the request: resolve answers it, or undefined for none, and is asked only for a request whose path, as sent, is path — settled before dispatch, so no other request waits on it. It is handed the unit's signal; a client that leaves first settles the unit without waiting for it, and nothing is dispatched.

Properties ​

PropertyModifierTypeDefined in
pathreadonlystringpackages/http-server/src/protected-resource.ts:39
resolvereadonly(request, signal) => AsyncResult<HttpChallenge | undefined, never>packages/http-server/src/protected-resource.ts:40

Kinds ​

ts
type Kinds<A> = "anonymous" | keyof A & string;

Defined in: packages/http-server/src/unit.ts:38

Every kind a unit may be opened under: no credential, or the scheme that resolved one.

Type Parameters ​

Type Parameter
A

Principal ​

ts
type Principal<S, Schemes> = [S] extends [never] ? never : [S] extends [keyof Schemes] ? IsUnion<S> extends true ? Tagged<S & keyof Schemes, Schemes> : Schemes[S & keyof Schemes] : never;

Defined in: packages/http-server/src/principal.ts:30

What a leaf's handler reads. Bare when its requirements name one scheme — byte-for-byte what applications write today, so the common case pays nothing for the feature — and a discriminated union when they name several.

Type Parameters ​

Type Parameter
S extends string
Schemes

Principals ​

ts
type Principals<A> = { readonly [K in keyof A & string]: PortClassOf<`HttpPrincipal:${K}`, A[K]["principal"]> };

Defined in: packages/http-server/src/define-auth.ts:28

Type Parameters ​

Type Parameter
A extends Authenticators

ProtectedResourceOptions ​

ts
type ProtectedResourceOptions = object;

Defined in: packages/http-server/src/protected-resource.ts:220

Properties ​

PropertyModifierTypeDescriptionDefined in
allowInsecure?readonlybooleanAccept an http: resource or authorization server that is NOT on a loopback host. Default false, and a ConfigInvalid at boot without it: a client follows these URLs with its credentials.packages/http-server/src/protected-resource.ts:235
authorizationServers?readonlyreadonly string[]Pins HTTP_RESOURCE_AUTHORIZATION_SERVERS: the issuers whose tokens it accepts.packages/http-server/src/protected-resource.ts:227
resource?readonlystringPins HTTP_RESOURCE_URI: this API's resource identifier, an https: URL — usually the audience its JWT scheme requires.packages/http-server/src/protected-resource.ts:225
scopes?readonlyreadonly string[]Advertised as scopes_supported. Omitted from the document when absent or empty.packages/http-server/src/protected-resource.ts:229

ProtectedResourcePerHostOptions ​

ts
type ProtectedResourcePerHostOptions = object;

Defined in: packages/http-server/src/protected-resource.ts:481

Properties ​

PropertyModifierTypeDescriptionDefined in
allowInsecure?readonlybooleanAccept an http: authorization server, or an http: request target, that is NOT on a loopback host. Default false: a client follows these URLs with its credentials.packages/http-server/src/protected-resource.ts:493
authorizationServers?readonlyreadonly string[]Pins HTTP_RESOURCE_AUTHORIZATION_SERVERS: the issuers whose tokens it accepts.packages/http-server/src/protected-resource.ts:485
path?readonlystringPins HTTP_RESOURCE_PATH: the resource's path on every served host, /mcp for one.packages/http-server/src/protected-resource.ts:483
scopes?readonlyreadonly string[]Advertised as scopes_supported. Omitted from the document when absent or empty.packages/http-server/src/protected-resource.ts:487

ProtectedResourcePerHostProvider ​

ts
type ProtectedResourcePerHostProvider<O> = Provider<ProtectedResourcePerHost, ConfigInvalid, EnvReading<
  | Unpinned<O, "path", "HTTP_RESOURCE_PATH">
  | Unpinned<O, "authorizationServers", "HTTP_RESOURCE_AUTHORIZATION_SERVERS">, 
  | MaybePinned<O, "path", "HTTP_RESOURCE_PATH">
  | MaybePinned<O, "authorizationServers", "HTTP_RESOURCE_AUTHORIZATION_SERVERS">>>;

Defined in: packages/http-server/src/protected-resource.ts:499

The provider of ProtectedResourcePerHost, its variables required unless pinned.

Type Parameters ​

Type Parameter
O

ProtectedResourceProvider ​

ts
type ProtectedResourceProvider<O> = Provider<ProtectedResource, ConfigInvalid, EnvReading<
  | Unpinned<O, "resource", "HTTP_RESOURCE_URI">
  | Unpinned<O, "authorizationServers", "HTTP_RESOURCE_AUTHORIZATION_SERVERS">, 
  | MaybePinned<O, "resource", "HTTP_RESOURCE_URI">
  | MaybePinned<O, "authorizationServers", "HTTP_RESOURCE_AUTHORIZATION_SERVERS">>>;

Defined in: packages/http-server/src/protected-resource.ts:366

The provider of ProtectedResource, its variables required unless pinned.

Type Parameters ​

Type Parameter
O

SchemesFrom ​

ts
type SchemesFrom<A> = { readonly [K in keyof A]: A[K]["principal"] };

Defined in: packages/http-server/src/define-auth.ts:17

Type Parameters ​

Type Parameter
A extends Authenticators

SchemesOf ​

ts
type SchemesOf<R> = { [I in keyof R]: keyof R[I] & string }[number];

Defined in: packages/http-server/src/principal.ts:7

Type Parameters ​

Type Parameter
R extends Requirements

UnitsOf ​

ts
type UnitsOf<A> = Partial<Readonly<Record<Kinds<A>, AnyUnitModule>>>;

Defined in: packages/http-server/src/unit.ts:46

The module bound per kind. Every member is optional, which makes this a weak type — so a kind the authenticators never declared is refused for having no property in common rather than passing an excess-property check that a type argument would not get.

Type Parameters ​

Type Parameter
A

Functions ​

apiKeyAuthenticator() ​

ts
function apiKeyAuthenticator<P>(): <Keys>(options) => Authenticator<P, ScopesOf<Keys>, never>;

Defined in: packages/http-server/src/api-key.ts:79

An API-key scheme, with the constant-time compare people get wrong.

Three things it does that a hand-written one usually does not:

  • It compares digests, not strings. === on a secret leaks its prefix through timing, and timingSafeEqual refuses two buffers of different lengths — which would leak the key's LENGTH instead. Hashing first makes every comparison 32 bytes wide whatever was presented.
  • It checks every configured key, without an early return. A loop that breaks on the first match takes longer for a key configured late, which is a slower oracle but an oracle.
  • A missing header takes the same path as a wrong key, so "no credential" and "bad credential" are not distinguishable by timing either. Both answer Unauthenticated, which the starter turns into 401; the endpoint's own scope check is what produces a 403.

<!-- doctest: prelude import { apiKeyAuthenticator } from "@btravstack/http-server"; type ServiceIdentity = { readonly appId: string }; declare const env: { readonly REPORTING_KEY: string }; -->

ts
export const serviceAuth = apiKeyAuthenticator<ServiceIdentity>()({
  keys: [{ key: env.REPORTING_KEY, principal: { appId: "reporting" }, scopes: ["reports:read"] }],
});

Keys come from the caller — an Env-bound config field, a secret store — because a key list in the image is a key list in the repository.

Type Parameters ​

Type Parameter
P

Returns ​

<Keys>(options) => Authenticator<P, ScopesOf<Keys>, never>


authenticatorPort() ​

ts
function authenticatorPort<S>(scheme): PortClassOf<`HttpAuthenticator:${S}`, AuthenticatorService<unknown, never>>;

Defined in: packages/http-server/src/auth.ts:153

One port per scheme, its id carrying the scheme name. The service type is erased to AuthenticatorService<unknown>, since di identifies a port by id; the principal and scope types ride the description HttpAuthenticator returns.

The id is a LITERAL type, so a contract naming a scheme the registry has no authenticator for leaves that scheme's port unmet — di's own diagnostic, naming the port, rather than a gate this package writes.

Exported for the consumer defineHttp does not cover: a test substituting ONE scheme's authenticator provides its own on this port instead of minting a second registry.

Type Parameters ​

Type Parameter
S extends string

Parameters ​

ParameterType
schemeS

Returns ​

PortClassOf<`HttpAuthenticator:${S}`, AuthenticatorService<unknown, never>>


defineAuth() ​

ts
function defineAuth<A>(options?): HttpAuth<A>;

Defined in: packages/http-server/src/define-auth.ts:39

Type Parameters ​

Type ParameterDefault type
A extends Readonly<Record<string, Authenticator<unknown, string, unknown, unknown>>>Record<never, never>

Parameters ​

ParameterType
options?{ authenticators: A; }
options.authenticatorsA

Returns ​

HttpAuth<A>


granted() ​

ts
function granted<P, Scope>(identity, scopes): Grant<P, Scope>;

Defined in: packages/http-server/src/auth.ts:87

What a scoped scheme answers with:

ts
OkAsync(granted({ userId }, ["orders:export"]));

Scope is not inferred from the vocabulary — an empty grant would collapse it to never and take the return type back to the bare arm — so the array is what states it, checked against the vocabulary by the assignment.

Type Parameters ​

Type ParameterDefault type
P-
Scope extends stringnever

Parameters ​

ParameterType
identityP
scopesreadonly Scope[]

Returns ​

Grant<P, Scope>


HttpAuthenticator() ​

ts
function HttpAuthenticator<P, Scope>(): <D, O>(options) => Authenticator<P, Scope, InstanceType<D[keyof D]>, ErrorOfArm<O>>;

Defined in: packages/http-server/src/auth.ts:284

The authenticator for one scheme, with its principal type — and the scopes it can grant — stated at the call:

ts
export const userAuth = HttpAuthenticator<Identity, "orders:export">()({
  inject: { verify: JwtVerifier },
  sync: ({ verify }) => (headers) => verify(headers.authorization),
});

// An authenticator that reads nothing but the headers declares no deps:
export const serviceAuth = HttpAuthenticator<ServiceIdentity>()({
  inject: {},
  sync: () => (headers) => apiKey(headers["x-api-key"]),
});

// `make` where building the scheme can FAIL, and the failure is startup's:
export const jwtAuth = HttpAuthenticator<Identity>()({
  inject: { env: Env },
  make: ({ env }) => Config.parse("HttpJwt", schema)(env).map(verifier),
});

sync and make are the same pair di's Provider has, and naming both is refused. make answers an AsyncResult, so its Err is the graph's — a scheme whose configuration is wrong fails the boot, still typed, rather than refusing every caller at runtime.

The type arguments are explicit rather than inferred from the arm: inference through a returned function's AsyncResult is where a principal silently widens to unknown. The scheme NAME is not stated here — it is the key this authenticator sits under in defineHttp({ authenticators }).

Type Parameters ​

Type ParameterDefault type
P-
Scope extends stringnever

Returns ​

<D, O>(options) => Authenticator<P, Scope, InstanceType<D[keyof D]>, ErrorOfArm<O>>


principalPort() ​

ts
function principalPort<S, P>(scheme): PortClassOf<`HttpPrincipal:${S}`, P>;

Defined in: packages/http-server/src/auth.ts:170

One port per scheme carrying that scheme's PRINCIPAL, so a unit module the kind binds may name it in needs and inject the caller it was opened for. Minted from the scheme name alone — the seed lands on it per unit.

Memoised on the same map as authenticatorPort, and for the same reason: defineHttp mints, a unit module depends, and a second Port(id) call would cost di's duplicate-id warning for what is the designed pattern.

Type Parameters ​

Type ParameterDefault type
S extends string-
Punknown

Parameters ​

ParameterType
schemeS

Returns ​

PortClassOf<`HttpPrincipal:${S}`, P>


protectedResource() ​

ts
function protectedResource<O>(given?): readonly [ProtectedResourceProvider<O>, AnyProvider, AnyProvider];

Defined in: packages/http-server/src/protected-resource.ts:404

This API as an OAuth 2.0 protected resource: it serves its Protected Resource Metadata (RFC 9728) and tells a refused caller where to find it, so a client that holds no token — an MCP client is the usual one — discovers which authorization server to sign in with.

ts
export const Api = HttpModule("Api")({
  router,
  provides: [...protectedResource({ scopes: ["orders:read"] })],
});
  • GET /.well-known/oauth-protected-resource<path> answers the document: resource, authorization_servers and, when given, scopes_supported. <path> is the resource identifier's own, so a resource at https://api.test/mcp is described at /.well-known/oauth-protected-resource/mcp.
  • A 401 for the resource's own URL carries WWW-Authenticate: Bearer resource_metadata="<that URL>", whichever answerer refused — oRPC, GraphQL or fragments — without any of them knowing. Any other URL, a path below it or another query included, is another resource, whose metadata this is not (RFC 9728 §3.3).

It answers THREE providers, which is why it is spread: the configuration, the answerer and the HttpChallenges member.

Type Parameters ​

Type ParameterDefault type
O extends ProtectedResourceOptionsRecord<never, never>

Parameters ​

ParameterType
given?O & OptionsAs<O, ProtectedResourceOptions>

Returns ​

readonly [ProtectedResourceProvider<O>, AnyProvider, AnyProvider]


protectedResourcePerHost() ​

ts
function protectedResourcePerHost<O>(given?): readonly [ProtectedResourcePerHostProvider<O>, Provider<HttpHandler, never, 
  | ProtectedResourcePerHost
  | ServedHosts>, Provider<HttpChallenges, never, 
  | ProtectedResourcePerHost
  | ServedHosts>];

Defined in: packages/http-server/src/protected-resource.ts:556

This API as an OAuth 2.0 protected resource on every host the application serves — one resource per tenant domain, say — rather than on one configured URL: protectedResource's discovery, with the resource identifier <scheme>//<request host><path> derived per request.

ts
export const Api = HttpModule("Api")({
  router,
  provides: [...protectedResourcePerHost({ path: "/mcp" }), servedHosts],
});

The host is admitted only when ServedHosts answers true: an unserved host gets a 404 for the metadata document and no challenge, so a forged Host never mints discovery for a domain the application did not vouch for. It is asked at most once per request to the resource or its metadata, and only for those. Every matching rule of protectedResource's holds per host.

It answers THREE providers, which is why it is spread: the configuration, the answerer and the HttpChallenges member.

Type Parameters ​

Type ParameterDefault type
O extends ProtectedResourcePerHostOptionsRecord<never, never>

Parameters ​

ParameterType
given?O & OptionsAs<O, ProtectedResourcePerHostOptions>

Returns ​

readonly [ProtectedResourcePerHostProvider<O>, Provider<HttpHandler, never, | ProtectedResourcePerHost | ServedHosts>, Provider<HttpChallenges, never, | ProtectedResourcePerHost | ServedHosts>]


resolvePrincipal() ​

ts
function resolvePrincipal(
   requirements, 
   authenticators, 
   headers, 
   query?
): AsyncResult<unknown, 
  | AuthenticatorUnavailable
  | UnderScoped
  | Unauthenticated>;

Defined in: packages/http-server/src/auth.ts:349

resolveScheme folded to what a handler is injected.

Parameters ​

ParameterType
requirementsRequirements
authenticatorsReadonly<Record<string, AuthenticatorService<unknown>>>
headersIncomingHttpHeaders
query?URLSearchParams

Returns ​

AsyncResult<unknown, | AuthenticatorUnavailable | UnderScoped | Unauthenticated>

Released under the MIT License.