Add document converter, seeder data structure, and project wiki

- ai-service/convert.py: converts Office/PDF files to markdown with frontmatter
- database/seeders/data/: folder structure for themas, projects, documents, etc.
- database/seeders/data/raw/: drop zone for Office/PDF files to convert
- wiki/: project architecture, concepts, and knowledge graph documentation
- Remove unused Laravel example tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
znetsixe
2026-04-08 08:33:30 +02:00
parent 302c790c13
commit 926872a082
23 changed files with 1785 additions and 76 deletions

View File

@@ -0,0 +1,112 @@
---
title: Domain Model
created: 2026-04-08
updated: 2026-04-08
status: evolving
tags: [domain, models, relationships, lifecycle]
sources: [app/Models/, app/Enums/, database/migrations/]
---
# Domain Model
21 Eloquent models organized in 8 layers, with 14 enums for type safety.
## Entity Relationship Overview
```
Thema (strategic theme)
└── Speerpunt (focus area)
└── Project (innovation project)
├── Fase (lifecycle phase)
├── Risico (risk)
├── Commitment → Actie (action)
├── Besluit (decision) → Commitment
├── Budget → Besteding (expenditure)
├── Document ← Tag (M:N)
├── LessonLearned
├── Afhankelijkheid (dependency, Project ↔ Project)
├── Overdrachtsplan (handover plan)
│ ├── Criterium
│ └── Acceptatie
└── ProjectUser (team membership, pivot)
User ──── Role (M:N)
AuditLog (append-only, all mutations)
KennisArtikel ← Tag (M:N)
```
## Layer Details
### Strategic Layer
| Model | Key Fields | Relationships |
|---|---|---|
| **Thema** | naam, beschrijving, prioriteit, periode | has many Speerpunten |
| **Speerpunt** | naam, beschrijving, eigenaar, status | belongs to Thema, has many Projects |
| **RoadmapItem** | titel, start, eind, type, status | belongs to Thema |
### Project Layer
| Model | Key Fields | Relationships |
|---|---|---|
| **Project** | naam, beschrijving, eigenaar_id, status, prioriteit, startdatum, streef_einddatum | SoftDeletes, belongs to Speerpunt + User (eigenaar), has many of everything |
| **Fase** | type (enum), status (enum), startdatum, einddatum, opmerkingen | belongs to Project |
| **Risico** | beschrijving, impact, kans, mitigatie, eigenaar | belongs to Project |
| **Afhankelijkheid** | type, beschrijving, status | self-referential N:M between Projects |
### Commitment Layer
| Model | Key Fields | Relationships |
|---|---|---|
| **Commitment** | beschrijving, eigenaar_id, deadline, status, bron | belongs to Project + Besluit, has many Acties |
| **Actie** | beschrijving, eigenaar_id, deadline, status, prioriteit | belongs to Commitment |
### Governance Layer
| Model | Key Fields | Relationships |
|---|---|---|
| **Besluit** | titel, beschrijving, datum, type, status, onderbouwing | belongs to Project, has many Commitments |
| **Budget** | bedrag, type, periode, status | belongs to Project, has many Bestedingen |
| **Besteding** | bedrag, beschrijving, datum, categorie | belongs to Budget |
### Knowledge Layer
| Model | Key Fields | Relationships |
|---|---|---|
| **Document** | titel, type, inhoud, versie, auteur, datum, **embedding** (vector) | belongs to Project + Fase, M:N Tags |
| **KennisArtikel** | titel, inhoud, tags, auteur, datum, **embedding** (vector) | M:N Tags |
| **LessonLearned** | titel, inhoud, project, fase, tags | belongs to Project + Fase |
| **Tag** | naam, categorie | M:N with Documents, KennisArtikels |
### Handover Layer
| Model | Key Fields | Relationships |
|---|---|---|
| **Overdrachtsplan** | type, status, eigenaar_rnd, eigenaar_ontvanger | belongs to Project, has many Criteria + Acceptaties |
| **Criterium** | beschrijving, status, verificatie | belongs to Overdrachtsplan |
| **Acceptatie** | datum, door, opmerkingen, status | belongs to Overdrachtsplan |
### Auth Layer
| Model | Key Fields | Relationships |
|---|---|---|
| **User** | name, email, password, phone, afdeling, functie, 2FA fields | has many ProjectUsers, can own Projects/Commitments/Risicos |
| **Role** | naam, beschrijving, permissies | M:N with Users |
| **ProjectUser** | project_id, user_id, rol (enum) | pivot table |
### System Layer
| Model | Key Fields | Relationships |
|---|---|---|
| **AuditLog** | user_id, action, entity_type, entity_id, payload (JSON) | append-only |
## Innovation Lifecycle Phases (FaseType enum)
```
signaal → verkenning → concept → experiment → pilot → besluitvorming → overdracht_bouwen → overdracht_beheer → evaluatie
```
Special statuses (ProjectStatus only, not FaseType):
- `geparkeerd` — temporarily halted
- `gestopt` — permanently stopped
- `afgerond` — completed
## Key Design Decisions
1. **Dutch naming** — all models, fields, enums use Dutch names to match domain language
2. **Soft deletes on Project only** — projects are never hard-deleted
3. **Embedding vectors on Document + KennisArtikel** — pgvector columns for semantic search
4. **ProjectUser pivot with role** — team membership is role-typed (Eigenaar, Lid, Reviewer, Stakeholder)
5. **FaseType maps 1:1 to first 9 ProjectStatus values**`FaseType::tryFrom($projectStatus->value)` is used for phase transitions

