@cachly-dev/mcp-server 0.10.65 → 0.10.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/handlers/brain.js +1 -1
- package/dist/src/index.js +1 -1
- package/package.json +7 -1
- package/server.json +2 -2
- package/.env.test.example +0 -23
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -50
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -25
- package/.github/workflows/eas-build-android.yml +0 -58
- package/.github/workflows/eas-update.yml +0 -55
- package/.github/workflows/publish.yml +0 -72
- package/BENCH.md +0 -113
- package/CHANGELOG.md +0 -653
- package/Dockerfile +0 -16
- package/LAUNCH_TEXTS.md +0 -182
- package/PROGRESS.md +0 -141
- package/STRATEGY.md +0 -228
- package/VISION_10X.md +0 -133
- package/apps/travel-chaos-organizer/.env.example +0 -49
- package/apps/travel-chaos-organizer/DEPLOY.md +0 -328
- package/apps/travel-chaos-organizer/Makefile +0 -57
- package/apps/travel-chaos-organizer/README.md +0 -159
- package/apps/travel-chaos-organizer/backend/.env.example +0 -10
- package/apps/travel-chaos-organizer/backend/Dockerfile +0 -25
- package/apps/travel-chaos-organizer/backend/alembic/env.py +0 -56
- package/apps/travel-chaos-organizer/backend/alembic/script.py.mako +0 -24
- package/apps/travel-chaos-organizer/backend/alembic/versions/.gitkeep +0 -0
- package/apps/travel-chaos-organizer/backend/alembic/versions/0001_stripe_customer_id.py +0 -24
- package/apps/travel-chaos-organizer/backend/alembic/versions/0002_telegram_chat_id.py +0 -24
- package/apps/travel-chaos-organizer/backend/alembic.ini +0 -39
- package/apps/travel-chaos-organizer/backend/app/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/auth/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/auth/keycloak.py +0 -81
- package/apps/travel-chaos-organizer/backend/app/config.py +0 -66
- package/apps/travel-chaos-organizer/backend/app/db/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/db/database.py +0 -20
- package/apps/travel-chaos-organizer/backend/app/db/migrations/001_init.sql +0 -71
- package/apps/travel-chaos-organizer/backend/app/db/migrations/002_telemetry_freemium.sql +0 -31
- package/apps/travel-chaos-organizer/backend/app/db/migrations/003_telegram_chat_id.sql +0 -4
- package/apps/travel-chaos-organizer/backend/app/db/migrations/004_stripe_and_email.sql +0 -5
- package/apps/travel-chaos-organizer/backend/app/limiter.py +0 -4
- package/apps/travel-chaos-organizer/backend/app/logging_config.py +0 -25
- package/apps/travel-chaos-organizer/backend/app/main.py +0 -77
- package/apps/travel-chaos-organizer/backend/app/models/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/models/schemas.py +0 -142
- package/apps/travel-chaos-organizer/backend/app/routers/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/routers/admin.py +0 -237
- package/apps/travel-chaos-organizer/backend/app/routers/cache.py +0 -13
- package/apps/travel-chaos-organizer/backend/app/routers/events.py +0 -29
- package/apps/travel-chaos-organizer/backend/app/routers/export.py +0 -122
- package/apps/travel-chaos-organizer/backend/app/routers/inbox.py +0 -122
- package/apps/travel-chaos-organizer/backend/app/routers/items.py +0 -130
- package/apps/travel-chaos-organizer/backend/app/routers/mail.py +0 -108
- package/apps/travel-chaos-organizer/backend/app/routers/parse.py +0 -303
- package/apps/travel-chaos-organizer/backend/app/routers/payments.py +0 -179
- package/apps/travel-chaos-organizer/backend/app/routers/trips.py +0 -134
- package/apps/travel-chaos-organizer/backend/app/routers/users.py +0 -169
- package/apps/travel-chaos-organizer/backend/app/routers/waitlist.py +0 -37
- package/apps/travel-chaos-organizer/backend/app/services/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/services/cache.py +0 -131
- package/apps/travel-chaos-organizer/backend/app/services/drip.py +0 -128
- package/apps/travel-chaos-organizer/backend/app/services/email.py +0 -61
- package/apps/travel-chaos-organizer/backend/app/services/errors.py +0 -44
- package/apps/travel-chaos-organizer/backend/app/services/notifier.py +0 -10
- package/apps/travel-chaos-organizer/backend/app/services/ollama.py +0 -101
- package/apps/travel-chaos-organizer/backend/app/services/parser.py +0 -22
- package/apps/travel-chaos-organizer/backend/app/services/quota.py +0 -85
- package/apps/travel-chaos-organizer/backend/app/services/sentry.py +0 -11
- package/apps/travel-chaos-organizer/backend/app/services/telemetry.py +0 -35
- package/apps/travel-chaos-organizer/backend/pytest.ini +0 -4
- package/apps/travel-chaos-organizer/backend/requirements-dev.txt +0 -6
- package/apps/travel-chaos-organizer/backend/requirements.txt +0 -25
- package/apps/travel-chaos-organizer/backend/tests/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/tests/conftest.py +0 -223
- package/apps/travel-chaos-organizer/backend/tests/test_admin.py +0 -99
- package/apps/travel-chaos-organizer/backend/tests/test_cache.py +0 -142
- package/apps/travel-chaos-organizer/backend/tests/test_drip.py +0 -32
- package/apps/travel-chaos-organizer/backend/tests/test_e2e_chain.py +0 -121
- package/apps/travel-chaos-organizer/backend/tests/test_export.py +0 -48
- package/apps/travel-chaos-organizer/backend/tests/test_inbox.py +0 -107
- package/apps/travel-chaos-organizer/backend/tests/test_items.py +0 -138
- package/apps/travel-chaos-organizer/backend/tests/test_mail.py +0 -113
- package/apps/travel-chaos-organizer/backend/tests/test_ollama.py +0 -145
- package/apps/travel-chaos-organizer/backend/tests/test_parse_url.py +0 -98
- package/apps/travel-chaos-organizer/backend/tests/test_parser.py +0 -72
- package/apps/travel-chaos-organizer/backend/tests/test_payments.py +0 -163
- package/apps/travel-chaos-organizer/backend/tests/test_quota.py +0 -46
- package/apps/travel-chaos-organizer/backend/tests/test_search.py +0 -67
- package/apps/travel-chaos-organizer/backend/tests/test_trips.py +0 -123
- package/apps/travel-chaos-organizer/backend/tests/test_users.py +0 -52
- package/apps/travel-chaos-organizer/backups/.gitkeep +0 -0
- package/apps/travel-chaos-organizer/caddy/Caddyfile +0 -27
- package/apps/travel-chaos-organizer/docker-compose.node1.yml +0 -31
- package/apps/travel-chaos-organizer/docker-compose.override.yml +0 -14
- package/apps/travel-chaos-organizer/docker-compose.yml +0 -128
- package/apps/travel-chaos-organizer/frontend/.env.example +0 -13
- package/apps/travel-chaos-organizer/frontend/app/(app)/_layout.tsx +0 -80
- package/apps/travel-chaos-organizer/frontend/app/(app)/inbox.tsx +0 -166
- package/apps/travel-chaos-organizer/frontend/app/(app)/search.tsx +0 -130
- package/apps/travel-chaos-organizer/frontend/app/(app)/settings.tsx +0 -381
- package/apps/travel-chaos-organizer/frontend/app/(app)/trips/[id].tsx +0 -346
- package/apps/travel-chaos-organizer/frontend/app/(app)/trips.tsx +0 -363
- package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/cancel.tsx +0 -34
- package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/success.tsx +0 -35
- package/apps/travel-chaos-organizer/frontend/app/(auth)/login.tsx +0 -91
- package/apps/travel-chaos-organizer/frontend/app/_layout.tsx +0 -71
- package/apps/travel-chaos-organizer/frontend/app/auth.tsx +0 -29
- package/apps/travel-chaos-organizer/frontend/app/index.tsx +0 -16
- package/apps/travel-chaos-organizer/frontend/app/onboarding.tsx +0 -119
- package/apps/travel-chaos-organizer/frontend/app.config.ts +0 -54
- package/apps/travel-chaos-organizer/frontend/assets/adaptive-icon.svg +0 -66
- package/apps/travel-chaos-organizer/frontend/assets/icon.svg +0 -79
- package/apps/travel-chaos-organizer/frontend/assets/splash.svg +0 -15
- package/apps/travel-chaos-organizer/frontend/components/BottomSheet.tsx +0 -102
- package/apps/travel-chaos-organizer/frontend/components/ConfettiCannon.tsx +0 -107
- package/apps/travel-chaos-organizer/frontend/components/ConfirmDialog.tsx +0 -109
- package/apps/travel-chaos-organizer/frontend/components/ErrorBoundary.tsx +0 -45
- package/apps/travel-chaos-organizer/frontend/components/FileUploadButton.tsx +0 -19
- package/apps/travel-chaos-organizer/frontend/components/ImportSheet.tsx +0 -155
- package/apps/travel-chaos-organizer/frontend/components/OfflineBadge.tsx +0 -55
- package/apps/travel-chaos-organizer/frontend/components/QRCodeViewer.tsx +0 -80
- package/apps/travel-chaos-organizer/frontend/components/ScoreRing.tsx +0 -39
- package/apps/travel-chaos-organizer/frontend/components/Screen.tsx +0 -39
- package/apps/travel-chaos-organizer/frontend/components/Skeleton.tsx +0 -70
- package/apps/travel-chaos-organizer/frontend/components/SwipeableInboxItem.tsx +0 -121
- package/apps/travel-chaos-organizer/frontend/components/SwipeableTimelineItem.tsx +0 -70
- package/apps/travel-chaos-organizer/frontend/components/TimelineItem.tsx +0 -73
- package/apps/travel-chaos-organizer/frontend/components/TimelineItemDetail.tsx +0 -130
- package/apps/travel-chaos-organizer/frontend/components/Toast.tsx +0 -60
- package/apps/travel-chaos-organizer/frontend/components/ToastContext.tsx +0 -42
- package/apps/travel-chaos-organizer/frontend/components/TripCard.tsx +0 -146
- package/apps/travel-chaos-organizer/frontend/components/TripQRModal.tsx +0 -70
- package/apps/travel-chaos-organizer/frontend/components/UpgradeBanner.tsx +0 -44
- package/apps/travel-chaos-organizer/frontend/eas.json +0 -22
- package/apps/travel-chaos-organizer/frontend/hooks/useInbox.ts +0 -24
- package/apps/travel-chaos-organizer/frontend/hooks/useNetworkSync.ts +0 -60
- package/apps/travel-chaos-organizer/frontend/hooks/useTrips.ts +0 -112
- package/apps/travel-chaos-organizer/frontend/lib/api.ts +0 -223
- package/apps/travel-chaos-organizer/frontend/lib/auth.ts +0 -93
- package/apps/travel-chaos-organizer/frontend/lib/db.ts +0 -86
- package/apps/travel-chaos-organizer/frontend/lib/fileCache.ts +0 -54
- package/apps/travel-chaos-organizer/frontend/lib/haptics.ts +0 -13
- package/apps/travel-chaos-organizer/frontend/lib/notifications.ts +0 -112
- package/apps/travel-chaos-organizer/frontend/lib/offlineQueue.ts +0 -145
- package/apps/travel-chaos-organizer/frontend/lib/quota.tsx +0 -43
- package/apps/travel-chaos-organizer/frontend/lib/sentry.ts +0 -28
- package/apps/travel-chaos-organizer/frontend/lib/shareIntent.ts +0 -44
- package/apps/travel-chaos-organizer/frontend/package-lock.json +0 -13221
- package/apps/travel-chaos-organizer/frontend/package.json +0 -44
- package/apps/travel-chaos-organizer/frontend/tsconfig.json +0 -23
- package/apps/travel-chaos-organizer/keycloak/realm-export.json +0 -59
- package/apps/travel-chaos-organizer/landing/index.html +0 -773
- package/apps/travel-chaos-organizer/scripts/backup.sh +0 -14
- package/apps/travel-chaos-organizer/scripts/configure-env.sh +0 -82
- package/apps/travel-chaos-organizer/scripts/deploy.sh +0 -54
- package/apps/travel-chaos-organizer/scripts/health-check.sh +0 -36
- package/apps/travel-chaos-organizer/scripts/migrate.sh +0 -7
- package/apps/travel-chaos-organizer/scripts/server-setup.sh +0 -85
- package/apps/travel-chaos-organizer/scripts/smoke-test.sh +0 -29
- package/apps/travel-chaos-organizer/scripts/verify-tracking.sh +0 -71
- package/apps/travel-chaos-organizer/telegram-bot/.env.example +0 -3
- package/apps/travel-chaos-organizer/telegram-bot/Dockerfile +0 -6
- package/apps/travel-chaos-organizer/telegram-bot/bot.py +0 -504
- package/apps/travel-chaos-organizer/telegram-bot/requirements.txt +0 -3
- package/dist/src/__tests__/auth.test.d.ts +0 -1
- package/dist/src/__tests__/auth.test.js +0 -107
- package/dist/src/__tests__/auth.test.js.map +0 -1
- package/dist/src/__tests__/brain-flow.test.d.ts +0 -12
- package/dist/src/__tests__/brain-flow.test.js +0 -1241
- package/dist/src/__tests__/brain-flow.test.js.map +0 -1
- package/dist/src/__tests__/confidence.test.d.ts +0 -13
- package/dist/src/__tests__/confidence.test.js +0 -233
- package/dist/src/__tests__/confidence.test.js.map +0 -1
- package/dist/src/__tests__/e2e/api-auth.test.d.ts +0 -7
- package/dist/src/__tests__/e2e/api-auth.test.js +0 -162
- package/dist/src/__tests__/e2e/api-auth.test.js.map +0 -1
- package/dist/src/__tests__/e2e/api-health.test.d.ts +0 -7
- package/dist/src/__tests__/e2e/api-health.test.js +0 -95
- package/dist/src/__tests__/e2e/api-health.test.js.map +0 -1
- package/dist/src/__tests__/e2e/cli.test.d.ts +0 -10
- package/dist/src/__tests__/e2e/cli.test.js +0 -204
- package/dist/src/__tests__/e2e/cli.test.js.map +0 -1
- package/dist/src/__tests__/e2e/config.d.ts +0 -35
- package/dist/src/__tests__/e2e/config.js +0 -53
- package/dist/src/__tests__/e2e/config.js.map +0 -1
- package/dist/src/__tests__/e2e/funnel.test.d.ts +0 -13
- package/dist/src/__tests__/e2e/funnel.test.js +0 -90
- package/dist/src/__tests__/e2e/funnel.test.js.map +0 -1
- package/dist/src/__tests__/e2e/mcp-tools.test.d.ts +0 -7
- package/dist/src/__tests__/e2e/mcp-tools.test.js +0 -129
- package/dist/src/__tests__/e2e/mcp-tools.test.js.map +0 -1
- package/dist/src/__tests__/e2e/provisioning.test.d.ts +0 -15
- package/dist/src/__tests__/e2e/provisioning.test.js +0 -123
- package/dist/src/__tests__/e2e/provisioning.test.js.map +0 -1
- package/dist/src/__tests__/handlers-unit.test.d.ts +0 -12
- package/dist/src/__tests__/handlers-unit.test.js +0 -505
- package/dist/src/__tests__/handlers-unit.test.js.map +0 -1
- package/dist/src/__tests__/namespace.test.d.ts +0 -1
- package/dist/src/__tests__/namespace.test.js +0 -114
- package/dist/src/__tests__/namespace.test.js.map +0 -1
- package/dist/src/__tests__/rerank.test.d.ts +0 -1
- package/dist/src/__tests__/rerank.test.js +0 -125
- package/dist/src/__tests__/rerank.test.js.map +0 -1
- package/dist/src/__tests__/utils.test.d.ts +0 -1
- package/dist/src/__tests__/utils.test.js +0 -83
- package/dist/src/__tests__/utils.test.js.map +0 -1
- package/dist/src/bench/cachly-bench.d.ts +0 -39
- package/dist/src/bench/cachly-bench.js +0 -223
- package/dist/src/bench/cachly-bench.js.map +0 -1
- package/dist/src/bench/fixtures.d.ts +0 -37
- package/dist/src/bench/fixtures.js +0 -225
- package/dist/src/bench/fixtures.js.map +0 -1
- package/dist/src/search.test.d.ts +0 -1
- package/dist/src/search.test.js +0 -713
- package/dist/src/search.test.js.map +0 -1
- package/eslint.config.js +0 -16
- package/glama.json +0 -36
- package/llms.txt +0 -155
- package/packages/telegram-notify/SPLIT_PLAN.md +0 -106
- package/packages/telegram-notify/client.ts +0 -88
- package/packages/telegram-notify/emojis.json +0 -22
- package/packages/telegram-notify/pyproject.toml +0 -17
- package/packages/telegram-notify/telegram_notify/__init__.py +0 -3
- package/packages/telegram-notify/telegram_notify/client.py +0 -87
- package/packages/telegram-notify/telegram_notify/emojis.json +0 -22
- package/scripts/e2e-run.sh +0 -160
- package/scripts/generate-icons.js +0 -28
- package/smithery.yaml +0 -45
- package/src/__tests__/auth.test.ts +0 -147
- package/src/__tests__/brain-flow.test.ts +0 -1472
- package/src/__tests__/confidence.test.ts +0 -285
- package/src/__tests__/e2e/api-auth.test.ts +0 -182
- package/src/__tests__/e2e/api-health.test.ts +0 -103
- package/src/__tests__/e2e/cli.test.ts +0 -228
- package/src/__tests__/e2e/config.ts +0 -53
- package/src/__tests__/e2e/funnel.test.ts +0 -99
- package/src/__tests__/e2e/mcp-tools.test.ts +0 -191
- package/src/__tests__/e2e/provisioning.test.ts +0 -128
- package/src/__tests__/handlers-unit.test.ts +0 -677
- package/src/__tests__/namespace.test.ts +0 -126
- package/src/__tests__/rerank.test.ts +0 -141
- package/src/__tests__/utils.test.ts +0 -81
- package/src/auth.ts +0 -46
- package/src/bench/cachly-bench.ts +0 -263
- package/src/bench/fixtures.ts +0 -256
- package/src/ckg.ts +0 -103
- package/src/confidence.ts +0 -38
- package/src/embeddings.ts +0 -217
- package/src/handlers/advanced.ts +0 -647
- package/src/handlers/brain.ts +0 -2622
- package/src/handlers/cache.ts +0 -633
- package/src/handlers/context.ts +0 -222
- package/src/handlers/fedbrain.ts +0 -1232
- package/src/handlers/instances.ts +0 -180
- package/src/handlers/roadmap.ts +0 -201
- package/src/handlers/syndicate.ts +0 -460
- package/src/handlers/tco.ts +0 -345
- package/src/handlers/team.ts +0 -1249
- package/src/index.ts +0 -2815
- package/src/namespace.ts +0 -128
- package/src/notifier.ts +0 -5
- package/src/rerank.ts +0 -148
- package/src/search.test.ts +0 -848
- package/src/search.ts +0 -1781
- package/src/tools.ts +0 -2056
- package/src/utils.ts +0 -90
- package/test-features.cjs +0 -23
- package/tsconfig.json +0 -16
- package/vitest.config.ts +0 -14
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
# Travel Chaos Organizer
|
|
2
|
-
|
|
3
|
-
Reisechaos automatisch organisieren — Screenshots, Buchungen, PDFs und Tickets in einer smarten Timeline.
|
|
4
|
-
|
|
5
|
-
## Stack
|
|
6
|
-
|
|
7
|
-
| Layer | Tech |
|
|
8
|
-
|---|---|
|
|
9
|
-
| Mobile | React Native + Expo SDK 52 |
|
|
10
|
-
| Auth | Keycloak (self-hosted, OIDC + PKCE) |
|
|
11
|
-
| Backend | Python 3.12 + FastAPI |
|
|
12
|
-
| Datenbank | PostgreSQL 16 |
|
|
13
|
-
| AI Parsing | Ollama (Vision-Modell, konfigurierbar) |
|
|
14
|
-
| Offline | expo-sqlite + expo-file-system |
|
|
15
|
-
|
|
16
|
-
## Architektur
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
Expo App ──OIDC──► Keycloak
|
|
20
|
-
│
|
|
21
|
-
└──REST──► FastAPI Backend
|
|
22
|
-
│
|
|
23
|
-
├── PostgreSQL
|
|
24
|
-
├── /data/uploads (Dateien)
|
|
25
|
-
└── Ollama API (AI Parsing)
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Lokales Setup
|
|
29
|
-
|
|
30
|
-
### 1. Voraussetzungen
|
|
31
|
-
- Docker + Docker Compose
|
|
32
|
-
- Ollama auf eurem Server mit Vision-Modell
|
|
33
|
-
|
|
34
|
-
### 2. Backend starten
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
cd apps/travel-chaos-organizer
|
|
38
|
-
cp .env.example .env
|
|
39
|
-
# OLLAMA_URL auf euren Server anpassen
|
|
40
|
-
docker compose up -d
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Die API ist dann unter `http://localhost:8000` erreichbar.
|
|
44
|
-
Swagger UI: `http://localhost:8000/docs`
|
|
45
|
-
Keycloak Admin: `http://localhost:8080` (admin/admin)
|
|
46
|
-
|
|
47
|
-
### 3. Frontend starten
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
cd frontend
|
|
51
|
-
cp .env.example .env
|
|
52
|
-
# EXPO_PUBLIC_API_URL + Keycloak-URLs anpassen
|
|
53
|
-
npm install
|
|
54
|
-
npm start
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## API Endpoints
|
|
58
|
-
|
|
59
|
-
### Trips
|
|
60
|
-
| Method | Path | Beschreibung |
|
|
61
|
-
|---|---|---|
|
|
62
|
-
| GET | `/api/v1/trips` | Alle Trips des Users |
|
|
63
|
-
| POST | `/api/v1/trips` | Neuen Trip anlegen |
|
|
64
|
-
| GET | `/api/v1/trips/{id}` | Trip Details |
|
|
65
|
-
| PATCH | `/api/v1/trips/{id}` | Trip updaten |
|
|
66
|
-
| DELETE | `/api/v1/trips/{id}` | Trip löschen |
|
|
67
|
-
|
|
68
|
-
### Trip Items (Timeline)
|
|
69
|
-
| Method | Path | Beschreibung |
|
|
70
|
-
|---|---|---|
|
|
71
|
-
| GET | `/api/v1/trips/{id}/items` | Timeline-Einträge |
|
|
72
|
-
| POST | `/api/v1/trips/{id}/items` | Manuell hinzufügen |
|
|
73
|
-
| PATCH | `/api/v1/trips/{id}/items/{item_id}` | Item updaten |
|
|
74
|
-
| DELETE | `/api/v1/trips/{id}/items/{item_id}` | Item löschen |
|
|
75
|
-
|
|
76
|
-
### AI Parsing
|
|
77
|
-
| Method | Path | Beschreibung |
|
|
78
|
-
|---|---|---|
|
|
79
|
-
| POST | `/api/v1/parse/file` | PDF / Bild / Text-Datei parsen |
|
|
80
|
-
| POST | `/api/v1/parse/text` | Raw-Text parsen |
|
|
81
|
-
|
|
82
|
-
### Chaos Inbox
|
|
83
|
-
| Method | Path | Beschreibung |
|
|
84
|
-
|---|---|---|
|
|
85
|
-
| GET | `/api/v1/inbox` | Unsortierten Eingang anzeigen |
|
|
86
|
-
| POST | `/api/v1/inbox/{id}/assign` | Item einem Trip zuweisen |
|
|
87
|
-
| DELETE | `/api/v1/inbox/{id}` | Item ablehnen |
|
|
88
|
-
|
|
89
|
-
## Cachly Integration
|
|
90
|
-
|
|
91
|
-
### Redis-Cache für Ollama-Ergebnisse (Kernintegration)
|
|
92
|
-
|
|
93
|
-
TCO nutzt **Cachly's Redis** als Deduplizierungs-Cache für Ollama-Parse-Ergebnisse.
|
|
94
|
-
Dasselbe PDF zweimal hochgeladen → sofortige Antwort aus dem Cache, kein zweiter AI-Call.
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
┌─────────────┐ parse_text(content) ┌──────────────────┐
|
|
98
|
-
│ TCO Backend│ ──── cache hit? ────────► │ Cachly Redis │
|
|
99
|
-
│ │ ◄─── hit: return dict ─── │ (tco:parse:*) │
|
|
100
|
-
│ │ miss: call Ollama └──────────────────┘
|
|
101
|
-
└─────────────┘ └── store result ──────────────────►┘
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
**Setup:**
|
|
105
|
-
```bash
|
|
106
|
-
# In apps/travel-chaos-organizer/.env
|
|
107
|
-
CACHLY_REDIS_URL=redis://:<password>@<host>.cachly.dev:6380/0
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Die Redis-URL findest du in deiner Cachly-Instanz unter *Connection String*.
|
|
111
|
-
`/health` zeigt `cachly_cache: enabled` sobald die Verbindung steht.
|
|
112
|
-
|
|
113
|
-
### MCP-Bridge (Power-User, optional)
|
|
114
|
-
|
|
115
|
-
Für Claude-Nutzer mit cachly-mcp: TCO-Tools sind als MCP-Tools verfügbar.
|
|
116
|
-
Da beide Dienste dieselbe Keycloak-Instanz teilen, wird das JWT direkt forwarded.
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
# In cachly-mcp env
|
|
120
|
-
TCO_API_URL=http://localhost:8000
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
Verfügbare Tools: `tco_list_trips`, `tco_create_trip`, `tco_get_timeline`,
|
|
124
|
-
`tco_inbox_list`, `tco_inbox_assign`, `tco_parse_url`, `tco_import_email` u.a.
|
|
125
|
-
|
|
126
|
-
## Aus dem Repo herauslösen
|
|
127
|
-
|
|
128
|
-
Das Projekt ist vollständig isoliert in `apps/travel-chaos-organizer/`.
|
|
129
|
-
Zum Herauslösen als eigenes Repo:
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
# Aus dem Monorepo extrahieren
|
|
133
|
-
git subtree split --prefix=apps/travel-chaos-organizer -b standalone-tco
|
|
134
|
-
git push <neues-remote> standalone-tco:main
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
Keine Abhängigkeiten zu cachly-mcp Code.
|
|
138
|
-
|
|
139
|
-
## Datenstruktur
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
trips user_id, name, start_date, end_date
|
|
143
|
-
└── trip_items type, title, parsed_data (JSONB), event_at
|
|
144
|
-
└── attachments file_path, mime_type
|
|
145
|
-
|
|
146
|
-
chaos_inbox raw_content, parsed_data, status
|
|
147
|
-
└── attachments
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Ollama Modell konfigurieren
|
|
151
|
-
|
|
152
|
-
In `.env`:
|
|
153
|
-
```
|
|
154
|
-
OLLAMA_URL=http://dein-server:11434
|
|
155
|
-
OLLAMA_MODEL=llama3.2-vision # oder llava, bakllava, etc.
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
Das Modell muss Vision-Fähigkeit haben für Screenshot-Parsing.
|
|
159
|
-
Für reines Text/PDF-Parsing reicht auch ein Text-only Modell.
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# Sentry (optional — get DSN at sentry.io)
|
|
2
|
-
# SENTRY_DSN=https://...@sentry.io/...
|
|
3
|
-
ENVIRONMENT=production
|
|
4
|
-
|
|
5
|
-
# Stripe (https://dashboard.stripe.com/apikeys)
|
|
6
|
-
# STRIPE_SECRET_KEY=sk_live_...
|
|
7
|
-
# STRIPE_WEBHOOK_SECRET=whsec_...
|
|
8
|
-
# STRIPE_PRO_PRICE_ID=price_...
|
|
9
|
-
STRIPE_SUCCESS_URL=https://YOUR_DOMAIN/upgrade/success
|
|
10
|
-
STRIPE_CANCEL_URL=https://YOUR_DOMAIN/upgrade/cancel
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
FROM python:3.12-slim
|
|
2
|
-
|
|
3
|
-
# system deps for PyMuPDF and python-magic
|
|
4
|
-
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
5
|
-
libmagic1 \
|
|
6
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
7
|
-
|
|
8
|
-
WORKDIR /app
|
|
9
|
-
|
|
10
|
-
# Install shared monorepo package first (build context = repo root)
|
|
11
|
-
COPY packages/telegram-notify /packages/telegram-notify
|
|
12
|
-
RUN pip install --no-cache-dir /packages/telegram-notify
|
|
13
|
-
|
|
14
|
-
COPY apps/travel-chaos-organizer/backend/requirements.txt .
|
|
15
|
-
# Strip the file:// line — package is already installed above
|
|
16
|
-
RUN grep -v "telegram-notify" requirements.txt | pip install --no-cache-dir -r /dev/stdin
|
|
17
|
-
|
|
18
|
-
COPY apps/travel-chaos-organizer/backend/app/ ./app/
|
|
19
|
-
|
|
20
|
-
ENV PYTHONUNBUFFERED=1 \
|
|
21
|
-
PYTHONDONTWRITEBYTECODE=1
|
|
22
|
-
|
|
23
|
-
EXPOSE 8000
|
|
24
|
-
|
|
25
|
-
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import os
|
|
3
|
-
from logging.config import fileConfig
|
|
4
|
-
from sqlalchemy.ext.asyncio import async_engine_from_config
|
|
5
|
-
from sqlalchemy import pool
|
|
6
|
-
from alembic import context
|
|
7
|
-
|
|
8
|
-
config = context.config
|
|
9
|
-
|
|
10
|
-
if config.config_file_name is not None:
|
|
11
|
-
fileConfig(config.config_file_name)
|
|
12
|
-
|
|
13
|
-
# Allow DATABASE_URL env var to override alembic.ini
|
|
14
|
-
db_url = os.getenv("DATABASE_URL", config.get_main_option("sqlalchemy.url"))
|
|
15
|
-
config.set_main_option("sqlalchemy.url", db_url)
|
|
16
|
-
|
|
17
|
-
target_metadata = None
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def run_migrations_offline() -> None:
|
|
21
|
-
url = config.get_main_option("sqlalchemy.url")
|
|
22
|
-
context.configure(
|
|
23
|
-
url=url,
|
|
24
|
-
target_metadata=target_metadata,
|
|
25
|
-
literal_binds=True,
|
|
26
|
-
dialect_opts={"paramstyle": "named"},
|
|
27
|
-
)
|
|
28
|
-
with context.begin_transaction():
|
|
29
|
-
context.run_migrations()
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def do_run_migrations(connection):
|
|
33
|
-
context.configure(connection=connection, target_metadata=target_metadata)
|
|
34
|
-
with context.begin_transaction():
|
|
35
|
-
context.run_migrations()
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
async def run_async_migrations() -> None:
|
|
39
|
-
connectable = async_engine_from_config(
|
|
40
|
-
config.get_section(config.config_ini_section, {}),
|
|
41
|
-
prefix="sqlalchemy.",
|
|
42
|
-
poolclass=pool.NullPool,
|
|
43
|
-
)
|
|
44
|
-
async with connectable.connect() as connection:
|
|
45
|
-
await connection.run_sync(do_run_migrations)
|
|
46
|
-
await connectable.dispose()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def run_migrations_online() -> None:
|
|
50
|
-
asyncio.run(run_async_migrations())
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if context.is_offline_mode():
|
|
54
|
-
run_migrations_offline()
|
|
55
|
-
else:
|
|
56
|
-
run_migrations_online()
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"""${message}
|
|
2
|
-
|
|
3
|
-
Revision ID: ${up_revision}
|
|
4
|
-
Revises: ${down_revision | comma,n}
|
|
5
|
-
Create Date: ${create_date}
|
|
6
|
-
|
|
7
|
-
"""
|
|
8
|
-
from typing import Sequence, Union
|
|
9
|
-
from alembic import op
|
|
10
|
-
import sqlalchemy as sa
|
|
11
|
-
${imports if imports else ""}
|
|
12
|
-
|
|
13
|
-
revision: str = ${repr(up_revision)}
|
|
14
|
-
down_revision: Union[str, None] = ${repr(down_revision)}
|
|
15
|
-
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
|
16
|
-
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def upgrade() -> None:
|
|
20
|
-
${upgrades if upgrades else "pass"}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def downgrade() -> None:
|
|
24
|
-
${downgrades if downgrades else "pass"}
|
|
File without changes
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"""add stripe_customer_id to users
|
|
2
|
-
|
|
3
|
-
Revision ID: 0001
|
|
4
|
-
Revises:
|
|
5
|
-
Create Date: 2025-01-01 00:00:00.000000
|
|
6
|
-
"""
|
|
7
|
-
from typing import Sequence, Union
|
|
8
|
-
from alembic import op
|
|
9
|
-
import sqlalchemy as sa
|
|
10
|
-
|
|
11
|
-
revision: str = '0001'
|
|
12
|
-
down_revision: Union[str, None] = None
|
|
13
|
-
branch_labels: Union[str, Sequence[str], None] = None
|
|
14
|
-
depends_on: Union[str, Sequence[str], None] = None
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def upgrade() -> None:
|
|
18
|
-
op.add_column('users', sa.Column('stripe_customer_id', sa.Text(), nullable=True))
|
|
19
|
-
op.create_index('idx_users_stripe_customer_id', 'users', ['stripe_customer_id'])
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def downgrade() -> None:
|
|
23
|
-
op.drop_index('idx_users_stripe_customer_id', 'users')
|
|
24
|
-
op.drop_column('users', 'stripe_customer_id')
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"""add telegram_chat_id to users
|
|
2
|
-
|
|
3
|
-
Revision ID: 0002
|
|
4
|
-
Revises: 0001
|
|
5
|
-
Create Date: 2025-01-02 00:00:00.000000
|
|
6
|
-
"""
|
|
7
|
-
from typing import Sequence, Union
|
|
8
|
-
from alembic import op
|
|
9
|
-
import sqlalchemy as sa
|
|
10
|
-
|
|
11
|
-
revision: str = '0002'
|
|
12
|
-
down_revision: Union[str, None] = '0001'
|
|
13
|
-
branch_labels: Union[str, Sequence[str], None] = None
|
|
14
|
-
depends_on: Union[str, Sequence[str], None] = None
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def upgrade() -> None:
|
|
18
|
-
op.add_column('users', sa.Column('telegram_chat_id', sa.Text(), nullable=True))
|
|
19
|
-
op.create_index('ix_users_telegram_chat_id', 'users', ['telegram_chat_id'], unique=True)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def downgrade() -> None:
|
|
23
|
-
op.drop_index('ix_users_telegram_chat_id', 'users')
|
|
24
|
-
op.drop_column('users', 'telegram_chat_id')
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
[alembic]
|
|
2
|
-
script_location = alembic
|
|
3
|
-
prepend_sys_path = .
|
|
4
|
-
version_path_separator = os
|
|
5
|
-
sqlalchemy.url = postgresql+asyncpg://tco:tco@localhost:5432/tco
|
|
6
|
-
|
|
7
|
-
[loggers]
|
|
8
|
-
keys = root,sqlalchemy,alembic
|
|
9
|
-
|
|
10
|
-
[handlers]
|
|
11
|
-
keys = console
|
|
12
|
-
|
|
13
|
-
[formatters]
|
|
14
|
-
keys = generic
|
|
15
|
-
|
|
16
|
-
[logger_root]
|
|
17
|
-
level = WARN
|
|
18
|
-
handlers = console
|
|
19
|
-
qualname =
|
|
20
|
-
|
|
21
|
-
[logger_sqlalchemy]
|
|
22
|
-
level = WARN
|
|
23
|
-
handlers =
|
|
24
|
-
qualname = sqlalchemy.engine
|
|
25
|
-
|
|
26
|
-
[logger_alembic]
|
|
27
|
-
level = INFO
|
|
28
|
-
handlers =
|
|
29
|
-
qualname = alembic
|
|
30
|
-
|
|
31
|
-
[handler_console]
|
|
32
|
-
class = StreamHandler
|
|
33
|
-
args = (sys.stderr,)
|
|
34
|
-
level = NOTSET
|
|
35
|
-
formatter = generic
|
|
36
|
-
|
|
37
|
-
[formatter_generic]
|
|
38
|
-
format = %(levelname)-5.5s [%(name)s] %(message)s
|
|
39
|
-
datefmt = %H:%M:%S
|
|
File without changes
|
|
File without changes
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
from datetime import datetime, timedelta, timezone
|
|
2
|
-
from typing import Annotated
|
|
3
|
-
import httpx
|
|
4
|
-
from fastapi import Depends, HTTPException, Request, status
|
|
5
|
-
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
|
6
|
-
from jose import JWTError, jwt
|
|
7
|
-
from app.config import get_settings
|
|
8
|
-
from app.db.database import get_db
|
|
9
|
-
from sqlalchemy.ext.asyncio import AsyncSession
|
|
10
|
-
|
|
11
|
-
settings = get_settings()
|
|
12
|
-
bearer_scheme = HTTPBearer()
|
|
13
|
-
|
|
14
|
-
_jwks_cache: dict | None = None
|
|
15
|
-
_jwks_cached_at: datetime | None = None
|
|
16
|
-
_JWKS_TTL = timedelta(hours=1) # refresh every hour to pick up key rotations
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
async def _get_jwks() -> dict:
|
|
20
|
-
global _jwks_cache, _jwks_cached_at
|
|
21
|
-
now = datetime.now(timezone.utc)
|
|
22
|
-
if _jwks_cache and _jwks_cached_at and (now - _jwks_cached_at) < _JWKS_TTL:
|
|
23
|
-
return _jwks_cache
|
|
24
|
-
url = f"{settings.keycloak_url}/realms/{settings.keycloak_realm}/protocol/openid-connect/certs"
|
|
25
|
-
async with httpx.AsyncClient() as client:
|
|
26
|
-
resp = await client.get(url, timeout=10)
|
|
27
|
-
resp.raise_for_status()
|
|
28
|
-
_jwks_cache = resp.json()
|
|
29
|
-
_jwks_cached_at = now
|
|
30
|
-
return _jwks_cache
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
async def get_current_user(
|
|
34
|
-
credentials: Annotated[HTTPAuthorizationCredentials, Depends(bearer_scheme)],
|
|
35
|
-
) -> dict:
|
|
36
|
-
token = credentials.credentials
|
|
37
|
-
try:
|
|
38
|
-
jwks = await _get_jwks()
|
|
39
|
-
unverified_header = jwt.get_unverified_header(token)
|
|
40
|
-
key = next(
|
|
41
|
-
(k for k in jwks["keys"] if k["kid"] == unverified_header.get("kid")),
|
|
42
|
-
None,
|
|
43
|
-
)
|
|
44
|
-
if key is None:
|
|
45
|
-
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Unknown signing key")
|
|
46
|
-
|
|
47
|
-
payload = jwt.decode(
|
|
48
|
-
token,
|
|
49
|
-
key,
|
|
50
|
-
algorithms=["RS256"],
|
|
51
|
-
audience=settings.keycloak_client_id,
|
|
52
|
-
options={"verify_exp": True},
|
|
53
|
-
)
|
|
54
|
-
return payload
|
|
55
|
-
except JWTError as exc:
|
|
56
|
-
raise HTTPException(
|
|
57
|
-
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
58
|
-
detail=f"Invalid token: {exc}",
|
|
59
|
-
) from exc
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def user_id(user: Annotated[dict, Depends(get_current_user)]) -> str:
|
|
63
|
-
return user["sub"]
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
async def user_id_or_bot(request: Request, db: AsyncSession = Depends(get_db)) -> str:
|
|
67
|
-
"""Accept either JWT auth or X-User-Id header (when X-Bot-Token matches)."""
|
|
68
|
-
s = get_settings()
|
|
69
|
-
bot_token = request.headers.get("X-Bot-Token", "")
|
|
70
|
-
if bot_token and s.telegram_bot_token and bot_token == s.telegram_bot_token:
|
|
71
|
-
uid = request.headers.get("X-User-Id")
|
|
72
|
-
if uid:
|
|
73
|
-
return uid
|
|
74
|
-
# Fall back to normal JWT auth — extract bearer token from request directly
|
|
75
|
-
auth_header = request.headers.get("Authorization", "")
|
|
76
|
-
if not auth_header.startswith("Bearer "):
|
|
77
|
-
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authenticated")
|
|
78
|
-
from fastapi.security import HTTPAuthorizationCredentials
|
|
79
|
-
credentials = HTTPAuthorizationCredentials(scheme="Bearer", credentials=auth_header[7:])
|
|
80
|
-
user = await get_current_user(credentials)
|
|
81
|
-
return user["sub"]
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
from pydantic_settings import BaseSettings
|
|
2
|
-
from functools import lru_cache
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class Settings(BaseSettings):
|
|
6
|
-
# App
|
|
7
|
-
app_name: str = "Travel Chaos Organizer API"
|
|
8
|
-
debug: bool = False
|
|
9
|
-
upload_dir: str = "/data/uploads"
|
|
10
|
-
app_url: str = "https://tco.app"
|
|
11
|
-
|
|
12
|
-
# Database
|
|
13
|
-
database_url: str = "postgresql+asyncpg://tco:tco@localhost:5432/tco"
|
|
14
|
-
|
|
15
|
-
# Keycloak
|
|
16
|
-
keycloak_url: str = "http://localhost:8080"
|
|
17
|
-
keycloak_realm: str = "travel-chaos"
|
|
18
|
-
keycloak_client_id: str = "tco-backend"
|
|
19
|
-
|
|
20
|
-
# Ollama
|
|
21
|
-
ollama_url: str = "http://localhost:11434"
|
|
22
|
-
ollama_model: str = "llama3.2-vision"
|
|
23
|
-
ollama_timeout: int = 120
|
|
24
|
-
|
|
25
|
-
# Cachly Redis (optional) — caches Ollama parse results by content hash.
|
|
26
|
-
# Set to your Cachly Redis connection string to enable deduplication.
|
|
27
|
-
# Format: redis://:<password>@<host>:<port>/0 or rediss:// for TLS
|
|
28
|
-
cachly_redis_url: str = ""
|
|
29
|
-
|
|
30
|
-
# CORS
|
|
31
|
-
cors_origins: str = "*" # Set to your domain in production: https://yourapp.com
|
|
32
|
-
|
|
33
|
-
# Telegram notifier (optional)
|
|
34
|
-
telegram_bot_token: str = ""
|
|
35
|
-
telegram_chat_id: str = "" # default chat; per-app override below
|
|
36
|
-
tco_telegram_chat_id: str = "" # if set, overrides telegram_chat_id for TCO events
|
|
37
|
-
|
|
38
|
-
# Email (Resend)
|
|
39
|
-
resend_api_key: str = ""
|
|
40
|
-
resend_from: str = "noreply@tco.app"
|
|
41
|
-
|
|
42
|
-
# Admin
|
|
43
|
-
admin_user: str = "admin"
|
|
44
|
-
admin_password: str = "changeme"
|
|
45
|
-
|
|
46
|
-
# Sentry (optional)
|
|
47
|
-
sentry_dsn: str = ""
|
|
48
|
-
environment: str = "production"
|
|
49
|
-
|
|
50
|
-
# Upload
|
|
51
|
-
max_upload_bytes: int = 20 * 1024 * 1024 # 20 MB
|
|
52
|
-
|
|
53
|
-
# Stripe
|
|
54
|
-
stripe_secret_key: str = ""
|
|
55
|
-
stripe_webhook_secret: str = ""
|
|
56
|
-
stripe_pro_price_id: str = "price_YOUR_PRICE_ID"
|
|
57
|
-
stripe_success_url: str = "tco://upgrade/success"
|
|
58
|
-
stripe_cancel_url: str = "tco://upgrade/cancel"
|
|
59
|
-
|
|
60
|
-
class Config:
|
|
61
|
-
env_file = ".env"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@lru_cache
|
|
65
|
-
def get_settings() -> Settings:
|
|
66
|
-
return Settings()
|
|
File without changes
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
|
|
2
|
-
from sqlalchemy.orm import DeclarativeBase
|
|
3
|
-
from app.config import get_settings
|
|
4
|
-
|
|
5
|
-
settings = get_settings()
|
|
6
|
-
|
|
7
|
-
engine = create_async_engine(settings.database_url, echo=settings.debug)
|
|
8
|
-
AsyncSessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class Base(DeclarativeBase):
|
|
12
|
-
pass
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
async def get_db() -> AsyncSession:
|
|
16
|
-
async with AsyncSessionLocal() as session:
|
|
17
|
-
try:
|
|
18
|
-
yield session
|
|
19
|
-
finally:
|
|
20
|
-
await session.close()
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
-- Travel Chaos Organizer — Initial Schema
|
|
2
|
-
|
|
3
|
-
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
4
|
-
|
|
5
|
-
CREATE TABLE IF NOT EXISTS trips (
|
|
6
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
7
|
-
user_id TEXT NOT NULL,
|
|
8
|
-
name TEXT NOT NULL,
|
|
9
|
-
description TEXT,
|
|
10
|
-
start_date DATE,
|
|
11
|
-
end_date DATE,
|
|
12
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
13
|
-
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
CREATE INDEX idx_trips_user_id ON trips(user_id);
|
|
17
|
-
|
|
18
|
-
CREATE TYPE item_type AS ENUM (
|
|
19
|
-
'flight', 'train', 'bus', 'hotel', 'rental_car',
|
|
20
|
-
'activity', 'transfer', 'document', 'other'
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
CREATE TABLE IF NOT EXISTS trip_items (
|
|
24
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
25
|
-
trip_id UUID NOT NULL REFERENCES trips(id) ON DELETE CASCADE,
|
|
26
|
-
user_id TEXT NOT NULL,
|
|
27
|
-
type item_type NOT NULL DEFAULT 'other',
|
|
28
|
-
title TEXT NOT NULL,
|
|
29
|
-
raw_text TEXT,
|
|
30
|
-
parsed_data JSONB,
|
|
31
|
-
event_at TIMESTAMPTZ,
|
|
32
|
-
event_end_at TIMESTAMPTZ,
|
|
33
|
-
booking_ref TEXT,
|
|
34
|
-
provider TEXT,
|
|
35
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
36
|
-
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
CREATE INDEX idx_trip_items_trip_id ON trip_items(trip_id);
|
|
40
|
-
CREATE INDEX idx_trip_items_event_at ON trip_items(event_at);
|
|
41
|
-
CREATE INDEX idx_trip_items_parsed_data ON trip_items USING gin(parsed_data);
|
|
42
|
-
|
|
43
|
-
CREATE TABLE IF NOT EXISTS attachments (
|
|
44
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
45
|
-
trip_item_id UUID REFERENCES trip_items(id) ON DELETE CASCADE,
|
|
46
|
-
inbox_id UUID,
|
|
47
|
-
user_id TEXT NOT NULL,
|
|
48
|
-
file_path TEXT NOT NULL,
|
|
49
|
-
file_name TEXT NOT NULL,
|
|
50
|
-
mime_type TEXT NOT NULL,
|
|
51
|
-
size_bytes BIGINT,
|
|
52
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
CREATE INDEX idx_attachments_trip_item_id ON attachments(trip_item_id);
|
|
56
|
-
|
|
57
|
-
CREATE TYPE inbox_status AS ENUM ('pending', 'processed', 'rejected', 'assigned');
|
|
58
|
-
|
|
59
|
-
CREATE TABLE IF NOT EXISTS chaos_inbox (
|
|
60
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
61
|
-
user_id TEXT NOT NULL,
|
|
62
|
-
raw_content TEXT,
|
|
63
|
-
source TEXT,
|
|
64
|
-
status inbox_status NOT NULL DEFAULT 'pending',
|
|
65
|
-
parsed_data JSONB,
|
|
66
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
67
|
-
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
CREATE INDEX idx_chaos_inbox_user_id ON chaos_inbox(user_id);
|
|
71
|
-
CREATE INDEX idx_chaos_inbox_status ON chaos_inbox(status);
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
-- users table: freemium plan tracking. id = Keycloak sub.
|
|
2
|
-
CREATE TABLE IF NOT EXISTS users (
|
|
3
|
-
id TEXT PRIMARY KEY,
|
|
4
|
-
email TEXT,
|
|
5
|
-
plan TEXT NOT NULL DEFAULT 'free',
|
|
6
|
-
plan_expires_at TIMESTAMPTZ,
|
|
7
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
8
|
-
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
-- events table: telemetry. user_id nullable for anonymous/server events.
|
|
12
|
-
CREATE TABLE IF NOT EXISTS events (
|
|
13
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
14
|
-
user_id TEXT,
|
|
15
|
-
event_name TEXT NOT NULL,
|
|
16
|
-
properties JSONB,
|
|
17
|
-
platform TEXT,
|
|
18
|
-
app_version TEXT,
|
|
19
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
20
|
-
);
|
|
21
|
-
CREATE INDEX idx_events_user_id ON events(user_id);
|
|
22
|
-
CREATE INDEX idx_events_name ON events(event_name);
|
|
23
|
-
CREATE INDEX idx_events_created ON events(created_at DESC);
|
|
24
|
-
|
|
25
|
-
-- waitlist: email capture from landing page (no auth required)
|
|
26
|
-
CREATE TABLE IF NOT EXISTS waitlist (
|
|
27
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
28
|
-
email TEXT NOT NULL UNIQUE,
|
|
29
|
-
source TEXT DEFAULT 'landing',
|
|
30
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
31
|
-
);
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
-- Add telegram_chat_id column to users table.
|
|
2
|
-
-- This column was referenced in the application but missing from the initial schema.
|
|
3
|
-
ALTER TABLE users ADD COLUMN IF NOT EXISTS telegram_chat_id TEXT;
|
|
4
|
-
CREATE INDEX IF NOT EXISTS idx_users_telegram_chat_id ON users(telegram_chat_id) WHERE telegram_chat_id IS NOT NULL;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
-- Add stripe_customer_id to users table.
|
|
2
|
-
-- Used by payments.py to link Stripe customer to user in webhook handlers.
|
|
3
|
-
-- Missing column causes crash on every Stripe webhook (checkout, subscription cancel, renewal, payment failed).
|
|
4
|
-
ALTER TABLE users ADD COLUMN IF NOT EXISTS stripe_customer_id TEXT;
|
|
5
|
-
CREATE INDEX IF NOT EXISTS idx_users_stripe_customer_id ON users(stripe_customer_id) WHERE stripe_customer_id IS NOT NULL;
|