Skip to main content

Phase 1 Steps 7-9: Complete Commercial Revenue Flow - Orchestration Plan

Project: CODITECT Cloud Backend License Management Date: December 1, 2025 Status: Phase 1 Steps 1-6 Complete (66.7%) → Completing Steps 7-9 (Final 33.3%) Timeline: 3-4 days to completion (Target: December 5, 2025) Objective: Enable complete user → payment → license → usage → renewal cycle


Executive Summary

Current Status:

  • ✅ Phase 1 Steps 1-6: 100% Complete (user registration, Stripe, licenses, email, seat management)
  • ⏳ Phase 1 Steps 7-9: 0% Complete (client SDK, renewal automation, admin APIs)
  • 📊 Code: ~5,300 lines implemented, 196 tests, 72% coverage
  • 🎯 Milestone: First paying customer by December 22, 2025 (21 days remaining)

Steps to Complete:

StepComponentComplexityEst. LOCEst. TimeDependencies
7Client-Side Python SDK + HeartbeatMedium~8008-10hStep 6 (API) ✅
8Monthly Renewal AutomationMedium~6006-8hSteps 2,5 ✅
9Admin Dashboard EndpointsHigh~1,20012-14hAll previous ✅
Total~2,60026-32h3-4 days

Parallelization Strategy:

  • Step 7 and Step 8 can execute in parallel (no dependencies)
  • Step 9 requires Steps 7-8 complete (needs live data for analytics)

Table of Contents

  1. Dependency Analysis
  2. Step 7: Client-Side Python SDK
  3. Step 8: Monthly Renewal Automation
  4. Step 9: Admin Dashboard Endpoints
  5. Multi-Agent Coordination Plan
  6. Execution Timeline
  7. Success Verification Checklist
  8. Risk Mitigation

Dependency Analysis

Execution Order

┌─────────────────┐
│ Steps 1-6 │ ✅ COMPLETE (user registration, Stripe, licenses, email, seats)
└────────┬────────┘

┌────┴────┐
│ │
▼ ▼
┌───────┐ ┌───────┐
│ Step 7│ │ Step 8│ ⚡ PARALLEL EXECUTION (no dependencies)
│ SDK │ │Renewal│
└───┬───┘ └───┬───┘
│ │
└────┬────┘


┌────────┐
│ Step 9 │ 📊 SEQUENTIAL (needs live data from 7+8)
│ Admin │
└────────┘

Optimal Execution Strategy

Phase A: Parallel Implementation (Days 1-2)

  • Agent 1: Implement Step 7 (Client SDK)
  • Agent 2: Implement Step 8 (Renewal Webhooks)
  • Estimated Time: 14-18 hours (1.5-2 days)

Phase B: Sequential Implementation (Days 3-4)

  • Agent 3: Implement Step 9 (Admin Dashboard)
  • Estimated Time: 12-14 hours (1.5-2 days)

Total Timeline: 3-4 days to completion


Step 7: Client-Side Python SDK

Overview

Purpose: Python SDK for CODITECT CLI/framework to acquire licenses, send heartbeats, and release seats automatically.

Status: ❌ Not Started (0%) Complexity: Medium (client library development, threading, error handling) Estimated LOC: ~800 lines Estimated Time: 8-10 hours Dependencies: Step 6 (Seat Management API) ✅ Complete

Technical Specifications

7.1 SDK Architecture

Package Structure:

coditect_license_sdk/
├── __init__.py # Public API exports
├── client.py # Main LicenseClient class (300 lines)
├── session.py # LicenseSession management (200 lines)
├── heartbeat.py # Background heartbeat thread (150 lines)
├── exceptions.py # Custom exceptions (50 lines)
├── models.py # Data models (100 lines)
└── utils.py # Helper functions (50 lines)

tests/
├── test_client.py # Client tests (200 lines)
├── test_session.py # Session tests (150 lines)
├── test_heartbeat.py # Heartbeat tests (100 lines)
└── conftest.py # Pytest fixtures (50 lines)

Total: ~1,350 lines (implementation + tests)

7.2 Core Components

LicenseClient (Main Interface)
from coditect_license_sdk import LicenseClient

# Initialize client
client = LicenseClient(
api_url="https://api.coditect.ai",
api_key="user_api_token"
)

# Acquire license (blocks until seat available)
session = client.acquire_license(
license_key="CODITECT-A7B2-9C4D-E6F8-1G3H-5J7K",
machine_id="a7b2c4d6e8f0a1b3c5d7e9f1a3b5c7d9",
machine_info={
"hostname": "johns-macbook",
"os": "macOS 14.1",
"coditect_version": "1.0.0"
}
)

# Session automatically sends heartbeats every 2 minutes
# Use CODITECT features...

# Release when done (automatically called on process exit)
session.release()
Automatic Heartbeat Management
# Heartbeat thread (background daemon)
import threading
import time

class HeartbeatThread(threading.Thread):
def __init__(self, session_id, client, interval=120):
super().__init__(daemon=True)
self.session_id = session_id
self.client = client
self.interval = interval # 2 minutes
self.running = True

def run(self):
while self.running:
time.sleep(self.interval)
try:
self.client.send_heartbeat(self.session_id)
except Exception as e:
# Exponential backoff on failure
time.sleep(min(300, self.interval * 2))

def stop(self):
self.running = False
Graceful Shutdown
import atexit
import signal

class LicenseSession:
def __init__(self, session_id, client):
self.session_id = session_id
self.client = client
self.released = False

# Register cleanup handlers
atexit.register(self.release)
signal.signal(signal.SIGTERM, self._signal_handler)
signal.signal(signal.SIGINT, self._signal_handler)

def _signal_handler(self, signum, frame):
self.release()
sys.exit(0)

def release(self):
if not self.released:
self.client.release_license(self.session_id)
self.released = True

7.3 Error Handling

Custom Exceptions:

class LicenseError(Exception):
"""Base exception for license operations"""
pass

class LicenseAcquisitionError(LicenseError):
"""Failed to acquire license seat"""
pass

class SeatUnavailableError(LicenseAcquisitionError):
"""All seats currently in use"""
pass

class LicenseExpiredError(LicenseError):
"""License has expired"""
pass

class HeartbeatFailedError(LicenseError):
"""Heartbeat request failed"""
pass

class NetworkError(LicenseError):
"""Network connectivity issue"""
pass

Retry Logic:

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=10)
)
def acquire_license_with_retry(self, license_key, machine_id, machine_info):
"""Retry acquisition up to 3 times with exponential backoff"""
response = self.api_client.post("/licenses/acquire", json={
"license_key": license_key,
"machine_id": machine_id,
"machine_info": machine_info
})

if response.status_code == 409: # Seat unavailable
raise SeatUnavailableError("All license seats are in use")
elif response.status_code == 401: # Unauthorized
raise LicenseAcquisitionError("Invalid license key")

response.raise_for_status()
return response.json()

7.4 Implementation Tasks

Agent Assignment: Backend Python Developer (codi-python-backend-developer)

