feat(ui): TDS migration stage 3 — integration fixes, legacy removal, docs
Lint / JS (eslint) (pull_request) Successful in 10s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / JS Security (npm audit) (pull_request) Failing after 10s
Test / JS Tests (jest) (pull_request) Successful in 14s
Lint / JS (eslint) (push) Successful in 11s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / JS Security (npm audit) (push) Failing after 11s
Test / JS Tests (jest) (push) Successful in 10s
Lint / JS (eslint) (pull_request) Successful in 10s
Lint / Notify on failure (pull_request) Skipped
Lint / Deploy (pull_request) Skipped
Security / JS Security (npm audit) (pull_request) Failing after 10s
Test / JS Tests (jest) (pull_request) Successful in 14s
Lint / JS (eslint) (push) Successful in 11s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Skipped
Security / JS Security (npm audit) (push) Failing after 11s
Test / JS Tests (jest) (push) Successful in 10s
- Fix design-system class names that do not exist in base.css (.lt-alert--error, .lt-form-hint); add shared .lt-modal-lg, .lt-field-error and .is-invalid rules - Remove public/index.html and the public/base.js symlink - package.json: start script, correct main - README: vendored design system, Web UI section, new env vars, read-only dev mode Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HamVMDrA8RqhyxmUHgiqRp
This commit is contained in:
@@ -12,7 +12,23 @@ A distributed workflow orchestration platform for managing and executing complex
|
||||
|
||||
## Styling & Layout
|
||||
|
||||
PULSE uses the **LotusGuild Terminal Design System**. For all styling, component, and layout documentation see:
|
||||
PULSE uses the **LotusGuild Terminal Design System**. The design system is **vendored** into this
|
||||
repo at `public/web_template/` (`base.css`, `base.js`, `VERSION`) and served from `/web_template/*`,
|
||||
so the app has no runtime dependency on a sibling checkout. `public/web_template/VERSION` records
|
||||
the design-system version, upstream short SHA, and sync date; asset URLs are cache-busted with it.
|
||||
|
||||
Update the vendored copy with:
|
||||
|
||||
```bash
|
||||
scripts/sync-web-template.sh <path-to-web_template-checkout>
|
||||
```
|
||||
|
||||
The script copies `base.css`/`base.js` as regular files (never symlinks) and rewrites `VERSION`.
|
||||
Never hand-edit `public/web_template/` — it is excluded from ESLint and overwritten on every sync.
|
||||
Pulse-local gaps in the design system live in `public/assets/app.css` (currently `.lt-modal-lg`,
|
||||
`.lt-field-error`, `.is-invalid`) and are candidates for upstreaming.
|
||||
|
||||
Reference documentation:
|
||||
|
||||
- [`web_template/README.md`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/README.md) — full component reference, CSS variables, JS API
|
||||
- [`web_template/base.css`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/base.css) — unified CSS (`.lt-*` classes)
|
||||
@@ -20,9 +36,39 @@ PULSE uses the **LotusGuild Terminal Design System**. For all styling, component
|
||||
- [`web_template/aesthetic_diff.md`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/aesthetic_diff.md) — cross-app divergence analysis and convergence guide
|
||||
- [`web_template/node/middleware.js`](https://code.lotusguild.org/LotusGuild/web_template/src/branch/main/node/middleware.js) — Express auth, CSRF, CSP nonce middleware
|
||||
|
||||
**Pending convergence items (see aesthetic_diff.md):**
|
||||
- Extract inline `<style>` from `public/index.html` into `public/style.css` and extend `base.css`
|
||||
- Use `lt.autoRefresh.start(refreshData, 30000)` instead of raw `setInterval`
|
||||
## Web UI
|
||||
|
||||
The UI is server-rendered with EJS. Every route renders `views/pages/<page>.ejs` into the shared
|
||||
chrome in `views/layout.ejs` (nav, header, WebSocket status dot, theme toggle, command palette).
|
||||
|
||||
| Route | Page | View | Page module |
|
||||
|---|---|---|---|
|
||||
| `/` | Dashboard | `views/pages/dashboard.ejs` | `public/assets/pages/dashboard.js` |
|
||||
| `/workers` | Workers | `views/pages/workers.ejs` | `public/assets/pages/workers.js` |
|
||||
| `/workflows` | Workflows | `views/pages/workflows.ejs` | `public/assets/pages/workflows.js` |
|
||||
| `/executions` | Executions | `views/pages/executions.ejs` | `public/assets/pages/executions.js` |
|
||||
| `/quick` | Quick Command | `views/pages/quick.ejs` | `public/assets/pages/quick.js` |
|
||||
| `/scheduler` | Scheduler | `views/pages/scheduler.ejs` | `public/assets/pages/scheduler.js` |
|
||||
|
||||
Scripts load in a fixed order: `/web_template/base.js` → `/assets/app.js` → `/assets/pages/<page>.js`.
|
||||
`app.js` owns the shell (`window.Pulse`: action registry, event bus, `Pulse.confirm`, formatters,
|
||||
WebSocket, the single 30 s auto-refresh) and each page module registers itself with:
|
||||
|
||||
```js
|
||||
Pulse.registerPage({ name, init(), refresh(), onEvent(type, data) /* return true if handled */ });
|
||||
```
|
||||
|
||||
Page modules never attach their own listeners for UI actions — they register handlers under their
|
||||
own action prefix (`dash:`, `wk:`, `wf:`, `ex:`, `qc:`, `sc:`) and the markup wires them up with
|
||||
`data-action` / `data-change-action` / `data-input-action` / `data-submit-action` attributes that
|
||||
`app.js` delegates. DOM ids are likewise prefixed per page. All dynamic strings go through
|
||||
`Pulse.esc`, and destructive actions use the themed `Pulse.confirm` (no native `confirm()`/`alert()`).
|
||||
|
||||
**Content Security Policy:** pages are served under a strict nonce-based CSP (helmet), including
|
||||
`script-src-attr 'none'`. There are **no inline `<script>` blocks without a nonce and no inline
|
||||
event handler attributes** anywhere in `views/` or `public/assets/`; anything added there must
|
||||
follow the same rule or the browser will refuse to run it. Set `PULSE_CSP_REPORT_ONLY=1` to switch
|
||||
the policy to report-only (violations are reported to `/csp-report` and logged) while debugging.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -311,8 +357,30 @@ DB_USER=pulse_user # Database user
|
||||
DB_PASSWORD=<password> # Database password
|
||||
WORKER_API_KEY=<api-key> # Worker authentication key
|
||||
EXECUTION_RETENTION_DAYS=30 # Auto-cleanup retention (default: 30)
|
||||
|
||||
# Web UI (all optional)
|
||||
APP_NAME=PULSE # Header/boot/title app name (default: PULSE)
|
||||
APP_SUBTITLE=<text> # Header subtitle (default: "Worker Orchestration // LotusGuild")
|
||||
PULSE_CSP_REPORT_ONLY=1 # Serve the CSP report-only instead of enforcing it
|
||||
PULSE_DEV_READONLY=1 # Local dev guard: disable all background writes (see below)
|
||||
DISABLE_BACKGROUND_JOBS=1 # Alias for PULSE_DEV_READONLY
|
||||
```
|
||||
|
||||
### Local development against a real database
|
||||
|
||||
Running a local instance against the production MariaDB is safe only with the read-only guard on:
|
||||
|
||||
```bash
|
||||
PULSE_DEV_READONLY=1 PORT=8099 HOST=127.0.0.1 npm start
|
||||
```
|
||||
|
||||
`PULSE_DEV_READONLY=1` (alias `DISABLE_BACKGROUND_JOBS=1`) disables every background writer, so a
|
||||
dev instance can never mutate shared state behind your back: stale-execution recovery at startup,
|
||||
the old-execution cleanup job (startup call and interval), the scheduled-command processor
|
||||
(startup call and interval), and the stale-worker offline sweep. Each skip is logged at startup
|
||||
alongside a `PULSE_DEV_READONLY IS ON` banner. The guard covers background jobs only — API routes
|
||||
still write, so avoid destructive actions in the UI when you are pointed at production data.
|
||||
|
||||
**Worker (.env):**
|
||||
```bash
|
||||
WORKER_NAME=pulse-worker-01 # Unique worker name
|
||||
|
||||
Reference in New Issue
Block a user