Media Assets Security Architecture
This document specifies the storage classification, access control policies, and serving architecture for uploaded media assets across ScannerSky Django.
1. Threat Model & Classification
ScannerSky processes various categories of binary media. Because certain media contain sensitive personal identifiable information (PII) and biometric data, media assets are strictly divided into Protected (Staff-Only) and Public classifications:
| Classification | File Path Pattern | Description & Privacy Impact | Authorization Requirement |
|---|---|---|---|
| Protected (High Risk) | media/signatures/*media/persons/*_signature.* | Handwritten/pad electronic signatures (biometric and legal signature PII). | is_authenticated and (is_superuser or core.view_person_sensitive_media) |
| Protected (High Risk) | media/id_cards/*media/persons/*_id_front.*media/persons/*_id_back.* | Rendered institutional smart ID cards containing full name, emergency contacts, blood type, address, and QR codes. | is_authenticated and (is_superuser or core.view_person_sensitive_media) |
| Public (Low Risk) | media/profiles/*media/persons/*_profile.* | Student and employee portrait photos used across public gate scan kiosks and real-time presentation. | Unrestricted / Public |
| Public (Low Risk) | media/id_templates/* | Blank graphical ID card background templates. | Unrestricted / Public |
| Public (Low Risk) | media/syllabi/* | Exported course syllabi PDFs produced for MCP / downloadable links. | Unrestricted / Public |
:::note Static Assets vs Media Assets
Application branding, UI icons, and favicons (/static/img/icon.png, /static/img/logofull.png) are true static assets packaged with the application codebase. They are served directly from /static/ via Nginx / MinIO static storage and are completely decoupled from the /media/ authorization pipeline.
:::
2. Request Flow & Serving Mechanics
graph TD
Client[Client Request: /media/path] --> Route[scannersky/urls.py: protected_media_view]
Route --> Classifier[is_sensitive_media_path?]
Classifier -- Yes (Signatures / ID Cards) --> AuthCheck{is_authenticated & view_person_sensitive_media?}
AuthCheck -- No --> Deny[403 PermissionDenied]
AuthCheck -- Yes --> Streamer
Classifier -- No (Profiles / Templates / Syllabi) --> Streamer
subgraph Serving Tier
Streamer{USE_X_ACCEL_REDIRECT?}
Streamer -- True (Production) --> Nginx[X-Accel-Redirect Header to /protected_media/]
Streamer -- False (Dev/WSGI) --> StaticServe[django.views.static.serve with Private Cache-Control]
end
Development vs Production Offloading
- Development Mode: Served directly via Django's internal static server (
django.views.static.serve) withCache-Control: private, max-age=3600set on protected files to prevent local disk re-reads while keeping test environments simple. - Production Mode (
USE_X_ACCEL_REDIRECT = True):- Django handles sub-millisecond authentication verification.
- On authorization, Django returns an empty
HttpResponsewith theX-Accel-Redirect: /protected_media/...header. - Nginx fulfills the request directly at the kernel level (
sendfile), consuming zero Python worker memory.
3. Nginx Reverse Proxy Configuration Reference
For production deployments, the corresponding Nginx virtual host configuration:
server {
server_name scannersky.example.com;
# Public gateway proxy to Django WSGI / Gunicorn / Uvicorn
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Internal protected media location (cannot be reached directly from external clients)
location /protected_media/ {
internal;
alias /var/www/scannersky/media/;
}
}
4. Future Roadmap & Enhancements
- Signed Kiosk URLs: If profile photos or ID card previews are later gated behind strict authentication, short-lived HMAC signed tokens (
/media/.../?token=...&expires=...) can be generated by/api/scan/for gate display screens without persistent sessions. - Per-Object Permissions: Future expansion may limit signature inspection to users with explicit
core.view_personor departmental scope.