fix: enforce API request limits
Add a single platform-owned request-body policy (hono/body-limit) with small, named limits for Better Auth and Core's grant-mutation endpoint, and a new required maxBodyBytes field on the executable module route contract so every module route makes a conscious no-body-or-bounded-body choice, capped at a platform ceiling. Every oversized request gets one sanitized 413 contract and never reaches business logic, authorization, or a handler. Also configure finite Node header/request/keep-alive timeouts, including the non-obvious connectionsCheckingInterval needed for them to take effect promptly, so a slow-header or slow-body connection cannot hold a socket indefinitely. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
cafd513019
commit
d3c6bd73d3
@@ -8,7 +8,10 @@ surfaces.
|
||||
|
||||
Phase 3 is complete, and Phase 4A (Core identity foundation), Phase 4B (identity HTTP transport),
|
||||
Phase 4C (Core authorization), Phase 5A (module authorization integration), Phase 5B (module HTTP
|
||||
transport), and Phase 5C (module database access) have landed. The repository includes
|
||||
transport), and Phase 5C (module database access) have landed. Phase 5D (public request perimeter
|
||||
hardening against an independent security audit) is in progress; pass 1 of 5 has landed — see
|
||||
below. **Phase 5D is not complete, and Phase 6 (Surface work) remains blocked until every audit
|
||||
finding is resolved and a final re-audit passes.** The repository includes
|
||||
public module contracts, independently versioned capabilities, static module manifests,
|
||||
deterministic automatic discovery, compiled server loading, a staged capability registry,
|
||||
dependency-ordered lifecycle with rollback, module-owned Drizzle table contracts, deterministic
|
||||
@@ -32,9 +35,10 @@ in `@ekklesia/contracts`, and an explicit Better Auth construction boundary in C
|
||||
Phase 4B adds identity HTTP transport: a minimal Hono-based `apps/api` composition root
|
||||
(`pnpm api:start`) mounts Better Auth at `/api/auth/*` and exposes `GET /api/v1/principal` behind
|
||||
Core's own Fetch-compatible identity runtime — Core still does not depend on Hono, and modules
|
||||
still cannot reach any of this. Public email/password registration is intentional; every account
|
||||
receives identical lowest-privilege baseline status and signup order never grants elevation. See
|
||||
[API](docs/development/api.md) and
|
||||
still cannot reach any of this. Public email/password registration is the intended eventual
|
||||
product policy — every account receives identical lowest-privilege baseline status and signup
|
||||
order never grants elevation — but is now **disabled by default** and requires an explicit opt-in
|
||||
(Phase 5D pass 1, below). See [API](docs/development/api.md) and
|
||||
[ADR 0011](docs/architecture/decisions/0011-identity-http-transport-and-public-enrollment.md).
|
||||
**No email verification, password recovery, or Dashboard exists yet** — that, along with
|
||||
production approval-provider composition, jobs, physical storage provisioning, surfaces, and
|
||||
@@ -91,6 +95,24 @@ startup. See [API](docs/development/api.md#module-database-access),
|
||||
[Module development](docs/module-development/README.md#database-access), and
|
||||
[ADR 0016](docs/architecture/decisions/0016-module-database-access.md).
|
||||
|
||||
Phase 5D pass 1 of 5 hardens the public request perimeter against an independent security audit
|
||||
of the Phase 5C checkpoint, without adding a Surface, a product module, or any new capability.
|
||||
Better Auth's authentication rate limiter now resolves client identity from a server-owned
|
||||
client-address boundary (`core/src/identity/client-address.ts`, wired in at the Node/API transport
|
||||
boundary) — direct mode trusts only the real socket peer by default, and an explicit trusted-proxy
|
||||
mode is required before any forwarded header is ever consulted, closing a rotating-header
|
||||
rate-limit bypass. Public sign-up is now **disabled by default** and requires an explicit typed
|
||||
opt-in (`EKKLESIA_PUBLIC_SIGNUP_ENABLED=true`). Every public body-consuming route — Better Auth,
|
||||
Core's grant-mutation endpoint, and every module route (via a new, required `maxBodyBytes` field on
|
||||
the executable route contract) — now has an explicit, platform-enforced byte ceiling with one
|
||||
sanitized `413` contract. The Node HTTP server now has finite header/request timeouts. See
|
||||
[API](docs/development/api.md), [Module development](docs/module-development/README.md#http-routes),
|
||||
and [ADR 0017](docs/architecture/decisions/0017-public-request-perimeter-hardening.md). **This pass
|
||||
does not add distributed rate limiting, durable public-signup abuse control, or any deployment/TLS
|
||||
guarantee, and it does not complete Phase 5D** — passes 2–5 (identity/database transport hardening,
|
||||
authorization integrity, module/runtime/migration correctness, and deployment/supply-chain closure
|
||||
plus a final independent re-audit) remain outstanding before Phase 6 (Surface work) may begin.
|
||||
|
||||
## Quick start
|
||||
|
||||
Prerequisites: Node.js 24 LTS, pnpm 11.12, and Docker with Compose.
|
||||
|
||||
Reference in New Issue
Block a user