Commit graph

16 commits

Author SHA1 Message Date
Daniel
713ed830a3 chore: script to move audio backups onto MinIO; record where things stand
Same MinIO, its own bucket, as asked. The audio-backups bucket is created;
what remains is a MinIO IAM change, which needs root credentials — my
permission layer blocked that call, so it is a script to run rather than
something I applied.

The script is additive and reversible: it attaches a second policy covering
only the new bucket and carries the existing generated-images grant over
rather than replacing it (attaching only the new one would break image
storage). It prints the AUDIO_BACKUPS_S3_* values to set, and how to undo.

A bucket policy alone does not work here: MinIO evaluates the user policy
first and it denies by default. Verified — the app key gets AccessDenied on
the new bucket until its own policy allows it.

TODO records that, and the indexer being repointed from Documents to
Personal assistant so mail is finally reached.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-10 17:00:02 +02:00
Daniel
6be2d1375a feat: integrate durable image jobs/private assets into current core 2026-09-07 16:53:42 +02:00
Daniel
cfaf8e957b feat: ship reviewed prompt history, conversation limits and account protections 2026-09-07 04:01:01 +02:00
Daniel
f556d50a09 Remove the --gh flag from release.sh
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 2m46s
release.sh --gh ran `gh release create` against GitHub. This project
publishes releases to Forgejo, and CI does it automatically on a v* tag
push (.forgejo/workflows/android-apk.yml attaches the signed APK for
Obtainium). The flag could not do anything useful here, and having it in
the usage text implied a manual publish step that does not exist.

Drops the flag, its DO_RELEASE branch, and the usage/header references.
--push remains the only option.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 01:52:04 +02:00
Daniel
a814d2a2c2 Fix release.sh pushing to a remote that does not exist
All checks were successful
Forgejo Android APK / Build signed APK (push) Successful in 2m27s
--push ran `git push origin HEAD`, but this repo's only remote is named
forgejo — so the flag failed after the script had already committed and
tagged, leaving the release half-done. Resolve the remote instead:
prefer forgejo, fall back to origin, else use the only remote present,
and fail with a clear message if there is none.

Also corrects the header comment, which claimed the script does not build
the APK and pointed at --gh / gh CLI. Forgejo CI builds the APK on every
branch push and attaches it to a Forgejo release on a v* tag push, which
is what Obtainium tracks. --gh is a leftover from the GitHub era.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 18:05:43 +02:00
Daniel
a08524d95f harden logging and observability 2026-05-08 19:08:19 +02:00
Daniel
67b7667e04 feat: ED encounters + notes model selector; remove AI corrections; fix notes framing
Four changes batched:

1. ED Encounters tab (new) — multi-stage emergency note with don't-miss
   tooltips and 2023 E/M MDM finalize. New route /api/ed-encounters
   (generate per-stage + finalize MDM), new ed-encounters.js owning all
   client logic, new ed-encounter.html component, new template_ed memory
   category. Persists draft to localStorage every keystroke and to
   saved_encounters on stage advance. encounters.js touched only to
   register the new tab in sessionStorage restore + tabMap (save and
   idempotency code untouched).

2. Notes model selector — /notes/from-voice now accepts a client-supplied
   model (validated by the existing callAI allow-list); falls back to the
   admin default. Added <select class="tab-model-select"> to notes.html
   so the existing app.js populator handles options + default.

3. Remove AI-learning-from-corrections — deleted correctionTracker.js,
   POST /memories/correction, the corrections branch in
   /memories/context, the settings UI section, the FAQ entry, and all
   dead trackAIOutput/saveCorrection guards in callers. Legacy
   correction_* DB rows are filtered (NOT LIKE) rather than dropped, so
   no destructive migration.

4. Fix notes AI framing — /notes/from-voice prompt no longer assumes
   "physician dictation". Plain notes (shopping lists, reminders,
   ideas) now match the dictation tone instead of being forced into
   clinical structure.

All 46 tests pass.
2026-04-28 03:09:38 +02:00
Daniel
d71714b65d test(lint): static reference linter — catches dead-code + orphan refs
You were right that Playwright has been catching the easy bugs while
the high-signal bugs (lightbox stranded after the Bedside reorg, PVC
clinically wrong, prod not rebuilt) all had to be caught by you as
the user. Adding a static linter so the class of bug that produced
the lightbox regression fails CI next time instead of the app.

