Files
tenant-registry/internal/config/config.go
T
sharang a048d47959
ci / shared (push) Successful in 12s
ci / test (push) Failing after 16m8s
ci / image (push) Skipped
feat(tenants): provision the product tenant with the registry UUID on create (#21)
2026-09-01 21:20:03 +00:00

72 lines
2.3 KiB
Go

package config
import (
"fmt"
"os"
"time"
)
type Config struct {
Env string // dev | stage | prod
Addr string // listen address, e.g. ":8090"
KeycloakIssuer string // e.g. http://localhost:8080/realms/breakpilot-dev
DatabaseURL string // postgres DSN (unused in skeleton; in-memory store)
// Keycloak Admin API — only used if KeycloakAdminURL is set. Empty
// values disable the adapter and tenant-registry falls back to the
// Mock (dev convenience).
KeycloakAdminURL string
KeycloakRealm string
KeycloakClientID string
KeycloakClientSecret string
KeycloakTimeout time.Duration
// Inbound API auth (RBAC Phase 1). With AuthEnabled the server refuses
// to start unless OIDC discovery against KeycloakIssuer succeeds, and
// every non-health route requires a bearer token whose audience
// contains AuthAudience.
AuthEnabled bool
AuthAudience string
// Downstream product provisioning. When ProductAPIURL is set, tenant
// creation also provisions the tenant in the product's own database with
// the SAME registry UUID, so both anchors agree. Empty ⇒ no-op adapter.
ProductAPIURL string
ProductAPIPath string
ProductTimeout time.Duration
}
func Load() (*Config, error) {
env := getenv("APP_ENV", "dev")
if env != "dev" && env != "stage" && env != "prod" {
return nil, fmt.Errorf("invalid APP_ENV %q", env)
}
return &Config{
Env: env,
// :8090 — Keycloak owns :8080 in the dev stack.
Addr: getenv("ADDR", ":8090"),
KeycloakIssuer: getenv("KEYCLOAK_ISSUER", "http://localhost:8080/realms/breakpilot-dev"),
DatabaseURL: os.Getenv("DATABASE_URL"),
KeycloakAdminURL: os.Getenv("KEYCLOAK_ADMIN_URL"),
KeycloakRealm: getenv("KEYCLOAK_REALM", "breakpilot-dev"),
KeycloakClientID: os.Getenv("KEYCLOAK_CLIENT_ID"),
KeycloakClientSecret: os.Getenv("KEYCLOAK_CLIENT_SECRET"),
KeycloakTimeout: 10 * time.Second,
AuthEnabled: getenv("AUTH_ENABLED", "false") == "true",
AuthAudience: getenv("AUTH_EXPECTED_AUDIENCE", "tenant-registry"),
ProductAPIURL: os.Getenv("PRODUCT_API_URL"),
ProductAPIPath: getenv("PRODUCT_API_TENANTS_PATH", "/sdk/v1/tenants"),
ProductTimeout: 10 * time.Second,
}, nil
}
func getenv(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}