View File

@@ -0,0 +1,121 @@
---
title: Metro Map UI Architecture
created: 2026-04-08
updated: 2026-04-08
status: evolving
tags: [architecture, ui, d3, metro-map, retro]
sources: [resources/js/Components/MetroMap/MetroCanvas.vue, STYLE_GUIDE.md, resources/js/Components/Cli/CliBar.vue]
---
# Metro Map UI Architecture
The entire platform navigates via a **zoomable metro/transit map**. No sidebar, no traditional dashboard. Users explore the innovation landscape visually.
## Map Levels
| Level | What You See | Lines = | Stations = | Zoom Target |
|---|---|---|---|---|
| 1. Strategy | Full innovation landscape | Strategic themes (Thema) | Projects | Click station → Level 2 |
| 2. Project | Single project lifecycle | Lifecycle + Commitments + Documents | Phases, items | Click station → Level 3 |
| 3. Detail | Individual item | (not yet implemented) | — | Click to open |
## Technical Implementation
### MetroCanvas.vue (356 LOC)
- **Rendering**: D3.js 7.9 on SVG
- **Zoom**: `d3.zoom()` with `scaleExtent([0.3, 5])`, pan + zoom
- **Lines**: `d3.curveMonotoneX` paths connecting stations
- **Stations**: Two concentric circles (outer ring = line color, inner dot = status color)
- **Labels**: VT323 monospace font, positioned below stations
- **Interactions**: hover → glow effect + tooltip, click → emit node-click
- **Dependencies**: Dashed lines between connected stations across lines
### Data Contract (MapDataService → MetroCanvas)
```json
{
"lines": [
{ "id": "thema-1", "name": "Waterkwaliteit", "color": "#00d2ff" }
],
"nodes": [
{
"id": "project-1",
"entityId": 1,
"entityType": "project",
"name": "Sensor Netwerk",
"lineId": "thema-1",
"x": -200, "y": 0,
"order": 1,
"status": "verkenning",
"description": "...",
"owner": "Jan",
"badge": "Verkenning",
"children": 5
}
],
"connections": [
{ "from": "project-1", "to": "project-3" }
],
"level": 1
}
```
### Station Status Colors
| Status | Color | Hex |
|---|---|---|
| afgerond / completed | Neon green | `#00ff88` |
| actief / active | Vivid cyan | `#00d2ff` |
| geparkeerd | Warning yellow | `#ffd93d` |
| gestopt | Signal red | `#e94560` |
| default (pending) | Dark fill | `#16213e` |
### Visual Effects
- **Glow filter**: SVG `feGaussianBlur` with `stdDeviation=4`, applied on hover
- **Scanline pattern**: 4px repeating lines at 8% opacity (subtle CRT effect)
- **Hover transition**: 200ms radius 8→12 + glow filter
- **Zoom animation**: 500ms d3 zoom transition for `zoomTo()` method
## C64 CLI Bar (CliBar.vue)
Fixed at bottom of screen. Commodore 64 aesthetic:
- Monospace font (Press Start 2P / VT323)
- Blinking block cursor
- Dark background, cyan/green text
- Natural language input
- Responses slide up above bar with `[AI]` prefix
## Design System
### Color Palette
| Role | Hex | Usage |
|---|---|---|
| Background | `#1a1a2e` | Canvas, page background |
| Surface | `#16213e` | Cards, tooltips, panels |
| Primary | `#0f3460` | Metro lines, primary actions |
| Accent (cyan) | `#00d2ff` | Active states, highlights, CLI cursor |
| Accent (red) | `#e94560` | Warnings, deadlines |
| Accent (green) | `#00ff88` | Success, completed |
| Accent (purple) | `#7b68ee` | Knowledge, documentation |
| Text primary | `#e8e8e8` | Main text |
| Text secondary | `#8892b0` | Labels, secondary text |
### Fonts
| Use | Font | Fallback |
|---|---|---|
| Map labels | VT323 | monospace |
| CLI bar | Press Start 2P | VT323, monospace |
| Body text | IBM Plex Sans | Inter, sans-serif |
| Code | IBM Plex Mono | monospace |
## Planned Enhancements
- **Zoom-to-dimension**: scroll-zoom near a station gradually cross-fades into child dimension (no click needed)
- **Recursive dimensions**: every node can contain children forming a sub-metro-map, infinitely nestable
- **Right-click context menu**: canvas = "New node here", station = "Edit/Delete/Add child"
- **[+] FAB**: creates at current depth
- **Mobile**: list fallback with metro line colors preserved