scripts/lint-references.js walks public/js and validates every
getElementById('X') and querySelector('#X') resolves to an id that
is defined SOMEWHERE in the repo — either a static HTML attribute,
a .id = 'X' assignment, or an id="X" substring inside a JS template
string. It also walks HTML for asset references (data-img-src,
<img src>, <audio src>, <link href>) and verifies each root-absolute
path maps to a real file on disk.

Running it on the current tree surfaced two real problems:

1. shadess.js:917 reached for #wv-note-transcript when collecting
   refine source context. The actual id is #wv-transcript (no -note-
   infix — the transcript element is shared across well-visit sub-
   panels). The bug meant a generated well-visit note's Refine call
   silently missed the original transcript as source context; the AI
   still "worked" but with less signal and no error. Fixed.

2. public/js/adminMilestones.js (221 lines) referenced 17 ids that
   were removed a year+ ago in commit 3173ce6 ("Remove milestone
   admin UI, add CMS content refresh button"). That commit dropped
   the HTML but forgot the JS, which has been dead-loaded on every
   page view since. All its addEventListener calls are guarded with
   optional chaining, so nothing errored — just silent cruft.
   Deleted the file and dropped the <script defer> tag from
   index.html.

scripts/e2e.sh runs the linter as a preflight before the Playwright
container starts; a broken reference now fails the suite before any
test even boots.

Allowlist is kept small and prefix-based for the handful of id families
that are built dynamically by JS (bedside em-* sections, BP chart
elements, etc.). When a new component is added, its ids get picked up
automatically by the repo-wide collect() pass; the allowlist rarely
needs to grow.

Suite: 294 passed / 0 failed.
2026-04-23 18:58:38 +02:00
Daniel
abdbaa3507 feat: A1+A2 — Playwright smoke suite + index.html mtime-based caching
Safety net for upcoming refactors:
- 26 Playwright smoke tests via @playwright/test 1.50.0 in an official
  Playwright container (no host Node needed). Covers every Bedside sub-pill,
  the age→weight estimator, dose calculators (seizure/sepsis/anaphylaxis/
  burns/airway), and interactive widgets (lightbox, vent SVG).
- `npm run e2e` wrapper runs tests inside mcr.microsoft.com/playwright:v1.50.0-noble
  on the ped-ai_default Docker network so no host port mapping is needed.
- public/e2e-harness.html + public/js/e2e-bootstrap.js load the calculators
  component without the SPA auth wall (scripts external to satisfy CSP).

Server:
- server.js now re-reads public/index.html on mtime change instead of
  caching at boot. Fixes the "edit HTML, restart container" friction.
- CSP upgradeInsecureRequests disabled in helmet config; Caddy still
  enforces HTTPS at the reverse-proxy layer in production.
2026-04-20 03:51:22 +02:00
Daniel
d0009e94ed release.sh: drop node dependency, use sed for version bump 2026-04-14 23:40:38 +02:00
Daniel
73398e91ed Version alignment + release script — single source of truth
Aligns every version string in the repo to 6.1.0:
  - package.json: 6.0.0 → 6.1.0
  - mobile/package.json: 1.0.0 → 6.1.0
  - mobile/android/app/build.gradle: versionCode 1 → 610,
      versionName "1.0" → "6.1.0"
  - server.js: hardcoded "v6.0" → reads root package.json at boot
  - /api/health/detailed now reports APP_VERSION from package.json

Adds scripts/release.sh — a one-command bump:
  scripts/release.sh 6.1.1                # local bump + tag
  scripts/release.sh 6.1.1 --push         # + git push
  scripts/release.sh 6.1.1 --push --gh    # + GitHub release (uploads
                                            APK if already built)

