Skip to content

30 Limitations

Anubha Parashar edited this page Oct 10, 2026 · 1 revision

This page lists the known limitations of HealthBook AI (internal code name: BabyCare) that can be seen in the code, the configuration and the code comments. It is deliberately plain: each item names where it comes from, so readers can check it and contributors can pick it up. Forward-looking work derived from this list is on the Roadmap.

Clinical and regulatory status

Limitation Evidence
No clinical validation and no regulatory status. HealthBook AI is a family-maintained record, not a medical device. Nothing in the code claims clinical validation or regulatory clearance. PDF footer "Family-maintained record"; share summary footer "not a diagnosis or treatment recommendation"; api/reporting.py: "verified transcription is not independent clinical validation"
Growth charts show no percentiles: validated pediatric standards are not implemented. mobile/HealthScreen.tsx, web/analytics.js notes
Stool-photo observations are deterministic colour and texture heuristics on 96–160 px copies, not a trained model. Consistency suggestions are always low confidence, and mucus is "not assessed" by the colour observer. api/care_vision.py, api/stool_intake.py (_texture, suggest)
Daily-care "Ask" answers come from keyword and regular-expression routing over recorded rows. Questions outside the patterns fall through to the general answerer. api/care.py (CARE_TERMS, care_answer)

Hosting and operations (free tier)

Limitation Evidence
The reference deployment uses a free web instance that sleeps after 15 idle minutes and shares 750 instance-hours a month. The first request after idling is slow; the doctor page tells clinicians "The free server may take a minute to wake up". render.yaml, web/doctor.js
The instance disk is ephemeral. Production refuses BABYCARE_STORAGE=local unless BABYCARE_ALLOW_LOCAL_STORAGE=true on a host with a persistent volume. api/config.py, api/storage.py
Background reminder ticks depend on an external scheduler calling the API, because a sleeping host cannot run its own timer. api/cloud.py
The free database pooler limits the app to 10 connections from one instance. api/database.py
Free cloud plans "pause projects and keep no automatic backups". Backups are a manual, user-run encrypted script. scripts/cloud_backup.py
Outbound SMTP is blocked on the free plan, so email depends on an HTTPS email provider being configured. api/mailer.py

Scaling and abuse protection

Limitation Evidence
The production rate limiter is in-memory and per process (BABYCARE_RATE_LIMIT_STORE=memory). It is only correct for a single instance, counts reset on restart, and the table is cleared above 50,000 keys. A database-backed mode exists but is not the configured default. api/guardrails.py, render.yaml
Exports and share ZIPs are built synchronously in memory for each request. Large records (many appended originals) use RAM and request time on a small instance. api/export_api.py, api/export_pdf.py, api/share.py
Upload size is capped at 12 MB per file and 13 MB per request. Bulk stool intake accepts at most 24 photos. api/main.py, api/guardrails.py, api/care_api.py

Documents, OCR and images

Limitation Evidence
OCR is Tesseract (--psm 3) with a 30-second timeout per page and a 200,000-character cap. Handwriting is not reliably transcribed: no dose, frequency or schedule is derived from handwriting, and every OCR row stays unverified until a human checks it. api/extract.py, api/history_api.py
External AI vision is off by default (BABYCARE_VISION_URL empty) and needs consent per document. The app cannot verify a provider's retention terms. api/providers.py, render.yaml
HEIC is optional. heif_support() may fail where the native plugin is blocked, and document upload then returns 415. The stool-photo path imports pillow_heif while reading image dimensions, so if that import fails, any stool photo is rejected as unreadable. api/extract.py, api/main.py, api/care_api.py (_dimensions)
The clinician summary inside share packages is drawn with PyMuPDF base fonts and passed through _latin(), so characters outside Latin-1 are replaced. The full export PDF uses bundled DejaVu fonts. export_pdf.build_share_summary_pdf exists, but the share routes do not call it. api/share.py, api/export_pdf.py
When stool photos are selected, the PDF export prints that they "follow at the end of the appendix", but _append_sources appends only the source documents. Stool photographs are not embedded in this build. api/export_pdf.py
PDF and manifest references use R{document id}, so internal document ids appear inside full exports, even though share-package file names avoid them. api/export_model.py

Daily Health

Limitation Evidence
local_date is computed from the profile timezone at write time. Changing a profile's timezone later does not re-bucket existing entries. api/care_models.py docstring, api/care_api.py (prepare)
Only the mobile app has an offline queue (SecureStore). The web client needs a connection, and a queued item that fails for a non-network reason is dropped. mobile/DailyCareScreen.tsx
Pending stool-intake cards expire after 48 hours, but only lazily: they are cleaned up when the intake list is next read or a new upload arrives. api/care_api.py (_expire_intakes)

Notifications

Limitation Evidence
Mobile push needs EXPO_PUBLIC_EAS_PROJECT_ID, a native development build and a real device. Server push is disabled by default (BABYCARE_PUSH_ENABLED=false, "enable only after device testing"). mobile/App.tsx, render.yaml, api/worker.py
Provider acceptance is not proof of display, and a notification is never proof a dose was given. Notifications

Accounts and sessions

Limitation Evidence
The only account recovery is the email password reset (30-minute single-use token). There is no recovery for a lost email account and no second factor. api/password_reset.py, api/main.py
Registration does not verify email ownership, and it answers 409 Email already registered, which reveals that an account exists, unlike the deliberately generic reset flow. api/main.py (register)
Sessions last 14 days. There is no per-device session management screen. api/security.py
Losing the application Fernet key makes encrypted records unreadable. The app refuses to generate a replacement key when encrypted data exists. api/crypto.py

Share With Doctor

Limitation Evidence
The doctor page keeps the token in the URL fragment, but its API calls put the token in the request path (/api/share/public/{token}), where hosting access logs may record it. web/doctor.js, api/share.py
PIN lockout is a 15-minute window after 8 failures, counted from the access log. There is no permanent lock. api/share.py (_open_package)

Home camera

Limitation Evidence
Posture classes (walking_like, crawling_like, standing, sitting) need a pose model that this build does not ship. The bundled analyser emits only movement and low_activity. api/camera.py
The activity mode is stored, but the bundled worker runs the same motion analyser as motion. api/camera_worker.py
record_clips and retention_days are configuration fields only. The bundled worker writes no clips, and the code has no scheduled retention sweep. Clip blobs are removed only by purge or delete camera. api/camera_worker.py, api/camera_api.py
Test connection and Preview run on the API host, so a cloud-hosted API cannot reach a camera on a private home network. Preview also needs OpenCV on that host. api/camera_api.py
Real streams need opencv-python-headless on the worker machine. The worker-key check uses a plain hash comparison rather than a constant-time compare. api/camera_worker.py, api/camera_api.py

Implementation

Evidence comes from render.yaml, api/config.py, api/guardrails.py, api/database.py, api/storage.py, api/crypto.py, api/extract.py, api/care_api.py, api/share.py, api/export_pdf.py, api/camera*.py, mobile/App.tsx, mobile/DailyCareScreen.tsx and scripts/cloud_backup.py.

Related pages

Roadmap · Deployment Architecture · Security and Privacy Model · Design Decisions · Testing and Validation

Clone this wiki locally