Auth guards vary by endpoint — Create, Update, and Delete require an admin or benefit-provider OIDC token. Get and List accept any authenticated actor; app users (mobile JWT) see only active benefits, while admins see all.
Overview
A benefit is a specific offering — a free consultation or a health insurance policy — provided by a Benefit Provider. Benefits carry abenefit_type enum and a benefit_details JSONB block whose variant must match the type.
Responses always include provider_name via a JOIN — callers never need a separate provider lookup.
Benefit Types
Type and details must be consistent at create time — a mismatch returns
BE_503. (update_benefit does not re-validate this consistency.)
benefit_details is a serde-tagged enum. The discriminator key is benefit_type and its value is the SCREAMING_SNAKE_CASE variant name (CONSULTATION / INSURANCE_POLICY) — the same value as the sibling benefit_type column.Insurance policy details
TheINSURANCE_POLICY variant holds:
description— optional human-readable copy.duration— externally-tagged single-key object:{"days": 90},{"months": 12}, or{"years": 1}.plans— a map keyed by free-form provider-definedplan_code(e.g."1A","2A","2A1C"). EachPlanVariantcarriesdaily_premium_amount,annual_premium_amount,coverage_amount(all amounts in minor units with acurrency), optionalgrace_period_days, andnominee_required.questionnaire— optional tree ofQuestions the policyholder answers at policy creation.
Visibility by Actor
Auth Guards by Endpoint
Endpoints
POST /benefits
Create a benefit. Provider must exist and be active.
GET /benefits
List benefits. App users see only
ACTIVE ones. Filter by provider_id, benefit_type, status.GET /benefits/{benefit_id}
Fetch a benefit by UUID. App users receive 404 for inactive benefits.
PATCH /benefits/{benefit_id}
Update
name, description, benefit_details, or status.DELETE /benefits/{benefit_id}
Soft-delete (
status → INACTIVE).