S1: Reading a member's KYC record is not logged, though opening their ID document is. Decision D612. No migration. Found by #1165's audit (area 7, kycAdminGet and adminGetProfile).
What is true on main
- Opening the ID document is logged.
GET /api/kyc/admin/:userId/document writes kyc_document_access to activity_logs on every view (cloudflare-worker/src/routes/kyc.ts), with the actor hashed.
- Reading the record is not.
GET /api/kyc/admin/:userId returns the record and logs nothing. The record holds legal name, date of birth, nationality, address, ID type and number, and phone.
- The queue. The admin KYC queue (
/admin?tab=kyc) reads rows that already carry the same kyc_data. Check whether that read is logged.
- Partner profiles.
GET /api/profiling/admin/:email (routes/profiling.ts) returns a partner profile's EIN and onboarding transcript, unlogged.
The work
- Log each read of identity data the way
kyc_document_access is logged: the actor hashed with hashEmail, the member's id, and no field values. The actions:
kyc_record_access, for the record;
kyc_queue_access, for a queue read: one row per read, with the count, not one per member;
partner_profile_access, for the profile read.
- Trim the queue. If the queue's rows carry full
kyc_data only to fill the review window, return them without the identity fields, and let the window read the record (now logged). Say in D612 which you did and why.
- D612 records what is logged, that values never reach the log, and the queue change.
Files this task owns
cloudflare-worker/src/routes/kyc.ts
cloudflare-worker/src/routes/profiling.ts (the admin read only)
- the KYC review window in
frontend/src/pages/AdminPage.jsx, only if step 2 changes what it reads
- new tests
documentation/architecture/decisions/D612.md
Do not build masking in the review windows. Its design is requested on #1165 (area 7, item 6).
Done when
- Tests cover:
- each read writes one log row, with the actor hashed and no identity value in
details;
- a 404 logs nothing;
- the queue's shape after step 2.
- Every new assertion is mutation-checked.
Generated by Claude Code
S1: Reading a member's KYC record is not logged, though opening their ID document is. Decision D612. No migration. Found by #1165's audit (area 7,
kycAdminGetandadminGetProfile).What is true on
mainGET /api/kyc/admin/:userId/documentwriteskyc_document_accesstoactivity_logson every view (cloudflare-worker/src/routes/kyc.ts), with the actor hashed.GET /api/kyc/admin/:userIdreturns the record and logs nothing. The record holds legal name, date of birth, nationality, address, ID type and number, and phone./admin?tab=kyc) reads rows that already carry the samekyc_data. Check whether that read is logged.GET /api/profiling/admin/:email(routes/profiling.ts) returns a partner profile's EIN and onboarding transcript, unlogged.The work
kyc_document_accessis logged: the actor hashed withhashEmail, the member's id, and no field values. The actions:kyc_record_access, for the record;kyc_queue_access, for a queue read: one row per read, with the count, not one per member;partner_profile_access, for the profile read.kyc_dataonly to fill the review window, return them without the identity fields, and let the window read the record (now logged). Say in D612 which you did and why.Files this task owns
cloudflare-worker/src/routes/kyc.tscloudflare-worker/src/routes/profiling.ts(the admin read only)frontend/src/pages/AdminPage.jsx, only if step 2 changes what it readsdocumentation/architecture/decisions/D612.mdDo not build masking in the review windows. Its design is requested on #1165 (area 7, item 6).
Done when
details;Generated by Claude Code