config

package
v1.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

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

View Source
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

	// DefaultAgeGateChildMaxAge is the conventional COPPA child boundary:
	// users 12 and under (i.e. under 13) are in the protected CHILD band.
	DefaultAgeGateChildMaxAge = 12
	// DefaultAgeGateAdultAge is the age at or above which a user is an adult;
	// below it (and above child-max) they are a TEEN minor.
	DefaultAgeGateAdultAge = 18
)

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).

View Source
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.

View Source
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 {

	// GRPCPort is the native gRPC listener port (reserved; currently unused).
	GRPCPort int
	// ConnectPort is the Connect-RPC HTTP listener port — the main public RPC surface.
	ConnectPort int
	// MetricsPort is the port serving the Prometheus /metrics endpoint.
	MetricsPort int

	// RepoDriver selects the persistence driver — which Repository / DB
	// implementation the binary wires up: "postgres" (default, the primary
	// datastore), "sqlite" (embedded single-node), or "memory" (in-process,
	// for local dev and tests). Driven by GATEWAY_REPO_DRIVER.
	RepoDriver string

	// DefaultTenantID is the storage-scope (shard) id the default project maps
	// onto — the data-plane tenant zero-config requests are pinned to; distinct
	// from DefaultProjectID. Driven by GATEWAY_DEFAULT_TENANT_ID.
	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; the memory driver ignores 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; the memory driver ignores 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

	// EmailServiceHost is the host of the internal email-sending gRPC service.
	EmailServiceHost string
	// EmailServicePort is the port of the internal email-sending gRPC service.
	EmailServicePort int

	// JWTSigner selects the JWT signing backend: "file" (default, RS256 keys
	// read from JWTKeysFile, reloaded on SIGHUP) or "kms_aws" (AWS KMS).
	JWTSigner string
	// JWTKeysFile is the path to the RS256 key document read by the "file"
	// signer; empty auto-generates a throwaway dev key at startup (local dev /
	// CI only — emits a warning log).
	JWTKeysFile string
	// JWTKMSKeys is a CSV of "kid=keyARN" entries for the "kms_aws" signer;
	// required when GATEWAY_JWT_SIGNER=kms_aws.
	JWTKMSKeys string
	// JWTKMSAWSRegion is the AWS region for the "kms_aws" signer.
	JWTKMSAWSRegion string
	// JWTExpirySeconds is the access-token (JWT) lifetime in seconds; capped at
	// 900 (RevocationModeTTLAccessTokenCap) under revocation mode "ttl".
	JWTExpirySeconds int

	// JWTAudience, when non-empty, is stamped on minted access tokens as the
	// "aud" claim and enforced by the verifier on every request.
	JWTAudience string
	// JWTRequireAudience, when true, also rejects tokens that carry no "aud"
	// claim; the false default lets a deploy roll out the mint-side change
	// first, wait for in-flight tokens to expire, then flip to required.
	JWTRequireAudience bool

	// RefreshExpirySeconds is the refresh-token lifetime in seconds (default 7 days).
	RefreshExpirySeconds int

	// RevocationMode selects how a DeleteRefreshTokensForUser propagates to
	// in-flight access tokens — "ttl" (default) or "session".
	//
	//   "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

	// GoogleClientID is the Google OAuth client ID.
	GoogleClientID string
	// GoogleClientSecret is the Google OAuth client secret.
	GoogleClientSecret string
	// MicrosoftClientID is the Microsoft / Entra ID OAuth client ID.
	MicrosoftClientID string
	// MicrosoftClientSecret is the Microsoft / Entra ID OAuth client secret.
	MicrosoftClientSecret string
	// MicrosoftTenantID is the Microsoft directory (tenant) id, or "common" for multi-tenant.
	MicrosoftTenantID string
	// GitHubClientID is the GitHub OAuth client ID.
	GitHubClientID string
	// GitHubClientSecret is the GitHub OAuth client secret.
	GitHubClientSecret string
	// AppleClientID is the Apple Service ID used as the OAuth client ID.
	AppleClientID string
	// AppleTeamID is the Apple Developer Team ID.
	AppleTeamID string
	// AppleKeyID is the Apple private-key (Key) ID.
	AppleKeyID string
	// ApplePrivateKey is the Apple Sign in private key (PEM or base64).
	ApplePrivateKey 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 path
	// prefix. A return_to must match the configured origin and, for path
	// entries, the configured path or one of its descendants. 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/POST /oauth/callback return 404. The headless BeginOAuthLogin / OAuthLogin
	// RPCs are unaffected. Driven by GATEWAY_OAUTH_ALLOWED_RETURN_URLS.
	OAuthAllowedReturnURLs string

	// IDVProvider selects the IDV backend — "azure", "stub", or "" (disabled;
	// the IDV RPCs return CodeUnimplemented).
	IDVProvider string
	// IDVAzureEndpoint is the Azure Cognitive Services Face endpoint URL for
	// the azure provider (e.g. https://NAME.cognitiveservices.azure.com).
	IDVAzureEndpoint string
	// IDVAzureKey is the Azure Cognitive Services API key (azure provider).
	IDVAzureKey string
	// IDVAzureSessionTTLSec is the IDV session-token lifetime in seconds.
	IDVAzureSessionTTLSec int
	// 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

	// CaptchaEnabled is the global on/off for CAPTCHA on unauthenticated endpoints.
	CaptchaEnabled bool
	// CaptchaProvider selects the pkg/captcha implementation — "turnstile" or
	// "recaptcha_v3"; the matching secret must be set.
	CaptchaProvider string
	// CaptchaTurnstileSecret is the Cloudflare Turnstile secret key (provider "turnstile").
	CaptchaTurnstileSecret string
	// CaptchaRecaptchaSecret is the reCAPTCHA v3 secret key (provider "recaptcha_v3").
	CaptchaRecaptchaSecret string
	// CaptchaRecaptchaScoreThreshold is the reCAPTCHA v3 score below which a
	// response is rejected; must be in [0,1].
	CaptchaRecaptchaScoreThreshold float64
	// CaptchaEnforcePasswordSignup gates CAPTCHA on the PasswordSignup endpoint.
	CaptchaEnforcePasswordSignup bool
	// CaptchaEnforcePasswordLogin gates CAPTCHA on the PasswordLogin endpoint.
	CaptchaEnforcePasswordLogin bool
	// CaptchaEnforcePasswordReset gates CAPTCHA on the RequestPasswordReset endpoint.
	CaptchaEnforcePasswordReset bool
	// CaptchaEnforceEmailLoginCode gates CAPTCHA on the RequestEmailLoginCode endpoint.
	CaptchaEnforceEmailLoginCode bool
	// CaptchaEnforceMagicLink gates CAPTCHA on the RequestMagicLink endpoint.
	CaptchaEnforceMagicLink bool

	// AgeGateEnabled is the global on/off for age-gating.
	AgeGateEnabled bool
	// AgeGateChildMaxAge is the inclusive upper age of the protected CHILD band
	// (default 12 → under-13).
	AgeGateChildMaxAge int
	// AgeGateAdultAge is the age at or above which a user is an adult; between it
	// and AgeGateChildMaxAge a user is a TEEN minor (default 18).
	AgeGateAdultAge int
	// AgeGateRequireDOB rejects a signup that omits a date of birth
	// (INVALID_ARGUMENT) instead of treating it as adult.
	AgeGateRequireDOB bool

	// MinorDataMinimization gates COPPA-style data-minimization for accounts
	// the age gate classifies as AGE_BAND_CHILD. When true (and the age gate
	// is enabled), the server refuses to collect or persist non-essential PII
	// from a child: RequestPhoneVerification and BeginIdentityVerification are
	// rejected with ErrMinorDataMinimized, and a recovery_email / avatar_url
	// supplied for a child at signup or profile-update is dropped rather than
	// stored. Default false preserves today's behavior — adults, teens, and
	// accounts with an unknown age band are never affected.
	MinorDataMinimization bool // GATEWAY_MINOR_DATA_MINIMIZATION (default false)

	// PasswordSignupEnabled gates self-serve PasswordSignup; set false to
	// disable it (admin-driven invitations still work).
	PasswordSignupEnabled bool
	// PasswordResetEnabled gates RequestPasswordReset; when false the RPC stays
	// enumeration-safe but is a no-op (admin resets still work).
	PasswordResetEnabled bool
	// PasswordResetExpirySeconds is the recovery-email reset-link lifetime in seconds.
	PasswordResetExpirySeconds int

	// PasswordlessSignupEnabled gates auto-create on a passwordless verify for
	// an unknown email: when false the unknown email gets the same
	// anti-enumeration decoy as a known one, so the endpoint never reveals which
	// addresses exist. Mirrors PasswordSignupEnabled.
	PasswordlessSignupEnabled bool
	// PasswordlessCodeTTLSeconds is the one-time-code lifetime in seconds (code length is fixed at 6 digits).
	PasswordlessCodeTTLSeconds int
	// PasswordlessCodeMaxAttempts is the max verify attempts per OTP before it
	// is invalidated (brute-force cap).
	PasswordlessCodeMaxAttempts int
	// PasswordlessMagicLinkTTLSeconds is the magic-link token lifetime in seconds.
	PasswordlessMagicLinkTTLSeconds int

	// SMSEnabled turns on phone (SMS OTP) verification.
	SMSEnabled bool
	// SMSProvider selects the SMS backend: "twilio", "sns", or "azure".
	SMSProvider string

	// SMSTwilioAccountSID is the Twilio Account SID (provider "twilio").
	SMSTwilioAccountSID string
	// SMSTwilioAuthToken is the Twilio auth token (provider "twilio").
	SMSTwilioAuthToken string
	// SMSTwilioFrom is the Twilio sender phone number (provider "twilio").
	SMSTwilioFrom string

	// SMSAWSRegion is the AWS region for the SNS sender (provider "sns").
	SMSAWSRegion string
	// SMSAWSAccessKeyID is the AWS access key id for SNS (provider "sns").
	SMSAWSAccessKeyID string
	// SMSAWSSecretAccessKey is the AWS secret access key for SNS (provider "sns").
	SMSAWSSecretAccessKey string
	// SMSAWSSenderID is the optional AWS SNS sender id (provider "sns").
	SMSAWSSenderID string

	// SMSAzureConnectionString is the Azure Communication Services connection
	// string (provider "azure").
	SMSAzureConnectionString string
	// SMSAzureFrom is the Azure Communication Services sender number (provider "azure").
	SMSAzureFrom string

	// PhoneCodeTTLSeconds is the phone-verification OTP lifetime in seconds.
	PhoneCodeTTLSeconds int
	// PhoneCodeMaxAttempts is the max wrong-code guesses before the OTP is invalidated.
	PhoneCodeMaxAttempts int
	// PhoneCodeCooldownSeconds is the per-request cooldown (seconds) between phone-verification sends.
	PhoneCodeCooldownSeconds int

	// TOTPEncryptionKey is the base64-encoded 32-byte AES-256 key that encrypts
	// TOTP secrets at rest. Throwaway dev key if unset; required in prod (a
	// deterministic dev fallback must never be used in production).
	TOTPEncryptionKey string
	// TOTPIssuer is the issuer name shown in users' authenticator apps.
	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

	// LoginChallengeExpirySeconds is the window (seconds) after a password
	// success in which the user must complete the 2FA challenge.
	LoginChallengeExpirySeconds int

	// PasskeyRPID is the WebAuthn relying-party ID — must match the registrable
	// domain (e.g. example.com).
	PasskeyRPID string
	// PasskeyRPName is the human-readable WebAuthn relying-party name.
	PasskeyRPName string
	// PasskeyOrigin is the allowed origin for passkey ceremonies (scheme + host + port).
	PasskeyOrigin string
	// PasskeyChallengeExpirySeconds is the lifetime in seconds of registration / login challenges.
	PasskeyChallengeExpirySeconds int

	// QRLoginBaseURL is the base URL embedded in the cross-device login QR code.
	QRLoginBaseURL string
	// QRLoginExpirySeconds is the QR login-session lifetime in seconds.
	QRLoginExpirySeconds int

	// LoginMaxFailedAttempts is the consecutive failed-login count that triggers a lockout.
	LoginMaxFailedAttempts int
	// LoginLockoutSeconds is how long (seconds) an account stays locked after the threshold is hit.
	LoginLockoutSeconds int

	// DefaultEmailDomain is the default email domain applied to new accounts.
	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

	// AllowedOrigins is the comma-separated list of CORS allowed origins.
	AllowedOrigins string

	// CookieDomain is the Domain attribute set on auth cookies (empty = host-only).
	CookieDomain string
	// CookieSecure sets the Secure attribute on auth cookies; enable in prod (HTTPS-only).
	CookieSecure bool
	// CookieSameSite is the SameSite attribute on auth cookies — "Lax", "Strict", or "None".
	CookieSameSite string

	// AuthAllowLocal enables local username/password auth; set false to require
	// OAuth (intended for development).
	AuthAllowLocal bool

	// AuthRequireVerifiedEmail blocks authentication until the account's email
	// is verified. Default ON. Closes an account pre-hijacking vector: an
	// attacker who plants a password account for an unverified address cannot
	// use it, and a session is never issued for an unverified account.
	AuthRequireVerifiedEmail bool

	// SMTPHost is the SMTP server hostname.
	SMTPHost string
	// SMTPPort is the SMTP server port.
	SMTPPort int
	// SMTPUser is the SMTP auth username.
	SMTPUser string
	// SMTPPass is the SMTP auth password.
	SMTPPass string
	// SMTPFrom is the envelope/From address for outbound mail.
	SMTPFrom string
	// SMTPTLS enables STARTTLS / TLS for the SMTP connection.
	SMTPTLS bool

	// SMTPProviders is a JSON array of SMTP configs ([]email.SMTPConfig) used as
	// a failover chain in order; overrides the single-provider SMTP_* vars.
	SMTPProviders string

	// EmailBrandProductName is the product name shown in email bodies.
	EmailBrandProductName string
	// EmailBrandFrom is the From address for transactional mail (falls back to SMTPFrom).
	EmailBrandFrom string
	// EmailBrandFromName is the From display name (rendered as "Name" <addr>).
	EmailBrandFromName string
	// EmailBrandLogoURL is the absolute https logo URL shown in HTML email.
	EmailBrandLogoURL string
	// EmailBrandPrimaryColor is the CSS colour used to tint branded HTML email.
	EmailBrandPrimaryColor string
	// EmailBrandSupportEmail is the support address shown in footers and set as the Reply-To header.
	EmailBrandSupportEmail string
	// EmailListUnsubscribe is the List-Unsubscribe header value applied to
	// configured mail (e.g. "<mailto:unsubscribe@example.com>"). Empty omits the
	// header; auth/transactional mail stays deliverable either way.
	EmailListUnsubscribe string

	// 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 the datastore 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")

	// RateLimitWindowSeconds is the sliding window length (seconds) for the per-IP limiter.
	RateLimitWindowSeconds int
	// RateLimitSignupPerIP is the per-IP request cap per window on PasswordSignup.
	RateLimitSignupPerIP int
	// RateLimitLoginPerIP is the per-IP request cap per window on the login endpoints.
	RateLimitLoginPerIP int
	// RateLimitResetPerIP is the per-IP request cap per window on RequestPasswordReset.
	RateLimitResetPerIP int
	// RateLimitVerifyPerIP is the per-IP request cap per window on the verification endpoints.
	RateLimitVerifyPerIP int
	// RateLimitPasswordlessPerIP is the per-IP cap per window on
	// RequestEmailLoginCode + RequestMagicLink.
	RateLimitPasswordlessPerIP int
	// RateLimitPhonePerIP is the per-IP cap per window on RequestPhoneVerification.
	RateLimitPhonePerIP int
	// RateLimitBootstrapPerIP is the per-IP cap per window on CreateFirstPlatformAdmin.
	RateLimitBootstrapPerIP int

	// PostgresDSN is the Postgres connection string (e.g.
	// "postgres://user:pass@host:5432/identity?sslmode=disable"); required when
	// RepoDriver is "postgres" (the default).
	PostgresDSN string
	// PostgresMaxConns is the connection-pool size.
	PostgresMaxConns int
	// PostgresAutoMigrate runs pending migrations on connect; leave false in
	// production and run migrations out-of-band (a rolling deploy can race replicas).
	PostgresAutoMigrate bool

	// SQLitePath is the SQLite database file path, or ":memory:" for an
	// ephemeral in-process database; required when RepoDriver is "sqlite".
	SQLitePath string
	// SQLiteMaxConns is the connection-pool size for a file database.
	SQLiteMaxConns int

	// OTelEnabled turns on OTLP trace export.
	OTelEnabled bool
	// OTelExporterEndpoint is the OTLP collector host:port; required when OTelEnabled.
	OTelExporterEndpoint string
	// OTelExporterProtocol is the OTLP transport — "grpc" or "http".
	OTelExporterProtocol string
	// OTelSampleRatio is the trace head-sampling ratio in [0.0, 1.0].
	OTelSampleRatio float64
	// OTelDeploymentEnv sets the deployment.environment.name resource attribute.
	OTelDeploymentEnv string
	// OTelServiceVersion overrides the build version baked into the binary on emitted traces.
	OTelServiceVersion string

	// SweeperIntervalSeconds is the sweep tick interval in seconds; 0 disables
	// sweeping entirely (for tests or deployers who run their own GC).
	SweeperIntervalSeconds int
	// SweeperBatchSize is the per-table, per-tick deletion cap.
	SweeperBatchSize int
	// SweeperGraceSeconds is extra grace past expires_at before a row is
	// eligible for deletion (covers flows that just consumed the token).
	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

func (c *Config) DefaultPrimaryAuthDomain() string

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

func (c *Config) DefaultProjectAuthDomainList() []string

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

func (c *Config) EmailServiceAddress() string

EmailServiceAddress returns the host:port for the email service.

func (*Config) IsPublicEmailDomain added in v0.17.0

func (c *Config) IsPublicEmailDomain(emailOrDomain string) bool

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) JWTExpiry

func (c *Config) JWTExpiry() time.Duration

JWTExpiry returns the JWT expiry as a time.Duration.

func (*Config) PasswordResetExpiry

func (c *Config) PasswordResetExpiry() time.Duration

PasswordResetExpiry returns the password reset expiry as a time.Duration.

func (*Config) ProjectResolutionCacheTTL added in v1.2.0

func (c *Config) ProjectResolutionCacheTTL() time.Duration

ProjectResolutionCacheTTL returns the configured project-resolution cache TTL as a time.Duration. 0 means disabled (resolve on every request).

func (*Config) RefreshExpiry

func (c *Config) RefreshExpiry() time.Duration

RefreshExpiry returns the refresh token expiry as a time.Duration.

func (*Config) SessionCacheTTL added in v0.8.0

func (c *Config) SessionCacheTTL() time.Duration

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

func (c *Config) Validate() error

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
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL