Known gaps and discrepancies
This list was compiled from a read-through of all six repositories in late October 2026. Each item says what the code actually does. When you fix one, delete it here.
Stale documentation inside the repos
| Where | Says | Actually |
|---|---|---|
emaw-mobile-app/CLAUDE.md | Base URL is https://dock.emaw-app.com/ | constants/backendIp.js points at https://app.emaw-app.com/ (dev URL commented out) |
emaw-mobile-app/CLAUDE.md | VersionsContext is in store/versionsContext.js | It is context/VersionsContext.js |
emaw-mobile-app/CLAUDE.md | Tab table lists Home as a tab and has no Bible tab | Home is a hidden tab; Bible is a visible tab |
emaw-mobile-app/CLAUDE.md | Runbook at EMAW_BACKEND/docs/GOOGLE_SIGN_IN_SETUP.md | emaw-django-app/docs/GOOGLE_SIGN_IN_SETUP.md (EMAW_BACKEND is a historical name for the repo) |
emaw-django-app/CLAUDE.md | "Single Django app (EMAW/)" | 14 local apps |
emaw-django-app/CLAUDE.md | Memory verse cache 300 s | USER_CACHE_TTL is 3600 |
emaw-django-app/CLAUDE.md | EMAW model list | Omits SocialIdentity and AppHandoffCode |
emaw-django-app/CLAUDE.md CI/CD section | Describes the GitHub Action to Azure Web App as the deployment | Live deployment is Docker Compose on VMs (dev: SSH; prod: Portainer) |
emaw-django-app/CLAUDE.md vs ONBOARDING.md | Dev DB via cloudflared tunnel on 127.0.0.1:5433 (CLAUDE) vs Tailscale + pgbouncer (ONBOARDING) | Tailscale is current; these docs follow ONBOARDING |
emaw-django-app/EMAW_BACKEND/urls.py comment | AI search is "Postgres + pgvector" | Qdrant |
emaw-website/README.md | Vite template boilerplate | Not project-specific; CLAUDE.md is the real doc |
emaw-crm-app/README.md env table | Lists 2 variables | 5 are read in src/config.ts |
Legacy and leftover artefacts
| Where | Item | Note |
|---|---|---|
emaw-django-app/.github/workflows/main_emawweb.yml, azure-pipelines.yml | Deploy to Azure Web App EMAWWeb on push to main, Python 3.10 / 3.11 | Not the live backend (Docker image is 3.12). Remove them or the App Service to avoid confusion |
emaw-django-app root | questions_with_ids.json, questions_with_ids_and_quiet_times.json, emaw_backup.json | No code references them |
emaw-django-app root | verify_redis_down.py, verify_redis_opt.py, verify_seed_dupes.py, verify_db.sqlite3 | Manual scratch scripts committed with a sqlite file |
emaw-website/constants/url.tsx | Points at an unrelated API | Unused |
emaw-website/.env.development, .env.production | Set VITE_BACKEND_URL | Nothing reads it |
emaw-website/.dev.vars | R2_*, STUDIO_* keys | Nothing in the repo reads them; R2 credentials belong on the backend |
emaw-mobile-app/.env | EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID, EXPO_PUBLIC_GOOGLE_ANDROID_LOCAL_CLIENT_ID | Never read; Android matches by package + SHA-1 |
emaw-mobile-app/android/app/src/main/res/values/strings.xml (local prebuild) | expo_runtime_version 1.1.2 | App is 1.1.3; regenerated by prebuild |
Configuration gaps
| Where | Gap |
|---|---|
emaw-django-app/docker-compose.yml x-app-env | Variables read by settings but not passed to containers: SHIPPING_RATE_SOURCE, SHIPPING_HISTORY_RECENT_DAYS, SHIPPING_HISTORY_HALF_LIFE_DAYS, FULFILLMENT_TIME_ZONE, EVENTS_PAYMENT_METHOD_CONFIGURATION, EVENTS_NOTIFY_RECIPIENTS, CONTACT_FORM_RECIPIENTS, GEOGRAPHY_ASSIGN_SYNC_MAX, GEOGRAPHY_RUN_STALE_MINUTES, CRM_CONTACT_LIST_CACHE_SECONDS, OPENAI_API_KEY |
emaw-django-app/.env | Present but never read: EMAIL_PASSWORD, QUICK_BOOKS_CLIENT_ID, QUICK_BOOKS_CLIENT_SECRET, ALLOWED_HOSTS (the hosts list is hard-coded per settings module) |
emaw-django-app settings | JWT_SIGNING_KEY is read but SIMPLE_JWT["SIGNING_KEY"] uses SECRET_KEY |
emaw-mobile-app/package.json | expo-dev-client is not a dependency although npm start uses --dev-client and the EAS development profile sets developmentClient: true |
emaw-mobile-app/eas.json | No ascAppId for iOS submit; no Android submit profile |
emaw-mobile-app | Backend URL is hard-coded; switching to dev means editing a tracked file |
| Package names | emaw-website is emapw-website; emaw-web-app is emaw-website; emaw-crm-app is emaw-admin |
| No repo | sets a Node engines field or .nvmrc; CI uses Node 24, the team standard is 26 |
Pipeline gaps
| App | Gap |
|---|---|
| Backend | No CI at all (no tests on PR, no automated deploy). Dev is deployed by git pull on the VM; prod by Portainer |
| Website | No production workflow; manual wrangler pages deploy |
| Admin CRM | No production workflow; npm test not run in the develop workflow |
| All frontends | The raw *.pages.dev hostnames should be behind Cloudflare Access where the custom domain is |
| Mobile | No EAS workflow; builds and updates are run by hand |
Test coverage gaps
| Where | Gap |
|---|---|
emaw-django-app | notes, bibles and ai are in pytest.ini testpaths but have no test files |
emaw-website, emaw-web-app, emaw-mobile-app | No test runner configured |
Operations gaps
See Backups and recovery (open items) and Logs and monitoring (no uptime check, alerting, log shipping or crash reporting).
Security notes
- Production VM and database are not on Tailscale yet; the IP whitelist is the control until the planned migration.
- Django admin (
/admin/) is behind the tunnel but not behind Cloudflare Access. emaw-mobile-app/.envis committed; it holds only public OAuth client ids, which is acceptable, but keep it that way.