Commit graph

8 commits

Author SHA1 Message Date
senke
9f4c2183a2 feat(backend,web): self-service creator role upgrade via /settings
First item of the v1.0.6 backlog surfaced by the v1.0.5 smoke test: a
brand-new account could register, verify email, and log in — but
attempting to upload hit a 403 because `role='user'` doesn't pass the
`RequireContentCreatorRole` middleware. The only way to get past that
gate was an admin DB update.

This commit wires the self-service path decided in the v1.0.6
specification:

  * One-way flip from `role='user'` to `role='creator'`, gated strictly
    on `is_verified=true` (the verification-email flow we restored in
    Fix 2 of the hardening sprint).
  * No KYC, no cooldown, no admin validation. The conscious click
    already requires ownership of the email address.
  * Downgrade is out of scope — a creator who wants back to `user`
    opens a support ticket. Avoids the "my uploads orphaned" edge case.

Backend
  * Migration `977_users_promoted_to_creator_at.sql`: nullable
    `TIMESTAMPTZ` column, partial index for non-null values. NULL
    preserves the semantic for users who never self-promoted
    (out-of-band admin assignments stay distinguishable from organic
    creators for audit/analytics).
  * `models.User`: new `PromotedToCreatorAt *time.Time` field.
  * `handlers.UpgradeToCreator(db, auditService, logger)`:
      - 401 if no `user_id` in context (belt-and-braces — middleware
        should catch this first)
      - 404 if the user row is missing
      - 403 `EMAIL_NOT_VERIFIED` when `is_verified=false`
      - 200 idempotent with `already_elevated=true` when the caller is
        already creator / premium / moderator / admin / artist /
        producer / label (same set accepted by
        `RequireContentCreatorRole`)
      - 200 with the new role + `promoted_to_creator_at` on the happy
        path. The UPDATE is scoped `WHERE role='user'` so a concurrent
        admin assignment can't be silently overwritten; the zero-rows
        case reloads and returns `already_elevated=true`.
      - audit logs a `user.upgrade_creator` action with IP, UA, and
        the role transition metadata. Non-fatal on failure — the
        upgrade itself already committed.
  * Route: `POST /api/v1/users/me/upgrade-creator` under the existing
    protected users group (RequireAuth + CSRF).

Frontend
  * `AccountSettingsCreatorCard`: new card in the Account tab of
    `/settings`. Completely hidden for users already on a creator-tier
    role (no "you're already a creator" clutter). Unverified users see
    a disabled-but-explanatory state with a "Resend verification"
    CTA to `/verify-email/resend`. Verified users see the "Become an
    artist" button, which POSTs to `/users/me/upgrade-creator` and
    refetches the user on success.
  * `upgradeToCreator()` service in `features/settings/services/`.
  * Copy is deliberately explicit that the change is one-way.

Tests
  * 6 Go unit tests covering: happy path (role + timestamp), unverified
    refused, already-creator idempotent (timestamp preserved),
    admin-assigned idempotent (no timestamp overwrite), user-not-found,
    no-auth-context.
  * 7 Vitest tests covering: verified button visible, unverified state
    shown, card hidden for creator, card hidden for admin, success +
    refetch, idempotent message, server error via toast.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 18:35:07 +02:00
senke
6a675565e1 feat(v0.13.3): complete - Polish Sécurité Avancée
TASK-SECADV-001: WebAuthn/Passkeys (F022)
- WebAuthn credential model, service, handler
- Registration/authentication ceremony endpoints
- CRUD operations (list, rename, delete passkeys)
- Routes: GET/POST/PUT/DELETE /auth/passkeys/*

TASK-SECADV-002: Configurable password policy (F015)
- PasswordPolicyConfig with MinLength, MaxLength, RequireUpper/Lower/Number/Special
- NewPasswordValidatorWithPolicy constructor
- PasswordPolicyFromEnv() reads env vars (PASSWORD_MIN_LENGTH, etc.)
- All character class checks now respect policy configuration

TASK-SECADV-003: Géolocalisation connexions (F025)
- GeoIPResolver interface + GeoIPService implementation
- Country/city columns added to login_history table
- LoginHistoryService.Record() performs GeoIP lookup
- GetUserHistory returns geolocation data
- GET /auth/login-history endpoint

TASK-SECADV-004: Password expiration (F016)
- password_changed_at column on users table
- CheckPasswordExpiration() method on PasswordService
- All password change/reset methods now set password_changed_at
- NewPasswordServiceWithPolicy() supports expiration days config

Migration: 971_security_advanced_v0133.sql

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:09:01 +01:00
senke
72b732664a feat(v0.12.6.3): remove ghost modules — gamification, A/B testing, GraphQL stubs
Some checks failed
Backend API CI / test-unit (push) Failing after 0s
Backend API CI / test-integration (push) Failing after 0s
Deleted 8 dead code modules identified by audit diagnostic:
- api/contest/, sound_design_contest/, production_challenge/, voting_system/
  (gamification stubs — violate CLAUDE.md Rule 3: no XP/streaks/leaderboards/badges)
- models/contest.go (314 lines: ContestBadge with rarity, ContestPrize, ContestVote)
- models/user.go: removed orphan JuryMember struct (contest reference)
- services/playback_abtest_service.go + test (476+579 lines: A/B testing on playback
  metrics — violates ORIGIN_UI_UX_SYSTEM.md §13 anti-dark-patterns)
- api/graphql/ (REST-only per ORIGIN spec)

Kept: listing/, offer/ (marketplace stubs, ORIGIN-approved), grpc/ (ORIGIN §9 approved).
Verified: go build passes, grep confirms 0 forbidden terms remaining.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 07:29:56 +01:00
senke
9be0e6e14f feat(profile): add profile banner (B1) 2026-02-20 14:56:25 +01:00
senke
81d08a4680 stabilisation commit 2026-01-04 01:44:23 +01:00
senke
40170e188a [FIX] PROD-010: Corriger ENUM PostgreSQL dans modèle User - Tests E2E passent
- Ajout de type:user_role dans le tag GORM du champ Role
- Amélioration de la détection d'erreurs ENUM dans le service Register
- L'endpoint /auth/register retourne maintenant 201 OK avec tokens
- Score production: 52/70 → 58/70
- PROD-010 marqué comme fixed (P0 blocker résolu)
2026-01-04 01:44:19 +01:00
senke
1b59fbaf34 [AUDIT] Real integration status - 58% pass rate, 2 blocking issues
- 19 tests executed (11 pass, 6 fail, 3 skip)
- 2 P0 blocking issues: Login email verification, Register empty tokens
- 4 P1 issues: Protected endpoints cannot be tested (depends on auth)
- 1 P2 issue: Sessions endpoint redirect
- Full test results documented with exact HTTP codes and error messages
- User journey analysis: can register but cannot login
- Recommendations: Fix auth workflow first, then retest protected endpoints
2026-01-04 01:44:13 +01:00
okinrev
2425c15b09 adding initial backend API (Go) 2025-12-03 20:29:37 +01:00