fix(admin-costs): list a user's deleted conversations in the cost drill-down - #1127
Merged
Merged
Conversation
…ll-down A soft delete flips `status` and drops the sidebar GSI keys, but the session's `C#` cost rows and its share of the user's period total survive it. The per-user conversation list dropped those tombstones, so the audit could not account for the spend it was built to explain: one prod user showed a single $3.77 conversation against $20.32 of September cost. Fleet-wide, 183 of 5,440 September-active sessions (3.4%) are deleted and carry $58 of $817. The storage reader gains `include_deleted` (default off, so callers that list what the user can still open are unchanged); the admin service asks for tombstones, normalises legacy `deleted` rows to `status="deleted"`, and reports `deletedSessionCount` / `deletedSessionCost` on the response. The SPA badges deleted rows and appends "N deleted ($X still counted in the total)" to the summary line. Profile and anatomy still resolve for a deleted session because `SessionLookupIndex` keys are kept on the tombstone. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A soft delete flips
statusand drops the sidebar GSI keys, but the session'sC#cost rows and its share of the user's period total survive it. The per-user conversation list (GET /admin/costs/users/{id}/sessions) dropped those tombstones, so the audit could not account for the spend it was built to explain.Found during the 2026-09-15 prod cost audit: one top-5 September user showed a single $3.77 conversation against $20.32 of period cost. Fleet-wide, 183 of 5,440 September-active sessions (3.4%) are deleted and carry $58 of $817.
What
get_user_session_diagnostics(..., include_deleted=False)— default unchanged, so callers that list what the user can still open are unaffected. The shared_query_user_session_rowsbody takes the same flag.deletedrows (no status flip) tostatus="deleted", and reportsdeletedSessionCount/deletedSessionCostonUserSessionsResponse. Deleted rows keep theirshareOfUserPeriod, because they still take that share.deletedbadge on the row (with a title explaining that its cost survives the delete) andN deleted ($X still counted in the total)on the summary line.GSI_PK/GSI_SKon the tombstone and only removes theGSI4sidebar keys.Content-free by construction: the deleted row goes through the same
SESSION_ROW_PROJECTION+strip_contentpath (test assertstitleis absent on the tombstone).Tests
tests/costs/test_content_free_projections.py: default excludes;include_deleted=Truelists the tombstone withdeleted/statusand notitle.tests/apis/app_api/admin/costs/test_user_sessions_service.py: deleted rows listed and flagged, legacy tombstones normalised, count/cost rollups, zero case.user-conversations.component.spec.ts: summary line and flagged rows.tests/costs+tests/apis/app_api/admin/costs. SPA spec: 6 passed;tsc --noEmitclean.🤖 Generated with Claude Code