Task Breakdown:

  1. Package Setup (1 hour)

    • Create package structure
    • Setup pyproject.toml with dependencies
    • Configure pytest for testing
  2. Core Client Implementation (3 hours)

    • Implement LicenseClient class
    • HTTP client with requests library
    • Authentication header handling
    • Error response parsing
  3. Session Management (2 hours)

    • LicenseSession class
    • Graceful shutdown handlers
    • State management (active/released)
  4. Heartbeat Threading (2 hours)

    • Background daemon thread
    • Exponential backoff on failure
    • Graceful thread termination
  5. Exception Handling (1 hour)

    • Custom exception hierarchy
    • Retry logic with tenacity
    • Network error handling
  6. Testing (2-3 hours)

    • Unit tests with mocked API
    • Integration tests with live API
    • Threading tests
    • Edge case handling

Dependencies:

# pyproject.toml
[project]
name = "coditect-license-sdk"
version = "1.0.0"
dependencies = [
"requests>=2.31.0",
"tenacity>=8.2.0",
"pydantic>=2.5.0",
]

[project.optional-dependencies]
dev = [
"pytest>=7.4.0",
"pytest-cov>=4.1.0",
"responses>=0.24.0", # Mock HTTP responses
]

7.5 Integration with CODITECT Framework

Usage in CODITECT CLI:

# coditect/cli/license_manager.py
from coditect_license_sdk import LicenseClient

def initialize_license():
"""Initialize license on CODITECT startup"""
config = load_coditect_config()

client = LicenseClient(
api_url=config.get("license_api_url"),
api_key=config.get("user_api_token")
)

session = client.acquire_license(
license_key=config.get("license_key"),
machine_id=get_machine_id(),
machine_info=get_machine_info()
)

# Store session globally for cleanup
global _active_license_session
_active_license_session = session

return session

7.6 Success Criteria

  • ✅ SDK can acquire license seat successfully
  • ✅ Heartbeat sends every 2 minutes automatically
  • ✅ Graceful release on normal exit
  • ✅ Graceful release on SIGTERM/SIGINT
  • ✅ Retry logic handles transient failures
  • ✅ Clear error messages for all failure modes
  • ✅ Unit tests: 80%+ coverage
  • ✅ Integration tests: All API endpoints tested
  • ✅ Documentation: API reference + examples

7.7 Deliverables

  1. SDK Package: coditect_license_sdk/ (800 lines)
  2. Test Suite: tests/ (500 lines, 80%+ coverage)
  3. Documentation: README.md with API reference and examples
  4. Integration: Modified CODITECT CLI to use SDK
  5. PyPI Package: Published coditect-license-sdk v1.0.0

Step 8: Monthly Renewal Automation

Overview

Purpose: Automatically renew licenses when Stripe charges monthly subscription, handle payment failures, send notifications.

Status: ❌ Not Started (0%) Complexity: Medium (webhook integration, edge cases, idempotency) Estimated LOC: ~600 lines Estimated Time: 6-8 hours Dependencies: Step 2 (Stripe Integration) ✅, Step 5 (SendGrid Email) ✅

Technical Specifications

8.1 Webhook Architecture

Stripe Webhooks to Handle:

1. invoice.payment_succeeded  → Renew license automatically
2. invoice.payment_failed → Suspend license + notify user
3. customer.subscription.deleted → Deactivate license + notify
4. customer.subscription.updated → Update license tier

Webhook Endpoint:

POST /api/v1/webhooks/stripe
Headers:
- stripe-signature: [webhook signature]

Body: JSON event from Stripe

8.2 Renewal Flow

┌─────────────────┐
│ Stripe charges │ Monthly billing cycle (e.g., 1st of month)
│ subscription │
└────────┬────────┘


┌─────────────────┐
│ Webhook Event │ invoice.payment_succeeded
│ Received │
└────────┬────────┘


┌─────────────────┐
│ Verify Signature│ Validate webhook authenticity
└────────┬────────┘


┌─────────────────┐
│ Find License │ subscription_id → license mapping
└────────┬────────┘


┌─────────────────┐
│ Renew License │ Update valid_until = now + 30 days
└────────┬────────┘


┌─────────────────┐
│ Send Email │ "Your CODITECT license has been renewed"
└─────────────────┘

8.3 Core Components

Webhook Handler View

File: api/v1/views/stripe_webhook.py (250 lines)

from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
from django.db import transaction
import stripe
import logging

logger = logging.getLogger(__name__)

@csrf_exempt
def stripe_webhook_handler(request):
"""
Handle Stripe webhook events for subscription lifecycle.

Idempotent: Safe to receive duplicate events.
"""
payload = request.body
sig_header = request.META.get('HTTP_STRIPE_SIGNATURE')

try:
# Verify webhook signature
event = stripe.Webhook.construct_event(
payload, sig_header, settings.STRIPE_WEBHOOK_SECRET
)
except ValueError:
logger.error("Invalid webhook payload")
return JsonResponse({'error': 'Invalid payload'}, status=400)
except stripe.error.SignatureVerificationError:
logger.error("Invalid webhook signature")
return JsonResponse({'error': 'Invalid signature'}, status=400)

# Route to appropriate handler
handlers = {
'invoice.payment_succeeded': handle_payment_succeeded,
'invoice.payment_failed': handle_payment_failed,
'customer.subscription.deleted': handle_subscription_deleted,
'customer.subscription.updated': handle_subscription_updated,
}

handler = handlers.get(event['type'])
if handler:
try:
handler(event['data']['object'])
return JsonResponse({'status': 'success'})
except Exception as e:
logger.error(f"Webhook handler failed: {e}", exc_info=True)
return JsonResponse({'error': str(e)}, status=500)

# Unknown event type (ignore)
return JsonResponse({'status': 'ignored'})
Payment Success Handler
@transaction.atomic
def handle_payment_succeeded(invoice):
"""
Renew license when monthly payment succeeds.

Idempotent: Check if already renewed for this billing period.
"""
subscription_id = invoice['subscription']
payment_intent = invoice['payment_intent']

# Find license by subscription
try:
license = License.objects.select_for_update().get(
subscription__stripe_subscription_id=subscription_id
)
except License.DoesNotExist:
logger.warning(f"License not found for subscription {subscription_id}")
return

# Check if already renewed (idempotency)
if license.valid_until and license.valid_until > timezone.now():
logger.info(f"License {license.key} already renewed")
return

# Renew license for 30 days
license.valid_until = timezone.now() + timedelta(days=30)
license.is_active = True
license.save()

# Create audit log
AuditLog.objects.create(
license=license,
action='license_renewed',
details={
'subscription_id': subscription_id,
'payment_intent': payment_intent,
'renewed_until': license.valid_until.isoformat(),
}
)

# Send renewal email
send_license_renewed_email(license)

