# Features — db_design (DB Diagram)

Evidence date: 2026-10-17. Source: `git@bitbucket.org:overdrive/db_design.git`, `main` at `992fbe3` (2026-07-07).

Status words used here:

- **Current** — present on `main` at `992fbe3` and reachable from the page or the API.
- **Documented only** — described in `README.md`, with no matching file or script in the tree.
- **Not in git** — named by the task-creation scan, and no file exists at that path.
- **Parsed, not drawn** — the DBML parser accepts it and the canvas does not render it as its own object.

There is no feature flagged in code as unfinished, and no comment that describes a feature that was not built. Git history does not show a removed feature.

## Current

### Accounts

| Feature | Location | Notes |
|---|---|---|
| Login form | `index.html`, `assets/js/app.js`, `api/auth.php` `login` | Username and password. Session cookie `DBDAIGRAM_SESS`. |
| Session resume | `api/auth.php` `me` | Page boot. Deleted user row ends the session. |
| Sign out | `api/auth.php` `logout` | Destroys the session and reloads. |
| Change password | `change_password`, Change password dialog | Current password checked. New password minimum 6 characters. Client checks the repeat field. |
| Seeded administrator | `api/db.php` | Created only when `users` is missing. Username `admin`, display name `Administrator`, password `admin123`, `is_admin = 1`. |
| List users | `users` | Admin session only. Ordered by username. |
| Create user | `create_user`, Manage users dialog | Username pattern, password length, optional display name, admin checkbox. |
| Reset another user's password | `reset_password` | Admin. Prompt in the dialog. No email. |
| Delete user | `delete_user` | Admin. Cannot delete the signed-in account. Owned diagrams cascade-delete. |
| Admin menu visibility | `enterApp` | Manage users is hidden unless `is_admin` on the user object returned at login or `me`. |

No feature edits an existing display name or flips `is_admin` after create.

### Diagram document

| Feature | Location | Notes |
|---|---|---|
| DBML editor | `assets/js/editor.js` | CodeMirror simple mode `dbml`. Vendored under `assets/vendor/`. |
| Sample document | `SAMPLE_DBML` in `assets/js/app.js` | Used when there is no last-diagram id, or that id fails to load. |
| Empty new document | `newDiagram(false)` | New button. Does not reload the sample. |
| Title field | `#diagramTitle` | Blank is saved as `Untitled diagram`. |
| Live parse | `assets/js/dbml-parser.js` | 250ms after the last edit. |
| Error list | `#errorBar` | First 20 errors. Click jumps to the line. |
| Autosave | `markDirty` / `save(false)` | About 1.8s after a change. No version row. |
| Explicit save | Save button, Ctrl/Cmd+S | `snapshot: true`. Toast confirms a version. |
| Unsaved warning | `beforeunload` | Browser prompt while dirty. |
| Save status | `#saveState` | Saving, Saved, Unsaved changes, Save failed. |
| Last opened diagram | `localStorage` `dbd_last_diagram` | This browser only. |

### Canvas

| Feature | Location | Notes |
|---|---|---|
| Table cards | `assets/js/canvas.js` `_renderTable` | Name, alias, fields, types, key mark, not-null asterisk, header colour, note tooltips. |
| Relationship lines | `_renderEdge` | Cardinality `1` / `*`. Hover highlight. Tooltip when the ref has a name or delete/update action. |
| Drag tables | pointer handlers | Positions stored in layout JSON. |
| Drag-to-connect | handles + `createRefFromUI` | Appends a `Ref` line. Infers `-`, `<`, or `>`. Refuses a duplicate single-column pair. |
| Table groups | `_renderGroups` | Dashed box from `TableGroup`. |
| Sticky notes | `_renderNote` | From top-level `Note`. Draggable. Default size 220×130. Text that does not fit is clipped with an ellipsis. |
| Zoom, pan, fit | `zoomAt`, `fit`, background drag | Zoom 0.15–3. Fit capped at 1.5. |
| Auto-arrange | `resetLayout` | Clears table and note positions, reflows, fits. |
| Jump to source | `onTableDblClick` | Double-click a table. |
| Editor width | `#splitter` | 220px to 70% of the window. Not saved. |
| Dark mode | `applyTheme` | `localStorage` `dbd_theme`. |

### Import and export

