Ordering Guarantees and Extension Resolvers Tighten a Go Admin Base Layer
Unordered database results are a silent data-corruption risk in any paginated API. Baking a primary-key fallback into the base layer removes a class of bugs that most projects never catch until production. The extension resolver pattern also decouples controller middleware from service signatures, letting teams pass session or tenant data without forking generated handler code.
Database-backed list queries now enforce an ORDER BY clause, defaulting to the primary key when no user sort is provided and always falling back to the primary key to prevent silent ordering drift across paginated results. A new BuildSerOpts method on the base controller collapses Omit, Select, and request parameters into a single call, cutting the List method setup from seven lines to one.
The base class also gains an ExtensionResolver — a function that accepts a Gin context and returns an arbitrary value — so controllers can inject custom session or business data into the service layer without rewriting handler methods. The resolver fires inside BuildSerOpts, populating a new Extension field on the service Options struct.
Finally, the Create path now automatically omits the primary key field from inserts when no explicit OmitFields are configured, using an existing model introspection method to identify the key.
Mandating a primary-key sort fallback at the framework level is a defensive design choice that eliminates an entire category of intermittent pagination bugs, yet it remains absent from most Go admin scaffolds.
Passing a resolver function rather than a static value for extension parameters keeps the base controller agnostic of concrete types while still allowing per-controller customization — a clean inversion-of-control pattern that avoids generics or interface bloat.
Collapsing Omit, Select, and request binding into BuildSerOpts trades explicit field-level visibility for call-site brevity; the risk is that future contributors may not realize which fields are being filtered unless the method name and action string convention are well-documented.