fix(admin): scope session timeline metrics by tenant#231
Merged
smaramwbc merged 1 commit intoJun 7, 2026
Merged
Conversation
Signed-off-by: skarL007 <marcelomachuca2023@gmail.com>
smaramwbc
approved these changes
Jun 7, 2026
smaramwbc
left a comment
Owner
There was a problem hiding this comment.
Exhaustively reviewed (correctness + security + test-quality, plus an adversarial verification pass that empirically tested pre/post against Postgres) — clean to merge.
- Correct & complete.
episode_countnow derives from the tenant-filteredbasequery instead of a tenant-ignoring subquery, and per-episodeciting_memory_countaddsif tenant_id: ...where(MemoryRow.tenant_id == tenant_id)— closing the cross-tenant metric leak on a shared subject/session id. No fan-out (episode/memory ids are global UUID PKs). - Operator-global view preserved. Both new clauses are gated behind
if tenant_id:, so the no-filter operator path is byte-identical pre/post (verified empirically). No over-scoping regression. - Security pass clean. admin.py + integration test only; single authored commit; no exec/network/secret/obfuscation; no info leak. The third hunk is cosmetic ReceiptRow reformatting.
One non-blocking nit: the test asserts only the tenant-a filtered view — adding the operator-global and tenant-b assertions (as the #229 sibling test does) would guard against a future over-scoping regression. Happy to follow up. Thanks for another tight isolation fix.
— Statewave team
smaramwbc
added a commit
that referenced
this pull request
Jun 7, 2026
… test Follow-up to #231. The session-timeline tenant-scope test asserted only the tenant-a filtered view. Add the operator-global assertion (episode_count==3 and the tenant-a episode cited by both tenants' memories == 2) and the tenant-b filtered view (episode_count==2, citing counts == 0). The global assertion guards against a future over-scoping regression where a tenant filter leaks into the operator path — the behavior #231 preserves. Mirrors the stronger both-tenants pattern in #229's test. Test-only.
smaramwbc
added a commit
that referenced
this pull request
Jun 7, 2026
… test Follow-up to #231. The session-timeline tenant-scope test asserted only the tenant-a filtered view. Add the operator-global assertion (episode_count==3 and the tenant-a episode cited by both tenants' memories == 2) and the tenant-b filtered view (episode_count==2, citing counts == 0). The global assertion guards against a future over-scoping regression where a tenant filter leaks into the operator path — the behavior #231 preserves. Mirrors the stronger both-tenants pattern in #229's test. Test-only.
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.
Summary
/admin/subjects/{subject_id}/sessions/{session_id}/timelineepisode_countto the same base query used for tenant-filtered episode rows.citing_memory_counttotenant_idwhen the timeline request is tenant-filtered.Test plan
python -m ruff check server\api\admin.py tests\integration\test_admin_session_timeline_tenant_scope.pypython -m ruff format --check server\api\admin.py tests\integration\test_admin_session_timeline_tenant_scope.pypython -m py_compile server\api\admin.py tests\integration\test_admin_session_timeline_tenant_scope.pypython -m pytest tests\test_tenant_scoping_invariant.py tests\test_route_limits_invariant.py tests\test_admin_dashboard.py -qSTATEWAVE_EMBEDDING_PROVIDER=stub STATEWAVE_COMPILER_TYPE=heuristic PYTHONUTF8=1 python -m pytest tests -q --ignore=tests/integration --ignore=tests/smoke --ignore=tests/test_admin_subjects.py --ignore=tests/test_admin_clone.py --ignore=tests/test_memory_templates.py --ignore=tests/test_usage.pyLocal integration note
python -m pytest tests\integration\test_admin_session_timeline_tenant_scope.py -qwas attempted, but this Windows environment has no runningstatewave_testPostgres on localhost:5432.docker compose up -d dbwas also attempted, but Docker Desktop's Linux daemon is not available on this machine.