@cachly-dev/mcp-server 0.10.47 → 0.10.49
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/.github/workflows/eas-build-android.yml +58 -0
- package/.github/workflows/eas-update.yml +55 -0
- package/STRATEGY.md +209 -0
- package/apps/travel-chaos-organizer/.env.example +49 -0
- package/apps/travel-chaos-organizer/DEPLOY.md +328 -0
- package/apps/travel-chaos-organizer/Makefile +57 -0
- package/apps/travel-chaos-organizer/README.md +159 -0
- package/apps/travel-chaos-organizer/backend/.env.example +10 -0
- package/apps/travel-chaos-organizer/backend/Dockerfile +25 -0
- package/apps/travel-chaos-organizer/backend/alembic/env.py +56 -0
- package/apps/travel-chaos-organizer/backend/alembic/script.py.mako +24 -0
- package/apps/travel-chaos-organizer/backend/alembic/versions/.gitkeep +0 -0
- package/apps/travel-chaos-organizer/backend/alembic/versions/0001_stripe_customer_id.py +24 -0
- package/apps/travel-chaos-organizer/backend/alembic/versions/0002_telegram_chat_id.py +24 -0
- package/apps/travel-chaos-organizer/backend/alembic.ini +39 -0
- 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 +81 -0
- package/apps/travel-chaos-organizer/backend/app/config.py +66 -0
- package/apps/travel-chaos-organizer/backend/app/db/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/db/database.py +20 -0
- package/apps/travel-chaos-organizer/backend/app/db/migrations/001_init.sql +71 -0
- package/apps/travel-chaos-organizer/backend/app/db/migrations/002_telemetry_freemium.sql +31 -0
- package/apps/travel-chaos-organizer/backend/app/db/migrations/003_telegram_chat_id.sql +4 -0
- package/apps/travel-chaos-organizer/backend/app/db/migrations/004_stripe_and_email.sql +5 -0
- package/apps/travel-chaos-organizer/backend/app/limiter.py +4 -0
- package/apps/travel-chaos-organizer/backend/app/logging_config.py +25 -0
- package/apps/travel-chaos-organizer/backend/app/main.py +77 -0
- package/apps/travel-chaos-organizer/backend/app/models/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/models/schemas.py +142 -0
- package/apps/travel-chaos-organizer/backend/app/routers/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/routers/admin.py +237 -0
- package/apps/travel-chaos-organizer/backend/app/routers/cache.py +13 -0
- package/apps/travel-chaos-organizer/backend/app/routers/events.py +29 -0
- package/apps/travel-chaos-organizer/backend/app/routers/export.py +122 -0
- package/apps/travel-chaos-organizer/backend/app/routers/inbox.py +122 -0
- package/apps/travel-chaos-organizer/backend/app/routers/items.py +130 -0
- package/apps/travel-chaos-organizer/backend/app/routers/mail.py +108 -0
- package/apps/travel-chaos-organizer/backend/app/routers/parse.py +303 -0
- package/apps/travel-chaos-organizer/backend/app/routers/payments.py +179 -0
- package/apps/travel-chaos-organizer/backend/app/routers/trips.py +134 -0
- package/apps/travel-chaos-organizer/backend/app/routers/users.py +169 -0
- package/apps/travel-chaos-organizer/backend/app/routers/waitlist.py +37 -0
- package/apps/travel-chaos-organizer/backend/app/services/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/services/cache.py +131 -0
- package/apps/travel-chaos-organizer/backend/app/services/drip.py +128 -0
- package/apps/travel-chaos-organizer/backend/app/services/email.py +61 -0
- package/apps/travel-chaos-organizer/backend/app/services/errors.py +44 -0
- package/apps/travel-chaos-organizer/backend/app/services/notifier.py +10 -0
- package/apps/travel-chaos-organizer/backend/app/services/ollama.py +101 -0
- package/apps/travel-chaos-organizer/backend/app/services/parser.py +22 -0
- package/apps/travel-chaos-organizer/backend/app/services/quota.py +85 -0
- package/apps/travel-chaos-organizer/backend/app/services/sentry.py +11 -0
- package/apps/travel-chaos-organizer/backend/app/services/telemetry.py +35 -0
- package/apps/travel-chaos-organizer/backend/pytest.ini +4 -0
- package/apps/travel-chaos-organizer/backend/requirements-dev.txt +6 -0
- package/apps/travel-chaos-organizer/backend/requirements.txt +25 -0
- package/apps/travel-chaos-organizer/backend/tests/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/tests/conftest.py +223 -0
- package/apps/travel-chaos-organizer/backend/tests/test_admin.py +99 -0
- package/apps/travel-chaos-organizer/backend/tests/test_cache.py +142 -0
- package/apps/travel-chaos-organizer/backend/tests/test_drip.py +32 -0
- package/apps/travel-chaos-organizer/backend/tests/test_e2e_chain.py +121 -0
- package/apps/travel-chaos-organizer/backend/tests/test_export.py +48 -0
- package/apps/travel-chaos-organizer/backend/tests/test_inbox.py +107 -0
- package/apps/travel-chaos-organizer/backend/tests/test_items.py +138 -0
- package/apps/travel-chaos-organizer/backend/tests/test_mail.py +113 -0
- package/apps/travel-chaos-organizer/backend/tests/test_ollama.py +145 -0
- package/apps/travel-chaos-organizer/backend/tests/test_parse_url.py +98 -0
- package/apps/travel-chaos-organizer/backend/tests/test_parser.py +72 -0
- package/apps/travel-chaos-organizer/backend/tests/test_payments.py +163 -0
- package/apps/travel-chaos-organizer/backend/tests/test_quota.py +46 -0
- package/apps/travel-chaos-organizer/backend/tests/test_search.py +67 -0
- package/apps/travel-chaos-organizer/backend/tests/test_trips.py +123 -0
- package/apps/travel-chaos-organizer/backend/tests/test_users.py +52 -0
- package/apps/travel-chaos-organizer/backups/.gitkeep +0 -0
- package/apps/travel-chaos-organizer/caddy/Caddyfile +27 -0
- package/apps/travel-chaos-organizer/docker-compose.node1.yml +31 -0
- package/apps/travel-chaos-organizer/docker-compose.override.yml +14 -0
- package/apps/travel-chaos-organizer/docker-compose.yml +128 -0
- package/apps/travel-chaos-organizer/frontend/.env.example +13 -0
- package/apps/travel-chaos-organizer/frontend/app/(app)/_layout.tsx +80 -0
- package/apps/travel-chaos-organizer/frontend/app/(app)/inbox.tsx +166 -0
- package/apps/travel-chaos-organizer/frontend/app/(app)/search.tsx +130 -0
- package/apps/travel-chaos-organizer/frontend/app/(app)/settings.tsx +381 -0
- package/apps/travel-chaos-organizer/frontend/app/(app)/trips/[id].tsx +346 -0
- package/apps/travel-chaos-organizer/frontend/app/(app)/trips.tsx +363 -0
- package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/cancel.tsx +34 -0
- package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/success.tsx +35 -0
- package/apps/travel-chaos-organizer/frontend/app/(auth)/login.tsx +91 -0
- package/apps/travel-chaos-organizer/frontend/app/_layout.tsx +71 -0
- package/apps/travel-chaos-organizer/frontend/app/auth.tsx +29 -0
- package/apps/travel-chaos-organizer/frontend/app/index.tsx +16 -0
- package/apps/travel-chaos-organizer/frontend/app/onboarding.tsx +119 -0
- package/apps/travel-chaos-organizer/frontend/app.config.ts +54 -0
- package/apps/travel-chaos-organizer/frontend/assets/adaptive-icon.svg +66 -0
- package/apps/travel-chaos-organizer/frontend/assets/icon.svg +79 -0
- package/apps/travel-chaos-organizer/frontend/assets/splash.svg +15 -0
- package/apps/travel-chaos-organizer/frontend/components/BottomSheet.tsx +102 -0
- package/apps/travel-chaos-organizer/frontend/components/ConfettiCannon.tsx +107 -0
- package/apps/travel-chaos-organizer/frontend/components/ConfirmDialog.tsx +109 -0
- package/apps/travel-chaos-organizer/frontend/components/ErrorBoundary.tsx +45 -0
- package/apps/travel-chaos-organizer/frontend/components/FileUploadButton.tsx +19 -0
- package/apps/travel-chaos-organizer/frontend/components/ImportSheet.tsx +155 -0
- package/apps/travel-chaos-organizer/frontend/components/OfflineBadge.tsx +55 -0
- package/apps/travel-chaos-organizer/frontend/components/QRCodeViewer.tsx +80 -0
- package/apps/travel-chaos-organizer/frontend/components/ScoreRing.tsx +39 -0
- package/apps/travel-chaos-organizer/frontend/components/Screen.tsx +39 -0
- package/apps/travel-chaos-organizer/frontend/components/Skeleton.tsx +70 -0
- package/apps/travel-chaos-organizer/frontend/components/SwipeableInboxItem.tsx +121 -0
- package/apps/travel-chaos-organizer/frontend/components/SwipeableTimelineItem.tsx +70 -0
- package/apps/travel-chaos-organizer/frontend/components/TimelineItem.tsx +73 -0
- package/apps/travel-chaos-organizer/frontend/components/TimelineItemDetail.tsx +130 -0
- package/apps/travel-chaos-organizer/frontend/components/Toast.tsx +60 -0
- package/apps/travel-chaos-organizer/frontend/components/ToastContext.tsx +42 -0
- package/apps/travel-chaos-organizer/frontend/components/TripCard.tsx +146 -0
- package/apps/travel-chaos-organizer/frontend/components/TripQRModal.tsx +70 -0
- package/apps/travel-chaos-organizer/frontend/components/UpgradeBanner.tsx +44 -0
- package/apps/travel-chaos-organizer/frontend/eas.json +22 -0
- package/apps/travel-chaos-organizer/frontend/hooks/useInbox.ts +24 -0
- package/apps/travel-chaos-organizer/frontend/hooks/useNetworkSync.ts +60 -0
- package/apps/travel-chaos-organizer/frontend/hooks/useTrips.ts +112 -0
- package/apps/travel-chaos-organizer/frontend/lib/api.ts +223 -0
- package/apps/travel-chaos-organizer/frontend/lib/auth.ts +93 -0
- package/apps/travel-chaos-organizer/frontend/lib/db.ts +86 -0
- package/apps/travel-chaos-organizer/frontend/lib/fileCache.ts +54 -0
- package/apps/travel-chaos-organizer/frontend/lib/haptics.ts +13 -0
- package/apps/travel-chaos-organizer/frontend/lib/notifications.ts +112 -0
- package/apps/travel-chaos-organizer/frontend/lib/offlineQueue.ts +145 -0
- package/apps/travel-chaos-organizer/frontend/lib/quota.tsx +43 -0
- package/apps/travel-chaos-organizer/frontend/lib/sentry.ts +28 -0
- package/apps/travel-chaos-organizer/frontend/lib/shareIntent.ts +44 -0
- package/apps/travel-chaos-organizer/frontend/package-lock.json +13037 -0
- package/apps/travel-chaos-organizer/frontend/package.json +44 -0
- package/apps/travel-chaos-organizer/frontend/tsconfig.json +23 -0
- package/apps/travel-chaos-organizer/keycloak/realm-export.json +59 -0
- package/apps/travel-chaos-organizer/landing/index.html +773 -0
- package/apps/travel-chaos-organizer/scripts/backup.sh +14 -0
- package/apps/travel-chaos-organizer/scripts/configure-env.sh +82 -0
- package/apps/travel-chaos-organizer/scripts/deploy.sh +54 -0
- package/apps/travel-chaos-organizer/scripts/health-check.sh +36 -0
- package/apps/travel-chaos-organizer/scripts/migrate.sh +7 -0
- package/apps/travel-chaos-organizer/scripts/server-setup.sh +85 -0
- package/apps/travel-chaos-organizer/scripts/smoke-test.sh +29 -0
- package/apps/travel-chaos-organizer/scripts/verify-tracking.sh +71 -0
- package/apps/travel-chaos-organizer/telegram-bot/.env.example +3 -0
- package/apps/travel-chaos-organizer/telegram-bot/Dockerfile +6 -0
- package/apps/travel-chaos-organizer/telegram-bot/bot.py +504 -0
- package/apps/travel-chaos-organizer/telegram-bot/requirements.txt +3 -0
- package/dist/packages/telegram-notify/client.d.ts +19 -0
- package/dist/packages/telegram-notify/client.js +75 -0
- package/dist/packages/telegram-notify/client.js.map +1 -0
- package/dist/src/__tests__/auth.test.js.map +1 -0
- package/dist/{__tests__ → src/__tests__}/brain-flow.test.js +143 -2
- package/dist/src/__tests__/brain-flow.test.js.map +1 -0
- package/dist/src/__tests__/confidence.test.js.map +1 -0
- package/dist/src/__tests__/e2e/api-auth.test.js.map +1 -0
- package/dist/src/__tests__/e2e/api-health.test.js.map +1 -0
- package/dist/src/__tests__/e2e/cli.test.js.map +1 -0
- package/dist/src/__tests__/e2e/config.js.map +1 -0
- package/dist/src/__tests__/e2e/funnel.test.js.map +1 -0
- package/dist/src/__tests__/e2e/mcp-tools.test.js.map +1 -0
- package/dist/src/__tests__/e2e/provisioning.test.js.map +1 -0
- package/dist/{__tests__ → src/__tests__}/handlers-unit.test.js +1 -1
- package/dist/src/__tests__/handlers-unit.test.js.map +1 -0
- package/dist/src/__tests__/namespace.test.js.map +1 -0
- package/dist/src/auth.js.map +1 -0
- package/dist/src/ckg.js.map +1 -0
- package/dist/src/confidence.js.map +1 -0
- package/dist/src/embeddings.js.map +1 -0
- package/dist/src/handlers/advanced.js.map +1 -0
- package/dist/{handlers → src/handlers}/brain.js +135 -31
- package/dist/src/handlers/brain.js.map +1 -0
- package/dist/src/handlers/cache.js.map +1 -0
- package/dist/{handlers → src/handlers}/context.js +9 -4
- package/dist/src/handlers/context.js.map +1 -0
- package/dist/{handlers → src/handlers}/fedbrain.d.ts +6 -0
- package/dist/{handlers → src/handlers}/fedbrain.js +15 -2
- package/dist/src/handlers/fedbrain.js.map +1 -0
- package/dist/src/handlers/instances.js.map +1 -0
- package/dist/{handlers → src/handlers}/roadmap.js +8 -4
- package/dist/src/handlers/roadmap.js.map +1 -0
- package/dist/src/handlers/syndicate.js.map +1 -0
- package/dist/src/handlers/tco.d.ts +16 -0
- package/dist/src/handlers/tco.js +303 -0
- package/dist/src/handlers/tco.js.map +1 -0
- package/dist/{handlers → src/handlers}/team.js +1 -1
- package/dist/src/handlers/team.js.map +1 -0
- package/dist/{index.js → src/index.js} +145 -97
- package/dist/src/index.js.map +1 -0
- package/dist/src/namespace.js.map +1 -0
- package/dist/src/notifier.d.ts +5 -0
- package/dist/src/notifier.js +6 -0
- package/dist/src/notifier.js.map +1 -0
- package/dist/{search.js → src/search.js} +3 -3
- package/dist/src/search.js.map +1 -0
- package/dist/src/search.test.js.map +1 -0
- package/dist/{tools.d.ts → src/tools.d.ts} +196 -0
- package/dist/{tools.js → src/tools.js} +178 -0
- package/dist/src/tools.js.map +1 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +3 -2
- package/packages/telegram-notify/SPLIT_PLAN.md +106 -0
- package/packages/telegram-notify/client.ts +88 -0
- package/packages/telegram-notify/emojis.json +22 -0
- package/packages/telegram-notify/pyproject.toml +17 -0
- package/packages/telegram-notify/telegram_notify/__init__.py +3 -0
- package/packages/telegram-notify/telegram_notify/client.py +87 -0
- package/packages/telegram-notify/telegram_notify/emojis.json +22 -0
- package/scripts/generate-icons.js +28 -0
- package/smithery.yaml +21 -10
- package/src/__tests__/brain-flow.test.ts +176 -2
- package/src/__tests__/handlers-unit.test.ts +1 -1
- package/src/handlers/brain.ts +139 -32
- package/src/handlers/context.ts +9 -4
- package/src/handlers/fedbrain.ts +17 -2
- package/src/handlers/roadmap.ts +8 -4
- package/src/handlers/tco.ts +347 -0
- package/src/handlers/team.ts +1 -1
- package/src/index.ts +137 -147
- package/src/notifier.ts +5 -0
- package/src/search.ts +3 -3
- package/src/tools.ts +191 -0
- package/tsconfig.json +2 -3
- package/dist/__tests__/auth.test.js.map +0 -1
- package/dist/__tests__/brain-flow.test.js.map +0 -1
- package/dist/__tests__/brain-predict-failures.test.d.ts +0 -17
- package/dist/__tests__/brain-predict-failures.test.js +0 -339
- package/dist/__tests__/brain-predict-failures.test.js.map +0 -1
- package/dist/__tests__/confidence.test.js.map +0 -1
- package/dist/__tests__/e2e/api-auth.test.js.map +0 -1
- package/dist/__tests__/e2e/api-health.test.js.map +0 -1
- package/dist/__tests__/e2e/cli.test.js.map +0 -1
- package/dist/__tests__/e2e/config.js.map +0 -1
- package/dist/__tests__/e2e/funnel.test.js.map +0 -1
- package/dist/__tests__/e2e/mcp-tools.test.js.map +0 -1
- package/dist/__tests__/e2e/provisioning.test.js.map +0 -1
- package/dist/__tests__/handlers-unit.test.js.map +0 -1
- package/dist/__tests__/namespace.test.js.map +0 -1
- package/dist/auth.js.map +0 -1
- package/dist/ckg.js.map +0 -1
- package/dist/confidence.js.map +0 -1
- package/dist/embeddings.js.map +0 -1
- package/dist/handlers/advanced.js.map +0 -1
- package/dist/handlers/brain.js.map +0 -1
- package/dist/handlers/cache.js.map +0 -1
- package/dist/handlers/context.js.map +0 -1
- package/dist/handlers/fedbrain.js.map +0 -1
- package/dist/handlers/instances.js.map +0 -1
- package/dist/handlers/roadmap.js.map +0 -1
- package/dist/handlers/syndicate.js.map +0 -1
- package/dist/handlers/team.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/namespace.js.map +0 -1
- package/dist/search.js.map +0 -1
- package/dist/search.test.js.map +0 -1
- package/dist/tools.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/src/__tests__/brain-predict-failures.test.ts +0 -430
- /package/dist/{__tests__ → src/__tests__}/auth.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/auth.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/brain-flow.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/confidence.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/confidence.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/api-auth.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/api-auth.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/api-health.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/api-health.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/cli.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/cli.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/config.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/config.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/funnel.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/funnel.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/mcp-tools.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/mcp-tools.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/provisioning.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/e2e/provisioning.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/handlers-unit.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/namespace.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/namespace.test.js +0 -0
- /package/dist/{auth.d.ts → src/auth.d.ts} +0 -0
- /package/dist/{auth.js → src/auth.js} +0 -0
- /package/dist/{ckg.d.ts → src/ckg.d.ts} +0 -0
- /package/dist/{ckg.js → src/ckg.js} +0 -0
- /package/dist/{confidence.d.ts → src/confidence.d.ts} +0 -0
- /package/dist/{confidence.js → src/confidence.js} +0 -0
- /package/dist/{embeddings.d.ts → src/embeddings.d.ts} +0 -0
- /package/dist/{embeddings.js → src/embeddings.js} +0 -0
- /package/dist/{handlers → src/handlers}/advanced.d.ts +0 -0
- /package/dist/{handlers → src/handlers}/advanced.js +0 -0
- /package/dist/{handlers → src/handlers}/brain.d.ts +0 -0
- /package/dist/{handlers → src/handlers}/cache.d.ts +0 -0
- /package/dist/{handlers → src/handlers}/cache.js +0 -0
- /package/dist/{handlers → src/handlers}/context.d.ts +0 -0
- /package/dist/{handlers → src/handlers}/instances.d.ts +0 -0
- /package/dist/{handlers → src/handlers}/instances.js +0 -0
- /package/dist/{handlers → src/handlers}/roadmap.d.ts +0 -0
- /package/dist/{handlers → src/handlers}/syndicate.d.ts +0 -0
- /package/dist/{handlers → src/handlers}/syndicate.js +0 -0
- /package/dist/{handlers → src/handlers}/team.d.ts +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{namespace.d.ts → src/namespace.d.ts} +0 -0
- /package/dist/{namespace.js → src/namespace.js} +0 -0
- /package/dist/{search.d.ts → src/search.d.ts} +0 -0
- /package/dist/{search.test.d.ts → src/search.test.d.ts} +0 -0
- /package/dist/{search.test.js → src/search.test.js} +0 -0
- /package/dist/{utils.d.ts → src/utils.d.ts} +0 -0
- /package/dist/{utils.js → src/utils.js} +0 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# Travel Chaos Organizer — Deployment & Test Checklist
|
|
2
|
+
|
|
3
|
+
> Hand this file to any agent or developer to get the app running end-to-end.
|
|
4
|
+
> Everything below assumes a fresh Ubuntu 22.04 VPS and an Android phone for testing.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Prerequisites
|
|
9
|
+
|
|
10
|
+
| What | Where to get |
|
|
11
|
+
|------|-------------|
|
|
12
|
+
| VPS (min. 2 GB RAM) | Hetzner / DigitalOcean / any Ubuntu 22.04 |
|
|
13
|
+
| Domain pointing to VPS | Your DNS provider → A record → VPS IP |
|
|
14
|
+
| Stripe account | stripe.com — get secret key + webhook secret + price ID |
|
|
15
|
+
| Resend account | resend.com — get API key, verify sender domain |
|
|
16
|
+
| Telegram bot (optional) | @BotFather → create bot → get token + chat ID |
|
|
17
|
+
| Expo account | expo.dev — needed for EAS builds |
|
|
18
|
+
| Android phone | Expo Go from Play Store for quick testing |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Step 1 — Server Setup (run once)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# On the VPS as root:
|
|
26
|
+
curl -o server-setup.sh https://raw.githubusercontent.com/cachly-dev/cachly-mcp/claude/plan-mvp-project-1ORlN/apps/travel-chaos-organizer/scripts/server-setup.sh
|
|
27
|
+
chmod +x server-setup.sh
|
|
28
|
+
bash server-setup.sh
|
|
29
|
+
# → installs Docker, UFW, creates tco user, sets up backup cron
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Step 2 — Configure Environment
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# As the tco user on the VPS:
|
|
38
|
+
git clone https://github.com/cachly-dev/cachly-mcp.git /home/tco/app
|
|
39
|
+
cd /home/tco/app/apps/travel-chaos-organizer
|
|
40
|
+
bash scripts/configure-env.sh
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**The script asks for these values — have them ready:**
|
|
44
|
+
|
|
45
|
+
### Backend `.env` (created at `apps/travel-chaos-organizer/.env`)
|
|
46
|
+
|
|
47
|
+
| Variable | Value / Where to find |
|
|
48
|
+
|----------|-----------------------|
|
|
49
|
+
| `DATABASE_URL` | `postgresql+asyncpg://tco:YOURPASSWORD@postgres:5432/tco` |
|
|
50
|
+
| `KEYCLOAK_URL` | `https://auth.YOURDOMAIN.com` |
|
|
51
|
+
| `KEYCLOAK_REALM` | `tco` |
|
|
52
|
+
| `KEYCLOAK_CLIENT_ID` | `tco-app` |
|
|
53
|
+
| `OLLAMA_URL` | `http://ollama:11434` |
|
|
54
|
+
| `OLLAMA_MODEL` | `llama3.2-vision` |
|
|
55
|
+
| `STRIPE_SECRET_KEY` | Stripe Dashboard → Developers → API keys |
|
|
56
|
+
| `STRIPE_WEBHOOK_SECRET` | Stripe Dashboard → Webhooks → signing secret |
|
|
57
|
+
| `STRIPE_PRO_PRICE_ID` | Stripe Dashboard → Products → your Pro price ID |
|
|
58
|
+
| `RESEND_API_KEY` | Resend Dashboard → API Keys |
|
|
59
|
+
| `RESEND_FROM` | `TCO <noreply@YOURDOMAIN.com>` |
|
|
60
|
+
| `ADMIN_USER` | choose a username (not "admin") |
|
|
61
|
+
| `ADMIN_PASSWORD` | strong password (min 20 chars) |
|
|
62
|
+
| `TELEGRAM_BOT_TOKEN` | @BotFather → your bot token (optional) |
|
|
63
|
+
| `TCO_TELEGRAM_CHAT_ID` | your personal/group chat ID (optional) |
|
|
64
|
+
| `SENTRY_DSN` | sentry.io → project → DSN (optional) |
|
|
65
|
+
| `CORS_ORIGINS` | `https://YOURDOMAIN.com` (lock down in production) |
|
|
66
|
+
| `SECRET_KEY` | run: `openssl rand -hex 32` |
|
|
67
|
+
| `APP_URL` | `https://YOURDOMAIN.com` |
|
|
68
|
+
|
|
69
|
+
### Frontend `.env.production` (created at `apps/travel-chaos-organizer/frontend/.env.production`)
|
|
70
|
+
|
|
71
|
+
| Variable | Value |
|
|
72
|
+
|----------|-------|
|
|
73
|
+
| `EXPO_PUBLIC_API_URL` | `https://YOURDOMAIN.com` |
|
|
74
|
+
| `EXPO_PUBLIC_KEYCLOAK_URL` | `https://auth.YOURDOMAIN.com` |
|
|
75
|
+
| `EXPO_PUBLIC_KEYCLOAK_REALM` | `tco` |
|
|
76
|
+
| `EXPO_PUBLIC_KEYCLOAK_CLIENT_ID` | `tco-app` |
|
|
77
|
+
| `EXPO_PUBLIC_UPGRADE_URL` | `https://YOURDOMAIN.com/upgrade` (or Stripe payment link) |
|
|
78
|
+
| `EXPO_PUBLIC_PRIVACY_URL` | `https://YOURDOMAIN.com/privacy` |
|
|
79
|
+
| `EXPO_PUBLIC_TERMS_URL` | `https://YOURDOMAIN.com/terms` |
|
|
80
|
+
| `EXPO_PUBLIC_SUPPORT_EMAIL` | `support@YOURDOMAIN.com` |
|
|
81
|
+
| `EXPO_PUBLIC_SENTRY_DSN` | same Sentry DSN as backend (optional) |
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Step 3 — Deploy Backend
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
cd /home/tco/app/apps/travel-chaos-organizer
|
|
89
|
+
bash scripts/deploy.sh
|
|
90
|
+
# → pulls images, builds, starts containers, runs Alembic migrations
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Verify it's running:**
|
|
94
|
+
```bash
|
|
95
|
+
bash scripts/health-check.sh
|
|
96
|
+
# Should print: ✓ API healthy, ✓ Keycloak reachable
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Step 4 — Pull Ollama Model
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# On the VPS (this downloads ~2GB, takes a few minutes):
|
|
105
|
+
docker exec tco-ollama ollama pull llama3.2-vision
|
|
106
|
+
|
|
107
|
+
# Verify:
|
|
108
|
+
docker exec tco-ollama ollama list
|
|
109
|
+
# Should show: llama3.2-vision
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Step 5 — Configure Keycloak
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Open in browser:
|
|
118
|
+
https://auth.YOURDOMAIN.com/admin
|
|
119
|
+
|
|
120
|
+
# Login with: admin / (password set during server-setup.sh)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
1. **Import realm**: Realm Settings → Import → upload `keycloak/realm-export.json`
|
|
124
|
+
2. **Set SMTP** (for password reset emails):
|
|
125
|
+
- Realm Settings → Email → configure with your SMTP provider
|
|
126
|
+
3. **Create first user** (optional — users can self-register):
|
|
127
|
+
- Users → Add user → set email + temp password
|
|
128
|
+
4. **Verify redirect URIs**: Clients → tco-app → Settings → Valid redirect URIs should include:
|
|
129
|
+
- `tco://*`
|
|
130
|
+
- `exp://*`
|
|
131
|
+
- `https://auth.expo.io/@YOUR_EXPO_USERNAME/tco`
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Step 6 — Configure Stripe Webhook
|
|
136
|
+
|
|
137
|
+
1. Go to Stripe Dashboard → Developers → Webhooks
|
|
138
|
+
2. Click "Add endpoint"
|
|
139
|
+
3. Endpoint URL: `https://YOURDOMAIN.com/api/v1/payments/webhook`
|
|
140
|
+
4. Events to listen for:
|
|
141
|
+
- `checkout.session.completed`
|
|
142
|
+
- `customer.subscription.deleted`
|
|
143
|
+
- `customer.subscription.paused`
|
|
144
|
+
- `invoice.payment_succeeded`
|
|
145
|
+
- `invoice.payment_failed`
|
|
146
|
+
5. Copy the signing secret → put in `STRIPE_WEBHOOK_SECRET` env var
|
|
147
|
+
6. Re-run `bash scripts/deploy.sh` to apply the new env var
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Step 7 — Generate App Icons (local, on your machine)
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# On your local machine in the repo:
|
|
155
|
+
cd apps/travel-chaos-organizer/frontend
|
|
156
|
+
npm install -g sharp-cli
|
|
157
|
+
node ../../scripts/generate-icons.js
|
|
158
|
+
# → creates icon.png, adaptive-icon.png, splash.png, favicon.png in assets/
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
> If sharp-cli fails: open `assets/icon.svg` in a browser, screenshot at 1024×1024, save as `assets/icon.png`. Repeat for splash at 1284×2778.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Step 8 — Test on Android with Expo Go (quickest)
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# On your local machine:
|
|
169
|
+
cd apps/travel-chaos-organizer/frontend
|
|
170
|
+
cp .env.production .env.local # use production config
|
|
171
|
+
npx expo start --tunnel # --tunnel makes it reachable over internet
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
1. Install **Expo Go** from Play Store on your Android phone
|
|
175
|
+
2. Scan the QR code shown in the terminal
|
|
176
|
+
3. App opens on your phone with live reload
|
|
177
|
+
|
|
178
|
+
**Test these flows in order:**
|
|
179
|
+
- [ ] Onboarding slides swipe correctly, "Start" navigates to login
|
|
180
|
+
- [ ] Login via Keycloak opens browser, redirects back to app
|
|
181
|
+
- [ ] `/api/v1/users/me` returns plan (check Network tab or backend logs)
|
|
182
|
+
- [ ] Create a trip → check it appears in list
|
|
183
|
+
- [ ] Upload a PDF/screenshot → Ollama parses it → item appears in timeline
|
|
184
|
+
- [ ] Parse success triggers confetti ✨
|
|
185
|
+
- [ ] Trip countdown shows correct days
|
|
186
|
+
- [ ] Score ring updates after adding flight/hotel items
|
|
187
|
+
- [ ] Tap "↗" share button → share sheet opens with formatted text
|
|
188
|
+
- [ ] Inbox shows parsed items without trip_id
|
|
189
|
+
- [ ] Assign inbox item to trip
|
|
190
|
+
- [ ] Go offline (airplane mode) → create trip → back online → syncs
|
|
191
|
+
- [ ] Settings → Plan shows Free/Pro correctly
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Step 9 — Build Production APK with EAS
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# On your local machine (one-time setup):
|
|
199
|
+
npm install -g eas-cli
|
|
200
|
+
eas login # with your Expo account
|
|
201
|
+
|
|
202
|
+
cd apps/travel-chaos-organizer/frontend
|
|
203
|
+
|
|
204
|
+
# Preview build (sideloadable APK, no Play Store needed):
|
|
205
|
+
eas build --profile preview --platform android
|
|
206
|
+
# → ~10-15 min build time on EAS servers
|
|
207
|
+
# → get download link by email + in Expo dashboard
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Install on phone:**
|
|
211
|
+
1. Open the download link on your Android phone
|
|
212
|
+
2. Tap Install (allow "Install unknown apps" for your browser)
|
|
213
|
+
3. Done — this is the real app, no Expo Go needed
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Step 10 — Smoke Test Production
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
bash scripts/smoke-test.sh
|
|
221
|
+
# Tests: health, waitlist signup, event tracking, admin auth
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
bash scripts/verify-tracking.sh
|
|
226
|
+
# Checks: Sentry DSN, Telegram bot, Resend API, Stripe, Ollama, Cachly Redis
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Admin Dashboard
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
https://YOURDOMAIN.com/admin
|
|
235
|
+
Username: (ADMIN_USER from .env)
|
|
236
|
+
Password: (ADMIN_PASSWORD from .env)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Features:
|
|
240
|
+
- See all users + their plan status
|
|
241
|
+
- Manually upgrade/downgrade a user's plan
|
|
242
|
+
- View telemetry events
|
|
243
|
+
- View waitlist signups
|
|
244
|
+
- Trigger drip email sequence (dry run first!)
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Drip Emails
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
# Dry run first — see what would be sent:
|
|
252
|
+
make drip-dry
|
|
253
|
+
# or: curl -X POST https://YOURDOMAIN.com/admin/drip/run?dry_run=true -u admin:password
|
|
254
|
+
|
|
255
|
+
# Actually send:
|
|
256
|
+
make drip-run
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Set up a cron job on the VPS to run daily:
|
|
260
|
+
```bash
|
|
261
|
+
# As tco user — add to crontab:
|
|
262
|
+
0 9 * * * curl -s -X POST https://YOURDOMAIN.com/admin/drip/run -u ADMIN_USER:ADMIN_PASSWORD
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Backups
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# Manual backup:
|
|
271
|
+
bash scripts/backup.sh
|
|
272
|
+
# → creates timestamped pg_dump in backups/
|
|
273
|
+
|
|
274
|
+
# Docker backup profile (scheduled):
|
|
275
|
+
docker compose --profile backup run backup
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Backups are kept for 30 days, stored in `backups/` on the VPS.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Monitoring
|
|
283
|
+
|
|
284
|
+
| What | Where |
|
|
285
|
+
|------|-------|
|
|
286
|
+
| App errors (mobile) | Sentry → your project |
|
|
287
|
+
| Backend errors | `docker compose logs backend -f` |
|
|
288
|
+
| Stripe payments | Stripe Dashboard → Events |
|
|
289
|
+
| New users / signups | Telegram bot notifications |
|
|
290
|
+
| Admin overview | `https://YOURDOMAIN.com/admin` |
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Common Issues
|
|
295
|
+
|
|
296
|
+
**Parse fails / Ollama error**
|
|
297
|
+
```bash
|
|
298
|
+
docker exec tco-ollama ollama list # is model downloaded?
|
|
299
|
+
docker logs tco-ollama --tail 50 # any errors?
|
|
300
|
+
curl http://localhost:11434/api/tags # is Ollama responding?
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Login fails / Keycloak error**
|
|
304
|
+
```bash
|
|
305
|
+
docker logs tco-keycloak --tail 50
|
|
306
|
+
# Check redirect URIs in Keycloak client config
|
|
307
|
+
# Check EXPO_PUBLIC_KEYCLOAK_URL matches exactly (no trailing slash)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**Stripe webhook returns 400**
|
|
311
|
+
```bash
|
|
312
|
+
docker logs tco-backend --tail 50
|
|
313
|
+
# Check STRIPE_WEBHOOK_SECRET is the signing secret (not the API key)
|
|
314
|
+
# In Stripe Dashboard: Webhooks → your endpoint → "Signing secret" (not "Secret key")
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Push notifications not arriving**
|
|
318
|
+
- Expo Go: notifications don't work in Expo Go — use EAS Preview build
|
|
319
|
+
- Check device has notifications enabled for the app
|
|
320
|
+
- event_at must be in the future for reminders to schedule
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Branch
|
|
325
|
+
|
|
326
|
+
All code is on: `claude/plan-mvp-project-1ORlN`
|
|
327
|
+
|
|
328
|
+
Merge to `main` when ready to ship.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
.PHONY: up down build logs ps health smoke migrate migrate-history backup deploy setup-env drip-dry drip-run shell-backend shell-db restart-backend caddy-reload
|
|
2
|
+
|
|
3
|
+
up:
|
|
4
|
+
docker compose up -d
|
|
5
|
+
|
|
6
|
+
down:
|
|
7
|
+
docker compose down
|
|
8
|
+
|
|
9
|
+
build:
|
|
10
|
+
docker compose build
|
|
11
|
+
|
|
12
|
+
logs:
|
|
13
|
+
docker compose logs -f --tail=100
|
|
14
|
+
|
|
15
|
+
ps:
|
|
16
|
+
docker compose ps
|
|
17
|
+
|
|
18
|
+
health:
|
|
19
|
+
bash scripts/health-check.sh
|
|
20
|
+
|
|
21
|
+
smoke:
|
|
22
|
+
bash scripts/smoke-test.sh
|
|
23
|
+
|
|
24
|
+
migrate:
|
|
25
|
+
docker compose exec backend alembic upgrade head
|
|
26
|
+
|
|
27
|
+
migrate-history:
|
|
28
|
+
docker compose exec backend alembic history
|
|
29
|
+
|
|
30
|
+
backup:
|
|
31
|
+
docker compose --profile backup run --rm backup
|
|
32
|
+
|
|
33
|
+
deploy:
|
|
34
|
+
bash scripts/deploy.sh
|
|
35
|
+
|
|
36
|
+
setup-env:
|
|
37
|
+
bash scripts/configure-env.sh
|
|
38
|
+
|
|
39
|
+
drip-dry:
|
|
40
|
+
curl -s -u "$$(grep ADMIN_USER .env | cut -d= -f2):$$(grep ADMIN_PASSWORD .env | cut -d= -f2)" \
|
|
41
|
+
-X POST "http://localhost:8000/admin/drip/run?dry_run=true" | python3 -m json.tool
|
|
42
|
+
|
|
43
|
+
drip-run:
|
|
44
|
+
curl -s -u "$$(grep ADMIN_USER .env | cut -d= -f2):$$(grep ADMIN_PASSWORD .env | cut -d= -f2)" \
|
|
45
|
+
-X POST "http://localhost:8000/admin/drip/run" | python3 -m json.tool
|
|
46
|
+
|
|
47
|
+
shell-backend:
|
|
48
|
+
docker compose exec backend bash
|
|
49
|
+
|
|
50
|
+
shell-db:
|
|
51
|
+
docker compose exec postgres psql -U tco -d tco
|
|
52
|
+
|
|
53
|
+
restart-backend:
|
|
54
|
+
docker compose restart backend
|
|
55
|
+
|
|
56
|
+
caddy-reload:
|
|
57
|
+
docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile
|
|
@@ -0,0 +1,159 @@
|
|
|
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.
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
|
@@ -0,0 +1,25 @@
|
|
|
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"]
|
|
@@ -0,0 +1,56 @@
|
|
|
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()
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
|
@@ -0,0 +1,24 @@
|
|
|
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')
|