logger.info(f"License {license.key} renewed until {license.valid_until}")
Payment Failure Handler
@transaction.atomic
def handle_payment_failed(invoice):
"""
Suspend license when payment fails.

Grace period: Allow 3 days before hard suspension.
"""
subscription_id = invoice['subscription']
attempt_count = invoice['attempt_count']

try:
license = License.objects.select_for_update().get(
subscription__stripe_subscription_id=subscription_id
)
except License.DoesNotExist:
return

# First failure: Send warning email (grace period)
if attempt_count == 1:
grace_until = timezone.now() + timedelta(days=3)
send_payment_failed_email(license, grace_until)
logger.warning(f"Payment failed for license {license.key} (attempt {attempt_count})")
return

# Multiple failures: Suspend license
if attempt_count >= 2:
license.is_active = False
license.save()

# Create audit log
AuditLog.objects.create(
license=license,
action='license_suspended',
details={
'reason': 'payment_failure',
'attempt_count': attempt_count,
}
)

# Send suspension email
send_license_suspended_email(license)

logger.error(f"License {license.key} suspended due to payment failure")
Subscription Deletion Handler
@transaction.atomic
def handle_subscription_deleted(subscription):
"""
Deactivate license when subscription is cancelled.

Immediate effect: No grace period.
"""
subscription_id = subscription['id']

try:
license = License.objects.select_for_update().get(
subscription__stripe_subscription_id=subscription_id
)
except License.DoesNotExist:
return

# Deactivate license
license.is_active = False
license.save()

# Create audit log
AuditLog.objects.create(
license=license,
action='license_deactivated',
details={
'reason': 'subscription_cancelled',
'subscription_id': subscription_id,
}
)

# Send cancellation confirmation email
send_subscription_cancelled_email(license)

logger.info(f"License {license.key} deactivated (subscription cancelled)")

8.4 Email Templates

File: api/v1/emails/license_renewed.py (150 lines)

def send_license_renewed_email(license):
"""
Send renewal confirmation email.

Template: license_renewed.html
"""
user = license.subscription.user

context = {
'user_name': user.full_name,
'license_key': license.key,
'valid_until': license.valid_until.strftime('%B %d, %Y'),
'plan_name': license.subscription.stripe_price_id,
'dashboard_url': 'https://dashboard.coditect.ai',
}

send_email(
to_email=user.email,
subject="Your CODITECT License Has Been Renewed",
template='license_renewed.html',
context=context
)

SendGrid Template Structure:

<!-- license_renewed.html -->
<h1>License Renewed Successfully</h1>
<p>Hi {{user_name}},</p>
<p>Your CODITECT license has been automatically renewed.</p>
<ul>
<li>License Key: <code>{{license_key}}</code></li>
<li>Valid Until: {{valid_until}}</li>
<li>Plan: {{plan_name}}</li>
</ul>
<p>Continue building amazing projects!</p>
<a href="{{dashboard_url}}">View Dashboard</a>

8.5 Implementation Tasks

Agent Assignment: Backend API Developer (codi-backend-api-developer)

Task Breakdown:

  1. Stripe Webhook Setup (1 hour)

    • Register webhook endpoint in Stripe Dashboard
    • Configure event types to listen for
    • Get webhook signing secret
  2. Webhook Handler Implementation (2 hours)

    • Main webhook view with signature verification
    • Event routing to specific handlers
    • Error handling and logging
  3. Renewal Logic Implementation (2 hours)

    • Payment success handler
    • Payment failure handler (with grace period)
    • Subscription deletion handler
    • Subscription update handler
  4. Email Integration (1 hour)

    • Renewal confirmation email
    • Payment failure warning email
    • License suspension email
    • Cancellation confirmation email
  5. Testing (2 hours)

    • Unit tests with mocked Stripe events
    • Webhook signature verification tests
    • Idempotency tests (duplicate events)
    • Integration tests with Stripe CLI

Testing with Stripe CLI:

# Install Stripe CLI
brew install stripe/stripe-cli/stripe

# Forward webhooks to local server
stripe listen --forward-to localhost:8000/api/v1/webhooks/stripe

# Trigger test events
stripe trigger invoice.payment_succeeded
stripe trigger invoice.payment_failed
stripe trigger customer.subscription.deleted

8.6 Idempotency Considerations

Critical: Stripe may send duplicate webhook events. All handlers must be idempotent.

Idempotency Strategies:

  1. Database Constraints:
# Prevent duplicate license renewals for same billing period
class LicenseRenewalLog(models.Model):
license = models.ForeignKey(License)
stripe_invoice_id = models.CharField(max_length=255, unique=True)
renewed_at = models.DateTimeField(auto_now_add=True)

class Meta:
unique_together = ('license', 'stripe_invoice_id')
  1. Check-Before-Act:
# Check if action already performed
if LicenseRenewalLog.objects.filter(stripe_invoice_id=invoice_id).exists():
logger.info(f"Invoice {invoice_id} already processed")
return # Skip duplicate
  1. Atomic Transactions:
@transaction.atomic
def handle_payment_succeeded(invoice):
# Use select_for_update to prevent race conditions
license = License.objects.select_for_update().get(...)
# ... perform operations ...

8.7 Success Criteria

  • ✅ Webhook endpoint receives Stripe events correctly
  • ✅ Signature verification prevents spoofed webhooks
  • ✅ Licenses renew automatically on payment success
  • ✅ Licenses suspend after 2 failed payments
  • ✅ Licenses deactivate on subscription cancellation
  • ✅ All email notifications sent correctly
  • ✅ Idempotency: Duplicate events handled safely
  • ✅ Unit tests: 85%+ coverage
  • ✅ Integration tests: All webhook types tested
  • ✅ Manual testing: Stripe CLI triggers verified

8.8 Deliverables

  1. Webhook Handler: api/v1/views/stripe_webhook.py (250 lines)
  2. Event Handlers: Payment, failure, cancellation handlers (200 lines)
  3. Email Templates: 4 SendGrid templates (150 lines)
  4. Test Suite: Webhook tests (200 lines, 85%+ coverage)
  5. Documentation: Webhook setup guide and testing procedures

Step 9: Admin Dashboard Endpoints

Overview

Purpose: Comprehensive API endpoints for admin dashboard to manage organizations, licenses, users, billing, and view analytics.

Status: ❌ Not Started (0%) Complexity: High (CRUD operations + analytics + admin auth) Estimated LOC: ~1,200 lines Estimated Time: 12-14 hours Dependencies: All previous steps (needs live data)

Technical Specifications

9.1 Admin Dashboard Requirements

User Stories:

  1. As an admin, I want to view all organizations so I can monitor customer base
  2. As an admin, I want to search organizations by name/email for support
  3. As an admin, I want to view all licenses and their status (active/expired/suspended)
  4. As an admin, I want to manually activate/deactivate licenses for edge cases
  5. As an admin, I want to view license usage analytics (seat utilization, uptime)
  6. As an admin, I want to manage users (view, suspend, delete)
  7. As an admin, I want to view billing history (Stripe transactions)
  8. As an admin, I want to view system health metrics (API performance, errors)

9.2 API Endpoints

