docs: update CLAUDE.md, ROADMAP.md, SESSION-LOG.md with all session findings

This commit is contained in:
AI Assistant
2026-02-27 13:26:45 +02:00
parent f6f7cf5982
commit b2618c041d
3 changed files with 165 additions and 121 deletions
+39 -30
View File
@@ -29,18 +29,22 @@ It runs on an on-premise Ubuntu server at `10.10.10.166`, containerized with Doc
|---|---|
| Framework | Next.js 16.x, App Router, TypeScript (strict) |
| Styling | Tailwind CSS v4, shadcn/ui |
| State | localStorage (via StorageService abstraction) |
| Deploy | Docker multi-stage, Portainer, Nginx Proxy Manager |
| Repo | Gitea at `http://10.10.10.166:3002/gitadmin/ArchiTools` |
| Database | PostgreSQL (10.10.10.166:5432) via Prisma v6 ORM |
| Storage | `DatabaseStorageAdapter` (PostgreSQL) — localStorage fallback available |
| File Storage | MinIO (10.10.10.166:9002 API / 9003 UI) — client configured, adapter pending |
| Auth | NextAuth v4 + Authentik OIDC (auth.beletage.ro) |
| Deploy | Docker multi-stage, Portainer CE, Nginx Proxy Manager |
| Repo | Gitea at `https://git.beletage.ro/gitadmin/ArchiTools` |
| Language | Code in **English**, UI in **Romanian** |
### Architecture Principles
- **Module platform, not monolith** — each module isolated with own types/services/hooks/components
- **Feature flags** gate module loading (disabled = zero bundle cost)
- **Storage abstraction**: `StorageService` interface with adapters (localStorage default, designed for future DB/MinIO)
- **Storage abstraction**: `StorageService` interface with adapters (database default via Prisma, localStorage fallback)
- **Cross-module tagging system** as shared service
- **Auth stub** designed for future Authentik SSO integration
- **Auth via Authentik SSO** — NextAuth v4 + OIDC, group→role/company mapping
- **All entities** include `visibility` / `createdBy` fields from day one
- **Company logos** — theme-aware (light/dark variants), dual-rendered for SSR safety
---
@@ -87,23 +91,24 @@ legacy/ # Original HTML tools for reference
---
## Implemented Modules (13/13 — zero placeholders)
## Implemented Modules (14/14 — zero placeholders)
| # | Module | Route | Key Features |
|---|---|---|---|
| 1 | **Dashboard** | `/` | Stats cards, module grid, external tools by category |
| 2 | **Email Signature** | `/email-signature` | Multi-company branding, live preview, zoom/copy/download |
| 1 | **Dashboard** | `/` | KPI cards (6), activity feed (last 20), module grid, external tools |
| 2 | **Email Signature** | `/email-signature` | Multi-company branding, address toggle, live preview, zoom/copy/download |
| 3 | **Word XML Generator** | `/word-xml` | Category-based XML gen, simple/advanced mode, ZIP export |
| 4 | **Registratura** | `/registratura` | CRUD registry, stats, filters, **legal deadline tracking** |
| 5 | **Tag Manager** | `/tag-manager` | CRUD tags, category/scope/color, grouped display |
| 6 | **IT Inventory** | `/it-inventory` | Equipment tracking, type/status/company filters |
| 7 | **Address Book** | `/address-book` | CRUD contacts, card grid, search/type filter |
| 8 | **Password Vault** | `/password-vault` | CRUD credentials, show/hide/copy, category filter |
| 9 | **Mini Utilities** | `/mini-utilities` | Text case, char counter, percentage calc, area converter |
| 10 | **Prompt Generator** | `/prompt-generator` | Template-driven prompt builder, 4 builtin templates |
| 11 | **Digital Signatures** | `/digital-signatures` | CRUD signature/stamp/initials assets |
| 12 | **Word Templates** | `/word-templates` | Template library, 8 categories, version tracking |
| 5 | **Tag Manager** | `/tag-manager` | CRUD tags, category/scope/color, US/SDT seeds, mandatory categories |
| 6 | **IT Inventory** | `/it-inventory` | Equipment tracking, Address Book contact link, type/status/company filters |
| 7 | **Address Book** | `/address-book` | CRUD contacts, card grid, vCard export, Registratura reverse lookup, **dynamic types** |
| 8 | **Password Vault** | `/password-vault` | CRUD credentials, email field, clickable URLs, strength meter, company scope |
| 9 | **Mini Utilities** | `/mini-utilities` | Text case, char counter, percentage, area converter, U→R, artifact cleaner, MDLPA, PDF reducer, OCR |
| 10 | **Prompt Generator** | `/prompt-generator` | Template-driven prompt builder, 14 builtin templates |
| 11 | **Digital Signatures** | `/digital-signatures` | CRUD assets, drag-and-drop file upload, tag chips |
| 12 | **Word Templates** | `/word-templates` | Template library, 8 categories, version tracking, .docx placeholder auto-detection |
| 13 | **AI Chat** | `/ai-chat` | Session-based chat UI, demo mode (no API keys yet) |
| 14 | **Hot Desk** | `/hot-desk` | 4 desks, week-ahead calendar, room layout (window+door), reserve/cancel |
### Registratura — Legal Deadline Tracking (Termene Legale)
@@ -130,12 +135,14 @@ Key files:
| Service | Port | Purpose |
|---|---|---|
| **ArchiTools** | 3000 | This app |
| **Gitea** | 3002 | Git hosting (`gitadmin/ArchiTools`) |
| **Portainer** | 9000 | Docker management, auto-deploy on push |
| **ArchiTools** | 3000 | This app (tools.beletage.ro) |
| **Gitea** | 3002 | Git hosting (git.beletage.ro) |
| **PostgreSQL** | 5432 | App database (Prisma ORM) |
| **Portainer** | 9000 | Docker management |
| **Nginx Proxy Manager** | 81 (admin) | Reverse proxy + SSL termination |
| **Uptime Kuma** | 3001 | Service monitoring |
| **MinIO** | 9003 | Object storage (future) |
| **MinIO** | 9002 (API) / 9003 (UI) | Object storage |
| **Authentik** | 9100 | SSO (auth.beletage.ro) — **active** |
| **N8N** | 5678 | Workflow automation (future) |
| **Stirling PDF** | 8087 | PDF tools |
| **IT-Tools** | 8085 | Developer utilities |
@@ -143,23 +150,25 @@ Key files:
| **Netdata** | 19999 | System monitoring |
| **Dozzle** | 9999 | Docker log viewer |
| **CrowdSec** | 8088 | Security |
| **Authentik** | 9100 | SSO (future) |
### Deployment Pipeline
```
git push origin main
→ Gitea webhook fires
→ Portainer auto-redeploys stack
Docker multi-stage build (~1-2 min)
Container starts on :3000
Nginx Proxy Manager routes traffic
→ Portainer CE detects new commit
Manual "Pull and redeploy" in Portainer (CE doesn't auto-rebuild)
Docker multi-stage build (~1-2 min)
Container starts on :3000
→ Nginx Proxy Manager routes to tools.beletage.ro
```
### Docker
- `Dockerfile`: 3-stage build (deps → builder → runner), `node:20-alpine`, non-root user
- `docker-compose.yml`: single service, port 3000, watchtower label
- `Dockerfile` includes `npx prisma generate` before build step
- `docker-compose.yml`: single service, port 3000, **all env vars hardcoded** (Portainer CE can't inject env vars)
- `output: 'standalone'` in `next.config.ts` is **required**
- `@prisma/client` must be in `dependencies` (not devDependencies) for runtime
---
@@ -211,13 +220,13 @@ src/modules/<name>/
---
## Future Integrations (not yet implemented)
## Current Integrations
| Feature | Status | Notes |
|---|---|---|
| **Authentik SSO** | Auth stub exists | `src/core/auth/` has types + provider shell |
| **MinIO storage** | Adapter pattern ready | Switch `NEXT_PUBLIC_STORAGE_ADAPTER` to `minio` |
| **API backend** | Adapter pattern ready | Switch to `api` adapter when backend exists |
| **Authentik SSO** | ✅ Active | NextAuth v4 + OIDC, group→role/company mapping |
| **PostgreSQL** | ✅ Active | Prisma ORM, `KeyValueStore` model, `/api/storage` route |
| **MinIO** | Client configured | 10.10.10.166:9002, bucket `tools`, adapter pending |
| **AI Chat API** | UI complete, demo mode | No API keys yet; supports Claude/GPT/Ollama |
| **N8N automations** | Webhook URL configured | For notifications, backups, workflows |
+61 -91
View File
@@ -225,47 +225,14 @@
---
## PHASE 2 — New Module: Hot Desk Management
## PHASE 2 — New Module: Hot Desk Management
> Module 14 from xlsx. Entirely new.
### 2.01 `[HEAVY]` Hot Desk Module — Full Implementation
### 2.01 `[HEAVY]` Hot Desk Module — Full Implementation (2026-02-26)
**What:** Build Module 14 from scratch per xlsx spec:
- 4 desks in a shared room
- Users reserve desks 1 week ahead
- Calendar view showing desk availability per day
- Reserve/cancel actions
- History of past reservations
- Visual room layout showing which desks are booked
**Module structure:**
```
src/modules/hot-desk/
├── components/
│ ├── hot-desk-module.tsx # Main view with calendar + room layout
│ ├── desk-calendar.tsx # Week view with 4 desk columns
│ ├── desk-room-layout.tsx # Visual 4-desk room diagram
│ └── reservation-dialog.tsx # Book/cancel dialog
├── hooks/
│ └── use-reservations.ts # CRUD + conflict detection
├── services/
│ └── reservation-service.ts # Business logic, overlap check
├── types.ts # DeskReservation, DeskId
├── config.ts # Module metadata
└── index.ts
```
**Files to also create/modify:**
- `src/app/(modules)/hot-desk/page.tsx` — Route
- `src/config/modules.ts` — Register module
- `src/config/navigation.ts` — Add sidebar entry
- `src/config/flags.ts` — Add feature flag
**User approval required** before moving to Phase 3.
**What:** Build Module 14 from scratch per xlsx spec.
**Status:** ✅ Done. Full implementation: 4 desks, week-ahead calendar, reserve/cancel, room layout with window (left) + door (right) landmarks, history. Registered in modules/navigation/flags.
---
@@ -273,13 +240,17 @@ src/modules/hot-desk/
> Fază adăugată pentru rafinarea cerințelor, UX și logicii de business înainte de implementarea tehnică.
### 3.01 `[UI/UX]` Header & Navigare Globală
### 3.01 `[UI/UX]` Header & Navigare Globală (2026-02-27)
**Cerințe noi:**
- **Logo-uri:** Mărirea dimensiunii logo-urilor în header ("nu se vede nimic acum").
- **Mini-joc Logo:** La click pe logo-uri, acestea se schimbă (efect interactiv/fun, gimmick vizual).
- **Logo-uri:** Mărirea dimensiunii logo-urilor în header.
- **Mini-joc Logo:** Click pe logo-uri le animează (spin/bounce/ping), combo secret BTG→US→SDT declanșează confetti.
- **Navigare:** Click pe titlul aplicației redirecționează către Dashboard.
- **Theme Toggle:** Slider animat sun/moon cu gradient zi/noapte, stele, nori.
- **Dark mode logos:** Variante corecte light/dark pe baza temei, cu fallback montat.
**Status:** ✅ Done. Sidebar redesigned: logos in centered row (flex-1, theme-aware, dual-render light+dark), "ArchiTools" text below, animated theme toggle (Sun/Moon lucide icons, gradient background, stars/clouds).
### 3.02 `[BUSINESS]` Registratura — Integrare și UX
@@ -306,12 +277,14 @@ src/modules/hot-desk/
- **Valabilitate Documente (Expirare CU/AC):** Adăugarea unui sistem de urmărire a valabilității pentru documente emise (ex: Certificat de Urbanism, Autorizație de Construire). Sistemul trebuie să permită setarea unei date de expirare și să genereze alerte/reamintiri cu X zile înainte de expirare (pentru a iniția procedurile de prelungire).
- **Pregătire Web Scraping (Wishlist):** Adăugarea unui câmp opțional "URL Verificare Status" (ex: link către portalul primăriei) și "ID Urmărire Extern". Arhitectura trebuie să permită pe viitor rularea unui job de fundal (ex: via N8N sau un worker intern) care să facă scraping/API call pe acel URL și să actualizeze automat statusul în ArchiTools.
### 3.04 `[ARCHITECTURE]` Autentificare & Identitate (Pregătire)
### 3.04 `[ARCHITECTURE]` Autentificare & Identitate (2026-02-27)
**Cerințe noi:**
- **Devansare Prioritate Authentik:** Deoarece funcționalități precum "Responsabil" și "Audit Log" depind de identitatea utilizatorului, integrarea cu Authentik (legat la Domain Controller/Active Directory) devine o prioritate arhitecturală.
- **Sincronizare Useri:** Sistemul trebuie să poată citi lista de utilizatori din Authentik/AD pentru a popula dropdown-urile de tip "Responsabil" chiar și pentru utilizatorii care nu s-au logat încă în ArchiTools.
- **Devansare Prioritate Authentik:** Integrarea cu Authentik (legat la Domain Controller/Active Directory).
- **Sincronizare Useri:** Sistemul poate citi lista de utilizatori din Authentik/AD.
**Status:** ✅ Done. NextAuth v4 + Authentik OIDC fully configured. Group→role mapping (admin/manager/user) and group→company mapping. Header user menu with login/logout. Env vars hardcoded in docker-compose.yml (Portainer CE limitation). See also Phase 6 below.
### 3.05 `[BUSINESS]` Email Signature — Automatizare și Branding
@@ -359,24 +332,30 @@ src/modules/hot-desk/
- Echipamentele care au aceste date completate vor fi randate automat în vizualizarea grafică a rack-ului.
- La hover pe un echipament din rack, va apărea un tooltip cu detaliile de bază (Nume, IP, Status).
### 3.09 `[BUSINESS]` Address Book — Tipuri Dinamice
### 3.09 `[BUSINESS]` Address Book — Tipuri Dinamice (2026-02-27)
**Cerințe noi:**
- **Tip Contact Dinamic:** Câmpul "Tip" (ex: Client, Furnizor, Instituție) trebuie să devină un câmp de tip "creatable select" (combinație între dropdown și text input). Utilizatorul trebuie să poată scrie un tip nou (ex: "Colaborator Extern"), iar acesta să se salveze automat și să apară în dropdown pentru viitoarele contacte.
- **Tip Contact Dinamic:** Câmpul "Tip" devine "creatable select" (dropdown + text input) cu salvare automată.
### 3.10 `[UI/UX]` Hot Desk — Orientare Vizuală
**Status:** ✅ Done. `CreatableTypeSelect` component (input + "+" button), `DEFAULT_TYPE_LABELS` + dynamic types from existing contacts, `ContactType` allows `| string` for custom types.
### 3.10 ✅ `[UI/UX]` Hot Desk — Orientare Vizuală (2026-02-27)
**Cerințe noi:**
- **Punct de Reper (Fereastră):** În vizualizarea grafică a camerei (room layout), trebuie adăugată schematic o fereastră pe peretele din stânga. Acest element vizual va servi ca punct de reper pentru ca utilizatorii să se poată orienta ușor și să înțeleagă care birou este care (ex: "biroul de lângă geam", "biroul de la ușă").
- **Punct de Reper (Fereastră):** Fereastră pe stânga, ușă pe dreapta.
### 3.11 `[BUSINESS]` Password Vault — Câmpuri Noi
**Status:** ✅ Done. Window on left wall (sky-blue, "Fereastră"), door on right wall (amber, "Ușă").
### 3.11 ✅ `[BUSINESS]` Password Vault — Câmpuri Noi (2026-02-27)
**Cerințe noi:**
- **Câmp Email:** Adăugarea unui câmp distinct pentru "Email", separat de "Username" (deoarece multe conturi folosesc un email pentru login, dar au și un username separat, sau invers).
- **Link Clickabil:** Asigurarea că URL-ul salvat este afișat ca un link clickabil (deschidere în tab nou) direct din lista de parole, pentru acces rapid.
- **Câmp Email:** Adăugarea unui câmp distinct pentru "Email", separat de "Username".
- **Link Clickabil:** URL afișat ca link clickabil (tab nou) din lista de parole.
**Status:** ✅ Done. Added `email: string` field to VaultEntry type. Form has email input. URLs rendered as clickable `<a>` links with `target="_blank"`.
### 3.12 `[BUSINESS]` Mini Utilities — Extindere și Fix-uri
@@ -530,80 +509,71 @@ AI_DEFAULT_MODEL=claude-sonnet-4-6-20261001
---
## PHASE 6 — Authentication (Authentik SSO)
## PHASE 6 — Authentication (Authentik SSO)
> Real users, real permissions. Requires server admin access.
> Real users, real permissions. Core auth done, access control pending.
### 6.01 `[HEAVY]` Authentik OIDC Integration
### 6.01 `[HEAVY]` Authentik OIDC Integration (2026-02-27)
**What:** Replace stub user with real Authentik SSO.
**Status:** ✅ Done. NextAuth v4 + Authentik OIDC provider configured. Group→role mapping (authentik groups → admin/manager/user). Group→company mapping (beletage/urban-switch/studii-de-teren). Cookie-based session. `useAuth()` returns real user. Header shows user name/email + logout. Sign in with Authentik page works.
- NextAuth.js / Auth.js route handler
- OIDC token → user profile resolution
- Cookie-based session
- `useAuth()` returns real user
**Server setup required:**
1. Create OAuth2 app in Authentik (http://10.10.10.166:9100)
2. Set redirect URI: `http://10.10.10.166:3000/api/auth/callback/authentik`
3. Set env vars: `AUTHENTIK_URL`, `AUTHENTIK_CLIENT_ID`, `AUTHENTIK_CLIENT_SECRET`, `NEXTAUTH_SECRET`
**User action needed:** Authentik admin credentials.
Env vars (hardcoded in docker-compose.yml for Portainer CE):
- `NEXTAUTH_URL=https://tools.beletage.ro`
- `NEXTAUTH_SECRET`, `AUTHENTIK_CLIENT_ID`, `AUTHENTIK_CLIENT_SECRET`, `AUTHENTIK_ISSUER`
---
### 6.02 `[STANDARD]` Module-Level Access Control
**What:** Implement `canAccessModule()` with role-based rules. FeatureGate checks flag + permission.
**Depends on:** 6.01
**Depends on:** 6.01
---
### 6.03 `[STANDARD]` Data Visibility Enforcement
**What:** Filter storage results by `visibility` and `createdBy` fields (already stored on every entity, never enforced).
**Depends on:** 6.01
**Depends on:** 6.01
---
### 6.04 `[LIGHT]` Audit Logging
**What:** Log create/update/delete actions with user ID + timestamp. Console initially, later storage/N8N.
**Depends on:** 6.01
**Depends on:** 6.01
---
## PHASE 7 — Storage Migration (localStorage → Database)
## PHASE 7 — Storage Migration (localStorage → Database) — PARTIALLY DONE
> Multi-user shared data. Requires PostgreSQL + infrastructure changes.
> Multi-user shared data. PostgreSQL + Prisma + MinIO client configured.
### 7.01 `[HEAVY]` PostgreSQL + Prisma Setup
### 7.01 `[HEAVY]` PostgreSQL + Prisma Setup (2026-02-27)
**What:** Add PostgreSQL container, create Prisma schema for all entities, run migrations.
**Infrastructure:** New `postgres` service in `docker-compose.yml`.
**What:** PostgreSQL + Prisma ORM setup.
**Status:** ✅ Done. Prisma v6.19.2 with PostgreSQL on 10.10.10.166:5432. `KeyValueStore` model. `npx prisma generate` in Dockerfile. `@prisma/client` in dependencies.
---
### 7.02 `[HEAVY]` API Storage Adapter
### 7.02 `[HEAVY]` API Storage Adapter (2026-02-27)
**What:** Create `ApiStorageAdapter` implementing `StorageService`. Use Next.js API routes + Prisma.
**Depends on:** 7.01
**What:** `DatabaseStorageAdapter` implementing `StorageService` via `/api/storage` route + Prisma.
**Status:** ✅ Done. Set `NEXT_PUBLIC_STORAGE_ADAPTER=database` to activate. All 14 modules instantly get DB persistence.
---
### 7.03 `[STANDARD]` Data Migration Tool
**What:** One-time export from localStorage → import to PostgreSQL. Preserve IDs and timestamps.
**Depends on:** 7.02
**Depends on:** 7.02
---
### 7.04 `[HEAVY]` MinIO File Storage
### 7.04 `[HEAVY]` MinIO File Storage (2026-02-27)
**What:** Create `MinioAdapter` for file uploads. Migrate base64 attachments to MinIO objects.
**MinIO already running** at http://10.10.10.166:9003.
**User action needed:** MinIO access key + secret key.
**What:** MinIO client configured and tested.
**Status:** ✅ Done. MinIO client installed (`minio` npm package). Connected to 10.10.10.166:9002 (API) / 9003 (UI). Bucket `tools` exists. File upload adapter not yet wired to StorageService (MinioAdapter pending).
---
@@ -691,16 +661,16 @@ AI_DEFAULT_MODEL=claude-sonnet-4-6-20261001
## Infrastructure Credentials Needed
| Service | What | When Needed |
| ------------------------ | --------------------------------------- | ------------------- |
| **US/SDT Logos** | SVG/PNG logo files | Phase 1 (task 1.01) |
| **US/SDT Addresses** | Office addresses for email signature | Phase 1 (task 1.02) |
| **Anthropic API Key** | `sk-ant-...` from console.anthropic.com | Phase 4 (task 4.01) |
| **OpenAI API Key** | `sk-...` from platform.openai.com | Phase 4 (task 4.01) |
| **Authentik Admin** | Login to create OAuth app at :9100 | Phase 5 (task 5.01) |
| **MinIO Credentials** | Access key + secret key for :9003 | Phase 6 (task 6.04) |
| **PostgreSQL** | New container + password | Phase 6 (task 6.01) |
| **Gitea Actions Runner** | Registration token from Gitea admin | Phase 9 (task 9.01) |
| Service | What | When Needed | Status |
| ------------------------ | --------------------------------------- | ------------------- | ------ |
| **US/SDT Logos** | SVG/PNG logo files | Phase 1 (task 1.01) | ✅ Done |
| **US/SDT Addresses** | Office addresses for email signature | Phase 1 (task 1.02) | ✅ Done (placeholder) |
| **Anthropic API Key** | `sk-ant-...` from console.anthropic.com | Phase 5 (task 5.01) | Pending |
| **OpenAI API Key** | `sk-...` from platform.openai.com | Phase 5 (task 5.01) | Pending |
| **Authentik Admin** | Login to create OAuth app at :9100 | Phase 6 (task 6.01) | ✅ Done |
| **MinIO Credentials** | Access key + secret key for :9003 | Phase 7 (task 7.04) | ✅ Done |
| **PostgreSQL** | Database + password | Phase 7 (task 7.01) | ✅ Done |
| **Gitea Actions Runner** | Registration token from Gitea admin | Phase 10 (task 10.01) | Pending |
---
+65
View File
@@ -4,6 +4,71 @@
---
## Session — 2026-02-27 evening (GitHub Copilot - Claude Opus 4.6)
### Context
Continued from earlier session (Gemini 3.1 Pro got stuck on Authentik testing). This session focused on fixing deployment pipeline, then implementing Phase 3 visual/UX tasks + infrastructure documentation.
### Completed
- **Deployment Pipeline Fixes:**
- Fixed Dockerfile: added `npx prisma generate` before build step
- Fixed docker-compose.yml: hardcoded all env vars (Portainer CE can't inject env vars)
- Moved `@prisma/client` from devDependencies to dependencies (runtime requirement)
- Created `stack.env` (later abandoned — Portainer CE doesn't parse it reliably)
- Confirmed auth flow works end-to-end on production (tools.beletage.ro)
- **3.01 ✅ Header & Navigation:**
- Added 3 company logos (BTG, US, SDT) with theme-aware variants (light/dark)
- Interactive mini-game: click animations (spin/bounce/ping), secret combo BTG→US→SDT triggers confetti
- Logo layout: flex-1 centered row with dual-render (both light+dark images, CSS toggle) to fix SSR hydration
- "ArchiTools" text centered below logos, links to Dashboard
- Created animated theme toggle: Sun/Moon lucide icons in sliding knob, gradient sky background, stars (dark), clouds (light)
- **3.04 ✅ Authentik Integration:**
- Already done by previous session (Gemini) — confirmed working. Marked as done.
- **3.09 ✅ Address Book Dynamic Types:**
- `CreatableTypeSelect` component (dropdown + text input + "+" button)
- `ContactType` union type extended with `| string` for custom types
- Dynamic `allTypes` derived from existing contacts' types
- **3.10 ✅ Hot Desk Window:**
- Window on left wall (sky-blue, "Fereastră"), door on right wall (amber, "Ușă")
- **3.11 ✅ Password Vault Email + Link:**
- Added `email: string` field to VaultEntry type + form
- URLs rendered as clickable `<a>` links with `target="_blank"`
- **Documentation Updated:**
- CLAUDE.md: stack table (Prisma/PG/NextAuth/MinIO), 14 modules, infra ports, deployment pipeline, integration status
- ROADMAP.md: marked Phase 2, 3.01, 3.04, 3.09, 3.10, 3.11, Phase 6 (6.01), Phase 7 (7.01, 7.02, 7.04) as done
- SESSION-LOG.md: this entry
### Files Created
- `src/shared/components/common/theme-toggle.tsx` — Animated sun/moon theme toggle
### Files Modified
- `Dockerfile` — Added `npx prisma generate`
- `docker-compose.yml` — All env vars hardcoded
- `package.json`@prisma/client moved to dependencies
- `src/config/companies.ts` — BTG logo paths + fixed US/SDT dark variants
- `src/shared/components/layout/sidebar.tsx` — Logo redesign + mini-game
- `src/shared/components/layout/header.tsx` — Theme toggle replacement
- `src/modules/password-vault/types.ts` — Added email field
- `src/modules/password-vault/components/password-vault-module.tsx` — Email + clickable URLs
- `src/modules/address-book/types.ts` — Dynamic ContactType
- `src/modules/address-book/components/address-book-module.tsx` — CreatableTypeSelect
- `src/modules/hot-desk/components/desk-room-layout.tsx` — Window + door landmarks
### Notes
- Portainer CE requires manual "Pull and redeploy" — no auto-rebuild on webhook
- "Re-pull image" checkbox only needed for base image updates (node:20-alpine), not for code changes
- Logo SVGs have very different aspect ratios (BTG ~7:1, US ~6:1, SDT ~3:1) — using flex-1 min-w-0 to handle this
- Theme toggle: `resolvedTheme` from next-themes is `undefined` on SSR first render — must use `mounted` state guard
---
## Session — 2026-02-27 (GitHub Copilot - Gemini 3.1 Pro)
### Completed