feat(feedback,credits): community-credit grants — +5 submit / +500 ship / +25 reaction-match

Phase 3.A des feedback-rewards-and-identity-Plans. Direkter Reziprozitäts-
Loop: User kriegt sofort etwas zurück fürs Mitwirken, Originalwunsch-
Eulen werden beim Ship belohnt, Reagierer kriegen einen Anteil.

mana-credits:
- Neuer Endpoint POST /api/v1/internal/credits/grant + grantCredits()
  Service-Methode mit Idempotency via metadata.referenceId.
- transaction_type-Enum erweitert um 'grant' (eigener Typ statt
  Mismatch mit 'refund').
- Migration 0001_grant_transaction_type.sql + partial-Index auf
  metadata->>'referenceId' für O(log n) Idempotency-Lookup.

mana-analytics:
- FeedbackService stempelt sofort +5 Credits beim createFeedback (top-
  level only, Replies bekommen nichts), wenn Mindest-20-Zeichen erfüllt
  und Rate-Limit (10/User/24h via feedback_grant_log) nicht überschritten.
- adminUpdate triggert beim FRISCHEN Übergang nach 'completed':
  +500 Credits an Original-Wisher + +25 an alle, die mit 👍 oder 🚀
  reagiert haben. Doppel-Pay strukturell unmöglich via referenceId
  (`<id>_shipped`, `<id>_reaction_<userId>`).
- Founder-Whitelist via FEEDBACK_FOUNDER_USER_IDS env (verhindert
  Self-Reward).
- Drop voteCount-Spalte (durch reactions/score seit 0002 ersetzt).
- Migration 0003_grant_log_drop_vote_count.sql idempotent, lokal +
  prod eingespielt.

Plan: docs/plans/feedback-rewards-and-identity.md (Phase 3.A-3.F).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-27 14:13:46 +02:00
parent e712faf7b7
commit dbe24acfc4
12 changed files with 882 additions and 7 deletions

View file

@ -583,10 +583,15 @@ services:
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/mana_platform
MANA_AUTH_URL: http://mana-auth:3001
MANA_LLM_URL: http://mana-llm:3025
MANA_CREDITS_URL: http://mana-credits:3061
MANA_SERVICE_KEY: ${MANA_SERVICE_KEY:?missing in .env.macmini}
# Seeds the per-user display-hash for the public-community pseudonym
# ("Wachsame Eule #4528"). Set in .env.macmini — rotation re-keys
# only future pseudonyms, existing rows keep the old hash/name.
FEEDBACK_PSEUDONYM_SECRET: ${FEEDBACK_PSEUDONYM_SECRET:?missing in .env.macmini}
# Comma-separated userIds that bypass community credit-grants
# (otherwise founders self-reward when posting/shipping).
FEEDBACK_FOUNDER_USER_IDS: ${FEEDBACK_FOUNDER_USER_IDS:-}
CORS_ORIGINS: https://mana.how,https://community.mana.how
ports:
- "3064:3064"