Updates all three version sites, commits "Release v6.1.1",
creates annotated tag, optionally pushes and opens a release.
versionCode encoded as MAJ*100000 + MIN*1000 + PATCH so patch
updates always increment monotonically.
2026-04-14 23:18:47 +02:00
Daniel
0bbecb76f9 Maintenance CLI + unpin postgres digest
Adds `npm run maint:check` (health report) and `npm run maint:reindex`
(REINDEX DATABASE + REFRESH COLLATION VERSION + ANALYZE) for post-
upgrade maintenance, modelled after Nextcloud's occ maintenance.
Documented in README.

Also relaxes postgres image from digest pin back to tag-pin
(pgvector/pgvector:pg16) — the auto-REINDEX-on-drift check in
database.js and the COLLATE "C" protection on critical indexes
make the digest pin redundant while blocking ordinary `compose
pull` updates.
2026-04-14 04:00:13 +02:00
ifedan-ed
540347c015 v6: Use transformers.js v2.0.0 (proven worker compatibility)
Some checks failed
Build TWA APK / build-apk (push) Has been cancelled
Build & Push Docker Image / build (push) Has been cancelled
2026-04-01 00:32:23 +00:00
ifedan-ed
0dc6812f38 FIX: Browser Whisper - 100% self-hosted, zero CDN dependencies
Some checks failed
Build TWA APK / build-apk (push) Has been cancelled
Build & Push Docker Image / build (push) Has been cancelled
FINAL WORKING SOLUTION:

Previous attempts failed because:
- transformers.js v2.17.2 is ES module-only
- Module workers require complex CSP and external imports
- importScripts() doesn't work with ES modules

Solution:
- Use transformers.js v2.6.2 (has worker-compatible UMD build)
- Bundle library + models, serve entirely from our server
- Classic worker with importScripts() - no CSP issues

What's self-hosted:
-  transformers.min.js (760KB) - at /models/transformers.min.js
-  Whisper models (42MB) - at /models/Xenova/whisper-tiny.en/

Worker loads:
1. importScripts('/models/transformers.min.js') - OUR SERVER
2. Loads models from /models/ - OUR SERVER
3. ZERO external network calls
4. Works in any network (firewalled, air-gapped, etc.)

This is the production-ready, truly offline solution.
2026-03-31 23:12:21 +00:00
ifedan-ed
a7dd08c9d1 Add admin dashboard for developmental milestones management
Features:
- Admin can add, edit, and delete developmental milestones via dashboard
- Milestones stored in PostgreSQL (developmental_milestones table)
- Client-side loads milestones from API instead of static file
- Import script to migrate existing static data to database
- Organized by age group and domain
- Supports sorting and filtering

Admin UI:
- New section in Admin panel for milestone management
- Filter by age group
- Add/Edit modal with validation
- Delete with confirmation
- Auto-complete for age groups and domains

API Endpoints:
- GET /api/milestones-data - Public endpoint for authenticated users
- GET /api/admin/milestones - List all milestones (admin only)
- GET /api/admin/milestones/meta - Get age groups and domains
- POST /api/admin/milestones - Create milestone
- PUT /api/admin/milestones/:id - Update milestone
- DELETE /api/admin/milestones/:id - Delete milestone
- POST /api/admin/milestones/bulk-import - Bulk import

Usage:
1. Run import script: node scripts/import-milestones.js
2. Access Admin dashboard → Developmental Milestones section
3. Add/Edit/Delete milestones as needed
2026-03-31 20:55:41 +00:00
ifedan-ed
9d817cd9f5 v18: Self-hosted Browser Whisper (zero CDN dependencies)
BREAKING FIX: Browser Whisper now fully self-contained

Previous issue:
- Loaded transformers.js from cdn.jsdelivr.net
- Downloaded models from cdn-lfs.huggingface.co
- Failed in corporate/clinical networks with firewall
- Stuck at "Initializing..." with no progress

Solution:
- Bundle transformers.js library (~876KB)
- Bundle Whisper tiny.en model (~42MB)
- Serve everything from local server
- Works in ANY network environment

Changes:
- whisperWorker.js: Load transformers from /models/ instead of CDN
- Dockerfile: Download models during Docker build
- Add download script for local dev
- Add comprehensive setup documentation

Docker image size: +~42MB (one-time cost, runtime benefit)

Tested: Works on unrestricted and firewalled networks
2026-03-31 20:02:11 +00:00