Skip to content

refactor: god-object decomposition, file splits, facade elimination, SettingsCache extraction#225

Merged
bartcode merged 18 commits into
mainfrom
refactor/god-object-decomposition
May 13, 2026
Merged

refactor: god-object decomposition, file splits, facade elimination, SettingsCache extraction#225
bartcode merged 18 commits into
mainfrom
refactor/god-object-decomposition

Conversation

@bartcode
Copy link
Copy Markdown
Collaborator

@bartcode bartcode commented May 13, 2026

Summary

Comprehensive refactoring to eliminate god-objects, split large files, extract coupled types, and remove facade methods across the codebase.

WS1-5: God-object decomposition (from PR scope)

  • jobs.Storage → 7 files by concern, 3 SQL duplicates eliminated
  • auth.Service → 19 sub-service getters + ServiceRegistry registration
  • api.AuthHandler → 10 files by auth flow
  • api.DashboardAuthHandler → 5 files by auth flow

WS6: SettingsCache coupling reduction

  • Exposed SettingsCache on AuthHandlers, replaced 10 authService chain calls

WS7: Large file splits (14 files across 10 packages)

Package File Before After
config config.go 1638 14 files
api query_parser.go 1748 5 files
ai chat_handler.go 1309 3 files
storage local.go 1305 4 files
auth saml.go 1292 4 files
auth platform.go 1256 4 files
settings custom_settings.go 1478 3 files
functions storage.go 1191 4 files
branching storage.go 1180 3 files
api oauth_handler.go 1172 3 files
webhook webhook.go 1070 4 files
api tenant_handler.go 1068 3 files
realtime subscription.go 1030 3 files
ai user_kb_handler.go 1118 4 files
api ddl_handler.go 1014 3 files
mcp/tools ddl.go 1087 3 files
mcp/tools branching.go 1034 3 files
database connection.go 1076 2 files

MV1: SettingsCache package extraction

  • Moved SettingsCache from auth to settings package with SettingProvider interface
  • 6+ packages no longer import auth just for cache access

MV2: Migration runner extraction

  • Extracted from database/connection.go into connection_migrations.go

HR1: auth.Service facade elimination

  • Removed 35 pass-through facade methods
  • Converted 68 call sites to use sub-services directly
  • auth.Service: 70 methods → 49 (19 getters + 18 orchestration + 12 utility)

Impact

  • 35+ god-objects decomposed into focused files
  • 1000+ lines eliminated from SQL deduplication
  • 68 facade call sites converted to direct sub-service access
  • 274 net lines removed from facade elimination
  • All changes are build + lint clean

bartcode added 10 commits May 13, 2026 07:19
…cates

Split storage.go (1509 lines) into 7 files by concern:
- storage.go: struct + constructor (13 lines)
- storage_functions.go: job function CRUD (18 methods)
- storage_function_files.go: file management (3 methods)
- storage_queue.go: job lifecycle (13 methods)
- storage_queries.go: job queries + stats (5 methods)
- storage_workers.go: worker management (8 methods)
- storage_namespaces.go: namespace queries (2 methods)

Eliminate 3 exact SQL duplicates:
- GetJobByIDAdmin -> delegates to GetJob
- ListJobsAdmin -> delegates to ListJobs
- CreateJob already aliased EnqueueJob
Add getter methods on auth.Service for all 13 sub-services
(JWTManager, TokenBlacklistService, MFAService, etc.) so callers
can access them directly without going through the facade.

Register key sub-services in AuthModule.Init() so downstream
modules can use GetService[T]().

Facade methods are kept for backward compatibility.
Split auth_handler.go (1593 lines) into focused files:
- auth_handler.go: struct, constructor, core auth (signup/signin/signout/refresh)
- auth_handler_magiclink.go: magic link flow
- auth_handler_password.go: password reset flow
- auth_handler_email.go: email verification
- auth_handler_impersonation.go: impersonation flows
- auth_handler_mfa.go: TOTP/MFA setup and verification
- auth_handler_otp.go: OTP send/verify/resend
- auth_handler_identity.go: identity link/unlink, OIDC, reauth
- auth_handler_captcha.go: CSRF, captcha config/check
- auth_handler_config.go: auth config endpoint
Split dashboard_auth_handler.go (1570 lines) into focused files:
- dashboard_auth_handler.go: struct, constructor, core auth, middleware
- dashboard_auth_handler_mfa.go: TOTP setup/enable/disable
- dashboard_auth_handler_password.go: password reset flow
- dashboard_auth_handler_oauth.go: OAuth SSO login/callback/providers
- dashboard_auth_handler_saml.go: SAML login/ACS callback
…rvice chain

