Documentation
¶
Overview ¶
Package dilion assembles the Dilion server: an embeddable, Supabase Auth compatible authentication engine with a built-in privacy/compliance plane.
Everything replaceable is injected through functional options (project.md §2.4). With no options beyond a database, every component falls back to a working default:
srv, err := dilion.NewServer(dilion.WithDSN(os.Getenv("DILION_DSN")))
if err != nil { ... }
if err := srv.Migrate(ctx); err != nil { ... }
log.Fatal(srv.Start(ctx))
API surfaces mounted by Handler:
/auth/v1/* Supabase Auth compatible (chi, hand-written JSON contract) /privacy/v1/* compliance API (huma, OpenAPI 3.1 generated) /iam/v1/* management-plane RBAC API (huma) /healthz liveness; /readyz database readiness
Multiple database instances ¶
A Dilion "instance" is a whole isolated database (auth.* + dilion_*). The built-in daemon runs exactly one. Embedders that need several inject a ports.InstanceResolver and select the instance per request themselves — Dilion ships no routing rule. Tokens are bound to their instance by key material: the resolver hands every instance its own JWT keys, so a token of one instance is rejected by every other (and by any PostgREST or resource server that trusts the other's JWKS):
srv, _ := dilion.NewServer(dilion.WithInstanceResolver(myResolver))
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := myTenantLookup(r) // subdomain, header, session, ...
r = r.WithContext(ports.ContextWithInstance(r.Context(), id))
srv.Handler().ServeHTTP(w, r)
})
Migrate then migrates every instance the resolver lists, and Start runs the compliance workers per instance.
Index ¶
- Constants
- type HookPoint
- type Option
- func WithAddr(addr string) Option
- func WithAuditSink(s ports.AuditSink) Option
- func WithAuthConfig(c *auth.Config) Option
- func WithAuthorizer(a ports.Authorizer) Option
- func WithClock(cl ports.Clock) Option
- func WithConnector(name string, conn ports.Connector) Option
- func WithDSN(dsn string) Option
- func WithHook(p ports.HookPoint, fn ports.HookFunc) Option
- func WithInstanceResolver(r ports.InstanceResolver) Option
- func WithJWTSecret(secret []byte) Option
- func WithKMS(k ports.KMS) Option
- func WithLogger(l *slog.Logger) Option
- func WithMailer(m ports.Mailer) Option
- func WithMasterKey(key []byte) Option
- func WithPIIFieldsYAML(b []byte) Option
- func WithPolicyYAML(b []byte) Option
- func WithPool(p *pgxpool.Pool) Option
- func WithSMS(s ports.SMSSender) Option
- func WithoutAdminMFA() Option
- type Server
- func (s *Server) Close() error
- func (s *Server) Handler() http.Handler
- func (s *Server) Migrate(ctx context.Context) error
- func (s *Server) Pool() *pgxpool.Pool
- func (s *Server) PoolFor(ctx context.Context) (*pgxpool.Pool, error)
- func (s *Server) Start(ctx context.Context) error
- func (s *Server) WithOpaqueSessionKey(ctx context.Context, bearer, keyID string, fn func([]byte) error) error
Constants ¶
const ( BeforeSignup = ports.BeforeSignup AfterSignup = ports.AfterSignup TokenClaims = ports.TokenClaims BeforeUserDelete = ports.BeforeUserDelete AfterUserDelete = ports.AfterUserDelete BeforeErasureStep = ports.BeforeErasureStep AfterErasure = ports.AfterErasure ConsentChanged = ports.ConsentChanged ConsentReconfirm = ports.ConsentReconfirm PIIReveal = ports.PIIReveal )
const DefaultAddr = ":8787"
DefaultAddr is the listen address used when WithAddr is not given.
const Version = "0.1.0"
Version is reported in the generated OpenAPI document.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option func(*config)
Option customises the server. Options are applied in order.
func WithAuditSink ¶
WithAuditSink replaces the Postgres audit sink.
func WithAuthConfig ¶
WithAuthConfig pins the /auth/v1 configuration (internal/auth.Config). Without it the configuration is read from the environment with auth.LoadConfig — DILION_AUTH_* first, the upstream GOTRUE_* names as a fallback — and an invalid value fails NewServer.
func WithAuthorizer ¶
func WithAuthorizer(a ports.Authorizer) Option
WithAuthorizer replaces the built-in management-plane RBAC decision point.
func WithConnector ¶
WithConnector registers an external-system connector under name; privacy destinations of type CONNECTOR reference it by that name (§3.1).
func WithDSN ¶
WithDSN connects a pool from a Postgres connection string. Ignored when WithPool is also given.
func WithInstanceResolver ¶
func WithInstanceResolver(r ports.InstanceResolver) Option
WithInstanceResolver turns the server multi-instance: every request resolves its database, KMS, JWT keys, policy and PII field definitions from r, keyed by the instance id the embedder puts on the context with ports.ContextWithInstance (typically in its own middleware). Dilion provides no HTTP routing — choosing the instance for a request is the embedder's responsibility — but it does bind tokens to instances: each instance signs and verifies with the keys r returns for it, so those keys must differ per instance (a shared key is logged as a warning).
Without this option the server is single-instance: WithPool/WithDSN, WithKMS, the JWT settings of the auth configuration, WithPolicyYAML and WithPIIFieldsYAML are wrapped in a static resolver under ports.DefaultInstanceID and nothing else changes.
A resolver must return stable results per instance id: constructed per-instance objects are cached for the lifetime of the server.
func WithJWTSecret ¶
WithJWTSecret sets the HS256 signing secret for the compat auth surface. Without it an ephemeral secret is generated and all tokens die on restart.
func WithLogger ¶
WithLogger sets the base slog logger (default slog.Default()).
func WithMailer ¶
WithMailer replaces the dev logging mailer.
func WithMasterKey ¶
WithMasterKey sets the 32-byte KEK for the default local KMS. Without it an ephemeral key is generated and stored PII becomes unreadable on restart.
func WithPIIFieldsYAML ¶
WithPIIFieldsYAML pins the PII vault's field definitions:
pii-fields:
email: {hint: EMAIL}
full_name: {hint: NAME}
With definitions in place a profile write may only use the defined keys, its `hint` may be omitted, and a supplied hint must equal the defined one; the stored hint always comes from the definition. Without them (the default) fields stay free-form. Invalid definitions fail NewServer.
func WithPolicyYAML ¶
WithPolicyYAML supplies compliance policy overrides merged onto the built-in policies (§2.8). Invalid policy data fails NewServer.
func WithPool ¶
WithPool injects an existing pool. The caller keeps ownership: Close does not close a pool it did not create.
func WithoutAdminMFA ¶
func WithoutAdminMFA() Option
WithoutAdminMFA disables the MFA requirement on the management plane. Development only — it removes a control required by the security baselines in project.md §8; a warning is logged at startup whenever it is set.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is a fully wired Dilion deployment. It serves one instance by default and any number of them when WithInstanceResolver is given.
func NewServer ¶
NewServer wires the server. It connects the database (unless WithPool was given), fills in defaults for every injectable component, validates the policy data and builds the HTTP surface.
func (*Server) Close ¶
Close releases resources owned by the server (the pool, when NewServer created it). A pool passed with WithPool is left alone.
func (*Server) Migrate ¶
Migrate applies pending schema migrations to every instance the resolver lists. Safe to run concurrently with other processes and on every boot: each database's run is serialised by a Postgres advisory lock.
func (*Server) Pool ¶
Pool exposes the database pool for embedders sharing it with their app. It is the pool given with WithPool/WithDSN and is nil in a deployment configured with WithInstanceResolver alone — use PoolFor there.
func (*Server) Start ¶
Start serves HTTP and runs the compliance background workers until ctx is cancelled, then shuts down gracefully. It returns nil on a clean shutdown.
func (*Server) WithOpaqueSessionKey ¶
func (s *Server) WithOpaqueSessionKey(ctx context.Context, bearer, keyID string, fn func([]byte) error) error
WithOpaqueSessionKey lends the shared OPAQUE key to a short, synchronous operation after checking the bearer, live session, MFA and key lifetime. Select the trusted instance on ctx just as for HTTP requests. fn must not retain the slice, perform network I/O, or recursively update auth state: account/session locks remain held, and the slice is wiped on return.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
dilion
command
Command dilion runs the Dilion server: Supabase Auth compatible auth plus the privacy/compliance plane.
|
Command dilion runs the Dilion server: Supabase Auth compatible auth plus the privacy/compliance plane. |
|
genkey
command
Command genkey mints an ES256 (P-256) signing key for the /auth/v1 surface.
|
Command genkey mints an ES256 (P-256) signing key for the /auth/v1 surface. |
|
openapi
command
Command openapi generates web/openapi.yaml from the huma route definitions.
|
Command openapi generates web/openapi.yaml from the huma route definitions. |
|
Package httpapi implements the API conventions from docs/api-conventions.md: resource IDs, cursor pagination envelope, and problem-details error codes.
|
Package httpapi implements the API conventions from docs/api-conventions.md: resource IDs, cursor pagination envelope, and problem-details error codes. |
|
internal
|
|
|
api
Package api implements the Dilion management-plane HTTP surface (/privacy/v1 and /iam/v1) with huma v2, following docs/api-conventions.md.
|
Package api implements the Dilion management-plane HTTP surface (/privacy/v1 and /iam/v1) with huma v2, following docs/api-conventions.md. |
|
audit
Package audit implements the default append-only audit sink (project.md §5).
|
Package audit implements the default append-only audit sink (project.md §5). |
|
auth
Package auth implements the Supabase Auth (gotrue) compatible surface mounted at /auth/v1 (project.md §2.2, §2.3).
|
Package auth implements the Supabase Auth (gotrue) compatible surface mounted at /auth/v1 (project.md §2.2, §2.3). |
|
auth/upstreamspec
Package upstreamspec holds Go types generated from the OpenAPI document that github.com/supabase/auth (GoTrue) publishes for its own REST API.
|
Package upstreamspec holds Go types generated from the OpenAPI document that github.com/supabase/auth (GoTrue) publishes for its own REST API. |
|
devmail
Package devmail provides the development-default ports.Mailer and ports.SMSSender: they deliver nothing and log the message with log/slog.
|
Package devmail provides the development-default ports.Mailer and ports.SMSSender: they deliver nothing and log the message with log/slog. |
|
hooks
Package hooks implements the hook registry (project.md §2.4).
|
Package hooks implements the hook registry (project.md §2.4). |
|
iam
Package iam implements the management-plane RBAC of project.md §2.11: flat permission strings bundled into roles, history-preserving role assignments (grant/revoke rows are never deleted — 안전성 확보조치 기준 제5조), scoped API keys, and the default Authorizer.
|
Package iam implements the management-plane RBAC of project.md §2.11: flat permission strings bundled into roles, history-preserving role assignments (grant/revoke rows are never deleted — 안전성 확보조치 기준 제5조), scoped API keys, and the default Authorizer. |
|
instances
Package instances resolves the per-request Dilion instance.
|
Package instances resolves the per-request Dilion instance. |
|
kmslocal
Package kmslocal is Dilion's default ports.KMS: AES-256-GCM envelope encryption with per-(subject, scope) data keys stored in dilion_pii.subject_keys, wrapped by a master key held in process memory.
|
Package kmslocal is Dilion's default ports.KMS: AES-256-GCM envelope encryption with per-(subject, scope) data keys stored in dilion_pii.subject_keys, wrapped by a master key held in process memory. |
|
privacy
Package privacy: engine implementation of the Service contract in service.go.
|
Package privacy: engine implementation of the Service contract in service.go. |
|
store
Package store owns the Postgres connection pool and the migration runner.
|
Package store owns the Postgres connection pool and the migration runner. |
|
Package migrations holds Dilion's forward-only SQL migrations as an embedded filesystem.
|
Package migrations holds Dilion's forward-only SQL migrations as an embedded filesystem. |
|
Package ports defines the shared interfaces (contracts) between Dilion domains and embedder-injectable components.
|
Package ports defines the shared interfaces (contracts) between Dilion domains and embedder-injectable components. |
|
test
|
|
|
parity
Package parity is Dilion's differential parity + coverage test harness: it runs the Dilion /auth/v1 surface side-by-side against the real upstream github.com/supabase/auth (GoTrue) and asserts behavioural equivalence, excluding the documented intentional deviations (deviations.yaml).
|
Package parity is Dilion's differential parity + coverage test harness: it runs the Dilion /auth/v1 surface side-by-side against the real upstream github.com/supabase/auth (GoTrue) and asserts behavioural equivalence, excluding the documented intentional deviations (deviations.yaml). |