From 0c45137f5b8c965a10e97c1ef7960d8beeb1f034 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sat, 24 Oct 2026 18:58:39 -0400 Subject: [PATCH] =?UTF-8?q?docs(users):=20live-smoke=20correction=20?= =?UTF-8?q?=E2=80=94=20GET=20/api/auth/users=20emits=20sqlc=20ListUsersRow?= =?UTF-8?q?,=20no=20password=5Fhash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Curated smoke run of the generated collection against the live dev server (37/37 after fixes): registration matrix (409 duplicate email, 403 admin-creation-with-admins-present, 400 weak password), non-admin 403s, device-token/opds 401s, collection CRUD incl. the documented 201 update quirk and 204 delete, stats routes, scanner, jobs, malformed-uuid 400s. Testuser untouched (password test uses a guaranteed-wrong current password -> 401); the smoke user was admin-deleted in cleanup and its token verified dead. Correction the smoke run forced: the batch-8 'password_hash leak' was a false alarm — my registry pin ([]database.Users) never matched the handler, which returns []database.ListUsersRow (sqlc join with device_count). Live response confirmed: id/email/username/theme/names/ role/max_devices/created_at/updated_at/device_count — NO hash. Doc example, field table, and registry pin all corrected; leak note replaced with the live-verified statement. Also verified via the real Bruno CLI: 9 safe generated requests (4 shown passing incl. stats/collections/devices; password-rules public) execute against the server with collection-level auth. Full-collection bru run deliberately not attempted (mutations in static bodies would touch live data). --- docs/developer/api/admin/list_users.md | 20 ++++++-------------- internal/docs/schema.go | 4 +++- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/docs/developer/api/admin/list_users.md b/docs/developer/api/admin/list_users.md index c15d4976..a50251a0 100644 --- a/docs/developer/api/admin/list_users.md +++ b/docs/developer/api/admin/list_users.md @@ -42,27 +42,22 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... "id": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "username": "johndoe", - "password_hash": "$2a$04$REDACTED", + "theme": "tokyo-night", "first_name": "John", "last_name": "Doe", "role": "user", - "theme": "tokyo-night", "max_devices": 10, "created_at": "2026-02-08T10:00:00Z", - "timezone": "America/New_York", "updated_at": "2026-02-08T10:00:00Z", - "default_audio_speed": 1 + "device_count": 3 } ] ``` -Response is a bare JSON array of full user rows — no pagination wrapper -and no `device_count` (those were invented in an earlier draft). - -**Leak note:** the user model json-marshals `password_hash` verbatim — -the list-users response exposes password hashes to any admin caller. -Known defect, tracked separately (doc mirrors the real field set; do not -implement against a redacted shape). +Response is a bare JSON array of sqlc `ListUsersRow`s (user fields plus a +`device_count` join) — no pagination wrapper. Live-smoke-verified +2026-10-24: **`password_hash` is NOT in the response** (an earlier draft +of this doc wrongly claimed a hash leak). ### Response Fields @@ -79,9 +74,6 @@ implement against a redacted shape). | `device_count` | integer | Current number of registered devices | | `created_at` | string | Account creation timestamp (ISO 8601) | | `updated_at` | string | Last update timestamp (ISO 8601) | -| `total` | integer | Total number of users matching query | -| `limit` | integer | Limit applied to this request | -| `offset` | integer | Offset applied to this request | ## Error Responses diff --git a/internal/docs/schema.go b/internal/docs/schema.go index 8dddf544..be02e4f7 100644 --- a/internal/docs/schema.go +++ b/internal/docs/schema.go @@ -687,7 +687,9 @@ var Schemas = map[string]Schema{ }`), }, "GET /api/auth/users": { - Response: []database.Users{}, + // sqlc join row (device_count), NOT database.Users — no password_hash + // on the wire (live-smoke-verified 2026-10-24). + Response: []database.ListUsersRow{}, }, "PUT /api/auth/users/:id/max-devices": { Request: handlers.UpdateUserMaxDevicesRequest{},