2de76d52e60a71540d3dbf78e60023108ad67126
CR-019 / wave 11. Adds GET /api/usage/export, reusing _usage_query()'s
scoped filters (from/to/project_id/username/tool) and the same
require_user_manager gate as /api/usage/summary. Two modes:
- raw (default): real usernames, for internal admin use.
- sanitize=true: usernames replaced with an HMAC-SHA256 pseudonym
(keyed with auth.SECRET_KEY, 16 hex chars, 'u_' prefix) so the file
can be fed into PowerBI or another external reporting tool without
carrying real identities. HMAC chosen over a plain hash since the
username space is small enough to brute-force a bare digest.
Both modes emit at, username, project_id, tool, event as columns and
deliberately omit the detail JSON column in both modes to avoid an
identity leak riding along inside free-form detail data. Response is
returned with a Content-Disposition: attachment header and a filename
that encodes mode + date.
Verified locally against a throwaway SQLite DB with two seeded users
and four seeded UsageEvent rows:
- raw export contains the real usernames and matches the summary
endpoint's event_count for the same session state
- sanitized export contains no real username or email anywhere in
the file body, across two independently-issued export calls
- the same real user maps to the same pseudonym both within one
export and across the two separate export calls
- raw and sanitized rows line up 1:1 on at/tool/event for the same
filter set
- the tool= filter narrows the export the same way it narrows the
summary
- a plain project_user is refused with 403; an unauthenticated
request is refused with 401
- full smoke test (27/27) and seed_demo.py both still pass
Description
No description provided
Languages
Python
49.3%
JavaScript
32.6%
CSS
8.9%
HTML
8.7%
Shell
0.4%