Files
ResolveSpec/pkg/security/breaking_changes.md
T

7.9 KiB
Raw Blame History

Breaking changes

Appended as each step of audit/sec_query_builder.plan.md lands.

Step 0: shared types moved to sectypes (no action needed)

The plain data types now live in pkg/security/sectypes and are aliased in pkg/security (types.go), so security.UserContext and sectypes.UserContext are the same type. Moved: UserContext, LoginRequest/Response, RegisterRequest, LogoutRequest, PasswordReset*, KeyType (+ constants), UserKey, CreateKey*, OAuthServerClient, OAuthCode, OAuthTokenInfo, Passkey* data structs, TwoFactorSecret, ColumnSecurity, RowSecurity (incl. GetTemplate).

Step 0b (totp): moved to pkg/security/totp

Import github.com/bitechdev/ResolveSpec/pkg/security/totp. No aliases (import cycle).

Old New
security.TwoFactorAuthProvider totp.AuthProvider
security.TwoFactorConfig / DefaultTwoFactorConfig totp.Config / totp.DefaultConfig
security.TOTPGenerator / NewTOTPGenerator totp.Generator / totp.NewGenerator
security.GenerateBackupCodes totp.GenerateBackupCodes
security.MemoryTwoFactorProvider / NewMemoryTwoFactorProvider totp.MemoryProvider / totp.NewMemoryProvider
security.TwoFactorAuthenticator / NewTwoFactorAuthenticator totp.Authenticator / totp.NewAuthenticator

totp.NewAuthenticator takes a totp.BaseAuthenticator (Login, Logout, Authenticate) instead of security.Authenticator; any security.Authenticator satisfies it.

DatabaseTwoFactorProvider stays in security (it now calls the lookup TOTPStore). Core imports totp, so totp must not import security.

Step 0b (providers, first part): moved to pkg/security/providers

Import github.com/bitechdev/ResolveSpec/pkg/security/providers. Names unchanged, no aliases (import cycle).

Old New
security.HeaderAuthenticator / NewHeaderAuthenticator providers.HeaderAuthenticator / providers.NewHeaderAuthenticator
security.ConfigKeyStore / NewConfigKeyStore providers.ConfigKeyStore / providers.NewConfigKeyStore
security.KeyStoreAuthenticator / NewKeyStoreAuthenticator providers.KeyStoreAuthenticator / providers.NewKeyStoreAuthenticator
security.ConfigColumnSecurityProvider / NewConfigColumnSecurityProvider providers.ConfigColumnSecurityProvider / providers.NewConfigColumnSecurityProvider
security.ConfigRowSecurityProvider / NewConfigRowSecurityProvider providers.ConfigRowSecurityProvider / providers.NewConfigRowSecurityProvider

The SHA-256 key hash helper is now sectypes.HashKey. The database-backed providers (DatabaseAuthenticator, JWTAuthenticator, DatabaseKeyStore, DatabaseColumn/RowSecurityProvider) stay in security; they call the lookup stores (see step 5).

Additions (no action needed)

  • common.SQLDBProvider (SQLDB() *sql.DB) is implemented by the bun, gorm and pgsql adapters (not their transaction adapters). lookup.FromDatabase(common.Database) uses it, plus the adapter's DriverName(), to get the *sql.DB and dialect name.

Steps 2–3: lookup dialects and procedure backend

  • New lookup/dialect (postgres, sqlite, mysql, mssql) and lookup/procedure packages. No existing exported security API changed in these steps.
  • Procedure-mode code paths in DatabaseAuthenticator, JWTAuthenticator, the policy providers, DatabaseKeyStore, DatabaseTwoFactorProvider and DatabasePasskeyProvider now delegate to lookup/procedure. Error texts are unchanged.
  • Behaviour change (improvement): these procedure paths now reconnect once on a closed *sql.DB (JWT logout, key create, TOTP, passkey, OAuth previously used the handle directly).

