Monitoring: - docker-compose.monitoring.yml — opt-in Loki + Grafana stack - Loki config with 6-year retention (HIPAA compliant) - Grafana auto-provisioned with Loki datasource + PedScribe dashboard (login activity, failed logins, clinical actions, API calls, log viewer) - Logger ships to Loki in parallel with PostgreSQL (fire-and-forget) - Labels: app=pedscribe, type=audit|api_call|access, category, action Usage: docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d Grafana at localhost:3003 (admin/pedscribe) Notifications: - ntfy push support (src/utils/notify.js) - Notifications on: login, password change, registration - Self-hosted, no Firebase dependency Mobile: - Biometric auth on app launch (Face ID/Touch ID/fingerprint) - PIN/password fallback, auto-prompt, skip option
70 lines
2 KiB
JSON
70 lines
2 KiB
JSON
{
|
|
"dashboard": {
|
|
"title": "PedScribe Audit & Usage",
|
|
"uid": "pedscribe-audit",
|
|
"timezone": "browser",
|
|
"refresh": "30s",
|
|
"time": { "from": "now-24h", "to": "now" },
|
|
"panels": [
|
|
{
|
|
"title": "Login Activity",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
|
|
"targets": [{
|
|
"datasource": "Loki",
|
|
"expr": "count_over_time({app=\"pedscribe\", category=\"auth\"} |= \"login\" [5m])",
|
|
"legendFormat": "Logins"
|
|
}]
|
|
},
|
|
{
|
|
"title": "Failed Logins",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 },
|
|
"targets": [{
|
|
"datasource": "Loki",
|
|
"expr": "count_over_time({app=\"pedscribe\", category=\"auth\"} |= \"login_failed\" [5m])",
|
|
"legendFormat": "Failed"
|
|
}]
|
|
},
|
|
{
|
|
"title": "Clinical Actions",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
|
|
"targets": [{
|
|
"datasource": "Loki",
|
|
"expr": "count_over_time({app=\"pedscribe\", category=\"clinical\"} [5m])",
|
|
"legendFormat": "Clinical Actions"
|
|
}]
|
|
},
|
|
{
|
|
"title": "API Calls by Model",
|
|
"type": "timeseries",
|
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 },
|
|
"targets": [{
|
|
"datasource": "Loki",
|
|
"expr": "count_over_time({app=\"pedscribe\", type=\"api_call\"} [5m])",
|
|
"legendFormat": "API Calls"
|
|
}]
|
|
},
|
|
{
|
|
"title": "Recent Audit Events",
|
|
"type": "logs",
|
|
"gridPos": { "h": 10, "w": 24, "x": 0, "y": 16 },
|
|
"targets": [{
|
|
"datasource": "Loki",
|
|
"expr": "{app=\"pedscribe\"}",
|
|
"maxLines": 100
|
|
}],
|
|
"options": {
|
|
"showTime": true,
|
|
"showLabels": true,
|
|
"showCommonLabels": false,
|
|
"wrapLogMessage": true,
|
|
"prettifyLogMessage": false,
|
|
"enableLogDetails": true,
|
|
"sortOrder": "Descending"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|