diff --git a/.readme/static/borrowed/Icon_Stackable.svg b/.readme/static/borrowed/Icon_Stackable.svg new file mode 100644 index 00000000..35e132a9 --- /dev/null +++ b/.readme/static/borrowed/Icon_Stackable.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/.readme/static/borrowed/stackable_overview.png b/.readme/static/borrowed/stackable_overview.png new file mode 100644 index 00000000..0ef39130 Binary files /dev/null and b/.readme/static/borrowed/stackable_overview.png differ diff --git a/AGENTS.md b/AGENTS.md index 981cc176..f365ec4a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,41 +1,63 @@ -# Instructions for Claude +# Instructions for AI Agents ## Project Overview -This is the **Stackable Unified Data Platform UI** - a SvelteKit application that serves as the first module of a unified platform UI for Stackable's data infrastructure. The initial module is a **Trino SQL query editor** with SSO, authorisation, and catalogue browsing. +**Stackable Cockpit** is a SvelteKit application that serves as the web UI of the Stackable Data Platform. It is built as a set of modules behind a shared OIDC login: -The application is designed with a **plugin/module architecture** so future Stackable services (trino-lb queue management, etc.) can be integrated as additional modules. +- **Trino** — SQL editor (Monaco + ANTLR grammar) with catalogue browser and query lifecycle management +- **Storage** — S3 file browser with preview, upload/download, archives, search and transfers (HDFS is a stub) +- **Settings** — user-managed storage connections, stored in PostgreSQL +- **Dashboard** with per-user bookmarks (stored in PostgreSQL) across modules + +The Trino connection is either fixed via `STACKABLE_COCKPIT_TRINO_URL` or entered per user on `/trino` and held in server memory. + +Further modules are added the same way: a route under `src/routes/(app)//`, server code under `src/lib/server//`, components under `src/lib/components//`. ## Tech Stack -- **SvelteKit** with **Svelte 5** - Always use Svelte 5 syntax with runes (`$props`, `$state`, `$derived`, etc.) -- **Tailwind CSS v4** - No tailwind.config.js file (uses CSS-based configuration) -- **DaisyUI** - Use DaisyUI components/classes where possible for consistent UI - This is DaisyUI v5! A lot of classes you know about DON'T EXIST anymore. Check if needed -- **Icon Library** - Use **unplugin-icons** with the `material-symbols` icon set (`@iconify-json/material-symbols`). Import icons as virtual Svelte components: `import IconMenu from 'virtual:icons/material-symbols/menu'`. -- **Monaco Editor** - SQL editor component (dynamic import, SSR-safe) -- **ANTLR4** (antlr4ng) - Trino SQL parsing for syntax highlighting and code completion -- **zod & superforms** - All forms are to use zod & superforms -- **Generic OIDC** (openid-client) - Authentication via any OIDC provider -- **OPA** - Authorisation / feature visibility -- **prom-client** - Prometheus metrics, exposed at `/metrics` +- **SvelteKit** with **Svelte 5** — always use runes (`$props`, `$state`, `$derived`, ...), adapter-node +- **Tailwind CSS v4** — CSS-based configuration in `src/app.css`, no `tailwind.config.js` +- **DaisyUI v5** — use its components/classes where possible. Many v4 classes no longer exist; check if needed +- **Icons** — `unplugin-icons` with the `material-symbols` set: `import IconMenu from 'virtual:icons/material-symbols/menu'` +- **Monaco Editor** + **ANTLR** (`antlr-ng` generator, `antlr4ng` runtime, `antlr4-c3` completion) for Trino SQL +- **zod + sveltekit-superforms** — all forms +- **better-auth** with the `genericOAuth` plugin — authentication via any OIDC provider +- **PostgreSQL + Drizzle ORM** — users/sessions, storage connections, bookmarks, recent searches, download manifests. See `docs/DATABASE.md` +- **AWS SDK v3** — S3 storage access +- **Paraglide-JS v2** — i18n +- **pino** — logging; **prom-client** — Prometheus metrics at `/metrics` ## Project Structure -This is a **single SvelteKit application** (not a monorepo). +Single SvelteKit application (not a monorepo). ```text ├── src/ -│ ├── lib/ # Shared utilities, components, stores -│ ├── routes/ # SvelteKit routes -│ │ └── (app)/ # Authenticated app routes -│ ├── app.css # Global styles (Tailwind + DaisyUI) -│ ├── app.d.ts # Type declarations -│ ├── app.html # HTML template -│ └── hooks.server.ts # Server hooks (auth middleware) -├── e2e/ # Playwright E2E tests -├── static/ # Static assets -├── docker/Dockerfile # Production container image -└── CLAUDE.md # AI assistant instructions +│ ├── lib/ +│ │ ├── server/ # Server-only code: auth, db, logging, metrics, feature flags, trino/, storage/ +│ │ ├── components/ # Svelte components (shared ones at top level, per-module subfolders) +│ │ ├── client/ # Client-only utilities +│ │ ├── stores/ # Svelte stores (*.svelte.ts) +│ │ ├── storage/ # Client-side storage module logic +│ │ ├── editor/ # Monaco/ANTLR Trino SQL support (grammar/, generated/, completion/) +│ │ ├── dashboard/ # Dashboard and bookmarks +│ │ ├── types/ # Shared types +│ │ ├── test-utils/ # Unit test helpers (e.g. mock-logger.ts) +│ │ └── paraglide/ # Generated i18n code (do not edit) +│ ├── routes/ +│ │ ├── (app)/ # Authenticated routes: trino, storage, settings, api +│ │ ├── auth/ # Login/logout +│ │ ├── healthz/ # Health check (public) +│ │ └── metrics/ # Prometheus endpoint (public) +│ ├── architecture-tests/ # Architecture fitness functions +│ ├── test/ # Unit test setup and stubs +│ └── hooks.server.ts # Auth middleware, request logging, metrics +├── messages/ # i18n message files (en.json, de.json) +├── e2e/ # Playwright E2E tests +├── dev/ # Local dev environment (kind cluster setup) +├── deploy/helm/ # Helm chart +├── docker/Dockerfile # Production container image +└── docs/ # Further documentation ``` ## Tech Debt @@ -46,111 +68,84 @@ When introducing shortcuts, known issues, or deferred security work, file an iss ### Browser Compatibility -- The application must work in both **Firefox** and **Chromium-based browsers** (Chrome, Edge). -- Do not use browser-specific features or CSS without verifying cross-browser support. -- E2E tests run on both Firefox and Chromium (desktop) plus a mobile Chromium viewport. +The application must work in **Firefox** and **Chromium-based browsers**. Do not use browser-specific features or CSS without verifying cross-browser support. E2E tests run on both. ### CSS & Styling -- **All UI must work in both light and dark mode automatically.** Never use hard-coded colours (e.g., `text-gray-700`, `bg-white`, `border-slate-200`). Always use DaisyUI semantic colour classes (`text-base-content`, `bg-base-100`, `bg-base-200`, `border-base-300`, `text-primary`, `bg-error`, etc.) and Tailwind opacity modifiers on those classes (`text-base-content/80`, `bg-primary/10`) so that colours adapt to the active theme. -- **Secondary text uses `text-muted`** (defined in `src/app.css`), never `text-base-content` at 60% opacity or less, and never `text-muted` with an opacity: those fail the 4.5:1 contrast ratio in the light theme. `aria-hidden` is no exemption, sighted users still read hidden text. Lower opacities are only allowed on `aria-hidden` icon components that duplicate adjacent text; icons that show a state (e.g. an expand chevron) need 3:1 and also use `text-muted` (enforced by `npm run test:arch`). -- **All pages and components must be mobile-friendly.** Use responsive Tailwind breakpoints (`sm:`, `md:`, `lg:`) and test layouts at mobile viewport widths. Navigation must be accessible on small screens. -- Use Tailwind v4 `@source` directive for component CSS scanning +- **Light and dark mode must work automatically.** Never use hard-coded colours (`text-gray-700`, `bg-white`, ...). Use DaisyUI semantic classes (`text-base-content`, `bg-base-200`, `border-base-300`, `text-primary`, `bg-error`, ...) with opacity modifiers (`text-base-content/80`) where needed. +- **Secondary text uses `text-muted`** (defined in `src/app.css`), never `text-base-content` at 60 % opacity or less, and never `text-muted` with an opacity: both fail 4.5:1 contrast in the light theme. `aria-hidden` is no exemption. Lower opacities are only allowed on `aria-hidden` icon components that duplicate adjacent text; state icons (e.g. an expand chevron) need 3:1 and use `text-muted` too (enforced by `npm run test:arch`). +- **Mobile-friendly**: use responsive breakpoints (`sm:`, `md:`, `lg:`) and check layouts at mobile widths. Navigation must work on small screens. ### Accessibility (WCAG 2.2 AA) -The application must comply with **WCAG 2.2 AA**. This covers **BITV 2.0** (German accessibility regulation, based on WCAG 2.1 AA). The axe tests in `e2e/accessibility.spec.ts` check the WCAG 2.0, 2.1 and 2.2 A/AA rules. Key requirements: +The application must comply with **WCAG 2.2 AA**, which covers **BITV 2.0** (based on WCAG 2.1 AA). The axe tests in `e2e/accessibility.spec.ts` check the WCAG 2.0, 2.1 and 2.2 A/AA rules. -- **Semantic HTML**: Use correct elements (`