Step 4: lookup/direct backend

  • New lookup/direct package: table-backed stores for auth, keys, OAuth (client + user), passkey, TOTP and policy, built from lookup.Schema and the dialect. Nothing in pkg/security calls it yet (wiring happens in step 5), so no existing API changes here.
  • Direct LoginAPIKey is new: header_api / api keys only; unknown, expired, inactive and wrong-type keys (and inactive users) all return lookup.ErrInvalidAPIKey.
  • Policy tables (sec_group_members, sec_column_rules, sec_row_rules) are required for the direct policy store; PolicyOptions.NoGroups skips the membership table.
  • Direct behaviour that changes when step 5 switches over: login, register, refresh, API-key login, password reset and passkey login now write in one transaction; Keys.Create stores NULL (not the text null) for empty scopes/meta; OAuth code exchange consumes the code atomically; a non-numeric row-security user reference is an error instead of loading no rules.

Step 5: pkg/security uses lookup

pkg/security no longer contains SQL (guarded by TestCoreContainsNoSQL). Every database call goes through a lookup.Provider built by lookup/backends.New.

Removed (replaced by lookup.Config: Dialect, Mode, Overrides, Procs, Schema):

  • Types and functions SQLNames, DefaultSQLNames, MergeSQLNames, ValidateSQLNames, TableNames (+ Default/Merge/Validate), KeyStoreSQLNames, KeyStoreTableNames (+ same), QueryMode, ModeAuto/ModeProcedure/ModeDirect, ErrDirectModeUnsupported.
  • Options fields SQLNames, TableNames, QueryMode on DatabaseAuthenticatorOptions, DatabaseKeyStoreOptions, DatabasePasskeyProviderOptions; replaced by Lookup lookup.Config and LookupProvider *lookup.Provider.
  • Builders WithQueryMode, WithTableNames on JWTAuthenticator, the column/row providers and DatabaseTwoFactorProvider; replaced by WithLookup(cfg) and WithLookupProvider(p).
  • The variadic names ...*SQLNames argument of NewJWTAuthenticator, NewDatabaseColumnSecurityProvider, NewDatabaseRowSecurityProvider and NewDatabaseTwoFactorProvider.

Behaviour changes:

  • Default mode is per dialect: stored procedures on Postgres, direct SQL elsewhere. ModeAuto (probe pg_proc once per procedure) is now opt-in via lookup.ModeAuto; it used to be the default everywhere. Procedure mode on a non-Postgres dialect is a configuration error.
  • A bad lookup configuration no longer panics or is silently ignored: the component logs it and every call returns the error.
  • Dialect is detected from the driver; if detection fails the postgres dialect is assumed.
  • Column and row security now work in direct mode (tables sec_group_members, sec_column_rules, sec_row_rules); they used to return ErrDirectModeUnsupported. WithNoGroupTables() skips the group membership table.
  • LoginWithAPIKey works in direct mode; DatabaseAuthenticator.Logout now clears the session cache in every mode (direct mode used to skip it).
  • Authenticate now holds the session lookup in the configured backend only; the activity update no longer silently falls back to a direct write when the procedure is missing.
  • Direct-mode behaviour changes listed under step 4 take effect here.

Step 6: schemas and docs

  • SQL files moved from pkg/security/ to pkg/security/lookup/ (database_schema.sql, keystore_schema.sql). database_schema_sqlite.sql is superseded by lookup/ddl/sqlite.sql (now also includes sec_group_members, sec_column_rules, sec_row_rules).
  • New lookup/ddl package: embedded reference table schemas for postgres, sqlite, mysql, mssql (ddl.SQL(dialect), ddl.Statements(dialect)). ddl/postgres.sql is tables only and uses base64 / JSON text columns, so it cannot be combined with the procedure schema (database_schema.sql, bytea / text[] columns) on the same tables.
  • security.ApplyTxSettings is unchanged; its SQL moved to lookup.ApplyTxSettings(ctx, tx, settings).
  • Removed the unexported password.go from pkg/security (bcrypt helpers live in lookup/direct).
  • README.md, KEYSTORE.md and the root README describe lookup.Config instead of QueryMode, SQLNames and TableNames.