Admin Organization Management:

GET    /api/v1/admin/organizations           # List all organizations
GET /api/v1/admin/organizations/{id} # Get organization details
POST /api/v1/admin/organizations # Create organization (manual)
PATCH /api/v1/admin/organizations/{id} # Update organization
DELETE /api/v1/admin/organizations/{id} # Delete organization
GET /api/v1/admin/organizations/search # Search by name/email

Admin License Management:

GET    /api/v1/admin/licenses                # List all licenses
GET /api/v1/admin/licenses/{key} # Get license details
POST /api/v1/admin/licenses # Create license manually
PATCH /api/v1/admin/licenses/{key} # Update license
DELETE /api/v1/admin/licenses/{key} # Revoke license
POST /api/v1/admin/licenses/{key}/activate # Activate license
POST /api/v1/admin/licenses/{key}/deactivate # Deactivate license
GET /api/v1/admin/licenses/{key}/sessions # View active sessions
POST /api/v1/admin/licenses/{key}/sessions/{id}/terminate # Kill session

Admin User Management:

GET    /api/v1/admin/users                   # List all users
GET /api/v1/admin/users/{id} # Get user details
POST /api/v1/admin/users # Create user manually
PATCH /api/v1/admin/users/{id} # Update user
DELETE /api/v1/admin/users/{id} # Delete user
POST /api/v1/admin/users/{id}/suspend # Suspend user account
POST /api/v1/admin/users/{id}/unsuspend # Unsuspend user account
GET /api/v1/admin/users/search # Search users

Admin Analytics:

GET    /api/v1/admin/analytics/overview      # Dashboard overview stats
GET /api/v1/admin/analytics/revenue # Revenue metrics
GET /api/v1/admin/analytics/licenses # License usage metrics
GET /api/v1/admin/analytics/users # User growth metrics
GET /api/v1/admin/analytics/sessions # Session analytics

Admin Billing:

GET    /api/v1/admin/billing/transactions    # All Stripe transactions
GET /api/v1/admin/billing/subscriptions # All subscriptions
GET /api/v1/admin/billing/invoices # All invoices
POST /api/v1/admin/billing/refunds # Issue refund

Total Endpoints: 31 admin endpoints

9.3 Core Components

Admin Authentication Middleware

File: api/middleware/admin_auth.py (100 lines)

from django.http import JsonResponse
from functools import wraps

def admin_required(view_func):
"""
Decorator for admin-only endpoints.

Requires:
- Valid JWT token
- User has 'admin' role
"""
@wraps(view_func)
def wrapper(request, *args, **kwargs):
# Check authentication
if not request.user or not request.user.is_authenticated:
return JsonResponse({
'error': 'Authentication required'
}, status=401)

# Check admin role
if not request.user.is_staff and not request.user.is_superuser:
return JsonResponse({
'error': 'Admin privileges required'
}, status=403)

return view_func(request, *args, **kwargs)

return wrapper
Organization Management View

File: api/v1/views/admin/organizations.py (250 lines)

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.core.paginator import Paginator
from api.middleware.admin_auth import admin_required

class AdminOrganizationListView(APIView):
"""
List all organizations with pagination and filtering.

Query params:
- page: Page number (default: 1)
- page_size: Items per page (default: 50)
- search: Search by name/email
- status: Filter by status (active/suspended)
"""

@admin_required
def get(self, request):
# Parse query params
page = int(request.GET.get('page', 1))
page_size = int(request.GET.get('page_size', 50))
search = request.GET.get('search', '')
status_filter = request.GET.get('status', '')

# Build queryset
orgs = Organization.objects.all()

if search:
orgs = orgs.filter(
Q(name__icontains=search) |
Q(owner__email__icontains=search)
)

if status_filter:
orgs = orgs.filter(is_active=(status_filter == 'active'))

# Order by creation date
orgs = orgs.order_by('-created_at')

# Paginate
paginator = Paginator(orgs, page_size)
page_obj = paginator.get_page(page)

# Serialize
data = {
'organizations': [
{
'id': org.id,
'name': org.name,
'owner_email': org.owner.email,
'created_at': org.created_at.isoformat(),
'is_active': org.is_active,
'license_count': org.licenses.count(),
'user_count': org.users.count(),
}
for org in page_obj
],
'pagination': {
'page': page,
'page_size': page_size,
'total_pages': paginator.num_pages,
'total_count': paginator.count,
}
}

return Response(data)
License Management View

File: api/v1/views/admin/licenses.py (300 lines)

class AdminLicenseListView(APIView):
"""
List all licenses with filtering and search.
"""

@admin_required
def get(self, request):
# Similar structure to OrganizationListView
# Filters: status, plan, expiration date range
pass

class AdminLicenseActivateView(APIView):
"""
Manually activate a license.
"""

@admin_required
@transaction.atomic
def post(self, request, license_key):
try:
license = License.objects.select_for_update().get(key=license_key)
except License.DoesNotExist:
return Response({
'error': 'License not found'
}, status=404)

# Activate license
license.is_active = True
license.save()

# Create audit log
AuditLog.objects.create(
license=license,
action='admin_activated',
details={
'admin_user': request.user.email,
'reason': request.data.get('reason', 'Manual activation'),
}
)

return Response({
'status': 'activated',
'license_key': license.key,
})

class AdminLicenseSessionTerminateView(APIView):
"""
Forcefully terminate an active license session.
"""

@admin_required
@transaction.atomic
def post(self, request, license_key, session_id):
try:
session = LicenseSession.objects.get(
id=session_id,
license__key=license_key
)
except LicenseSession.DoesNotExist:
return Response({
'error': 'Session not found'
}, status=404)

# End session
session.ended_at = timezone.now()
session.save()

# Release seat in Redis
redis_client.decr(f"license_seats:{license_key}")

# Create audit log
AuditLog.objects.create(
license=session.license,
action='admin_session_terminated',
details={
'admin_user': request.user.email,
'session_id': str(session_id),
'reason': request.data.get('reason', 'Admin intervention'),
}
)

return Response({
'status': 'terminated',
'session_id': str(session_id),
})
Analytics View

File: api/v1/views/admin/analytics.py (400 lines)

from django.db.models import Count, Sum, Avg
from datetime import datetime, timedelta

class AdminAnalyticsOverviewView(APIView):
"""
Dashboard overview with key metrics.
"""

@admin_required
def get(self, request):
now = timezone.now()
last_30_days = now - timedelta(days=30)

