Platform Technical Audit

Full-stack codebase review — 3 repositories, ~56,000 lines of code, 15+ integrations

Executive Summary

This audit reviewed 3 codebases across ~56,000 lines of application code, 15+ third-party integrations, and production infrastructure. The platform has been in maintenance mode for 2+ years with a single developer — no dedicated DevOps, QA, or security support.

Overall Score (Industry Standard)
4.9 / 10
Adjusted for Team Size (1-3 devs)
5.9 / 10

The platform serves production traffic across payments, blockchain, and commerce. The system-level architecture is sound. The primary gaps — security hardening, test coverage, error monitoring, dependency updates — are all addressable without rearchitecting the system.

Scorecard

Area Score Startup-Adjusted Path to Improvement Summary
Architecture 7/10 8/10 Already strong Clean tier separation (frontend / API / workers / blockchain). One Django app has absorbed too many domains and needs splitting.
Security 4/10 6/10 Straightforward Secrets are not in repos, CORS and HMAC verification are correct. Credentials are shared across environments, tokens never expire, and 18 XSS-vulnerable components lack sanitization.
Code Quality 5/10 6/10 Incremental Consistent naming conventions and standardized API responses. God modules, 132 TODOs, 115 print statements, and near-zero type hints indicate deferred maintenance.
Blockchain 6/10 7/10 Moderate All transactions routed through async workers with a correct proposer wallet pattern. The monolithic 2,482-line handler needs splitting. No retry logic or monitoring.
Performance 5/10 6/10 Straightforward Connection pooling and selective query optimization are in place. Task routing, pagination defaults, and caching are missing — configuration-level changes.
Error Handling 4/10 5/10 Easy Consistent response format exists. No error monitoring on the backend. Exception messages leak to clients. Highest-impact fix is a single package install.
Third-Party Integrations 5/10 6/10 Time-consuming but low-risk 15+ services functional in production. Several critical dependencies are years out of date (Django 3.2 EOL, boto3 from 2019).
Infrastructure & CI/CD 4/10 5/10 Straightforward Frontend CI/CD is fully automated across 3 environments. Backend deployment is manual (SSH). E-commerce app has zero automation.
Testing 1/10 2/10 Time investment No application-level tests exist across any codebase. Testing frameworks are installed but unused.
Documentation 8/10 9/10 Already strong Dedicated docs repo with architecture guides, runbooks, and setup instructions. New developer onboarding in 1-2 hours.

Score columns:

Top Risks & Strengths

Top 5 Risks

  1. No backend error monitoring — errors are only in rotating log files on a single server instance. No alerting on failures.
  2. Django 3.2 is past end-of-life (April 2024) — no security patches for nearly 2 years.
  3. Shared credentials across all environments — a compromise in dev/staging exposes production.
  4. Zero test coverage — no safety net for any code change across any repo.
  5. No containerization or deployment automation — backend is deployed manually via SSH. No Dockerfiles, no Infrastructure as Code.

Top 5 Strengths

  1. Clean system architecture with async processing — strict layered communication (Frontend → API → Workers → Blockchain). On-chain issues don't block API responses.
  2. Comprehensive documentation — dedicated docs repo with architecture guides, operational runbooks, and setup instructions.
  3. 15+ integrations working in production — Stripe, Shopify, Flow blockchain, Firebase, AWS — all functional and correctly implemented.
  4. Security-aware auth framework — token-based auth with global default. Custom permission classes enforce domain-level access control. HMAC-verified webhooks, encrypted tokens, reCAPTCHA on auth endpoints.
  5. Frontend CI/CD and build tooling — full automated deployment to 3 environments, static analysis scanning, well-optimized build config.

Security — 4/10

Secrets Management High

Credentials are stored as config files on each server and are not committed to any repository. However:

ConcernDetailEnvironments
Shared AWS IAM keypairSame key used for S3, SES, Lambda, SQS across all environmentsAll
Shared Django SECRET_KEYPrefixed django-insecure- — identical across dev/staging/prodAll
Shared Fernet encryption keySame key encrypts Stripe Connect tokens in all environmentsAll
Shared reCAPTCHA secretIdentical across environmentsAll
No secrets managerCredentials live as files on servers — no rotation policy, no audit trailAll

Remediation: Migrate to a secrets manager (e.g., AWS Secrets Manager). Use per-environment IAM roles with least-privilege policies. Implement key rotation.

Authentication High

Remediation: Replace static tokens with JWT (with expiry + refresh). Remove BasicAuthentication. Re-enable object-level permissions.

CORS / CSRF / Headers High

