Public: anyone can read this; the crew can change it.

A SQLite file committed to a repository (.db, .sqlite, .sqlite3) renders as its tables and their first rows, read-only #10290

shipped production is serving it opened this has it
opened this

Serves P11 Files and data: every database reads in the browser. This is about a database file that sits in a repository. An app's live databases are #7579, which this does not wait for or replace.

Done when:

  • [x] src/web/render/kinds.ts has a sqlite kind for db, sqlite and sqlite3, confirmed by the magic SQLite format 3\0. A .db file without that header stays binary.
  • [x] A new src/web/render/sqlite.ts opens the blob in memory with bun:sqlite Database.deserialize, read-only. It never writes a temp file, never touches FORGE_APP_DATA, and closes the database before the response is sent.
  • [x] The page lists each table and view with its row count and columns. ?table=<name> shows that table's first 100 rows. The name is checked against the list from sqlite_master and is never interpolated unchecked. Every cell is escaped, and a BLOB shows as its size.
  • [x] There is no free-form SQL on this page.
  • [x] It is bounded. A file over the kind's inline limit (8 MB is suggested) offers Download. A corrupt or encrypted file falls back to Download with one sentence. The page never shows a 500, and the common case answers in under 50 ms.
  • [x] Tests build a small database in the test and commit it as a blob. They check the table list, the rows, an unknown ?table= (404 or back to the list), a cell holding <script> (escaped), a truncated file (falls back) and a non-SQLite .db (binary).
  • [x] bun scripts/design-lint.ts passes.

Files: src/web/render/kinds.ts, src/web/render/renderers.ts, a new src/web/render/sqlite.ts, and tests.

commented

Reviewed pull #10332 at its head: ticked src/web/render/kinds.ts has a sqlite kind for db, sqlite and sqlite3, confirmed by the magic SQLite format 3\0. A .db file without that header stays binary.; A new src/web/render/sqlite.ts opens the blob in memory with bun:sqlite Database.deserialize, read-only. It never writes a temp file, never touches FORGE_APP_DATA, and closes the database before the response is sent.; The page lists each table and view with its row count and columns. ?table=<name> shows that table's first 100 rows. The name is checked against the list from sqlite_master and is never interpolated unchecked. Every cell is escaped, and a BLOB shows as its size.; There is no free-form SQL on this page.; It is bounded. A file over the kind's inline limit (8 MB is suggested) offers Download. A corrupt or encrypted file falls back to Download with one sentence. The page never shows a 500, and the common case answers in under 50 ms.; Tests build a small database in the test and commit it as a blob. They check the table list, the rows, an unknown ?table= (404 or back to the list), a cell holding <script> (escaped), a truncated file (falls back) and a non-SQLite .db (binary).; bun scripts/design-lint.ts passes..

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs