# Features — dbdaigram (DB Diagram)

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

Status words used here:

- **Current** — present on `main` at `c6e0389` and reachable from the page or the API.
- **Documented only** — described in `README.md`, with no matching file or script in the tree.
- **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. The repository has two commits, both on 2026-07-07.

## 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. A missing user row ends the session. |
| Sign out | `api/auth.php` `logout` | Destroys the session and reloads the page. |
| Change password | `change_password`, Change password dialog | Current password checked. New password minimum 6 characters. The 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`. The README says to change it immediately. |
| 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` is true 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. Tables `users` and `posts`, enum `user_role`, one ref. |
| 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. Unique and increment are not drawn as their own marks. |
| Relationship lines | `_renderEdge` | Cardinality `1` / `*`. Hover highlight. Tooltip when the ref has a name or a delete/update action. |
| Drag tables | pointer handlers | Positions snap to an 8px grid and are stored in layout JSON. |
| Drag-to-connect | field 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. Extra lines are clipped and the last visible line gains 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`. Default light. |

### 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. Not blocked by parse errors. |
| Download MySQL | `assets/js/sql-export.js` | Blocked while parse errors exist. |
| Download PNG | `exportPNG` | 2× raster of the diagram bounds. Connection handles omitted. |

### Sharing and history

| Feature | Location | Notes |
|---|---|---|
| Diagram list | `diagrams.php` `list`, Open dialog | Own diagrams plus shared ones, newest `updated_at` first. |
| 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)`. Versions are not copied. |
| Delete diagram | `delete` | Owner, or admin if they can already open it. Confirm dialog. |
| Version list | `versions` | Newest id 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. On-delete and on-update are not copied from an inline ref. |

## 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` |
| Bitbucket repo | `overdrive/dbdaigram` |
| DNS | A record for `dbdesign.appnotify.co.za` to `102.37.22.152`, same host as `kb.appnotify.co.za` |
| TLS | Let's Encrypt in Dokploy after DNS propagates |
| 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 this repository

| Item | Notes |
|---|---|
| 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`. No `ports:` mapping. |
| `.env` example | `.env` is gitignored and dockerignored. No `.env.example` is committed. |

## Planned

No planned feature is written in the repository.

**Unknown / Requires Confirmation:** any roadmap that lives outside this repository, including work that may have continued on `overdrive/db_design` after `c6e0389`. See `project-plan.md`.

## 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, Bitbucket repo name, DNS, default-login reminder. |

Nothing on `main` is newer than `c6e0389`.

## Deprecated or removed

No removed feature is visible in the two-commit history. `.gitignore` at `HEAD` is two lines: `.env` and `.claude/`.
