From b0fec2037064be4dfd1a0fea97f87841bf210ad5 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Mon, 8 Jun 2026 16:15:22 +0800 Subject: [PATCH] Document feedback reward account details --- ...8-feedback-reward-account-detail-design.md | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-08-feedback-reward-account-detail-design.md diff --git a/docs/superpowers/specs/2026-06-08-feedback-reward-account-detail-design.md b/docs/superpowers/specs/2026-06-08-feedback-reward-account-detail-design.md new file mode 100644 index 00000000..39b8ef34 --- /dev/null +++ b/docs/superpowers/specs/2026-06-08-feedback-reward-account-detail-design.md @@ -0,0 +1,124 @@ +# Feedback Reward Account Detail Design + +## Goal + +Show users which submitted feedback earned points, how many points were awarded, and why. + +The first implementation focuses on account-page visibility. The later ops workflow for automatic reward issuance should reuse the same fields and display contract. + +## Current Context + +- `user_feedback` already stores each submitted feedback item with `status`, `message`, `user_id`, `user_email`, timestamps, and context JSON. +- `/api/feedback` already returns the current user's feedback list. +- `AccountFeedbackPanel` already renders the current user's feedback in the account page. +- Current points balance is shown through `/api/auth/me`, but account UI has no per-feedback reward source detail. +- Existing points grant helpers update `users.points`; feedback-specific rewards are not yet linked back to a feedback row. + +## Scope + +In scope: + +- Add feedback reward metadata to feedback rows. +- Return reward metadata through the existing current-user feedback API. +- Display feedback reward details in the account page next to the matching feedback item. +- Keep the data contract ready for future ops automation: a processed feedback item can carry reward points and a human-readable reason. + +Out of scope for this phase: + +- Building the ops action that decides and grants points. +- Sending push/email/Telegram notifications after ops processing. +- Rebuilding a general points ledger for all point sources. +- Merging historical Supabase referral ledger entries into the account page. + +## Data Model + +Extend `user_feedback` with nullable columns: + +- `reward_points INTEGER DEFAULT 0` +- `reward_reason TEXT DEFAULT ''` +- `rewarded_at TIMESTAMP` +- `reward_status TEXT DEFAULT ''` + +Recommended `reward_status` values: + +- empty string: no reward decision recorded +- `granted`: points were awarded for this feedback +- `skipped`: reviewed but no points awarded +- `pending`: reward decision is queued or awaiting processing + +The display should treat `reward_points > 0` as the strongest signal that the user earned points. + +## API Contract + +`DBManager._feedback_row_to_dict()` should include: + +- `reward_points` +- `reward_reason` +- `rewarded_at` +- `reward_status` + +`GET /api/feedback` should continue using the same response shape: + +```json +{ + "feedback": [ + { + "id": 123, + "status": "resolved", + "message": "Hong Kong COWIN reading looked stale", + "reward_points": 300, + "reward_reason": "Valid data freshness report", + "rewarded_at": "2026-06-08T12:00:00", + "reward_status": "granted" + } + ] +} +``` + +The frontend proxy does not need a new route if it transparently forwards the existing payload. + +## Account UI + +`AccountFeedbackPanel` should show reward detail inside each feedback row: + +- Granted reward: `+300 points` plus reward reason. +- Skipped reward: a muted note that no points were awarded, with reason if available. +- Pending reward: a small pending label. +- No reward metadata: render nothing extra to avoid noise. + +The account page should remain dense and scannable. Reward content belongs inside the existing feedback row, not in a separate marketing-style card. + +## Future Ops Workflow + +The later feedback-processing feature can use a single backend operation: + +1. Update feedback status. +2. Grant points to the matching user. +3. Write `reward_points`, `reward_reason`, `rewarded_at`, and `reward_status = granted` back to the same feedback row. + +If the grant fails, the operation should not mark the feedback as granted. It should either keep `reward_status = pending` or return a clear ops error. + +## Error Handling + +- Missing reward fields should default to zero or empty strings in API responses. +- If old SQLite databases do not have the new columns, `DBManager` migration should add them with `_ensure_column`. +- Account UI should tolerate partial payloads without crashing. +- Reward reason should be bounded in storage and display to avoid oversized rows. + +## Testing + +Backend tests: + +- Existing feedback rows serialize reward fields with defaults. +- Updating reward metadata for a feedback row returns the fields in `/api/feedback`. +- Old rows without rewards still list normally. + +Frontend tests: + +- Account feedback panel displays `+N points` and reason for rewarded feedback. +- Skipped and pending reward states render without implying points were granted. +- Rows without reward metadata do not show an empty reward block. + +## Rollout + +This is a backward-compatible schema and UI change. Existing feedback rows keep working with empty reward metadata. The account page can ship before the ops reward action; it will simply show reward details once rows carry those fields.