SettingValueIssue
ALLOWED_HOSTS['*']Host header injection in production
CORS_ALLOW_ALL_ORIGINSFalseCorrect
X_FRAME_OPTIONS'ALLOWALL'Clickjacking on staging
DEBUGTrue (dev/staging)Debug info exposed
DEBUGFalse (prod)Correct

Production CORS whitelist is correctly scoped. Dev/staging CORS includes legacy entries (old CDN URLs, private IPs, ngrok domains).

Frontend — Hardcoded Secrets in JS Bundle Critical

Frontend — XSS via dangerouslySetInnerHTML High

18 components use dangerouslySetInnerHTML to render backend-sourced content. DOMPurify is installed but only used in 1 location. If any backend field accepts user-generated HTML, stored XSS is possible.

Remediation: Wrap all usages with DOMPurify.sanitize(). Better: sanitize server-side on write.

E-commerce App — Express Proxy High

Recommendations (Priority Order)

  1. Rotate all production secrets — move to a secrets manager.
  2. Set ALLOWED_HOSTS to specific domains in production.
  3. Sanitize all dangerouslySetInnerHTML usages with DOMPurify.
  4. Remove staging password from frontend bundle — use server-side gate.
  5. Never expose private keys as frontend env vars.
  6. Remove dev tools from production builds.
  7. Implement token expiry — replace static tokens with JWT.
  8. Restrict proxy CORS and add rate limiting.
  9. Re-enable object-level permissions.
  10. Remove BasicAuthentication from API defaults.
  11. Return generic error messages — stop leaking str(e) to clients.
  12. Review write_script_tags scope — remove if unused.

Code Quality & Architecture — 5/10

Platform Architecture

The platform has a clean separation of concerns across tiers:

Communication is strictly layered: Frontend → Backend API → Workers → Blockchain. No shortcuts exist.

The main concern is at the module level: one Django app has become a god module absorbing too many domains, and the task file contains inline business logic.

Backend App Structure

18 Django apps, 326 Python files, ~47,500 lines of code.

God Files

FileLinesIssue
Blockchain worker2,482All blockchain transaction types in one monolithic file
E-commerce views2,205Webhooks, OAuth, order logic, product management mixed
Admin config1,953All admin registrations in one file
Core models1,76424 model classes in a single file
Task definitions1,27521 Celery tasks with inline business logic

Dead Code & Debug Artifacts

Frontend

485 files, React 18 + Vite + TypeScript, atomic design pattern.

E-commerce App

24 source files, 8,285 lines. Cleanest TypeScript discipline: zero : any, zero @ts-ignore.

Recommendations

  1. Split the god app into separate Django apps (e-commerce, UGC, orders).
  2. Split the 24-class model file into per-domain model files.
  3. Extract business logic from task definitions into service modules.
  4. Fix filename typos committed to the repo.
  5. Replace bare except Exception blocks with specific exception types.
  6. Remove 115 print() statements — use logger consistently.
  7. Split inline SVGs into sprite sheet or individual assets.
  8. Decompose overloaded context provider into focused providers.
  9. Remove debug components from production builds.
  10. Move legal text out of JSX into markdown/CMS.

Blockchain — 6/10

Architecture

Django View (API request)
    │
    ├── Creates BlockchainTransaction record (status: pending)
    │
    └── Dispatches async task: blockchain_transaction.delay(txn_id)
            │
            └── Worker
                    │
                    ├── Loads transaction from DB
                    ├── Selects proposer wallet (round-robin)
                    ├── Builds Cadence transaction
                    ├── Signs with service account + proposer key
                    ├── Submits to Flow Access Node
                    ├── Waits for seal
                    └── Updates BlockchainTransaction status (success/failed)

Frontend does not execute server-side blockchain transactions. The React app uses FCL (Flow Client Library) only for wallet connection, account setup, and user-initiated purchases. All minting, airdrops, and admin operations are backend-only via workers.

Proposer Wallet Architecture

Flow requires sequential sequence_number values per account key. The platform uses 3 separate proposer wallets for concurrent transaction submission, avoiding sequence number conflicts. Selection is round-robin based on transaction ID modulo.

This correctly solves the contention problem but creates a hard ceiling of 3 concurrent blockchain operations.

Transaction Types

All types handled via a single monolithic _execute() function with if/elif branching:

TypeOperation
mint_nftMint new NFT
airdrop_nftAirdrop (mint + transfer)
batch_mintBatch mint multiple NFTs
setup_accountSet up user's Flow account
transfer_nftTransfer between accounts
update_metadataUpdate on-chain metadata
destroy_nftBurn/destroy an NFT
create_listingMarketplace listing
purchase_listingMarketplace purchase