# Calculate metrics
metrics = {
'organizations': {
'total': Organization.objects.count(),
'active': Organization.objects.filter(is_active=True).count(),
'new_this_month': Organization.objects.filter(
created_at__gte=last_30_days
).count(),
},
'licenses': {
'total': License.objects.count(),
'active': License.objects.filter(is_active=True).count(),
'expired': License.objects.filter(
valid_until__lt=now
).count(),
'suspended': License.objects.filter(
is_active=False,
valid_until__gte=now
).count(),
},
'users': {
'total': User.objects.count(),
'active': User.objects.filter(is_active=True).count(),
'new_this_month': User.objects.filter(
created_at__gte=last_30_days
).count(),
},
'sessions': {
'active_now': LicenseSession.objects.filter(
ended_at__isnull=True,
last_heartbeat_at__gte=now - timedelta(minutes=6)
).count(),
'total_this_month': LicenseSession.objects.filter(
started_at__gte=last_30_days
).count(),
},
'revenue': {
'mrr': calculate_monthly_recurring_revenue(),
'arr': calculate_annual_recurring_revenue(),
'churn_rate': calculate_churn_rate(),
},
}

return Response(metrics)

class AdminAnalyticsLicenseUsageView(APIView):
"""
Detailed license usage analytics.
"""

@admin_required
def get(self, request):
# Calculate seat utilization per license
licenses = License.objects.annotate(
total_sessions=Count('sessions'),
active_sessions=Count('sessions', filter=Q(
sessions__ended_at__isnull=True,
sessions__last_heartbeat_at__gte=timezone.now() - timedelta(minutes=6)
))
)

usage_data = []
for license in licenses:
usage_data.append({
'license_key': license.key,
'max_seats': license.max_seats,
'active_sessions': license.active_sessions,
'utilization_percent': (license.active_sessions / license.max_seats) * 100 if license.max_seats > 0 else 0,
'total_sessions_all_time': license.total_sessions,
})

# Sort by utilization (highest first)
usage_data.sort(key=lambda x: x['utilization_percent'], reverse=True)

return Response({
'license_usage': usage_data,
'summary': {
'avg_utilization': sum(d['utilization_percent'] for d in usage_data) / len(usage_data) if usage_data else 0,
'over_utilized': [d for d in usage_data if d['utilization_percent'] >= 90],
'under_utilized': [d for d in usage_data if d['utilization_percent'] < 20],
}
})

9.4 Pagination & Filtering

Standard Pagination:

# Query params
?page=1&page_size=50

# Response format
{
"data": [...],
"pagination": {
"page": 1,
"page_size": 50,
"total_pages": 10,
"total_count": 487,
"has_next": true,
"has_previous": false
}
}

Standard Filtering:

# Organizations
?status=active&search=acme

# Licenses
?status=active&plan=pro&expires_after=2025-12-01

# Users
?status=active&role=admin&search=john

# Sessions
?active=true&license_key=CODITECT-xxx

9.5 Implementation Tasks

Agent Assignment: Full-Stack API Developer (codi-fullstack-developer)

Task Breakdown:

  1. Admin Middleware Setup (1 hour)

    • Admin authentication decorator
    • Role-based access control
    • Audit logging for admin actions
  2. Organization Management (2 hours)

    • List, view, create, update, delete endpoints
    • Search and filtering
    • Pagination
  3. License Management (3 hours)

    • List, view, create, update, delete endpoints
    • Activate/deactivate actions
    • Session management (view, terminate)
    • Search and filtering
  4. User Management (2 hours)

    • List, view, create, update, delete endpoints
    • Suspend/unsuspend actions
    • Search and filtering
  5. Analytics Implementation (3 hours)

    • Overview dashboard metrics
    • Revenue calculations (MRR, ARR, churn)
    • License usage analytics
    • User growth metrics
    • Session analytics
  6. Billing Integration (1 hour)

    • Transaction history
    • Subscription listing
    • Refund API
  7. Testing (3 hours)

    • Unit tests for all endpoints
    • Authorization tests (admin vs. non-admin)
    • Pagination tests
    • Analytics calculation tests

Testing Strategy:

# pytest tests/admin/test_admin_organizations.py
def test_admin_can_list_organizations(admin_client):
response = admin_client.get('/api/v1/admin/organizations')
assert response.status_code == 200
assert 'organizations' in response.json()

def test_non_admin_cannot_list_organizations(user_client):
response = user_client.get('/api/v1/admin/organizations')
assert response.status_code == 403

def test_organization_search_works(admin_client):
response = admin_client.get('/api/v1/admin/organizations?search=acme')
assert response.status_code == 200
results = response.json()['organizations']
assert all('acme' in org['name'].lower() for org in results)

9.6 Success Criteria

  • ✅ All 31 admin endpoints implemented
  • ✅ Admin-only authorization enforced
  • ✅ Pagination works on all list endpoints
  • ✅ Search and filtering functional
  • ✅ Analytics calculations accurate (MRR, ARR, churn, utilization)
  • ✅ Audit logging for all admin actions
  • ✅ Manual license activation/deactivation works
  • ✅ Session termination functional
  • ✅ Unit tests: 80%+ coverage
  • ✅ Integration tests: All endpoints tested
  • ✅ OpenAPI documentation generated

9.7 Deliverables

  1. Admin Middleware: api/middleware/admin_auth.py (100 lines)
  2. Organization Management: api/v1/views/admin/organizations.py (250 lines)
  3. License Management: api/v1/views/admin/licenses.py (300 lines)
  4. User Management: api/v1/views/admin/users.py (200 lines)
  5. Analytics: api/v1/views/admin/analytics.py (400 lines)
  6. Billing: api/v1/views/admin/billing.py (150 lines)
  7. Test Suite: tests/admin/ (500 lines, 80%+ coverage)
  8. API Documentation: OpenAPI specs for all endpoints

Multi-Agent Coordination Plan

Agent Assignments

Agent TypeStepTasksParallel?
codi-python-backend-developerStep 7Client SDK implementation✅ Yes (with Agent 2)
codi-backend-api-developerStep 8Stripe webhook handlers✅ Yes (with Agent 1)
codi-fullstack-developerStep 9Admin dashboard APIs❌ Sequential (after 7+8)
codi-test-engineerAll StepsComprehensive testing⚡ Continuous
codi-documentation-writerAll StepsAPI documentation⚡ Continuous

Execution Phases

Phase A: Parallel Implementation (Days 1-2)

Agent 1: Python Backend Developer (Step 7)

Task(
subagent_type="codi-python-backend-developer",
description="Implement CODITECT License SDK with automatic heartbeat scheduling",
prompt="""
Implement client-side Python SDK for CODITECT license management:

1. Package Structure:
- coditect_license_sdk/ (main package)
- client.py (LicenseClient class)
- session.py (LicenseSession management)
- heartbeat.py (background thread)
- exceptions.py (custom errors)

2. Core Features:
- acquire_license(): Obtain seat from API
- Automatic heartbeat every 2 minutes (background thread)
- Graceful release on exit (atexit, signal handlers)
- Retry logic with exponential backoff
- Clear error messages

3. API Integration:
- POST /api/v1/licenses/acquire
- PATCH /api/v1/licenses/sessions/{id}/heartbeat
- DELETE /api/v1/licenses/sessions/{id}

4. Testing:
- Unit tests with mocked API (responses library)
- Threading tests
- Integration tests with live API
- 80%+ coverage

5. Documentation:
- README.md with examples
- API reference
- Error handling guide

Reference: phase1-step6-api-quick-reference.md for API specs
Target: 800 lines implementation + 500 lines tests
Completion: 8-10 hours
"""
)

