src/lib/adapters.ts#adaptBounty maps status with no coercion or validation at all,
unlike almost every other field on the same object:
return {
...
reward: coerceNonNegative(raw.amount),
asset: raw.asset,
difficulty: raw.difficulty,
status: raw.status,
...
};
reward goes through coerceNonNegative, percentages go through coercePercentage, but
status (typed as Bounty["status"], i.e. trusted at compile time to already be one of
the eight known BountyStatus values) is passed straight through from
raw.status: Bounty["status"] with no runtime check that the backend actually sent one
of those eight strings.
If mergefi-backend's status enum is ever extended before this frontend's BountyStatus
union is updated to match (a realistic sequencing risk across two independently-deployed
repos), an unrecognized status value flows straight through into:
src/components/ui/Badge.tsx#StatusBadge, where statusStyles[status] returns
undefined for the unknown key, rendering the badge with no color styling at all.
src/app/issues/[id]/IssueActions.tsx, where none of the hardcoded status checks
("open", "funded", ["in_review", "merged", "paid", "refunded", "expired"], etc.)
match the unrecognized value — so the bounty renders with no action buttons at all,
not even the disabled "No action available" fallback, since that's also gated on the
same fixed status list.
Suggested fix: validate raw.status against the known BountyStatus set in
adaptBounty, falling back to a safe default (or surfacing a distinct "unknown status"
UI state) rather than letting an unrecognized value silently produce an uncolored badge
and a bounty page with zero available actions.
src/lib/adapters.ts#adaptBountymapsstatuswith no coercion or validation at all,unlike almost every other field on the same object:
rewardgoes throughcoerceNonNegative, percentages go throughcoercePercentage, butstatus(typed asBounty["status"], i.e. trusted at compile time to already be one ofthe eight known
BountyStatusvalues) is passed straight through fromraw.status: Bounty["status"]with no runtime check that the backend actually sent oneof those eight strings.
If
mergefi-backend's status enum is ever extended before this frontend'sBountyStatusunion is updated to match (a realistic sequencing risk across two independently-deployed
repos), an unrecognized status value flows straight through into:
src/components/ui/Badge.tsx#StatusBadge, wherestatusStyles[status]returnsundefinedfor the unknown key, rendering the badge with no color styling at all.src/app/issues/[id]/IssueActions.tsx, where none of the hardcoded status checks(
"open","funded",["in_review", "merged", "paid", "refunded", "expired"], etc.)match the unrecognized value — so the bounty renders with no action buttons at all,
not even the disabled "No action available" fallback, since that's also gated on the
same fixed status list.
Suggested fix: validate
raw.statusagainst the knownBountyStatusset inadaptBounty, falling back to a safe default (or surfacing a distinct "unknown status"UI state) rather than letting an unrecognized value silently produce an uncolored badge
and a bounty page with zero available actions.