feat: accept tenant slug in team endpoints (tenant_id int vs slug contract mismatch) #87

Closed
opened 2026-03-15 02:22:28 +00:00 by forgejo_admin · 0 comments

Lineage

plan-2026-03-08-tryout-prep → Phase 10 → Phase 10d-1 (Fix integration bugs)
First sub-phase of the integration validation + observability loop.

Repo

forgejo_admin/basketball-api

User Story

As the westside-app frontend
I want to call team endpoints using the tenant slug westside-kings-queens
So that the API contract matches the roster endpoints and the frontend doesn't need to know internal tenant IDs

Context

Playwright E2E validation (2026-03-15) revealed that all team endpoints return 422 Unprocessable Entity when called with tenant_id=westside-kings-queens. The endpoints expect tenant_id: int but the westside-app sends the tenant slug string.

The roster endpoints (/api/roster/{tenant_slug}) use the slug as a path parameter. The team endpoints use tenant_id: int as a query parameter. This contract mismatch means the frontend has no way to call team endpoints without knowing the internal numeric ID.

Fix approach: Change team endpoint tenant_id query parameters to accept either an integer ID or a string slug. Use a helper function that resolves the input to a Tenant object: if the value is numeric, look up by ID; if string, look up by slug. This is backwards-compatible — existing integer callers still work.

File Targets

Files the agent should modify:

  • src/basketball_api/routes/teams.py — change tenant_id: int query params to tenant_id: str on all endpoints that accept it. Add resolution logic: if tenant_id.isdigit() → lookup by ID, else → lookup by slug. Apply to: list teams, create team, team overview, assign players, unassign player.
  • Existing _get_tenant_or_404(db, tenant_id: int) helper — update to accept str | int and resolve accordingly.

Files the agent should NOT touch:

  • src/basketball_api/routes/roster.py — already uses slug, working correctly
  • src/basketball_api/models.py — no schema changes needed
  • Any migration files — no DB changes

Acceptance Criteria

  • GET /api/teams?tenant_id=westside-kings-queens returns 200 with team list
  • GET /api/teams?tenant_id=1 still returns 200 (backwards compatible)
  • GET /api/teams/overview?tenant_id=westside-kings-queens returns 200
  • POST /api/teams with tenant_id: "westside-kings-queens" in body → resolves to correct tenant
  • Invalid slug → 404 (not 422 or 500)
  • All existing team tests pass

Test Expectations

  • Existing 35 team tests pass (they use integer tenant_id — backwards compat)
  • Add 3-5 new tests: slug-based team list, slug-based overview, invalid slug → 404
  • Run command: pytest tests/test_teams.py -v

Constraints

  • Must be backwards compatible — integer tenant_id callers must still work
  • The TeamCreate Pydantic model has tenant_id: int — change to tenant_id: int | str and resolve in the route handler
  • Follow the existing _get_tenant_or_404 pattern
  • Keep it simple — this is a resolution layer, not a refactor

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • project-westside-basketball — Phase 10d-1 (integration validation)
  • Blocks Phase 10d-2 (E2E test suite)
### Lineage `plan-2026-03-08-tryout-prep` → Phase 10 → Phase 10d-1 (Fix integration bugs) First sub-phase of the integration validation + observability loop. ### Repo `forgejo_admin/basketball-api` ### User Story As the westside-app frontend I want to call team endpoints using the tenant slug `westside-kings-queens` So that the API contract matches the roster endpoints and the frontend doesn't need to know internal tenant IDs ### Context Playwright E2E validation (2026-03-15) revealed that all team endpoints return **422 Unprocessable Entity** when called with `tenant_id=westside-kings-queens`. The endpoints expect `tenant_id: int` but the westside-app sends the tenant slug string. The roster endpoints (`/api/roster/{tenant_slug}`) use the slug as a path parameter. The team endpoints use `tenant_id: int` as a query parameter. This contract mismatch means the frontend has no way to call team endpoints without knowing the internal numeric ID. **Fix approach**: Change team endpoint `tenant_id` query parameters to accept **either** an integer ID or a string slug. Use a helper function that resolves the input to a Tenant object: if the value is numeric, look up by ID; if string, look up by slug. This is backwards-compatible — existing integer callers still work. ### File Targets Files the agent should modify: - `src/basketball_api/routes/teams.py` — change `tenant_id: int` query params to `tenant_id: str` on all endpoints that accept it. Add resolution logic: if `tenant_id.isdigit()` → lookup by ID, else → lookup by slug. Apply to: list teams, create team, team overview, assign players, unassign player. - Existing `_get_tenant_or_404(db, tenant_id: int)` helper — update to accept `str | int` and resolve accordingly. Files the agent should NOT touch: - `src/basketball_api/routes/roster.py` — already uses slug, working correctly - `src/basketball_api/models.py` — no schema changes needed - Any migration files — no DB changes ### Acceptance Criteria - [ ] `GET /api/teams?tenant_id=westside-kings-queens` returns 200 with team list - [ ] `GET /api/teams?tenant_id=1` still returns 200 (backwards compatible) - [ ] `GET /api/teams/overview?tenant_id=westside-kings-queens` returns 200 - [ ] `POST /api/teams` with `tenant_id: "westside-kings-queens"` in body → resolves to correct tenant - [ ] Invalid slug → 404 (not 422 or 500) - [ ] All existing team tests pass ### Test Expectations - [ ] Existing 35 team tests pass (they use integer tenant_id — backwards compat) - [ ] Add 3-5 new tests: slug-based team list, slug-based overview, invalid slug → 404 - Run command: `pytest tests/test_teams.py -v` ### Constraints - Must be backwards compatible — integer tenant_id callers must still work - The `TeamCreate` Pydantic model has `tenant_id: int` — change to `tenant_id: int | str` and resolve in the route handler - Follow the existing `_get_tenant_or_404` pattern - Keep it simple — this is a resolution layer, not a refactor ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - `project-westside-basketball` — Phase 10d-1 (integration validation) - Blocks Phase 10d-2 (E2E test suite)
forgejo_admin 2026-03-15 02:29:38 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/basketball-api#87
No description provided.