Known Issues and Edge Cases
Last updated: 2026-03-19 Jira ticket: DEV-4 Purpose: Reference document for QA team. Catalogs known issues, edge cases, incomplete features, and testing recommendations across the Pyra codebase.
1. Critical Issues
These must be fixed before production deployment.
1.1 No Rate Limiting on SMS Sends
- File:
server/src/services/twilio/TwilioSmsService.ts:284-286 - Description: No proactive rate limiting before Twilio API calls. System can exceed account limits or trigger unexpected billing.
- Impact: Potential for massive SMS costs, service abuse, or hitting Twilio platform rate limits.
- Test: Simulate 50+ concurrent SMS sends; verify rate limiting prevents excessive API calls.
1.2 A2P 10DLC Regulatory Compliance Missing
- File:
server/src/services/communications/ComplianceService.ts - Description: No validation that an A2P brand is approved before SMS/MMS sends. System can send SMS without proper regulatory registration.
- Impact: Legal and compliance violations (TCPA), potential FCC fines.
- Test: Attempt SMS send without A2P registration; verify system blocks the send.
1.3 SMS Cost Calculation Precision Error
- File:
server/src/services/communications/UsageTrackingService.ts:164 - Description: Falls back to
smsOutboundcount whensmsSegmentsis missing. Multi-segment SMS not properly charged (Twilio charges per segment, not per message). - Impact: Revenue loss on multi-segment messages; billing inaccuracy.
- Test: Send a 200-character SMS (2+ segments); verify cost reflects segment count, not message count.
2. Security Edge Cases
2.1 Soft Authorization Checks Return Null
- File:
server/src/graphql/resolvers/sharedInventoryResolvers.ts:36-55 - Description: Many resolvers return
nullon unauthorized access instead of throwing a FORBIDDEN error. Client can't distinguish "not found" from "forbidden". - Impact: Information leakage (existence of resource revealed by null vs error).
- Test: Query shared inventory as unauthorized user; verify proper 403 response, not null.
2.2 calculateSmsSegments Missing Auth Check
- File:
server/src/graphql/resolvers/communicationResolvers.ts:770-775 - Description: The
calculateSmsSegmentsquery has no authentication check — it directly calls the service without validating the caller. Note:canSendMessage(line 804) does have auth viagetOrganizationId. - Impact: Unauthenticated users can probe SMS segment calculation.
- Test: Call
calculateSmsSegmentswithout auth token; verify it's rejected.
2.3 Test Mode Webhook Validation Bypass
- File:
server/src/routes/twilioWebhookRoutes.ts:18-20 - Description: Webhook signature validation disabled in test mode without additional safeguards.
- Impact: Unauthenticated webhooks possible in staging environments.
- Test: Verify production environment always validates webhook signatures.
2.4 Phone Numbers Logged Without Masking
- File:
server/src/services/twilio/TwilioSmsService.ts:288 - Description: Phone numbers logged in plaintext.
- Impact: PII exposure in logs; compliance risk.
- Test: Check server logs after SMS operations; verify phone numbers are masked.
3. Data Integrity Concerns
3.1 Missing Cascade Delete Rules
- File:
server/prisma/schema.prisma - Description: 6 relations missing
onDelete: CascadeoronDelete: SetNull:- Message -> MessageTemplate
- ScheduledMessage -> Conversation
- ScheduledMessage -> MessageTemplate
- TwilioMessageLog -> Message
- DeadLetterMessage -> Message
- VoiceCallLog -> Message
- Impact: Orphaned records in database after parent deletion.
- Test: Delete a conversation with messages; verify no orphaned TwilioMessageLog or DeadLetterMessage records.
3.2 Duplicate Affiliate Programs Possible
- File:
server/src/services/affiliateService.ts:126-128 - Description: Database lacks unique constraints to prevent duplicate MAIN or ORGANIZATION programs per org.
- Impact: Duplicate affiliate programs silently created; data inconsistency.
- Test: Create two MAIN affiliate programs for the same org; verify the second is rejected.
3.3 Missing Database Indexes
- File:
server/prisma/schema.prisma - Description: Missing composite indexes for high-frequency queries:
[organizationId, customerId, status]on ConversationmessageIdon TwilioMessageLog, TwilioVoiceCallLogoriginalMessageIdon DeadLetterMessage
- Impact: Query performance degradation as data grows.
- Test: Load test with 10K+ messages; measure query latency on these tables.
4. Business Logic Edge Cases
4.1 Delivery Fee Not Implemented
- File:
server/src/services/CheckoutService.ts:423 - Description: Delivery fee calculation is hardcoded to 0. Feature not implemented.
- Impact: All delivery orders have $0 delivery fee.
- Test: Create order with delivery option; verify delivery fee is $0 (expected current behavior).
4.2 Shared Inventory Date-Range Filtering Not Working
- File:
server/src/graphql/resolvers/sharedInventoryResolvers.ts:477-479 - Description:
startDate/endDateparameters accepted but not used to filter holds. Returns point-in-time availability. - Impact: Incorrect availability for date-range queries; potential double-booking of shared inventory.
- Test: Query shared inventory with date range; verify availability reflects holds within that range (currently broken).
4.3 Concurrent Coupon Over-Redemption
- File:
server/src/services/couponService.ts:82-90 - Description: Coupon max uses (
maxUses,maxUsesPerCustomer) checked without transaction locking. - Impact: Two concurrent redemptions can exceed coupon limits.
- Test: Simultaneously redeem a coupon with
maxUses: 1from two sessions; verify only one succeeds.
4.4 Inventory Hold Expiry — Theoretical Edge Case
- File:
server/src/services/inventoryHoldService.ts:88-140 - Description: Row-level locking (
FOR UPDATE) is properly implemented, but expired holds are filtered byexpiresAt > now(). At the exact millisecond boundary of expiry, concurrent requests could theoretically see different availability. The transaction isolation makes exploitation very unlikely. - Impact: Extremely low risk — locking mitigates most scenarios.
- Test: Stress test hold creation with rapid concurrent requests near expiry boundary (likely passes).
4.5 Trial Expiry Notification Not Retry-Safe
- File:
server/src/jobs/trialExpiryWorker.ts:208-212 - Description:
trialExpiredNotifiedflag is set before confirming email delivery. If email send fails, flag is already set and retry won't fire. - Impact: Some organizations don't receive trial expiry notifications.
- Test: Simulate email failure during trial expiry; verify notification is retried.
4.6 Daily Spend Tracking Inaccurate
- File:
server/src/services/communications/FinancialCircuitBreaker.ts:594-627 - Description: Daily spend approximated by dividing monthly spend by days elapsed. Inaccurate after server restarts or mid-day resets.
- Impact: Spending limits may be over or under-enforced.
- Test: Verify spend tracking accuracy after a server restart mid-billing-cycle.
4.7 International SMS Rate Hardcoded
- File:
server/src/services/communications/UsageTrackingService.ts:425 - Description: International SMS uses hardcoded 2x multiplier vs actual Twilio rates.
- Impact: Billing inaccuracy for international SMS.
- Test: Send international SMS; verify cost matches actual Twilio rate, not 2x domestic.
5. Race Conditions and Concurrency
5.1 Voice Webhook Idempotency Not Atomic
- File:
server/src/routes/twilioWebhookRoutes.ts:227-241 - Description: Idempotency check in voice webhook is not atomic. Concurrent duplicate webhooks can process the same event twice.
- Impact: Double-booking, duplicate charges, or duplicate notifications.
- Test: Send duplicate voice webhook payloads simultaneously; verify only one is processed.
5.2 Apollo Cache Race on Rapid Mutations
- File:
client/src/pages/v2/invite-codes.tsx:100-107 - Description: Multiple
refetch()calls in succession after mutations. Second mutation can fire before first refetch completes. - Impact: Stale data displayed; UI shows outdated state.
- Test: Rapidly create/delete invite codes; verify list stays consistent.
5.3 Stale Response Guard Inconsistency
- Files: Various v2 pages
- Description: Some pages use cancellation flag pattern for stale async responses (register.tsx, scheduling hooks), but this pattern is not consistently applied across all async operations.
- Impact: Data inconsistency in pages without the guard.
- Test: Rapidly switch filters/tabs on pages like scheduling, inventory; verify displayed data matches current selection.
6. Frontend / UX Issues
6.1 Silent Error Handling (80+ instances)
- Files:
useNLBSProducts.js,useFileCenter.js,useSharedInventoryGrid.ts,useInventoryHolds.js,usePageSections.js,useThemeManager.js - Description: Errors logged to console only; user gets no visual feedback for operation failures.
- Impact: Users unaware when file uploads, inventory operations, theme saves, etc. fail.
- Test: Simulate network failure during file upload; verify user sees an error message (not just console).
6.2 Production Blockers in Communication Module
- Files:
components/Communication/tabs/InboxView.jsx:131— File upload not implementedcomponents/Communication/tabs/WorkflowManagement.jsx:18— Migration from localStorage to backend incompletecomponents/Communication/tabs/AnalyticsView.jsx:236, 293— Mock data instead of real queriescomponents/Communication/settings/DiagnosticsPanel.jsx:14— SIMULATION_MODE should be false in production
- Impact: Communication module partially functional; some features show fake data.
- Test: Navigate to Communication module; verify each tab loads real data.
6.3 Incomplete V2 Network Pages
- Files:
client/src/pages/v2/network/ - Description: Several network sub-pages have unimplemented features:
- Backlinks: directory page, export, settings persistence not wired
- Analytics: period selector uses mock constants
- Affiliate manage: detail view, commission editor, messaging, bulk ops not wired
- Affiliate settings: not persisted via mutation
- Sponsored content: create flow and marketplace view not wired
- Impact: Network center pages partially functional.
- Test: Navigate to each network sub-page; verify CRUD operations work end-to-end.
6.4 Accessibility Gaps
- Files:
client/src/pages/v2/file-center.tsx:208—<div>withonClickbut noroleor keyboard supportclient/src/pages/v2/organizations.tsx:395—role="button"withoutonKeyDownclient/src/pages/v2/customers.tsx:376—role="button"without keyboard supportclient/src/pages/v2/admin-feedback.tsx:236—role="button"on div without keyboard handler
- Impact: Keyboard-only users cannot interact with these elements.
- Test: Navigate each page using only keyboard (Tab, Enter, Space); verify all interactive elements are reachable and activatable.
6.5 V2 Payment Method Migration Incomplete
- File:
client/src/pages/v2/settings/account.tsx:283 - Description: Stripe card entry component not migrated to v2.
- Impact: Payment method UI may not function correctly in v2 settings.
- Test: Navigate to v2 account settings; attempt to add/update payment method.
6.6 Order Delivery Tracking — Image Integration Pending
- File:
client/src/pages/v2/order-delivery-tracking.tsx:525 - Description: Cloudflare Images fileId integration pending for delivery photo uploads.
- Impact: Delivery proof photos may not persist correctly.
- Test: Upload delivery photo; verify it saves and displays correctly.
7. Form Validation Gaps
7.1 Customer Form
- File:
client/src/pages/v2/add-customer.tsx - Description: Billing address validation is client-side only. Service address validation missing when
sameAsBilling=true. Email format validation not visible. - Test: Submit customer form with invalid email, missing ZIP code, very long name; verify appropriate validation errors.
7.2 Inventory Form
- File:
client/src/pages/v2/inventory-form.tsx - Description: No max-length validation on name/description fields. Custom duration input accepts strings.
- Test: Submit inventory item with 10,000-character name; verify server-side validation catches it.
7.3 Online Store Page Form
- File:
client/src/pages/v2/online-store-page-form.tsx - Description: Title validation only checks
trim(), no length limits. - Test: Create page with very long title (500+ chars); verify behavior.
7.4 Number Input Edge Cases (All Financial Forms)
- Description: Risk of integer overflow, decimal precision issues, and negative values across pricing forms.
- Test: Enter
99999999.999,-1,0.001, andNaNin all price/quantity fields; verify correct handling.
8. Testing Gaps
8.1 Inventory Management Test Suite Disabled
- File:
client/src/tests/pages/InventoryManagement.test.jsx:70 - Description: Entire test suite skipped with
describe.skip()due to JavaScript heap OOM crashes. - Impact: No automated regression testing for inventory operations.
- Action: Investigate OOM root cause (likely test fixture bloat); re-enable tests.
8.2 No V2 Page Unit Tests
- Description: Only auth pages (login, forgot-password, reset-password, not-authorized) have v2 test files. The other 70+ v2 pages have zero test coverage.
- Impact: No automated regression safety for migrated pages.
- Action: Create smoke tests for top 10 v2 pages (dashboard, inventory-list, orders, scheduling, customers, categories, employee-app, file-center, reports, settings).
8.3 Missing Error Boundary Coverage
- Description: Only 6 error boundaries exist across the entire app. Large v2 pages (category-form, order-detail, file-center, inventory-list, express-checkout) have no error boundaries.
- Impact: A single component crash can take down an entire page with no recovery option.
- Action: Add error boundaries wrapping top-level v2 page content.
8.4 Large V2 Pages Approaching 1000-Line Limit
- Description: Several pages are near the ESLint max-lines limit:
category-form.tsx(997 lines)order-detail.tsx(970 lines)file-center.tsx(966 lines)inventory-list.tsx(963 lines)order-charges.tsx(960 lines)express-checkout.tsx(944 lines)
- Impact: Future changes may trigger ESLint failures. Maintenance burden.
- Action: Refactor into smaller sub-components.
9. Incomplete Features
9.1 Voice Channel
- File:
server/src/graphql/resolvers/communicationResolvers.ts:1201-1202 - Description:
sendMessagethrows at runtime ifchannel === 'VOICE'. Transcription webhook endpoint not implemented. - Test: Verify VOICE option is hidden from UI, or that error is handled gracefully.
9.2 BYO Provider Config
- File:
server/src/services/communications/MessageClassificationService.ts:170-172 - Description: "Bring Your Own" SMS provider support is stubbed; always returns
false. - Test: Verify BYO provider option is hidden from UI.
9.3 PDF Report Export
- File:
server/src/services/reportExportService.ts:73-75 - Description: PDF generation not implemented; returns HTML instead of PDF.
- Test: Export a report as PDF; verify file format and content.
9.4 WhatsApp Channel
- File:
server/src/graphql/resolvers/communicationResolvers.ts:2463-2466 - Description: WhatsApp fields return hardcoded
falseornullvalues. - Test: Verify WhatsApp features are hidden from UI if not supported.
9.5 Usage Alert Notifications
- File:
server/src/services/communications/UsageTrackingService.ts:417-418 - Description: Alerts are computed but only logged to console; never delivered to users.
- Test: Exceed a usage threshold; verify no alert notification is received (expected current behavior).
9.6 Sandbox Usage Cache Not Production-Ready
- File:
server/src/services/communications/ComplianceService.ts:122-123 - Description: Sandbox SMS usage tracked in-memory Map; doesn't survive restarts or multi-instance deployments.
- Test: Restart server during sandbox testing; verify usage limits reset (known bug).
10. Caching Issues
10.1 Twilio Client Cache Never Expires
- File:
server/src/services/twilio/TwilioClientFactory.ts:77-79 - Description: In-memory client cache has no expiry. Credential rotation not reflected.
- Impact: Long-running server instances can use stale Twilio credentials.
- Test: Rotate Twilio credentials; verify new credentials take effect without restart.
11. Compliance Gaps
11.1 TCPA Written Consent Not Tracked
- File:
server/src/services/communications/ComplianceService.ts - Description: No tracking of express written consent documentation or proof. Only tracks opt-in flag.
- Impact: Can't prove consent if audited.
- Test: Check consent audit log after customer opt-in; verify proof documentation is captured.
11.2 Voice Opt-In IP Not Captured
- File:
server/src/services/communications/ComplianceService.ts:851-856 - Description: Voice channel doesn't capture consent IP address (SMS does at line 841, EMAIL at line 848, but VOICE omits it).
- Impact: Incomplete audit trail for voice consent compliance.
- Test: Opt in to voice communications; verify IP is logged.
11.3 Consent Source Validation Missing
- File:
server/src/services/communications/ComplianceService.ts:225-244 - Description: Any
ConsentSourcevalue accepted without validation against enum. - Impact: Invalid consent source strings persist in database.
- Test: Submit consent with invalid source value; verify rejection.
12. Stripe / Payment Edge Cases
12.1 Minimum Amount Validation Missing Stripe's $0.50 Floor
- File:
server/src/services/StripeCheckoutService.ts:63-64 - Description: Amount validation checks for positive integers but doesn't enforce Stripe's minimum charge amount ($0.50 USD). Orders with tiny amounts (e.g., $0.01) will fail at the Stripe API with an opaque error.
- Impact: Checkout fails with unhelpful error for small orders.
- Test: Submit checkout with $0.01 subtotal; verify user-friendly error about minimum amount.
12.2 Platform Fee Rounds to $0 for Small Orders
- File:
server/src/services/StripeCheckoutService.ts:67-69 - Description:
Math.floor((amountCents * feeBasisPoints) / 10000)rounds down. For small orders, platform fee can be $0. No validation that fee doesn't exceed order amount. No cap on fee percentage. - Impact: Revenue loss on small orders. Misconfigured fee percentage (>100%) causes Stripe rejection.
- Test: Create $1.00 order with 10% fee; verify fee is 10 cents, not $0. Try 150% fee; verify rejection.
12.3 Stripe Account Link Expiry Not Managed
- File:
server/src/services/StripeConnectService.ts:121-124 - Description: Account links expire after 24 hours. No client-side expiry warning, no server-side refresh mechanism. If a user bookmarks the link or returns the next day, they see a Stripe error page.
- Impact: Poor UX for Stripe Connect onboarding; users may abandon setup.
- Test: Generate onboarding link, wait >24 hours, attempt to use link; verify error handling.
12.4 Stripe Account Deletion Doesn't Check Liabilities
- File:
server/src/services/StripeConnectService.ts:216-246 - Description:
deleteConnectedAccount()deletes from Stripe then clears database. No check for active payouts, disputes, or non-zero balance. Stripe may reject deletion. - Impact: Partial deletion leaves orphaned account in Stripe. Account funds may be trapped.
- Test: Attempt to delete account with pending payout or dispute; verify error handling.
12.5 Webhook Processing Failures Not Retried
- File:
server/src/routes/webhookRoutes.ts:160-174 - Description: Failed webhook events are logged but not retried or dead-lettered. Returns 500, causing Stripe to retry and potentially duplicate-process. No alert to ops about persistent failures.
- Impact: Failed payments may be double-processed on Stripe retry. No monitoring of webhook health.
- Test: Simulate handler error during webhook; verify second attempt doesn't duplicate work.
12.6 Payment Intent Idempotency Key Issue
- File:
server/src/services/StripeCheckoutService.ts:88-90 - Description: Idempotency key uses
orderId, notcartId. If an order is deleted and recreated with the same ID, Stripe returns the old PaymentIntent. - Impact: Cart retry logic can attach to wrong previous PaymentIntent.
- Test: Create order, delete it, recreate with same ID; verify new PaymentIntent is created.
13. Email / Notification Edge Cases
13.1 No Production Guard for Missing RESEND_API_KEY
- File:
server/src/services/ResendEmailService.ts:27-30 - Description: If
RESEND_API_KEYis not set, the service logs a warning but doesn't prevent startup. All email sends silently fail in production if the env var is missing. - Impact: Users never receive verification codes, password resets, or booking confirmations.
- Test: Run server without
RESEND_API_KEY; verify app either refuses to start or gracefully degrades with clear error messages.
14. Image Upload Edge Cases
14.1 No File Size Limits for Cloudflare Uploads
- File:
server/src/services/cloudflareImageService.ts:125-226 - Description:
uploadBase64Image()anduploadBuffer()don't validate image file size or MIME type. No limit on base64 string length. Cloudflare Images has a 10MB limit, but the server doesn't enforce it before sending. - Impact: Users can attempt to upload very large images, causing OOM on server, slow/stalled requests, and unhelpful errors. Potential DoS vector.
- Test: Upload base64 image >10MB; verify helpful error message before it reaches Cloudflare.
Testing Recommendations
Priority 1 — Security
- Authorization bypass attempts on all resolver queries/mutations
- Webhook signature validation in production mode
- Unauthenticated access to
calculateSmsSegmentsquery
Priority 2 — Financial Accuracy
- Multi-segment SMS cost calculation accuracy
- Coupon over-redemption with concurrent checkout requests
- International SMS billing vs actual Twilio rates
- Negative and zero values in all pricing fields
- Stripe minimum amount enforcement ($0.50 floor)
- Platform fee calculation for small orders (rounding to $0)
- Payment Intent idempotency with reused order IDs
Priority 3 — Data Integrity
- Concurrent inventory operations (create, share, unshare)
- Cascade deletes on conversations with messages
- Webhook failure retry and duplicate-processing prevention
Priority 4 — User Experience
- File upload failures with user feedback
- Navigation between v1 and v2 routes (session preservation)
- Mobile responsive testing on all v2 pages
- Keyboard-only navigation audit
- Stripe Connect onboarding with expired account links
- Email delivery when RESEND_API_KEY is missing
Priority 5 — Reliability
- Server restart during active operations (trial expiry, sandbox limits)
- Webhook idempotency under concurrent Twilio callbacks
- Error boundary coverage for large v2 pages
- Image upload size limits (>10MB files)