All checks were successful
Gitea Actions Demo / build-and-push (push) Successful in 24s
- Added tracking events for tasks, penalties, and rewards with timestamps. - Created new TinyDB table for tracking records to maintain audit history. - Developed backend API for querying tracking events with filters and pagination. - Implemented logging for tracking events with per-user rotating log files. - Added unit tests for tracking event creation, querying, and anonymization. - Deferred frontend changes for future implementation. - Established acceptance criteria and documentation for the tracking feature. feat: Introduce account deletion scheduler - Implemented a scheduler to delete accounts marked for deletion after a configurable threshold. - Added new fields to the User model to manage deletion status and attempts. - Created admin API endpoints for managing deletion thresholds and viewing the deletion queue. - Integrated error handling and logging for the deletion process. - Developed unit tests for the deletion scheduler and related API endpoints. - Documented the deletion process and acceptance criteria.
4.9 KiB
4.9 KiB
Tracking Feature Implementation Summary
✅ Implementation Complete
All acceptance criteria from feat-tracking.md have been implemented and tested.
📦 What Was Delivered
Backend
-
Data Model (tracking_event.py)
TrackingEventdataclass with full type safety- Factory method
create_event()for server-side timestamp generation - Delta invariant validation (
delta == points_after - points_before)
-
Database Layer (tracking.py)
- New TinyDB table:
tracking_events.json - Helper functions:
insert_tracking_event,get_tracking_events_by_child,get_tracking_events_by_user,anonymize_tracking_events_for_user - Offset-based pagination with sorting by
occurred_at(desc)
- New TinyDB table:
-
Audit Logging (tracking_logger.py)
- Per-user rotating file handlers (
logs/tracking_user_<user_id>.log) - 10MB max file size, 5 backups
- Structured log format with all event metadata
- Per-user rotating file handlers (
-
API Integration (child_api.py)
- Tracking added to:
POST /child/<id>/trigger-task→ action:activatedPOST /child/<id>/request-reward→ action:requestedPOST /child/<id>/trigger-reward→ action:redeemedPOST /child/<id>/cancel-request-reward→ action:cancelled
- Tracking added to:
-
Admin API (tracking_api.py)
GET /admin/trackingwith filters:child_id(required if nouser_id)user_id(admin only)entity_type(task|reward|penalty)action(activated|requested|redeemed|cancelled)limit(default 50, max 500)offset(default 0)
- Returns total count for future pagination UI
-
SSE Events (event_types.py, tracking_event_created.py)
- New event type:
TRACKING_EVENT_CREATED - Payload:
tracking_event_id,child_id,entity_type,action - Emitted on every tracking event creation
- New event type:
Frontend
-
TypeScript Models (models.ts)
TrackingEventinterface (1:1 parity with Python)- Type aliases:
EntityType,ActionType TrackingEventCreatedPayloadfor SSE events
-
API Helpers (api.ts)
getTrackingEventsForChild()function with all filter params
-
SSE Registration
- Event type registered in type union
- Ready for future UI components
Tests
Backend Unit Tests (test_tracking.py):
- ✅ Tracking event creation with factory method
- ✅ Delta invariant validation
- ✅ Insert and query tracking events
- ✅ Filtering by
entity_typeandaction - ✅ Offset-based pagination
- ✅ User anonymization on deletion
- ✅ Points change correctness (positive/negative/zero delta)
- ✅ No points change for request/cancel actions
🔑 Key Design Decisions
- Append-only tracking table - No deletions, only anonymization on user deletion
- Server timestamps -
occurred_atalways uses server time (UTC) to avoid client clock drift - Separate logging - Per-user audit logs independent of database
- Offset pagination - Simpler than cursors, sufficient for expected scale
- No UI (yet) - API/models/SSE only; UI deferred to future phase
🚀 Usage Examples
Backend: Create a tracking event
from models.tracking_event import TrackingEvent
from db.tracking import insert_tracking_event
from utils.tracking_logger import log_tracking_event
event = TrackingEvent.create_event(
user_id='user123',
child_id='child456',
entity_type='task',
entity_id='task789',
action='activated',
points_before=50,
points_after=60,
metadata={'task_name': 'Homework'}
)
insert_tracking_event(event)
log_tracking_event(event)
Frontend: Query tracking events
import { getTrackingEventsForChild } from "@/common/api";
const res = await getTrackingEventsForChild({
childId: "child456",
entityType: "task",
limit: 20,
offset: 0,
});
const data = await res.json();
// { tracking_events: [...], total: 42, count: 20, limit: 20, offset: 0 }
📋 Migration Notes
- New database file:
backend/data/db/tracking_events.jsonwill be created automatically on first tracking event. - New log directory:
backend/logs/tracking_user_<user_id>.logfiles will be created per user. - No breaking changes to existing APIs or data models.
🔮 Future Enhancements (Not in This Phase)
- Admin/parent UI for viewing tracking history
- Badges and certificates based on tracking data
- Analytics and reporting dashboards
- Export tracking data (CSV, JSON)
- Time-based filters (date range queries)