Managed Seedbox Control Plane - First Implementation Slice
This is a compact implementation handoff for the accepted seedbox platform gig. It is scoped as a first technical slice, not a claim that the entire platform is complete.
Core recommendation: start with the launch-blocking pieces that make later
provisioning safe: prepaid billing state, immutable audit events, provider interface, and a
non-custodial BYOS key model. Avoid WHMCS and avoid storing customer private keys.
First Slice
| Area | Build first | Why it belongs in slice 1 | Acceptance check |
|---|---|---|---|
| Billing | seedbox_billing_accounts, top-up credit ledger, low-balance states |
Crypto cannot be auto-pulled like a card; prepaid credit is the clean subscription substitute. | Unit tests cover top-up, monthly deduction, warning threshold, suspension trigger, and idempotency. |
| Lifecycle | seedbox_resources + state machine for pending, provisioning, active, suspended, terminated, failed |
Every worker, dashboard, and support action depends on one canonical state model. | Invalid transitions reject; valid transitions emit audit events. |
| Provisioning | ProvisioningProvider interface with DigitalOcean stub implementation |
Prevents locking the UI and billing model to one host; Hetzner/Vultr can be added later. | Provider contract tests pass for create, suspend, terminate, status, rotateCredentials. |
| BYOS | Generate our per-connection keypair and show public-key onboarding command | Preserves the PRD's main security rule: never ask users to upload private keys. | Supabase stores public key + secret reference only; no private key material in app DB. |
| Audit | seedbox_audit_events append-only writer |
Required for abuse response, billing disputes, operator actions, and debugging. | All privileged actions write actor, action, resource, detail, timestamp. |
Suggested File Map
src/app/seedbox/page.tsx
src/app/api/seedbox/orders/route.ts
src/app/api/seedbox/resources/[id]/route.ts
src/app/api/byos/connections/route.ts
src/lib/seedbox/repository.ts
src/lib/seedbox/lifecycle.ts
src/lib/seedbox/billing.ts
src/lib/provisioning/index.ts
src/lib/provisioning/digitalocean.ts
src/lib/byos/keys.ts
src/lib/audit/events.ts
workers/seedbox-provisioner/index.ts
workers/seedbox-billing/index.ts
supabase/migrations/*_seedbox_control_plane.sql
Minimal Contracts
Provisioning Provider
export interface ProvisioningProvider {
create(input: ProvisioningCreateInput): Promise<ProvisioningResource>;
suspend(resourceRef: string): Promise<void>;
terminate(resourceRef: string): Promise<void>;
status(resourceRef: string): Promise<ProvisioningStatus>;
rotateCredentials(resourceRef: string): Promise<ProvisioningCredentials>;
}
Lifecycle Guard
pending -> provisioning -> active
active -> suspended -> active
active|suspended|failed -> terminating -> terminated
provisioning -> failed
Launch Blockers
- Provider policy: verify DigitalOcean, Hetzner, Vultr, or OVH allow the intended BitTorrent workload before selling seats.
- AUP/DMCA: publish Acceptable Use Policy, repeat-infringer process, and abuse response before first paid customer.
- Secrets: store private keys in KMS/Vault only; Supabase gets references, never private key material.
- Payments: provision only after CoinPayPortal webhook verification and on-chain confirmation.
Test Plan
| Test | Purpose |
|---|---|
seedbox/billing.test.ts | Credit top-up, monthly deduction, low-balance warning, suspension threshold, idempotent webhook handling. |
seedbox/lifecycle.test.ts | Valid/invalid state transitions and audit emission. |
provisioning/provider-contract.test.ts | Every provider implementation follows the same create/suspend/terminate/status contract. |
byos/keys.test.ts | Per-connection keys are generated; only public key and secret reference are persisted. |
api/seedbox-orders.test.ts | Orders cannot provision until verified payment state is present. |
Next Paid Milestone
Best next milestone: implement the Supabase migration plus the lifecycle, billing, audit, and provider-interface tests. That is a bounded $100+ engineering slice with clear pass/fail evidence and does not require production API secrets.