View File

@@ -0,0 +1,109 @@
---
title: System Architecture
created: 2026-04-08
updated: 2026-04-08
status: evolving
tags: [architecture, stack, docker, layers]
sources: [docker-compose.yml, composer.json, package.json, ai-service/app/main.py]
---
# System Architecture
## Stack
| Layer | Technology | Version |
|---|---|---|
| Backend | Laravel (PHP) | 13.0 / PHP 8.3+ |
| Frontend | Vue 3 + Inertia.js | Vue 3.5, Inertia 3 |
| Build | Vite | 8.0 |
| Styling | Tailwind CSS | 4.2 |
| Visualization | D3.js | 7.9 |
| Database | PostgreSQL + pgvector | 16 |
| Cache / Queue | Redis | alpine |
| AI Service | Python FastAPI | 0.1.0 |
| Auth | Laravel Fortify + Sanctum | Fortify 1.36, Sanctum 4.0 |
| Fonts | VT323, Press Start 2P, IBM Plex Mono | — |
## Architecture Principles
1. **Service-oriented** — domain logic lives in service classes (`app/Services/`), not controllers
2. **Event-driven** — status transitions go through transactional methods with audit logging
3. **API-first** — all functionality reachable via REST endpoints
4. **Audit trail** — all mutations logged to `audit_logs` table (append-only)
5. **AI content labeled** — AI-generated content marked and requires human confirmation
6. **Inertia SPA** — server-side routing (Laravel) with client-side rendering (Vue 3), no separate API layer needed for pages
## Docker Topology
```
┌─────────────────────────────────────────────────────────┐
│ nginx:alpine ─────────────────────────────→ :80 │
│ │ │
│ ▼ │
│ laravel-app (PHP 8.4-FPM) │
│ │ │
│ ├── laravel-worker (queue:work) │
│ ├── laravel-scheduler (cron) │
│ │ │
│ ┌───▼────────────┐ ┌─────────────────┐ │
│ │ postgresql:16 │ │ redis:alpine │ │
│ │ + pgvector │ │ cache/queue │ │
│ │ :5432 │ │ :6379 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ ai-service (Python FastAPI) ──────────────→ :8000 │
│ └── connects to postgresql for embeddings │
└─────────────────────────────────────────────────────────┘
```
7 services total. All on `innovatieplatform` bridge network.
## Data Flow
### Page Rendering (Inertia)
```
Browser → nginx → PHP-FPM → Laravel Router → Controller
→ Service (business logic)
→ Inertia::render('Page', $data)
→ Vue component receives props
→ D3.js renders metro map canvas
```
### API Calls (Map data)
```
Vue component → axios GET /api/map/strategy
→ MapController::apiStrategy()
→ MapDataService::getStrategyMap()
→ Eloquent queries (Thema → Speerpunten → Projects)
→ JSON response {lines, nodes, connections, level}
→ D3 re-renders canvas
```
### AI Integration (planned)
```
CliBar.vue → POST /api/chat
→ Laravel proxy → ai-service:8000/api/chat
→ LangGraph agent → Anthropic Claude
→ RAG: pgvector similarity search on documents
→ Response with source attribution
→ CliBar displays with [AI] prefix
```
## Key Service Classes
| Service | LOC | Responsibility |
|---|---|---|
| `ProjectService` | 186 | Project CRUD, lifecycle transitions, park/stop, audit logging |
| `MapDataService` | 165 | Build metro map data structures (Level 1: strategy, Level 2: project) |
| `ThemaService` | 60 | Theme CRUD operations |
## Configuration
- **Session/Cache/Queue**: All Redis-backed (`config/session.php`, `config/cache.php`, `config/queue.php`)
- **Database**: PostgreSQL with pgvector extension for embedding vectors
- **Auth**: Fortify handles registration/login/password flows, Sanctum for API tokens
- **OPcache**: Production-optimized (`docker/php/opcache.ini`)
- **Gzip**: Enabled in nginx config