Concerns

Recommendations

  1. Split the blockchain worker into per-transaction-type handlers.
  2. Add transaction retry logic with backoff for transient failures.
  3. Add blockchain monitoring — failed transaction rate, confirmation latency, wallet balances.
  4. Remove legacy Ethereum dependencies.
  5. Add explicit timeouts for Flow Access Node calls.
  6. Document contract deployment — contract source and deployment procedures are not in any repository.

Performance — 5/10

This audit is based on static code analysis. Production performance metrics (response times, throughput, error rates) were not reviewed.

Database

Caching

Redis is configured as the Django cache backend. Usage is minimal:

LocationWhat's CachedTTL
Analytics viewsAnalytics results1 hour
Webhook handlerE-commerce webhook dedup24 hours
Auth viewsEmail verification tokens, OTP codes48 hours

No view-level caching, no queryset caching, no template fragment caching.

Worker Configuration

3 workers x concurrency=1 = 3 concurrent tasks total

Task types competing for these 3 slots: blockchain minting (10-30s each), e-commerce sync, payment processing, email sending, analytics aggregation, notification delivery. No task routing — a long blockchain mint blocks all other tasks on that worker.

Frontend

Recommendations

  1. Add task routing — separate queues for fast (email, notifications) vs slow (blockchain, sync) tasks.
  2. Increase worker concurrency and add max-tasks-per-child for memory management.
  3. Set global DEFAULT_PAGINATION_CLASS.
  4. Reduce max_page_size to 100.
  5. Add view-level caching for public/read-heavy endpoints.
  6. Remove dev tools from production bundle.
  7. Audit serializers for N+1 queries.
  8. Add rate limiting to the proxy server.
  9. Configure global staleTime in React Query.
  10. Review server sizing and scaling — single-instance backend is a single point of failure.

Error Handling — 4/10

Backend Response Format

All API responses follow a consistent JSON envelope:

// Success
{ "statusCode": 200, "message": "success", ...data }

// Error
{ "statusCode": 400, "error": {"details": ["..."]}, "message": "Bad Request" }

A custom DRF exception handler normalizes exceptions into this format. Manual helper functions (http_400_invalid_response, etc.) are also used directly in views.

Bug

http_201_created_response sets statusCode: 201 in the body but returns HTTP 200 — the status code and body don't match.

Exception Message Leakage Medium

Several auth views return raw str(e) directly to clients, exposing database column names, Python tracebacks, or third-party SDK errors.

Logging

Two rotating file loggers (50MB, 10 backups). Logs exist only on the server instance — if the instance is terminated, logs are lost. watchtower (CloudWatch log shipping) is installed but not configured.

Error Monitoring

Recommendations

  1. Add Sentry to the backend — single highest-value monitoring improvement.
  2. Stop leaking str(e) to clients — return generic messages.
  3. Add ErrorBoundary to the e-commerce app.
  4. Fix http_201_created_response returning HTTP 200.
  5. Add a global 401 interceptor in the frontend.
  6. Configure CloudWatch log shipping (already installed).
  7. Catch specific exceptions instead of blanket except Exception.
  8. Enable Sentry Replay at 10% sample rate.
  9. Add user-facing error UI in frontend error boundaries.
  10. Remove console.* from production builds.

Third-Party Integrations — 5/10

Integration Inventory

ServiceCategoryAuth Method
Stripe (Checkout + Connect)PaymentsSecret key + webhook secret
Shopify (OAuth + webhooks + sync)CommerceOAuth2 + HMAC verification
Flow BlockchainBlockchainService account private keys
FirebasePush notificationsService account JSON
AWS S3StorageIAM access key
AWS SESEmailIAM access key
AWS LambdaImage processingIAM access key
AWS SQSMessage queueIAM access key
Google OAuth2Social authOAuth2 client
Twitter/X OAuth2Social authOAuth2 manual
Google reCAPTCHA v3Bot preventionSecret key
Google SheetsData lookupsService account
Google Cloud VisionImage analysisService account
SentryMonitoring (frontend only)DSN
WalletConnectWallet connectionProject ID

Outdated / End-of-Life Packages

PackageCurrentConcern
Django3.2.83.2 LTS reached end of life April 2024. No security patches.
boto31.10 (Nov 2019)6+ years behind. Missing security patches and features.
cryptography35.0Multiple security advisories. Current is 42.x.
Pillow8.4Known CVEs. Current is 11.x.
axios0.27.xPre-1.0. Known prototype pollution CVE.
requests2.27Pre-2.31, which fixed CVE-2023-32681 (cookie leakage).
urllib31.25Pre-2.0, multiple CVEs.
python-social-auth0.3.6Unmaintained — replaced by social-auth-core.