| Feature | Location | Notes |
|---|---|---|
| Paste MySQL DDL | `assets/js/sql-import.js`, Import SQL dialog | `CREATE TABLE` and `ALTER TABLE` foreign keys. Replace or append. |
| Enums from SQL | `emitDbml` | Column `ENUM` becomes a DBML enum `{table}_{column}_enum`. |
| Download DBML | `doExport('dbml')` | Exact editor buffer. |
| Download MySQL | `assets/js/sql-export.js` | Blocked while parse errors exist. |
| Download PNG | `exportPNG` | 2× raster of the diagram bounds. |

### Sharing and history

| Feature | Location | Notes |
|---|---|---|
| Diagram list | `diagrams.php` `list`, Open dialog | Own diagrams plus shared ones. |
| Share / unshare | `toggleShare`, `is_shared` | Owner only. One flag for the whole team, not a list of people. |
| Duplicate | `duplicate` | Private copy owned by the caller. Title suffix ` (copy)`. |
| Delete diagram | `delete` | Owner, or admin if they can already open it. Confirm dialog. |
| Version list | `versions` | Newest first. Shows who saved, when the user row still exists. |
| Restore version | `version_get`, History dialog | Snapshots the current text first, then writes the old DBML and layout. |
| Keep 50 versions | `update` when `snapshot` is set | Older rows for that diagram are deleted. |

### Hosting in the repository

| Feature | Location | Notes |
|---|---|---|
| PHP/Apache image | `Dockerfile` | `php:8.2-apache`, PDO MySQL, intl, rewrite, headers. |
| Compose stack | `docker-compose.yml` | Services `mysql` (`mysql:8.0`) and `app`. Named volume `mysql_data`. Health check on MySQL. |
| Env overrides | `api/config.php`, Compose | `DB_HOST`, `DB_PORT`, `DB_USER`, `DB_PASS`, `DB_NAME`. Compose also reads `DBDAIGRAM_MYSQL_PASSWORD` and `DBDAIGRAM_DB_NAME`. |
| Apache rewrite file | `.htaccess` | Enables the engine. Does not route the site through a front controller. |

## Parsed, not drawn

| Construct | Parser | Canvas / export |
|---|---|---|
| `Project` and `database_type` | `parseProject` | Not drawn. Not written into MySQL export. |
| `Enum` blocks | `parseEnum` | Not drawn as cards. Used when MySQL export maps a column type. |
| Index `type` setting | `parseIndexes` | Stored on the model. MySQL export does not emit an index type. |
| Inline column `ref:` | `resolveInlineRefs` | Becomes a normal ref and is drawn. |

## Documented only

These are in `README.md` and are not scripts in the repository:

| Item | What the README says |
|---|---|
| Local URL | `http://localhost/dbdaigram/` on the WAMP machine that hosts the files. |
| LAN publish steps | Change `Require local` in `httpd-vhosts.conf`, restart Apache, allow port 80. |
| Backup command | A `mysqldump.exe` path under `C:\wamp64\bin\mysql\mysql9.1.0\`. |
| Production URL | `https://dbdesign.appnotify.co.za/` |
| Dokploy project | `dbdaigram` |
| DNS | A record to `102.37.22.152` |
| Auto-deploy | Push to `main` on Bitbucket deploys via Dokploy |

This inspection did not call that URL. Whether DNS and Dokploy still match the README is **Unknown / Requires Confirmation**.

## Not in git

| Item | Notes |
|---|---|
| `sonar-project.properties` | Named in the 2026-09-28 discovery listing. Absent at `992fbe3`. |
| Tests | No test directory, PHPUnit config, or browser test. |
| CI | No `bitbucket-pipelines.yml` or other pipeline file. |
| Dependency manifest | No `composer.json` or `package.json`. |
| Dokploy/Traefik labels | Not in `docker-compose.yml`. |

## Planned

No planned feature is written in the repository. `.gitignore` mentions `node_modules/` with the comment "if added later". That is not a specification.

**Unknown / Requires Confirmation:** any roadmap that lives outside this repository.

## Recently changed

All product code arrived on 2026-07-07.

| Commit | Change |
|---|---|
| `334e2aa` | Application, Docker, Compose, first README. |
| `c6e0389` | README production section: URL, Dokploy project, DNS, default-login reminder. |
| `992fbe3` | Merge onto `overdrive/db_design` `main`. |

Nothing on `main` is newer than that merge.

## Deprecated or removed

No removed feature is visible in git history. The Bitbucket initial commit (`88d998d`) contained only a default `.gitignore`. The file at `HEAD` is the shorter ignore list added with the application.
