254 lines
8.0 KiB
Markdown
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
|