Blast Radius Assessment

If CompromisedImpact
AWS IAM keyAccess to all S3 buckets, SES, Lambda, SQS, potentially RDS
Stripe secret keyCharge customers, refund payments, access payment data
E-commerce API secretForge HMAC signatures, inject scripts into merchant storefronts
Blockchain wallet keysExecute unauthorized transactions, transfer/mint NFTs
Django SECRET_KEYForge session cookies, bypass CSRF, impersonate any user
Fernet keyDecrypt all stored Stripe Connect tokens
Firebase service accountFull admin access to notification database

Recommendations

  1. Rotate all credentials and move to a secrets manager with per-environment, per-service IAM roles.
  2. Upgrade Django to 4.2 LTS (or 5.x).
  3. Update boto3 to current — 6 years of drift.
  4. Update cryptography to 42.x.
  5. Update Pillow to 11.x.
  6. Audit e-commerce scopes — remove write_script_tags if unused.
  7. Replace unmaintained python-social-auth.
  8. Add Sentry to backend.
  9. Separate AWS IAM credentials per service with least-privilege policies.
  10. Update frontend deps — axios to 1.x, Sentry to 8.x.

Infrastructure & CI/CD — 4/10

Cross-Repo Comparison

CapabilityBackendFrontendE-commerce App
Automated lint in CIYes (black on push)Yes (eslint on PR)No
Static analysisYes (SonarQube, main only)Yes (SonarQube, main only)No
Automated deploymentNoYes (3 environments)No
Tests in CINoNoNo
DockerizedNoNoNo
Infrastructure as CodeNoNoNo
Rollback mechanismNoS3 versioning (if enabled)No
Health checksNoNo/health endpoint

Backend Deployment

Entirely manual: SSH into the server, git pull, supervisorctl update. No rollback mechanism, no health checks, no zero-downtime strategy.

Server stack: Nginx → uWSGI (5 workers, 300s timeout) → Django. Workers managed by Supervisor (3 workers × concurrency=1).

Frontend Deployment

Fully automated via GitHub Actions. Three workflows deploy to dev/staging/prod on branch push: checkout → build → S3 sync → CloudFront invalidation.

No test step in any deployment workflow.

Recommendations

  1. Add backend deployment pipeline (mirroring the frontend pattern).
  2. Add test steps to all deployment workflows.
  3. Add CI/CD to the e-commerce repo.
  4. Containerize the backend (Dockerfile for API + workers).
  5. Use path-specific CloudFront invalidation instead of wildcards.
  6. Update stale domain references in nginx config.
  7. Add PR templates across all repos.
  8. Consider Infrastructure as Code (Terraform) for reproducible environments.

Testing — 1/10

No meaningful application tests exist across any of the three repositories. All backend test files are empty stubs. No CI workflow runs tests.

Backend

Frontend

E-commerce App

High-Value Test Targets

AreaWhyComplexity
Payment webhook handlingMoney flows — incorrect handling means lost revenueMedium
E-commerce HMAC verificationSecurity gate — if broken, anyone can forge webhooksLow
Auth flowsCore user journey — login, signup, OTP, password resetMedium
Blockchain transaction signingAsset creation/transfer — errors mean lost NFTsHigh
Background task logicSilent failures affect subscriptions, analytics, syncMedium
Activation claim logicBusiness-critical — claim codes, airdrops, dropsMedium

Recommendations

  1. Fix yarn test — install Vitest or switch to Jest.
  2. Start with backend integration tests (payment webhooks, HMAC verification, auth flows).
  3. Add coverage tooling and set a threshold in CI (even 10%).
  4. Add test steps to CI — block merges on test failure.
  5. Expand Playwright E2E specs to cover auth, checkout, and claim flows.
  6. Add blockchain unit tests with mocked SDK responses.

Documentation — 8/10

What Exists

DocumentQuality
Technical architecture + API referenceComprehensive — all endpoints, auth patterns, inter-app relationships
Database schemaComplete — all models, relationships, schema details
Background task guideThorough — task definitions, scheduling, worker config
AWS operations runbookPractical — full inventory, deployment procedures, troubleshooting
Local dev setup guidePlatform-specific setup instructions
Architecture diagramVisual overview of system
E-commerce plugin guideArchitecture, endpoints, webhooks, deployment, billing

Onboarding Assessment

RepoTime to RunningNotes
Backend~1 hourNeeds PostgreSQL with hstore extension, DB restore, env vars
Frontend~30 minStraightforward: clone, install, configure .env, run
E-commerce app~45 minNeeds partner account, app credentials, and backend running
Full platform2-3 hoursAll repos + database + workers + cache

