14 KiB
Raspberry Pi Time Tracker — Software Requirements Document (SRD)
Version: 1.0 Date: 2025-08-15 Owner: (to be assigned)
1. Purpose & Scope
This SRD defines requirements for a Python application that primarily runs on a Raspberry Pi (RPI) using Docker, with a web-based frontend. The application tracks time across multiple projects with two tracking modes: manual entry and automatic timers that persist even if the browser is closed. The system supports per-user tracking with simple username-only login (no passwords) and provides project overviews, reporting, and per-entry annotations. No external REST API is required.
In Scope
- Project management (name, client, brief description, billing information)
- Per-user time tracking
- Manual time entry (start/end date & time + project)
- Automatic timers that continue running server-side after browser close
- Project-level overviews of time spent
- Ability to add extra information (notes/metadata) per time entry
- Web-based UI (sleek, modern, and user-friendly)
- Execution on Raspberry Pi via Docker
- Local data storage and backups
Out of Scope (for v1)
- Public internet exposure (LAN only)
- External integrations (e.g., third-party invoicing, calendars)
- Advanced permissions/roles beyond simple user identification
- Mobile apps (web frontend should be responsive)
- External REST API endpoints
2. Stakeholders & Users
- End Users: Team members who log time per project.
- Project Managers / Admins: Configure projects, view summaries, export reports.
- IT/Ops: Deploy and maintain the Dockerized application on RPI.
3. Definitions & Glossary
- Automatic Timer: A server-side, long-lived timer associated with a user and project that continues running even if the browser is closed.
- Entry Notes/Metadata: Additional text fields or tags recorded with each time entry.
- Billing Information: Basic fields such as billing rate, billable flag, PO/Cost center, or invoicing reference stored on the project.
4. System Overview
A Python backend (Flask recommended) runs inside Docker on a Raspberry Pi. The frontend is a server-rendered web UI with light interactive components and optional WebSocket events for live timers. Data persists locally (SQLite by default) with optional scheduled backups.
5. Functional Requirements
5.1 Authentication & User Identity
-
Username-only Login:
- Users enter a username to start a session; no password.
- If username does not exist, offer to create it (admin-configurable setting).
- Persist session via secure cookies.
-
Access Model:
- All logged-in users can create and edit their own time entries.
- Admin users can manage projects, view all reports, and edit any entry.
- Admin assignment via config or first user bootstrap.
5.2 Project Management
-
Create/Read/Update/Archive Projects with fields:
- Project Name (required)
- Client (required)
- Brief Description (optional)
- Billing Information (see 5.2.2)
- Status: Active/Archived
-
Billing Information Fields (configurable subset):
- Billable (Yes/No)
- Hourly Rate (currency-aware)
- Billing Reference (e.g., PO number)
- Default Time Rounding (e.g., 1/5/15 minutes) (optional)
5.3 Manual Time Entry
-
Create Manual Entry:
- Required: Project, Start DateTime, End DateTime
- Optional: Notes/Description (free text), Tags
- Validation: End must be after Start; no overlaps check (configurable) with warning.
-
Edit/Delete Entry: Users can edit or delete their own entries; Admins can edit any.
-
Bulk Operations: Optional bulk edit for tags or project reassignment.
5.4 Automatic Timer Tracking
- Start Timer: User selects project and clicks Start.
- Server-Side Persistence: Timer continues running on the server even if the browser closes, device sleeps, or network drops.
- Stop Timer: User clicks Stop from any browser session or device; server finalizes entry (start->stop).
- Resilience: If the RPI restarts, active timers are restored using last known start time and a flag indicating “active”.
- Single Active Timer per User: Enforced; starting a new timer stops the previous one (configurable).
- Idle/AFK (optional v1.1): After N minutes of inactivity, prompt on next visit to confirm whether to subtract idle time.
5.5 Time Entry Annotations & Metadata
- Notes Field: Rich text (plain text in v1, markdown in v1.1) per entry.
- Tags: Freeform comma-separated tags; auto-suggest from existing tags.
- Edit History (optional): Keep non-destructive audit trail for edits.
5.6 Reporting & Overview
-
Project Overview:
- Total time spent, grouped by user and by time period (day/week/month).
- Filters: date range, user, tags, billable/non-billable.
- Summaries: total hours, billable hours, estimated cost (rate × hours).
-
User Overview:
- Personal dashboard of own entries and totals.
-
Entry List & Detail:
- Paginated list with search, sort by date/project/duration.
-
Exports:
- CSV export for entries and summaries.
5.7 Notifications & Feedback
- Inline validations, toasts for success/errors.
- Live timer display (mm:ss) with WebSocket/SSE updates.
5.8 Administration
- User list (usernames), role assignment (User/Admin).
- Project archival/unarchive.
- Configuration page (see 6.4) with authentication mode, rounding rules, timezone, currency.
6. Non-Functional Requirements
6.1 Platform & Runtime
- Target Hardware: Raspberry Pi 4 (2GB+) recommended.
- OS: Raspberry Pi OS (64-bit) or compatible Linux.
- Containerization: Docker + docker-compose.
- Python: 3.11+.
6.2 Performance
- Support 10–25 concurrent users on LAN with sub-200 ms page actions.
- Timer accuracy within ±1 second over 24 hours.
6.3 Reliability & Resilience
- Automatic restart with
restart: unless-stoppedin Compose. - Graceful shutdown; in-flight timers persisted.
- Periodic health checks and liveness endpoints (internal only).
6.4 Configurability
.env/config UI for: timezone (default Europe/Brussels), currency, default rounding, allow self-register, single-active-timer, idle timeout, export delimiter.
6.5 Security
- LAN-only by default; bind to private IP.
- Reverse proxy optional (Caddy/nginx) for TLS on LAN.
- Username-only login; display clear banner that this is an internal tool.
- CSRF protection disabled for simplified development; secure cookies; session timeout.
- Role-based checks server-side.
6.6 Privacy & Data Retention
- Store minimal PII (username only).
- Retain entries indefinitely unless purged. Admin-configurable retention and backup.
6.7 Localization & Timezones
- System default timezone configurable; all storage in UTC; UI displays local time.
- Handle DST transitions; prevent overlapping/invalid times via UI validation.
6.8 Accessibility
- WCAG 2.1 AA-aligned basics: keyboard navigation, color-contrast, focus states.
7. Architecture & Design
7.1 High-Level Components
- Web App (Flask): Server-rendered templates (Jinja2) + HTMX/Alpine.js for interactivity.
- Background Scheduler: APScheduler (or asyncio task) for periodic jobs (backups, health checks).
- Real-Time Layer: WebSocket or Server-Sent Events for live timer updates.
- Storage: SQLite with WAL mode; upgrade path to PostgreSQL.
- Reverse Proxy (optional): Caddy/nginx container for TLS and static asset caching.
7.2 Data Model (Initial Schema)
users
- id (PK)
- username (unique, required)
- role (enum: user, admin)
- created_at
projects
- id (PK)
- name (required)
- client (required)
- description (text)
- billable (bool)
- hourly_rate (decimal, nullable)
- billing_ref (text, nullable)
- status (enum: active, archived)
- created_at, updated_at
time_entries
- id (PK)
- user_id (FK → users)
- project_id (FK → projects)
- start_utc (datetime)
- end_utc (datetime, nullable when active)
- duration_seconds (int, computed on finalize)
- notes (text)
- tags (text)
- source (enum: manual, auto)
- edited_at
settings
- id (singleton)
- timezone, currency, rounding_minutes, single_active_timer, allow_self_register, idle_timeout_minutes
Indexes on (user_id, start_utc), (project_id, start_utc), and active entries (end_utc IS NULL).
7.3 Timer Persistence Logic
- On Start: create
time_entriesrow withend_utc=NULLandsource=auto. - Heartbeat optional; not required for persistence.
- On Stop: set
end_utc, computeduration_secondsapplying rounding rules. - On Server Restart: query all
end_utc IS NULLand treat as still running sincestart_utc.
7.4 UI/UX Guidelines
-
Clean, modern layout with responsive design.
-
Primary views:
- Dashboard: Active timer status, quick Start/Stop, recent entries.
- Projects: List, filter, create/edit, archive.
- Log Time: Manual entry form.
- Reports: Project and user overviews with filters and CSV export.
- Admin: Users, settings.
-
Components: sticky header timer, toasts, modal dialogs, date/time picker, tag chips.
8. Deployment & Operations
8.1 Docker Compose (concept)
app(Flask + Gunicorn)db(optional Postgres; otherwise SQLite volume inapp)proxy(optional Caddy/nginx)- Volumes for
/data(DB, exports, backups).
8.2 Environment Variables
TZ,CURRENCY,ROUNDING_MINUTES,ALLOW_SELF_REGISTER,SINGLE_ACTIVE_TIMER,IDLE_TIMEOUT_MINUTES,ADMIN_USERNAMES.
8.3 Backup & Restore
- Nightly SQLite copy to
/backups/YYYY-MM-DD/with retention policy. - Manual on-demand export (zip: DB + CSVs of key tables).
8.4 Monitoring
- Health endpoint
/_health(no auth) for local check. - Logs to stdout; optional file rotation.
9. Security Considerations
- Username-only login is weak; mitigate by LAN isolation, optional reverse proxy auth, and kiosk usage.
- CSRF protection disabled; use SameSite cookies; disable framing.
- Rate-limit login attempts by IP to prevent session abuse.
10. Compliance & Legal
- Internal tool; ensure local employment/time-tracking rules if used formally (outside v1 scope).
11. Acceptance Criteria (Sample)
- Users can create projects with client and billing fields.
- Users can log manual entries with start & end times and notes.
- Users can start a timer, close the browser, reopen, and see the timer still running.
- Only one active timer per user (by default).
- Project overview shows total hours per user for a chosen date range.
- CSV export contains correct rows and computed durations.
- System restarts do not lose active timers or historical entries.
- Admin can archive a project; archived projects cannot be chosen for new entries.
- UI renders well on desktop and mobile and passes basic keyboard navigation.
12. Test Cases (Illustrative)
- TC-01: Create project with required fields → Project listed as Active.
- TC-02: Manual entry with end before start → Validation error displayed.
- TC-03: Start timer, close browser, wait 2 minutes, reopen, stop → Duration ≥ 120s.
- TC-04: Start timer A, then start timer B → Timer A auto-stops (if configured).
- TC-05: Edit entry notes and tags → Changes persist and appear in reports.
- TC-06: Archive project, attempt to log time → Not selectable in new entry form.
- TC-07: CSV export for project/date range → Matches on-screen totals.
- TC-08: RPI reboot → Active timers restored, dashboard reflects running state.
- TC-09: CSRF protection disabled - no CSRF validation required.
13. UI Wireframe Descriptions (Textual)
- Login: Username input, “Continue” button, disclaimer about internal use.
- Dashboard: Header with current user + active timer (project name, elapsed). Large Start/Stop button, quick project selector, recent entries table with inline edit.
- Projects: Card list with name, client, billable badge, actions (Edit, Archive).
- Log Time: Form with project dropdown, start/end pickers, notes, tags.
- Reports: Filters row (date range, user, project, tags), totals cards, table, export button.
- Admin: Users list with role toggles, settings form.
14. Future Enhancements (Backlog)
- Idle detection and retroactive adjustments.
- Mobile PWA installability and offline caching for UI.
- Calendar and Kanban views; week grid editor.
- Rate cards by client; multi-currency.
- LDAP/SSO or reverse-proxy auth (e.g., Authelia) for stronger security.
- REST API (if needed) or WebDAV/ICS export.
- PDF report templates and invoice drafts.
15. Constraints & Assumptions
- LAN-only deployment; minimal threat model.
- No external REST API required.
- SQLite is sufficient for initial scale; PostgreSQL available if needed.
16. Appendix: Example docker-compose.yml (Skeleton)
services:
app:
image: timetracker:latest
build: .
environment:
- TZ=Europe/Brussels
- ROUNDING_MINUTES=1
- SINGLE_ACTIVE_TIMER=true
- ALLOW_SELF_REGISTER=true
- ADMIN_USERNAMES=admin
ports:
- "8080:8080"
volumes:
- app_data:/data
restart: unless-stopped
# Optional reverse proxy (TLS on LAN)
proxy:
image: caddy:latest
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
ports:
- "80:80"
- "443:443"
depends_on:
- app
restart: unless-stopped
volumes:
app_data:
caddy_data:
caddy_config:
17. Appendix: Data Dictionary (Selected Fields)
- projects.hourly_rate: Decimal(9,2), nullable; interpreted in
settings.currency. - time_entries.tags: CSV string; UI presents chips; stored raw for simplicity.
- time_entries.duration_seconds: Calculated as
round_to(duration, rounding_minutes)when finalized.
End of Document