Mobayilo - Project Status
Mobayilo - Project Status
Section titled “Mobayilo - Project Status”Last Updated: 2026-02-21
Current Phase: Social OAuth Rollout Phase 2 (X implementation + tests)
Branch Policy: Work on development, merge to main when approved.
Current Phase Status
Section titled “Current Phase Status”Current Phase: Social OAuth Rollout Phase 2 (X implementation + tests)
State: 🟡 Google complete; X implementation started on development; Facebook queued after X
Branch: development (merge to main when approved)
Recent updates (2026-02-21)
Section titled “Recent updates (2026-02-21)”- Social login scope finalized: Google, Facebook, and X (x.com) included in roadmap.
- Rollout strategy locked: Provider-by-provider delivery; no one-shot implementation.
- Execution order updated: Google first (done), X second (in progress), Facebook third.
- Safety policy: Existing passwordless flow remains active; social login will not bypass current account/role boundaries.
- New implementation plan added: See
docs/src/content/docs/project-history/SOCIAL_OAUTH_IMPLEMENTATION_PLAN.md. - Google OAuth implemented (Phase 1): Added Devise OmniAuth Google provider, callback controller, and
oauth_identitiesmodel/table. - Boundary enforcement added: Company-seat/claimed-domain and company-account users are routed to magic-link flow in this rollout cycle.
- Google test pass complete (local):
test/integration/google_oauth_sign_in_test.rbandtest/integration/beta_access_test.rbgreen. - Provider priority change approved: X.com is being implemented before Facebook.
Recent updates (2026-02-16)
Section titled “Recent updates (2026-02-16)”- Font GDPR + render path cleanup: Removed Google Fonts CDN import and switched to self-hosted WOFF2 fonts (
Cormorant Garamond,Inconsolata,Geist Mono) withfont-display: swap. - Route-level font preload fix: Added targeted font preloads on Home only to remove unused preload warnings on non-home pages.
- Third-party script deferral: Moved Simple Analytics and Tally loading out of critical path; now loaded on first interaction, with a 10s fallback for analytics.
- Critical-chain reduction: Replaced Cloudflare email-obfuscation dependency in hero copy (
mail_to-> internal contact link) and removed external transparent texture dependency (local CSS background utility). - Image payload reduction: Converted key desktop marketing images to responsive
srcset+sizeswith explicit dimensions to reduce oversized image transfers. - JS bundle optimization: Enabled production minification in
pnpm build, addedbuild:devfor watch mode, and split Twilio SDK into a separate entry (twilio_sdk.js) loaded only where dialer is mounted. - Main-thread task reduction: Updated country selector controller to lazy-build dropdown items on first open/search instead of building all entries at connect.
- Animation hygiene: Removed the flagged non-composited transition from the homepage rate calculator call-type toggle.
- Layout consistency: Switched desktop
/ratesto sharedmarketing_desktop_shelllayout to match/featuresand avoid route-specific maintenance drift. - How-it-works CTA logic: Removed extra Sign In button and made
Start calling nowroute by auth state (/dialif signed in, otherwise/users/sign_in). - Validation: Local CI-equivalent checks passed (
bundler-audit,brakeman,rubocop, JS/CSS build, Rails test, Rails system test) before push toorigin/development(0441a59).
Recent updates (2026-02-12)
Section titled “Recent updates (2026-02-12)”- Twilio cancel/hangup stability: Hardened dialer call-state handling to prevent frozen UI when canceling/ending calls on mobile Safari.
- Dialer controller safety: Added hidden-instance guard + disconnect cleanup so only visible dialer instances initialize and stale device state is torn down cleanly.
- Hangup fail-safe UX: Added client-side hangup safety timeout to force UI recovery when Twilio disconnect events are delayed.
- Voice webhook resilience: Added fail-safe rescue in
Api::Webhooks::TwilioController#voiceto always return valid TwiML instead of surfacing 5xx on unexpected exceptions. - Callback URL hardening: Status callback URL now supports
APP_BASE_URLand enforces HTTPS in production fallback. - Verification: Added/ran controller coverage for fallback TwiML path (
test/controllers/api/webhooks/twilio_controller_test.rb).
Recent updates (2026-02-11)
Section titled “Recent updates (2026-02-11)”- Mobile shell harmonization: Completed light-theme app-like shell across Dialer, Contacts, History, Rates, Settings, and auth touchpoints.
- Strict mobile frame behavior: Preserved
shared/mobile_phone_shellapp-like experience for signed-in mobile users while showing full marketing/homefor signed-out mobile users. - Auth UX in frame: Sign-in + “magic link sent” views now render cleanly in iPhone frame without duplicate headings.
- Rates UX fixes: Fixed “Back to Dialer” placement/visibility, corrected landline/mobile toggle highlight state, and improved country dropdown contrast/readability.
- Navigation/copy polish: Header state labels standardized to
SIGN IN(logged out) andONLINE(logged in); fixed mobile sign-out button contrast. - Dialer fit tuning: Reduced keypad and display spacing/font footprint so the blue call button remains fully visible in mobile Safari viewport.
- Routing bug fix: Resolved missing
contact_pathroute key issue in mobile shell/help center flow. - Docs deploy pipeline: Fixed Cloudflare Pages deploy workflow by aligning pnpm setup (
pnpm/action-setup@v4, pinned pnpm, lockfile install, cache dependency path).
Recent updates (2026-02-10)
Section titled “Recent updates (2026-02-10)”- Contacts Management: Added full CRUD for Contacts (Add, Edit, Delete) with normalized phone number storage.
- UI Harmonization (Desktop): Refined Desktop Dialer to match Light Theme (Blue/White), fixed contrast issues, and unified button styles.
- Mobile Light Theme:
- Converted Mobile App Experience to a consistent Light Theme (
slate-50background, white cards). - Updated
Dialer,Contacts,History,Settings,Ratespages on mobile. - Replaced dark mode components with clean, modern light alternatives.
- Converted Mobile App Experience to a consistent Light Theme (
- UX Improvements:
- Added “Back” links to Contacts/History pages.
- Improved touch targets and spacing for mobile.
- Dynamic “Call” button shadow (Blue for light theme).
Recent updates (2026-02-08)
Section titled “Recent updates (2026-02-08)”- Added Twilio call linkage fields to
calls(parent_call_sid,twilio_price,twilio_price_unit) and indexed parent linkage. - Persisted
ParentCallSidfrom status callbacks and fetch Twilio Call Resource on terminal status. - Added child leg status callbacks on
<Dial>/<Number>so PSTN leg events are captured. - Fixed
statusCallbackEventformat to Twilio-compliant space-separated string. - Validated in production: parent/child linkage appears, parent price captured.
✅ What’s already done (documentation)
Section titled “✅ What’s already done (documentation)”- PRD defined (
docs/PRD.md) - Setup guidance drafted (
docs/SETUP.md) - Architecture notes drafted (
docs/ARCHITECTURE.md) - Market overview drafted (
docs/MARKET_OVERVIEW.md) - MVP analysis captured (
docs/MVP_ANALYSIS_AND_PROPOSAL.md)
🚀 MVP Delivery Goal
Section titled “🚀 MVP Delivery Goal”MVP = individual + company wallets with:
- Browser dialer (WebRTC) → PSTN via Twilio
- Pay-as-you-go credits + ledger
- Stripe top-ups (min $5 individual, min $100 company)
- Company seats (magic link), shared numbers allowed, usage tracked per seat
- Billing: per-started-minute (
ceil(duration_seconds / 60)) - Jobs: Solid Queue
Phase 0: Bootstrap Rails monolith (Target: Day 1)
Section titled “Phase 0: Bootstrap Rails monolith (Target: Day 1)”Objective: Generate the Rails 8.1 app at repo root and run it locally.
- Generate Rails app in repo root (
--database=postgresql --css=tailwind --javascript=esbuild) - Ensure
docs/remains intact and readable - Configure database and run migrations
- Confirm local boot: Rails server starts and serves a home page
- Document required env keys in
docs/SETUP.md
Test checklist (Phase 0)
-
bundle exec rails serverboots without errors - Home page renders at
/
Exit criteria: Rails boots locally and serves pages.
Phase 1: Auth + Accounts (Target: Day 1–2)
Section titled “Phase 1: Auth + Accounts (Target: Day 1–2)”Objective: Support individuals and company admins (password) + company seats (magic link).
- Add
Userauthentication for individuals + company admins (Devise) - Password reset via email (Devise recoverable)
- Add
Company/Accountmodel (wallet owner) - Add company seat login (magic link)
- Add company allowlist policy (domain-based)
- Add basic navigation (mobile-first): Dial / History / Credits / Settings
Test checklist (Phase 1)
- Individual sign up → land on home → bottom nav visible
- Individual sign out → sign in again successfully
- Company admin sign up → account created → allowlist set to admin email domain
- Create seat with allowed domain succeeds; disallowed domain fails
- Seat magic-link sign-in works (email delivered)
- Seat auto-provision works for allowed-domain email (no pre-created seat)
Exit criteria: Individual can sign up/login; company admin can create seats; seat can sign in via magic link.
Phase 1.5: Pre-Flight Fixes (Target: Day 2)
Section titled “Phase 1.5: Pre-Flight Fixes (Target: Day 2)”Objective: Resolve critical architectural gaps before building the ledger and VoIP layers.
Ledger safety
Section titled “Ledger safety”- Add immutable
Transactionmodel with idempotency keys - Add cached balance column on
accounts(computed from ledger) - Add idempotent ledger service for credits/debits
Ownership constraints
Section titled “Ownership constraints”- Validate accounts always have at least one owner user
- Prevent orphaned individual/company accounts (app-level guard)
Phone normalization
Section titled “Phone normalization”- Add
phony_rails(or equivalent) to normalize E.164 numbers - Add
PhoneNormalizableconcern for future Call model
Security baseline
Section titled “Security baseline”- Add
rack-attack - Throttle: login, magic link, token, call initiation
- Remove dev-only SMTP CRL bypass (
SMTP_DISABLE_CRL_CHECK,VERIFY_NONE) before production
Exit criteria: Ledger is safe for concurrent updates, ownership is enforced, phone normalization is ready, and rate limits are in place.
Phase 2: Wallet + Ledger (Target: Day 2–3)
Section titled “Phase 2: Wallet + Ledger (Target: Day 2–3)”Objective: Store balances and an auditable transaction log for both individual and company wallets.
- Balance stored as
*_centsinteger on wallet owner (Account) -
Transactionledger with idempotency keys (avoid double credits/charges) - Basic credits page showing current balance + recent transactions
- Admin-safe “manual adjustment” transaction type
Test checklist (Phase 2)
- Credits page shows current balance + ledger-backed balance
- Create admin adjustment (Avo): positive amount increases balance
- Create admin adjustment (Avo): negative amount decreases balance
- Transaction appears in credits list with type, status, amount
- Idempotency check via console does not double-credit
Exit criteria: You can credit/debit balances in dev with a consistent ledger.
Phase 3: “First Call” thin slice (Target: Day 3–4)
Section titled “Phase 3: “First Call” thin slice (Target: Day 3–4)”Objective: Successfully place an outbound call from the browser to PSTN.
- Twilio token endpoint:
GET /api/calls/token(rate-limited) - TwiML endpoint:
POST /api/webhooks/twilio/voice - Status endpoint:
POST /api/webhooks/twilio/status(persist call lifecycle) - Twilio webhook signatures validated (RequestValidator)
- Webhook processing offloaded to background job
- Dialer page (mobile-first)
- Stimulus controller integrating Twilio Voice JS (connect/disconnect/status)
- Server-side number normalization/validation to E.164 (e.g.,
phony_rails) - Persist Call records from Twilio webhooks
- Attribute calls to account/user/seat from client identity
- Show recent numbers on the dialer (server-side)
Exit criteria: You can dial a real number, it rings, answers, and hangs up cleanly.
Phase 3.1: Security & Quality Hardening (Target: Day 4)
Section titled “Phase 3.1: Security & Quality Hardening (Target: Day 4)”Objective: Address code review findings and improve system robustness.
- Security: Enforce strong parameter permitting in Twilio webhooks
- Observability: Enhanced error logging for Twilio API calls
- Quality: Refactored authentication and async logic
- Testing: Verified webhook security and error handling with integration tests
Phase 3.5: Unified Magic-Link Entry (Target: Day 4)
Section titled “Phase 3.5: Unified Magic-Link Entry (Target: Day 4)”Objective: Single email-first sign-in flow that routes users/seats automatically.
- Single sign-in screen with email-only input
- Existing user → magic link
- Allowed company domain → auto-provision seat + magic link
- Unknown domain → create individual account + magic link
- Navbar/CTA “Get Started” routes to the same entry point
- Async magic-link delivery (
deliver_later) + resend link - Trackable sign-in counters for cleanup
- Daily cleanup job for unconfirmed users (Solid Queue recurring)
- Mismatch handling for
/magicvs/seatslinks with expired link fallback - Add guardrails/observability for domain auto-provisioning (logging, rate limits)
Exit criteria: One entry point handles all sign-ins without account-type selection.
UI Updates (Dialer)
Section titled “UI Updates (Dialer)”Objective: Refresh the dialer UI with a glass + iPhone-style keypad layout.
- Glass/glow background shell for
/dial - iPhone-like dialpad layout with keypad interactions
- Phonebook and balance panels added (design scaffolding)
- Mobile app-like shell for Contacts/History/Settings and compact Credits summary
- Logged-out and logged-in hamburger menus aligned to mobile design
- Desktop pricing calculator now uses live rates + searchable country picker
- Public 404 page styled to match Mobayilo brand
Phase 4: Stripe top-ups + auto top-up (Target: Day 4–6)
Section titled “Phase 4: Stripe top-ups + auto top-up (Target: Day 4–6)”Objective: Users can top up credits and enable auto top-up; balances update reliably.
- Stripe Checkout session for one-time top-ups
- Stripe Checkout (setup mode) for saving a card for auto top-up
- Stripe webhook handler (idempotent) credits wallet balance + stores payment method
- Enforce minimums:
- Individual ≥ $5
- Company ≥ $100
- Auto top-up settings: enabled, threshold, amount, daily cap
- Auto top-up triggers off-session charge when balance < threshold
- Receipt/transaction record created for each top-up
Notes:
- Credits flow now redirects back to
/dialafter successful checkout or settings save. - Auto top-up values are rounded to whole dollars for entry.
Exit criteria: A real Stripe test payment increases wallet balance and auto top-up can charge and record a top-up.
Phase 5: Bill calls and update balances (Target: Day 5–7)
Section titled “Phase 5: Bill calls and update balances (Target: Day 5–7)”Objective: Calls produce costs and deduct credits correctly.
- Persist
Callrecords with Twilio SID and final duration - Billing calculation: per-started-minute
- Deduct credits exactly once on completion (idempotent)
- Call history page with cost and duration
- Seat attribution for company calls (who initiated the call)
Notes:
- Call charge rate uses
CALL_RATE_CENTS_PER_MINUTE(default 5) until rate tables land. - Static rate table now lives in
config/call_rates.ymland is served via/api/rates/:iso - Admin sync actions: “Sync Twilio Voice Rates” (Twilio) and “Sync YAML Call Rates” (static table)
Exit criteria: Balance decreases correctly after completed calls and ledger reconciles.
Phase 5.5: Caller ID & Company Number Enforcement (MVP-CRITICAL) (Target: Day 6–7)
Section titled “Phase 5.5: Caller ID & Company Number Enforcement (MVP-CRITICAL) (Target: Day 6–7)”Objective: Optional Caller ID verification for individuals; server-enforced usage only.
- Account fields for caller ID status + E.164 storage.
- API endpoints: preview, request, confirm.
- Country-required national number input with E.164 normalization.
- Twilio Outgoing Caller ID validation integration.
- Verification audit events logged.
- Cooldown (60s) and daily cap (5 attempts) per account.
- Already-verified Twilio numbers treated as verified.
- Mobile UI: dedicated Caller ID page + menu link for individual accounts.
Exit criteria: Individual users can verify a personal number and the server selects it as caller ID; unverified numbers are never used.
Phase 8: Admin Call Investigation (Twilio Data + Avo) (Target: Day 8–10)
Section titled “Phase 8: Admin Call Investigation (Twilio Data + Avo) (Target: Day 8–10)”Objective: Capture full Twilio call-leg data (no paid SDK/Insights) and provide a clean Avo workflow for support investigations.
Phase 8.1 — Schema (Twilio linkage + pricing fields)
- Add
calls.parent_call_sidfor leg linking (parent ↔ child). - Add
calls.twilio_priceandcalls.twilio_price_unitfor Twilio cost. - Add index on
calls.parent_call_sid. - Document why we are not storing paid SDK/Insights data yet.
Phase 8.1 Tests
- Migration runs and schema loads locally.
- Index on
parent_call_sidexists.
Phase 8.1 Exit criteria: Schema supports parent/child linkage and Twilio price fields. ✅
Phase 8.2 — Data Collection (Webhook + Call Resource fetch)
- Persist
ParentCallSidfrom Twilio status callbacks intocalls.parent_call_sid. - On terminal status, enqueue a job to fetch the Twilio Call Resource.
- Persist
price,price_unit,start_time,end_time,durationfrom Call Resource. - Ensure parent/child linkage is preserved when call legs arrive out of order.
- Child leg callbacks enabled via
<Dial>/<Number>status callbacks.
Phase 8.2 Tests
- Webhook status updates persist
parent_call_sidfor child legs. - Twilio Call Resource fetch populates
twilio_priceandtwilio_price_unit. - Completed calls show
twilio_priceeven if the webhook arrives before the fetch job.
Phase 8.2 Exit criteria: Parent/child linkage is captured in production and parent price is stored. Child price may lag and can be refreshed by re-running the fetch job.
Phase 8.3 — Avo UX (Investigation surfaces)
- Add
Callresource with parent/child links and Twilio pricing fields. - Add
CallerIdEventresource for audit history. - Add
CompanyPhoneNumberresource for company caller ID status. - Enrich
Accountwith caller ID status, company number, and recent calls. - Enrich
Transactionwithrelated_call_idand Twilio Call SID from metadata.
Phase 8.3 Tests
- Avo Call show page links parent and child call legs.
- Avo Transaction show page links to the related call when present.
- Avo Account show page surfaces caller ID status and company number.
Phase 8.3 Exit criteria: Support can trace call legs and billing directly in Avo without manual SQL.
Phase 8.4 — Backfill + QA
- Backfill Twilio pricing for recent calls (batch job or rake task).
- Validate parent/child linking for recent call pairs.
- Reconcile Twilio price per leg vs internal ledger charge.
Phase 8.4 Tests
- Backfill populates
twilio_pricefor at least the last 7 days. - Spot-check parent/child link integrity for real customer calls.
- Verify call leg counts and pricing totals match Twilio console.
Phase 8.4 Exit criteria: Recent call history is populated and Avo investigation workflow is trusted.
Phase 8 Exit criteria: Admin can trace a customer issue from Account → Call (parent/child) → Transaction, with Twilio cost per leg captured and visible in Avo.
Handover Notes (2026-02-08)
- Production TwiML now returns
<Number statusCallback="https://mobayilo.com/api/webhooks/twilio/status" statusCallbackEvent="initiated ringing answered completed" statusCallbackMethod="POST">. - Parent and child legs are now visible in production DB with
parent_call_sidpopulated. - Parent leg price is captured; child leg price may lag and can be refreshed by rerunning
Twilio::FetchCallDetailsJob. - If Twilio REST fetch returns 401, check
TWILIO_ACCOUNT_SIDin runtime env matches theAccountSidin webhook payloads. - Phase 8.3/8.4 (Avo UI + backfill) intentionally deferred; next focus is user feedback on UI.
Post-Phase: Beta Audit Remediation (2026-02-03)
Section titled “Post-Phase: Beta Audit Remediation (2026-02-03)”✅ Senior Engineer Checklist — Beta Audit Remediation
Rule of engagement
No production changes without local validation + CI
No “quick fixes” — every item requires explicit reasoning
If a risk is accepted, it must be documented
🔴 PRIORITY 1 — Must Be Addressed Before Feature Work ☐ 1. Call Balance Guardrail (1-Minute Threshold)
Verification
☐ Trace call initiation flow from request → Twilio call creation.
☐ Identify exact point where balance is checked.
☐ Confirm current logic only blocks when cached_balance_cents <= 0.
☐ Confirm rate resolution happens after call completion.
Risk Analysis
☐ Calculate minimum charge for 1 minute using RateResolver.
☐ Validate scenario: balance > 0 but < 1-minute rate → call allowed.
☐ Quantify worst-case negative balance exposure.
Decision
☐ Define minimum required balance at call start.
☐ Decide behavior when balance is insufficient:
☐ Block call
☐ Allow but cap duration
☐ Allow with overdraft limit
☐ Confirm behavior is race-condition safe.
Pre-merge Validation
☐ Unit tests cover insufficient balance cases.
☐ CI passes.
☐ Manual reasoning documented in PR description.
☐ 2. Webhook Endpoint Throttling (Stripe & Twilio)
Verification
☐ List all webhook routes:
☐ /api/webhooks/stripe
☐ /api/webhooks/twilio/*
☐ Confirm no Rack::Attack throttles apply.
Risk Analysis
☐ Evaluate request cost (DB writes, jobs enqueued).
☐ Consider provider retry behavior on 429s.
☐ Identify safe throttle limits.
Decision
☐ Decide throttle strategy:
☐ IP-based
☐ Endpoint-specific
☐ Provider-aware (Stripe vs Twilio)
☐ Ensure signature verification still runs.
Pre-merge Validation
☐ Throttle rules documented.
☐ CI passes.
☐ No webhook retries unintentionally broken.
🟠 PRIORITY 2 — Security & Financial Integrity ☐ 3. Passwordless Session Expiration & Token Safety
Verification
☐ Identify passwordless gem version.
☐ Confirm defaults for:
☐ Token expiration
☐ Single-use enforcement
☐ Session timeout
☐ Validate against schema (expires_at, timeout_at).
Risk Decision
☐ Are defaults acceptable for beta?
☐ Yes → document acceptance
☐ No → explicit config required
Pre-merge Validation
☐ If changed, tests cover token reuse & expiry.
☐ Security decision recorded in PR.
☐ 4. Stripe Idempotency & DB Constraints
Verification
☐ Confirm current uniqueness:
☐ idempotency_key unique
☐ stripe_payment_intent_id non-unique
☐ Trace all credit creation paths.
Risk Analysis
☐ Identify scenario where a different idempotency key is used.
☐ Assess likelihood of double-credit.
Decision
☐ Decide whether to enforce DB-level uniqueness.
☐ Evaluate migration safety with existing data.
Pre-merge Validation
☐ Migration reviewed for locking risk.
☐ CI passes.
☐ 5. Negative Balance via update_all
Verification
☐ Identify all update_all balance mutations.
☐ Confirm no validation or guardrails are applied.
Risk Analysis
☐ Determine whether negative balances are:
☐ Allowed
☐ Temporarily tolerated
☐ Forbidden
Decision
☐ Define invariant for cached_balance_cents. ☐ Invariant: no negative ledger entries may be persisted.
☐ Ensure solution does not introduce race conditions.
Pre-merge Validation
☐ Tests cover overdraft edge cases.
☐ Decision documented.
🟡 PRIORITY 3 — Operational & Observability ☐ 6. Environment Variable & Log Safety
Verification
☐ Review production logging config.
☐ Confirm no logs include:
☐ Webhook signatures
☐ API keys
☐ Authorization headers
☐ Validate filter_parameter_logging.rb coverage.
Decision
☐ Determine if additional filtering is required.
☐ Or formally accept current risk.
☐ 7. Solid Queue Failure Visibility
Verification
☐ Confirm retry limits (5 attempts).
☐ Identify where discarded jobs surface.
☐ Confirm alerts or dashboards exist.
Decision
☐ Decide if beta needs:
☐ Alerting
☐ Manual review process
☐ Dead-letter handling
🧾 Final Sign-Off (Required)
☐ All Priority 1 items resolved or explicitly accepted
☐ Medium risks documented with rationale
☐ No changes merged without CI green
☐ PR descriptions include risk reasoning, not just code
Priority 3 Verification Notes (2026-02-03)
Section titled “Priority 3 Verification Notes (2026-02-03)”Scope: Verification + documentation only. No behavior changes unless evidence of leak/blind spot is confirmed.
6) Environment Variable & Log Safety
Section titled “6) Environment Variable & Log Safety”- Code review:
config/initializers/filter_parameter_logging.rbfilters common secrets (:secret,:token,:_key,:otp, etc.).config/environments/production.rblogs to STDOUT atinfo, withattributes_for_inspect = [:id]. - Potential gaps: Header-level secrets (
Authorization,Stripe-Signature,X-Twilio-Signature) are not filtered by param filters. - Verification required in prod: Confirm runtime logs do not include webhook headers/payloads or authorization headers (app + platform logs).
- Decision: No code changes unless production log inspection confirms leakage.
7) Solid Queue Failure Visibility
Section titled “7) Solid Queue Failure Visibility”- Code review:
config/initializers/active_job_logging.rblogsdiscard.active_jobandretry_stopped.active_jobto STDOUT. - Verification required in prod: Confirm these warnings are retained and monitored; verify alerting or review process exists.
- Decision: No code changes unless monitoring is absent or discards are not visible.
Verification Gaps to Close (Explicit)
Section titled “Verification Gaps to Close (Explicit)”- Confirm
STRIPE_WEBHOOK_SECRETis present and correct in production. - Confirm webhook payloads/headers are not logged in production (app + platform logs).
- Confirm Solid Queue discarded/retry-stopped logs are visible/retained and tied to alerting or manual review.
Follow-Up Recommendations (If Gaps Confirmed)
Section titled “Follow-Up Recommendations (If Gaps Confirmed)”- Add structured logging filter/middleware to redact sensitive headers.
- Add log-based alert for
ActiveJob discardedandretry_stoppedmessages.
Ops Verification Checklist (Read-Only)
Section titled “Ops Verification Checklist (Read-Only)”- Confirm
STRIPE_WEBHOOK_SECRETis set in production environment and matches Stripe dashboard. - Confirm production logs do not include
Stripe-Signature,X-Twilio-Signature, orAuthorizationheaders. - Confirm production logs do not include full webhook payloads for Stripe/Twilio.
- Confirm
ActiveJob discardedandretry_stoppedmessages are visible in log aggregation. - Confirm a human review or alerting process exists for discarded/retry-stopped jobs. Objective: Enable compliant outbound identity for individuals and companies, close audit blockers, and prepare for public beta.
Individual: Caller ID Verification
Section titled “Individual: Caller ID Verification”- OTP verification via Twilio Verify (anti-abuse gate, balance ≥ $5)
- Optional verified Caller ID using Twilio Outgoing Caller ID validation
- Correct flow implemented:
- Twilio returns validation_code
- User enters code on phone keypad (not website)
- No web-based confirmation endpoint
- Persist pending verification state
- Server-side enforcement at call time:
- Verified Caller ID used when available
- Fallback to Mobayilo default number otherwise
Company: Number Provisioning & Billing
Section titled “Company: Number Provisioning & Billing”- Mandatory Twilio phone number for outbound calls
- Balance pre-check before provisioning (prevents real-money risk)
- Monthly number fee charged (idempotent, once per month)
- Insufficient funds:
- Number suspended
- Outbound calls hard-fail
- Inbound calls explicitly rejected with TwiML message
Security & Compliance
Section titled “Security & Compliance”- Caller ID always chosen server-side
- Client cannot spoof callerId
- Twilio API behavior aligned with SDK constraints (validation_requests.create)
- Audit blocking issues fully resolved
Exit criteria: Caller ID and company number enforcement works end-to-end; no Twilio resources are purchased without funds; audit verdict cleared.
Phase 6 (MVP+): Marketing & Growth (Target: Day 7+)
Section titled “Phase 6 (MVP+): Marketing & Growth (Target: Day 7+)”Objective: Capture leads and enable external subscriptions.
Subscriber API
Section titled “Subscriber API”-
subscriberstable for capturing email interest - JSON API
POST /api/subscribefor public form submissions - Email uniqueness and format validation
- CORS configuration allowing
mobayilo.comrequests - Admin dashboard (Avo) resource for managing subscribers
Exit criteria: Public marketing site can successfully POST emails to the backend.
Phase 7 (Beta): Access Control (Target: Day 7+)
Section titled “Phase 7 (Beta): Access Control (Target: Day 7+)”Objective: Gate sign-ups behind a beta waitlist managed by admins.
- Add
status(waiting/invited) tosubscriberstable - Update
Subscribermodel logic - Protect
Users::SessionsControllerwith beta gatekeeper - “You’re on the list” message for blocked users
- Admin action (Avo) to “Invite to Beta”
- Add case-insensitive unique index on
subscribers.email
Exit criteria: Only invited emails can complete the sign-up flow.
Phase 7.5: Docs + CDN + DB Console Hardening (Target: Day 8+)
Section titled “Phase 7.5: Docs + CDN + DB Console Hardening (Target: Day 8+)”Objective: Ship internal docs safely, serve public assets via CDN, and enable local production console access.
- Active Storage reads now use R2 public domain (
R2_PUBLIC_DOMAIN) - R2
cloudflarestorage markedpublic: truefor direct CDN URLs - Cloudflare Pages docs project created (
mobayilo-docs) + custom domaindocs.mobayilo.com - Docs locked behind Basic Auth (Cloudflare Pages)
- Docs deploy workflow targets
mobayilo-docsproject - Docs build pinned to Node + pnpm only (
docs/.tool-versions) to avoid Ruby install failures - Production DB config flattened with cache/queue/cable URL fallbacks for local CLI
Exit criteria: Docs deploy green, docs domain serves correct content, and local rails console can connect via public DB URL.
Phase 7.6: Social OAuth Rollout (Google → X → Facebook) (Target: Day 9+)
Section titled “Phase 7.6: Social OAuth Rollout (Google → X → Facebook) (Target: Day 9+)”Objective: Add social sign-in safely without breaking existing magic-link authentication.
- Finalize shared OAuth data model (
oauth_identities) and security guardrails. - Implement Google OAuth end-to-end for
Userauth. - Complete Google test checklist (callbacks, linking, conflicts, regressions).
- Validate Google rollout on
developmentwith no passwordless regressions. - Implement X OAuth after Google checklist (safe fallback first for missing email).
- Complete X test checklist and regression checks.
- Implement Facebook OAuth only after X checklist is fully green.
- Complete Facebook test checklist, including provider conflict behavior.
- Keep
CompanySeatauth on magic-link flow for this rollout cycle. - Update docs/support flows after each provider phase completion.
Test checklist (Phase 7.6)
- Google: linked identity sign-in, verified email linking, conflict handling.
- Google: existing passwordless flows remain unchanged.
- X: safe fallback when email is unavailable or unverified.
- Facebook: parity with Google linking/conflict rules.
- Full regression pass before enabling each next provider.
Exit criteria: Google, Facebook, and X are delivered in sequence with full test coverage and no regressions to existing auth/session/account behavior.
Reference plan: docs/src/content/docs/project-history/SOCIAL_OAUTH_IMPLEMENTATION_PLAN.md
Recent updates (2026-02-04)
Section titled “Recent updates (2026-02-04)”- Balance Guardrails: Calls blocked UI-side when balance is empty; redirects to
/creditswith specific warning. - Desktop Content Pages: Added
/how-it-works,/features,/pricing,/testimonialspages with shared design system. - Dynamic Pricing:
/pricingpage now fetches real rates from theCallRatedatabase (US, CA, UK, etc.). - Smart Navigation: Desktop navbar intelligently switches between anchor links (on Home) and full path links (elsewhere).
- Code Quality: Fixed Rubocop offenses in controllers; CI passing.
Recent updates (2026-02-01)
Section titled “Recent updates (2026-02-01)”- Caller ID verification rewritten to match Twilio’s keypad-entry flow
- Company number provisioning now gated by available balance (pre-purchase)
- Server-side caller ID enforcement finalized for individuals and companies
- Audit blocking issues resolved; ready for public beta verification
- Mobile: in-phone shell for Contacts/History/Settings + Credits summary view
- Mobile: hamburger menu polish + sign-in overlay improvements
- Rates: YAML-backed rates table + API integration (individual vs company seat rates)
- Admin: Call Rates visible in Avo; added “Sync YAML Call Rates” action
- Desktop: pricing calculator uses searchable country picker + live rates
- Auth:
/dialnow requires login; “Open Dialer” routes to sign-in when logged out - Misc: styled 404 page; fixed sign-in page background; CSRF hardening for magic link form
- Infrastructure: R2 public CDN domain for Active Storage reads
- Docs: new
mobayilo-docsCloudflare Pages project + Basic Auth - Ops: production DB config flattened with cache/queue/cable fallbacks for local console
What’s missing before opening Public Beta
Section titled “What’s missing before opening Public Beta”- Payments hardening: verify Stripe webhooks in production, SCA fallback, retry UX.
- Rate integrity: finalize rate source of truth (Twilio vs YAML), document update cadence.
- Monitoring/alerts: basic error tracking (Sentry) + uptime checks for Twilio webhooks.
- Abuse controls: finalize rate limits and add logging for domain auto-provisioning.
- Legal/Compliance: finalize Terms/Privacy and add KYC/telephony compliance checks if required.
- Support flow: user-facing help/support channel and basic FAQ.
Phase 8 (MVP+): Auto top-up hardening (optional)
Section titled “Phase 8 (MVP+): Auto top-up hardening (optional)”Objective: Improve reliability, visibility, and safeguards for auto top-up.
- Notify user on auto top-up failures (email + in-app banner)
- Add SCA recovery flow for off-session failures
- Admin dashboard for auto top-up retries and caps
Exit criteria: Auto top-ups are observable with retry + recovery path.
Decisions needed before/during Phase 1
Section titled “Decisions needed before/during Phase 1”- Company seat allowlist: domain-based vs explicit email allowlist
- Number provisioning: company admin self-serve vs manual/admin-only (MVP)
New decisions before Phase 4–5
Section titled “New decisions before Phase 4–5”- Should individual account creation ever be blocked for company-like domains?
- Do we need email-domain verification before auto-provisioning seats?
- Stripe Checkout + setup mode for payments and saved cards
- Subscriber API requires public CORS access? (Yes, implemented)