Close all 25 codex audit findings and add KMP contract tests
Remediate all P0-S priority findings from cross-platform architecture audit: - Add input validation and authorization checks across handlers - Harden social auth (Apple/Google) token validation - Add document ownership verification and file type validation - Add rate limiting config and CORS origin restrictions - Add subscription tier enforcement in handlers - Add OpenAPI 3.0.3 spec (81 schemas, 104 operations) - Add URL-level contract test (KMP API routes match spec paths) - Add model-level contract test (65 schemas, 464 fields validated) - Add CI workflow for backend tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -28,12 +28,13 @@ type Config struct {
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Port int
|
||||
Debug bool
|
||||
AllowedHosts []string
|
||||
Timezone string
|
||||
StaticDir string // Directory for static landing page files
|
||||
BaseURL string // Public base URL for email tracking links (e.g., https://casera.app)
|
||||
Port int
|
||||
Debug bool
|
||||
AllowedHosts []string
|
||||
CorsAllowedOrigins []string // Comma-separated origins for CORS (production only; debug uses wildcard)
|
||||
Timezone string
|
||||
StaticDir string // Directory for static landing page files
|
||||
BaseURL string // Public base URL for email tracking links (e.g., https://casera.app)
|
||||
}
|
||||
|
||||
type DatabaseConfig struct {
|
||||
@@ -166,12 +167,13 @@ func Load() (*Config, error) {
|
||||
|
||||
cfg = &Config{
|
||||
Server: ServerConfig{
|
||||
Port: viper.GetInt("PORT"),
|
||||
Debug: viper.GetBool("DEBUG"),
|
||||
AllowedHosts: strings.Split(viper.GetString("ALLOWED_HOSTS"), ","),
|
||||
Timezone: viper.GetString("TIMEZONE"),
|
||||
StaticDir: viper.GetString("STATIC_DIR"),
|
||||
BaseURL: viper.GetString("BASE_URL"),
|
||||
Port: viper.GetInt("PORT"),
|
||||
Debug: viper.GetBool("DEBUG"),
|
||||
AllowedHosts: strings.Split(viper.GetString("ALLOWED_HOSTS"), ","),
|
||||
CorsAllowedOrigins: parseCorsOrigins(viper.GetString("CORS_ALLOWED_ORIGINS")),
|
||||
Timezone: viper.GetString("TIMEZONE"),
|
||||
StaticDir: viper.GetString("STATIC_DIR"),
|
||||
BaseURL: viper.GetString("BASE_URL"),
|
||||
},
|
||||
Database: dbConfig,
|
||||
Redis: RedisConfig{
|
||||
@@ -304,10 +306,13 @@ func setDefaults() {
|
||||
|
||||
func validate(cfg *Config) error {
|
||||
if cfg.Security.SecretKey == "" {
|
||||
// Use a default key but log a warning in production
|
||||
cfg.Security.SecretKey = "change-me-in-production-secret-key-12345"
|
||||
if !cfg.Server.Debug {
|
||||
fmt.Println("WARNING: SECRET_KEY not set, using default (insecure)")
|
||||
if cfg.Server.Debug {
|
||||
// In debug mode, use a default key with a warning for local development
|
||||
cfg.Security.SecretKey = "change-me-in-production-secret-key-12345"
|
||||
fmt.Println("WARNING: SECRET_KEY not set, using default (debug mode only)")
|
||||
} else {
|
||||
// In production, refuse to start without a proper secret key
|
||||
return fmt.Errorf("FATAL: SECRET_KEY environment variable is required in production (DEBUG=false)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,6 +344,23 @@ func (p *PushConfig) ReadAPNSKey() (string, error) {
|
||||
return string(content), nil
|
||||
}
|
||||
|
||||
// parseCorsOrigins splits a comma-separated CORS_ALLOWED_ORIGINS string
|
||||
// into a slice, trimming whitespace. Returns nil if the input is empty.
|
||||
func parseCorsOrigins(raw string) []string {
|
||||
if raw == "" {
|
||||
return nil
|
||||
}
|
||||
parts := strings.Split(raw, ",")
|
||||
var origins []string
|
||||
for _, p := range parts {
|
||||
trimmed := strings.TrimSpace(p)
|
||||
if trimmed != "" {
|
||||
origins = append(origins, trimmed)
|
||||
}
|
||||
}
|
||||
return origins
|
||||
}
|
||||
|
||||
// parseDatabaseURL parses a PostgreSQL URL into DatabaseConfig
|
||||
// Format: postgres://user:password@host:port/database?sslmode=disable
|
||||
func parseDatabaseURL(databaseURL string) (*DatabaseConfig, error) {
|
||||
|
||||
Reference in New Issue
Block a user