Documentation
¶
Overview ¶
Package identity answers one question: who owns this request?
SEAM 2 of 4. The engine deliberately does not own authentication. It defines the question and consumes the answer; how the answer is produced is injected.
The reason is the open-core boundary. The engine now hosts several teams and ships a session-backed provider of its own, so it is no longer true that authentication lives entirely outside it. What is still true is the part that matters: a wrapping application resolves an owner from a signed token, an org membership, or its own sessions, and must be able to do so without fighting the engine — usually by forking, which defeats the point of a module.
The seam survives because account.Sessions is an implementation of Provider rather than a replacement for it. The engine's own sign-in goes through the same interface a wrapping application swaps out, which is why adding teams, people and sessions changed no handler, no store query and no orchestrator call.
Everything downstream — handlers, storage, the orchestrator — takes an OwnerID and never asks where it came from.
Index ¶
Constants ¶
const DefaultOwnerID = "owner-local"
DefaultOwnerID is the owner every resource belongs to in a single-owner deployment.
It is a fixed value rather than a generated one so that the schema's owner_id column is populated identically across restarts and reinstalls, and so a later migration to multi-owner has one known value to rewrite.
Variables ¶
var ErrUnauthenticated = errors.New("identity: unauthenticated")
ErrUnauthenticated means no owner could be resolved for a request.
Functions ¶
func Middleware ¶
Middleware resolves the owner once per request and puts it in the context.
Doing this in one place, rather than in each handler, is deliberate. A check every handler has to remember is a check some handler will eventually forget, and the forgotten one is the security bug. Mount this on the router group and handlers cannot opt out by accident.
Types ¶
type Owner ¶
Owner is the principal a request acts as.
The engine treats ID as opaque and never parses it. A wrapping application is free to make it a tenant UUID, an org slug, or anything else stable.
func FromContext ¶
FromContext returns the owner carried by ctx, if any.
func MustFromContext ¶
MustFromContext returns the owner, panicking if absent.
Intended for handlers mounted behind Middleware, where a missing owner is a wiring bug rather than a runtime condition. Panicking makes that bug loud in development instead of silently serving another owner's data — which is the failure this whole seam exists to prevent.
type Provider ¶
Provider resolves the owner for an inbound request.
Implementations must not write to the response; the middleware owns the failure path so that every rejection looks the same regardless of provider.
type ProviderFunc ¶
ProviderFunc adapts a function to Provider.
type SingleOwner ¶
type SingleOwner struct {
// contains filtered or unexported fields
}
SingleOwner resolves every request to the same owner without authenticating it.
This is the right default for the engine's primary use case — one person running it on their own machine or a private network — and the wrong choice for anything reachable from the internet. Pair it with StaticToken, a reverse proxy that authenticates, or a provider of your own for exposed deployments.
func NewSingleOwner ¶
func NewSingleOwner(owner Owner) *SingleOwner
NewSingleOwner returns a provider that always resolves to owner. A zero-value owner falls back to a sensible local default.
type StaticToken ¶
type StaticToken struct {
// contains filtered or unexported fields
}
StaticToken authenticates a single owner with a shared bearer token.
Modest by design: it exists so a self-hoster can expose the engine without running it wide open, and so the Provider interface ships with more than one implementation — an interface with a single implementation tends not to stay a real seam.
func NewStaticToken ¶
func NewStaticToken(owner Owner, token string) (*StaticToken, error)
NewStaticToken returns a provider that accepts exactly one bearer token. It returns an error rather than silently allowing everything if token is empty.