# 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