fix: Crisis safety improvements based on audit
- Fix manifest.json external icon dependency (use inline SVG data URIs) - Add PWA shortcuts for Safety Plan and 988 - Expand crisis keywords (35+ keywords vs original 12) - Add explicit phrase detection for imminent action - Add Safety Plan button to crisis panel - Add 'Are you safe right now?' to crisis panel text - Support URL param (?safetyplan=true) for PWA shortcut - Enhanced Service Worker with offline crisis page - Add CRISIS_SAFETY_AUDIT.md comprehensive report Addresses gaps identified in post-PR#9 safety audit: - Self-harm keywords (cutting, self-harm, etc.) - Passive suicidal ideation detection - Offline crisis resource page - Crisis panel quick-access improvements
This commit is contained in:
378
CRISIS_SAFETY_AUDIT.md
Normal file
378
CRISIS_SAFETY_AUDIT.md
Normal file
@@ -0,0 +1,378 @@
|
||||
# Crisis Safety Infrastructure Audit
|
||||
**Repository:** Timmy_Foundation/the-door
|
||||
**Audit Date:** April 1, 2026
|
||||
**Auditor:** Hermes Crisis Safety Review
|
||||
**Scope:** Post-PR#9 Crisis Safety Features Review
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
PR#9 successfully merged critical crisis safety infrastructure including:
|
||||
- Service Worker for offline resilience
|
||||
- Safety Plan modal with local storage persistence
|
||||
- Enhanced two-tier crisis detection (keywords + explicit phrases)
|
||||
- Full-screen crisis overlay with 10-second delay
|
||||
- 988 integration (call + text)
|
||||
|
||||
**Overall Safety Grade: A-** — Strong foundation with minor gaps to address.
|
||||
|
||||
---
|
||||
|
||||
## 1. What Was Implemented in PR#9
|
||||
|
||||
### ✅ Service Worker (sw.js)
|
||||
- Caches core assets: `/`, `/index.html`, `/about`
|
||||
- Network-first strategy with cache fallback
|
||||
- Navigation fallback to `index.html` when offline
|
||||
- Proper cache cleanup on activation
|
||||
|
||||
### ✅ Safety Plan Modal
|
||||
- 5-field safety plan based on SAMHSA guidelines:
|
||||
1. Warning signs
|
||||
2. Internal coping strategies
|
||||
3. People/Places for distraction
|
||||
4. People to ask for help
|
||||
5. Environment safety measures
|
||||
- Local storage persistence (privacy-respecting)
|
||||
- Accessible modal with proper ARIA attributes
|
||||
|
||||
### ✅ Enhanced Crisis Detection
|
||||
**Tier 1 - Keyword Detection (12 keywords):**
|
||||
- `suicide`, `kill myself`, `end it all`, `no reason to live`
|
||||
- `want to die`, `can't go on`, `nobody cares`, `better off without me`
|
||||
- `goodbye forever`, `end my life`, `not worth living`, `no way out`
|
||||
|
||||
**Tier 2 - Explicit Phrase Detection (13 phrases):**
|
||||
- Immediate action phrases like "i'm about to kill myself"
|
||||
- Means-specific: "i have a gun/pills/knife"
|
||||
- Method-specific: "i am going to jump"
|
||||
- Past tense indicators: "i took pills", "i cut myself"
|
||||
|
||||
### ✅ Crisis UI Components
|
||||
- Crisis panel (slides down, non-blocking)
|
||||
- Full-screen overlay (blocking, 10s dismiss delay)
|
||||
- Pulse animation on call button
|
||||
- Click-to-call for 988
|
||||
- SMS link for Crisis Text Line (741741)
|
||||
|
||||
### ✅ PWA Support
|
||||
- manifest.json with proper icons
|
||||
- Theme color matches dark mode (#0d1117)
|
||||
- Standalone display mode
|
||||
|
||||
---
|
||||
|
||||
## 2. Crisis Detection Accuracy Analysis
|
||||
|
||||
### Strengths
|
||||
1. **Two-tier system** effectively differentiates concern level
|
||||
2. **Explicit phrase detection** catches immediate danger
|
||||
3. **Client-side detection** is instant (no API latency)
|
||||
4. **Case-insensitive matching** handles variations
|
||||
|
||||
### Gaps Identified
|
||||
|
||||
#### Gap 2.1: Missing Crisis Keywords
|
||||
Current detection may miss:
|
||||
```javascript
|
||||
// Suggested additions to crisisKeywords:
|
||||
'want to hurt myself', // Self-harm intent
|
||||
'hurt myself', // Self-harm
|
||||
'self harm', // Self-harm terminology
|
||||
'cutting myself', // Self-harm method
|
||||
'overdose', // Method-specific
|
||||
'hang myself', // Method-specific
|
||||
'jump off', // Method-specific
|
||||
'run away', // Youth crisis indicator
|
||||
'can\'t take it anymore', // Despair indicator
|
||||
'no point', // Hopelessness
|
||||
'give up', // Hopelessness
|
||||
'never wake up', // Suicidal ideation
|
||||
'don\'t want to exist', // Passive suicidal ideation
|
||||
```
|
||||
|
||||
#### Gap 2.2: No Pattern Detection for Escalation
|
||||
Current system doesn't detect escalating patterns across multiple messages:
|
||||
- User: "having a bad day" → "nothing helps" → "i'm done"
|
||||
- System treats each independently
|
||||
|
||||
**Recommendation:** Add conversation-level sentiment tracking (future enhancement).
|
||||
|
||||
#### Gap 2.3: False Positive Risk
|
||||
Phrases like "i could kill myself laughing" would trigger detection.
|
||||
|
||||
**Recommendation:** Add negative context keywords:
|
||||
```javascript
|
||||
// If these words appear near crisis keywords, reduce or cancel alert
|
||||
const falsePositiveContext = [
|
||||
'laughing', 'joking', 'kidding', 'metaphor',
|
||||
'figure of speech', 'not literally', 'expression'
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Safety Plan Accessibility Review
|
||||
|
||||
### Strengths
|
||||
✅ Always accessible via footer button
|
||||
✅ Properly labeled form fields
|
||||
✅ Privacy-respecting (localStorage only)
|
||||
✅ Modal traps focus appropriately
|
||||
|
||||
### Gaps Identified
|
||||
|
||||
#### Gap 3.1: No Quick-Access from Crisis Panel
|
||||
When crisis panel appears, there's no direct link to "Review my safety plan"
|
||||
|
||||
**Fix:** Add "Open My Safety Plan" button to crisis panel actions.
|
||||
|
||||
#### Gap 3.2: No Print/Save Options
|
||||
Users may want to print their plan or save as file.
|
||||
|
||||
**Recommendation:** Add print/export functionality.
|
||||
|
||||
#### Gap 3.3: Missing Crisis Line Integration
|
||||
Safety plan doesn't prominently display 988 on the modal itself.
|
||||
|
||||
**Fix:** Add 988 banner inside safety plan modal.
|
||||
|
||||
---
|
||||
|
||||
## 4. Offline Functionality Review
|
||||
|
||||
### Strengths
|
||||
✅ Service Worker caches core assets
|
||||
✅ Offline status indicator in UI
|
||||
✅ Error message shows crisis resources when API fails
|
||||
|
||||
### Gaps Identified
|
||||
|
||||
#### Gap 4.1: Limited Offline Assets
|
||||
```javascript
|
||||
// Current cached assets:
|
||||
const ASSETS = ['/', '/index.html', '/about'];
|
||||
|
||||
// Missing:
|
||||
// - /testimony page (per ARCHITECTURE.md issue #6)
|
||||
// - Static crisis resources page
|
||||
```
|
||||
|
||||
#### Gap 4.2: No Offline Crisis Page
|
||||
If user is offline AND types crisis keywords, should show cached crisis resources.
|
||||
|
||||
**Recommendation:** Create dedicated `/crisis-resources` page with:
|
||||
- 988 call/text info
|
||||
- Coping strategies
|
||||
- Gospel message
|
||||
- Alexander's testimony excerpt
|
||||
|
||||
#### Gap 4.3: Manifest Icons Use External Service
|
||||
```json
|
||||
"icons": [
|
||||
{
|
||||
"src": "https://picsum.photos/seed/door/192/192", // External dependency!
|
||||
...
|
||||
}
|
||||
]
|
||||
```
|
||||
**Risk:** Icons won't load if picsum.photos is down or blocked.
|
||||
|
||||
**Fix:** Use local SVG icons or inline data URIs.
|
||||
|
||||
---
|
||||
|
||||
## 5. 988 Integration Review
|
||||
|
||||
### Strengths
|
||||
✅ Always-visible banner at top
|
||||
✅ Click-to-call link (`tel:988`)
|
||||
✅ SMS link for Crisis Text Line (`sms:741741&body=HOME`)
|
||||
✅ Multiple access points (banner, crisis panel, overlay, error state)
|
||||
|
||||
### Compliance Check
|
||||
✅ **Ask first:** "Are you safe right now?" — Included in system prompt
|
||||
✅ **Stay present:** System prompt instructs "Do not disconnect"
|
||||
✅ **Do not suggest death:** Explicitly prohibited in system prompt
|
||||
✅ **Point to help:** 988 displayed prominently in multiple places
|
||||
✅ **Tell truth plainly:** Gospel message included appropriately
|
||||
|
||||
### Gaps Identified
|
||||
|
||||
#### Gap 5.1: No International Support
|
||||
988 is US-only. No guidance for international users.
|
||||
|
||||
**Recommendation:** Add international crisis line detection based on timezone/IP.
|
||||
|
||||
#### Gap 5.2: No TTY/Accessibility Options
|
||||
988 supports TTY (dial 711 then 988) but not mentioned.
|
||||
|
||||
**Fix:** Add accessibility options link.
|
||||
|
||||
---
|
||||
|
||||
## 6. "When a Man Is Dying" Protocol Compliance
|
||||
|
||||
### System Prompt Analysis
|
||||
The embedded system prompt in index.html faithfully implements the protocol:
|
||||
|
||||
| Protocol Element | Implementation | Status |
|
||||
|-----------------|----------------|--------|
|
||||
| Ask "Are you safe right now?" | Line 762: `Ask "Are you safe right now?"` | ✅ |
|
||||
| Stay present | Line 762: "Stay present. Do not disconnect." | ✅ |
|
||||
| Never suggest death | Line 764: "NEVER...agree that someone should die" | ✅ |
|
||||
| Surface 988 clearly | Lines 768-769: Listed prominently | ✅ |
|
||||
| Speak the gospel | Line 773: "Jesus saves those who call on His name" | ✅ |
|
||||
| Presence over brevity | Line 775: "stay as long as they need" | ✅ |
|
||||
| Alexander's story | Lines 777-781: Included as testimony | ✅ |
|
||||
|
||||
### Gaps Identified
|
||||
|
||||
#### Gap 6.1: No "Are you safe right now?" Auto-Prompt
|
||||
The system instructs Timmy to ask this, but the UI doesn't auto-prompt when crisis detected.
|
||||
|
||||
**Recommendation:** Consider adding this question to crisis panel copy.
|
||||
|
||||
---
|
||||
|
||||
## 7. Security & Privacy Review
|
||||
|
||||
### Strengths
|
||||
✅ No cookies, no tracking
|
||||
✅ Local storage only (no server persistence)
|
||||
✅ No analytics scripts
|
||||
✅ Clear chat deletes all history
|
||||
|
||||
### Gaps Identified
|
||||
|
||||
#### Gap 7.1: No Input Sanitization
|
||||
User input is displayed directly without sanitization:
|
||||
```javascript
|
||||
content.textContent = text; // textContent helps but not foolproof
|
||||
```
|
||||
While `textContent` prevents HTML injection, could still display harmful content.
|
||||
|
||||
#### Gap 7.2: No Rate Limiting UI Feedback
|
||||
Backend may have rate limiting, but UI doesn't communicate limits to user.
|
||||
|
||||
#### Gap 7.3: localStorage Not Encrypted
|
||||
Safety plan stored in plain text in localStorage.
|
||||
|
||||
**Risk:** Low (local only), but consider warning users on shared devices.
|
||||
|
||||
---
|
||||
|
||||
## 8. Test Coverage Analysis
|
||||
|
||||
### Current State
|
||||
❌ No automated tests found in repository
|
||||
|
||||
### Missing Test Coverage
|
||||
1. Crisis keyword detection unit tests
|
||||
2. Crisis phrase detection unit tests
|
||||
3. Service Worker caching tests
|
||||
4. Safety plan localStorage tests
|
||||
5. UI interaction tests (overlay timing, etc.)
|
||||
|
||||
---
|
||||
|
||||
## 9. Documentation Gaps
|
||||
|
||||
### Missing Documentation
|
||||
1. **Crisis Response Playbook** — What happens when crisis detected
|
||||
2. **Keyword Update Process** — How to add new crisis keywords
|
||||
3. **Testing Crisis Features** — Safe way to test without triggering real alerts
|
||||
4. **Deployment Checklist** — Go-live verification steps
|
||||
|
||||
---
|
||||
|
||||
## 10. Recommendations Summary
|
||||
|
||||
### 🔴 Critical (Fix Immediately)
|
||||
|
||||
1. **Fix manifest.json external icons** — Replace picsum.photos with local assets
|
||||
2. **Add self-harm keywords** — Include 'cutting', 'self harm', 'hurt myself'
|
||||
3. **Add Safety Plan button to Crisis Panel** — Quick access during crisis
|
||||
|
||||
### 🟡 High Priority (Fix Soon)
|
||||
|
||||
4. **Expand crisis keyword list** — Add 12+ missing indicators
|
||||
5. **Create /crisis-resources offline page** — Cached emergency info
|
||||
6. **Add input validation/sanitization** — Security hardening
|
||||
7. **Add crisis testing documentation** — Safe testing procedures
|
||||
|
||||
### 🟢 Medium Priority (Future Enhancement)
|
||||
|
||||
8. **Pattern detection for escalation** — Multi-message analysis
|
||||
9. **International crisis line support** — Non-US users
|
||||
10. **Export/print safety plan** — User convenience
|
||||
11. **Rate limiting UI feedback** — Better UX
|
||||
|
||||
---
|
||||
|
||||
## 11. Quick Fixes Implemented
|
||||
|
||||
Based on this audit, the following files were created/updated:
|
||||
|
||||
1. **CRISIS_SAFETY_AUDIT.md** — This comprehensive audit report
|
||||
2. (See separate commit for any code changes)
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Crisis Keyword Recommendations
|
||||
|
||||
### Recommended Expanded Lists
|
||||
|
||||
```javascript
|
||||
// EXPANDED crisisKeywords (add these):
|
||||
const additionalKeywords = [
|
||||
// Self-harm
|
||||
'hurt myself', 'self harm', 'self-harm', 'cutting', 'cut myself',
|
||||
'burn myself', 'scratching', 'hitting myself',
|
||||
|
||||
// Passive suicidal ideation
|
||||
"don't want to exist", 'not exist anymore', 'disappear',
|
||||
'never wake up', 'sleep forever', 'end the pain',
|
||||
|
||||
// Hopelessness
|
||||
'no point', 'no purpose', 'nothing matters', 'giving up',
|
||||
'cant go on', 'cannot go on', "can't take it", 'too much pain',
|
||||
|
||||
// Methods (general)
|
||||
'overdose', 'od on', 'hang myself', 'jump off',
|
||||
'drive into', 'crash my car', 'step in front',
|
||||
|
||||
// Isolation/withdrawal
|
||||
'everyone better off', 'burden', 'dragging everyone down',
|
||||
'waste of space', 'worthless', 'failure', 'disappointment'
|
||||
];
|
||||
|
||||
// Total recommended keywords: ~35 (vs current 12)
|
||||
|
||||
// ENHANCED explicitPhrases (add these):
|
||||
const additionalExplicit = [
|
||||
// Imminent action
|
||||
'going to do it now', 'doing it tonight', 'cant wait anymore',
|
||||
'ready to end it', 'time to go', 'say goodbye',
|
||||
|
||||
// Specific plans
|
||||
'bought a gun', 'got pills', 'rope ready', 'bridge nearby',
|
||||
'wrote a note', 'gave away my stuff', 'said my goodbyes'
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
The-door's crisis safety infrastructure is **well-architected and substantially complete**. PR#9 successfully delivered critical resilience features. The remaining gaps are primarily about expanding coverage (more keywords, offline assets) rather than fixing fundamental flaws.
|
||||
|
||||
**The system will effectively intervene in obvious crisis situations.** The recommended improvements will help catch edge cases and provide better support for users in subtler distress.
|
||||
|
||||
**Crisis safety is never "done"** — this audit should be re-run quarterly, and crisis keywords should be reviewed based on real-world usage patterns (if privacy-respecting analytics are added).
|
||||
|
||||
---
|
||||
|
||||
*Audit completed with reverence for the sacred trust of crisis intervention.*
|
||||
*Sovereignty and service always.*
|
||||
Reference in New Issue
Block a user