Story 2669: Matter team HTTP endpoints

This walkthrough covers F3 only: exposing the Story-2664 matter roster, staffing, removal, and lead-transfer service operations over the app HTTP API. It also adds the missing vacant-lead self-claim path for already staffed editors.

1. HTTP surface

RoutePermissionService operationResponse
GET /app/matters/{matter_id}/roster matters:read MatterService.matter_roster MatterRosterView
POST /app/matters/{matter_id}/team matters:write MatterService.add_to_team dispatches to staff_editor or staff_member by active target firm role. MatterRosterView
DELETE /app/matters/{matter_id}/team/{user_id} matters:write MatterService.remove_from_team MatterRosterView
PUT /app/matters/{matter_id}/lead matters:write MatterService.assign_or_claim_lead MatterRosterView

2. Roster visibility

The roster endpoint is not a broad firm-editor list view. A firm admin may read the roster. Any other caller must already have a matter_assignments row on the matter; otherwise the endpoint returns the same not-found envelope used by the neighbouring matter routes.

3. Lead assignment and self-claim

The router does not decide whether a request is an admin transfer, current-lead transfer, or vacant-lead claim. That branch lives in MatterService.assign_or_claim_lead.
if actor is firm_admin or current lead:
    transfer_lead(target active editor)
elif lead is vacant and target is current user and current user is a staffed active editor:
    promote current user to lead_counsel
else:
    reject with pramaan.matter.lead_assign_forbidden

The claim path never lets an unstaffed editor laterally claim a matter. It also keeps the existing partial-unique-lead and IntegrityError vacancy repair pattern used by lead transfer.

4. Contract and audit hooks

MatterTeamAddRequest and MatterLeadAssignRequest use the existing ApiRequestModel camelCase aliasing convention. make openapi adds the new paths and schemas to openapi/app-api.json, and make gen-permissions adds the permission map entries.

The mutating endpoints are classified in the audit route coverage manifest. Actual team additions and lead assignments emit matter.assigned; removals emit a matter.edited roster diff.

Verification covers MT-15 roster reads, MT-16 vacant-lead disclosure, MT-20 lead transfer, MT-23 admin recovery from vacancy, MT-29 staffed-editor self-claim, OpenAPI regeneration, permission-map regeneration, and the full test suite.