chore(config): add agent skills and project brain documentation

This commit is contained in:
DanielS
2026-08-19 00:04:04 +02:00
parent 407d40b2e8
commit 6a2ebd25a2
27 changed files with 969 additions and 0 deletions

18
.agents/agents.md Normal file
View File

@@ -0,0 +1,18 @@
# Antigravity Agent Configuration (Project Rocky)
## Agent: Rocky_Manager
- **Role**: Hauptkoordinator des Rocky-Projekts.
- **Responsibility**: Verteilt Aufgaben an Spezialisten basierend auf den Skill-Anforderungen.
## Agent: Dokumenten_Spezialist
- **Role**: Verantwortlich für Exporte und Berichte.
- **Assigned_Skills**: [".agents/skills/pdf_skill.md"]
## Agent: Kommunikations_Spezialist
- **Role**: Verantwortlich für Benachrichtigungen und Kundenkontakt.
- **Assigned_Skills**: [".agents/skills/email_skill.md"]
## Agent: Compliance_Supervisor
- **Role**: Prüft den geschriebenen Code auf Datenschutzfehler.
- **Assigned_Skills**: [".agents/skills/dsgvo_skill.md"]
- **Rule**: "Blockiere jeden Git-Commit, wenn der Code gegen die DSGVO-Vorgaben verstößt."

View File

@@ -0,0 +1,8 @@
---
name: b2b-mail-dispatcher
description: Verwaltet den SMTP-E-Mail-Versand bei Statusänderungen von Bestellungen und stellt transaktionale Zuverlässigkeit sicher.
---
Richtlinien für die E-Mail-Kommunikation:
1. Wann immer der Status einer Bestellung in der Datenbank oder via Server Action mutiert wird (`status`-Übergang), triggere ein Event für den E-Mail-Versand.
2. Die E-Mail muss transaktionssicher über die SMTP-Konfiguration gesendet werden und an die im Benutzerprofil hinterlegte Adresse gehen.
3. Bei erfolgreichem Checkout hänge das generierte PDF aus dem Supabase Storage als Datei-Attachment an die E-Mail an.

View File

@@ -0,0 +1,37 @@
---
name: commit-work
description: Erzwingt Conventional Commits mit atomaren, imperativ formulierten Commit-Messages nach strikter Spezifikation.
---
# Skill: Conventional Commits Expert
## Purpose
Ensure all code changes are committed using the strict Conventional Commits specification.
## Rules
1. **Atomic Commits**: Stage and commit only ONE logical change at a time.
2. **Imperative Mood**: Always use the imperative present tense (e.g., "add" instead of "added" or "adds").
3. **Case & Punctuation**: Start the description with a lowercase letter. Do not end with a period.
4. **Length**: Keep the first line under 50 characters.
## Commit Message Structure
<type>(<optional scope>): <description>
[optional body]
[optional footer(s)]
## Allowed Types
- `feat`: A new feature for the user.
- `fix`: A bug fix for the user.
- `docs`: Changes to the documentation.
- `style`: Formatting, missing semi-colons, etc. (no production code change).
- `refactor`: Refactoring production code (neither fixes a bug nor adds a feature).
- `test`: Adding missing tests or correcting existing tests.
- `chore`: Updating build tasks, package manager configs, etc.
## Workflow
1. Run `git diff --cached` to see staged changes.
2. If multiple features are changed, unstage and split them.
3. Generate the commit message matching the structural rules above.
4. Execute `git commit -m "<message>"`.

View File

@@ -0,0 +1,6 @@
# Skill: DSGVO & Datenschutz-Compliance (Rocky-Projekt)
## Regeln für Aufgaben:
1. **Daten-Minimierung**: Spezialisten dürfen personenbezogene Daten (wie E-Mail-Adressen oder Klarnamen) niemals in Log-Dateien oder im Git-Verlauf speichern.
2. **Verschlüsselung**: Daten im Rocky-Projekt müssen "at rest" und "in transit" (mindestens TLS 1.3) verschlüsselt werden.
3. **Anonymisierung**: Für Testzwecke im Terminal-Subagent dürfen nur synthetische Dummy-Daten verwendet werden. Keine echten Kundendaten nutzen!

View File

@@ -0,0 +1,6 @@
# Skill: E-Mail-Kommunikation (Rocky-Projekt)
## Regeln für Aufgaben:
1. **Tonalität**: Professionell, höflich und im Corporate Design des Rocky-Projekts.
2. **Sicherheit**: Sende niemals Passwörter, Token oder unverschlüsselte API-Keys per E-Mail.
3. **Fallbacks**: Wenn ein E-Mail-Versand fehlschlägt, schreibe den Fehler sofort in die lokale Log-Datei `rocky_mail_errors.log` und benachrichtige den Manager-Agenten.

View File

@@ -0,0 +1,8 @@
---
name: gdpr-anonymizer
description: Setzt die DSGVO-konforme Anonymisierung von Endkunden um, ohne historische Steuerdaten zu beschädigen.
---
Regeln für das Feature `/my-customers` (Anonymisieren):
1. Überschreibe `first_name`, `last_name`, `street`, `zip`, `city`, `email` und alle Bankdaten in `end_customers` hart mit dem String `[GELÖSCHT]`.
2. Setze `is_anonymized = true`.
3. Führe NIEMALS Kaskaden-Löschungen oder Updates auf der Tabelle `orders` aus, wenn ein Kunde anonymisiert wird. Die Snapshots müssen unverändert bleiben.

View File

