honest framework

honest-auth

Identity is validated once, at the boundary, then passed inward as data. No link trusts an actor it read from the request.

You know guards and the Auth facade. honest-auth validates once at the boundary and threads the actor inward — no code deep in the call trusts the request.

A handler needs to know who is calling. So it reads request.user_id from the query string. Another handler trusts a header. A third decodes the token itself, inline, and forgets to check the expiry. Now "who is the actor" has three answers depending on which handler you land in, and at least one of them believes whatever the request claims. The privilege check three functions deep is reading a value an attacker set.

honest-auth validates identity once, at the boundary, and passes it inward as data. The boundary authenticates the request and produces an actor, a plain value. Every function below the boundary receives the actor as an argument. A link never re-derives identity from request input, and honest-check enforces it: HC-A001 and HC-A002 flag any deeper function that trusts an actor field it read from the request instead of the one handed to it.

A contract, a registry, and one dispatch

honest-auth is an interface, not a password store. It defines the AuthProvider contract: a recognizer that says whether a request carries a credential this provider handles, and a resolver that turns that credential into an actor. Providers are declared as data in a registry; the boundary dispatch picks the matching one and calls it. Adopters plug in a provider; the dispatch itself is plumbing.

The decision is pure. The provider's recognizer and resolver are the injected I/O, the one place that touches a session store or verifies a signature. Everything the application sees is the resulting actor, already validated, passed as a value.

Why boundary validation is a poka-yoke

"Trust the request's claim about who you are" is the root of a whole family of authorization bugs, and it is a category, not a slip: any function that can read request.user_id can be fooled by it. Validate identity at exactly one place and forbid re-reading it below, and the category closes. A deep function cannot trust a forged actor, because it has no access to the request to read one from; it has only the actor it was handed, which the boundary already checked.

The framework's FOSS line stops at boundary validation with the actor passed inward. Stricter guarantees — verifying the actor again at every write — are a commercial concern, not part of the standard.