Design Specification · 2026-07-22
A ground-up, open-source successor to Freeside — the Perl/Mason billing, CRM, and provisioning platform for ISPs, WISPs, VoIP providers, and hosting companies. Freeside 4.x is ~250k lines of core Perl, ~128k lines of Mason templates, 306+ database tables, and is effectively quiescent (last upstream commit July 2024).
Primary goal: a fully operational billing system that existing Freeside 4.x deployments can migrate to safely and fully accurately. Accuracy of migrated data and generated invoices is the project's non-negotiable bar and is enforced by CI, not by QA.
Audience: open-source community project from day one, with Fibernetics as the loudly-credited creator and flagship production user. The maintainer's own production Freeside deployment is the first migration and the source of the validation corpus, but scope and interfaces are designed for general adoption.
| Decision | Choice |
|---|---|
| Stack | Go API + React/TypeScript UI + PostgreSQL |
| Architecture | Modular monolith, single binary, UI embedded |
| License | MIT |
| Migration contract | Clean new schema; one-way importer from 4.x (no schema compatibility, no sync bridge) |
| V1 scope | Billing core, CRM, payments, tax, CDR rating, provisioning exports, self-service portal, multi-company/agents, RT integration, 4.x importer |
| Ticketing | Not rebuilt — integrate with the operator's existing RT server |
| Network monitoring | Torrus dropped — modern alternatives exist (Prometheus, LibreNMS) |
| UI principle | Modern feel, familiar structure — Freeside's menu tree and workflow layout preserved so operators need no retraining |
| Build approach | Vertical slices with golden-data validation |
| Dev environment | Dedicated VM/server hosting the 4.2 reference instance, production snapshot, and golden CI runner |
| Repo | Maintainer's GitHub org; goes public once Phase 0 lands (clean-room rule and scaffold in place) |
| Web presence | ratecenter.app (primary; confirmed free 2026-07-22, register promptly) — .io/.systems/.dev also free, recommended as defensive registrations |
Freeside 4.x is AGPLv3. Ratecenter is MIT. These coexist only under a strict clean-room discipline:
Naming note (resolved 2026-07-22): the project is Ratecenter (ratecenter.app) — named for the telco rate center, the geographic unit that determines call rating, chosen for instant insider recognition with the target audience. Fibernetics is the credited creator and flagship production user ("Ratecenter, the open-source billing system for ISPs and telcos — built by Fibernetics"); a neutral product name avoids competitor-brand friction for adopting telcos and the "Freeside" mark of Freeside Internet Services, Inc. entirely. A formal trademark search is advised before public launch.
One Go binary, internally decomposed into domain modules with enforced boundaries. A domain exposes a public Go interface; internals are package-private. Domains may only call each other's public interfaces (enforced by lint/arch tests). This preserves the option to split into services later without paying the microservices tax now — and single-binary distribution is a deliberate adoption feature for the self-hosting ISP audience.
| Module | Responsibility |
|---|---|
catalog | Package definitions, pricing, price plans, tax classes |
party | Customers, contacts, service locations, agents (multi-company) |
billing | Billing runs, proration, invoice generation, credits/voids, event framework (conditions/actions) |
payments | Gateway interface + drivers, payment application, refunds, dunning/collections |
tax | Internal tax tables v1; connector interface for Avalara/SureTax-class services later |
provisioning | Export framework (queue, retry, driver interface) + drivers (RADIUS, LDAP, DNS, SSH-command, …) |
rating | CDR import framework + format parsers, usage rating, usage→invoice flow |
portal | Customer self-service API surface (separate principal type) |
ticketing | REST client for the operator's existing RT server; customer↔ticket linkage |
importer | Freeside 4.x migration — grows with every phase, never a standalone phase |
oapi-codegen generates Go server stubs and the TypeScript client, so the React app is permanently type-locked to the API.sqlc — schema-first, plain SQL, generated type-safe Go. No ORM between us and billing queries; keeps report SQL explainable and indexable for the later optimization phase.shopspring/decimal at rating/tax boundaries where fractional intermediates exist. Float types are banned from money paths by lint rule.embed.FS. ratecenter serve serves API and UI from one process. SSE for live job/billing-run progress.chromedp; driver interface allows Typst later). The same template renders the in-browser invoice view — one source of truth for invoice appearance.Phase 0 captures the 4.x menu tree and top ~30 staff workflows as the information-architecture contract: same menu names, grouping, and customer-page mental model. What changes is responsiveness: instant type-ahead customer search, no full-page reloads, SSE-driven progress, dark mode, responsive layout.
Reports: every long-running report immediately returns a progress view and streams results (async job + pagination). Deep SQL optimization is deferred, but slowness becomes visible, cancelable, and non-blocking in v1 — no more frozen white pages.
Two rules hold across all phases:
Test corpus: a full copy of the maintainer's production Freeside database, resident on the dedicated VM only. Private data never enters the public repo or leaves the VM; the golden gate runs there as a self-hosted CI runner. Public GitHub Actions runs everything that doesn't need the corpus.
Testing layers:
Nine sub-projects in dependency order. Each gets its own spec → plan → implementation cycle and ends with working software.
| Phase | Name | Delivers |
|---|---|---|
| 0 | Archaeology & harness | jcodemunch index of 4.x; inventory of actually used exports/CDR formats/price plans/gateways/events/reports from production config; dev VM with 4.2 reference instance + snapshot; invoice-diff harness proven against 4.x itself; repo scaffold, CI, graphify, MIT license, module skeleton; IA contract (menu tree + workflows) |
| 1 | Catalog & party | New schema for packages/pricing/tax classes; customers/contacts/locations/agents (multi-company native); importer v1 (customers + packages); customer search/view + package browser UI |
| 2 | Package lifecycle | Order/suspend/cancel/change state machine; event framework skeleton; importer v2 (states + history) |
| 3 | Billing engine | Billing runs, proration, recurring/setup fees, invoice generation, internal tax tables, credits/voids; importer v3 (balances + historical invoices); golden CI gate on, permanently |
| 4 | Payments & collections | Gateway interface; drivers for the operator's gateways (per Phase 0 inventory) + Stripe as OSS reference; dunning; payment application; refunds |
| 5 | Provisioning | Export framework (queue/retry/driver interface); starter drivers: RADIUS, LDAP, DNS, SSH-command + inventoried needs; job/queue UI |
| 6 | CDR & rating | CDR import framework + inventoried formats; rating engine; usage→invoice via Phase 3 engine |
| 7 | Portal & RT | Self-service portal (view/pay invoices, update card); RT REST integration with customer↔ticket UI linkage |
| 8 | Cutover kit | Pre-flight checks, dry-run reports, full reconciliation report, rollback plan, operator runbook — makes migration safe for shops other than the maintainer's |
Explicitly deferred past v1: report SQL optimization (pattern in place, tuning later), tax-service connectors (interface in v1), additional gateway/export/CDR drivers beyond inventory (plugin interfaces are the product; drivers accrete by community), any Torrus replacement.
FS/t/Msgcat.t vs msgcat.t) — clone on a case-sensitive filesystem (the VM), not default macOS, when fidelity matters.| Risk | Mitigation |
|---|---|
| Silent billing inaccuracy (the failure mode of every billing rewrite) | Golden production gate in CI from Phase 3; characterization tests; TDD on money math; integer money + decimal boundaries; float lint ban |
| Business-logic archaeology gaps (20 years of edge cases, no upstream behavioral tests) | Phase 0 inventory narrows scope to what's actually used; 4.2 reference instance answers "what does it do?" empirically; jcodemunch for structural questions |
| Scope explosion (4.x is five products) | RT integrated not rebuilt; Torrus dropped; drivers limited to inventory + reference implementations; plugin interfaces carry the long tail |
| AGPL contamination of MIT codebase | Clean-room rule in CONTRIBUTING.md; legacy knowledge enters only as schema docs, behavioral notes, and test fixtures |
| Trademark exposure on the name | Resolved: named Ratecenter (generic telco term, no Freeside mark); formal trademark search before public launch |
| Schema rework after billing reality hits | Vertical slices put the billing engine on the new schema by Phase 3, early enough to correct Phase 1 decisions cheaply |
git clone, run one binary against Postgres, and evaluate the product — and a Freeside 4.x shop can run the cutover kit's dry-run against their own data.