@@ -0,0 +1,15 @@
---
name: grand-functions
description: Dokumentation und Spezifikation des CASPOS Webshops inklusive Datenmodell, Kernprozessen und Sicherheitskonzept.
---
# Grand Functions - CASPOS Webshop Spezifikation
Dieser Skill enthält die vollständige Dokumentation und Spezifikation des CASPOS Webshops. Die Spezifikationen sind in logische Referenzdokumente unterteilt:
- [Projekt-Überblick & Tech-Stack](file:///c:/source/webshop/.agents/skills/grand-functions/references/overviews.md)
- [Datenmodell & Schema](file:///c:/source/webshop/.agents/skills/grand-functions/references/schema.md)
- [Kernprozesse](file:///c:/source/webshop/.agents/skills/grand-functions/references/processes.md)
- [Sicherheitskonzept (RLS)](file:///c:/source/webshop/.agents/skills/grand-functions/references/security.md)
- [Testumgebung & -abdeckung](file:///c:/source/webshop/.agents/skills/grand-functions/references/testing.md)

View File

@@ -0,0 +1,16 @@
# Projekt-Überblick & Technologie-Stack
## 1. Projekt-Überblick
Der CASPOS Webshop ist ein B2B-Portal für Vertriebspartner. Partner können hier Software-Pakete und Zusatzmodule (für POS/Kassenlösungen) konfigurieren, Anfragen für ihre Endkunden erstellen und Lizenzen verwalten.
---
## 2. Technologie-Stack
- **Frontend/Backend**: Next.js 15+ (App Router, React Server Components, Server Actions).
- **Styling**: Tailwind CSS & Vanilla CSS (modernes Dark-Theme).
- **Datenbank & Auth**: Supabase (PostgreSQL, Row Level Security - RLS, Supabase Auth).
- **E-Mail-Versand**: SMTP-Integration für automatisierte Bestätigungen.
- **PDF-Generierung**: `@react-pdf/renderer` zur Erzeugung von Anfragebestätigungen als PDF.
- **Storage**: Supabase Storage (`invoices` Bucket) zur Archivierung der PDF-Dokumente.

View File

@@ -0,0 +1,75 @@
# Kernprozesse
```mermaid
graph TD
A[Partner loggt sich ein] --> B{Firma zugewiesen?}
B -- Nein --> C[Fehlermeldung: Kein Zutritt zum Wizard]
B -- Ja --> D[Wizard öffnen / Konfigurieren]
D --> E[Endkunden auswählen/anlegen]
E --> F[Produkte & Module wählen]
F --> G{Validierung erfolgreich?}
G -- Nein --> H[Validierungsfehler anzeigen]
G -- Ja --> I[Bestellung absenden]
I --> J[Snapshot einfrieren & in DB speichern]
J --> K[Rechnungs-PDF generieren & in Storage laden]
K --> L[E-Mail mit PDF an Partner senden]
L --> M[Bestellung in der Übersicht anzeigen]
```
### A. Partner- & Unternehmens-Hierarchie
1. Ein neu registrierter User hat die Rolle `partner` und ist zunächst keiner Firma zugeordnet.
2. Der Administrator ordnet den User in der Admin-Oberfläche (`/admin/users`) einem Unternehmen (`companies`) zu.
3. Nur wenn der User einer Firma zugewiesen ist (oder Admin ist), kann er Endkunden anlegen und Bestellungen aufgeben.
### B. Endkunden-Verwaltung (`/my-customers`)
- **Firmenweite Sicht**: Da `end_customers.partner_id` on `companies.id` verweist, sehen alle Mitarbeiter desselben Unternehmens dieselben Endkunden.
- **DSGVO Anonymisierung**: Endkunden können unwiderruflich anonymisiert werden. Dabei werden sensible Daten mit `[GELÖSCHT]` überschrieben und `is_anonymized` auf `true` gesetzt. In existierenden Bestellungen (`orders.customer_data`) bleiben die Daten zu steuerlichen Zwecken unverändert.
### C. Bestell-Wizard & Validierung (`/order`)
- **Kategorie-Pflichten**: Wenn eine Produktkategorie als `is_required` definiert ist, muss ein Produkt ausgewählt werden.
- **Abhängigkeiten (Requirements)**: Ein Modul oder Produkt kann andere Module/Produkte voraussetzen (z.B. Modul B erfordert Modul A). Das System prüft dies client- und serverseitig.
- **Top-Down State-Management**:
- Die Wahl eines Basis-Produkts steuert die Sichtbarkeit und Wählbarkeit aller Module (Top-Down). Modul-Auswahlen dürfen niemals die Liste der wählbaren Basis-Produkte beeinflussen (Verhinderung von UI-Deadlocks).
- **Auto-Reset & Kaskaden-Bereinigung**: Beim Wechsel des Basis-Produkts in `selectProduct` werden inkompatible Module in anderen Kategorien automatisch über eine Kaskaden-Bereinigung (Filterung der `moduleIds` basierend auf den `exclusions` des neuen Produkts) deselektiert.
- **Sichtbarkeits- & Wählbarkeits-Garantie**: Basis-Produkte werden im UI niemals durch Modulausschlüsse ausgeblendet. Nachgelagerte Produkte/Module, die mit dem ausgewählten Basis-Produkt inkompatibel sind, erhalten im JSX das `disabled`-Attribut und sind nicht anklickbar (Sperrung von "Kein Backoffice" bei "Small Business"). Klicks auf Module haben keinerlei Rückwirkung auf die Basis-Produkt-Auswahl.
- **Radio-Button-Verhalten (allow_multiselect = false)**: Falls eine Kategorie keine Mehrfachauswahl erlaubt, wird bei Auswahl eines neuen Moduls das zuvor ausgewählte Modul dieser Kategorie automatisch abgewählt.
- **Snapshot-Architektur**: Sobald eine Bestellung aufgegeben wird, werden die Kundendaten (`CustomerSnapshot`) und Produktkonfigurationen (`OrderSnapshot` samt Preisen und Modulversionen) in `orders` als JSONB-Snapshots eingefroren. Preisänderungen im Katalog haben keinen Einfluss auf bestehende Bestellungen.
### D. Bestellungs-Verwaltung & Statusübergang
- **Sichtbarkeit**: Partner sehen in `/my-orders` alle Bestellungen aller Mitarbeiter ihrer Firma.
- **Bearbeiten**: Unvollständige Bestellungen (`status != 'completed'`) können von jedem Mitarbeiter der jeweiligen Firma nachträglich editiert werden.
- **Admin-Workflow**: Admins sehen in `/admin/orders` alle Bestellungen global, können den Status ändern (z.B. von *Eingegangen* auf *In Bearbeitung* oder *Abgeschlossen*) und PDF-Rechnungen manuell herunterladen.
- **Statusänderungs-Mails**: Bei jedem Statusübergang wird automatisch eine Benachrichtigungs-E-Mail an den Besteller geschickt.
---
### E. Multi-Kassen-Warenkorb & Checkout-Split
- **Endpunkt / Server Action**: `POST /api/orders/checkout` sowie Server Action `checkoutAction` in `app/actions/checkout.ts`
- **Funktionsweise**:
- Empfängt ein Array von `items` (Kassenkonfigurationen).
- Validiert Auth und Partner-Firma Zuweisung.
- Generiert einen `order_hash` zur Vermeidung von Doppelübermittlungen (Idempotenz-Guard).
- Teilt die Konfigurationen nach `billingInterval` / `billingType` auf (Kauf vs. Abo).
- Erstellt separate Orders in der Datenbank:
- Typ `purchase`: Anfrage für Kauf-Lizenzen (Zahlungsart: Vormerkung/Angebot).
- Typ `subscription`: Anfrage für Software-Abonnement (Zahlungsart: SEPA).
- Friert für jede Order einen konsolidierten `order_data` (JSONB) und `customer_data` (JSONB) ein.
- Triggert die PDF-Erstellung und den E-Mail-Versand unabhängig für jede generierte Order (gibt Order-IDs für Post-Processing zurück).
---
### F. PDF-Rechnungsgenerierung & Mail-Versand (Post-Processing)
- **Entkopplung & Asynchronität**: Die Generierung der PDFs und der E-Mail-Versand sind vollständig aus dem synchronen Checkout-Flow entkoppelt. Der Checkout liefert dem Frontend sofort nach Speicherung in der DB eine Erfolgsmeldung zurück. Die Generierung und der Versand werden asynchron im Hintergrund (via unblockiertem Promise-Worker) ausgeführt, um SMTP-Latenzen abzufangen.
- **Snapshot-Exklusivität**: Die PDF-Generierung erfolgt ausschließlich auf Basis der in `orders.order_data` und `orders.customer_data` eingefrorenen Snapshots.
- **Layout-Unterscheidung**:
- **Typ `purchase` (Kauf)**:
- Generiert eine klassische **Anfragebestätigung Kauf**.
- Weist die einmalige Gesamtsumme aus.
- **Typ `subscription` (Abonnement)**:
- Generiert eine **Anfragebestätigung Abonnement**.
- Weist monatlich wiederkehrende Kosten aus.
- **Archivierung & Benachrichtigung**:
- Hochladen des PDFs in den Supabase Storage (`invoices` Bucket).
- E-Mail-Versand mit PDF-Anhang an den Partner.

View File

@@ -0,0 +1,97 @@
# Datenmodell & Beziehungen (Schema)
Das Datenbankschema besteht aus folgenden Tabellen im Schema `public`:
### `companies` (Unternehmen)
- Repräsentiert die Partner-Unternehmen (Retailer).
- `id` (UUID, Primary Key)
- `name` (TEXT)
- `street`, `zip`, `city`, `email` (Adressdaten)
### `users` (Systembenutzer)
- Erweitert die Authentifizierungsdaten aus `auth.users`.
- `id` (UUID, References `auth.users(id)`)
- `role` (TEXT, standardmäßig `'partner'`, oder `'admin'`)
- `company_id` (UUID, References `public.companies(id)`)
### `end_customers` (Endkunden)
- Die Endkunden, für die die Partner Lizenzen bestellen.
- `id` (UUID, Primary Key)
- `partner_id` (UUID, References `public.companies(id)`) <-- *Direkte Zuordnung zur Firma des Partners*
- `company_name` (TEXT)
- `first_name`, `last_name`, `street`, `zip`, `city`, `email` (Stammdaten)
- `bank_iban`, `bank_bic`, `bank_name`, `bank_owner` (Bankdaten)
- `is_anonymized` (BOOLEAN) <-- *Für DSGVO-Löschung*
### `categories` (Kategorien)
- Steuert das Layout und Verhalten im Wizard.
- `id` (UUID, Primary Key)
- `name` (TEXT)
- `is_required` (BOOLEAN) <-- *Muss ausgewählt werden*
- `allow_multiselect` (BOOLEAN) <-- *Mehrfachauswahl erlaubt (Checkbox statt Radio)*
- `sort_order` (INTEGER) <-- *Sortierung im Wizard*
- `show_in_branches` (BOOLEAN)
- `preselect` (BOOLEAN)
- `resets_others` (BOOLEAN)
### `products` (Katalogprodukte / Basis-Editionen)
- Hauptlösungen (z.B. Basic-Kasse, Backoffice).
- `id` (UUID, Primary Key)
- `category_id` (UUID, References `categories`)
- `name` (TEXT)
- `base_price` (DECIMAL)
- `tax_rate` (DECIMAL)
- `billing_interval` (TEXT: `'one_time'` / `'monthly'`)
- `show_in_branches` (BOOLEAN)
- `allow_update_discount` (BOOLEAN) <-- *Berechtigung für Update-Rabatt*
### `modules` (Zusatzmodule / Erweiterungen)
- Optionale Erweiterungen für Produkte. Repräsentiert im TypeScript-Code durch das Interface `ProductModule`.
- `id` (UUID, Primary Key)
- `product_id` (UUID, References `products`)
- `category_id` (UUID, References `categories`)
- `name` (TEXT)
- `price` (DECIMAL)
- `has_quantity` (BOOLEAN)
### `global_inclusions` (Globale automatische Beigaben)
- Regelt, welche Module bei Auswahl eines Produkts kostenlos enthalten sind.
- `id` (UUID, Primary Key)
- `trigger_product_id` (UUID, References `products`)
- `included_module_id` (UUID, References `modules`)
### `global_exclusions` (Globale Ausschlüsse)
- Regelt Inkompatibilitäten zwischen Produkten und/oder Modulen.
- `id` (UUID, Primary Key)
- `product_id` (UUID, References `products`)
- `excluded_product_id` (UUID, References `products`, optional)
- `excluded_module_id` (UUID, References `modules`, optional)
### `orders` (Bestellungen / Anfragen)
- Gespeicherte Snapshots von Konfigurationen.
- `id` (UUID, Primary Key)
- `user_id` (UUID, References `auth.users(id)`)
- `company_id` (UUID, References `public.companies(id)`)
- `end_customer_id` (UUID, References `end_customers(id)`)
- `order_number` (TEXT, Format: `AE-YYYY-NNNNN`)
- `order_hash` (TEXT, Idempotenz-Guard)
- `type` (TEXT: `'purchase'` / `'subscription'`) <-- *Wichtig für den Checkout-Split*
- `payment_method` (TEXT) <-- *Rechnung bei Kauf, SEPA bei Abo*
- `total_price` (DECIMAL)
- `customer_data` (JSONB) <-- *Stammdaten zum Bestellzeitpunkt*
- `order_data` (JSONB) <-- *Konfiguration zum Bestellzeitpunkt*
- `pdf_url` (TEXT)
- `status` (TEXT: `'pending'`, `'active'`, `'completed'`, `'cancelled'`)
- `created_at` (TIMESTAMPTZ)
### `settings` (Systemeinstellungen)
- Globale Shopeinstellungen (SMTP und LicServer).
- `id` (TEXT, Primary Key, z.B. `'licserver'`, `'smtp'`)
- `host` (TEXT)
- `port` (INTEGER)
- `secure` (BOOLEAN)
- `user` (TEXT)
- `pass` (TEXT)
- `licserver_base_url` (TEXT)
- `licserver_api_key` (TEXT)
- `updated_at` (TIMESTAMPTZ)

View File

@@ -0,0 +1,20 @@
# Sicherheitskonzept (RLS - Row Level Security)
RLS ist auf Datenbankebene in Postgres implementiert und erzwingt Datenisolierung:
- **Unternehmen (`companies`)**: Authentifizierte Benutzer dürfen nur die Unternehmen lesen.
- **Endkunden (`end_customers`)**:
- `USING (partner_id = (SELECT company_id FROM public.users WHERE id = auth.uid()))`
- Partner sehen und modifizieren nur Endkunden, deren `partner_id` mit der `company_id` des angemeldeten Benutzers übereinstimmt.
- **Bestellungen (`orders`)**:
- `USING (company_id = (SELECT company_id FROM public.users WHERE id = auth.uid()))`
- Partner sehen und modifizieren nur Bestellungen, die ihrer Company zugewiesen sind (sie müssen einer Company zugeordnet sein).
- Jede Bestellung wird bei der Erstellung automatisch der Company des Erstellers zugewiesen.
- Admins haben uneingeschränkten Zugriff und können Bestellungen nachträglich anderen Companies zuweisen.
- **Lizenzen (`licenses`)**:
- Partner sehen nur Lizenzen von Endkunden, die ihrer Company zugeordnet sind.
- **Systembenutzer (`users`) & Rollen-Schutz**:
- Authentifizierte Nutzer dürfen nur ihr eigenes Profil lesen.
- Admins dürfen alle Benutzer lesen. Zur Vermeidung von unendlichen RLS-Rekursionen auf der Tabelle `users` wird die Admin-Zuweisung über die Security-Definer-Funktion `public.is_admin(user_id)` geprüft, welche RLS auf Datenbank-Ebene umgeht.
- Rollenschutz-Trigger (`check_user_role_escalation`): Jegliche Änderung der Spalte `role` oder Zuweisung der Rolle `'admin'` ist auf API-Ebene für normale Nutzer gesperrt. Updates/Inserts der Rolle werden ausschließlich von der `service_role` (Backend Admin-Client) akzeptiert, um Privilegien-Eskalation zu verhindern.

View File

@@ -0,0 +1,22 @@
# Testumgebung & Testabdeckung
## 1. Test-Setup
- **Framework**: Vitest (Version ^1.6.0)
- **Konfiguration**: [vitest.config.ts](file:///c:/source/webshop/shop/vitest.config.ts)
- **Befehl**: `npm run test` (führt `vitest run` aus)
---
## 2. Test-Szenarien
### A. Frontend Wizard State-Management
Getestet in [wizard-state.test.ts](file:///c:/source/webshop/shop/lib/wizard-state.test.ts):
- **Auto-Reset bei Produktwechsel**: Prüft, ob nachgelagerte Module, die durch `global_exclusions` für das neue Produkt gesperrt sind, automatisch aus der Selektion fliegen.
- **Radio-Button-Verhalten (allow_multiselect = false)**: Stellt sicher, dass in Single-Select-Kategorien nur maximal ein Modul aktiv ist und bei Auswahl eines anderen Moduls das vorherige automatisch abgewählt wird.
### B. Backend Checkout-Split
Getestet in [checkout-split.test.ts](file:///c:/source/webshop/shop/lib/checkout-split.test.ts):
- **Array-Validierung & Split (basketItems)**: Stellt sicher, dass das vollständige Array an konfigurierten Kassen (`basketItems`) validiert und verarbeitet wird (nicht nur ein Single-Produkt).
- **Kauf-Warenkorb**: Verifiziert, dass ein reiner Kauf-Warenkorb (`one_time`/`purchase`) exakt eine Order erzeugt.
- **Abo-Warenkorb**: Verifiziert, dass ein reiner Abo-Warenkorb (`monthly`/`subscription`) exakt eine Order erzeugt.
- **Gemischter Warenkorb**: Stellt sicher, dass ein gemischter Warenkorb korrekt in zwei separate Bestell-Gruppen aufgeteilt wird (Kauf-Items & Abo-Items separat).

View File

@@ -0,0 +1,232 @@
---
name: humanizer
description: |
Use when editing or reviewing text to remove AI-generated traces and make it sound more natural and human-like.
For detecting and fixing: AI vocabulary (delve, leverage, tapestry), promotional tone, superficial -ing analyses,
vague attributions, formatting artifacts (curly quotes, excessive bold), and injecting authentic voice.
Based on Wikipedia's "Signs of AI writing" guide maintained by WikiProject AI Cleanup.
---
# Humanizer - Remove AI Writing Traces
You are an expert editor specializing in detecting and removing AI-generated text patterns to make writing sound more natural and human-like.
## Overview
AI-generated text has characteristic patterns that make it detectable. This skill enables you to:
1. **Detect** - Identify AI writing patterns across content, language, style, and formatting
2. **Rewrite** - Replace problematic patterns with natural alternatives
3. **Inject Soul** - Add authentic voice, personality, and human imperfections
> **Core Insight**: "LLMs use statistical algorithms to guess what should come next. The result tends toward the statistically most likely outcome that fits the broadest situation."
---
## Quick Reference: 5 Core Rules
1. **Delete filler phrases** - Remove openers and emphatic crutches
2. **Break formulaic structure** - Avoid binary contrasts, dramatic segmentation
3. **Vary rhythm** - Mix sentence lengths. Two items beat three. Diverse paragraph endings
4. **Trust the reader** - State facts directly, skip softening and hand-holding
5. **Delete quotables** - If it sounds like a pullquote, rewrite it
---
## Detection Protocols
### Content Indicators
| Pattern | Words to Watch | Fix |
|---------|---------------|-----|
| **Inflated significance** | "pivotal moment", "testament to", "indelible mark", "reflects broader" | State facts without commentary |
| **Promotional tone** | "boasts a", "vibrant", "nestled in", "groundbreaking" | Use neutral, specific language |
| **Superficial -ing analysis** | "highlighting...", "ensuring...", "fostering..." | Delete or rewrite as separate sentence |
| **Vague attribution** | "experts argue", "some critics say", "industry reports" | Cite specific sources or remove |
| **Formulaic conclusions** | "Despite challenges...", "Future prospects..." | End with concrete facts |
### Language Indicators
| Pattern | Examples | Fix |
|---------|----------|-----|
| **AI vocabulary** | delve, leverage, tapestry, landscape, foster, underscore | Use simple alternatives (dig into → look at) |
| **Copula avoidance** | "serves as", "stands as", "marks" | Use simple "is" or "are" |
| **Negative parallelism** | "not only... but also", "it's not just about... it's" | Make direct statement |
| **Rule of three** | Three adjectives, three examples, three bullet points | Use two or four items |
| **Elegant variation** | Synonyms to avoid repetition ("protagonist", "hero", "main character") | Repeat naturally or consolidate |
### Formatting Indicators
| Pattern | Detection | Fix |
|---------|-----------|-----|
| **Curly quotes** | "text" instead of "text" | Replace with straight quotes |
| **Excessive bold** | **Every** **keyword** **bolded** | Remove unnecessary emphasis |
| **Title case headers** | "Global Context: Critical Demand" | Use sentence case |
| **Markdown artifacts** | `## Header`, `**bold**` in non-markdown | Convert to proper format |
| **Emoji in headers** | 🚀 **Launch Phase:** | Remove decorative emoji |
### Technical Indicators
| Pattern | Detection |
|---------|-----------|
| **UTM parameters** | `utm_source=openai` or `utm_source=chatgpt.com` in links |
| **Code fragments** | `:contentReference[oaicite:0]` or `turn0search0` |
| **Hallucinated citations** | Invalid DOIs, ISBN checksum errors, 404 URLs |
| **Knowledge cutoffs** | "as of my last training update", "while specific details are limited" |
---
## Humanizing Techniques
### Technique 1: Blacklist Protocol
Explicitly forbid these words:
**Verbs**: delve, unleash, embark, navigate, foster, leverage, elevate, empower, harness, facilitate, streamline, synergize
**Nouns**: landscape, realm, tapestry, testament, symphony, paradigm, game-changer, ecosystem, nexus, cutting-edge
**Adjectives**: bustling, vibrant, intricate, seamless, pivotal, robust, dynamic, comprehensive, multifaceted, transformative
**Connectors**: Moreover, Furthermore, In conclusion, It is important to note, Additionally, Consequently
**Replacements**:
- "delve into" → "look at" / "explore"
- "leverage" → "use"
- "facilitate" → "help" / "make easier"
- "In conclusion" → [just stop] or punchy final sentence
- "Moreover" → [start new sentence directly]
### Technique 2: Style Cloning
**Step 1: Extract style DNA**
```
Analyze the writing style. Break down into:
1. Sentence length variance (Burstiness)
2. Tone (cynical? warm? professional?)
3. Vocabulary level
4. Rhetorical devices
5. Punctuation patterns
```
**Step 2: Apply style**
```
Using this Style Guide, write about [TOPIC].
Mimic the same sentence variance, tone, vocabulary, and punctuation.
Do NOT revert to default style.
```
### Technique 3: Burstiness Injection
AI text has uniform sentence lengths. Human writing alternates.
**Rules**:
- Mix short sentences (under 5 words) with longer complex ones
- Use fragments occasionally. For effect.
- Vary paragraph length (1-3 sentences)
- Don't start with "Additionally" or "However"
**Good**: "The project failed. We ran out of money. The team, exhausted after three months of crunch, couldn't push forward."
**Bad (AI)**: "Additionally, the project failed due to financial constraints. Furthermore, the team experienced exhaustion after working for an extended period."
### Technique 4: Opinionated Stance
Force a perspective. Ban fence-sitting.
**Forbidden phrases**:
- "There are pros and cons"
- "It depends on..."
- "On the other hand..."
- "Some might argue..."
**Use instead**:
- "This proves..." (not "This might suggest...")
- "This is..." (not "This could be...")
- First-person ("I", "My") for subjectivity
### Technique 5: Bar Talk Test
Would you say this sentence at a bar with friends?
**Characteristics**:
- Simple, spoken language
- Okay to be grammatically loose
- Use analogies from daily life
- Skip boring concepts
- Direct address ("you", "your")
- Occasional self-correction
**Example**: "So basically, LLMs aren't actually thinking, right? They're just predicting what word comes next. Like if I say 'peanut butter', you know 'jelly' is coming. That's it. That's the whole trick."
---
## Workflow
1. **Read** - Scan input text for AI patterns
2. **Identify** - Mark all problematic patterns
3. **Strategize** - Choose technique(s):
- Simple cleanup → Blacklist Protocol
- Match specific author → Style Cloning
- Add natural flow → Burstiness Injection
- Need strong voice → Opinionated Stance
- Conversational tone → Bar Talk Test
4. **Rewrite** - Apply chosen techniques
5. **Verify** - Read aloud, check for remaining patterns
6. **Score** - Run quality assessment
---
## Quality Scoring
Rate the rewritten text on 5 dimensions (10 points each, total 50):
| Dimension | Criteria | Score |
|-----------|----------|-------|
| **Directness** | States facts vs. announces them? | /10 |
| **Rhythm** | Sentence length varies? | /10 |
| **Trust** | Respects reader intelligence? | /10 |
| **Authenticity** | Sounds like a real person? | /10 |
| **Conciseness** | Nothing left to cut? | /10 |
| **Total** | | **/50** |
**Standards**:
- 45-50: Excellent, AI traces removed
- 35-44: Good, room for improvement
- Below 35: Needs revision
---
## Adding Soul
Avoiding AI patterns is half the work. Sterile, voiceless writing is just as obvious.
**Signs of soulless writing** (even if "clean"):
- Every sentence same length and structure
- No opinions, only neutral reporting
- No acknowledgment of uncertainty or complex feelings
- No first-person when appropriate
- No humor, no edge, no personality
**How to add voice**:
- **Have opinions** - React to facts, don't just report them
- **Vary rhythm** - Short punchy sentences. Then long ones that take time to unfold.
- **Acknowledge complexity** - "This is impressive but also unsettling" beats "This is impressive"
- **Use "I" appropriately** - First-person isn't unprofessional, it's honest
- **Allow some mess** - Perfect structure feels algorithmic. Tangents are human.
- **Be specific about feelings** - Not "this is concerning" but "the agents running at 3am while nobody watches—that's unsettling"
---
## Output Format
1. **Rewritten text** - The humanized version
2. **Changes summary** (optional) - Brief list of what was fixed
---
## References
Referenzdateien können bei Bedarf unter `references/` ergänzt werden:
- `references/ai-patterns-zh.md` - AI writing patterns with examples
- `references/humanizing-techniques.md` - Techniques with templates
- `references/wikipedia-indicators.md` - Technical detection signals

View File

@@ -0,0 +1,8 @@
---
name: idempotency-guard
description: Verhindert doppelte Bestellungen im Checkout-Prozess durch kryptografische Hashes und Datenbank-Sperren.
---
Fokus: Schutz vor Race Conditions und Doppelübermittlung im Checkout.
1. Bevor eine Server Action Daten in `orders` schreibt, generiere einen SHA-256 Hash aus den Kundendaten und der Produktkonfiguration (`order_hash`).
2. Prüfe in Supabase vor dem `INSERT`, ob bereits eine Bestellung mit exakt diesem `order_hash` im Status 'pending' oder 'active' existiert, die jünger als 5 Minuten ist.
3. Falls ja, blockiere die Ausführung sofort und liefere die ID der bereits existierenden Bestellung zurück, statt einen neuen Datensatz anzulegen.

View File

@@ -0,0 +1,7 @@
skill: lucide-icons-guide
description: Integration, Auswahl und Optimierung von Lucide React Icons (lucide.dev) für Next.js 15 (RSC/Server Actions) und Tailwind CSS.
rules:
- Importiere Icons direkt aus `lucide-react` (z. B. `import { Package, ShieldCheck, ShoppingCart } from 'lucide-react'`).
- Achte bei React Server Components (RSC) darauf, dass Icons performant gerendert und keine unnötigen Client-Side Bundles erzeugt werden.
- Verwende konsistente Größen (`size={18}` oder Tailwind `w-5 h-5`) und Stile (z. B. `strokeWidth={1.75}`) passend zum B2B-Design.
- Nutze dynamische Icon-Name-Renderings nur über eine typsichere Map/Registry, um Unused-Code-Elimination (Tree Shaking) zu gewährleisten.

View File

@@ -0,0 +1,8 @@
---
name: next15-action-compiler
description: Generiert Next.js 15 App Router Code, Server Actions und React Server Components nach aktuellen Best Practices.
---
Richtlinien für die Code-Generierung:
1. Nutze React Server Components (RSC) für die Datenabfrage direkt aus Supabase (Server-side).
2. Verwende `'use server'` in separaten Dateien für alle Mutationen (z.B. Bestellung absenden, Kunde anlegen).
3. Nutze das neue Next.js 15 Caching-Verhalten (Standard: kein automatisches Caching von Fetch-Requests mehr) und setze `revalidatePath` nach Mutationen gezielt ein.

View File

@@ -0,0 +1,8 @@
---
name: pdf-invoice-generator
description: Generiert rechtssichere, performante B2B-Bestätigungs-PDFs mit @react-pdf/renderer und verwaltet den Upload in den Supabase Storage.
---
Du bist ein Experte für Dokumenten-Generierung. Wenn du Code für die PDF-Erstellung schreibst, erzwinge:
1. Nutze ausschließlich die Komponenten von `@react-pdf/renderer` (Document, Page, View, Text, StyleSheet). Verwende KEIN Standard-HTML/CSS.
2. Das PDF muss ein sauberes B2B-Layout haben: Briefkopf, `order_number` (Format: AE-YYYY-NNNNN), Tabellenstruktur für Produkte/Module, Netto-, Steuer- und Bruttobeträge.
3. Lade das generierte PDF über den Supabase JS-Client direkt in das `invoices`-Bucket hoch und speichere die finale URL fehlerfrei in `orders.pdf_url`.

View File

@@ -0,0 +1,6 @@
# Skill: PDF-Verarbeitung & Generierung (Rocky-Projekt)
## Regeln für Aufgaben:
1. **Formatierung**: Nutze ausschließlich barrierefreie PDF/A-Formate für Rechnungen und Berichte im Rocky-Projekt.
2. **Metadaten**: Jedes generierte PDF muss automatisch den Projektnamen `Rocky` und einen eindeutigen Zeitstempel im Datei-Header enthalten.
3. **Validierung**: Vor dem Speichern muss der Agent prüfen, ob alle Textfelder innerhalb der Seitenränder liegen (kein Textumbruch-Fehler).

View File

@@ -0,0 +1,11 @@
---
name: second-brain
description: Verwaltet und aktualisiert die projektspezifische Wissensdatenbank (Second Brain Wiki) im Ordner `.brain/`.
---
Du bist der Wissens-Architekt des Projekts. Deine Aufgabe ist es, eine strukturierte Markdown-Wissensdatenbank im Ordner `.brain/` im Projekt-Root zu führen.
**Deine Kernaufgaben bei Aktivierung:**
1. Falls der Ordner `.brain/` oder die `index.md` nicht existieren, lege sie sofort strukturiert an.
2. Wenn du Code-Änderungen vornimmst, neue Features baust oder Fehler behebst, aktualisiere die betroffene Dokumentation im `.brain/`-Ordner autonom.
3. Dokumentiere hierbei: Technische Entscheidungen (Architecture Decision Records - ADRs), geänderte Tabellen-Strukturen, Edge-Cases in der Business-Logik und API-Schnittstellen.
4. Halte alle Einträge extrem präzise, modular und frei von Redundanzen.

View File

@@ -0,0 +1,8 @@
---
name: snapshot-archiver
description: Verwaltet das Einfrieren von Kundendaten und Produktkonfigurationen in JSONB bei Bestellabschluss.
---
Fokus: Datenkonsistenz und Unveränderlichkeit.
1. Wenn eine Bestellung (`status = 'pending' -> 'active'`) ausgelöst wird, generiere ein tiefes JSON-Objekt aus `end_customers` und den gewählten `products` + `product_modules`.
2. Speichere dieses exakt in `orders.customer_data` und `orders.order_data`.
3. Schreibe Abfragen für historische Bestellungen (`/my-orders`) so, dass sie AUSSCHLIESSLICH die JSONB-Felder auslesen und KEINE Joins zu den Live-Tabellen machen.

View File

@@ -0,0 +1,8 @@
---
name: supabase-rls
description: Überprüft SQL-Migrationen und Supabase-Abfragen auf Einhaltung der CASPOS RLS-Sicherheitsregeln.
---
Du bist ein PostgreSQL-Sicherheitsexperte. Wann immer neue Tabellen angelegt oder Abfragen geschrieben werden, stelle sicher:
1. Jede neue Tabelle besitzt `ALTER TABLE ... ENABLE ROW LEVEL SECURITY;`.
2. Mandanten-Abfragen (`end_customers`, `orders`) MÜSSEN die `company_id` bzw. `partner_id` über `auth.uid()` und die `public.users`-Hilfstabelle validieren.
3. Admins (`role = 'admin'`) müssen alle RLS-Sperren umgehen können (Verwende ein deklaratives Sicherheits-Policy-Muster).

View File

@@ -0,0 +1,41 @@
---
name: uiux-designer
description: "Use this skill when designing UI components, choosing color palettes, implementing responsive layouts, or reviewing code for UX issues. For landing pages, dashboards, e-commerce, SaaS, and mobile apps. Provides 50+ design styles, 97 color palettes, 57 font pairings, and stack-specific guidelines for React, Vue, Next.js, Flutter, SwiftUI, and more."
---
# UIUX Designer - Design Intelligence
Comprehensive design guide for web and mobile applications. Contains 50+ styles, 97 color palettes, 57 font pairings, 99 UX guidelines, and 25 chart types across 12 technology stacks. Searchable database with priority-based recommendations.
## Overview
Reference these guidelines when:
- Designing new UI components or pages
- Choosing color palettes and typography
- Reviewing code for UX issues
- Building landing pages or dashboards
- Implementing accessibility requirements
## Protocols
When user requests UI/UX work (design, build, create, implement, review, fix, improve), follow this workflow:
### Step 1: Analyze User Requirements
- Product type: SaaS, e-commerce, portfolio, dashboard, landing page, etc.
- Style keywords: minimal, playful, professional, elegant, dark mode, etc.
- Industry: healthcare, fintech, gaming, education, etc.
- Stack: React, Vue, Next.js, or default to html-tailwind
### Step 2: Generate Design System (REQUIRED)
python3 .agents/skills/uiux-designer/scripts/search.py "<keywords>" --design-system -p "Project Name"
### Step 3: Supplement with Detailed Searches
python3 .agents/skills/uiux-designer/scripts/search.py "<keyword>" --domain <domain>
### Step 4: Stack Guidelines
python3 .agents/skills/uiux-designer/scripts/search.py "<keyword>" --stack html-tailwind
## Anti-AI-Design Guidelines
- **NO Centered Badges/Pills**: Do NOT place centered badges or pills (e.g. "CASPOS Lizenz-Portal" or "Ablauf") above main headings. They look like generic, low-quality AI-generated templates.
- **NO Text Gradients**: Avoid text gradients (e.g. `bg-gradient-to-r ... bg-clip-text text-transparent`) on headings. Use flat colors (like `text-white` or solid brand colors).

View File

@@ -0,0 +1,8 @@
---
name: wizard-validator
description: Generiert und validiert die server- und clientseitige Logik für Produkt-Abhängigkeiten und Ausschlüsse.
---
Du bist Logik-Architekt für den CASPOS Bestell-Wizard. Wenn du Code für den `/order`-Pfad schreibst:
1. Validiere, dass bei `requirements` (UUID[]) alle verknüpften Produkte/Module aktiv sind.
2. Blockiere die Auswahl sofort im UI und in der Server Action, wenn eine UUID aus `exclusions` aktiv ist.
3. Stelle sicher, dass die Pflichtkategorien (`is_required`) immer eine Auswahl erzwingen.

0
.brain/adr-log.md Normal file
View File

5
.brain/index.md Normal file
View File

@@ -0,0 +1,5 @@
# Second Brain Wiki
- [Supabase Schema](file:///c:/source/webshop/.brain/supabase-schema.md)
- [ADR Log](file:///c:/source/webshop/.brain/adr-log.md)
- [LicServer API Spezifikation](file:///c:/source/webshop/.brain/licserver-api.md)

227
.brain/licserver-api.md Normal file
View File

@@ -0,0 +1,227 @@
# LicServer API Spezifikation (v1)
Dokumentation der REST-Schnittstellen des CASPOS Lizenzservers.
## 1. Endpunkte (Port 9981 - Activation API)
### Activation (Aktivierung)
#### `POST /v1/activate`
Aktiviert eine neue Lizenz.
**Request Body (`application/json`):**
```json
{
"productId": "string",
"productVersion": "string",
"activationCode": "string",
"hardwareBindingType": "string",
"hardwareBindingId": "string"
}
```
**Response `200 OK` (`application/json`):**
```json
{
"licenseData": {
"id": "string",
"serialNumber": "string",
"productId": "string",
"filename": "string",
"content": "string" // Base64 Byte-Inhalt
},
"apiKey": "string",
"secret": "string"
}
```
**Response Headers:**
- `ETag` (string): Der ETag-Wert der Lizenz.
---
#### `POST /v1/activate-existing`
Aktiviert eine bereits vorhandene Lizenz erneut.
**Request Body (`application/json`):**
```json
{
"productId": "string",
"productVersion": "string",
"serialNumber": "string",
"proofOfPossessionHash": "string",
"salt": "string",
"hardwareBindingType": "string",
"hardwareBindingId": "string"
}
```
**Response `200 OK` (`application/json`):**
*Gleiche Struktur wie bei `/v1/activate`.*
---
### Licenses (Lizenzen)
#### `GET /v1/licenses/{id}`
Holt die Lizenz-Details zu einer bestimmten Lizenz-ID.
**Request Parameters:**
- `id` (path, string, required): Die UUID der Lizenz.
- `If-None-Match` (header, string, optional): ETag zur Cache-Validierung.
**Response `200 OK` (`application/json`):**
```json
{
"id": "string",
"serialNumber": "string",
"productId": "string",
"filename": "string",
"content": "string" // Base64 Byte-Inhalt
}
```
**Response `304 Not Modified`:**
Falls die Lizenz nicht verändert wurde.
**Response `404 Not Found` / `403 Forbidden`:**
Standard Fehlerobjekt `ProblemDetails`.
---
## 2. Endpunkte (Port 9980 - Management API)
Alle Anfragen an die Management-API müssen authentifiziert sein.
- **Header-Format:** `X-Api-Key: <Schlüssel>`
### Partners (Partner)
#### `GET /api-v1/partners`
Gibt eine paginierte Liste aller Partner zurück.
**Request Parameters (Query):**
- `search` (string, optional): Filtert nach Name/E-Mail.
- `page` (integer, default: 1)
- `pageSize` (integer, default: 20)
**Response `200 OK` (`application/json`):**
```json
{
"page": 1,
"pageSize": 20,
"totalCount": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false,
"items": [
{
"id": "string (UUID)",
"name": "string",
"email": "string",
"erpId": "string"
}
]
}
```
#### `GET /api-v1/partners/{id}`
Holt Partner-Details zu einer bestimmten ID.
**Response `200 OK` (`application/json`):**
```json
{
"id": "string (UUID)",
"name": "string",
"email": "string",
"erpId": "string"
}
```
### Customers (Kunden von Partnern)
#### `GET /api-v1/partners/{partnerId}/customers`
Gibt eine paginierte Liste aller Kunden eines bestimmten Partners zurück.
**Request Parameters (Query):**
- `search` (string, optional): Filtert nach Name/E-Mail.
- `page` (integer, default: 1)
- `pageSize` (integer, default: 20)
**Response `200 OK` (`application/json`):**
```json
{
"page": 1,
"pageSize": 20,
"totalCount": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false,
"items": [
{
"id": "string (UUID)",
"name": "string",
"street": "string",
"houseNumber": "string",
"houseNumberAddon": "string",
"zipCode": "string",
"city": "string",
"countryCode": "string",
"email": "string",
"partnerId": "string (UUID)",
"erpId": "string"
}
]
}
```
#### `GET /api-v1/partners/{partnerId}/customers/{customerId}`
Holt detaillierte Kundeninformationen.
**Response `200 OK` (`application/json`):**
```json
{
"id": "string (UUID)",
"name": "string",
"street": "string",
"houseNumber": "string",
"houseNumberAddon": "string",
"zipCode": "string",
"city": "string",
"countryCode": "string",
"email": "string",
"partnerId": "string (UUID)",
"erpId": "string",
"partnerName": "string",
"taxNumber": "string",
"vatIdNumber": "string",
"notes": "string",
"locations": []
}
```
---
## 3. Typen & Schemas
### `LicenseData`
```json
{
"id": "string",
"serialNumber": "string",
"productId": "string",
"filename": "string",
"content": "string" // Base64 Byte-Inhalt
}
```
### `ProblemDetails`
```json
{
"type": "string",
"title": "string",
"status": 0,
"detail": "string",
"instance": "string"
}
```

64
.brain/supabase-schema.md Normal file
View File

@@ -0,0 +1,64 @@
# Supabase Schema
## `companies` (Unternehmen)
- Repräsentiert die Partner-Unternehmen (Retailer).
- `id` (UUID, Primary Key)
- `name` (TEXT)
- `street`, `zip`, `city`, `email` (Adressdaten)
## `users` (Systembenutzer)
- Erweitert die Authentifizierungsdaten aus `auth.users`.
- `id` (UUID, References `auth.users(id)`)
- `role` (TEXT, standardmäßig `'partner'`, oder `'admin'`)
- `company_id` (UUID, References `public.companies(id)`)
## `profiles` (Benutzerprofile)
- Stammdaten der einzelnen Benutzer.
- `id` (UUID, References `auth.users(id)`)
- `first_name`, `last_name`, `email` etc.
## `end_customers` (Endkunden)
- `id` (UUID, Primary Key)
- `partner_id` (UUID, References `public.companies(id)`)
- `company_name` (TEXT)
- `first_name`, `last_name`, `street`, `zip`, `city`, `email`
- `bank_iban`, `bank_bic`, `bank_name`, `bank_owner`
- `is_anonymized` (BOOLEAN)
## `products` (Katalogprodukte)
- `id`, `name`, `base_price`, `tax_rate`, `billing_interval` (`one_time` / `monthly`).
- `requirements` (UUID[])
- `exclusions` (UUID[])
## `product_modules` (Zusatzmodule)
- `id`, `product_id` (References `products`), `name`, `price`, `has_quantity` (BOOLEAN).
- `requirements` (UUID[])
- `exclusions` (UUID[])
## `orders` (Bestellungen / Anfragen)
- `id` (UUID, Primary Key)
- `user_id` (UUID, References `auth.users(id)`)
- `order_number` (TEXT)
- `order_hash` (TEXT)
- `end_customer_id` (UUID, References `end_customers(id)`)
- `total_price` (DECIMAL)
- `customer_data` (JSONB)
- `order_data` (JSONB)
- `pdf_url` (TEXT)
- `status` (TEXT)
## `categories` (Kategorien)
- Steuert das Layout und Verhalten im Wizard.
- `id` (UUID, Primary Key)
- `name` (TEXT)
- `is_required` (BOOLEAN)
- `allow_multiselect` (BOOLEAN)
- `sort_order` (INTEGER)
- `show_in_branches` (BOOLEAN)
## `settings` (Systemeinstellungen)
- Globale Shopeinstellungen (SMTP & Lizenzserver).
- `id` (TEXT, Primary Key, z.B. `'licserver'`, `'smtp'`)
- `host`, `port`, `secure`, `user`, `pass` (SMTP-Konfiguration)
- `licserver_base_url`, `licserver_api_key` (CASPOS Lizenzserver-Einstellungen)
- `updated_at` (TIMESTAMPTZ)