pediatric-ai-scribe-v3/src/routes/refine.js
Daniel 020e831b3c v6.2: Session management, password change, audit logging, refine context, UI fixes
Security:
- Add session management: users can view/revoke active sessions in Settings
- Add password change in Settings (requires current password, HIBP check)
- Force logout all sessions on password reset
- Fix logout to destroy server-side session (was only clearing cookie)
- Add trust proxy for correct client IP in rate limiting and audit logs
- Add CORS support for multiple domains (CORS_ORIGINS env var)
- Add HIBP breach check endpoint and inline warnings on password fields

Audit logging:
- Add audit logging to all 24 PHI-handling endpoints across 13 route files
- Covers: generation, transcription, TTS, refine, encounters, documents, Nextcloud
- All fire-and-forget (no response delay)

AI improvements:
- Refine now includes original source material (transcript, notes, labs)
  so AI can reference the full input when modifying output
- Add correction tracking (trackAIOutput) to sick visit and well visit tabs
- Fix sickvisit missing from encounter save noteIdMap

UI fixes:
- Non-blocking busy bar for transcription and AI generation (replaces full-screen overlay)
- Fix encounter recording: hide record button during recording (was showing two stop buttons)
- Fix ROS/PE "All WNL" stacking duplicate event handlers; add Clear buttons
- Enlarge AI instructions textarea in Learning Hub CMS

Domain:
- Primary domain now app.pedshub.com, with scribe.pedshub.com and peds.danvics.com as CORS origins
2026-04-08 20:27:45 +02:00

82 lines
3.1 KiB
JavaScript

// ============================================================
// REFINE ROUTES — Modify, shorten, clarify any document
// ============================================================
var express = require('express');
var router = express.Router();
var { callAI } = require('../utils/ai');
var PROMPTS = require('../utils/prompts');
var { authMiddleware } = require('../middleware/auth');
var logger = require('../utils/logger');
// Refine/modify document with instructions
router.post('/refine', authMiddleware, async function(req, res) {
try {
var currentDocument = req.body.currentDocument;
var instructions = req.body.instructions;
var sourceContext = req.body.sourceContext;
var model = req.body.model;
if (!currentDocument) return res.status(400).json({ error: 'No document to refine' });
if (!instructions) return res.status(400).json({ error: 'No instructions provided' });
var userContent = '';
if (sourceContext) {
userContent += 'ORIGINAL SOURCE MATERIAL (reference this for any data lookups — labs, notes, history):\n' + sourceContext + '\n\n';
}
userContent += 'CURRENT DOCUMENT (modify this based on user instructions):\n' + currentDocument + '\n\nUSER INSTRUCTIONS:\n' + instructions;
var result = await callAI([
{ role: 'system', content: PROMPTS.refine },
{ role: 'user', content: userContent }
], { model: model, maxTokens: 6000 });
res.json({ success: true, refined: result.content, model: result.model });
logger.audit(req.user.id, 'refine_document', 'Refined document', req, { category: 'clinical' });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Shorten document
router.post('/shorten', authMiddleware, async function(req, res) {
try {
var document = req.body.document;
var model = req.body.model;
if (!document) return res.status(400).json({ error: 'No document' });
var result = await callAI([
{ role: 'system', content: PROMPTS.shortenDocument },
{ role: 'user', content: document }
], { model: model });
res.json({ success: true, shortened: result.content, model: result.model });
logger.audit(req.user.id, 'shorten_document', 'Shortened document', req, { category: 'clinical' });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Ask AI for clarification questions
router.post('/clarify', authMiddleware, async function(req, res) {
try {
var document = req.body.document;
var context = req.body.context;
var model = req.body.model;
if (!document) return res.status(400).json({ error: 'No document' });
var result = await callAI([
{ role: 'system', content: PROMPTS.askClarification },
{ role: 'user', content: 'Document type: ' + (context || 'medical document') + '\n\nDOCUMENT:\n' + document }
], { model: model, maxTokens: 1000 });
res.json({ success: true, questions: result.content, model: result.model });
logger.audit(req.user.id, 'clarify_document', 'Generated clarification questions', req, { category: 'clinical' });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
module.exports = router;