12 KiB
12 KiB
AGENTS.md - AI Assistant Context
Dieses Dokument hilft AI-Assistenten (Amp, Copilot, etc.) das Projekt zu verstehen.
Projekt-Überblick
kashilo.com ist eine Kleinanzeigen-PWA mit Monero-Bezahlung.
- Status: Active Development (Frontend + Directus Backend)
- Ziel: Privater, dezentraler Marktplatz mit Monero
- Name: kashilo = Esperanto "kaŝilo" (Werkzeug zum Verbergen)
Tech-Stack
| Layer | Technologie |
|---|---|
| Frontend | Vanilla JS, Web Components, CSS Custom Properties |
| Routing | Hash-basierter Client-Side Router (js/router.js) |
| i18n | Custom System (js/i18n.js), JSON-Dateien in /locales/ |
| Theming | CSS Variables, Dark/Light Mode |
| Backend | Directus (api.kashilo.com) |
| Auth | UUID-basiert, anonym (js/services/auth.js) |
| E2E Crypto | TweetNaCl (self-hosted in js/vendor/), box.before + secretbox |
| PoW Captcha | PHP-Server (pow.kashilo.com), Fallback auf lokal |
Häufige Befehle
# Lokaler Entwicklungsserver
python3 -m http.server 8080
# Oder mit Live-Reload
npx live-server
# Build (JS/CSS minifizieren → dist/)
pip3 install rjsmin rcssmin # einmalig
python3 build.py
# Deploy (baut automatisch, dann rsync von dist/)
./deploy.sh
# Tests ausführen (im Browser)
# Server starten, dann http://localhost:8080/tests/ öffnen
# Git Push (Token in URL)
git push origin master
Commit-Konvention
Wenn der User nach "commit text" fragt:
- Immer nur eine einzeilige Commit-Message im Format:
git commit -m "..." - Keine mehrzeiligen Messages oder Body-Text
- Nutze Conventional Commits:
feat:,fix:,docs:,refactor:,chore: - Standardsprache: Englisch (außer User fragt explizit nach "de")
Dateistruktur
js/
├── app.js # Entry, lädt i18n, dann Shell
├── router.js # Hash-Router mit :params
├── i18n.js # t('key'), subscribe(), updateDOM()
├── services/
│ ├── directus.js # Directus API Client (Core)
│ ├── auth.js # UUID-basierte Authentifizierung (SHA-256 Hash)
│ ├── listings.js # Listings Service (Filter)
│ ├── categories.js # Kategorien Service (Baum, Übersetzungen, Cache)
│ ├── locations.js # Standorte Service (Geo-Suche)
│ ├── conversations.js # Zero-Knowledge Chat (E2E, per-listing keys)
│ ├── crypto.js # NaCl Encryption + per-listing keypair management
│ ├── key-pinning.js # TOFU Key-Pinning (warnt bei Schlüsseländerung)
│ ├── currency.js # XMR/Fiat Umrechnung
│ ├── pow-captcha.js # Proof-of-Work Captcha (Challenge/Verify)
│ ├── btcpay.js # BTCPay Server Integration (Invoice, Checkout, Webhook)
│ ├── favorites.js # Favoriten-Service (localStorage + Directus Sync)
│ ├── notifications.js # Benachrichtigungen (Polling, Badge)
│ ├── reputation.js # Reputation-System (Deals, Ratings, Level)
│ └── identity.js # Pseudonyme & Identicon-Avatare (deterministisch aus User-ID)
└── components/
├── app-shell.js # Layout, registriert Routes
├── app-header.js # Header (Theme-Toggle, Lang-Dropdown, Profil-Dropdown)
├── app-footer.js # Footer
├── auth-modal.js # Login/Register Modal (mit PoW-Captcha)
├── pow-captcha.js # PoW-Captcha Web Component
├── chat-widget.js # E2E Chat Widget
└── pages/ # Seiten als Web Components
docs/
├── DIRECTUS-SETUP.md # Directus Backend Setup
├── DIRECTUS-SCHEMA.md # Collection-Strukturen & Permissions
├── MONETIZATION.md # Monetarisierung & Anti-Abuse
├── LAUNCH-PLAN.md # Release-Phasen, Pricing, Checkliste
├── REPUTATION.md # Reputation-System (Konzept, Directus-Anleitung)
├── KILLER-FEATURES.md # Geplante Features (Blind Meeting Points, Verifiable Listings, Self-Destruct)
├── pow-server/ # PHP PoW-Captcha Server (pow.kashilo.com)
└── og-proxy.php # Open Graph Meta-Tag Proxy (pow.kashilo.com)
css/
├── fonts.css # @font-face Definitionen (Inter, Space Grotesk)
├── variables.css # CSS Custom Properties (Farben, Spacing)
├── base.css # Reset, Container
└── components.css # UI-Komponenten (Buttons, Cards, etc.)
assets/
├── fonts/ # Self-hosted Fonts (Inter, Space Grotesk)
└── press/ # Press Kit (Logos, OG-Image, Brand Guidelines)
tests/
├── index.html # Test-Runner UI (im Browser öffnen)
├── test-runner.js # Minimaler Test-Framework
├── helpers.test.js # Unit Tests für helpers.js
├── i18n.test.js # Unit Tests für i18n.js
├── router.test.js # Unit Tests für router.js
├── crypto.test.js # E2E Encryption, per-listing keys, TOFU
├── client.test.js # Directus Client Tests
└── services.test.js # Service Tests
locales/
├── de.json # Deutsch (Fallback)
├── en.json
├── fr.json
├── it.json # Italienisch
├── es.json # Spanisch
├── pt.json # Portugiesisch (BR)
└── ru.json # Russisch
Konventionen
JavaScript
- Keine Semikolons am Zeilenende (außer in for-loops, CSS)
- Englische Kommentare im Code
- ES Modules mit
import/export
Web Components
- Custom Elements mit
class extends HTMLElement - Styles als
<style>imdocument.headoder inline - i18n:
render()Methode, Subscribe auf Sprachwechsel - Auth-Subscriber nur in
connectedCallback(), nicht insetupEventListeners()
CSS
- Keine festen Farben - immer
var(--color-*)nutzen - Spacing:
var(--space-xs|sm|md|lg|xl|2xl|3xl) - Font-Size:
var(--font-size-xs|sm|base|lg|xl|2xl|3xl) - Font-Family:
var(--font-family)für Body,var(--font-family-heading)für Headlines - Border-Radius:
var(--radius-sm|md|lg|xl|full) - Breakpoint:
@media (max-width: 768px)- einziger Mobile-Breakpoint für alle Komponenten - Kontrast-Text:
var(--color-success-text)für Text auf Success-Hintergrund (Light:#fff, Dark:#042F2E)
i18n
- Schlüssel:
section.key(z.B.home.title) - Im HTML:
data-i18n="key"oder${t('key')} - Placeholder:
data-i18n-placeholder="key" - Neue Texte in allen 7 Sprachen hinzufügen (de, en, fr, it, es, pt, ru)
- Frontend nutzt Kurzcodes (
de), Directus Langcodes (de-DE) — Mapping ini18n.js(LOCALE_TO_DIRECTUS)
Aktuelle Probleme / Hinweise
- SSH funktioniert nicht mit diesem Repo auf gitea.pro - HTTPS mit Token nutzen
- Service Worker kann lokale Änderungen cachen - bei Problemen Cache leeren
- i18n muss vor Shell laden - siehe
app.js(dynamischer Import) - E2E Chat: Per-listing Keypairs (nicht Account-Key) für Seller-Identität. Listing braucht
contact_public_keyFeld in Directus. TOFU Key-Pinning warnt bei Schlüsseländerung. Conversations/Messages nur über User-Rolle zugänglich (kein Public-Zugriff). Crypto-Storage ist per Account namespaced (kashilo_kp_<hash>,kashilo_salt_<hash>,kashilo_lk_<hash>) — unterstützt mehrere Accounts im selben Browser, Migration vom alten Format automatisch. Chat-Widget pollt alle 5s nach neuen Nachrichten wenn geöffnet. Conversations haben einbuyer_userFeld (UUID, FK → directus_users).
Nächste Schritte
Seiten für Profil-Dropdown✅ FertigSuchseite mit Filtern✅ Merged inpage-home.jsListings bearbeiten✅ Edit-Modus via#/edit/:idPoW-Captcha server-seitig✅ PHP-Server aufpow.kashilo.comTweetNaCl self-hosted✅ Injs/vendor/Chat-Crypto fix✅ Per-listing E2E Keys, TOFU Key-Pinning, kein Pending-Flow mehrPayment-Integration mit BTCpay Server✅ Proxy aufpow.kashilo.com, Frontend-Servicebtcpay.jsFavoriten Directus Sync✅ FavoritesService mit Union-Merge bei LoginExpired Listings✅ Directus Flow (alle 15 Min), Status-Badges auf CardsReputation-System✅reputation.jsService, Deals/Ratings Collections, Chat-Widget Deal-Bestätigung + Sterne-Bewertung, Seller-Card Badges (siehedocs/REPUTATION.md)In-App Benachrichtigungen✅ NotificationsService mit Polling, Glocke-Icon mit Badge- Push-Benachrichtigungen (Web Push API)
Monero MultiSig Escrow❌ Gestrichen (erfordert VASP-Lizenz + KYC, widerspricht Privacy-Konzept)- Tor Hidden Service (.onion URL)
- Öffentliche Statistiken (Anzeigen, User, Deals — erst ab Schwellwert anzeigen)
Pseudonyme & Avatare✅identity.js— deterministisch aus User-ID, Identicon + Name (Adjektiv+Tier+Zahl)Verifiable Listings✅verification.jsService,verification-widget.jsComponent, Badge auf Cards + Listing-Detail- Selbstzerstörende Listings (siehe
docs/KILLER-FEATURES.md) - Blind Meeting Points (siehe
docs/KILLER-FEATURES.md) - Öffentliche Q&A pro Listing (siehe
docs/KILLER-FEATURES.md)
Reputation-System (Konzept)
- Erfolgreiche Deals: Stufensystem (5/15/50 abgeschlossene Transaktionen)
- Account-Alter: Vertrauensbonus für ältere Accounts
- PoW-Difficulty: Höherer PoW-Aufwand bei Registrierung als "Skin in the Game"
- Kein KYC — Vertrauen durch nachweisbare Aktivität
- Visuelles Badge/Level auf Profil und Listings
Directus Berechtigungen (Public-Rolle)
| Collection | Read | Create | Update | Hinweise |
|---|---|---|---|---|
listings |
✓ | ✓ | ✓ | Nur status=published lesen, Update: views (Public), verified/verification_* (User) |
listings_files |
✓ | ✓ | - | Junction-Table für Bilder |
directus_files |
✓ | ✓ | - | Für Assets/Bilder |
categories |
✓ | - | - | Nur status=published |
categories_translations |
✓ | - | - | Für i18n |
locations |
✓ | ✓ | - | User kann neue Orte anlegen |
languages |
✓ | - | - | Für Sprachen-Liste |
conversations |
- | - | ✓ | Nur User-Rolle (Auth-Pflicht, kein Public-Zugriff). Update: buyer_user Feld |
messages |
- | - | - | Nur User-Rolle (Auth-Pflicht, kein Public-Zugriff) |
favorites |
✓ | ✓ | - | User-Rolle: Filter user = $CURRENT_USER, Delete erlaubt |
notifications |
✓ | ✓ (via Flow/Webhook) | ✓ | User-Rolle: Filter user_hash, nur read updaten |
deals |
✓ | ✓ | ✓ | Update nur *_confirmed, status, date_confirmed |
ratings |
✓ | ✓ | - | Bewertungen sind final, kein Update/Delete |
Directus Flows
| Flow | Trigger | Aktion |
|---|---|---|
| Archive Expired Listings | Schedule */15 * * * * |
status → archived wenn expires_at < NOW |
Deaktiviert — wird jetzt direkt von btcpay-webhook.php gehandhabt (mit Duplikat-Check) |
||
| Notify: New Message | Event Hook items.create on messages |
Read Data (Conversation + Listing) → Run Script (Empfänger ermitteln) → Condition → Create Data (Notification). Benötigt $full Permissions auf Read Data und Create Data |
Siehe docs/DIRECTUS-SCHEMA.md für vollständiges Schema.
Farbpalette
Warm Teal Theme
Light Mode:
- BG: #FAFAF9 (warm white)
- Text: #1C1917
- Accent: #0D9488 (Teal)
- Border: #D6D3D1
- Success: #16A34A / Warning: #D97706 / Error: #DC2626
Dark Mode:
- BG: #171717 (warm black)
- Text: #F5F5F4
- Accent: #2DD4BF (Teal light)
- Border: #3D3836
- Success: #4ADE80 / Warning: #FBBF24 / Error: #F87171