Agent 2: Backend API Developer (Step 8)

Task(
subagent_type="codi-backend-api-developer",
description="Implement Stripe webhook handlers for automatic license renewal",
prompt="""
Implement Stripe webhook integration for subscription lifecycle:

1. Webhook Endpoint:
- POST /api/v1/webhooks/stripe
- Signature verification (stripe.Webhook.construct_event)
- Event routing to handlers

2. Event Handlers:
- invoice.payment_succeeded → Renew license (valid_until + 30 days)
- invoice.payment_failed → Suspend license (grace period: 3 days)
- customer.subscription.deleted → Deactivate license
- customer.subscription.updated → Update license tier

3. Idempotency:
- Check for duplicate events (invoice_id uniqueness)
- Atomic transactions (select_for_update)
- LicenseRenewalLog table for tracking

4. Email Notifications:
- Renewal confirmation (license_renewed.html)
- Payment failure warning (payment_failed.html)
- License suspended (license_suspended.html)
- Cancellation confirmation (subscription_cancelled.html)

5. Testing:
- Unit tests with mocked Stripe events
- Idempotency tests (duplicate events)
- Integration tests with Stripe CLI
- 85%+ coverage

Reference: phase1-step2-stripe-design.md, phase1-step5-sendgrid-email-design.md
Target: 600 lines implementation + 200 lines tests
Completion: 6-8 hours
"""
)

Synchronization Point: Wait for both agents to complete Phase A before starting Phase B.

Phase B: Sequential Implementation (Days 3-4)

Agent 3: Full-Stack Developer (Step 9)

Task(
subagent_type="codi-fullstack-developer",
description="Implement comprehensive admin dashboard API endpoints",
prompt="""
Implement 31 admin endpoints for dashboard management:

1. Admin Authentication:
- @admin_required decorator
- JWT + is_staff/is_superuser check
- Audit logging for all admin actions

2. Organization Management (6 endpoints):
- GET /admin/organizations (list with pagination)
- GET /admin/organizations/{id} (details)
- POST /admin/organizations (create)
- PATCH /admin/organizations/{id} (update)
- DELETE /admin/organizations/{id} (delete)
- GET /admin/organizations/search (search by name/email)

3. License Management (10 endpoints):
- GET /admin/licenses (list with filtering)
- GET /admin/licenses/{key} (details)
- POST /admin/licenses (create manually)
- PATCH /admin/licenses/{key} (update)
- DELETE /admin/licenses/{key} (revoke)
- POST /admin/licenses/{key}/activate
- POST /admin/licenses/{key}/deactivate
- GET /admin/licenses/{key}/sessions (view active)
- POST /admin/licenses/{key}/sessions/{id}/terminate
- GET /admin/licenses/search

4. User Management (7 endpoints):
- GET /admin/users (list with pagination)
- GET /admin/users/{id} (details)
- POST /admin/users (create)
- PATCH /admin/users/{id} (update)
- DELETE /admin/users/{id} (delete)
- POST /admin/users/{id}/suspend
- POST /admin/users/{id}/unsuspend

5. Analytics (5 endpoints):
- GET /admin/analytics/overview (dashboard metrics)
- GET /admin/analytics/revenue (MRR, ARR, churn)
- GET /admin/analytics/licenses (seat utilization)
- GET /admin/analytics/users (growth metrics)
- GET /admin/analytics/sessions (activity)

6. Billing (3 endpoints):
- GET /admin/billing/transactions
- GET /admin/billing/subscriptions
- POST /admin/billing/refunds

7. Pagination & Filtering:
- Standard pagination (page, page_size)
- Search and filtering on all list endpoints
- Consistent response format

8. Testing:
- Unit tests for all endpoints
- Authorization tests (admin vs. non-admin)
- Pagination tests
- Analytics calculation tests
- 80%+ coverage

Reference: All previous PHASE1-STEP* documents for data models
Target: 1,200 lines implementation + 500 lines tests
Completion: 12-14 hours
Dependencies: Steps 7-8 complete (needs live session data for analytics)
"""
)

Continuous Tasks (All Phases)

Test Engineer: Comprehensive Testing

Task(
subagent_type="codi-test-engineer",
description="Create comprehensive test suite for Steps 7-9",
prompt="""
Develop and execute comprehensive testing:

1. Unit Tests:
- Step 7: SDK client, session, heartbeat (500 lines)
- Step 8: Webhook handlers, idempotency (200 lines)
- Step 9: Admin endpoints, analytics (500 lines)

2. Integration Tests:
- Step 7: Live API integration
- Step 8: Stripe CLI webhook testing
- Step 9: End-to-end admin workflows

3. Edge Cases:
- Network failures and retries
- Concurrent requests and race conditions
- Duplicate events (idempotency)
- Invalid authentication
- Missing data scenarios

4. Performance Tests:
- SDK heartbeat timing accuracy
- Admin endpoint response times
- Pagination efficiency

5. Coverage Goals:
- Overall: 80%+ coverage
- Critical paths: 95%+ coverage
- Admin endpoints: 85%+ coverage

Tools: pytest, pytest-cov, responses (HTTP mocking), Stripe CLI
Target: 1,200 lines of tests across all steps
"""
)

Documentation Writer: API Documentation

Task(
subagent_type="codi-documentation-writer",
description="Create comprehensive API documentation for Steps 7-9",
prompt="""
Generate complete API documentation:

1. SDK Documentation:
- Installation guide
- Quick start example
- API reference (all classes and methods)
- Error handling guide
- Threading considerations

2. Webhook Documentation:
- Stripe webhook setup guide
- Event types and handlers
- Idempotency guarantees
- Testing with Stripe CLI
- Troubleshooting guide

3. Admin API Documentation:
- Authentication requirements
- Endpoint reference (31 endpoints)
- Pagination and filtering guide
- Analytics metrics explanation
- Example requests/responses

4. Integration Guides:
- SDK integration in CODITECT CLI
- Webhook deployment checklist
- Admin dashboard frontend integration

Deliverables:
- SDK_README.md (SDK usage guide)
- WEBHOOK_SETUP_GUIDE.md (Stripe integration)
- ADMIN_API_REFERENCE.md (Admin endpoints)
- INTEGRATION_GUIDES.md (End-to-end flows)
"""
)

Execution Timeline

Day 1: Phase A Start (Parallel Implementation)

Morning (4 hours):

  • Agent 1: SDK package setup + LicenseClient implementation
  • Agent 2: Webhook endpoint + signature verification

Afternoon (4 hours):

  • Agent 1: Session management + heartbeat threading
  • Agent 2: Event handlers (payment success, failure, cancellation)

Evening (2 hours):

  • Agent 1: Exception handling + retry logic
  • Agent 2: Email template integration

Status Check:

  • Step 7: ~60% complete
  • Step 8: ~70% complete

