Files: - STACK.md - FEATURES.md - ARCHITECTURE.md - PITFALLS.md - SUMMARY.md Key findings: - Stack: Next.js 15 + TypeScript + PostgreSQL + Prisma monolith; BullMQ for billing cron jobs; MikroTik client needs library verification (LOW confidence) - Architecture: Modular monolith with shared-DB multi-tenancy; JournalEntryService as sole ledger gateway; derived financial state (no balance fields) - Critical pitfall: Cross-tenant data leakage + fake accounting + billing state machine must all be solved in Phase 1 before any feature work Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
24 KiB
Project Research Summary
Project: NetForge — Multi-Tenant ISP Management SaaS Domain: ISP Operations Management (billing, accounting, inventory, ticketing) Researched: 2026-03-04 Confidence: MEDIUM (core architecture HIGH; library versions and market specifics MEDIUM-LOW)
Executive Summary
NetForge is a vertical SaaS product targeting small-to-medium ISPs (50–2,000 subscribers per tenant) in the Philippine market and similar developing-market contexts where cash collection, MikroTik routers, and Facebook Messenger are operational norms. The dominant pattern for this class of application is a modular monolith with shared-database multi-tenancy — every table carries a tenant_id, enforced both at the application layer (Prisma middleware) and at the database layer (PostgreSQL Row Level Security). This is not a microservices problem; splitting too early would kill development velocity with no meaningful benefit at the target scale.
The recommended stack is Next.js 15 + TypeScript + PostgreSQL + Prisma, with BullMQ on Redis for background billing jobs, Auth.js for authentication, and CASL for fine-grained role-based access control across the five-role model (Admin, Office Staff, Collector, Technician, Client). The double-entry accounting engine is the most complex component and must be built custom — no off-the-shelf library covers the ISP-specific patterns (collector cash-in-transit, prepaid vs. postpaid cycles, field remittance workflows). This engine is also NetForge's primary competitive differentiator: no current competitor combines deep MikroTik integration, real double-entry accounting, field collector workflows, and Facebook Messenger self-service in a single multi-tenant SaaS.
The highest risks are architectural, not feature-level. Missing tenant_id on even one query leaks cross-tenant data catastrophically. Building billing as simple invoice generation without a proper state machine and journal-entry foundation leads to a rewrite. Collector cash tracking without an audit trail creates unresolvable disputes. All three of these must be addressed in Phase 1 before any user-facing features ship — they are infrastructure, not features.
Key Findings
Recommended Stack
The core stack (Next.js 15, TypeScript, PostgreSQL 16, Prisma 5) is well-established for multi-tenant SaaS at this scale and carries HIGH confidence. Authentication is handled by Auth.js (NextAuth v5) with CASL for RBAC — this avoids managed-auth vendor lock-in while supporting the complex five-role permission matrix. UI is built with Tailwind CSS 4 + shadcn/ui components (copy-paste model for full control) + TanStack Table for the data-heavy views (billing history, ledger, inventory). Background billing jobs run on BullMQ backed by Redis — Vercel cron jobs are explicitly ruled out due to execution time limits. Deployment should target Railway or a self-hosted VPS with Docker, not Vercel alone, because the billing worker requires a persistent process.
Core technologies:
- Next.js 15 + TypeScript 5: Full-stack framework with App Router; API Routes serve as the REST API consumed by n8n and MikroTik webhooks. TypeScript catches ledger arithmetic errors at compile time.
- PostgreSQL 16 + Prisma 5: ACID transactions required for double-entry accounting; Prisma
$transactionwraps every journal entry write. Row Level Security provides second-layer tenant isolation. - Auth.js (NextAuth v5) + CASL 6: Credential-based auth with JWT session; CASL encodes per-role, per-context permission rules without sprawling if/else blocks.
- BullMQ 5 on Redis 7: Reliable, retryable job queue for billing cron runs, SMS reminders, and async operations. Persistent worker process required (not serverless).
- decimal.js (non-negotiable): All monetary values stored as integer centavos; decimal.js handles arithmetic. JavaScript floating-point must never touch financial calculations.
- MikroTik RouterOS Node.js client:
node-routerosormikronode— LOW confidence on maintenance status; verify before Phase 1 MikroTik work. - Semaphore SMS: Primary SMS provider for the Philippine market; abstract behind a
SmsServiceinterface for swappability.
See .planning/research/STACK.md for full technology table and alternatives analysis.
Expected Features
The ISP management market has a well-defined set of table stakes that no ISP will migrate without. NetForge's differentiated position combines features no single competitor currently offers together.
Must have (table stakes — MVP blockers):
- Client/subscriber database with status lifecycle (Active / Suspended / Cancelled)
- Service plan registry (configurable per tenant, not hardcoded)
- Invoice auto-generation with monthly recurring billing
- Payment logging by office staff (cash/bank transfer dominant)
- Overdue/outstanding reports (daily operational necessity)
- MikroTik auto-suspend and auto-activate via RouterOS API
- Multi-user roles (Admin, Office Staff, Collector, Technician, Client)
- Basic ticketing and job order workflow
- SMS reminders (pre-due, overdue, payment confirmation)
- Executive dashboard (revenue collected, overdue count, active clients)
Should have (competitive differentiators — Phase 2):
- Full double-entry accounting with automated journal entries (primary differentiator — competitors do billing, not accounting)
- Collector zone management + field cash collection with audit trail
- Inventory/asset tracking per subscriber (prevents equipment loss)
- Facebook Messenger chatbot via n8n API integration
- API documentation and webhook support
Defer (v2+ / Phase 3+):
- Technician native mobile app (responsive web PWA first)
- White-label client portal
- Prepaid voucher / hotspot load management
- Live MikroTik connection status polling per subscriber
- Automated PPPoE profile sync on plan changes
- Super-admin / SaaS platform subscription management (meta-layer)
- Network usage graphs
Anti-features — do not build:
- Full RADIUS server (integrate with FreeRADIUS instead)
- Built-in VoIP billing
- Zero-touch provisioning / complex provisioning workflows
- Full ERP (HR, payroll, procurement)
- Built-in email marketing
See .planning/research/FEATURES.md for full competitor comparison table and feature dependency graph.
Architecture Approach
NetForge is a modular monolith with tenant-scoped data isolation. Twelve domain modules communicate through in-process service calls (not a message bus), with BullMQ handling the only genuinely async operations (scheduled billing runs, report pre-computation, SMS dispatch). The central invariant: every database query carries tenant_id, enforced at the Prisma middleware layer and backed by PostgreSQL RLS. No balance fields exist — all financial state is derived from immutable journal entry lines. The JournalEntryService is the sole gateway to the ledger; no module writes accounting records directly.
Major components:
- Auth + Tenant Resolution — JWT carries
{user_id, tenant_id, role}; subdomain resolves totenant_id; CASL enforces permissions at every route handler. - Subscriber Management — Core entity. Billing, inventory, and ticketing all reference subscribers. Does not write to accounting directly — emits to Billing Engine.
- Billing Engine — Prepaid and postpaid as distinct state machines. Generates invoices, tracks cycles, detects overdue. Calls Accounting module for journal entries.
- Payment Tracker — Records cash/online payments, links to invoices, manages collector running balances. Immutable records — corrections via reversals only.
- Accounting Module (Double-Entry Ledger) — Chart of Accounts, JournalEntryService (enforces debits = credits), Report Engine (read-only). Auto-provisioned default COA at tenant signup.
- Ticketing + Job Order Workflow — Separate entities (one ticket spawns multiple job orders). Technician completion triggers inventory depletion and compensation journal entries.
- Technician Management — Per-job and salary compensation models; CompensationService encapsulates all pay logic.
- Inventory Module — Stock (warehouse) and deployed assets (at subscriber premises) tracked as an event ledger of movements, not mutable quantity columns.
- Expense Tracking — Non-inventory operational expenses; each entry posts a journal entry.
- Dashboard + Report Engine — Read-only aggregation. Pre-computed snapshots for performance; never live scans of full tables.
- Client Portal — Subscriber-facing; scoped at tenant_id AND subscriber_id. Read-heavy with ticket submission as primary write.
- Notification Module — In-app v1; SMS/email extendable via abstracted interfaces.
See .planning/research/ARCHITECTURE.md for full component diagrams, data flow, and anti-patterns.
Critical Pitfalls
-
Cross-tenant data leakage — A single query missing
WHERE tenant_id = ?exposes one ISP's data to another. Prevention: Prisma middleware injectstenant_idon every query; PostgreSQL RLS as backstop; integration tests with two tenants asserting zero cross-contamination. Must be implemented in Phase 1 before any feature work. -
Fake double-entry accounting — Building
paymentsandexpensestables and calling it accounting produces financial reports that cannot be reconciled or audited. Prevention: Implementjournal_entries+journal_entry_linesas the single source of truth from Phase 1. All balances are derived from the ledger, never stored as mutable fields. Validate debits = credits at the database constraint level. -
Billing as simple invoice generation — The complexity is in the state machine: partial payments, mid-cycle plan changes, grace periods, suspension/reinstatement timing, credit memos. Prevention: Model billing as an explicit state machine (
pending → active → overdue → suspended → reinstated | cancelled) before writing any billing code. Define edge case rules in writing before implementation. -
Collector cash with no audit trail — Door-to-door cash collection without chain-of-custody records (collector ID, collection run, remittance verification) enables unresolvable disputes and undetectable theft. Prevention: Model collection sessions with two-party remittance verification. Accounting entries post only on verified remittance, not on collection logging.
-
UI-only RBAC — Enforcing permissions only in frontend components means any technically savvy user can call API endpoints directly and access billing data as a Technician or other clients' data as a Collector. Prevention: Every API endpoint enforces role AND row-level access in the service layer. Write API tests for unauthorized access scenarios for each role from day one.
See .planning/research/PITFALLS.md for 12 additional moderate and minor pitfalls with phase-specific warnings.
Implications for Roadmap
The feature dependency graph from FEATURES.md and the build-order tiers from ARCHITECTURE.md are in strong agreement. The roadmap must follow this dependency chain: multi-tenant foundation → subscriber + billing core → payment tracking + accounting → operational modules → visibility/reporting. There is no shortcut. Any attempt to build the accounting reports before the journal entry foundation, or to build MikroTik integration before the billing state machine, creates architectural debt requiring rewrites.
Phase 1: Multi-Tenant Foundation and Billing Core
Rationale: Everything else depends on this. Tenant isolation, auth, subscriber management, billing engine, payment tracking, and the accounting ledger must all be established together. These are not separable — a billing engine without accounting posts is half-built. The journal entry schema must exist before the first invoice is generated.
Delivers: A working ISP can be onboarded. Subscribers managed, invoices generated on schedule, payments recorded, MikroTik suspensions automated, double-entry ledger posting correctly.
Addresses features from FEATURES.md:
- Client/subscriber database with status lifecycle
- Service plan registry (database-driven, per tenant)
- Invoice auto-generation (monthly recurring, prepaid and postpaid state machines)
- Payment logging by office staff
- MikroTik auto-suspend and auto-activate
- Multi-user roles with API-level enforcement
- Chart of Accounts + Journal Entry Service (accounting foundation)
- Executive dashboard (basic metrics — active, overdue, revenue collected)
Avoids pitfalls:
- Cross-tenant leakage (Prisma middleware + RLS from day one)
- Fake accounting (journal_entries schema established before first invoice)
- Billing state machine not modeled (prepaid/postpaid strategies built as distinct classes)
- UI-only RBAC (API-level enforcement from first endpoint)
- Idempotency missing on payments (idempotency keys on payment creation)
- One-router assumption (network_nodes table with router_id from day one)
Needs research-phase: YES — MikroTik RouterOS Node.js client library maintenance status is LOW confidence and must be verified before implementation commits to a specific library.
Phase 2: Operational Modules and Accounting Completion
Rationale: Once the billing and accounting core is stable, the operational modules that depend on it (ticketing, job orders, inventory, expense tracking, collector workflows) can be built. These modules also complete the accounting picture — every expense, equipment purchase, and labor cost posts to the ledger.
Delivers: A complete operational platform. ISP staff can manage support tickets, dispatch technicians, track equipment from warehouse to subscriber, log expenses, and see collector accountability. The accounting system now has real data across all account types.
Addresses features from FEATURES.md:
- Basic ticketing and job order workflow
- Collector zone management and field payment receipting
- Inventory/asset tracking
- Expense and vendor tracking
- Overdue/outstanding reports (operational)
- SMS reminders (billing + payment confirmation)
- Financial reports (Trial Balance, Income Statement, Balance Sheet)
Implements architecture: Inventory Module (event-ledger model), Ticketing + Job Order Workflow (separate entities with explicit status sync), Collector Remittance Workflow (two-party verification), CompensationService.
Avoids pitfalls:
- Collector cash without audit trail (modeled as collection sessions in Phase 2)
- Inventory as mutable quantity (event-ledger model decided now even if partially deferred)
- Ticket/job order status desync (explicit one-to-many mapping with sync rules)
- Technician compensation in UI layer (CompensationService built as dedicated service)
Needs research-phase: MAYBE — Semaphore SMS API integration is MEDIUM confidence; verify current API documentation and pricing before SMS implementation work.
Phase 3: External Integrations and Self-Service
Rationale: With a stable operational core, external-facing integrations and self-service features become viable. The API-first architecture from Phase 1 makes n8n and Facebook Messenger integration straightforward. The client portal can now be built on top of the billing and payment history that exists.
Delivers: Reduced support overhead (client self-service), automated workflows (n8n / Facebook Messenger balance checks), and the platform's third key differentiator operational.
Addresses features from FEATURES.md:
- Facebook Messenger chatbot via n8n API
- Client portal (balance view, payment history, ticket submission)
- API documentation and webhook support
- Live MikroTik connection status query
Uses stack: Next.js API Routes (already built), n8n webhook endpoints, SMS gateway (Semaphore).
Needs research-phase: YES — n8n integration patterns and Facebook Messenger API webhook setup may need current documentation review.
Phase 4: Platform Scale and Differentiation
Rationale: Super-admin panel, white-label support, and advanced MikroTik features (automated PPPoE profile sync, live status polling) require the earlier phases to be stable and load-tested. The super-admin auth isolation (separate context from tenant users) is a security requirement that must not be shortcut.
Delivers: The SaaS platform operator can manage ISP tenants, monitor usage, and bill them. Advanced ISPs can use white-label portals. Plan changes automatically propagate to router speed profiles.
Addresses features from FEATURES.md:
- Super-admin panel (ISP tenant management, usage metering, platform billing via Stripe)
- White-label client portal (per-tenant theme/logo/custom domain)
- Automated PPPoE profile sync on plan change
- Prepaid voucher / hotspot load management
Avoids pitfalls:
- Super-admin using same auth system as tenant users (separate auth context, separate table)
Needs research-phase: YES — Stripe integration for B2B SaaS subscriptions and PayMongo/GCash integration for Philippine online subscriber payments both need current API verification.
Phase Ordering Rationale
- Dependency chains are strict: Billing Engine requires Subscriber Management. Payment Tracker requires invoices from Billing Engine. Journal Entry Service requires Chart of Accounts. Dashboard requires all operational modules to have data. This ordering is not optional.
- Accounting foundation cannot be retrofitted: The journal_entries schema and JournalEntryService must exist before the first financial transaction is written anywhere in the system. Building billing first and adding accounting later is a rewrite path.
- MikroTik is in Phase 1 because it's a table-stakes feature: ISPs will not adopt NetForge without auto-suspend/activate. However, the RouterOS client library must be verified (LOW confidence) before committing to implementation.
- Collector workflow is Phase 2 (not Phase 1): Office payment logging covers the MVP. The full collector session / remittance workflow adds complexity that should follow the core billing foundation being proven.
- External integrations (n8n, Facebook Messenger) are Phase 3: They require the API layer to be stable. Building them before the API is finalized creates rework.
Research Flags
Phases needing /gsd:research-phase during planning:
- Phase 1 (MikroTik integration):
node-routerosandmikronodemaintenance status is LOW confidence as of research date. Must verify which Node.js RouterOS API client is actively maintained before implementation. - Phase 2 (SMS): Semaphore SMS API pricing and stability for 2026 is MEDIUM confidence. Verify current API documentation and rate limits before implementation.
- Phase 3 (n8n + Facebook Messenger): Integration patterns for n8n webhook → Facebook Messenger API need current documentation. Facebook Messenger API has a history of breaking changes.
- Phase 4 (Payments): Stripe B2B SaaS subscription integration is standard, but PayMongo/GCash integration for Philippine online payments needs current API research.
Phases with well-documented standard patterns (can skip research-phase):
- Phase 1 (multi-tenant foundation): Prisma middleware tenant injection, PostgreSQL RLS, Auth.js setup, and BullMQ job queue are all well-documented patterns with extensive community examples.
- Phase 1 (double-entry accounting schema): The
journal_entries+journal_entry_linesledger pattern is industry-standard and stable. No research needed — implement as specified in ARCHITECTURE.md. - Phase 2 (ticketing and job orders): Standard CRUD with state machine patterns. No novel integration required.
Confidence Assessment
| Area | Confidence | Notes |
|---|---|---|
| Stack | MEDIUM-HIGH | Core framework/DB/ORM choices are HIGH confidence. Auth.js + CASL architecture is HIGH; version numbers are MEDIUM. MikroTik Node.js client is LOW — needs verification before Phase 1 implementation commits. |
| Features | MEDIUM | Based on training knowledge of Splynx, UISP, Sonar, ISPApp. No live verification of competitor feature pages possible during research. Competitor comparison table is directionally reliable but should be validated before roadmap lock. |
| Architecture | HIGH | Double-entry accounting patterns, modular monolith for this scale, shared-DB multi-tenancy, and collector cash-in-transit workflows are all well-established patterns. High confidence independent of tool availability. |
| Pitfalls | MEDIUM-HIGH | Critical pitfalls (tenant isolation, fake accounting, billing state machine) are well-established engineering patterns with HIGH confidence. ISP-specific operational pitfalls (collector audit trail, MikroTik coupling) are MEDIUM — derived from domain analysis, not validated with live ISP operators. |
Overall confidence: MEDIUM-HIGH
The architectural and accounting foundations are HIGH confidence. Stack choices are defensible and well-supported. The main uncertainties are market-specific (Semaphore SMS pricing, MikroTik library maintenance, Philippine payment gateway options) and should be validated with quick targeted research during Phase 1 and Phase 2 planning.
Gaps to Address
-
MikroTik RouterOS Node.js client: Verify
node-routerosvsmikronodevs direct protocol implementation before Phase 1 commits to an approach. Check npm download trends and GitHub last-commit dates. This is LOW confidence and blocks Phase 1 MikroTik work. -
Semaphore SMS: Verify API is still active, competitively priced for Philippine market in 2026, and has adequate throughput for billing reminder volume. The
SmsServiceabstraction from STACK.md means this can be swapped if Semaphore is unsuitable. -
Collector workflow business rules: The two-party remittance verification model is architecturally sound, but the exact operational flow (does the office staff verify before or after the collector remits? Is there a physical receipt?) should be validated with real ISP operators before Phase 2 implementation.
-
Philippine payment gateways (Phase 3+): PayMongo, GCash, and Maya (PayMaya) integration options need current API research when online subscriber payments are in scope. The research notes this as relevant to the market but defers it from v1.
-
Competitor feature verification: The FEATURES.md competitor table is based on training data (mid-2025). Verify Splynx, UISP, and Sonar current feature pages before finalizing the differentiator claims in product positioning.
-
Stripe vs alternative for ISP subscription billing: Stripe is recommended for the SaaS owner billing ISPs (B2B subscription). Verify this is the right choice for the target market's legal entity types and banking setup. PayMongo may be more appropriate if the SaaS owner is Philippines-based.
Sources
Primary (HIGH confidence)
- NetForge PRD (
isp_system_prd.md) — project requirements, reviewed directly - Established SaaS architecture patterns — modular monolith, shared-DB multi-tenancy (Martin Fowler, Sam Newman), PostgreSQL RLS
- Double-entry accounting principles (GAAP) — COA, journal entry ledger, trial balance derivation
- BullMQ, Prisma, Auth.js, Next.js official documentation — from training data through August 2025
Secondary (MEDIUM confidence)
- Training knowledge of Splynx, UISP CRM, ISPApp, Sonar Software feature sets (public documentation up to mid-2025)
- Philippine ISP market patterns (cash/bank-transfer dominance, GCash/Maya prevalence, Facebook Messenger as primary support channel)
- Semaphore SMS as dominant Philippine SMS gateway
- Railway vs Vercel deployment trade-offs
Tertiary (LOW confidence — needs verification)
node-routerosandmikronodeNode.js MikroTik client maintenance status (open-source project activity not verifiable without WebSearch)- Specific package version numbers across the stack — verify against npm before pinning in package.json
- Current Semaphore SMS API pricing and throughput limits
Research completed: 2026-03-04 Ready for roadmap: yes