Problem
Every repository over BaseRepository inherits get, get_all, delete and count, none of which carry a tenant predicate. On a table that is scoped to a user or a workspace, await repo.get(file_id) reads across every tenant, and it reads like the obvious way to fetch a row.
Nothing calls them that way today. The repositories over tenant-scoped tables (FileRepository, ApiKeyRepository, BudgetRepository, ScopedBudgetRepository) each define their own scoped lookups and nothing under src/gateway or tests reaches for the inherited ones. So this is a footgun rather than a defect: the next scoped lookup someone adds has a shorter unscoped path sitting beside it.
Proposal
Options, in rough order of cost:
- Say it in
repositories/base_repository.py: the generic accessors carry no tenant predicate, and a repository over a scoped table defines its own lookups.
- Have the boundary check refuse a call to the inherited accessors from a service over a table with a tenant column.
- Split the base so a repository opts into the generic accessors rather than inheriting them.
Raised by the review of #1483.
Problem
Every repository over
BaseRepositoryinheritsget,get_all,deleteandcount, none of which carry a tenant predicate. On a table that is scoped to a user or a workspace,await repo.get(file_id)reads across every tenant, and it reads like the obvious way to fetch a row.Nothing calls them that way today. The repositories over tenant-scoped tables (
FileRepository,ApiKeyRepository,BudgetRepository,ScopedBudgetRepository) each define their own scoped lookups and nothing undersrc/gatewayortestsreaches for the inherited ones. So this is a footgun rather than a defect: the next scoped lookup someone adds has a shorter unscoped path sitting beside it.Proposal
Options, in rough order of cost:
repositories/base_repository.py: the generic accessors carry no tenant predicate, and a repository over a scoped table defines its own lookups.Raised by the review of #1483.