Roadmap
Ingenium is alpha (v0.0.1). The API is mostly settled but still subject to change before 0.1.0. This page tracks what's shipped, what's known-broken, and what's planned. Authoritative changelog lives in the source repo.
⚠️ Production caveats — read first
Not production-ready for multi-instance deploys. The default in-memory stores for sessions, idempotency, and rate-limit don't share state across pods. Use the Redis-backed adapters in ingenium-redis before deploying behind a load balancer.
Alpha API surface. Verb registration, ctx shape, and middleware composition are stable enough to use; everything tagged @internal may change before 0.1.0.
Version targets
| Milestone | Goal | Status |
|---|---|---|
| v0.0.x | Feature-complete framework surface; alpha API. | current |
| v0.1.0 | All Redis stores shipped; plugin scoping; ExtractParams runtime narrowing; benchmark matrix on CI. | in progress |
| v1.0.0 | API frozen. SemVer stability commitment. Production deployments officially supported. | planned |
Shipped in v0.0.1
Core surface:
ingenium()app factory with lazy-composed middleware pipeline andapp.compose()pre-warm.Router()with prefix mounting, nested routers, and deterministic precedence (static > param > wildcard).- IngeniumContext with params, query, headers,
state, status/header setters, and terminal writers (json/text/html/send/redirect/stream). - Lazy body parsers -
json(with optional Zod-like schema +maxBytes),text,urlencoded,buffer,stream. - Native multipart / file upload (
ctx.body.multipart()). ctx.query.parse(schema)symmetric withctx.body.json(schema)— shallow-array-aware coercion for repeated keys.- Handler return-value reflection (object → JSON, string → text/html,
Buffer→ octet-stream,Readable→ stream,undefined→ 204). - Type-level
ExtractParams<Path>narrowing on verb handlers —app.get('/users/:id', ctx => ctx.params.id)types asstring. - Error class hierarchy (
IngeniumErrorand friends) with default JSON error boundary;app.onErroroverride + re-throw delegation. - Express compatibility shim (
expressCompat) - real-streamreq/resshims so(req, res, next)middleware is a genuine drop-in:cors,helmet,body-parser,multer,compression,express-session,morgan,express-rate-limitall work end-to-end. - Plugin system -
app.register(plugin, opts?)with lifecycle hooks (onRoute,onCompose,onRequest,onResponse,onError) and per-request decorators. - Standard Schema v1 integration -
ctx.body.json(schema)andctx.query.parse(schema)accept any validator exposing['~standard'](TypeBox, Valibot, ArkType) alongside the existing Zod-stylesafeParseand duck-typed{ parse }shapes.
Transports:
- Node HTTP adapter with
app.listen(port, host?)returning{ port, close }. - HTTP/2 and HTTP/2 cleartext (h2c) transports.
- WebSocket and SSE transports sharing the same dispatch entry.
- Bun adapter (
ingenium-bun) forBun.serve()with a Web-Streams ↔node:streambridge.
Production primitives:
- Static file middleware - ETag,
If-None-Match, range requests, MIME detection, HEAD support,index/extensions/dotfiles/maxAgeoptions. - Rate limiting - sliding-window middleware with pluggable store (in-memory ships in core; Redis adapter in
ingenium-redis). - Sessions - cookie + server-side stores.
- CSRF protection - native
ingenium.csrf(opts)middleware, double-submit cookie or session-synchronizer pattern, HMAC-SHA-256 signed, timing-safe verification. - CORS - origin allowlist, preflight caching, credentials handling.
- Trust proxy -
X-Forwarded-*andForwardedparsing with explicit-hop counting. - Body parsing - schema-validated JSON with hard
maxRequestBytescap enforced at the transport layer (default 2 MiB). - Per-request timeout (
requestTimeoutMs) withIngeniumTimeoutError(503) and late-write protection via per-context_epochcounter. - Graceful shutdown - drain in-flight requests, refuse new ones.
Auth + integrations:
- JWT middleware - HS256/384/512, RS256/384/512, PS256/384/512, ES256/384/512, plus JWKS support with in-flight request coalescing.
'none'rejected unconditionally. - API-key middleware.
- Idempotency-Key middleware - skip-caching 5xx by default via
IdempotencyOptions.cacheable. - OpenAPI generation, RFC 7807
application/problem+jsonerrors, content negotiation, reverse-proxy helpers, cron + background jobs primitives.
Hardening:
- Header injection guard -
\r/\nin header names or values throwsIngeniumHeaderInjectionError(500, codeHEADER_INJECTION). ctx.json()safety - circular refs,BigInt, and unserializable values throwIngeniumUnserializableError(500, codeUNSERIALIZABLE_RESPONSE) instead of bubbling a genericJSON.stringifyTypeError.safeJsonStringifyhelper exported for lenient mode.
Tooling:
- CLI scaffolder -
ingenium new <name> [--bun|--minimal]. - ADR docs covering load-bearing decisions (radix-trie router, lazy composition with dirty bit, return-value reflection, context pool, compat shim scope).
QOL pass (merged, awaiting next tagged release):
app.inject({ method, url, headers, body })— in-process test client returning{ status, headers, body, json<T>() }. Bypasses the socket entirely; ~10× faster integration tests.app.route(path).get(h).put(h).delete(h).all(h)— chainable per-path verb builder. Pure registration sugar; works on bothIngeniumAppandRouter.ctx.cookies— first-class cookie API with signed-cookie support (cookieSecretson app options, HMAC-SHA-256, key rotation,timingSafeEqualverify).- Inline OpenAPI route options —
app.get('/path', { tags, summary, response, requestBody, deprecated, ... }, handler). Built-in keys are peeled off at registration and merged into the route descriptor. ctx.body.json()parse cache — multiple consumers (audit middleware then handler) can read the body without "already consumed" errors. Buffer-level cache, so different schemas across calls all validate cleanly.- Plugin scoping —
app.scope('/api/v2', s => s.use(authPlugin))so plugins only decorate their subtree. - Dev-mode footgun warnings — double-write detection, trust-proxy misuse hints, double-
listen()errors, fetch-Responsereturn-value warning. All gated byNODE_ENV !== 'production'; zero hot-path cost.
Known issues — bugs
ExtractParamsdoesn't narrow constrained params -:id(\\d+)strips the constraint and staysstring. Unconstrained params (:id) do narrow correctly. The router doesn't yet honor inline constraints at runtime; types and runtime have to land together.
Known issues — gaps
- Inline OpenAPI
response/requestBodyaccepts raw OpenAPI Schema only - Standard Schema / Zod validators throw at registration with a clear message; convert validators to JSON Schema or use precomputed schemas. Validator→JSON-Schema bridging tracked for 0.1.0. - Scoped decorators are still global -
app.scope(path, ...)scopes middleware and plugins, butscope.decorate(...)installs onto the shared context. A dev-mode warning explains the limitation; path-aware resolution tracked for 0.1.0.
Open questions
- Lazy compose dirty-bit cost under heavy mutation. Apps that register routes per-request will recompose on every request. Cap it, warn after N recomposes per minute, or expose a
freeze()toggle for production? - Compat shim long-tail strategy. Aim for "covers the top 20 middleware on npm" with documented gaps, or stay minimal and route everyone to native ports?
- Scoped decorators. Today
app.scope(...)scopes middleware but decorators remain global (a lazy decorator installs onto the context, not per-path). Worth path-checking inside the decorator factory, or document as intentional and let userland gate?
Non-goals
These come up often enough to call out explicitly:
- A full Express drop-in. The compat shim is for the long tail of
(req, res, next)middleware; it is not a goal to make Express apps work unmodified. The migration guide is the supported path. - A monorepo bundler / framework wrapper. Ingenium is the HTTP framework. Adding view templating, ORM, or a CLI for app structure is out of scope.
- Multi-runtime fetch-style
Responseinterop. Handlers return plain values or call ctx writers. We will not addreturn new Response(...)translation; the dev warning makes the mistake loud and the fix is one line. - A community plugin marketplace. Plugins are npm packages; discovery happens via npm and the docs index.
Where to next?
- Production hardening - what's shippable today.
- Express compatibility shim - the long-tail status.
- Schema validation - current validator support.
- Introduction - back to the top.