2.7 KiB
2.7 KiB
TOML Configuration File Design
Date: 2026-02-18 Status: Approved
Goal
Add a TOML configuration file to Porchlight so that server settings and OIDC client registrations can be defined in a file. Environment variables retain highest priority and override any file-based values.
Decisions
| Decision | Choice | Rationale |
|---|---|---|
| File format | TOML | Human-friendly, supports comments, stdlib tomllib on 3.11+ |
| Integration | pydantic-settings TomlConfigSettingsSource |
Already available in pydantic-settings 2.12, handles precedence natively |
| Default path | porchlight.toml in CWD |
Simple convention, overridable via OIDC_OP_CONFIG_FILE |
| Missing file | Silently skip | Env vars and defaults still work — file is optional |
| Scope | Server settings + client registrations in one file | Single source of truth |
Precedence
env vars > TOML file > defaults
pydantic-settings handles this via settings_customise_sources().
Example porchlight.toml
issuer = "https://auth.example.com"
debug = false
session_secret = "a-long-random-string"
sqlite_path = "data/porchlight.db"
signing_key_path = "data/keys"
invite_ttl = 86400
[clients.my-webapp]
client_secret = "super-secret-value"
redirect_uris = ["https://app.example.com/callback"]
response_types = ["code"]
scope = ["openid", "profile", "email"]
token_endpoint_auth_method = "client_secret_basic"
[clients.another-app]
client_secret = "another-secret"
redirect_uris = ["https://other.example.com/oidc/callback"]
response_types = ["code"]
scope = ["openid", "profile"]
token_endpoint_auth_method = "client_secret_basic"
Code Changes
config.py
- Add
ClientConfig(BaseModel)with fields:client_secret,redirect_uris,response_types(default["code"]),scope(default["openid"]),token_endpoint_auth_method(default"client_secret_basic"). - Add
config_file: str = "porchlight.toml"field toSettings. - Add
clients: dict[str, ClientConfig] = {}field toSettings. - Override
settings_customise_sources()to insertTomlConfigSettingsSourcebetween env and defaults. Useconfig_filefield as the TOML path.
app.py
- After creating the OIDC server, loop over
settings.clientsand register each client inoidc_server.context.cdb. - Keep the internal
manage-appclient registration as-is (always registered regardless of config file).
cli.py
- No changes.
Settings()picks up the TOML file automatically.
What Stays the Same
- All existing
OIDC_OP_*env vars work identically. Settings()call sites unchanged.- Docker/compose env var configuration unchanged.
- No new dependencies (pydantic-settings 2.12 already has TOML support,
Python 3.13 has
tomllibin stdlib).