Skip to content

Implement sponsor tier model (Gold/Silver/Bronze) with database constraints - #71

Open
federicopfund wants to merge 1 commit into
mainfrom
claude/sponsor-tier-business-model-jrg66v
Open

Implement sponsor tier model (Gold/Silver/Bronze) with database constraints#71
federicopfund wants to merge 1 commit into
mainfrom
claude/sponsor-tier-business-model-jrg66v

Conversation

@federicopfund

Copy link
Copy Markdown
Owner

Summary

This PR implements the definitive sponsor business model with three tiers (Gold/Silver/Bronze), each with distinct content scope, exclusivity rules, and concurrency limits. The changes enforce these rules at the database level through constraints and indexes, eliminating reliance on application-layer validation alone.

Key Changes

  • Evolution 32 (conf/evolutions/default/32.sql): Core schema updates

    • Added publication_id FK to sponsor_agreements to support publication-level sponsorships
    • Introduced unit_type = 'platform' for Gold tier agreements (single agreement covering entire site)
    • Added sponsor_id, sponsor_label, sponsor_show_public columns to publications table (matching existing pattern in seasons/collections/events)
    • Implemented chk_agreement_tier_scope constraint to enforce tier-specific content scope:
      • Gold: only platform (all content)
      • Silver: event, newsletter, publication
      • Bronze: event, publication
    • Created unique partial indexes for exclusivity enforcement:
      • idx_sponsor_gold_exclusive: ensures max 1 active Gold agreement platform-wide
      • idx_sponsor_silver_event_exclusive, idx_sponsor_silver_publication_exclusive, idx_sponsor_silver_newsletter_exclusive: ensures max 1 active Silver per unit
    • Extended sponsor_deliverables types with Gold-exclusive surfaces: homepage_banner, site_header_badge
  • Trigger (sql/trigger_sponsor_bronze_limit.sql): Bronce concurrency enforcement

    • Implements enforce_bronze_sponsor_limit() function to enforce max 2 active Bronze agreements per unit
    • Cannot be expressed as a unique index (limit > 1), so implemented as a trigger
    • Kept outside Play evolutions due to PL/pgSQL dollar-quoting incompatibility (same pattern as evolution 16)
  • Documentation (docs/SPONSOR_TIER_MODEL.md): Comprehensive business model specification

    • Evaluates evolution 31 limitations and explains corrections
    • Details tier definitions, scope rules, and concurrency models
    • Explains database-level enforcement mechanisms
    • Documents visibility across content interfaces
    • Outlines scalability patterns and future application-layer work

Notable Implementation Details

  • Gold exclusivity: Implemented via unique partial index on tier column where tier='gold' AND status='active', preventing database-level violations even if application logic fails
  • Unit coherence: Constraint ensures exactly one FK is set per agreement based on unit_type, preventing data inconsistency
  • Platform agreements: Gold tier uses unit_type='platform' with no FK to specific content, allowing single agreement to cover all content surfaces
  • Backward compatibility: Evolution 32 includes proper !Downs section to safely rollback all changes
  • Denormalization strategy: Sponsor fields replicated across content tables (seasons, collections, events, publications) to avoid join overhead on every render

https://claude.ai/code/session_011GvPuvd3UBUf1hPFRHNEza

Evolution 32: agrega unit_type 'publication' y 'platform' a
sponsor_agreements, restringe qué contenido puede auspiciar cada tier
(chk_agreement_tier_scope) y garantiza con índices únicos parciales que
Oro sea exclusivo a nivel de toda la plataforma (no por unidad) y que
Plata tenga como máximo un acuerdo activo por unidad. publications gana
sponsor_id/sponsor_label/sponsor_show_public igual que seasons/
collections/events.

El límite de 2 sponsors Bronce activos por unidad no se puede expresar
como índice único, así que se aplica con un trigger fuera de las
evolutions de Play (sql/trigger_sponsor_bronze_limit.sql), siguiendo el
mismo patrón que trigger_close_previous_stage.sql.

docs/SPONSOR_TIER_MODEL.md documenta la evaluación de la evolution 31,
las reglas de negocio resultantes y los próximos pasos de capa de
aplicación (modelos, repos, admin UI, partial de badge).

Validado aplicando las 32 evolutions contra Postgres real y probando
las 10 reglas de negocio (exclusividad de Oro, alcance por tier,
exclusividad de Plata, límite de Bronce).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011GvPuvd3UBUf1hPFRHNEza
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants