diff --git a/.gitignore b/.gitignore index b8969b8..60f9580 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,10 @@ backend/node_modules/ backend/.env + +# macOS metadata +.DS_Store +._.DS_Store + +# Playwright artifacts +backend/playwright-report/ +backend/test-results/ diff --git a/NEXT_STEPS.md b/NEXT_STEPS.md new file mode 100644 index 0000000..a12c5b7 --- /dev/null +++ b/NEXT_STEPS.md @@ -0,0 +1,30 @@ +# Nächste Schritte für helpyourneighbour + +## Aktueller Status +- Smoke-Test erfolgreich ausgeführt +- Docker nicht verfügbar (kein `docker` Befehl) +- Integrationstests fehlgeschlagen wegen Playwright-Konfigurationsfehler +- Es gibt 3 Commits, die noch nicht gepusht wurden +- Es gibt drei ungetrackte Dateien (NEXT_STEPS.md, PROJECT_SUMMARY.md, STATUS.md) + +## Konkrete nächste Schritte + +1. **Docker-Installation prüfen** + - Prüfen, ob Docker auf dem System installiert ist + - Falls nicht, Installation vorbereiten + +2. **Playwright-Konfiguration reparieren** + - Fehlerursache der Integrationstests identifizieren + - Konfiguration korrigieren + +3. **Lokalen Test-Prozess optimieren** + - `cd backend && npm ci && npm test` ausführen + - Ergebnisse dokumentieren + +4. **Dokumentation aktualisieren** + - STATUS.md aktualisieren mit aktuellen Fehlern und Lösungen + - NEXT_STEPS.md als Planungsdokument verwenden + +5. **Git-Status aufräumen** + - Ungetrackte Dateien commiten oder löschen + - Push auf origin durchführen \ No newline at end of file diff --git a/PROJECT_SUMMARY.md b/PROJECT_SUMMARY.md new file mode 100644 index 0000000..4c6edbf --- /dev/null +++ b/PROJECT_SUMMARY.md @@ -0,0 +1,51 @@ +# HelpYourNeighbour Projektübersicht + +## Projektbeschreibung +HelpYourNeighbour ist ein Backend-System für eine Plattform zur Unterstützung von Nachbarn. Es ermöglicht Nutzern, Hilfeanfragen zu stellen und anzubieten, sowie Deals abzuschließen und Bewertungen auszutauschen. + +## Hauptfunktionen +1. **Authentifizierung**: Registrierung und Login +2. **Hilfeanfragen**: Erstellen und Auflisten von Anfragen +3. **Angebote**: Erstellen, Verhandeln und Akzeptieren von Angeboten +4. **Bewertungssystem**: 2-14 Tage Verzögerung für Bewertungen +5. **Adressmanagement**: Änderung von Adressen per Briefbestätigung +6. **Kontaktdaten-Austausch**: Nach Deal abgeschlossen + +## Datenbankschema +Das System verwendet ein MySQL-Datenbankschema mit folgenden Tabellen: +- users: Nutzerdaten +- help_requests: Hilfeanfragen +- offers: Angebote +- negotiations: Verhandlungen +- deals: Abschlüsse +- contact_exchange_requests: Kontaktanfragen +- addresses: Adressen +- address_change_requests: Adressänderungsanfragen +- reviews: Bewertungen + +## Technologie Stack +- Backend: Node.js mit Express +- Datenbank: MySQL +- Authentifizierung: JWT +- Verschlüsselung: AES-256-GCM für sensible Daten +- Validierung: Zod +- Tests: Playwright (Integration), Custom (Smoke) + +## Testumgebung +- Smoke-Tests funktionieren +- Integrationstests haben Playwright-Konfigurationsprobleme +- Docker-basierte Testumgebung vorhanden, aber keine lokale Docker-Installation + +## Konfiguration +Die .env.example zeigt die Produktionskonfiguration mit externer Datenbank: +- DB_HOST=80.74.142.125 +- DB_PORT=3306 +- DB_NAME=helpyourneighbour +- DB_USER=helpyourneighbour +- DB_PASSWORD=change-me + +## Nächste Schritte für Entwicklung +1. Lokale MySQL-Datenbank einrichten +2. Docker-Installation prüfen oder installieren +3. Testumgebung vollständig aufbauen +4. Integrationstests reparieren \ No newline at end of file diff --git a/README.md b/README.md index 5d2dff6..9996495 100644 --- a/README.md +++ b/README.md @@ -41,3 +41,13 @@ npm run start - OpenAPI: `openapi.yaml` (Spiegel: `docs/openapi.yaml`) - Versioning/Deprecation Policy: `docs/api-versioning.md` - Rollen- und Rechtekonzept: `docs/roles-and-permissions.md` + +## Development Quickstart (auto-synced) + +```bash +cd backend +npm install +npm test +npm run start +``` + diff --git a/STATUS.md b/STATUS.md new file mode 100644 index 0000000..0edb19a --- /dev/null +++ b/STATUS.md @@ -0,0 +1,22 @@ +# Status des HelpYourNeighbour Projekts + +## Aktueller Stand +- Projekt ist ein Backend für eine Hilfeplattform mit Auth, Requests, Offers, Deals, Reviews, Address-Management +- Datenbank-Schema ist vollständig implementiert +- Backend verwendet Node.js mit Express, MySQL, bcryptjs, jsonwebtoken, zod +- Es gibt Test-Skripte für Smoke- und Integrationstests + +## Getestete Funktionen +- Smoke-Test erfolgreich: Syntax Checks OK +- Integrationstests fehlgeschlagen: Playwright-Konfigurationsfehler +- Datenbankinitialisierung fehlgeschlagen: Keine MySQL-Datenbank verfügbar + +## Verfügbare Konfigurationen +- .env.example zeigt Produktionskonfiguration für externe Datenbank +- Docker Compose Test-Umgebung vorhanden, aber keine lokale Docker-Installation + +## Nächste Schritte +1. Lokale MySQL-Datenbank einrichten für Entwicklung +2. Backend mit lokaler Datenbank testen +3. Integrationstests reparieren oder anpassen +4. Vollständige Entwicklungsumgebung aufbauen \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index fafb01e..f3e6fe3 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -15,6 +15,26 @@ "jsonwebtoken": "^9.0.3", "mysql2": "^3.18.2", "zod": "^4.3.6" + }, + "devDependencies": { + "@playwright/test": "^1.58.2", + "playwright": "^1.58.2" + } + }, + "node_modules/@playwright/test": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" } }, "node_modules/@types/node": { @@ -378,6 +398,21 @@ "node": ">= 0.8" } }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -794,6 +829,38 @@ "url": "https://opencollective.com/express" } }, + "node_modules/playwright": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", diff --git a/backend/package.json b/backend/package.json index 28162e3..af10e91 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "backend", - "comment": "added by heartbeat" + "comment": "added by heartbeat", "version": "1.0.0", "description": "", "main": "index.js", @@ -10,7 +10,8 @@ "dev": "node --watch src/server.js", "db:init": "node src/db/init.js", "db:seed": "node src/db/seed.js", - "test:smoke": "node scripts/smoke-test.mjs" + "test:smoke": "node scripts/smoke-test.mjs", + "test:integration": "node scripts/integration-test.mjs" }, "keywords": [], "author": "", @@ -23,5 +24,9 @@ "jsonwebtoken": "^9.0.3", "mysql2": "^3.18.2", "zod": "^4.3.6" + }, + "devDependencies": { + "@playwright/test": "^1.58.2", + "playwright": "^1.58.2" } } diff --git a/backend/playwright.config.js b/backend/playwright.config.js new file mode 100644 index 0000000..d2fc64f --- /dev/null +++ b/backend/playwright.config.js @@ -0,0 +1,27 @@ +const { defineConfig, devices } = require('@playwright/test'); + +module.exports = defineConfig({ + testDir: './tests', + timeout: 30000, + expect: { + timeout: 5000 + }, + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: 'html', + use: { + actionTimeout: 0, + baseURL: 'http://localhost:3000', + trace: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}); \ No newline at end of file diff --git a/backend/playwright.config.mjs b/backend/playwright.config.mjs new file mode 100644 index 0000000..d063a8f --- /dev/null +++ b/backend/playwright.config.mjs @@ -0,0 +1,27 @@ +import { defineConfig } from '@playwright/test'; + +export default defineConfig({ + testDir: './tests', + timeout: 30000, + expect: { + timeout: 5000 + }, + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + reporter: 'html', + use: { + actionTimeout: 0, + baseURL: 'http://localhost:3000', + trace: 'on-first-retry', + }, + projects: [ + { + name: 'chromium', + use: { + // ...devices['Desktop Chrome'], + }, + }, + ], +}); \ No newline at end of file diff --git a/backend/scripts/integration-test.mjs b/backend/scripts/integration-test.mjs new file mode 100644 index 0000000..4cb2951 --- /dev/null +++ b/backend/scripts/integration-test.mjs @@ -0,0 +1,24 @@ +// Einfacher HTTP-Test ohne Playwright +// Funktion zum Senden einer HTTP-Anfrage +async function testHealthEndpoint() { + try { + const response = await fetch('http://localhost:3000/health'); + if (response.status === 200) { + console.log('Integration test passed: API server is running and healthy'); + return true; + } else { + console.error(`Integration test failed: Expected status 200, got ${response.status}`); + return false; + } + } catch (error) { + console.error('Integration test failed:', error.message); + return false; + } +} + +// Führe den Test aus +testHealthEndpoint().then(success => { + if (!success) { + process.exit(1); + } +}); \ No newline at end of file diff --git a/backend/src/services/encryption.test.js b/backend/src/services/encryption.test.js new file mode 100644 index 0000000..ce20df1 --- /dev/null +++ b/backend/src/services/encryption.test.js @@ -0,0 +1,23 @@ +import { encryptText, decryptText } from './encryption.js'; + +const TEST_KEY = 'YixWi1MYh77NMEQYSJZR+2IsVotTGIe+zTBEGEiWUfs='; // 32 bytes base64 + +process.env.DATA_ENCRYPTION_KEY = TEST_KEY; + +const run = async () => { + const plain = 'Hello, World! 123'; + const encrypted = encryptText(plain); + const decrypted = decryptText(encrypted); + + if (decrypted !== plain) { + console.error('Decryption mismatch:', { plain, decrypted }); + process.exit(1); + } + + console.log('Encryption tests passed'); +}; + +run().catch((err) => { + console.error('Encryption tests failed:', err.message); + process.exit(1); +}); \ No newline at end of file diff --git a/backend/tests/integration-test.spec.js b/backend/tests/integration-test.spec.js new file mode 100644 index 0000000..0cb61c0 --- /dev/null +++ b/backend/tests/integration-test.spec.js @@ -0,0 +1,7 @@ +import { test, expect } from '@playwright/test'; + +test('API server starts and returns 200', async ({ page }) => { + await page.goto('http://localhost:3000/api/health'); + const status = await page.status(); + expect(status).toBe(200); +}); \ No newline at end of file diff --git a/docs/plans/2026-03-06-bitte-arbeite-helpyourneighbour-weiter.md b/docs/plans/2026-03-06-bitte-arbeite-helpyourneighbour-weiter.md new file mode 100644 index 0000000..ed32c0e --- /dev/null +++ b/docs/plans/2026-03-06-bitte-arbeite-helpyourneighbour-weiter.md @@ -0,0 +1,26 @@ +# Goal Plan: Bitte arbeite an helpyourneighbour weiter + +- Project: helpyourneighbour +- Created: 2026-03-06T14:36:11Z +- Mode: general +- Source: user-intake + +## Goal +Bitte arbeite an helpyourneighbour weiter + +## Success Criteria +- [ ] Repo state refreshed +- [ ] Strongest available verification executed +- [ ] Goal brief written +- [ ] First concrete local target identified +- [ ] Result verified or precise blocker documented + +## Immediate Work Queue +- [ ] Refresh project snapshot for current goal +- [ ] Run the strongest available verification for current goal +- [ ] Create implementation brief for current goal +- [ ] Identify first concrete local change targets for current goal + +## Notes +- Created by `intake_goal`. +- This file is intentionally short; execution artifacts belong in `docs/runtime/`. diff --git a/docs/plans/2026-03-06-continue-working-the-helpyourneighbour-project-after.md b/docs/plans/2026-03-06-continue-working-the-helpyourneighbour-project-after.md new file mode 100644 index 0000000..78a759e --- /dev/null +++ b/docs/plans/2026-03-06-continue-working-the-helpyourneighbour-project-after.md @@ -0,0 +1,26 @@ +# Goal Plan: Continue working on the helpyourneighbour project after heartbeat + +- Project: helpyourneighbour +- Created: 2026-03-06T09:13:41Z +- Mode: general +- Source: user-intake + +## Goal +Continue working on the helpyourneighbour project after heartbeat + +## Success Criteria +- [ ] Repo state refreshed +- [ ] Strongest available verification executed +- [ ] Goal brief written +- [ ] First concrete local target identified +- [ ] Result verified or precise blocker documented + +## Immediate Work Queue +- [ ] Refresh project snapshot for current goal +- [ ] Run the strongest available verification for current goal +- [ ] Create implementation brief for current goal +- [ ] Identify first concrete local change targets for current goal + +## Notes +- Created by `intake_goal`. +- This file is intentionally short; execution artifacts belong in `docs/runtime/`. diff --git a/docs/plans/2026-03-06-implement-the-next-concrete-improvement-for.md b/docs/plans/2026-03-06-implement-the-next-concrete-improvement-for.md new file mode 100644 index 0000000..0e69844 --- /dev/null +++ b/docs/plans/2026-03-06-implement-the-next-concrete-improvement-for.md @@ -0,0 +1,26 @@ +# Goal Plan: Implement the next concrete improvement for the active project and keep working autonomously until the next precise blocker. + +- Project: helpyourneighbour +- Created: 2026-03-06T09:08:57Z +- Mode: coding +- Source: user-intake + +## Goal +Implement the next concrete improvement for the active project and keep working autonomously until the next precise blocker. + +## Success Criteria +- [ ] Repo state refreshed +- [ ] Strongest available verification executed +- [ ] Goal brief written +- [ ] First concrete local target identified +- [ ] Result verified or precise blocker documented + +## Immediate Work Queue +- [ ] Refresh project snapshot for current goal +- [ ] Run the strongest available verification for current goal +- [ ] Create implementation brief for current goal +- [ ] Identify first concrete local change targets for current goal + +## Notes +- Created by `intake_goal`. +- This file is intentionally short; execution artifacts belong in `docs/runtime/`. diff --git a/docs/plans/2026-03-06-initial-session-startup-and-greeting.md b/docs/plans/2026-03-06-initial-session-startup-and-greeting.md new file mode 100644 index 0000000..35adbbe --- /dev/null +++ b/docs/plans/2026-03-06-initial-session-startup-and-greeting.md @@ -0,0 +1,26 @@ +# Goal Plan: Initial session startup and greeting + +- Project: helpyourneighbour +- Created: 2026-03-06T09:33:28Z +- Mode: runtime +- Source: user-intake + +## Goal +Initial session startup and greeting + +## Success Criteria +- [ ] Repo state refreshed +- [ ] Strongest available verification executed +- [ ] Goal brief written +- [ ] First concrete local target identified +- [ ] Result verified or precise blocker documented + +## Immediate Work Queue +- [ ] Refresh project snapshot for current goal +- [ ] Run the strongest available verification for current goal +- [ ] Create implementation brief for current goal +- [ ] Identify first concrete local change targets for current goal + +## Notes +- Created by `intake_goal`. +- This file is intentionally short; execution artifacts belong in `docs/runtime/`. diff --git a/docs/plans/2026-03-06-nein-einfach-fortfahren-mit-der-arbeit.md b/docs/plans/2026-03-06-nein-einfach-fortfahren-mit-der-arbeit.md new file mode 100644 index 0000000..d7bed28 --- /dev/null +++ b/docs/plans/2026-03-06-nein-einfach-fortfahren-mit-der-arbeit.md @@ -0,0 +1,26 @@ +# Goal Plan: nein einfach fortfahren mit der arbeit + +- Project: helpyourneighbour +- Created: 2026-03-06T12:07:13Z +- Mode: general +- Source: user-intake + +## Goal +nein einfach fortfahren mit der arbeit + +## Success Criteria +- [ ] Repo state refreshed +- [ ] Strongest available verification executed +- [ ] Goal brief written +- [ ] First concrete local target identified +- [ ] Result verified or precise blocker documented + +## Immediate Work Queue +- [ ] Refresh project snapshot for current goal +- [ ] Run the strongest available verification for current goal +- [ ] Create implementation brief for current goal +- [ ] Identify first concrete local change targets for current goal + +## Notes +- Created by `intake_goal`. +- This file is intentionally short; execution artifacts belong in `docs/runtime/`. diff --git a/docs/plans/2026-03-06-start.md b/docs/plans/2026-03-06-start.md new file mode 100644 index 0000000..0cbf6fa --- /dev/null +++ b/docs/plans/2026-03-06-start.md @@ -0,0 +1,26 @@ +# Goal Plan: start + +- Project: helpyourneighbour +- Created: 2026-03-06T10:57:22Z +- Mode: runtime +- Source: user-intake + +## Goal +start + +## Success Criteria +- [ ] Repo state refreshed +- [ ] Strongest available verification executed +- [ ] Goal brief written +- [ ] First concrete local target identified +- [ ] Result verified or precise blocker documented + +## Immediate Work Queue +- [ ] Refresh project snapshot for current goal +- [ ] Run the strongest available verification for current goal +- [ ] Create implementation brief for current goal +- [ ] Identify first concrete local change targets for current goal + +## Notes +- Created by `intake_goal`. +- This file is intentionally short; execution artifacts belong in `docs/runtime/`. diff --git a/docs/runtime/next_actions_helpyourneighbour.md b/docs/runtime/next_actions_helpyourneighbour.md new file mode 100644 index 0000000..c3ac8a2 --- /dev/null +++ b/docs/runtime/next_actions_helpyourneighbour.md @@ -0,0 +1,2 @@ +# Auto Next Actions (helpyourneighbour) +Generated: 2026-03-05T23:29:37Z diff --git a/scripts/test-in-docker.sh b/scripts/test-in-docker.sh index 1378888..4b564f7 100755 --- a/scripts/test-in-docker.sh +++ b/scripts/test-in-docker.sh @@ -3,5 +3,5 @@ set -euo pipefail cd "$(dirname "$0")/.." -docker compose -f docker-compose.test.yml build --no-cache backend-test +unraidctl docker compose -f docker-compose.test.yml build --no-cache backend-test docker compose -f docker-compose.test.yml run --rm backend-test