Documentation
¶
Overview ¶
Package config loads the identity service configuration from environment variables with the GATEWAY_ prefix.
This is the Go port of backend/api_gateway/config.py. It uses os.Getenv with typed defaults — no external config library needed. Sensitive values (secrets, encryption keys, client secrets) are never logged.
Index ¶
- Constants
- type Config
- func (c *Config) DefaultPrimaryAuthDomain() string
- func (c *Config) DefaultProjectAuthDomainList() []string
- func (c *Config) EmailServiceAddress() string
- func (c *Config) IsPublicEmailDomain(emailOrDomain string) bool
- func (c *Config) JWTExpiry() time.Duration
- func (c *Config) PasswordResetExpiry() time.Duration
- func (c *Config) ProjectResolutionCacheTTL() time.Duration
- func (c *Config) RefreshExpiry() time.Duration
- func (c *Config) SessionCacheTTL() time.Duration
- func (c *Config) Validate() error
- type RevocationMode
Constants ¶
const ( CaptchaProviderTurnstile = "turnstile" CaptchaProviderRecaptchaV3 = "recaptcha_v3" // DefaultCaptchaRecaptchaScoreThreshold is the reCAPTCHA v3 score below // which a response is rejected when no threshold is configured. DefaultCaptchaRecaptchaScoreThreshold = 0.5 )
CAPTCHA provider names accepted in GATEWAY_CAPTCHA_PROVIDER. They mirror the captcha.Provider* constants; config validates against these without importing pkg/captcha (config has no dependencies on the service tree).
const ( SMSProviderTwilio = "twilio" SMSProviderSNS = "sns" SMSProviderAzure = "azure" )
SMS provider names for GATEWAY_SMS_PROVIDER. Firebase/Google are intentionally out of scope — those are client-SDK flows, not server REST APIs.
const DefaultProjectIDFallback = "default"
DefaultProjectIDFallback is the project id used when none is configured. It is the env-loader default for GATEWAY_DEFAULT_PROJECT_ID and the value app.New normalizes an empty DefaultProjectID to, so a directly-constructed Config (tests, embedding callers) never reaches the repo boundary with an empty project shard id. The single source of truth for this literal.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Server
GRPCPort int
ConnectPort int
MetricsPort int
// Persistence driver. Selects which Repository / DB
// implementation the binary wires up — "entdb" (default), "memory"
// for an in-process store useful for local dev, or "postgres"
// once the Postgres driver lands. Driven by GATEWAY_REPO_DRIVER.
RepoDriver string
// EntDB
EntDBAddress string
// Tenant
DefaultTenantID string
// DefaultProjectID is the id of the control-plane Project the service
// seeds on boot (postgres driver) and pins zero-config requests to. It
// is a logical control-plane entity that MAPS ONTO the storage scope
// DefaultTenantID — the two are distinct values and must not be
// conflated. Driven by GATEWAY_DEFAULT_PROJECT_ID (default "default").
// Only the postgres driver has a control plane; entdb/memory ignore it.
DefaultProjectID string
// AdminAPISecret is the shared secret that authenticates the
// control-plane admin RPCs (AdminCreateProject and friends), which a
// PLATFORM operator uses to provision projects/tenants out-of-band.
// These RPCs are NOT user-authenticated: a caller proves it is the
// operator by presenting this exact value in the
// middleware.AdminAPISecretHeader header, compared in constant time.
//
// Empty (the default) DISABLES the admin RPCs entirely — they return
// CodeUnimplemented — so a deployer who never sets it cannot have them
// reached. Driven by GATEWAY_ADMIN_API_SECRET. Only the postgres driver
// has a control plane; entdb/memory ignore it.
//
// TODO(redesign): the shared secret is the shipped mechanism. Future
// work hardens this with mTLS client-certificate auth and an optional
// internal-only listener port bound away from the public RPC surface.
AdminAPISecret string
// DefaultProjectAuthDomains is a comma-separated list of serving
// hostnames seeded onto the default project at boot (postgres driver),
// so the Host→project resolver maps these branded hostnames to the
// default project. The FIRST entry is the primary auth-domain (used to
// build branded links and cookie domains); the rest are additional
// serving hosts. All are seeded VERIFIED — they are deployer-owned (a
// customer-supplied custom domain goes through DNS verification
// instead). Empty disables seeding. Driven by
// GATEWAY_DEFAULT_PROJECT_AUTH_DOMAINS.
DefaultProjectAuthDomains string
// RequireVerifiedAuthDomain governs whether an UNVERIFIED custom
// auth-domain marked is_primary may become a project's primary
// auth-domain — the host that drives branded link URLs (magic links,
// invitations) and cookie domains. When true (the safe default), the
// primary-auth-domain selection requires verified_at_ms > 0, so only a
// DNS-verified host can drive branded links, matching the verified-only
// Host→project resolver and the proto contract on is_primary. identity
// is a library/OSS server, so whether to trust an unverified is_primary
// host is the deployer's policy: set this false to opt in. Driven by
// GATEWAY_REQUIRE_VERIFIED_AUTH_DOMAIN, default true.
RequireVerifiedAuthDomain bool
// Email service (internal gRPC)
EmailServiceHost string
EmailServicePort int
// JWT (RS256). Two backends ship in-tree:
//
// file (default) reads the keys file at GATEWAY_JWT_KEYS_FILE,
// reloads on SIGHUP. The default for any non-KMS
// deployment; works without external dependencies. If
// JWTKeysFile is empty, the binary auto-generates a
// throwaway dev key in a temp file at startup (suitable
// for local dev / CI only — emits a warning log).
// kms_aws delegates Sign to AWS KMS. JWTKMSKeys is a CSV of
// "kid=keyARN" entries.
//
// Adding a new backend (GCP KMS, HashiCorp Vault, hardware HSM, …)
// is a matter of implementing pkg/jwt.Signer in a sibling package.
JWTSigner string
JWTKeysFile string
JWTKMSKeys string
JWTKMSAWSRegion string
JWTExpirySeconds int
// JWT audience. When non-empty, minted access tokens carry this as
// the "aud" claim and the verifier enforces a match. When
// JWTRequireAudience is true, tokens with no "aud" claim are also
// rejected; the false default exists so a deploy can roll out the
// mint-side change first, wait for in-flight tokens to expire, then
// flip to required.
JWTAudience string
JWTRequireAudience bool
// Refresh tokens
RefreshExpirySeconds int
// Revocation mode. Selects how the service propagates a
// DeleteRefreshTokensForUser to in-flight access tokens.
//
// "ttl" (default) — refresh tokens are deleted; already-minted
// access tokens stay valid until natural JWT expiry. Zero
// hot-path cost. Hard startup assertion:
// `JWTExpirySeconds <= 900` so a deployer cannot raise the
// access-token lifetime without explicitly switching modes.
// "session" — opt-in. Access tokens carry an `sid` claim referencing
// a Session row; the verification middleware reads that
// row (via an in-process cache, configurable below) and
// rejects the request when `revoked_at_ms != 0`.
// DeleteRefreshTokensForUser additionally triggers
// RevokeSessionsForUser so the existing replay-detection
// code path also kills the access tokens.
//
// See docs/IDENTITY.md decision log §6 for the two-mode contract.
RevocationMode RevocationMode
// SessionCacheTTLSeconds bounds how long a session-state read from the
// in-process cache may serve "active" before being re-read from the
// repository. 0 = strict mode: every authenticated request reads the
// row. Effective only when RevocationMode == RevocationModeSession.
SessionCacheTTLSeconds int
// ProjectResolutionCacheTTLSeconds bounds how long a per-request
// project resolution (credential-key→project and Host→project) may be
// served from the in-process cache before being re-read from the
// control-plane store. Project resolution runs ahead of the rate
// limiter and on every CORS preflight, so caching it removes 2-3
// uncached DB queries from the hot path. Kept short so a suspended
// project or revoked credential is never served stale beyond the TTL.
// 0 = disabled: every request resolves against the store.
ProjectResolutionCacheTTLSeconds int
// ProjectResolutionCacheMaxEntries bounds the number of distinct
// resolution keys (credential ids + hostnames) held in the cache,
// evicting the least-recently-used entry past the bound so the cache
// cannot grow unbounded under hostile or high-cardinality traffic.
ProjectResolutionCacheMaxEntries int
// OAuth providers. Identity does the code exchange for these
// providers itself — see pkg/oauth. A provider is enabled only
// when BOTH the ID and secret are non-empty.
GoogleClientID string
GoogleClientSecret string
MicrosoftClientID string
MicrosoftClientSecret string
MicrosoftTenantID string
GitHubClientID string
GitHubClientSecret string
// OAuthAllowedReturnURLs is the comma-separated allowlist of app URLs
// the hosted OAuth flow may redirect back to (the `return_to` param of
// GET /oauth/start/{provider}). Each entry is an exact origin or a URL
// prefix; a return_to matches when it equals an entry or begins with
// an entry. Validation is fail-closed: a return_to that matches no
// entry is rejected with 400.
//
// Empty disables the hosted flow entirely — GET /oauth/start and GET
// /oauth/callback return 404. The headless BeginOAuthLogin / OAuthLogin
// RPCs are unaffected. Driven by GATEWAY_OAUTH_ALLOWED_RETURN_URLS.
OAuthAllowedReturnURLs string
// Identity Verification (document + selfie). The provider name
// selects the implementation in pkg/idv. Empty disables IDV; the
// RPCs return CodeUnimplemented to clients in that case.
IDVProvider string // "azure", "stub", or "" (disabled)
IDVAzureEndpoint string // e.g. https://my-face.cognitiveservices.azure.com
IDVAzureKey string // Cognitive Services key
IDVAzureSessionTTLSec int // session token lifetime; default 600
// When true, PasswordLogin / OAuthLogin reject users without an
// approved identity verification. The default is false (verification
// is offered but not required) to match the existing email-verified
// pattern. Tenants that need stricter onboarding flip this on.
IDVRequired bool
// CAPTCHA verification on unauthenticated endpoints. CaptchaEnabled is
// the global on/off; when off the no-op verifier is wired and the
// per-endpoint toggles are ignored. CaptchaProvider selects the
// implementation in pkg/captcha ("turnstile" or "recaptcha_v3"); the
// matching secret must be set. The per-endpoint toggles let a deployer
// enforce CAPTCHA on a subset of the gated endpoints (all default true,
// so enabling CAPTCHA gates every endpoint unless one is flipped off).
CaptchaEnabled bool // GATEWAY_CAPTCHA_ENABLED (default false)
CaptchaProvider string // GATEWAY_CAPTCHA_PROVIDER ("turnstile" | "recaptcha_v3" | "")
CaptchaTurnstileSecret string // GATEWAY_CAPTCHA_TURNSTILE_SECRET
CaptchaRecaptchaSecret string // GATEWAY_CAPTCHA_RECAPTCHA_SECRET
CaptchaRecaptchaScoreThreshold float64 // GATEWAY_CAPTCHA_RECAPTCHA_SCORE_THRESHOLD (default 0.5)
CaptchaEnforcePasswordSignup bool // GATEWAY_CAPTCHA_ENFORCE_PASSWORD_SIGNUP (default true)
CaptchaEnforcePasswordLogin bool // GATEWAY_CAPTCHA_ENFORCE_PASSWORD_LOGIN (default true)
CaptchaEnforcePasswordReset bool // GATEWAY_CAPTCHA_ENFORCE_PASSWORD_RESET (default true)
CaptchaEnforceEmailLoginCode bool // GATEWAY_CAPTCHA_ENFORCE_EMAIL_LOGIN_CODE (default true)
CaptchaEnforceMagicLink bool // GATEWAY_CAPTCHA_ENFORCE_MAGIC_LINK (default true)
// Password
PasswordSignupEnabled bool
PasswordResetEnabled bool
PasswordResetExpirySeconds int
// Passwordless email login (OTP code + magic link).
//
// PasswordlessSignupEnabled (default true) gates auto-create: when a
// passwordless login verifies an email with no existing account and
// this is true, the account is created on the spot; when false the
// unknown email gets the same anti-enumeration decoy a request for a
// known email would produce, so the endpoint never reveals which
// addresses exist. Mirrors GATEWAY_PASSWORD_SIGNUP_ENABLED.
PasswordlessSignupEnabled bool // GATEWAY_PASSWORDLESS_SIGNUP_ENABLED (default true)
// OTP code lifetime, length is fixed at 6 digits.
PasswordlessCodeTTLSeconds int // GATEWAY_PASSWORDLESS_CODE_TTL_SECONDS (default 300)
// Max verify attempts per OTP before it is invalidated (brute-force cap).
PasswordlessCodeMaxAttempts int // GATEWAY_PASSWORDLESS_CODE_MAX_ATTEMPTS (default 5)
// Magic-link token lifetime.
PasswordlessMagicLinkTTLSeconds int // GATEWAY_PASSWORDLESS_MAGIC_LINK_TTL_SECONDS (default 900)
// Phone verification (SMS OTP). Standalone phone-ownership
// verification for an already-authenticated user — not yet a login
// factor. Disabled by default; when SMSEnabled is true a provider and
// its credentials must be set (enforced by Validate).
SMSEnabled bool // GATEWAY_SMS_ENABLED (default false)
SMSProvider string // GATEWAY_SMS_PROVIDER: twilio | sns | azure
// Twilio credentials (SMSProvider == twilio).
SMSTwilioAccountSID string // GATEWAY_SMS_TWILIO_ACCOUNT_SID
SMSTwilioAuthToken string // GATEWAY_SMS_TWILIO_AUTH_TOKEN
SMSTwilioFrom string // GATEWAY_SMS_TWILIO_FROM
// AWS SNS credentials (SMSProvider == sns).
SMSAWSRegion string // GATEWAY_SMS_AWS_REGION
SMSAWSAccessKeyID string // GATEWAY_SMS_AWS_ACCESS_KEY_ID
SMSAWSSecretAccessKey string // GATEWAY_SMS_AWS_SECRET_ACCESS_KEY
SMSAWSSenderID string // GATEWAY_SMS_AWS_SENDER_ID (optional)
// Azure Communication Services credentials (SMSProvider == azure).
SMSAzureConnectionString string // GATEWAY_SMS_AZURE_CONNECTION_STRING
SMSAzureFrom string // GATEWAY_SMS_AZURE_FROM
// Phone-verification OTP policy (mirrors the Passwordless* knobs).
PhoneCodeTTLSeconds int // GATEWAY_PHONE_CODE_TTL_SECONDS (default 300)
PhoneCodeMaxAttempts int // GATEWAY_PHONE_CODE_MAX_ATTEMPTS (default 5)
PhoneCodeCooldownSeconds int // GATEWAY_PHONE_CODE_COOLDOWN_SECONDS (default 60)
// TOTP (2FA)
// 32-byte key, base64-encoded. Required in prod; dev falls back to
// a deterministic throwaway key.
TOTPEncryptionKey string
TOTPIssuer string
// Pepper used as the HMAC-SHA-256 key for recovery-code hashing.
// Base64-encoded; must decode to >= 32 bytes. Required whenever
// TOTPEncryptionKey is set (i.e. any non-dev deployment). The
// pepper turns a stolen DB into a brute-force-resistant artifact:
// without it, an attacker cannot precompute or enumerate hashes.
TOTPRecoveryPepper string
// Login challenge (how long after password success user has to complete 2FA)
LoginChallengeExpirySeconds int
// WebAuthn / Passkeys
PasskeyRPID string
PasskeyRPName string
PasskeyOrigin string
PasskeyChallengeExpirySeconds int
// QR Login (cross-device authorization)
QRLoginBaseURL string
QRLoginExpirySeconds int
// Login security (failed-login lockout)
LoginMaxFailedAttempts int
LoginLockoutSeconds int
// Default email domain
DefaultEmailDomain string
// PublicEmailDomains extends the built-in set of consumer/public email
// providers (gmail, outlook, yahoo, …) used by IsPublicEmailDomain. A
// verified email under a public domain does NOT imply company
// affiliation, so a tenant is never auto-formed from one. Comma-
// separated; entries are punycode-canonicalised. Driven by
// GATEWAY_PUBLIC_EMAIL_DOMAINS (default empty — the built-in set
// already covers the major global providers).
PublicEmailDomains string
// CORS
AllowedOrigins string
// Cookie settings
CookieDomain string
CookieSecure bool
CookieSameSite string
// Dev-only
AuthAllowLocal bool
// SMTP single-provider config (simple form). If SMTPProviders is set,
// that takes precedence.
SMTPHost string // GATEWAY_SMTP_HOST
SMTPPort int // GATEWAY_SMTP_PORT (default 587)
SMTPUser string // GATEWAY_SMTP_USER
SMTPPass string // GATEWAY_SMTP_PASS
SMTPFrom string // GATEWAY_SMTP_FROM
SMTPTLS bool // GATEWAY_SMTP_TLS (default true)
// SMTP multi-provider JSON. If set, parsed as []email.SMTPConfig and
// used as a chain in order. Overrides the single-provider env vars.
SMTPProviders string // GATEWAY_SMTP_PROVIDERS
// Public app URLs used in email links.
AppBaseURL string // GATEWAY_APP_BASE_URL — e.g. "https://app.example.com"
// How long an email-verification or password-reset token is valid for.
EmailTokenExpirySeconds int // GATEWAY_EMAIL_TOKEN_EXPIRY_SECONDS (default 86400)
// How long a tenant-membership invitation is valid for before it must be
// reissued. Longer than an email token because joining a team is a less
// time-sensitive action than a password reset.
TenantInvitationExpirySeconds int // GATEWAY_TENANT_INVITATION_EXPIRY_SECONDS (default 604800 = 7 days)
// Per-recipient cooldown between transactional email sends. Defeats
// inbox-bombing via repeated unauthenticated RequestPasswordReset /
// SendEmailVerification calls. In-memory per replica.
EmailSendCooldownSeconds int // GATEWAY_EMAIL_SEND_COOLDOWN_SECONDS (default 60)
// Per-email cooldown on PasswordSignup. Throttled signups return
// the same anti-enumeration decoy as a duplicate-email signup so the
// endpoint cannot be used to probe for which addresses are
// rate-limited (which would itself reveal recent attempts).
// Complements the per-IP rate limit at the middleware layer.
SignupEmailCooldownSeconds int // GATEWAY_SIGNUP_EMAIL_COOLDOWN_SECONDS (default 60)
// Audit log queue depth for the async flusher. Drops happen if the
// auth hot path produces events faster than EntDB can absorb them.
// Surface via audit.Logger.DroppedCount() on a metric.
AuditQueueSize int // GATEWAY_AUDIT_QUEUE_SIZE (default 4096)
// Maximum HTTP request body size in bytes, enforced via
// http.MaxBytesHandler so a slow-POST / oversize-payload attacker
// can't exhaust memory. Default 1 MiB — auth RPC bodies are tiny.
HTTPMaxBodyBytes int64 // GATEWAY_HTTP_MAX_BODY_BYTES (default 1048576)
// Trusted proxies: comma-separated list of CIDRs whose
// X-Forwarded-For headers the service will honour. Anything outside
// these ranges is treated as an untrusted client and its forwarded
// headers are ignored — TCP peer IP is used instead.
TrustedProxies string // GATEWAY_TRUSTED_PROXIES (default "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128")
// Rate-limit configuration. The in-memory token bucket is keyed by
// client IP. quotas are requests-per-window per IP. Set to 0 to
// disable the per-endpoint limiter.
RateLimitWindowSeconds int // GATEWAY_RATE_LIMIT_WINDOW_SECONDS (default 60)
RateLimitSignupPerIP int // GATEWAY_RATE_LIMIT_SIGNUP_PER_IP (default 10/min)
RateLimitLoginPerIP int // GATEWAY_RATE_LIMIT_LOGIN_PER_IP (default 30/min)
RateLimitResetPerIP int // GATEWAY_RATE_LIMIT_RESET_PER_IP (default 5/min)
RateLimitVerifyPerIP int // GATEWAY_RATE_LIMIT_VERIFY_PER_IP (default 20/min)
RateLimitPasswordlessPerIP int // GATEWAY_RATE_LIMIT_PASSWORDLESS_PER_IP (default 5/min) — RequestEmailLoginCode + RequestMagicLink
RateLimitPhonePerIP int // GATEWAY_RATE_LIMIT_PHONE_PER_IP (default 5/min) — RequestPhoneVerification
RateLimitBootstrapPerIP int // GATEWAY_RATE_LIMIT_BOOTSTRAP_PER_IP (default 5/min) — CreateFirstPlatformAdmin
// Postgres (alternate persistence driver). When PostgresDSN is set
// the application bootstrapper may prefer the Postgres-backed
// repository over EntDB; the actual driver selection lives in the
// internal/repo package.
//
// GATEWAY_POSTGRES_DSN e.g. "postgres://user:pass@host:5432/identity?sslmode=disable"
// GATEWAY_POSTGRES_MAX_CONNS pool size, default 25
// GATEWAY_POSTGRES_AUTO_MIGRATE run pending migrations on connect, default false
// (production: run migrations out-of-band as a
// separate Job; setting this true on a rolling
// deploy can race multiple replicas).
PostgresDSN string
PostgresMaxConns int
PostgresAutoMigrate bool
// OTel exports OpenTelemetry traces to a deployer-supplied OTLP
// collector. Default off so a deployer who has no collector pays
// zero cost — when disabled the no-op tracer is installed and the
// otelconnect interceptor is omitted from the handler chain.
//
// GATEWAY_OTEL_ENABLED true|false (default false)
// GATEWAY_OTEL_EXPORTER_ENDPOINT host:port — required when enabled
// GATEWAY_OTEL_EXPORTER_PROTOCOL grpc|http (default grpc)
// GATEWAY_OTEL_SAMPLE_RATIO 0.0–1.0 (default 0.1)
// GATEWAY_OTEL_DEPLOYMENT_ENV deployment.environment.name (default "")
// GATEWAY_OTEL_SERVICE_VERSION overrides build version baked into the binary
OTelEnabled bool
OTelExporterEndpoint string
OTelExporterProtocol string
OTelSampleRatio float64
OTelDeploymentEnv string
OTelServiceVersion string
// Sweeper (#94). A background goroutine periodically deletes
// expired-but-uncollected rows from five ephemeral tables
// (WebAuthn challenges, email-verification / password-reset /
// email-change tokens, login challenges). Without GC these
// tables grow unboundedly with the abandoned-flow rate.
//
// GATEWAY_SWEEPER_INTERVAL_SECONDS tick interval; 0 disables sweeping
// entirely (useful for tests and for
// deployers who run their own GC).
// GATEWAY_SWEEPER_BATCH_SIZE per-table per-tick deletion cap.
// GATEWAY_SWEEPER_GRACE_SECONDS additional grace past expires_at
// before a row is eligible to delete;
// covers in-flight flows that just
// consumed the token.
SweeperIntervalSeconds int
SweeperBatchSize int
SweeperGraceSeconds int
}
Config holds all identity service configuration.
func Load ¶
func Load() *Config
Load reads configuration from environment variables with GATEWAY_ prefix, falling back to sensible defaults for local development.
func (*Config) DefaultPrimaryAuthDomain ¶ added in v0.17.0
DefaultPrimaryAuthDomain returns the default project's primary serving hostname — the first entry of DefaultProjectAuthDomainList — or "" when none is configured.
func (*Config) DefaultProjectAuthDomainList ¶ added in v0.17.0
DefaultProjectAuthDomainList returns the configured default-project auth domains, lower-cased and de-duplicated, in order — the first entry is the primary. Blank entries are dropped; an empty config yields nil.
func (*Config) EmailServiceAddress ¶
EmailServiceAddress returns the host:port for the email service.
func (*Config) IsPublicEmailDomain ¶ added in v0.17.0
IsPublicEmailDomain reports whether emailOrDomain belongs to a public / consumer email provider — a domain a Tenant must never be auto-formed from. The input may be a full address (the part after the last '@' is used) or a bare domain; it is lower-cased, trimmed, stripped of a trailing FQDN dot, and punycode-canonicalised before the built-in set and GATEWAY_PUBLIC_EMAIL_DOMAINS are consulted, so an IDN homograph cannot slip past the check.
func (*Config) PasswordResetExpiry ¶
PasswordResetExpiry returns the password reset expiry as a time.Duration.
func (*Config) ProjectResolutionCacheTTL ¶ added in v1.2.0
ProjectResolutionCacheTTL returns the configured project-resolution cache TTL as a time.Duration. 0 means disabled (resolve on every request).
func (*Config) RefreshExpiry ¶
RefreshExpiry returns the refresh token expiry as a time.Duration.
func (*Config) SessionCacheTTL ¶ added in v0.8.0
SessionCacheTTL returns the configured cache TTL as a time.Duration. 0 means strict mode (read on every request).
func (*Config) Validate ¶ added in v0.8.0
Validate enforces invariants that are too complex to express as per-field defaults: most importantly the `mode=ttl` access-token TTL ceiling. The binary calls this at startup; tests pin their configs through the same path so misuse surfaces immediately rather than as a silent revocation-window gap.
Why a method rather than running inside Load(): tests build *Config values directly (without going through Load) and a silent failure mode there would re-introduce the bug this function prevents. Callers that synthesise a Config must invoke Validate before handing it to app.New.
type RevocationMode ¶ added in v0.8.0
type RevocationMode string
RevocationMode names the two refresh-token revocation models the service supports. See the Config.RevocationMode comment for the semantics; the two-mode contract is in docs/IDENTITY.md decision log §6.
const ( // RevocationModeTTL keeps the existing zero-cost hot path. // DeleteRefreshTokensForUser deletes refresh tokens; in-flight // access tokens stay valid until natural JWT expiry. The default. RevocationModeTTL RevocationMode = "ttl" // RevocationModeSession mints access tokens with an `sid` claim // referencing a Session row. The verification middleware reads // that row (via an in-process cache) and rejects the request when // the session is revoked. RevocationModeSession RevocationMode = "session" // RevocationModeTTLAccessTokenCap is the maximum access-token TTL // (seconds) compatible with the `ttl` revocation model. A deployer // who needs a longer-lived access token must switch to // `RevocationModeSession`, where cache TTL bounds the revocation // latency. RevocationModeTTLAccessTokenCap = 900 )