Story-1392: Staff Grant Detail Contract
This walkthrough documents the producer-side contract for
GET /admin/staff/{user_id}/grants. The endpoint gives the
admin staff-detail page the staff member's active support grants,
recent grant history, and the exact firms where the staffer may create
a self-grant.
What Changed
-
Added
StaffGrantDetailResponsewithactiveGrants,recentGrantHistory, andeligibleGrantFirms. -
Added a companion route at
GET /admin/staff/{user_id}/grants, leaving the existingGET /admin/staff/{user_id}list-item shape unchanged. - Eligibility mirrors the create gate exactly: the staffer must be the firm's CSM owner or a permanent support-roster member.
-
If both relationships are true, the response returns one eligible
firm row with
relationshipset tocsm.
Contract Shape
The staff grant detail response is camelCase on the wire:
{
"staffUserId": "...",
"activeGrants": [
{
"id": "...",
"firmId": "...",
"firmRef": "FIRM-00042",
"firmName": "Example LLP",
"staffUserId": "...",
"reason": "Customer support investigation",
"grantedAt": "2026-06-18T00:00:00Z",
"createdAt": "2026-06-18T00:00:00Z",
"expiresAt": "2026-06-25T00:00:00Z",
"grantedByUserId": "...",
"revokedAt": null,
"revokedReason": null,
"revokedByUserId": null,
"isActive": true
}
],
"recentGrantHistory": [],
"eligibleGrantFirms": [
{
"firmId": "...",
"firmRef": "FIRM-00042",
"name": "Example LLP",
"plan": "growth",
"relationship": "csm"
}
]
}
Verification
-
Route coverage validates the full
StaffGrantDetailResponseDTO round-trip. - Tests cover CSM-only, roster-only, both, and neither eligibility.
- Tests cover active, revoked, and expired grants in the response.
- A real admin request for a newly seeded staffer with no grants and no eligible firms returns empty arrays instead of an error.
-
openapi/admin-api.jsonwas regenerated for the new producer contract.
Consumer Impact
pramaan-admin must regenerate src/gen/,
call GET /admin/staff/{user_id}/grants from the staff
detail page, delete the adaptListItemToDetail stub for
grant arrays, and use eligibleGrantFirms as the grant
modal firm picker source.