Add SettingsCache field to AuthHandlers struct, set in AuthModule.Init().
Replace 10 call sites of s.Auth.Handler.authService.GetSettingsCache()
with direct s.Auth.SettingsCache access. Removes coupling to private
authService field from route wiring and middleware setup.
Split config.go (1638 lines, 32 structs) into focused files by domain:
- config.go: Config struct, Load(), Validate(), small structs (CORS, Admin, etc.)
- config_server.go: ServerConfig, BodyLimitsConfig
- config_database.go: DatabaseConfig + connection string methods
- config_auth.go: AuthConfig, SAMLProviderConfig, OAuthProviderConfig
- config_security.go: SecurityConfig, CaptchaConfig, AdaptiveTrustConfig
- config_storage.go: StorageConfig, TransformConfig
- config_email.go: EmailConfig
- config_functions.go: FunctionsConfig
- config_api.go: APIConfig
- config_jobs.go: JobsConfig
- config_ai.go: AIConfig
- config_telemetry.go: TracingConfig, MetricsConfig, LoggingConfig
- config_tenants.go: TenantsConfig + sub-types
- config_scaling.go: ScalingConfig
Split query_parser.go (1748 lines) into focused files:
- query_parser.go: types, Parse(), ParseWithOptions()
- query_parser_select.go: select field and aggregation parsing
- query_parser_order.go: order by and vector order parsing
- query_parser_filter.go: filter, logical, nested filter parsing
- query_parser_sql.go: SQL generation, buildWhereClause, filterToSQL
chat_handler.go (1309 → 3 files):
- chat_handler.go: struct, WebSocket, connection handling, providers
- chat_handler_message.go: handleMessage LLM tool-calling loop
- chat_handler_tools.go: SQL and MCP tool execution

local.go (1305 → 4 files):
- local.go: core operations (upload, download, delete, list, copy, move)
- local_bucket.go: bucket CRUD
- local_signed.go: signed URL generation and validation
- local_chunked.go: chunked upload sessions
saml.go (1292 → 4 files):
- saml.go: core service, assertion parsing, metadata, user extraction
- saml_session.go: SAML session management, assertion replay checks
- saml_logout.go: logout request/response generation and parsing

platform.go (1256 → 4 files):
- platform.go: DashboardAuthService core, Login, CreateUser, tokens
- platform_sso.go: SSO identity lookup, creation, linking
- platform_password.go: password reset, change, profile update, delete
- platform_mfa.go: TOTP setup, enable, verify, disable
custom_settings.go (1478 → 3 files):
- custom_settings.go: types, CRUD, queries
- custom_settings_secrets.go: secret setting methods
- custom_settings_user.go: user setting methods

functions/storage.go (1191 → 4 files):
- storage.go: function CRUD
- storage_sync.go: sync/import methods
- storage_executions.go: execution logging
- storage_files.go: shared modules and file management

branching/storage.go (1180 → 3 files):
- storage.go: branch CRUD
- storage_queries.go: list, count, query methods
- storage_lifecycle.go: activity, migrations, GitHub, access

oauth_handler.go (1172 → 3 files):
- oauth_handler.go: authorize, providers, state
- oauth_handler_callback.go: callback, user linking
- oauth_handler_providers.go: provider config, user info
@bartcode bartcode changed the title refactor: god-object decomposition across jobs, auth, and API handlers refactor: god-object decomposition + large file splits across 10 packages May 13, 2026
bartcode added 4 commits May 13, 2026 09:38
webhook/webhook.go (1070 → 4 files):
- webhook.go: types, CRUD
- webhook_delivery.go: delivery and retry logic
- webhook_trigger.go: trigger management
- webhook_crypto.go: signatures, validation, private IP checks

api/tenant_handler.go (1068 → 3 files):
- tenant_handler.go: tenant CRUD, helpers
- tenant_handler_admin.go: admin assignment methods
- tenant_handler_schema.go: declarative schema methods

