Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cursor/rules/sql-editor-agent-memory.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ FoxSchema = schema diff/migration + SQL Editor + workspaces. Destinations checkl
- Admins see all workspaces but open one only by joining (#495 / Admin → Workspaces).
- Public vs private: signed-in users can join public (#496).
- Isolation proven e2e both ways (#497).
- UI: `workspace-switcher`, `workspace-menu`, `workspace-settings`, profile embeds WorkspaceMenu.
- UI: rail `WorkspaceRailButton` (under the Fox mark) opens `WorkspaceMenu` / settings; launch sessions hide it. Profile menu does not list workspaces.

## Auth / admin (Claude + follow-ons)
- **Launch sessions** (#490): `foxschema open` one-time local launch token → session with `launch: true`; skip signup wizard; profile **"Create your account"**; registration grace then blocks; admin/SSO gated until registered.
Expand Down
13 changes: 11 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ connection grant follows the connection’s workspace.
(`GET /api/workspaces/discover`, `POST /:id/join`). Join role is viewer or
editor, never owner. An invite never adds: the invitee accepts
(`POST /api/workspaces/invites/:id/accept`, 14-day TTL).
- **UI.** One workspace is open. `WorkspaceRailButton` sits under the Fox mark
on the activity rail (not the profile menu) and opens the same
`WorkspaceMenu` (switch, invites, settings, public join, create). A launch
session hides it. Switching is still `POST /api/workspaces/:id/select` then
reload. Editor tabs/scripts in this browser are keyed by workspace id
(`editorWorkspaceStorage.ts`); the unscoped blob is claimed once by the first
workspace the rail sees.

Startup `backfillWorkspaces` gives each account a personal workspace and moves
rows that still have `workspace_id` null or `'local'` into their author’s.
Expand Down Expand Up @@ -285,8 +292,10 @@ largest files when it fails. Everything else loads when it is used:
`prefetchView` on hover or focus, so a view's code is usually already loaded by the time
the click lands.
- **Panels that open on a click** (admin console, credentials, applies history, new
connection) are `lazy()` inside `MountWhenOpened`. That mounts a panel on its first open
and keeps it mounted afterwards, so its state survives closing exactly as before.
connection, the workspace menu) are `lazy()` inside `MountWhenOpened`. That mounts a
panel on its first open and keeps it mounted afterwards, so its state survives
closing exactly as before. The workspace button is shell, not a view — it is
not in the view registry.
- **Heavy libraries** (sql-formatter, Prettier, faker, lodash, date-fns, zod, ajv) load
through `shared/lib/loadOnce.ts`: one shared promise, retried after a failure. A
component that needs one while rendering uses `useLoaded(loader)`, which re-renders
Expand Down
14 changes: 7 additions & 7 deletions docs/CODE_MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ modules/ One folder per domain, named to match the frontend feature
| `lokee-weave` | Content-addressed schema versioning and revert |
| `sql-editor` | FoxScript parsing, code cells, SELECT aliasing, the SQL subset |
| `access` | Permission intent, effective access, GRANT/REVOKE and account DDL (facades; emitters live in `providers/<dialect>`) |
| `utilities` | DBA queries: server insights, index fragmentation, backup/restore command builders |
| `utilities` | DBA queries: server insights, index fragmentation (`isSafeIndexFragmentationCustomSql`: one read-only SELECT; Db2 defrag is `providers/db2/db2.index-fragmentation.ts`), backup/restore command builders |

`dialect` and `sql-text` are the foundations: the other folders build on
them, never the reverse.
Expand Down Expand Up @@ -140,7 +140,7 @@ database/ The metadata store and its migrations.

| Folder | What it covers |
|---|---|
| `access` | Database permission inspection and DBA utilities |
| `access` | Database permission inspection and DBA utilities. Index-fragmentation custom SQL is gated read-only in `index-fragmentation.service.ts` (same tokenizer as `/sql/execute`). |
| `system` | Health and version, updates, app info, the metadata-database probe, activity |
| `admin` | Users and roles, secrets, cloud credentials, policy |
| `backup` | Per-user backup defaults (`GET`/`PUT /api/backup-settings`). Commands themselves are built in `@foxschema/sql` (`modules/utilities/backup.ts` + `providers/<d>/*.backup.ts`); the panel runs only a server-side SQL backup, after confirmation, and lists the backups the server recorded (`backupHistoryQuery`); restores are never run. |
Expand All @@ -153,10 +153,10 @@ database/ The metadata store and its migrations.
| `history` | Schema history and revert (Lokee Weave) |
| `migration` | Applying DDL migrations, and their run history |
| `schema` | Reading a schema |
| `sql-editor` | SQL editor, code cells, sandboxed execution |
| `sql-editor` | SQL editor, code cells, sandboxed execution. `sql-execute.service.ts` (`runStatements`) applies the saved schema (`adapter.setCurrentSchema`) then optionally `BEGIN`s one transaction for the batch; paging wrap is `sql-page-wrap.service.ts`. |
| `users` | Profile, preferences, first-run wizard |
| `workspaces` | Shared workspaces: create, switch, members, invites, public or private (`/api/workspaces`). Which workspace a request acts in is `platform/workspaces`. Admins list every workspace (`GET /all`) and open one only by joining. |
| `workflow` | Workflow engine settings and health; the engine proxy (an allowlist of engine routes, each behind a `workflow.*` permission); saved-connection grants; and the token-guarded internal routes the engine calls to resolve a granted connection and read its settings. Runbook: [workflow.md](workflow.md). |
| `workflow` | Workflow engine settings and health; the engine proxy (an allowlist of engine routes, each behind a `workflow.*` permission); saved-connection grants; and the token-guarded internal routes the engine calls to resolve a granted connection and read its settings. Save, run, and steering (cancel / resume / answer a paused run) refuse a connection the caller cannot use in this workspace (`WorkflowConnectionGrants.notUsableBy`). Runbook: [workflow.md](workflow.md). |

Every feature folder has an `index.ts` exporting its `ServerFeatureModule`
and its public API; other features import only that
Expand Down Expand Up @@ -245,10 +245,10 @@ the page-epoch guard, bookmarks and recents, SQL variables.
| `lokee-weave` | Schema history graph and version compare (Snapshots workspace) |
| `migrations` | Migration run history (Applies on the rail) |
| `schema-diff` | Diff rendering shared by compare and history |
| `sql-editor` | SQL editor, its store, results grid, data peek, the shared Monaco setup (`monaco.ts`) (Index/Clone/Query files live in `utilities`) |
| `sql-editor` | SQL editor, its store (`oneTransaction`, `selectOnlyConnection` so the schema browser's connection is the one Run hits), results grid, data peek, the shared Monaco setup (`monaco.ts`) (Index/Clone/Query files live in `utilities`) |
| `utilities` | Own workspace: clone table, index management, backup & restore commands, server insights, query files, DB users & grants |
| `workflow` | Workflow designer (canvas, inspector, triggers, SQL and script editors), runs, variables, credentials and engine settings — through the engine proxy, plus linking saved connections to workflows |
| `workspaces` | Switcher and settings in the profile menu: create, invite, join public, members. Admin → Workspaces lists every workspace; opening one is joining. |
| `workflow` | Workflow designer (canvas, inspector, triggers, SQL and script editors), runs (`RunsPanel` cancel / answer a paused human gate), variables, credentials and engine settings — through the engine proxy, plus linking saved connections to workflows |
| `workspaces` | The rail's workspace button (`WorkspaceRailButton`) and the menu it opens: switch, invite, join public, members, settings. Admin → Workspaces lists every workspace; opening one is joining. Editor localStorage is keyed by workspace (`shared/lib/editorWorkspaceStorage.ts`). |

## Where does my change go?

Expand Down
4 changes: 3 additions & 1 deletion docs/architecture/FEATURE-MODULE-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ checks access itself; its button follows its nav item's permission (`navId`).

The rail, the lazy view, prefetch-on-hover, the "you lost access, go home"
redirect and the view's part of the top toolbar (`toolbar: { start, end, below }`)
all read this entry. Adding a view touches no shell file.
all read this entry. Adding a view touches no shell file. The workspace button
under the Fox mark is shell (`WorkspaceRailButton`), not a view — do not add it
to the view registry.

Keep components local until a second feature needs them; then move the
product-neutral part to `shared/`, not to another feature.
Expand Down
28 changes: 28 additions & 0 deletions docs/releases/UNRELEASED.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,34 @@
Notes for the next release. At ship time, rename this file to that version's
`RELEASE_<version>.md` and use it as the GitHub Release body.

## One workspace on the rail

The workspace you are in sits under the Fox mark on the left rail — switch,
invites (amber dot), settings, public join, and create. It is no longer inside
the profile menu. A launch session hides the button. SQL editor tabs in this
browser follow the workspace.

## SQL Editor: the schema you are browsing, and one transaction

Run applies the saved connection's schema (`CURRENT SCHEMA` / `search_path`)
so unqualified names resolve to the tables the explorer shows, not the
database user's default. Picking a connection in the explorer checks that
destination alone. **One transaction** wraps a multi-statement SQL run per
destination; a failure rolls it back. Code cells and `-- @set` stay statement
by statement.

## Workflow: steer a paused run; connections stay in their workspace

**Runs** can cancel a live job and answer **Ask a person**. Saving or running
a workflow that names another workspace's connection is refused — the engine
is install-wide; the connection is not.

## Index custom SQL is read-only; Db2 reorgs the table's indexes

A custom fragmentation probe must be one `SELECT`. GRANT / REVOKE scripts stop
at the first failure. Db2 defrag reorganises every index on the table, quoting
catalog names.

## Left-rail views

- **Snapshots** is its own left-rail view (schema history / Lokee). **Applies**
Expand Down
Loading
Loading