What's Missing

Recommendations

  1. Export OpenAPI spec and check it into the docs repo.
  2. Create a comprehensive environment variable reference.
  3. Add CONTRIBUTING.md with PR process and branching strategy.
  4. Write 3-5 retroactive ADRs for key architectural decisions.
  5. Remove commented-out code — document removed features in a changelog.
  6. Add docstrings to Django model classes.

Action Plan

Organized by priority and effort. These represent findings from the audit — not prescriptive assignments.

Sprint 1 — Quick Wins & Safety

#ActionAreaEffort
1Set ALLOWED_HOSTS to specific domainsSecurityLow
2Sanitize all dangerouslySetInnerHTML with DOMPurifySecurityLow
3Remove staging password from frontend bundleSecurityLow
4Remove dev tools from productionSecurityLow
5Add Sentry to backend (Django + Celery integrations)Error HandlingLow
6Stop leaking str(e) to API clientsError HandlingLow
7Add ErrorBoundary to e-commerce appError HandlingLow
8Fix test runner — install missing test frameworkTestingLow
9Export OpenAPI spec and check into docs repoDocumentationLow

Sprint 2-3 — Foundation

#ActionAreaEffort
10Write integration tests for payment webhooks and HMAC verificationTestingMedium
11Add test steps to frontend deploy workflowsInfrastructureLow
12Use per-environment Django SECRET_KEYSecurityLow
13Use per-environment AWS IAM credentials with least-privilegeSecurityMedium
14Migrate secrets to a secrets managerSecurityMedium
15Add backend deployment pipeline (GitHub Actions)InfrastructureMedium
16Add CI/CD to e-commerce repoInfrastructureLow
17Implement task routing — separate queues for fast vs slow tasksPerformanceMedium
18Set global pagination default and reduce max page sizePerformanceLow
19Complete activation validation (start/end dates, claim rules)Code QualityMedium
20Complete e-commerce inventory/collection sync TODOsCode QualityMedium

Sprint 4-6 — Hardening

#ActionAreaEffort
21Upgrade Django 3.2 → 4.2 LTS (or 5.x)DependenciesHigh
22Update boto3, cryptography, Pillow, requests, urllib3DependenciesMedium
23Replace static tokens with JWT (expiry + refresh)SecurityHigh
24Fix timezone handling TODOsCode QualityLow
25Add CSV validation for data importsCode QualityLow
26Fix filename typosCode QualityLow
27Remove 115 print() statementsCode QualityLow
28Configure CloudWatch log shipping (already installed)Error HandlingLow

Backlog — Refactoring & Scale

#ActionAreaEffort
29Split god app into separate Django appsCode QualityHigh
30Split 24-class model file into per-domain filesCode QualityMedium
31Extract business logic from task definitions into service modulesCode QualityMedium
32Consolidate media model into a single JSON fieldCode QualityMedium
33Re-enable object-level permissionsSecurityHigh
34Decompose overloaded context provider (579 lines)Code QualityMedium
35Split icon component (3,115 lines of inline SVG)Code QualityLow
36Remove BasicAuthentication from API defaultsSecurityLow
37Audit and remove write_script_tags scope if unusedSecurityLow
38Restrict proxy CORS and add rate limitingSecurityLow
39Split blockchain worker into per-transaction-type handlersBlockchainHigh
40Add transaction retry logic for transient failuresBlockchainMedium
41Add blockchain monitoringBlockchainMedium
42Remove legacy Ethereum dependenciesBlockchainLow
43Containerize backend (Dockerfile for API + workers)InfrastructureMedium
44Add CONTRIBUTING.md and retroactive ADRsDocumentationLow
45Move legal text out of JSX into markdown/CMSCode QualityLow
46Create environment variable reference documentDocumentationLow

Appendix: Audit Methodology

Process

This audit was conducted collaboratively between a human reviewer (platform developer with full system context) and an AI assistant over multiple sessions:

  1. Scope definition — 3 repositories, audit areas, and intended audience defined.
  2. Codebase exploration — Source files, configuration, environment files, CI/CD workflows, and dependency manifests reviewed across all repos.
  3. Finding documentation — Each area written as a standalone report with specific code patterns and configuration values.
  4. Iterative refinement — Multiple review passes corrected errors, adjusted tone, and added missing areas.
  5. Scoring — Scores assigned based on static analysis findings, calibrated against a 3-5 developer team for a platform of this complexity.

What Was Reviewed

What Was Not Reviewed