docs: define customer portal requirements

This commit is contained in:
root
2026-07-24 11:34:39 -04:00
parent d0acaf6a87
commit 0768622a52
3 changed files with 946 additions and 0 deletions
+598
View File
@@ -0,0 +1,598 @@
# my.voipsimplicity.com — Portal Requirements
**Version:** 1.0
**Date:** 2026-07-24
**Status:** Pre-MVP documentation
**Owner:** Germaine Brown (VoIPSimplicity LLC)
**Platform:** RingLogix-powered, deployed on app3 (CloudPanel CE)
**Design:** Light, mobile-first, single-file HTML SPA (see [voip-portal-development skill](#sources--methodology))
---
## Table of Contents
1. [Sources & Methodology](#sources--methodology)
2. [Source of Truth & Data Architecture](#source-of-truth--data-architecture)
3. [RBAC, Tenant Isolation & Security](#rbac-tenant-isolation--security)
4. [Audit & Compliance](#audit--compliance)
5. [Phased MVP Sequence](#phased-mvp-sequence)
6. [Requirement Areas](#requirement-areas)
- [1. My Dashboard](#1-my-dashboard)
- [2. Call History](#2-call-history)
- [3. Marketplace](#3-marketplace)
- [4. Billing](#4-billing)
- [5. My Info](#5-my-info)
- [6. Site Login](#6-site-login)
- [7. Screenshot-Informed Requirements](#7-screenshot-informed-requirements)
7. [Nav Organization (Expanded Canonical)](#nav-organization-expanded-canonical)
8. [Acceptance Criteria by Phase](#acceptance-criteria-by-phase)
9. [Unknowns & Caveats](#unknowns--caveats)
10. [Out of Scope (Deferred to Post-MVP)](#out-of-scope-deferred-to-post-mvp)
---
## Sources & Methodology
### Owner-Provided Materials
- **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](./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 100399 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](#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 | Hardcoded credentials: `info@voipsimplicity.com` + password | Email |
| **Customer Admin** | 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:
| Operation | Audit Fields |
|---|---|
| Login/logout | `ts`, `user`, `role`, `domain`, `action`, `ip` (if available) |
| Marketplace add-on request | `ts`, `user`, `action:'addon_request'`, `domain`, `detail` (item name, extension, choice) |
| Plan change / upgrade | `ts`, `user`, `action:'plan_change'`, `domain`, `detail` (from → to plan) |
| Authorized user add/remove | `ts`, `user`, `action:'user_add'|'user_remove'`, `domain`, `detail` (affected user email + role) |
| 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 100399 | 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 100399. 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.
#### 2.3 Table Columns
| # | Column | Content | Notes |
|---|---|---|---|
| 1 | Date/Time | `YYYY-MM-DD HH:MM AM/PM` | Sortable |
| 2 | Direction | `↓ Incoming` (teal) or `↑ Outgoing` (gold) | Text label + arrow |
| 3 | Caller Name | Avatar circle + name | Unknown callers: gray "?" avatar + "Unknown" |
| 4 | Caller Phone | Formatted `(XXX) XXX-XXXX` | Muted secondary text |
| 5 | Destination | Extension number or queue name | Who handled the call |
| 6 | Status | Badge: Answered (teal), Missed (red), Voicemail (gray) | Color-coded |
| 7 | Voicemail | `📝 View Transcript` button or `—` | 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 (100399) — 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:
1. **Audit log entry** with full detail (item, domain, extensions, provisioning choice).
2. **Staff-visible ticket** in Admin Panel → Audit Log tab.
3. **Confirmation notification** to the customer (on-screen success modal: "Our team will contact you within 24 hours.").
- Staff can view, approve, or reject requests.
#### 3.4 Approval Boundaries
| Item Type | Auto-Provision? | Requires Approval? |
|---|---|---|
| Per-account add-on (SMS, Analytics, DID, Fax, Priority Support) | No (Phase 2 target) | Yes — staff review |
| Per-extension add-on (Call Recording, Voicemail Transcription) | No (Phase 2 target) | Yes — staff review |
| Plan upgrade/downgrade | No | Yes — billing + provisioning review |
| International calling enablement | No | Yes — fraud review |
**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.
- **Card display in view mode:** `•••• 4242` (last 4 only) + expiry.
#### 5.3 Authorized Users
| Requirement | Detail |
|---|---|
| Add user | 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](#rbac-tenant-isolation--security)). |
| 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) | `domain/read` ✅ |
| **Quotes** | Marketplace → Quote requests / orders (staff review tab) | ❌ Unknown — RingLogix quoting API not confirmed |
| **Products** | Marketplace → Catalog management (staff) | ❌ Unknown — manual catalog in portal |
| **LNP (Local Number Porting)** | Admin Panel → Porting Status (staff) | ❌ Unknown — ViiBE LNP integration not confirmed for RingLogix |
| **Number Orders** | Admin Panel → Number Orders (staff) | ❌ Unknown — RingLogix number ordering API not confirmed |
| **CNAM** | Admin Panel → CNAM Management (staff) | ❌ Unknown — ViiBE screenshots show CNAM tab |
| **Mobile Connect** | Future: Mobile app pairing / softphone config | ❌ Not available via RingLogix API |
| **Reports** | Admin Panel → Reports (staff) | ⚠️ Partial — domain/subscriber/queue stats available; CDR reports NOT available |
#### 7.2 NetSapiens Customer/Manager Views
| Screenshot Group | Portal Equivalent | API Availability | Customer or Staff? |
|---|---|---|---|
| **Home / Statistics** | My Dashboard (stats + lists) | ✅ `subscriber/read`, `callqueue/read`, etc. | Customer |
| **Domains** | Admin Panel (staff domain selector) | ✅ `domain/read` | Staff |
| **SIP Trunks** | Dashboard → SIP Trunks card (Phase 4) | ❌ Unknown — no confirmed RingLogix endpoint | Customer/Staff |
| **Phone Inventory** | Dashboard → DIDs list | ✅ `phonenumber/read` (filter client-side) | Customer |
| **E911 Inventory** | Dashboard → E911 card (Phase 4) | ❌ Unknown — no confirmed RingLogix endpoint | Customer/Staff |
| **Call History** | Call History view | ❌ CDR endpoints all return 404 | Customer |
| **Contacts** | Future: Personal/speed-dial contacts | ❌ Not available via RingLogix API | Customer |
| **Answer Rules** | Extensions → Answer Rules tab (Phase 4) | ❌ Unknown — no confirmed RingLogix endpoint | Customer |
| **Time Frames** | Dashboard → Time Frames list | ✅ `timeframe/read` | Customer |
| **User Voicemail / Settings** | Voicemail view | ✅ `subscriber/read` (vmail fields) | Customer |
| **Music / Messages** | Dashboard → Music on Hold (Phase 3) | ❌ Unknown — no confirmed endpoint | Customer/Staff |
| **Call-Center Queues / Statistics** | Call Queues view + Dashboard stats | ✅ `callqueue/read` (queue list; real-time stats unknown) | Customer/Staff |
| **Auto Attendants** | Auto Attendants view | ✅ `attendant/read` (object list; menu detail NOT available) | Customer |
**Key:** ✅ Available | ⚠️ Partial | ❌ Unknown/Unavailable | 🔮 Future
---
## Nav Organization (Expanded Canonical)
Based on the existing portal skill's nav structure, expanded for the full requirement set:
```
Main
Dashboard # Per-customer stats, lists, topology (Phase 3)
Phone System
Extensions # List + detail: 100-399 users, voicemail status
Call History # Unified incoming/outgoing, search, export, recordings
Call Queues # Queue list, members, strategy
Auto Attendants # Attendant list, schedules, prompts
Voicemail # Voicemail messages, settings, transcription
Account
Billing # Plan, invoices, invoice viewer, payment method
Marketplace # Plans catalog, cart, add-on requests
My Info # Contact info, payment method, authorized users
Administration (staff only — hidden for customers)
Admin Panel # Domain selector, domain roster, audit log
Reports # Staff reports (Phase 4)
Number Orders # DIDs, LNP, CNAM (Phase 4)
```
---
## Acceptance Criteria by Phase
### Phase 1: Foundation
- [ ] Login page renders split-half layout; mobile stacks vertically.
- [ ] Customer can log in with domain ID (e.g., `287275`), account email, or authorized-user email.
- [ ] Staff can log in with `info@voipsimplicity.com` and see domain selector.
- [ ] Refresh/back button does NOT log out (sessionStorage persistence).
- [ ] Dashboard shows per-customer aggregate stats (extensions, queues, DIDs, attendants) — filtered to real extensions (100399).
- [ ] Dashboard extension list shows Name, Email, voicemail badge.
- [ ] Dashboard DID list, queue list, attendant list render with correct data.
- [ ] Call History table renders with search (if CDR data unavailable: clear "No data available — Call history coming soon" empty state).
- [ ] Navigation toggles active state; customer never sees Admin nav items.
- [ ] Domain selector hidden for customer-role users.
- [ ] All unwired views show canonical "No data available." empty state with RingLogix API note.
### Phase 2: Self-Service
- [ ] My Info: Name, Email, Phone editable with Edit/Save/Cancel pattern.
- [ ] Payment method: secure Stripe Elements form, card data never in browser storage.
- [ ] Authorized users: add/remove with RBAC, invitation email, audit log.
- [ ] Marketplace: catalog cards render with per-extension vs per-account distinction.
- [ ] Marketplace: extension/DID selector modal for per-line items (one, multiple, all).
- [ ] Marketplace: immediate provisioning vs request-discussion radio choice.
- [ ] Marketplace: all requests produce audit entry + staff notification.
- [ ] Billing: invoice list with date, number, amount, status.
- [ ] Billing: inline framed invoice viewer with close/ESC dismiss.
- [ ] Billing: download individual, multiple (checkbox-select), or all invoices.
### Phase 3: Advanced
- [ ] Graphical phone-system topology in Dashboard (DID → TF → AA → Queue → Ext).
- [ ] MFA enrollment flow with email OTP (SMS optional).
- [ ] Call History: recording playback (only when recording enabled).
- [ ] Call History: voicemail transcript inline.
- [ ] Dashboard: Music on Hold display.
- [ ] Dashboard: Time Frames list with schedules.
- [ ] 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 reports (aggregate call stats, domain comparisons).
- [ ] LNP porting status.
- [ ] Number orders.
---
## Unknowns & Caveats
### Confirmed Unavailable
| Feature | Detail | Impact |
|---|---|---|
| CDR / Call History API | `cdr`, `call_detail_record`, `callhistory` all return 404 | Call History requires alternative data source |
| Auto Attendant menu details | `attendant/read` returns object metadata but NOT per-option menu routing | Attendant detail view limited to name, schedule, prompt type |
| DID domain filtering | `phonenumber/read` ignores `domain` param — returns all DIDs across all domains | Client-side filtering required |
### Unconfirmed / Needs Investigation
| Feature | What to Verify | Priority |
|---|---|---|
| Billing/invoice API | Contact RingLogix: is there a billing API or reseller invoice endpoint? | High |
| Marketplace catalog API | Is there a reseller product catalog? If not, maintain hardcoded catalog synced manually. | High |
| Write API (provisioning) | Can add-ons be provisioned via API? `object=subscriber&action=update`? | High |
| Music on Hold endpoint | Is there an `musiconhold` or `moh` object? Test known NetSapiens object names. | Medium |
| E911 endpoint | Is there an `e911` or `emergency` object? | Medium |
| SIP trunk endpoint | Is there a `siptrunk` or `trunk` object? | Medium |
| Answer rules endpoint | Is there an `answerrule` or `callforward` object? | Medium |
| CNAM endpoint | ViiBE screenshots show CNAM tab — is this a ViiBE-only feature or available via RingLogix? | Medium |
| OAuth scope grants | Read endpoints may need scope grants from RingLogix support (Hussain Alkalaf, hussain@ringlogix.com, 440-382-3223) | Medium |
| Rate limiting | 429 observed — current sync script uses 0.5s delay. Portal must match. | Low |
### Design Constraints (from Owner)
- **Light/neutral theme ONLY** — white/light gray backgrounds, dark text. No dark mode for customer-facing portal.
- **Mobile-first** — all views must be usable on ≤375px screens.
- **No framework dependencies** — single-file HTML SPA, no React/Vue/Angular.
- **Google Fonts (Inter) only external dependency.**
- **No fabricated data** — every unwired view shows canonical "No data available." empty state.
- **Canonical nav** — sidebar with `data-view` attributes, `switchView()` dispatch.
---
## Out of Scope (Deferred to Post-MVP)
| Feature | Reason |
|---|---|
| AI Receptionist integration | Separate product (see [ai-receptionist.md](./ai-receptionist.md)), not portal-bound |
| Twilio call handling | Twilio setup is infrastructure, not portal feature |
| Competitor price monitoring | Covered in [competitor-analysis.md](./competitor-analysis.md) — not portal feature |
| WordPress marketing site | `voipsimplicity.com` is a separate WordPress site, out of portal scope |
| Full RingLogix admin replacement | Portal is customer-facing + staff review, NOT a full admin panel replacement |
| International numbers / multi-currency | US-only for MVP |
| Developer APIs / webhooks | Post-MVP |
| White-label reskinning | Post-MVP |
| Mobile native app | Web-only SPA for MVP; PWA wrapper considered for Phase 4 |
---
*Document maintained in `/root/projects/voipsimplicity/PORTAL-REQUIREMENTS.md`. Companion gap analysis at [PORTAL-GAP-ANALYSIS.md](./PORTAL-GAP-ANALYSIS.md).*