fix(04-rbac): revise plans based on checker feedback

This commit is contained in:
2026-03-24 13:46:03 -06:00
parent bf4adf0b21
commit 2aecc5c787
3 changed files with 60 additions and 27 deletions

View File

@@ -16,6 +16,7 @@ files_modified:
- migrations/versions/006_rbac_roles.py
- tests/unit/test_rbac_guards.py
- tests/unit/test_invitations.py
- tests/unit/test_portal_auth.py
autonomous: true
requirements:
- RBAC-01
@@ -54,6 +55,9 @@ must_haves:
- path: "tests/unit/test_invitations.py"
provides: "Unit tests for HMAC token and invitation flow"
min_lines: 40
- path: "tests/unit/test_portal_auth.py"
provides: "Unit tests for auth/verify endpoint returning role + tenant_ids claims"
min_lines: 30
key_links:
- from: "packages/shared/shared/api/rbac.py"
to: "packages/shared/shared/models/auth.py"
@@ -266,10 +270,11 @@ class AuditEvent(Base): # Reuse for impersonation logging in Plan 03
</task>
<task type="auto" tdd="true">
<name>Task 3: Unit tests for RBAC guards and invitation system</name>
<name>Task 3: Unit tests for RBAC guards, invitation system, and portal auth</name>
<files>
tests/unit/test_rbac_guards.py,
tests/unit/test_invitations.py
tests/unit/test_invitations.py,
tests/unit/test_portal_auth.py
</files>
<behavior>
- test_platform_admin_passes: platform_admin caller gets through require_platform_admin
@@ -285,6 +290,9 @@ class AuditEvent(Base): # Reuse for impersonation logging in Plan 03
- test_invite_accept_creates_user: accepting invite creates PortalUser + UserTenantRole
- test_invite_accept_rejects_expired: expired invitation returns error
- test_invite_resend_updates_token: resend generates new token_hash and extends expires_at
- test_auth_verify_returns_role: auth/verify response contains role field (not is_admin)
- test_auth_verify_returns_tenant_ids: auth/verify response contains tenant_ids list
- test_auth_verify_returns_active_tenant: auth/verify response contains active_tenant_id
</behavior>
<action>
Create `tests/unit/test_rbac_guards.py`:
@@ -309,18 +317,27 @@ class AuditEvent(Base): # Reuse for impersonation logging in Plan 03
- Test invitation acceptance via POST /api/portal/invitations/accept (mock DB session with pending invitation)
- Test resend updates token_hash and extends expires_at
Create `tests/unit/test_portal_auth.py`:
- Test the updated auth/verify endpoint returns role (not is_admin) in the response
- Test auth/verify returns tenant_ids as a list of UUID strings for a user with UserTenantRole memberships
- Test auth/verify returns active_tenant_id as the first tenant ID (or None for users with no memberships)
- Test auth/verify for platform_admin returns all tenant IDs from the tenants table
- Test auth/verify for customer_admin returns only tenant IDs from their UserTenantRole rows
- Mock the DB session with appropriate PortalUser (role field) and UserTenantRole rows
- Use httpx.AsyncClient with the app, following existing test patterns (make_app(session) factory)
Follow existing test patterns: use `make_app(session)` factory from tests/ or direct httpx.AsyncClient with app.
</action>
<verify>
<automated>cd /home/adelorenzo/repos/konstruct && pytest tests/unit/test_rbac_guards.py tests/unit/test_invitations.py -x -v</automated>
<automated>cd /home/adelorenzo/repos/konstruct && pytest tests/unit/test_rbac_guards.py tests/unit/test_invitations.py tests/unit/test_portal_auth.py -x -v</automated>
</verify>
<done>All RBAC guard unit tests pass. All invitation token and API unit tests pass. Coverage includes platform_admin bypass, tenant membership checks, token tampering, and expiry validation.</done>
<done>All RBAC guard unit tests pass. All invitation token and API unit tests pass. All portal auth unit tests pass verifying role + tenant_ids claims. Coverage includes platform_admin bypass, tenant membership checks, token tampering, expiry validation, and auth/verify response shape.</done>
</task>
</tasks>
<verification>
- `pytest tests/unit/test_rbac_guards.py tests/unit/test_invitations.py -x -v` — all pass
- `pytest tests/unit/test_rbac_guards.py tests/unit/test_invitations.py tests/unit/test_portal_auth.py -x -v` — all pass
- `python -c "from shared.models.auth import UserRole; assert len(UserRole) == 3"` — enum has 3 values
- `python -c "from shared.api.rbac import require_platform_admin"` — guard imports clean
- `python -c "from shared.invite_token import generate_invite_token, validate_invite_token"` — token utils import clean
@@ -335,7 +352,7 @@ class AuditEvent(Base): # Reuse for impersonation logging in Plan 03
- HMAC invite tokens generate and validate with 48h TTL
- SMTP email utility exists (sync, for Celery)
- Auth/verify returns role + tenant_ids
- All unit tests pass
- All unit tests pass (including test_portal_auth.py for JWT callback claims)
</success_criteria>
<output>