Skip to content

Admin Scripts & Management

Seed scripts, migrations, mongosh commands, and bash helpers for managing Voicex.


Seed Scripts

Voicex requires seed data to function. Run these scripts in order after setting up your environment.

1. Seed Plans

Creates the 4 standard plans (free, starter, pro, enterprise) with model access, limits, pricing, and features.

bash
bash scripts/seed-plans.sh

Source: backend/src/scripts/seed-plans.ts

What it does:

  • Creates plans if they don't exist
  • Backfills features field on existing plans if missing
  • Never modifies existing plan data (idempotent)

2. Seed Global Providers

Creates platform-owned providers with encrypted credentials from your env vars.

bash
bash scripts/seed-global-providers.sh

Source: backend/src/scripts/seed-global-providers.ts

Reads these env vars:

  • GROQ_API_KEY → Groq LLM provider
  • OPENAI_API_KEY → OpenAI LLM + TTS providers
  • ELEVENLABS_API_KEY → ElevenLabs TTS provider
  • DEEPGRAM_API_KEY → Deepgram STT provider
  • OLLAMA_BASE_URL → Ollama LLM provider (no key needed)
  • ENCRYPTION_KEY → for encrypting credentials

Creates 7 providers (all with orgId: null):

CategoryKeyName
llmollamaOllama (Local)
llmgroqGroq Cloud
llmopenaiOpenAI
ttsedgeEdge TTS (Free)
ttselevenlabsElevenLabs
ttsopenaiOpenAI TTS
sttdeepgramDeepgram

Skips existing providers. Safe to run multiple times.

3. Seed Provider Registry + Test Data

Seeds the provider registry catalog and creates a test organization with a test user and agent.

bash
bash scripts/seed.sh

Source: backend/src/scripts/seed.ts

What it does:

  1. Ensures all database indexes
  2. Seeds the provider_registry collection (catalog of supported provider types)
  3. Runs migrations (org plans, agent configs, client providers)
  4. Creates a test organization:
    • Org: TestOrg (pro plan, status: active)
    • User: a@a.dev / 12345678 (admin)
    • Agent: Default Agent (uses Ollama LLM, Edge TTS, Deepgram STT)
    • API Key: printed to console

Migrations

The seed.ts script includes several migration functions that run automatically:

migrateOrgPlans

Migrates organizations from old plan string field to planId ObjectId reference.

Before: { plan: "pro", limits: {...} }
After:  { planId: ObjectId("..."), limits: {...} }

migrateAgents

Migrates agents from old embedded config to relational FK structure.

Before: { llm: { provider: "groq", model: "llama-3.3-70b-versatile" }, voice: {...} }
After:  { llmProviderId: ObjectId("..."), llmModelId: "llama-3.3-70b-versatile", llmConfig: {...} }

migrateClientProviders

Moves documents from the deprecated client_providers collection into the unified providers collection.

All migrations are idempotent — they skip records that have already been migrated.


MongoDB Admin Commands

Connect to MongoDB:

bash
# Local
mongosh mongodb://localhost:27017/voicex

# Docker
docker exec -it voicex-mongo-1 mongosh voicex

# Remote / Atlas
mongosh "mongodb+srv://<user>:<pass>@cluster.mongodb.net/voicex"

Organization Management

View pending accounts:

javascript
db.organizations.find({ status: "pending" }).pretty()

Activate by email:

javascript
db.organizations.updateOne(
  { ownerEmail: "client@company.com" },
  { $set: { status: "active", updatedAt: new Date() } }
)

Activate by org name:

javascript
db.organizations.updateOne(
  { name: "Acme Corp" },
  { $set: { status: "active", updatedAt: new Date() } }
)

Suspend a client:

javascript
db.organizations.updateOne(
  { ownerEmail: "client@company.com" },
  { $set: { status: "pending", updatedAt: new Date() } }
)

Bulk activate all pending:

javascript
db.organizations.updateMany(
  { status: "pending" },
  { $set: { status: "active", updatedAt: new Date() } }
)

Plan Management

Change a client's plan:

javascript
// Get the target plan
const plan = db.plans.findOne({ slug: "pro" })

// Update the org
db.organizations.updateOne(
  { ownerEmail: "client@company.com" },
  { $set: { planId: plan._id, updatedAt: new Date() } }
)

View all plans:

javascript
db.plans.find({}, { slug: 1, name: 1, "limits": 1, "features": 1 }).pretty()

Create a custom plan for a specific client:

javascript
db.plans.insertOne({
  slug: "acme-custom",
  name: "Acme Custom",
  description: "Custom plan for Acme Corp",
  custom: true,
  public: false,
  pricing: { monthly: 199, annual: 1990, maxDiscountPercent: 20 },
  limits: { maxAgents: 50, maxConcurrentCalls: 100, maxCallDurationSec: 7200, maxMonthlyMinutes: 50000 },
  models: {
    llm: ["ollama/llama3.2:3b", "groq/llama-3.3-70b-versatile", "openai/gpt-4o-mini", "openai/gpt-4o"],
    tts: ["edge/en-US-AriaNeural", "elevenlabs/21m00Tcm4TlvDq8ikWAM", "openai/alloy"],
    stt: ["deepgram/nova-2"]
  },
  features: { customProviders: true, maxCustomProviders: 20 },
  createdAt: new Date(),
  updatedAt: new Date()
})

API Key Management

List active keys for a client:

javascript
const org = db.organizations.findOne({ ownerEmail: "client@company.com" })
db.api_keys.find({ orgId: org._id, revokedAt: null }).pretty()

Revoke all keys for an org:

javascript
const org = db.organizations.findOne({ ownerEmail: "client@company.com" })
db.api_keys.updateMany(
  { orgId: org._id, revokedAt: null },
  { $set: { revokedAt: new Date() } }
)

Provider Management

View global providers:

javascript
db.providers.find({ orgId: null }, { credentials: 0 }).pretty()

View client providers for an org:

javascript
const org = db.organizations.findOne({ ownerEmail: "client@company.com" })
db.providers.find({ orgId: org._id }, { credentials: 0 }).pretty()

Disable a global provider:

javascript
db.providers.updateOne(
  { orgId: null, providerKey: "groq", category: "llm" },
  { $set: { active: false, updatedAt: new Date() } }
)

Re-enable:

javascript
db.providers.updateOne(
  { orgId: null, providerKey: "groq", category: "llm" },
  { $set: { active: true, updatedAt: new Date() } }
)

Agent Inspection

List agents with their provider references:

javascript
const org = db.organizations.findOne({ ownerEmail: "client@company.com" })
db.agents.find({ orgId: org._id }, {
  name: 1, active: 1, llmProviderId: 1, llmModelId: 1,
  ttsProviderId: 1, ttsModelId: 1, sttProviderId: 1
}).pretty()

Find agents using a specific provider:

javascript
const providerId = ObjectId("YOUR_PROVIDER_ID")
db.agents.find({
  $or: [
    { llmProviderId: providerId },
    { ttsProviderId: providerId },
    { sttProviderId: providerId }
  ]
}, { name: 1, orgId: 1 }).pretty()

Usage & Stats

Total usage for a client:

javascript
const org = db.organizations.findOne({ ownerEmail: "client@company.com" })
db.daily_usage.aggregate([
  { $match: { orgId: org._id } },
  { $group: {
    _id: null,
    totalCalls: { $sum: "$calls" },
    totalMinutes: { $sum: "$minutes" },
    totalTokens: { $sum: "$llmTokens" }
  }}
])

Active calls right now:

javascript
db.calls.find({ status: "active" }).pretty()

Password Reset

No self-service password reset yet. Manual process:

bash
# Generate hash for temporary password
node -e "
const {scryptSync, randomBytes} = require('crypto');
const salt = randomBytes(16).toString('hex');
const hash = scryptSync('TempPass123!', salt, 64).toString('hex');
console.log(salt + ':' + hash);
"
javascript
db.users.updateOne(
  { email: "client@company.com" },
  { $set: { passwordHash: "<output_from_above>" } }
)

Delete a Client (Irreversible)

javascript
const org = db.organizations.findOne({ ownerEmail: "client@company.com" })
const orgId = org._id

db.calls.deleteMany({ orgId })
db.agents.deleteMany({ orgId })
db.api_keys.deleteMany({ orgId })
db.daily_usage.deleteMany({ orgId })
db.providers.deleteMany({ orgId })  // client providers only
db.users.deleteMany({ orgId })
db.organizations.deleteOne({ _id: orgId })

print("Deleted org:", org.name)

Database Health Check

javascript
print("Organizations:", db.organizations.countDocuments())
print("  - active:   ", db.organizations.countDocuments({ status: "active" }))
print("  - pending:  ", db.organizations.countDocuments({ status: "pending" }))
print("Users:        ", db.users.countDocuments())
print("Agents:       ", db.agents.countDocuments())
print("Providers:    ", db.providers.countDocuments())
print("  - global:   ", db.providers.countDocuments({ orgId: null }))
print("  - client:   ", db.providers.countDocuments({ orgId: { $ne: null } }))
print("Plans:        ", db.plans.countDocuments())
print("Calls total:  ", db.calls.countDocuments())
print("Calls active: ", db.calls.countDocuments({ status: "active" }))
print("API keys:     ", db.api_keys.countDocuments({ revokedAt: null }))

Quick Reference

TaskCommand
Seed plansbash scripts/seed-plans.sh
Seed providersbash scripts/seed-global-providers.sh
Seed test databash scripts/seed.sh
Activate clientdb.organizations.updateOne({ ownerEmail: "..." }, { $set: { status: "active" } })
Change planGet plan by slug, then update org's planId
Disable providerdb.providers.updateOne({ providerKey: "..." }, { $set: { active: false } })
Find agents for providerdb.agents.find({ $or: [{ llmProviderId: id }, ...] })
Health checkRun the queries in the health check section
Delete clientRun the deletion block (irreversible)

Built with Deepgram, Groq, and ElevenLabs.