6.0 KiB
admin — platform config, holidays, audit, support alerts
Client seam
client/src/services/admin/·USE_ADMIN_MOCK = true(mock is primary) · 14 server ops Last verified: 2026-07-30 against commitd3ec723and swagger.v1.json (2026-07-29).
The ops console's cross-cutting reads and writes. Domain-specific admin surfaces live with their domain — verification admin in verification.md, refunds in refunds.md, payouts in payouts.md, catalog in catalog.md, geo in geography.md, partner centers in partner-center.md, the ticket queue in tickets.md.
Every endpoint here is [Authorize(ConstantPolicies.DynamicPermission)] + sensitive rate limit
(20/min), except the three platform_config/holidays/audit/support_alerts controllers, which
carry the dynamic-permission policy without the sensitive limit — they fall to the 100/min global limiter.
Endpoints
| Method | Path | Verdict |
|---|---|---|
| GET | /api/v1/platform_config/get_platform_configs |
wired · paginated |
| POST | /api/v1/platform_config/update_platform_config |
wired |
| GET | /api/v1/platform_config/get_config_change_history |
wired · paginated |
| GET | /api/v1/holidays/get_holidays |
wired · paginated |
| POST | /api/v1/holidays/upsert_holiday |
wired |
| POST | /api/v1/holidays/delete_holiday |
unwired — no real client caller; the console offers no delete |
| GET | /api/v1/audit/get_audit_trail |
wired · paginated |
| GET | /api/v1/support_alerts/get_support_alerts |
wired · paginated |
| POST | /api/v1/support_alerts/assign_support_alert |
wired |
| POST | /api/v1/support_alerts/resolve_support_alert |
wired |
| GET | /api/v1/admin_cancellation_policies/list |
unwired — the tier table is read through refunds.md's policy preview instead |
| POST | /api/v1/admin_cancellation_policies/upsert |
unwired — no console screen edits tiers |
| POST | /api/v1/admin_search/rebuild_index |
unwired — an ops one-shot, no UI |
| POST | /api/v1/admin_booking_requests/expire |
unwired — an ops one-shot; the scheduler does this unattended |
Phantom — 5
The client's real clientApi.ts calls five routes the server does not expose. Both groups are
deliberately written real-shaped so flipping the seam is one line once they ship.
| Client call | REQ | Note |
|---|---|---|
GET /api/v1/admin_roles/list_roles |
REQ-031 | Deferred in refinement-phase-3. The admin sub-role vocabulary and phone-OTP admins are seeded, not managed |
POST /api/v1/admin_roles/grant_role |
REQ-031 | |
POST /api/v1/admin_roles/revoke_role |
REQ-031 | |
GET /api/v1/admin_users/search |
REQ-061 — never filed | Backs UserPicker/NursePicker |
POST /api/v1/admin_users/lookup |
REQ-061 — never filed | Batch id→label resolve for AuditLogRow |
REQ-061 does not exist in the ledger.
ui-phase-11-report.mdrecords "REQ-061…064 appended", but only 062/063/064 were. Ten live client files cite REQ-061 for the admin user directory. Phase 4 must file it rather than assume it is tracked.
Two live drifts
1. The client sends page_size; these endpoints declare PageSize. admin/apis/clientApi.ts's
pageQuery() builds page + page_size "per b1 api-conventions". Model binding is case-insensitive,
not separator-insensitive, so page_size does not bind to PageSize — every admin list would
silently fall back to the server's default page size. Invisible today because the mock is primary; it
becomes a real defect the moment USE_ADMIN_MOCK flips. See
../api-contract.md.
2. updatedAt/updatedBy and the audit filters are on the wire. REQ-029 (config audit fields) and
REQ-030 (actorId/action/from/to filters on audit/get_audit_trail) were both delivered in
refinement-phase-3. admin/constants.ts still gives them as reasons the mock is primary. The only
remaining reason is REQ-031 + REQ-061.
Shape rules the JSON does not express
- Platform config is rows read at compute time, never hardcoded, and a rate change is never retroactive — the effective rate is snapshotted onto the row when the amount is computed.
platform_fee_rateandvat_rateare rates in[0, 1)— the console validates the closed-open interval before writing (RATE_CONFIG_KEYSinadmin/constants.ts). The canonical values are0.15fee /0.10VAT (refinement-phase-3).- The audit trail's
changedFieldsJsonis a string containing JSON, not an object:{"Field": {"old": …, "new": …}}. The client parses it defensively and yieldsnullon malformed input. POST update_platform_configand the holiday/alert writes go through self-committing facades that callSaveChangeson the shared scoped context — they run after the handler's ownCommitAsync.- Holidays drive payout date shifting: the server resolves a bank-closure-safe payout date from this calendar and the client never computes one.
Enums
| Vocabulary | Values |
|---|---|
ConfigDataType |
string int decimal bool json |
AuditAction |
created updated deleted |
HolidayType |
official religious national |
SupportAlertType |
low_rating evv_no_show evv_location_mismatch verification_expired shared_sim payment_anomaly fraud_signal nurse_clawback emergency |
SupportAlertSeverity |
low medium high |
SupportAlertStatus |
open assigned resolved |
AdminRole (phantom surface) |
super_admin admin support finance moderation |
DirectoryUserRole (phantom surface) |
customer nurse admin partner |
The last two describe the REQ-031/REQ-061 shapes and are not on the wire.
Open REQs
| REQ | Status | Effect |
|---|---|---|
| REQ-031 | deferred | No RBAC console. Admin roles are seeded |
| REQ-061 | never filed | No admin user directory. AuditLogRow shows #id instead of a name |