realtime/subscription.go (1030 → 3 files):
- subscription.go: SubscriptionManager core
- subscription_rls.go: RLS cache
- subscription_db.go: SubscriptionDB interface and impl

ai/user_kb_handler.go (1118 → 4 files):
- user_kb_handler.go: KB CRUD, permissions
- user_kb_handler_documents.go: document methods
- user_kb_handler_search.go: search methods
- user_kb_handler_entities.go: entity/graph methods

api/ddl_handler.go (1014 → 3 files):
- ddl_handler.go: core, validation, schema ops
- ddl_handler_table.go: table DDL methods
- ddl_handler_column.go: column DDL methods

mcp/tools/ddl.go (1087 → 3 files):
- ddl.go: shared helpers, schema tools
- ddl_table.go: table tools
- ddl_column.go: column tools

mcp/tools/branching.go (1034 → 3 files):
- branching_lifecycle.go: create/delete/reset/set-active
- branching_access.go: list/get/grant/revoke
Define SettingProvider interface in settings package, breaking the
coupling where 6+ non-auth packages imported auth just for SettingsCache.

- New: settings.SettingsCache with SettingProvider interface
- auth.SystemSettingsService implements SettingProvider via AsProvider()
- auth.SettingsCache kept as type alias for backward compat
- 10+ files updated to use settings.SettingsCache directly
- Middleware, email, API handlers no longer depend on auth for caching
Extract migration-related methods into connection_migrations.go (353 lines):
Migrate, runUserMigrations, scanMigrationFiles, getAppliedMigrations,
applyFilesystemMigration, logMigrationExecution, grantRolesToRuntimeUser,
validateMigrationSQL, migrationFile type.

Connection.go reduced from 1076 to 735 lines.
…rvice

Convert callers to use sub-services directly via existing getter methods:
- JWTManager: ValidateToken, ValidateTokenWithSecret, ValidateServiceRoleToken (18 sites)
- TokenBlacklistService: IsTokenRevoked, IsTokenRevokedWithClaims, RevokeAllUserTokens (15 sites)
- MFAService: SetupTOTP, EnableTOTP, VerifyTOTP, DisableTOTP, IsTOTPEnabled (10 sites)
- ImpersonationService: Start/Stop/GetActive/List/StartAnon/StartService (6 sites)
- PasswordResetService: Request/Reset/VerifyPasswordResetToken (6 sites)
- IdentityService: GetUserIdentities, LinkIdentity, UnlinkIdentity (3 sites)
- EmailVerificationService: SendEmailVerification, VerifyEmailToken (2 sites)
- OTPService: VerifyOTP, ResendOTP (2 sites)
- NonceService: Reauthenticate (1 site)
- Other: GetOAuthManager, GenerateTokensForSAMLUser, VerifyNonce, CleanupExpiredNonces

Methods kept: those with real orchestration logic (SignUp, SignIn, SignOut,
RefreshToken, GetUser, etc.) and sub-service getters.
@bartcode bartcode changed the title refactor: god-object decomposition + large file splits across 10 packages refactor: god-object decomposition, file splits, facade elimination, SettingsCache extraction May 13, 2026
bartcode added 4 commits May 13, 2026 11:07
…cade removal

GenerateTokensForSAMLUser was removed and the test now calls GenerateTokensForUser
which delegates to MFAService. But TestableService doesn't wire MFAService (needs DB).
Test now directly exercises jwtManager.GenerateTokenPair instead.
…etMetrics

Race detected between SetMetrics() (called during NewServer) and
concurrent reads from background goroutines (OAuthLogoutService cleanup).
Uses atomic.Pointer for safe concurrent access.
Two root causes for flaky webhook tests:

1. Cleanup used ExecuteSQL (app user) which is blocked by RLS on webhook
   tables. Changed to ExecuteSQLAsSuperuser so old webhooks/events are
   actually cleaned up between tests. Also drops existing triggers for
   clean state.

2. Tests relied solely on async LISTEN/NOTIFY delivery which can be
   unreliable in CI. Added synchronous ProcessWebhookEventsNow/CheckBacklogNow
   as fallback during the wait loop, ensuring delivery even if the
   notification is delayed or missed.
@bartcode bartcode merged commit 38281c5 into main May 13, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant