π Evidence Collection MVP¶
Scope: Simple evidence storage and retrieval for compliance Status: Basic file upload with metadata tagging Target Users: IT managers uploading policies, screenshots, certificates Not: Complex document management system
Customer Need¶
Auditors ask: "Show me evidence of [specific control]" Boards ask: "How do we know our controls are working?" Managers need: "Where did I put that firewall config screenshot?"
MVP Answer: Tagged file storage with easy retrieval
Core MVP Features¶
1. Smart Upload Interface¶
interface Evidence {
id: string
fileName: string
fileType: 'pdf' | 'image' | 'document' | 'spreadsheet'
fileSize: number
uploadedBy: User
uploadedAt: Date
// Smart tagging
tags: {
frameworks: string[] // ['E8', 'ACSC', 'S180', 'Privacy']
controls: string[] // ['MFA', 'Patching']
evidenceType: string // 'Policy', 'Screenshot', 'Report'
period?: string // '2024-Q1'
}
// Metadata
description?: string
validFrom?: Date
validUntil?: Date
// Relationships
linkedTo: {
tasks?: string[]
assessments?: string[]
vendors?: string[]
}
}
2. Drag & Drop Upload¶
<DropZone
on:drop={handleFiles}
accept=".pdf,.png,.jpg,.docx,.xlsx"
maxSize="50MB"
>
<div class="upload-prompt">
<Upload size={48} />
<p>Drop evidence files here</p>
<p class="hint">PDFs, images, documents up to 50MB</p>
</div>
</DropZone>
<!-- Auto-tag based on filename -->
<script>
function autoTag(filename) {
// "MFA-Policy-2024.pdf" β tags: ['MFA', 'Policy', '2024']
// "essential-eight-assessment.xlsx" β tags: ['E8', 'Assessment']
return smartParse(filename);
}
</script>
3. Quick Retrieval¶
Find Evidence By:
- Framework: 'Show all E8 evidence'
- Control: 'Show MFA evidence'
- Date: 'Evidence from last audit'
- Type: 'All policies'
- Expiry: 'Expiring in 30 days'
One-Click Actions:
- Preview (in-browser)
- Download
- Share link (time-limited)
- Add to report
Storage Architecture¶
File Organization¶
{tenant-id}/
/evidence/
/2024/
/01/
/{uuid}-MFA-Policy.pdf
/{uuid}-Firewall-Config.png
/02/
/{uuid}-Pen-Test-Report.pdf
Metadata Storage¶
CREATE TABLE evidence (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
file_name TEXT NOT NULL,
file_path TEXT NOT NULL,
file_type TEXT NOT NULL,
file_size BIGINT NOT NULL,
-- Searchable tags
framework_tags TEXT[],
control_tags TEXT[],
evidence_type TEXT,
period TEXT,
-- Metadata
description TEXT,
valid_from DATE,
valid_until DATE,
-- Audit trail
uploaded_by UUID REFERENCES users(id),
uploaded_at TIMESTAMPTZ DEFAULT NOW(),
last_accessed_at TIMESTAMPTZ,
access_count INTEGER DEFAULT 0,
tenant_id UUID NOT NULL,
-- Full text search
search_vector tsvector GENERATED ALWAYS AS (
to_tsvector('english',
coalesce(file_name, '') || ' ' ||
coalesce(description, '') || ' ' ||
array_to_string(framework_tags, ' ') || ' ' ||
array_to_string(control_tags, ' ')
)
) STORED
);
CREATE INDEX idx_evidence_search ON evidence USING GIN(search_vector);
CREATE INDEX idx_evidence_tags ON evidence USING GIN(framework_tags, control_tags);
CREATE INDEX idx_evidence_expiry ON evidence(valid_until) WHERE valid_until IS NOT NULL;
Smart Features¶
1. Auto-Tagging¶
const TAG_PATTERNS = {
frameworks: {
'E8|essential.?eight': ['E8'],
ACSC: ['ACSC'],
'S180|section.?180': ['S180'],
'Privacy|Privacy.?Act': ['Privacy'],
},
controls: {
'MFA|multi.?factor': ['MFA'],
patch: ['Patching'],
backup: ['Backup'],
firewall: ['Network Security'],
},
types: {
'policy|policies': 'Policy',
'screenshot|screen': 'Screenshot',
report: 'Report',
'certificate|cert': 'Certificate',
},
}
function autoTagEvidence(filename: string, content?: string) {
const tags = {
frameworks: [],
controls: [],
evidenceType: 'Document',
}
// Check filename and content against patterns
for (const [pattern, tag] of Object.entries(TAG_PATTERNS.frameworks)) {
if (new RegExp(pattern, 'i').test(filename + ' ' + (content || ''))) {
tags.frameworks.push(...tag)
}
}
return tags
}
2. Evidence Dashboard¶
ββββββββββββββββββββββββββββββββββββββββββββ
β Evidence Library β
ββββββββββββββββββββββββββββββββββββββββββββ€
β Total Files: 127 β
β This Month: 12 β β
β Expiring Soon: 3 β οΈ β
β β
β By Framework: β
β [E8: 45] [ACSC: 23] [S180: 15] [Privacy: 10] β
β β
β Recent Uploads: β
β β’ MFA-Config-Screenshot.png (2 min ago) β
β β’ Patch-Schedule-2024.xlsx (1 hour ago) β
ββββββββββββββββββββββββββββββββββββββββββββ
3. Quick Evidence for Auditors¶
// Generate evidence package for specific request
export async function createAuditPackage(request: AuditRequest) {
const evidence = await db.evidence.findMany({
where: {
framework_tags: { contains: request.framework },
control_tags: { overlap: request.controls },
valid_until: { gte: new Date() },
},
orderBy: { uploaded_at: 'desc' },
})
// Create ZIP with organized folders
const zip = new JSZip()
for (const item of evidence) {
const folder = `${item.framework_tags[0]}/${item.control_tags[0]}/`
zip.file(folder + item.file_name, await getFile(item.file_path))
}
return zip.generateAsync({ type: 'blob' })
}
Integration Points¶
WhatsApp Upload¶
// Handle evidence via WhatsApp
Bot: "Please send the MFA policy document"
User: [Sends PDF]
Bot: "Received 'MFA-Policy-Jan.pdf' (2.3MB)
Tagged: E8, MFA, Policy
Stored in Evidence Library β"
Task Linking¶
// When completing a task
interface TaskCompletion {
taskId: string
evidence: string[] // Evidence IDs
notes: string
}
// Auto-prompt for evidence
if (task.requires_evidence && !completion.evidence.length) {
prompt('This task requires evidence. Upload or select existing.')
}
Report Generation¶
// Include evidence links in reports
function generateBoardReport(period: string) {
const sections = {
compliance: getComplianceScores(period),
evidence: {
total: getEvidenceCount(period),
byFramework: getEvidenceByFramework(period),
expiring: getExpiringEvidence(30),
recentUploads: getRecentEvidence(10),
},
}
// Include direct links to evidence
return renderReport(sections)
}
What We're NOT Building (MVP)¶
- Document versioning
- OCR or content extraction
- Advanced metadata schemas
- Workflow approvals
- Document editing
- Complex folder hierarchies
- Integration with DMS systems
- Automated evidence gathering
Success Metrics¶
Usage Metrics¶
- Files uploaded per customer: 50-200
- Average upload time: < 30 seconds
- Retrieval time: < 2 seconds
- Evidence used in reports: > 80%
Quality Metrics¶
- Auto-tag accuracy: > 70%
- Evidence found on first search: > 90%
- Expired evidence caught: 100%
Implementation Timeline¶
- Week 1: File upload + basic storage
- Week 2: Tagging system + search
- Week 3: Evidence dashboard
- Week 4: Audit package generation
- Week 5: Integrations (WhatsApp, tasks)
Future Enhancements (Post-MVP)¶
- AI-powered content extraction
- Evidence quality scoring
- Automated evidence requests
- Version control
- Digital signatures
- Chain of custody tracking
Related Documents: