Both came out of using the app: the preview works but is all-or-nothing, and
signing in should be possible without a password without replacing it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
CLINICAL_ASSISTANT.md described DeepL as an admin-configurable translation
provider with its own keys and a fallback between providers. There is no
DeepL client in the code: TRANSLATE_PROVIDERS is ['libretranslate'], and an
unrecognised setting silently falls back rather than being rejected — the
first wording I wrote claimed a rejection that does not happen either.
TODO.md now names clinical-storage-milvus and
personal-assistant-storage-milvus, and records the MinIO audio-backup work
as finished.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
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
- adminMilestones was reached only because adminConfig is mounted on
/api/admin ahead of it and guards the whole path. adminMiddleware checks
req.user.role and nothing else, so it failed closed (403) rather than
open — but on mount order, not intent. It now states the requirement,
with a test covering all four admin routers.
- TODO.md records the whole audit: what was verified working (live
transcription round trip, voice mode wiring), what was fixed, the two
advisories that are unreachable and why, and the CI/CD and Kubernetes
work worth doing before scaling out.
Security review found nothing else exploitable: parameterised SQL
throughout (the one interpolated table name is allowlisted), CORS refuses
to start open in production, JWT_SECRET refuses to start unset in
production, rate limits on /api and each auth route, a real CSP, and no
secrets in the repo.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
Records what is genuinely outstanding and the non-obvious infrastructure facts
found while fixing it, so the next session does not rediscover them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjVc5oaAaYFNbZGLeJp6TX