Files
turborfq/bible/architecture.md
Mikhail Chusavitin c97d49e762 Add project Bible and consolidate documentation
- Create bible/ as single source of truth (architecture, API, frontend, installation, usage, security, roadmap)
- Verify and fix Bible against actual source code (API methods, endpoints, data flow)
- Trim README.md and CLAUDE.md to minimal stubs pointing to the Bible
- Remove duplicate claude.md (lowercase)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 14:11:57 +03:00

4.5 KiB

Architecture

Overview

TurboRFQ follows a thin MVC-like structure: a PHP backend exposes a JSON REST API consumed by a single-page vanilla-JS frontend. There is no ORM — SQL is built generically from information_schema metadata at runtime.

Browser
  └── index.html + app.js  (Tabulator grid, fetch calls)
        │  JSON over HTTP
        ▼
  public/index.php  (Slim 4 router + PHP-DI container)
        │
        ├── Db.php          — PDO factory (session credentials)
        ├── MetaService.php — schema / table / column metadata
        ├── DataService.php — all data operations
        └── BackupService.php — mysqldump wrapper
              │
              ▼
         MariaDB server  (user's own credentials)

Backend Services

Db.php — Database Layer

Responsibility Details
PDO factory Creates a PDO instance from credentials stored in the PHP session
Connection test Verifies credentials before storing them in session on login
Session auth Credentials live in $_SESSION; every request re-creates PDO

Key design decision: no connection pool, no persistent connections. Each API request opens a fresh PDO with the session user's credentials so MariaDB's own permission system is fully enforced.


MetaService.php — Metadata Service

Queries information_schema exclusively — never touches actual table data.

Method / responsibility What it does
Schema tree Lists schemas (databases) the user can see → table names within each
Column definitions Reads information_schema.COLUMNS: name, DATA_TYPE, COLUMN_TYPE, COLUMN_KEY, IS_NULLABLE, COLUMN_DEFAULT, EXTRA, COLUMN_COMMENT, ORDINAL_POSITION
Primary key detection Reads COLUMN_KEY = 'PRI' directly from information_schema.COLUMNS
Foreign key relationships Reads information_schema.KEY_COLUMN_USAGE where REFERENCED_TABLE_NAME IS NOT NULL
Editor type mapping Maps DATA_TYPE strings to Tabulator editor types

DataService.php — Data Service

All operations accept schema, table, and optional filter/pagination parameters.

Operation Mechanism
SELECT Parameterized SQL with LIKE %val% filters per column; LIMIT/OFFSET pagination; optional ORDER BY
INSERT Skips auto_increment columns; uses column list from MetaService
UPDATE WHERE clause built from primary key columns only
DELETE WHERE clause built from primary key columns only
DELETE batch Single-column PK: batched WHERE … IN (…) (batch size 500) inside one transaction. Composite PK: row-by-row within one transaction
CSV import Receives pre-parsed rows as a JSON array (CSV parsing is done on the frontend); each row is inserted inside a single transaction; per-row errors are collected without stopping the import
CSV export Runs a full SELECT (filters/sort applied), converts to CSV string using ; delimiter, returns JSON {csv, rowCount} — download is handled on the frontend
FK suggestions Queries referenced table for distinct values; search param filters with LIKE; without search limited to 1000 values

BackupService.php — Backup Service

Thin wrapper around the mysqldump CLI binary.

Feature Detail
Scope Single database or all databases
Output Temporary file streamed to browser as a download
Cleanup Temp file removed after streaming

Frontend Architecture

See frontend.md for details.


Data Flow — Typical Read Request

  1. User clicks a table in the sidebar.
  2. app.js calls GET /api/table/meta?schema=X&table=Y.
  3. Backend: MetaService queries information_schema, returns column definitions + PK info.
  4. app.js builds Tabulator column config from metadata.
  5. Tabulator calls POST /api/table/data with {schema, table, page, size, filters, sort} in the request body.
  6. Backend: DataService builds parameterized SELECT, returns {data, total}.
  7. Tabulator renders rows, activates column header filters and pagination.

Data Flow — Typical Write Request

  1. User edits a cell and clicks Save row.
  2. app.js sends POST /api/table/update with {schema, table, row, pk}.
  3. Backend: DataService builds UPDATE … SET … WHERE pk = ?, executes, returns affected rows.
  4. Frontend refreshes the row or shows an error.