Day 2: Phase A Completion

Morning (4 hours):

  • Agent 1: SDK testing (unit + integration)
  • Agent 2: Webhook testing (Stripe CLI)

Afternoon (3 hours):

  • Agent 1: SDK documentation + PyPI packaging
  • Agent 2: Idempotency testing + edge cases

Evening (1 hour):

  • Integration verification
  • Code review
  • Phase A sign-off

Status Check:

  • Step 7: ✅ 100% complete
  • Step 8: ✅ 100% complete

Day 3: Phase B Start (Sequential Implementation)

Morning (4 hours):

  • Agent 3: Admin middleware + organization endpoints

Afternoon (4 hours):

  • Agent 3: License management endpoints

Evening (2 hours):

  • Agent 3: User management endpoints

Status Check:

  • Step 9: ~50% complete

Day 4: Phase B Completion

Morning (4 hours):

  • Agent 3: Analytics endpoints + calculations

Afternoon (3 hours):

  • Agent 3: Billing endpoints + testing

Evening (2 hours):

  • Agent 3: Comprehensive testing + documentation

Status Check:

  • Step 9: ✅ 100% complete

Final Review (1-2 hours)

  • ✅ All tests passing (196 existing + ~1,200 new = ~1,400 tests)
  • ✅ Code coverage ≥80% overall
  • ✅ Documentation complete
  • ✅ Integration verified end-to-end
  • ✅ project-plan.md updated
  • ✅ tasklist.md updated

Total Timeline: 3-4 days (26-32 hours of development)


Success Verification Checklist

Step 7: Client SDK

Functional Tests:

  • SDK can acquire license seat successfully
  • Heartbeat sends every 2 minutes automatically
  • Graceful release on normal exit
  • Graceful release on SIGTERM signal
  • Graceful release on SIGINT (Ctrl+C)
  • Retry logic handles transient API failures
  • Clear error messages for all failure modes
  • No memory leaks in heartbeat thread

Technical Tests:

  • Unit tests: 80%+ coverage
  • Integration tests: All API endpoints tested
  • Threading tests: Heartbeat timing verified
  • Edge case tests: Network failures, API errors
  • Performance: <100ms overhead for heartbeat

Documentation:

  • README.md with installation and examples
  • API reference for all public methods
  • Error handling guide
  • PyPI package published

Step 8: Renewal Automation

Functional Tests:

  • Webhook receives Stripe events successfully
  • Signature verification prevents spoofed webhooks
  • Payment success → License renewed (valid_until + 30 days)
  • Payment failure (1st attempt) → Warning email sent
  • Payment failure (2nd attempt) → License suspended
  • Subscription cancelled → License deactivated
  • All email notifications sent correctly

Technical Tests:

  • Unit tests: 85%+ coverage
  • Idempotency tests: Duplicate events handled safely
  • Integration tests: All webhook types tested with Stripe CLI
  • Atomic transactions prevent race conditions
  • LicenseRenewalLog prevents duplicate renewals

Documentation:

  • Webhook setup guide
  • Event handler documentation
  • Testing procedures with Stripe CLI
  • Troubleshooting guide

Step 9: Admin Dashboard

Functional Tests:

  • Admin authentication enforced on all endpoints
  • Non-admin users cannot access endpoints (403 Forbidden)
  • All 31 endpoints return correct responses
  • Pagination works on all list endpoints
  • Search and filtering functional
  • Analytics calculations accurate (MRR, ARR, churn, utilization)
  • Manual license activation/deactivation works
  • Session termination functional

Technical Tests:

  • Unit tests: 80%+ coverage
  • Authorization tests (admin vs. non-admin)
  • Pagination tests (page boundaries)
  • Analytics calculation tests (edge cases)
  • Performance: List endpoints <500ms

Documentation:

  • Admin API reference (31 endpoints)
  • Pagination and filtering guide
  • Analytics metrics explanation
  • Frontend integration guide

Overall Integration

End-to-End Flow:

  • User registers → Pays → Receives license
  • User installs SDK → Acquires seat
  • Heartbeats send automatically
  • Monthly payment → License renews automatically
  • Payment failure → Suspension after grace period
  • Admin can view all data in dashboard
  • Admin can manage licenses manually

Production Readiness:

  • All tests passing (1,400+ tests)
  • Code coverage ≥80%
  • No security vulnerabilities (admin auth, webhook signature)
  • Performance acceptable (<1s response times)
  • Error handling comprehensive
  • Logging comprehensive (info, warning, error)
  • Documentation complete

Project Management:

  • project-plan.md updated with completion status
  • tasklist.md checkboxes updated
  • Git commits with conventional commit messages
  • PHASE1-STEPS-7-9-implementation-summary.md created

Risk Mitigation

Risk 1: SDK Threading Issues

Risk: Heartbeat thread may not terminate cleanly, causing zombie processes.

Likelihood: Medium Impact: High (bad user experience)

Mitigation:

  1. Use daemon threads (automatically killed on exit)
  2. Implement explicit stop() method
  3. Register atexit handlers
  4. Test with kill -9 (hard kill) scenarios
  5. Add timeout to thread join (5 seconds max)

Acceptance Criteria:

  • Thread terminates within 5 seconds on normal exit
  • No zombie processes after force kill
  • Seat released correctly in all scenarios

Risk 2: Webhook Idempotency Failures

Risk: Duplicate Stripe events may cause double renewals or incorrect state.

Likelihood: High (Stripe guarantees at-least-once delivery) Impact: Critical (incorrect billing, license state)

Mitigation:

  1. Database uniqueness constraints (invoice_id)
  2. Check-before-act pattern in all handlers
  3. Atomic transactions with select_for_update
  4. Comprehensive idempotency tests
  5. LicenseRenewalLog table for audit trail

Acceptance Criteria:

  • Same event processed 5 times → Only 1 renewal
  • No race conditions under concurrent webhook load
  • All duplicate events logged but skipped

Risk 3: Admin API Performance Degradation

Risk: Analytics queries may be slow with large datasets (10K+ licenses).

Likelihood: Medium Impact: Medium (slow dashboard)

Mitigation:

  1. Database indexes on frequently queried fields
  2. Pagination on all list endpoints
  3. Caching for analytics (Redis, 5-minute TTL)
  4. Query optimization (select_related, prefetch_related)
  5. Background job for complex analytics (Celery)

Acceptance Criteria:

  • List endpoints: <500ms with 10K records
  • Analytics endpoints: <2s with caching
  • Dashboard loads in <3s total

Risk 4: Timeline Slippage

Risk: Implementation takes longer than 3-4 days.

Likelihood: Medium Impact: High (delays first paying customer)

Mitigation:

  1. Start with parallel execution (Steps 7+8)
  2. Daily progress check-ins
  3. Reduce scope if needed (defer low-priority admin endpoints)
  4. Use AI-assisted development for faster coding
  5. Focus on critical path (Steps 7-8 more important than 9)

