inou/CLAUDE.md

254 lines
8.0 KiB
Markdown

# inou
Medical imaging platform with AI-powered health data exploration via MCP integration.
## Design Documentation
- **API Design (Jan 2026)**: `docs/api-design-2026-01.md` — token auth, REST endpoints, progressive disclosure, thumbnails, anatomy analysis
## Architecture
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Portal │ │ API │ │ MCP Bridge │
│ (Go/HTML) │ │ (Go) │ │ (Go) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────┬───────┴───────────────────┘
┌──────┴──────┐
│ lib │
│ (shared Go) │
└──────┬──────┘
┌──────┴──────┐
│ SQLite │
│ (encrypted)│
└─────────────┘
```
## Code Locations
| Component | Path | Purpose |
|-----------|------|---------|
| lib | `~/dev/inou/lib/` | Shared: crypto, db, types, translations |
| Portal | `~/dev/inou/portal/` | Web UI, DICOM import, genome processing |
| API | `~/dev/inou/api/` | REST API for LLM access |
| Viewer | `~/dev/inou/viewer/` | DICOM viewer (Electron) |
| MCP Client | `~/dev/inou/mcp-client/` | Claude Desktop bridge |
| Doc Processor | `~/dev/inou/doc-processor/` | PDF extraction tool |
| Docs | `~/dev/inou/docs/` | Design documentation |
| Deployed | `/tank/inou/` | Runtime on both staging & prod |
## Environments
| Environment | Server | URL | Purpose |
|-------------|--------|-----|---------|
| **Production** | 192.168.100.2 | https://inou.com | Live users |
| **Staging** | 192.168.1.253 | https://dev.inou.com | Development/testing |
Production is on an isolated VLAN (192.168.100.0/24, VLAN 10) with firewall rules restricting access.
## Server Access
```bash
ssh johan@192.168.1.253 # Staging
ssh johan@192.168.100.2 # Production
```
## Database
**SQLite** with encrypted fields. Single file at `/tank/inou/data/inou.db`.
### ⛔ CRITICAL: Database Access Rules
**ALL database operations MUST go through `lib/db_queries.go` functions. NO EXCEPTIONS.**
Allowed functions (defined in db_queries.go):
- `Save(table, struct)` — INSERT/UPDATE
- `Load(table, id, struct)` — SELECT by primary key
- `Query(sql, args, &slice)` — SELECT with custom queries
- `Delete(table, pkCol, id)` — DELETE by primary key
- `Count(sql, args...)` — SELECT COUNT(*)
**FORBIDDEN (requires Johan's express consent):**
- Any use of `db.Exec()`, `db.Query()`, `db.QueryRow()` outside db_queries.go
- Any use of `lib.DB()` anywhere
- Any modifications to `lib/db_queries.go`
- Any new database wrapper functions
- Any direct SQL execution
**Before making ANY database-related changes:**
1. ASK Johan for permission
2. Explain what you need and why
3. Wait for explicit approval
**Verification:** Run `make check-db` to verify no direct DB access exists.
This check runs automatically on deploy.
Key tables:
- `dossiers` — user profiles (everyone is a dossier)
- `entries` — all health data (imaging, labs, genome, documents, etc.)
- `dossier_access` — who can access whom
- `audit` — activity log
### Querying Encrypted Data
**IMPORTANT:** Do NOT write Python/Go scripts to decrypt database fields. Use the `decrypt` tool:
```bash
# Raw mode - decrypts inline
sqlite3 /tank/inou/data/inou.db "SELECT * FROM entries LIMIT 5" | /tank/inou/bin/decrypt
# JSON mode - pretty output
sqlite3 -json /tank/inou/data/inou.db "SELECT * FROM entries LIMIT 5" | /tank/inou/bin/decrypt -json
# Combine with grep
sqlite3 /tank/inou/data/inou.db "SELECT * FROM dossiers" | /tank/inou/bin/decrypt | grep -i sophia
```
The tool automatically detects and decrypts base64-encoded encrypted fields while leaving IDs and other plain fields unchanged. Rebuild with `make decrypt` if needed.
## Categories (lib/types.go)
Integer enums (iota), 27 total. Key ones:
| Int | Name | Notes |
|-----|------|-------|
| 1 | imaging | slice, series, study (Type differentiates) |
| 2 | document | PDFs, reports |
| 3 | lab | lab results |
| 4 | genome | variants, tiers (Type differentiates) |
| 5 | upload | pending processing |
Translations in `portal/lang/*.yaml` (15 languages).
## API Endpoints (Current)
> Note: Being redesigned. See `docs/api-design-2026-01.md` for new design.
Current endpoints:
- `GET /api/dossiers` — list accessible dossiers
- `GET /api/studies?dossier=X` — list imaging studies
- `GET /api/series?dossier=X&study=Y` — list series
- `GET /api/slices?dossier=X&series=Y` — list slices
- `GET /image/{id}?token=X` — fetch image
- `GET /api/genome?dossier=X` — query variants
- `GET /api/entries` — generic entry CRUD
## Deploy
### Staging (default)
```bash
make deploy
```
Deploys to **staging** (192.168.1.253 / dev.inou.com). Use for development and testing.
### Release to Production
```bash
make deploy-prod
```
Deploys to **production** (192.168.100.2 / inou.com). Use when ready to release.
**"Release to prod"** = `make deploy-prod`
### What Deploy Does
Both commands:
1. Run `check-db` (blocks if violations found)
2. Build all binaries (FIPS 140-3 compliant)
3. Stop services on target
4. Copy binaries, templates, static, lang files
5. Start services
6. Show status
### Typical Workflow
```bash
# 1. Develop and test
make deploy # Deploy to staging
# Test at https://dev.inou.com
# 2. When ready for production
make deploy-prod # Release to prod
# Live at https://inou.com
```
## Testing
```bash
make test # Run integration tests (services must be running)
make check-db # Verify no direct DB access (runs automatically on deploy)
```
### Integration Tests (`make test`)
Runs 18 tests covering the full stack:
| Category | Tests |
|----------|-------|
| Service Health | Portal HTTPS, API HTTPS, internal ports |
| Login Flow | Login page, send verification code |
| Authenticated Routes | Dashboard, add/view/edit dossier |
| Dossier CRUD | Create dossier, verify via API, cleanup |
| API Data Access | List dossiers/studies/series/slices |
| Image Fetch | Fetch DICOM slice |
### DB Access Check (`make check-db`)
Scans core codebase for forbidden direct database access:
- `lib.DB()` usage
- `db.Exec/Query/QueryRow` outside db_queries.go/db_schema.go
- Deprecated wrappers (DBExec, DBInsert, etc.)
Runs automatically before every deploy. Blocks deployment if violations found.
### MCP Bridge (Mac)
```bash
~/dev/inou/build-mac.sh
```
Version in `build-mac.sh` and `viewer/main.go`. Current: **1.2.0**
## Test Dossiers
- **Sophia** — brain MRI, spine MRI, CT, X-rays (May 2022)
- **Johan** — genome data, labs
- **Alena** — genome data, labs
## URLs
**Production:**
- Portal: https://inou.com
- API: https://inou.com/api/*
- API Docs: https://inou.com/api/docs
**Staging:**
- Portal: https://dev.inou.com
- API: https://dev.inou.com/api/*
## Key Design Decisions
1. **No accounts table** — everyone is a dossier (for virality)
2. **Encrypted fields** — all PII encrypted at rest via `lib.CryptoEncrypt`
3. **Categories as integers** — scalable, translated at API boundary
4. **Type field** — differentiates within category (slice/series/study all CategoryImaging)
5. **parent_id** — hierarchy navigation, not category
6. **SQLite** — simple, single file, handles the scale
## File Editing
**Native (on Linux server):** Use standard tools — `sed`, Edit tool, etc. all work fine.
**Remote (from Mac via SSH):** Use `claude-edit` to avoid quote escaping issues:
```bash
cat /tmp/edit.json | ssh johan@192.168.1.253 "~/bin/claude-edit"
```
## Known Limitations
- Large X-rays (2836x2336+) fail via MCP fetch
- See `~/dev/inou/TODO.md` for roadmap