Owner screenshots: ViiBE seller-side views (Accounts, Quotes, Products, LNP, Number Orders, CNAM, Mobile Connect, Reports) and NetSapiens customer/manager views (Home/Statistics, Domains, SIP Trunks, Phone Inventory, E911 Inventory, Call History, Contacts, Answer Rules, Time Frames, User Voicemail/Settings, Music/Messages, Call-Center Queues/Statistics, Auto Attendants).
Owner Obsidian notes: Captured preferences, design constraints, competitive feature wishlist, and operational requirements from Germaine Brown.
Owner business records:ENTITY.md — verified phone assets and legal entity.
Existing Portal Artifacts
Deployed portal:/home/myvoip/htdocs/my.voipsimplicity.com/index.html on app3 (533 lines production, 1,471 enhanced reference).
Skill documentation:voip-portal-development skill in ~/.hermes/skills/devops/voip-portal-development/ with 13 reference files covering API integration, call patterns, marketplace flows, and deployment.
Domain roster: 14 customer domains, 189 subscribers, 17 DIDs, 30 call queues, 19 auto attendants, 16 time frames — all on RingLogix.
Source of Truth & Data Architecture
Data Domain
Primary Source
API/Object
Notes
Subscribers/Extensions
RingLogix
subscriber/read
domain param required; filter to 100–399 for real users
DIDs/Phone Numbers
RingLogix
phonenumber/read
Ignores domain filter — filter client-side by dialrule_domain
Call Queues
RingLogix
callqueue/read
domain param required
Auto Attendants
RingLogix
attendant/read
NOT autoattendant (returns 404)
Time Frames
RingLogix
timeframe/read
domain param required
Music on Hold
RingLogix
Unknown — no confirmed endpoint
Screenshots show MOH config; API availability TBD
Call History / CDRs
RingLogix
NOT AVAILABLE — cdr, call_detail_record, callhistory all return 404
Must use alternative source or NetSapiens CDR export
Call Recordings
RingLogix → Wasabi S3
s3:* bucket policy for RingLogix IPs (192.92.8.0/24, 64.52.82.0/24, 64.52.83.0/24)
Portal would proxy through signed URLs
Billing / Invoices
RingLogix
Unknown — no confirmed billing API endpoint
Likely via RingLogix admin panel export or Stripe integration
Plans & Features
RingLogix / Manual
Unknown — no confirmed catalog API
Marketplace catalog maintained manually or via RingLogix reseller API
User Auth / RBAC
Custom (portal-local)
N/A — built in portal JS
No RingLogix customer-auth API; staff info@voipsimplicity.com hardcoded
E911 Inventory
RingLogix
Unknown — no confirmed endpoint
NetSapiens screenshots reference; API path TBD
SIP Trunks
RingLogix
Unknown — no confirmed endpoint
NetSapiens screenshots reference; API path TBD
Answer Rules
RingLogix
Unknown — no confirmed endpoint
NetSapiens screenshots reference; API path TBD
CNAM
RingLogix / ViiBE
Unknown — ViiBE screenshots show CNAM tab
API path and data model TBD
API base URL:https://api.ringlogix.com/pbx/v1/ (all calls POST with object and action in body — NOT RESTful GET).
CRITICAL: CDR/call-history, billing, and E911 endpoints are NOT available via the current RingLogix API. See Unknowns & Caveats.
RBAC, Tenant Isolation & Security
Role Definitions
Role
Access Scope
Auth Mechanism
Login Identifier
IT Staff
All 14 domains, all views, admin panel, audit log, domain selector
Single domain, all customer views, billing, add/remove authorized users
Domain ID or registered email + password
Domain ID, account email, or authorized-user email
Authorized User
Single domain, subset of views (no billing, no user management) — configurable by Customer Admin
Email + password, invited by Customer Admin
Authorized-user email
View-Only User
Single domain, read-only dashboard + call history
Email + password, invited by Customer Admin
Authorized-user email
Tenant Isolation Rules
Every data query is scoped to currentDomain (customer) or selected domain (staff).
Staff domain selector changes currentDomain and re-renders the active view — never leaks cross-domain data.
Customer sessions are locked to a single domain ID returned on login.
Staff audit log entries include performedBy (staff email), domain (affected domain), and impersonated flag if acting as customer.
Security Constraints
Card data: Never stored in browser session storage, localStorage, or cookies. Card updates go through a separate, secure payment-gateway path (Stripe Elements or equivalent hosted iframe).
Session tokens:sessionStorage only — cleared on logout (sessionStorage.clear() + location.reload()).
No JWTs in URL: Auth state never appears in query strings or URL fragments.
MFA recovery codes: Generated server-side, shown once, never stored in browser.
Rate limiting: Login attempts, MFA token requests, and password-reset requests rate-limited per IP and per account (5 attempts / 15 min window).
Password reset tokens: Single-use, time-limited (15 min), delivered via email only (SMS fallback TBD per provider availability).
Audit & Compliance
Audit Trail Requirements
All state-changing operations produce immutable audit log entries:
ts, user, action:'plan_change', domain, detail (from → to plan)
Authorized user add/remove
ts, user, `action:'user_add'
Contact info update
ts, user, action:'contact_update', domain, detail (changed fields, not values)
Payment method change
ts, user, action:'payment_update', domain (no card details logged)
Password reset
ts, user, action:'password_reset', domain
Staff domain switch
ts, user, action:'domain_switch', detail (from → to domain)
Notification Rules
All marketplace orders produce a notification (ticket-like) visible to staff.
Authorized-user invitation emails are sent with a time-limited registration link.
Password reset and MFA token delivery produce notifications with delivery method noted.
Phased MVP Sequence
Phase 1: Foundation (MVP Launch)
Site login (split-half page, domain ID / email auth, password reset)
My Dashboard (per-customer stats + lists, no topology graph)
Call History (searchable, exportable — mock/placeholder data if CDR API unavailable)
Nav: Dashboard, Call History, Billing (read-only), My Info (read-only)
Phase 2: Self-Service
My Info: editable contact info + payment method update (secure, separate path)
Marketplace: catalog browsing, cart, per-extension vs per-account selection, immediate provisioning vs request-discussion choice
Billing: invoice viewer, download, prior invoices list
Authorized user management: add/remove with RBAC
Phase 3: Advanced
Graphical phone-system topology in Dashboard
MFA / one-time token delivery (email/SMS)
Recording playback in Call History (only if enabled)
Voicemail inline in Call History
Music on Hold, Time Frames displays
Order-services contact form on login page
Phase 4: Feature Parity
E911 inventory display
SIP trunk status
Answer rules viewer
CNAM management (if API available)
Staff-only reports, LNP, number orders (ViiBE integration)
Requirement Areas
1. My Dashboard
1.1 Per-Customer Aggregate View
Customer sees:
Metric
Data Source
Format
Total extensions
subscriber/read filtered to 100–399
Large stat card: "12 Extensions"
Call queues
callqueue/read count
Stat card: "3 Queues"
DID inventory
phonenumber/read filtered by dialrule_domain
Stat card: "5 Phone Numbers"
Auto attendants
attendant/read count
Stat card: "2 Attendants"
Subscribed plan
Manual / RingLogix catalog (TBD)
Badge: "Business Pro"
Staff sees (domain selector active):
Same metrics for the selected domain.
Aggregate "All Domains" stats: total subscribers, DIDs, queues, attendants across all 14 domains.
1.2 Detail Lists (Expandable Under Stats)
List
Columns
Notes
Extensions
Name, Email, Extension #, Voicemail (badge)
Filtered to 100–399. System routes hidden by toggle.
DIDs
Phone Number (formatted), Domain, Assigned Extension
Full DID list for domain.
Call Queues
Queue Name, Extension, Strategy (Linear Hunt, etc.), Members count
From callqueue/read.
Auto Attendants
Extension, Name, Schedule, Prompt Type
From attendant/read. Menu options NOT available via API — show note to use RingLogix admin.
1.3 Music on Hold
Data source: Unknown endpoint. Screenshots (NetSapiens) show MOH configuration per domain.
Fallback: Display "Configured via RingLogix Admin Panel" with a note until API endpoint is confirmed.
1.4 Time Frames
Data source:timeframe/read per domain.
Display: Table of time frame names, schedules, and associated objects (attendants, routes).
Staff view: Full edit capability (if API supports write), otherwise read-only with admin-panel link.
1.5 Graphical Phone-System Topology (Phase 3)
Requirement: Visual graph/flowchart showing:
Inbound DID → Time Frame → Auto Attendant → Call Queue → Extensions
Nodes color-coded by type (DID=gold, Attendant=blue, Queue=teal, Extension=green)
Connected edges show full routing path
Rendering: Canvas or SVG-based, mobile-responsive (scrollable on small screens).
Data: Built from phonenumber/read (matchrule, dialrule_domain), attendant/read (timeframes, menus), callqueue/read (connect_to), subscriber/read relationships.
Note: Menu-level routing (specific attendant option → extension) is NOT available via current API. Graph shows attendant → connected queues/extensions at the object level, not per-menu-option.
2. Call History
2.1 Unified View
Single page merging incoming and outgoing calls — NOT separate "Call Logs" + "Recordings" tabs. Customers see one searchable list.
2.2 Search
Searchable fields: Caller name AND phone number.
Behavior:oninput handler with no submit button. Real-time filtering across both inbound and outbound calls.
Implementation: Single search box with data-search attribute on rows containing lowercase concatenation of caller name + phone number.
Opens modal with transcript text; only shown if call was missed → voicemail left
8
Recording
▶ MM:SS play button or —
Only shown if recording is enabled for this domain/extension. Inline playback.
9
Duration
MM:SS
Call duration
2.4 Recording Playback
Conditional: Recording play button appears ONLY when recording is enabled. RingLogix recording toggle is per-domain or per-extension — portal must check this.
Playback: Inline HTML5 <audio> or Web Audio API. Signed URLs from Wasabi S3 (proxy through portal or generate pre-signed URLs).
No download required: Play in-page. Download button separate if needed.
2.5 Export
"Export All": Downloads entire call history dataset as CSV (all calls for the domain, unfiltered).
"Export Current View": Downloads only the currently filtered/search-results as CSV.
Format: Standard CSV with column headers matching table columns. Arrow characters cleaned: ↓ → Incoming, ↑ → Outgoing.
Implementation: Build CSV string, create Blob, trigger download via temporary <a> element with download attribute.
2.6 Data Source Caveat
CDR endpoints all return 404 from RingLogix API (cdr, call_detail_record, callhistory). Until an alternative is found:
MVP fallback: Placeholder/mock call data with clear labeling OR NetSapiens CDR export imported manually.
Target source: NetSapiens CDR API (if RingLogix exposes it under a different object name), RingLogix reseller-level call reporting, or direct PBX CDR collection.
Recording source: Wasabi S3 bucket (confirmed: RingLogix writes call recordings to Wasabi). Portal can list/stream recordings if bucket paths are structured by domain.
3. Marketplace
3.1 Catalog & Cart
Requirement
Detail
Plans/features browsing
Cards with plan name, price, included features, description
Cart metaphor
Add-on items collected in a running cart before submission
Per-extension vs per-account distinction
Each item tagged perLine: true/false/'did'
Per-extension selection
Modal with extension dropdown (100–399) — user selects ONE, MULTIPLE (checkboxes), or ALL extensions
Per-DID selection
SMS/Text Messaging shows DID dropdown instead of extensions
Per-account items
No selector — applies to entire domain
3.2 Provisioning Choice
After selecting extensions/DIDs, user chooses:
Option
Behavior
Apply Now(Immediate Provisioning)
If the applicable provider API supports the requested write action and the item is eligible for automation, provision the add-on immediately. Confirmation + audit log.
Discuss with VoIPSimplicity(Request Discussion)
Creates a ticket/order for staff review. Audit log entry. Notification to staff.
Note: Immediate provisioning requires RingLogix write API access (not yet confirmed). Until confirmed, ALL additions default to "Request Discussion" flow.
3.3 Audit, Ticket & Notification
Every add-on request (immediate or discussion) produces:
Audit log entry with full detail (item, domain, extensions, provisioning choice).
Staff-visible ticket in Admin Panel → Audit Log tab.
Confirmation notification to the customer (on-screen success modal: "Our team will contact you within 24 hours.").
Caveat: Approval automation depends on RingLogix write API availability. Until confirmed, ALL changes go through manual staff review. This document must not claim RingLogix supports write endpoints that are unverified.
3.5 Data-Source Caveat
The marketplace catalog (plans, add-ons, pricing) has no confirmed RingLogix API endpoint. Current implementation uses:
Hardcoded catalog in portal JS (10 items with name, price, description, perLine flag).
Manual sync from RingLogix reseller panel pricing.
Target: RingLogix reseller catalog API (to be confirmed) or Stripe product catalog.
4. Billing
4.1 Current Plan Summary
Field
Data Source
Notes
Plan name
Hardcoded / RingLogix catalog
e.g., "Business Pro"
Plan price
Hardcoded / RingLogix
Monthly or annual
Included features
Hardcoded list
Teal "Active" badges
Available but unsubscribed options
Hardcoded list
Gray "Available" badges with "Add in Marketplace" link
4.2 Prior Invoices
Column
Notes
Date
YYYY-MM-DD
Invoice Number
Unique identifier
Amount
Formatted currency
Status
Paid (teal), Pending (gold), Overdue (red)
4.3 Invoice Viewer
Inline framed viewer: Opens an iframe/modal overlay showing the invoice PDF.
Closeable: Close button, backdrop click, Escape key dismiss.
Download options:
Download individual invoice
Download multiple (selected via checkboxes)
Download all invoices
Data source caveat: No confirmed RingLogix billing API. Invoice data likely from RingLogix admin panel export, Stripe billing portal, or manual upload.
4.4 Payment Method
Separate, secure update path: Card update form isolated from the main billing view.
Never stored in browser: Card number, CVV, expiry never touch sessionStorage, localStorage, or in-memory JS objects longer than the update transaction.
Integration: Stripe Elements (hosted iframe) or equivalent PCI-compliant solution. Portal sends a token, never raw card data.
Current implementation (demo): sessionStorage-backed card display (voip_cc, voip_cc_expiry) — NOT production-grade. Migration to Stripe Elements required before go-live.
5. My Info
5.1 Contact Information
Field
Editable
Validation
Name
Yes
Required
Email (account)
Yes
Required, valid email format
Phone
Yes
Optional, US format
Address
Yes
Optional, street/city/state/ZIP
Company Name
No
Read-only, set at account creation
Domain ID
No
Read-only, displayed for reference
Edit pattern: All fields disabled by default. "Edit" button toggles to "Cancel"; editable fields get teal border. "Save Changes" button appears during edit mode. Save writes to currentUser + sessionStorage, redraws header badge.
5.2 Payment Method (Separate from Billing)
Update payment method: Button opens a modal/section with secure card form (Stripe Elements).
Separate from Contact Info card: Payment update is its own card/section, not mixed with personal info fields.
Customer Admin enters name, email, role (Authorized User / View-Only). Invitation email sent.
Manage users
Table of current authorized users: Name, Email, Role, Status (Active/Invited/Revoked). Revoke button.
RBAC
Per-user role controls which views are accessible (see RBAC).
Invitation flow
Email with time-limited registration link → user sets password → added to domain.
Audit trail
All add/remove/role-change operations logged in audit.
6. Site Login
6.1 Split-Half Login Page
Layout:
LEFT (60% desktop, 100% mobile): Navy gradient background. Login form: "Email or Domain ID" field + "Password" field + "Sign In" button + "Forgot Password?" link.
RIGHT (40% desktop, 100% mobile): White/light background. "Need Help?" section: "Submit a Ticket" button (mailto:support@voipsimplicity.com), phone (888.601.1173), email (support@voipsimplicity.com), and order-services contact form.
Mobile (<768px): Stack vertically — login on top, help/contact below.
6.2 Authentication Methods
Method
Identifier
Use Case
Domain ID
6-digit numeric (e.g., 287275)
Customer authenticates with their RingLogix domain ID + password
Account email
Registered email (e.g., admin@grandlakeclub.com)
Customer authenticates with account-level email
Authorized-user email
Individual user email (e.g., deborah@grandlakeclub.com)
Authorized users sign in with their own email
Staff email
info@voipsimplicity.com
IT staff — full admin access to all domains
Customer→domain mapping: Real-time API lookup against RingLogix domain/read or a local domain-to-email mapping cache.
6.3 Password Reset
Trigger: "Forgot Password?" link on login page.
Flow: Enter email or domain ID → email sent with single-use, time-limited (15 min) reset link → user sets new password → confirmation.
Rate limiting: 3 reset requests per email per hour.
6.4 MFA / One-Time Token (Phase 3)
Aspect
Requirement
Delivery methods
Email (primary) + SMS (secondary, if provider supports)
Token lifetime
5 minutes
Rate limiting
5 attempts per 15 minutes per account
Recovery
Recovery codes generated on MFA enrollment (shown once, stored by user)
Exploration scope
Evaluate Twilio Verify, email OTP, and TOTP authenticator apps
Caveat
SMS delivery depends on Twilio number provisioning and A2P 10DLC registration
6.5 Order-Services Contact Form
Location: Right panel of login page (below "Need Help?" section).
Fields: Name, Email, Phone, Company, Service Interest (dropdown: New Phone System, Add Features, Porting Numbers, Other), Message.
Submission: Emailed to info@voipsimplicity.com (or CRM integration). Confirmation message displayed.
Spam protection: reCAPTCHA or honeypot field.
7. Screenshot-Informed Requirements
The owner provided screenshot groups from two platforms. These inform the portal's feature surface and data expectations but do NOT imply all features are available via API.
7.1 ViiBE Seller-Side Views (Staff-Only)
Screenshot Group
Portal Equivalent
API Availability
Accounts
Admin Panel → Domains list (already built: 14-domain roster with stats)