Acceptance Criteria:

  • Phase A complete by end of Day 2
  • If Day 3 slips, defer non-critical admin endpoints
  • Minimum viable: Steps 7-8 complete, Step 9 at 60%

Risk 5: Integration Bugs

Risk: SDK doesn't work correctly with CODITECT CLI in production.

Likelihood: Low Impact: Critical (blocks usage)

Mitigation:

  1. Integration tests with live API
  2. Manual testing with actual CODITECT CLI
  3. Staging environment deployment
  4. Gradual rollout (beta users first)
  5. Rollback plan ready

Acceptance Criteria:

  • SDK works in CODITECT CLI staging environment
  • Manual end-to-end test successful
  • Beta user validation before GA

Post-Completion Actions

Immediate (Same Day)

  1. Update Documentation:

    • Update project-plan.md (Phase 1 complete: 9/9 steps)
    • Update tasklist.md (mark all Step 7-9 tasks complete)
    • Create PHASE1-STEPS-7-9-implementation-summary.md
  2. Git Operations:

    • Commit all code with conventional commits
    • Tag release: v1.0.0-phase1-complete
    • Push to GitHub
    • Create PR for review
  3. Deploy to Staging:

    • Deploy backend to staging environment
    • Publish SDK to PyPI (or internal registry)
    • Configure Stripe webhooks for staging

Short-Term (Within 1 Week)

  1. Testing & Validation:

    • Manual end-to-end testing in staging
    • Beta user testing (5-10 users)
    • Performance testing under load
    • Security audit (webhook signatures, admin auth)
  2. Monitoring Setup:

    • Configure alerts for webhook failures
    • Monitor SDK heartbeat success rates
    • Track admin dashboard performance
    • Setup error tracking (Sentry)
  3. Documentation Finalization:

    • User guide for SDK installation
    • Admin dashboard user manual
    • Troubleshooting FAQ
    • Video tutorials (optional)

Medium-Term (1-2 Weeks)

  1. Production Deployment:

    • Deploy to production environment
    • Configure production Stripe webhooks
    • Publish SDK to public PyPI
    • Announce availability to beta users
  2. First Paying Customer Milestone:

    • Complete first payment flow
    • Verify license acquisition works
    • Confirm monthly renewal works
    • Collect feedback and iterate

Appendix A: Technology Stack Summary

Backend (Django REST Framework):

  • Python 3.12
  • Django 5.2.8
  • Django REST Framework
  • PostgreSQL (Cloud SQL)
  • Redis (Memorystore)
  • Cloud KMS (license signing)
  • Stripe API (payments)
  • SendGrid API (emails)

Client SDK (Python):

  • Python 3.9+ compatibility
  • requests library (HTTP client)
  • tenacity (retry logic)
  • threading (heartbeat daemon)
  • pydantic (data validation)

Testing:

  • pytest (test framework)
  • pytest-cov (coverage)
  • responses (HTTP mocking)
  • Stripe CLI (webhook testing)

Infrastructure:

  • Google Kubernetes Engine (GKE)
  • Cloud Build (CI/CD)
  • Cloud Load Balancer
  • Identity Platform (OAuth2)

Appendix B: Estimated Lines of Code

ComponentImplementationTestsDocumentationTotal
Step 7: Client SDK8005002001,500
Step 8: Renewal600200150950
Step 9: Admin APIs1,2005003002,000
Total2,6001,2006504,450

Current Codebase: ~5,300 lines + 196 tests After Steps 7-9: ~7,900 lines + 1,396 tests (~50% increase)


Appendix C: API Endpoint Summary

Existing Endpoints (Steps 1-6)

POST   /api/v1/auth/register
POST /api/v1/auth/login
POST /api/v1/auth/verify-email
POST /api/v1/subscriptions
GET /api/v1/subscriptions/{id}
GET /api/v1/licenses
GET /api/v1/licenses/{key}
POST /api/v1/licenses/{key}/sign
POST /api/v1/licenses/acquire
PATCH /api/v1/licenses/sessions/{id}/heartbeat
DELETE /api/v1/licenses/sessions/{id}

Total: 11 endpoints ✅ Complete

New Endpoints (Steps 7-9)

Step 7: None (client SDK, no new backend endpoints)

Step 8: Webhooks

POST   /api/v1/webhooks/stripe

Total: 1 endpoint

Step 9: Admin Dashboard

# Organizations (6)
GET /api/v1/admin/organizations
GET /api/v1/admin/organizations/{id}
POST /api/v1/admin/organizations
PATCH /api/v1/admin/organizations/{id}
DELETE /api/v1/admin/organizations/{id}
GET /api/v1/admin/organizations/search

# Licenses (10)
GET /api/v1/admin/licenses
GET /api/v1/admin/licenses/{key}
POST /api/v1/admin/licenses
PATCH /api/v1/admin/licenses/{key}
DELETE /api/v1/admin/licenses/{key}
POST /api/v1/admin/licenses/{key}/activate
POST /api/v1/admin/licenses/{key}/deactivate
GET /api/v1/admin/licenses/{key}/sessions
POST /api/v1/admin/licenses/{key}/sessions/{id}/terminate
GET /api/v1/admin/licenses/search

# Users (7)
GET /api/v1/admin/users
GET /api/v1/admin/users/{id}
POST /api/v1/admin/users
PATCH /api/v1/admin/users/{id}
DELETE /api/v1/admin/users/{id}
POST /api/v1/admin/users/{id}/suspend
POST /api/v1/admin/users/{id}/unsuspend

# Analytics (5)
GET /api/v1/admin/analytics/overview
GET /api/v1/admin/analytics/revenue
GET /api/v1/admin/analytics/licenses
GET /api/v1/admin/analytics/users
GET /api/v1/admin/analytics/sessions

# Billing (3)
GET /api/v1/admin/billing/transactions
GET /api/v1/admin/billing/subscriptions
POST /api/v1/admin/billing/refunds

Total: 31 endpoints

Grand Total After Phase 1: 43 endpoints


Appendix D: Success Metrics

Phase 1 Completion Criteria:

MetricTargetVerification
Steps Complete9/9 (100%)All steps implemented and tested
Lines of Code~7,900find . -name "*.py" | xargs wc -l
Test Count1,396+ testspytest --collect-only
Test Coverage≥80%pytest --cov
API Endpoints43 totalOpenAPI schema
Documentation100%All endpoints documented
First CustomerBy Dec 22Payment → License → Usage flow complete

Quality Gates:

  • ✅ All tests passing
  • ✅ No security vulnerabilities
  • ✅ Performance acceptable (<1s API responses)
  • ✅ Error handling comprehensive
  • ✅ Logging configured
  • ✅ Admin authentication enforced
  • ✅ Webhook idempotency verified
  • ✅ SDK integration tested

Document Status: Draft v1.0 - Ready for Implementation Next Action: Begin Phase A (Parallel Implementation) with Agent 1 and Agent 2 Target Completion: December 5, 2025 (4 days from December 1) Critical Path: Steps 7-8 (parallel) → Step 9 (sequential)