Skip to content

feat: Universal Extension Marketplace Backend#28

Open
roncodes wants to merge 1 commit intomainfrom
feature/universal-extension-marketplace
Open

feat: Universal Extension Marketplace Backend#28
roncodes wants to merge 1 commit intomainfrom
feature/universal-extension-marketplace

Conversation

@roncodes
Copy link
Member

Overview

This PR implements the backend infrastructure for the Universal Extension Marketplace, enabling self-hosted Fleetbase instances to discover and purchase both free and paid extensions without requiring a cloud subscription.

Key Features

1. Public Extension Discovery

  • New endpoint: GET /~registry/v1/extensions
  • Returns all published extensions (free and paid)
  • Publicly accessible (no authentication required)
  • Cached for 15 minutes for optimal performance
  • Ordered by install count (most popular first)

2. Polymorphic Purchase System

  • Purchases can now be linked to either:
    • Company (cloud users)
    • RegistryDeveloperAccount (self-hosted users)
  • Uses Laravel's polymorphic relationship pattern
  • Maintains backward compatibility with existing purchases

3. Multi-Authentication Purchase Flow

  • Supports two authentication methods:
    • Session-based (cloud users via company_uuid)
    • Token-based (developer accounts via bearer token)
  • Automatically identifies purchaser type
  • Creates appropriate purchase records

Database Changes

Migration 1: Convert to Polymorphic

// Add to registry_extension_purchases
- purchaser_uuid (string)
- purchaser_type (string)

// Migrate existing data
company_uuid → purchaser_uuid
'Fleetbase\Models\Company' → purchaser_type

Migration 2: Add Indexes

- purchases_purchaser_index (purchaser_uuid, purchaser_type)
- purchases_extension_purchaser_index (extension_uuid, purchaser_uuid, purchaser_type)

Code Changes

Models

RegistryExtensionPurchase

  • Added purchaser() polymorphic relationship
  • Kept company() for backward compatibility
  • Updated `` to include new columns

Controllers

RegistryExtensionController

  • Added listPublicExtensions() method
  • Implements caching strategy
  • Returns formatted resource collection

RegistryPaymentsController

  • Updated getStripeCheckoutSessionStatus()
  • Identifies purchaser from session or bearer token
  • Creates polymorphic purchase records
  • Maintains company_uuid for backward compatibility

Routes

  • Added public route: GET /~registry/v1/extensions
  • No middleware (publicly accessible)

Benefits

For Self-Hosted Users

  • Can discover all available extensions
  • Can purchase paid extensions without cloud subscription
  • Seamless experience via centralized purchase flow

For Extension Developers

  • Clear monetization path
  • Access to entire Fleetbase user base
  • Automatic payment processing via Stripe

For Fleetbase

  • Unified marketplace for all users
  • Maintains 10% facilitator fee
  • Centralized payment security

For the Ecosystem

  • Encourages high-quality extension development
  • Creates vibrant commercial marketplace
  • Increases extension adoption

Testing Checklist

  • Test public extension endpoint returns all published extensions
  • Verify caching works correctly (15-minute TTL)
  • Test purchase flow with cloud user (session auth)
  • Test purchase flow with developer account (token auth)
  • Verify polymorphic relationships work correctly
  • Confirm backward compatibility with existing purchases
  • Test that duplicate purchases are prevented
  • Verify Stripe integration still works

Migration Notes

  • Existing company_uuid values are automatically migrated to polymorphic format
  • No data loss during migration
  • Backward compatible with existing code that uses company_uuid
  • Can safely deploy without breaking existing functionality

Related Work

This PR works in conjunction with:

Security Considerations

  • Public endpoint only exposes published extensions (no sensitive data)
  • Purchase authentication required via session or token
  • Stripe handles all payment processing (PCI compliant)
  • Polymorphic relationship prevents unauthorized purchases

Performance

  • 15-minute cache significantly reduces database load
  • Indexed polymorphic columns ensure fast queries
  • Ordered by popularity for better UX
  • Minimal overhead on existing purchase flow

This commit enables self-hosted instances to discover and purchase extensions
through a centralized marketplace system.

## Database Changes
- Convert registry_extension_purchases to polymorphic relationship
- Add purchaser_uuid and purchaser_type columns
- Add indexes for efficient polymorphic queries
- Maintain backward compatibility with company_uuid

## Model Updates
- Add polymorphic purchaser() relationship to RegistryExtensionPurchase
- Support both Company and RegistryDeveloperAccount as purchasers
- Maintain legacy company() relationship for backward compatibility

## Controller Updates
- Update getStripeCheckoutSessionStatus to identify purchaser via:
  - Session company_uuid (cloud users)
  - Bearer token + RegistryUser (developer accounts)
- Create purchase records with polymorphic purchaser data
- Add listPublicExtensions() method with 15-minute caching

## New Public Endpoint
- GET /~registry/v1/extensions - Publicly accessible extension listing
- Returns all published extensions (free and paid)
- Cached for performance and scalability
- Enables self-hosted instances to discover extensions

## Benefits
- Self-hosted users can view all available extensions
- Developer accounts can purchase extensions without cloud subscription
- Centralized payment processing maintains security
- Clear monetization path for extension developers
- Backward compatible with existing cloud user purchases
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments