Platform Admin Manual

Setup and operations reference for system administrators running the Trenvar platform.

PART ONE

Foundations

Before you touch a single tenant, understand who you are in the system, what you control, and what you don't.

Chapter 1 — Your Role as a Trenvar Employee

If you're reading this, you work for Trenvar (the platform company), not for a tenant. Your job is to make sure tenants can run their warehouses; not to run their warehouses for them.

What you'll do

  • Onboard new tenants — provision their account, set up their owner login, walk them through first steps.
  • Manage their lifecycle — suspend, resume, archive when needed.
  • Configure their plan and modules.
  • Run the platform's monthly billing cycle (charge tenants what they owe).
  • Watch the audit log and analytics for unusual activity.
  • Respond to support tickets and incidents.

What you won't do

  • Run a tenant's day-to-day operations (their staff does that).
  • See inside a tenant's data unless you impersonate (and impersonation is logged + restricted).
  • Set per-customer pricing inside a tenant (the tenant's company_admin does that).
Mental model
Think of yourself as the building manager of an office tower. You don't run the businesses inside the suites — you keep the lights on, manage the leases, and step in when the fire alarm goes off.

Chapter 2 — Platform vs. Tenant

Trenvar has two entirely separate worlds. They share infrastructure but the data, controls, and visibility are different.

Platform world

  • Database collection: platformTenants/*, platformAudit/*.
  • Console: /console/owner/*.
  • Roles: system_admin (only).
  • Permissions start with platform.*.
  • What it controls: tenant lifecycle, module enablement, platform billing.

Tenant world

  • Database collection: tenants/{tenantId}/*.
  • Console: /console/business/*, /console/operator/*, etc.
  • Roles: company_admin, operations_manager, operator, driver, customer_service, accounting, customer_*.
  • Permissions start with tenant.*, wms.*, dispatch.*, etc.
  • What it controls: warehouse, fulfillment, billing of downstream customers, etc.
Don't confuse "the tenant's customer" with "our tenant"
Our customer is the tenant. Their customer is a downstream party using their warehouse. When someone says "the customer is mad," ask which level.

Chapter 3 — Logging In to the Owner Console

Getting your account

Your manager creates your account in platformUsers with role system_admin. You'll receive a Firebase invite email. Set a password and you're in.

The owner console URL

Production: www.trenvar.com/owner/login. After signing in you land at /console/owner/tenants by default.

Treat your owner credentials like nuclear codes
A compromised system_admin account can suspend tenants, change pricing, impersonate users, and read security events. Use a strong unique password. Use a password manager. Never share. Report any suspicious activity immediately.

Chapter 4 — What system_admin Can and Cannot Do

Can

PermissionWhat it lets you do
platform.tenants.list / readSee every tenant.
platform.tenants.createCreate new tenants.
platform.tenants.updateEdit tenant fields including modules, owner login, status.
platform.tenants.suspendSuspend tenants.
platform.entitlements.configureToggle OSes/addons on or off per tenant.
platform.billing.read / updateSee and edit platform billing — what we charge tenants.
platform.analytics.readSee MRR, ARR, plan mix, churn.
platform.impersonation.startStart an impersonation session into a tenant.
platform.impersonation.write_enableEnable WRITE during impersonation (extra dangerous).
platform.security.readRead security events.
audit.security_events.readSame.

Cannot

  • Read or write tenant business data without impersonation.
  • Set tenant-internal user roles (company_admin does that).
  • Configure customer-specific pricing inside a tenant.
  • Modify another platform user's role without elevation.
PART TWO

Tenant Onboarding

From "lead converted" or "manual provisioning request" to "tenant is up and running."

Chapter 5 — The Trial Signup Flow (Customer's Path)

Most tenants come in via self-serve trial. This is what they experience.

  1. Visitor lands on the Trenvar website and clicks "Start Free Trial."
  2. Form: company name, email, password.
  3. Submit goes to POST /api/public/trial-signup.
  4. Backend creates a trialSignup record with signupSource: "public_trial", encrypts password, redirects to Stripe Checkout in setup mode (collects card, no charge).
  5. Customer enters card. Stripe returns to /trial/activation?signupId=...&session_id=....
  6. Stripe webhook hits /api/billing/stripe/webhook. Backend creates the actual tenant in trialing status.
  7. Customer logs in for the first time and lands at /console/business/settings/company.

Your involvement

Usually none — it's fully automated. You only step in when:

  • The customer reports the activation didn't work.
  • The card was declined and you need to follow up.
  • The trial signup landed in pending_approval (we have a manual gate enabled).
  • The customer wants to skip self-serve and have you provision them.

Chapter 6 — Provisioning a Tenant Manually

Sometimes you create a tenant by hand — an enterprise sales handoff, an internal test, a partner.

Where
/console/owner/tenants → Create Tenant
  1. Click Create Tenant.
  2. Fill the form:
    • Company Name — full legal name.
    • Company Slug — short URL-safe ID. Lowercase. Cannot change after creation.
    • Tax ID — optional but recommended for billing.
    • Address — street, city, state, zip, country.
    • Domain — their primary domain, used for email.
    • Contact Name + Email — primary contact at the tenant.
    • Plan — pick a plan that turns on the right OSes.
    • Free Platform Access — tick if they don't pay us (internal/partner).
  3. Click Create. Tenant status starts as pending_approval (or active if you have auto-approve on).
Slug naming
Use the customer's primary brand. Lowercase. Hyphens not underscores. Example: acme-logistics. They cannot change this after onboarding.

Chapter 7 — Setting Up the Owner Login

A tenant exists, but no one can log in until you set up their owner login (their first company_admin user).

Where
/console/owner/tenants/[tenantId] → Credentials section

Check current state

The tenant detail page shows:

  • loginStatus: configured or not_configured.
  • ownerLoginUid, ownerLoginEmail: who their admin is.
  • loginUrl: where they log in.

Create the owner login

  1. Click Set Up Owner Login.
  2. Enter:
    • Email — their admin's email (matches Contact Email if you provisioned).
    • Display Name — their full name.
    • Password — leave blank to auto-generate, or set one.
  3. Submit. The API returns:
    • temporaryPassword if you didn't set one.
    • passwordGenerated: true/false.
  4. Send the credentials to the customer via secure channel (encrypted email, password manager share — not Slack, not plain email).
Never put a password in plain Slack/email
Use 1Password sharing, encrypted email, or a phone call. Document who you sent it to and when.

Reset password for an existing owner

  1. From the tenant detail, find the credentials section.
  2. Click Reset Owner Password.
  3. Enter the existing UID or email + new password.
  4. Submit. Send them the new password securely.

Chapter 8 — Approving or Rejecting Pending Tenants

If your platform has manual approval enabled, every signup lands in pending_approval.

Reasons to reject

  • Sketchy company name or contact.
  • Disposable email domain.
  • Already known fraud signal.
  • Industry doesn't match Trenvar's target.

Workflow

  1. Filter tenants by status = pending_approval.
  2. Open one. Review company info, contact, signup source.
  3. Either click Approve (status → active) or Reject (status → rejected) with a reason.

Chapter 9 — The New-Tenant Onboarding Checklist

A reliable script you can hand to every new tenant — keeps onboarding consistent.

#StepWho does it
1Provision tenant + owner loginYou (system_admin)
2Send credentials securelyYou
3Customer logs in for first timeCustomer's company_admin
4Complete company profile + brandingCustomer
5Set up email provider (Resend) — optional but recommendedCustomer
6Invite their team (operators, accounting, etc.)Customer's company_admin
7Create warehouse locationsCustomer
8Build Item MasterCustomer
9Configure Service CatalogCustomer
10Configure Pricing Rules (if 3PL OS on)Customer
11Configure storage rules (if 3PL OS on)Customer
12Configure tax regionsCustomer
13Create AWB provider env (if Air Cargo OS on)You + Customer
14Run a test pre-alert → receive → put away → invoiceCustomer
15Verify with you on a 30-min check-in callYou + Customer
Send them the OS guides
After step 2, email them the relevant guides: TRENVAR_FOUNDATIONS.html plus the per-OS guides for the OSes they have.

Full worked example — onboarding "Acme Corp" Tuesday morning

You receive a sales handoff Monday EOD: Acme Corp signed for Warehouse + 3PL, Net 30, $899/mo. Tuesday at 9 AM you sit down to provision them.

09:00 — provision the tenant

  1. Sign in to /console/owner/tenants.
  2. Click Create Tenant.
  3. Fill: Company Name "Acme Corp", Slug "acme-corp", Tax ID "12-3456789", Address (sales handoff has it), Domain "acme.com", Contact "Jane Smith / jane@acme.com / +1-555-0100", Plan "WMS+3PL bundle", Free Platform Access OFF.
  4. Click Create. Tenant lands in status pending_approval (your tenant has manual approval on).
  5. Filter list to pending. Open Acme. Click Approve. Status flips to active.

09:10 — set up owner login

  1. From Acme's tenant detail, find the Credentials section. Status: not_configured.
  2. Click Set Up Owner Login.
  3. Email = jane@acme.com (matches the contact). Display Name = Jane Smith. Password = leave blank (auto-generate).
  4. Submit. Modal returns: temporaryPassword=Tj4kP9!mZx2v.
  5. Open 1Password. Create a shared item: title "Acme Corp — Trenvar owner login (TEMP)", note that it expires after first use, expires_at=24h, share with Jane via 1Password's secure-share URL.
  6. Send Jane an email: "Your Trenvar tenant is live at www.trenvar.com/acme-corp/login. Your temporary password is in this 1Password share: [link]. Please change it on first login."

09:20 — enable modules

  1. Acme's tenant detail → Modules section.
  2. Tick: wms_core, module_3pl. Untick the rest.
  3. Save. Audit log records the change.

09:25 — send the guides

  1. Email Jane separately: attach (or link) TRENVAR_FOUNDATIONS.html, TRENVAR_WAREHOUSE_OS.html, TRENVAR_3PL_OS.html, TRENVAR_WAREHOUSE_3PL_COMBO.html.
  2. Add note: "Read Foundations first (10 min). Then the Warehouse + 3PL combo guide for end-to-end. Reference the OS guides for specific functions."

09:30 — book a 30-min check-in for Friday

You'll walk Jane through her first test pre-alert → receive → put-away → invoice. By Friday she should have set up locations, item master, services, pricing, and storage rules. The check-in catches any blockers.

Done. Total time: 30 minutes for you. Acme is live and self-serving.

PART THREE

Tenant Lifecycle

Past onboarding, day-to-day tenant management is mostly invisible. The visible moments — suspend, resume, archive — happen here.

Chapter 10 — Suspending and Resuming

Reasons to suspend

  • Non-payment past grace period.
  • Terms-of-service violation.
  • Customer requested temporary pause.
  • Security incident requiring lockdown.

How

Where
/console/owner/tenants/[tenantId]
  1. Open the tenant.
  2. Change status from active to suspended.
  3. Enter a suspension reason (becomes part of the audit trail).
  4. Save.

Effect: all tenant users immediately get blocked at the auth layer. Their data is not deleted. Webhooks pause. Stripe charges pause.

Resuming

Same screen. Status: suspendedactive. Tenant users can log in again immediately. No data loss.

Communicate first
Always reach out to the tenant before suspending (unless it's a security incident). Surprise suspensions destroy trust.

Chapter 11 — Archiving (Off-Boarding)

When a tenant churns and won't return.

  1. Confirm cancellation in writing from the tenant's company_admin.
  2. Run a final billing cycle if there are unbilled accruals.
  3. Offer a data export (we'll do CSV exports of their key collections).
  4. In /console/owner/tenants/[tenantId], change status to archived.
  5. Set autoChargeEnabled to false.
  6. Document the off-boarding in the audit notes.
Data retention
Archived tenants stay in the database for our retention window (typically 12 months) before purge. During that window, we can resurrect them on request.

Chapter 12 — Tenant Data on Suspension and Archive

StateLoginDataWebhooksStripe billing
activeAllowedLiveActiveActive
suspendedBlockedFrozen, retainedPausedPaused
archivedBlockedRead-only retained for retention window, then purgedDisabledDisabled
rejectedBlockedMinimal record retained for compliance
PART FOUR

Plans, Modules, Pricing

How tenants pay us, and how you control what they get.

Chapter 13 — The Platform Billing Model

We charge tenants a recurring monthly fee for the modules they have enabled.

How it adds up

  • Each tenant has a set of major modules (wms_core, module_3pl, module_tms, module_ground_ops, module_b2b_storefront, module_crm).
  • Each module has a monthlyPriceCents in the platform pricing config.
  • Each tenant's monthly bill = sum of enabled modules' prices.
  • Plus optional minor modules (add-ons like advanced returns, EDI integration).

Default pricing

ModuleDefault price (USD/mo)
wms_core$299
module_3pl$300
module_tms$200
module_ground_ops$400
module_b2b_storefront$99
module_crm (sales CRM add-on)$150

OS bundles

OS BundleModules includedBundle price (USD/mo)
Warehouse OSwms_core$299
3PL OSwms_core + module_3pl$599
Transport OSwms_core + module_tms$499
Air Cargo OSwms_core + module_ground_ops$699
Commerce OSwms_core + module_b2b_storefront$398

Chapter 14 — Module Pricing Configuration

Where
/console/owner/modules

Editing the global price

  1. Open the modules screen.
  2. Edit monthlyPriceCents for any module.
  3. Click Save Pricing Config. PATCH goes to /api/owner/modules-pricing.

Changes apply at the next billing cycle. Existing tenants on the old price keep that price until you renew them or until the cycle hits.

The pricing config schema

{
  "modules": {
    "wms_core":              { "enabled": true,  "monthlyPriceCents": 29900 },
    "module_3pl":            { "enabled": true,  "monthlyPriceCents": 30000 },
    "module_tms":            { "enabled": true,  "monthlyPriceCents": 20000 },
    "module_ground_ops":     { "enabled": true,  "monthlyPriceCents": 40000 },
    "module_b2b_storefront": { "enabled": true,  "monthlyPriceCents":  9900 },
    "module_crm":            { "enabled": true,  "monthlyPriceCents": 15000 }
  },
  "minorModules": {
    "advanced_returns":      { "enabled": true,  "monthlyPriceCents":  4900 },
    "edi_integration":       { "enabled": false, "monthlyPriceCents":  9900 }
  },
  "currency": "USD",
  "invoiceIssueDay": 1,
  "paymentDueDays": 14,
  "enforceSubscription": true
}

Chapter 15 — Enabling and Disabling OSes per Tenant

A tenant's enabled modules are stored in their tenant record under majorModules.

Where
/console/owner/tenants/[tenantId]
  1. Open the tenant.
  2. Find the Modules section.
  3. Tick the modules to enable; untick to disable.
  4. Save.

What happens when you toggle

  • Server checks dependency rules (e.g., Commerce OS auto-enables Warehouse OS).
  • UI screens appear or disappear for the tenant on next page load.
  • Module entitlement caches are invalidated.
  • Audit log records the change with your UID.
  • Next platform invoice reflects the new module set.
Disabling doesn't delete data
If you disable, say, Transport OS — driver users can't log in but their data (jobs, PODs, etc.) stays. Re-enabling restores access.

Chapter 16 — Free Platform Access

Some tenants don't pay us — internal demos, partner test environments, sales-funded pilots.

  1. On the tenant record, tick Free Platform Access.
  2. Subscription cycle skips them (no Stripe charges).
  3. Document the reason in the tenant notes.
Audit free tenants quarterly
Free access tends to live forever once granted. Run a quarterly review and convert paying-but-shouldn't-be-free or remove access from stale ones.

Chapter 17 — Running the Subscription Cycle

Monthly: charge every billable tenant for what they owe.

Triggering the run

POST /api/owner/billing/subscriptions/run creates platform invoices for every active billable tenant in the current period.

What returns

{
  "billingLifecycle": {
    "periodFrom": "2026-05-01",
    "periodTo": "2026-05-31",
    "createdCount": 42,
    "skippedExistingCount": 3,
    "skippedFreeCount": 5,
    "skippedStatusCount": 2,
    "skippedNoChargeCount": 1
  }
}
CounterWhat it means
createdCountNew invoices generated.
skippedExistingCountTenant already has an invoice for this period.
skippedFreeCountTenant has freePlatformAccess.
skippedStatusCountTenant suspended/archived/rejected.
skippedNoChargeCountNo enabled modules to charge for.

Walkthrough — run the subscription cycle on the 1st of the month

Prerequisites

  • system_admin with platform.billing.update.
  • It's the 1st of the month (or you're running back-fill).
  • You've already verified module pricing config is current.

Step-by-step

  1. Sign in to /console/owner/plans.
  2. Find the Run Subscription Cycle button.
  3. Click it. A confirmation modal opens:
    • Period From → defaults to first of current month.
    • Period To → defaults to last of current month.
    • Dry Run toggle → tick to preview without creating invoices.
  4. First time? Always Dry Run first. Tick it. Click Run.
  5. Result panel shows the counts (createdCount, skippedExistingCount, etc.) without persisting anything.
  6. If counts look right (e.g., 42 expected new invoices), untick Dry Run and click Run again. Real invoices are created.
  7. Stripe auto-charge runs against tenants with autoChargeEnabled=true. Card declines flow back as invoice status "payment_failed" — investigate per tenant.

When to run

Either schedule it (cron at /api/cron/platform-subscriptions at 02:00 UTC on day 1 of each month) or run manually on the 1st of each month. Default invoiceIssueDay = 1, paymentDueDays = 14.

Don't run twice in the same period
Re-running just shows skippedExistingCount = N (no harm), but it's a sign someone's confused. Check the audit log for prior runs before triggering.
PART FIVE

Audit, Analytics, Security

Watch the platform like a hawk. Most signal lives in the audit log.

Chapter 18 — The Audit Log

Every meaningful action across the platform is logged immutably.

Where
/console/owner/audit

What's recorded

FieldNotes
actioncreate / update / delete / revoke / rotate / transition / etc.
entity_typetenant / user / pod / invoice / api_credential / api_rate_limit / abuse_protection / etc.
entity_idID of the thing acted on.
tenant_idScope.
actor_uidWho did it (user UID, or "air_awb_webhook" for system actors).
actor_roleTheir role at the time.
created_at_msWhen (server-time).
metadataAction-specific extras (retry hints, throttle reasons, etc.).

Filters

Filter by action, entity_type, tenant_id, actor_role. Use date range. Search free-text in metadata.

Chapter 19 — Throttle Awareness

The audit log surfaces rate-limit / abuse-protection events at the top of the page.

MetricWhat to do
Throttles in last 1hSpike means someone (or something) is hammering the API.
Throttles in last 24hTrend.
Max retry-after observedHow aggressively we're pushing back.

If you see a sustained throttle stream from one tenant, drill in:

  • Filter by tenant_id.
  • Look at action = "throttle" and entity_type = "api_rate_limit".
  • Check which credential/IP is hitting limits.
  • Decide: contact tenant, raise their quota, or revoke an abusive credential.

Chapter 20 — Platform Analytics

MRR, ARR, plan mix, churn, total tenants.

Where
/console/owner/analytics

Backed by /api/owner/analytics/financial-rollups. View shows:

  • MRR — total monthly recurring revenue.
  • ARR — annual run rate.
  • Active tenant count.
  • Plan mix — breakdown by which OS bundles tenants have.
  • Churn — tenants archived this period.
  • New tenants — onboarded this period.

Chapter 21 — Impersonation

Sometimes you need to log in as a tenant user to debug. This chapter walks through how, with a strong emphasis on doing it correctly.

Walkthrough — start a read-only impersonation session

Prerequisites

  • system_admin with platform.impersonation.start.
  • Explicit permission from the tenant (over email, ticket, or call) — document who gave it and when.
  • You know which user you need to impersonate and why.

Step-by-step

  1. Sign in to the Owner Console.
  2. Go to /console/owner/tenants. Find the target tenant. Click its row.
  3. Tenant detail page → Users tab.
  4. Find the user you have permission to impersonate. Click the three-dot menu next to their row.
  5. Click Impersonate. Modal opens with three fields:
    • Reason → mandatory free text. ("Debugging Jane's reported invoice issue, ticket #4521.")
    • Permission Source → mandatory dropdown: Email from user / Phone call / Ticket / Other.
    • Permission Reference → ticket number, email subject, or call timestamp.
    • Write Mode → off by default. Leave off unless you absolutely need to make changes.
  6. Click Start Impersonation. New tab opens; you're now signed in as the target user.
  7. An orange banner appears at the top of every screen: "IMPERSONATING jane@acme.com (read-only) — End session". The banner is sticky and unmissable.
  8. Reproduce the issue from the user's perspective. Take screenshots if needed.
  9. When done, click End session in the banner. You return to your owner console.

Walkthrough — write-mode impersonation (rare, dangerous)

When to use

Almost never. Only when fixing a stuck record on behalf of a customer who can't fix it themselves and explicitly asked you to. Most "fixes" should be done by the customer's company_admin under their own session, with you walking them through it.

Step-by-step

  1. You need both platform.impersonation.start AND platform.impersonation.write_enable. Most system_admins don't have the second one — only senior or designated admins do.
  2. In the Impersonate modal, tick Write Mode.
  3. Banner color changes from orange to red.
  4. Make the minimum-needed change. Document everything in your own notes (what record, before/after).
  5. End session immediately when done. Don't browse around.
  6. Email the customer afterwards: "I made the following change on your behalf at your request: [details]. Audit reference: [link]."

The audit trail (always-on, unhideable)

Every impersonation event is logged immutably with:

  • Your UID + role.
  • The impersonated user's UID + role + tenant.
  • Reason, permission source, permission reference (the fields you filled in).
  • Mode (read or write).
  • Session start + end timestamps.
  • Every action taken during the session, with full payloads.

The customer's company_admin can see every impersonation in their own tenant audit log. So can you in the platform audit. So can future-you in 3 years if there's a dispute.

Use only with permission and document everything
Don't impersonate a tenant's user without their explicit permission. If you do, you will be caught — by them, by an audit, by another admin reviewing logs. Trust takes years to build and one impersonation to lose.

Chapter 22 — Security Read Access

platform.security.read and audit.security_events.read let you see security events.

Examples:

  • Failed login attempts above threshold.
  • Unusual API access patterns.
  • Cross-tenant data access attempts (always investigated).
  • Webhook signature verification failures.

Use during incident response. Document everything you find.

PART SIX

Operations & Runbooks

Step-by-step actions for the situations that come up. Written so you can follow them at 3am.

Chapter 23 — Common Support Tickets

"My team can't log in"

  1. Confirm tenant status is active (not suspended).
  2. Confirm Firebase Auth is healthy globally.
  3. Have the user try password reset.
  4. If multi-user: check if their tenant slug or domain has changed.

"I forgot the company_admin password"

  1. Verify identity (email match, phone confirmation, contact-of-record).
  2. Use Reset Owner Password flow (Chapter 7).
  3. Send new password securely.

"Module X stopped working"

  1. Open the tenant's modules section. Is X still ticked?
  2. Check entitlement keys via Firestore inspection (or via owner console).
  3. Check audit log: was anything changed in last 24h?
  4. If a deploy went out: check for related incidents.

"I want to upgrade to a bigger plan"

  1. Tick the additional modules in the tenant's modules section.
  2. Save.
  3. Run the next subscription cycle (or wait for the scheduled one).
  4. Confirm with tenant that screens are now visible.

"I want to downgrade"

  1. Confirm in writing from company_admin.
  2. Note any data they'll lose access to (drivers can't log in if Transport OS goes off).
  3. Untick modules.
  4. Save.

Chapter 24 — Provider Outage Runbook

Resend, Stripe, AWB carrier, Shopify, or any third-party we depend on goes down.

  1. Confirm the provider's status page is showing degradation.
  2. Check audit log for related throttle/error events.
  3. Estimate impact: which tenants are affected? (e.g., AWB outage only affects Air Cargo OS tenants.)
  4. Post a notice via /console/owner notices to affected tenants.
  5. Disable any retry loops that might be aggravating the provider.
  6. Monitor; when provider recovers, resume retries.
  7. For failed deliveries during the outage: bulk replay from the deliveries queue.
  8. Post-mortem if outage was >30 minutes.

Chapter 25 — Webhook Backlog Runbook

A tenant's webhook endpoint is failing or slow, and our retry queue is backing up.

  1. Identify the affected endpoint from the audit log throttle/failure events.
  2. Open the tenant's webhooks settings (impersonate if needed).
  3. Check the Deliveries tab: how many queued? How many failed? What's the lastErrorMessage?
  4. If their endpoint is the bottleneck: contact the tenant, suggest scaling.
  5. If signature verification is failing: rotate signing secret, alert the tenant.
  6. Use API to retry in batches; avoid thundering-herd retries.
  7. For dead-letter deliveries that should be replayed: flag for manual reattempt once root cause is fixed.

Chapter 26 — Credential Leak Runbook

A tenant's API credential or webhook signing secret has been exposed (committed to public repo, posted in support ticket, leaked any other way).

  1. Confirm the leak: see the actual exposed credential.
  2. Impersonate the tenant's company_admin (with permission) and revoke the credential immediately. Add reason: "Exposed publicly on YYYY-MM-DD".
  3. Create a replacement credential with the same scope. Send it to the tenant securely.
  4. Audit the platform audit log for unusual access during the leak window.
  5. If the leak was a Resend or Stripe key, rotate at the provider as well.
  6. Document the incident: who, what, when, scope, response.
  7. Post-incident review with the tenant — how did the leak happen, how to prevent next time.

Chapter 27 — Replay Storm Runbook

An integration or test script is hammering an endpoint, generating a flood of throttled requests.

  1. Identify the source from the audit log throttle events.
  2. Disable the misbehaving endpoint or revoke the credential.
  3. Contact the integration owner (the tenant or one of their developers).
  4. Diagnose root cause (infinite loop, unbounded retry, runaway test).
  5. Re-enable when the loop is fixed.
  6. If the storm caused customer-facing pain, post-mortem.

Chapter 28 — Cross-Tenant Data Leak Runbook

Worst-case scenario: a tenant or customer reports they can see data from another tenant.

Treat this as P0
Cross-tenant or cross-customer data visibility is a critical security failure. Stop everything else.
  1. Get screenshots and exact timestamps from the reporter.
  2. Capture URL, Firestore paths, exact data they saw.
  3. Reproduce in a controlled environment (impersonate carefully if needed).
  4. Identify the offending code path. Bug or config?
  5. Patch immediately if it's a bug. Lock down config if it's config.
  6. Audit who else might have seen what (search the access logs).
  7. Notify both tenants involved.
  8. If material data was exposed, follow legal/compliance breach notification process.
  9. Post-mortem mandatory.
PART SEVEN

New Employee Cheat Sheet

If you're new — start here.

Chapter 29 — Your First Day

  1. Get your system_admin account from your manager. Set a strong password. Add to password manager.
  2. Log in to /console/owner/tenants. Browse the tenant list. Get a feel for the scale.
  3. Open one tenant. Read every section without changing anything. Understand what's there.
  4. Read TRENVAR_FOUNDATIONS.html — what your tenants are looking at.
  5. Read this manual cover-to-cover. Yes, all of it.
  6. Shadow your manager through one tenant onboarding before doing one yourself.
  7. Shadow them through one support ticket triage.
  8. Ask questions. The platform is small — anyone will help.

Chapter 30 — Common Gotchas

  • Slug is immutable. Triple-check before saving a new tenant.
  • Disabling a module hides screens but doesn't delete data. Tenant data persists across module toggles.
  • Free Platform Access is sticky. Once granted, no one ever audits it. Quarterly review.
  • Stripe webhook signing matters. If you regenerate keys, the webhook stops working until you update both ends.
  • Impersonation is logged forever. Don't be the person who shows up in someone's audit and can't explain why.
  • Suspending without warning destroys trust. Communication first.
  • "customer" is overloaded. "Trenvar's customer" = tenant. "Tenant's customer" = downstream. Always clarify.
  • The owner login email is hard to change. Get it right at provisioning.

Chapter 31 — Where to Escalate

SituationEscalate to
Cross-tenant data leakPlatform engineering lead + legal
Active credential leakSecurity team + tenant's company_admin
Suspected payment fraudFinance + Stripe
P0 incident (full outage)On-call engineer + leadership
Tenant threatening churnCustomer success + sales
"This tenant is doing something we don't allow"Trust & safety / legal
"I touched something I shouldn't have"Your manager — immediately

Appendix A — Owner Console Paths

PathScreen
/console/owner/Owner home
/console/owner/tenantsTenant list + lifecycle
/console/owner/tenants/[tenantId]Tenant detail (status, modules, owner login)
/console/owner/plansPlans + subscription run
/console/owner/modulesModule pricing config
/console/owner/auditPlatform audit log
/console/owner/analyticsFinancial rollups, MRR/ARR, plan mix

Critical APIs

EndpointPurpose
POST /api/public/trial-signupPublic trial signup intake
POST /api/billing/stripe/webhookStripe events (incoming)
GET/POST/PATCH /api/owner/tenants/[tenantId]/credentialsSet up + reset owner login
POST /api/owner/billing/subscriptions/runRun monthly subscription cycle
PATCH /api/owner/modules-pricingUpdate pricing config
GET /api/owner/auditAudit log feed
GET /api/owner/analytics/financial-rollupsMRR/ARR analytics
GET /api/cron/platform-subscriptionsCron-driven trial conversion check

Appendix B — Platform Permissions

PermissionDefault holderNotes
platform.tenants.list / readsystem_adminBrowse tenants.
platform.tenants.createsystem_adminManual provisioning.
platform.tenants.updatesystem_adminEdit tenant fields.
platform.tenants.suspendsystem_adminSuspend/resume.
platform.entitlements.configuresystem_adminToggle modules per tenant.
platform.billing.read / updatesystem_adminPlatform billing.
platform.analytics.readsystem_adminMRR/ARR/churn.
platform.impersonation.startsystem_adminBegin impersonation.
platform.impersonation.write_enablesystem_adminMake changes during impersonation. Audit-loud.
platform.security.readsystem_adminSecurity events.
audit.security_events.readsystem_adminSame.

Appendix C — Glossary (Employee Perspective)

Tenant — Our customer. One company that uses Trenvar.

Tenant's customer — A downstream customer of one of our tenants. We rarely deal with these directly.

Owner Console — The internal control plane at /console/owner/*.

system_admin — Your role. Platform-wide access.

OS bundle — A commercial package of modules (Warehouse, 3PL, Transport, Air Cargo, Commerce).

Module — A specific capability, billed individually.

Entitlement — The switch that turns a module on for a tenant.

Free Platform Access — Tenant flag that exempts them from platform billing.

Subscription Cycle — Monthly batch job that creates platform invoices for billable tenants.

Impersonation — Logging in as a tenant user (with audit trail) to debug or support.

Throttle event — Rate-limit hit. Surfaced in audit log.

Trial signup — Self-serve flow where a new tenant signs up and converts after 7 days.

Cross-tenant leak — A user seeing data outside their own tenant. Critical security incident.

Trenvar — Internal
Platform support: info@trenvar.com  ·  www.trenvar.com

End of Trenvar Platform Admin Manual  ·  v1.0  ·  May 2026
Internal use only.