GORM Studio (Database Browser)
A database browser that runs inside your API, reached at /studio. Tables, rows, relationships, a query box, import and export. It is mounted in every Grit project, because the moments you most want to look at the data are a staging container and a customer's install, and those are exactly where a desktop database client is not.
What it gives you
Schema Discovery
Reads the database and your GORM structs, and shows you where they disagree
Browse & Filter
Paginated grid, column sorting, full-text search
Editing Records
Create, edit and delete through forms, with bulk delete
Relationships
Follow a foreign key instead of copying an id into another query
SQL Editor
Read/write detection and DDL blocking, and it can be turned off entirely
Export
Schema as SQL, JSON, YAML, DBML or an ERD; data as JSON, CSV or INSERTs
Import
Data from JSON, CSV, SQL or Excel; schema from SQL, JSON, YAML or DBML
Go Code Generation
Structs from the schema, and tables from a .go file
Access Control
Row scoping, hidden and read-only tables, and an audit logger
Authentication
A real login page, and the token never touches browser storage
grit doctor fails when it is mounted with no login or on a default password.Every feature, in detail
Schema Discovery
Studio reads your schema from two places: the database itself, and your GORM model structs by reflection. Having both is the useful part, because the gap between them is where migration bugs live. A column the struct declares and the database does not have is a migration that never ran; a column the database has and no struct mentions is one a DropColumn forgot.
SQLite, PostgreSQL and MySQL are supported. SQLite goes through a pure-Go driver, so there is no CGO and no build toolchain to install.
Browse and Filter
A paginated grid per table, with column sorting and full-text search across the row. It is a data grid rather than a report builder: the question it answers well is "what does this row actually contain", which is the question you usually have at the point you reach for a database client.
Editing Records
Create, edit and delete through modal forms, and select several rows for a bulk delete. Deletion goes through a styled confirmation rather than the browser's own confirm(), which matters more than it sounds: the native dialog is easy to dismiss by reflex.
Writes here bypass your handlers and therefore your validation, your hooks and your audit log. That is the point when you are repairing data, and a hazard when you are not, which is what the read-only policy below is for.
Relationship Navigation
Foreign keys are shown as links you can follow, across has_one, has_many, belongs_to and many_to_many. In practice this is what makes the tool fast to use: tracing an order to its customer to their addresses is three clicks rather than three queries with ids copied between them.
Raw SQL Editor
A query box, with read and write detected automatically and DDL blocked, so a stray DROP TABLE is refused rather than run. A table listed as hidden is refused here too, not only in the grid.
It cannot be row-scoped, because arbitrary SQL cannot be. If you use the scoping below to keep one tenant out of another's data, turn the SQL editor off with DisableSQL: true, or the scoping is decoration.
Export
Schema as SQL DDL, JSON, YAML, DBML, or an ERD diagram as PNG or PDF. Data as JSON, CSV (zipped, one file per table) or SQL INSERT statements.
CSV export escapes formula injection, so a cell beginning = or + arrives in a spreadsheet as text rather than as something that runs. A field an attacker controls is an attack on whoever opens the export, which is usually not the person who was attacked.
Import
Data from JSON, CSV, SQL or Excel. Schema from SQL, JSON, YAML or DBML, which creates the tables. Useful for seeding an environment from a sample, and the fastest way to ruin one, so it belongs behind the same authentication as everything else here.
Go Code Generation
Two directions. Generate Go structs from an existing schema, with the GORM tags that match, which is how you adopt a database you did not create. Or upload a .go file of struct definitions and have the tables created from it.
In a Grit project you usually want grit generate resource instead, which writes the model plus the service, handler, routes, schemas, types and admin screen. Studio's generator gives you the struct alone.
Access Control
Three controls, and they compose:
studio.Mount(router, db, models, studio.Config{DisableSQL: true, // the SQL editor cannot be scopedScope: func(c *gin.Context, table string, tx *gorm.DB) *gorm.DB {if table == "orders" {return tx.Where("tenant_id = ?", c.GetString("tenant_id"))}return tx},TablePolicy: studio.TablePolicy{Hidden: []string{"payment_tokens"}, // never exposedReadOnly: []string{"audit_log"}, // browsable, not editable},AuditLogger: studio.DefaultAuditLogger, // log every mutation})
Scope narrows what a request may see, per table, from whatever the request carries. Hidden removes a table entirely, including from the SQL editor. ReadOnly lets a table be browsed but not changed, which is the right setting for anything whose value is that nobody edited it: an audit log, an append-only ledger. AuditLogger records every mutation made through Studio, because a change made here leaves no trace in your application's own log.
Authentication
With AuthMiddleware configured, Studio serves a themed login page rather than the browser's native auth popup. The credential token is kept in memory only and never written to browser storage, so a refresh asks again and a shared machine does not keep your database open for the next person.
In a Grit project this is GORM_STUDIO_USERNAME and GORM_STUDIO_PASSWORD. The scaffold adds the middleware only when both are set, which means forgetting one leaves Studio open; grit doctor reports exactly that, and reports a default password as an error in production.
Turning it off
GORM_STUDIO_ENABLED=false does not mount it at all. Worth doing on a deployment where nobody is going to use it: the safest console is the one that is not there.
