637 Commits

Author SHA1 Message Date
isra el
fd7e6cac3f feat(billing): introduce Scale plan tier above Pro
Add Scale plan ($29.99/mo, 25k SMS/mo, 15 devices) between Pro and
Custom in the subscription priority chain. Update dashboard upgrade
prompts to surface Scale for Pro users approaching their monthly limit,
and expose Scale upgrade links in subscription-info and account-settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 22:32:13 +03:00
isra el
3f1037373f feat(billing): enforce per-plan device limits and consolidate billingInterval naming
Add deviceLimit to plans (default -1 = unlimited) with per-subscription
customDeviceLimit override, resolved in getEffectiveLimits and exposed
via the usage object. Gateway blocks device creation and disabled to
enabled transitions with 429 once the enabled-device count reaches the
limit; already-enabled devices are never affected and the check fails
open on lookup errors. Send a throttled device_limit_reached email
notification and show approaching/reached banners with an upgrade CTA
in the dashboard device list.

Also replace the isYearly checkout field with billingInterval
('monthly' | 'yearly') across DTO, service, and checkout page (legacy
?billing= param still accepted until the marketing site redeploys).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 18:23:13 +03:00
isra el
288ad7d15a feat(billing): respect selected billing interval in polar checkout
Order the polar products array from the isYearly flag so the chosen
interval is preselected at checkout, forward the ?billing= param from
the checkout page as isYearly, and only reuse cached checkout sessions
that match the requested plan and billing interval and are neither
completed nor abandoned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 17:51:38 +03:00
isra el
6ce9fce9a2 chore(android): bump version to 2.8.0 (versionCode 18)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 09:00:56 +03:00
isra el
243bbdd1d0 feat(android): complete Kotlin migration, UI overhaul, and dashboard polish
Kotlin migration (phases 3-5):
- Port all DTOs, helpers, models, workers, receivers, and services from Java to Kotlin
- Room DB files ported to Kotlin with all logic kept commented out (not yet enabled)
- Add SMSFilterScreen and SMSFilterViewModel in Compose (replaces Java SMSFilterActivity in new UI)
- All helpers exposed as Kotlin objects with @JvmStatic for Java interop

Onboarding improvements:
- Rewrote copy on all 5 onboarding screens (Welcome, Credentials, DeviceSetup, Permissions, SetupComplete)
- Added receive SMS toggle on SetupCompleteScreen (defaults on)
- Gateway now set to enabled by default after successful registration

Dashboard improvements:
- Add receive SMS toggle and SIM subscription ID display in device card
- Add permission warning card when SMS permissions are missing
- Remove all-time stats section (replaced by subscription usage bars)
- Trim Quick Actions to Dashboard + Docs; move Get Support and Share to Settings
- Merge user greeting into TopAppBar subtitle
- Device ID now has inline copy button

Dashboard UI polish (community review fixes):
- Redundant Enabled badge removed; only shows when gateway is Disabled
- Add Gateway label below the main switch for clarity
- Replace infinity symbol with Unlimited in usage display
- SIM subscription IDs use neutral color instead of primary/orange
- Status bar matches background color instead of primary orange

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 08:57:16 +03:00
isra el
9b629d3291 feat(android): new Kotlin/Compose UI with onboarding, dashboard, messages, and settings
Adds a full parallel Jetpack Compose UI alongside the legacy Java/XML app.
Users can switch between UIs via Settings; SplashActivity routes on launch.

New screens:
- Onboarding wizard (QR/manual API key, device registration, permissions)
- Dashboard (device status, all-time stats, subscription card, quick actions)
- Messages tab (SMS history with filter chips, pagination, detail dialog)
- Compose screen (multi-recipient input, send with snackbar feedback)
- Settings (account, gateway, SMS, legal, system, about sections)
- Splash screen with textbee logo and routing logic

Infrastructure:
- Compose BOM 2023.08.00, Material3, Navigation Compose, Kotlin coroutines
- GatewayApiServiceKt (suspend Retrofit interface) + ApiManagerKt singleton
- Kotlin DTOs for stats, subscription, user profile, messages, send SMS
- Material3 theme with brand orange, dark mode safe (dynamicColor = false)

Also adds MIGRATION.md tracking what's done vs what remains to port.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 22:11:27 +03:00
isra el
f6a8f21e64 fix(infra): pin pnpm to v9 in Dockerfiles and update GitHub Actions
pnpm v10 is now the npm "latest" tag but generates a different lockfile
format than v9.0 used in this repo, causing --frozen-lockfile to fail.
Replace corepack pnpm@latest with npm install -g pnpm@9 in api and web
Dockerfiles. Also bump docker/* actions to v3/v6 to resolve Node.js 20
deprecation warnings ahead of the June 2026 forced migration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 07:28:30 +03:00
isra el
08d9015048 remove lifecycle email logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:42:27 +03:00
isra el
c235526583 remove abandoned checkout email logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 13:37:45 +03:00
isra el
3bef5f90a0 feat(billing): wire up all 6 abandoned checkout emails
- Add fourth_reminder to AbandonedEmailType and schema enum
- Replace expiry-based timing with createdAt-based timing so the
  schedule is independent of Stripe session expiry windows
- Register all 6 emails in emailSchedule with correct delays:
  10 min, 1 hr, 24 hr, 3 d, 7 d, 14 d after session creation
- Add isCompleted filter to query so paid users are never emailed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 12:58:39 +03:00
isra el
0e4c7481b9 feat(mail): rewrite abandoned checkout email sequence
Complete rewrite of all 6 abandoned checkout templates for better
conversion and deliverability:

- Remove social media icons from all templates (promotions tab signal)
- Remove fake discounts, fabricated testimonials, and unverifiable
  claims (money-back guarantee, Calendly link)
- Give each email a distinct purpose: recovery nudge (10min), feature
  comparison table (1hr), cost objection handling (24hr), personal
  founder message (3d), honest comparison + low pressure (7d),
  graceful farewell + feedback ask (14d)
- Add opt-out notice to every email footer (required for marketing emails)
- Fix spam trigger subject ' Your textbee pro upgrade is waiting!'
  to 'Your TextBee checkout is still open'
- Standardise year to 2026 and brand to on-brand orange throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 12:53:58 +03:00
isra el
110bdbc3ef feat(api): enhance webhook subscription management
- Added `lastEnabledAt` property to track when a user re-enables a previously disabled webhook, preventing immediate auto-disable due to historical failures.
- Updated `WebhookService` to set `lastEnabledAt` when a webhook is re-enabled and adjusted the auto-disable logic to respect a grace period based on this new property.
2026-05-27 16:15:41 +03:00
isra el
93ac880dd7 chore(api): update polar sdk version 2026-05-24 17:06:04 +03:00
isra el
35a98f3288 infra: update node version for github workflow 2026-05-24 16:56:47 +03:00
isra el
b1c8585e11 chore(api): update polar sdk version 2026-05-24 16:48:39 +03:00
isra el
f4e23ba3d3 fix(api): resolve Mongoose strict type conflict in GatewayService
- Updated device query in GatewayService to cast the filter object, addressing a type collision with the reserved `model` field in Mongoose 9.6. This change maintains the runtime behavior while ensuring type compatibility.
2026-05-24 16:39:33 +03:00
isra el
1b35e76d82 chore(web): improve webhooks section ui 2026-05-24 16:32:20 +03:00
isra el
8046324c48 fix(api): disambiguate model query in GatewayService
- Updated the model query in GatewayService to use $eq for clarity, resolving a conflict with Mongoose Query.model in TypeScript 9.6+.
2026-05-24 14:08:07 +03:00
isra el
31a69e62ee fix(web): improve date formatting and device label handling in webhook table
- Updated formatDate function to handle undefined and invalid date strings.
- Introduced buildDeviceLabel function to construct device labels more robustly.
- Refactored deviceName mapping in ProductClient to utilize the new buildDeviceLabel function.
2026-05-24 14:07:23 +03:00
isra el
336bb65e0a feat(web): allow multiple webhook subscriptions 2026-05-24 13:35:59 +03:00
isra el
c952040b2b feat(api): allow multiple webhook subscriptions 2026-05-24 13:35:32 +03:00
isra el
cf02c3c50d fix(android): remove unnecessary usesCleartextTraffic attribute from AndroidManifest
- Removed the usesCleartextTraffic attribute from the AndroidManifest.xml file as it is no longer needed.
2026-04-20 00:25:14 +03:00
isra el
004f50d82d refactor(android): remove unnecessary SMS permissions and adjust receiver priority
- Removed READ_SMS permission from AndroidManifest and AppConstants.
- Updated SMSBroadcastReceiver intent filter priority from maximum to a standard value.
2026-04-20 00:20:36 +03:00
isra el
f6556ea512 feat(web): show past-due billing alert with Polar portal CTA
Add dashboard banner when subscription status is past_due for paid plans.
Links to Polar customer portal via existing polarCustomerPortalRequestUrl.
2026-04-05 19:24:21 +03:00
isra el
7e9c036ec1 fix(web): structural skeleton for Get Started card while whoAmI loads
Replace the monolithic h-64 skeleton with GetStartedCardSkeleton that mirrors
the card header and step list so first paint matches the loaded layout.

Made-with: Cursor
2026-04-05 18:05:05 +03:00
isra el
1a5e095c56 fix(api): use subscription document _id in webhook updateOne filters
Mongoose 9 updateOne expects an ObjectId for _id; webhookSubscriptionId
was inferred as ObjectId | WebhookSubscription in CI, causing TS2769.
Use webhookSubscription._id after findById instead.

Made-with: Cursor
2026-04-05 17:43:18 +03:00
isra el
6f5190aade feat(web): prefill Polar customer portal with user email
Add polarCustomerPortalRequestUrl() pointing to /portal/request with a
URL-encoded email query when available. Wire Manage Subscription links in
account settings and subscription info; subscription info loads currentUser
via whoAmI (shared React Query cache with account settings).

Made-with: Cursor
2026-04-05 17:34:14 +03:00
isra el
aea2d27fbb feat(web): allow device deletion 2026-04-05 10:01:25 +03:00
isra el
9586712712 feat(api): enhance API key retrieval logic
- Added a new method in AuthService to find active API keys using a masked match and fallback to regex.
- Updated OptionalAuthGuard and AuthGuard to utilize the new method for improved API key validation.
- Introduced an index on the apiKey field in the ApiKey schema for optimized query performance.
2026-04-05 09:32:41 +03:00
isra el
77f2f38686 chore: improve API key management
- Added a query parameter to filter API keys by status (active, revoked, all) in the getApiKey endpoint.
- Updated the AuthService to handle status filtering logic for API key retrieval.
- Modified the frontend to support status-based API key listing and added a button to view revoked keys.
2026-04-01 07:41:02 +03:00
isra el
5467a85fb0 chore(api): allow device deletion 2026-03-31 22:59:16 +03:00
isra el
9b6e044aa2 Revert "chore(web): update dashboard banners"
This reverts commit f64a520b86.
2026-03-31 15:16:19 +03:00
isra el
8286938b9e ux: improve onboarding steps 2026-03-31 05:16:13 +03:00
isra el
f64a520b86 chore(web): update dashboard banners 2026-03-30 15:02:51 +03:00
isra el
4da8570cd2 feat(api): add fallback for SMS document insertion
- Implemented a check for the existence of the insertMany method in the SMS model to enhance flexibility.
- Added a fallback mechanism for models that do not support insertMany, allowing for individual document creation.
- Improved SMS document insertion process by maintaining performance while ensuring compatibility with various model types.
2026-03-24 17:54:40 +03:00
isra el
839ad24c83 feat(api): enhance SMS processing and queue management
- Introduced batching for SMS document insertion to improve performance.
- Added metadata tracking for SMS to FCM message mapping.
- Implemented error handling for mismatched SMS records and queue payloads.
- Updated SMS queue service to support dynamic batch sizes and immediate queue delays.
2026-03-24 17:24:10 +03:00
isra el
af03623396 fix(api): enhance SMS queue processing and error handling
- Refactored SMS status updates in SmsQueueProcessor to batch updates for failed and dispatched SMS records.
- Improved error handling by collecting failed SMS details and updating their status in a single operation.
- Updated the SMS queue registration to use asynchronous configuration with dynamic limits from the ConfigService.
2026-03-24 17:23:57 +03:00
isra el
ab76237fbb test(api): fix failing tests 2026-03-23 14:22:39 +03:00
isra el
01af5a9786 chore(api): invalidate stale fcm tokens 2026-03-23 14:17:57 +03:00
isra el
7bec9e8acf chore(api): logging improvements 2026-03-23 13:54:52 +03:00
isra el
002ac9c144 chore(web): show update app version cta 2026-03-13 21:54:00 +03:00
isra el
87006c226f refactor(ui): enhance layout and error display in SmsDetailsDialog
- Updated the grid layout for the Info Grid to better represent label-value proportions.
- Improved error details section to display error codes and messages in a full-width format for better visibility.
- Ensured consistent styling for error messages and codes to enhance user experience.
2026-03-12 17:31:12 +03:00
isra el
9d4ec8186b fix(api): improve FCM error handling and messaging in SmsQueueProcessor
- Updated getFcmErrorCode function to remove 'messaging/' prefix from error codes.
- Introduced getFcmErrorMessage function to provide actionable feedback for invalid device tokens.
- Enhanced error messages in SMS processing to utilize the new getFcmErrorMessage function for better clarity.
2026-03-12 17:18:04 +03:00
isra el
dafc433575 fix(ui): improve error display in message history component
- Enhanced error handling in the SmsDetailsDialog to display both error codes and messages.
- Added conditional rendering for error code and message sections to improve clarity for users.
2026-03-12 17:00:21 +03:00
isra el
a87094498c Merge branch 'main' into dev 2026-03-12 16:39:58 +03:00
isra el
c488c16f59 feat(api): enhance SMS status processing and error handling improvements
- Added `dispatchedAt` property to SMS schema and updated status options to include 'dispatched'.
- Implemented logic in SmsQueueProcessor to mark SMS as 'dispatched' upon successful FCM push.
- Enhanced error handling for SMS failures, including specific error codes for FCM delivery issues.
- Updated SmsStatusUpdateTask to handle both 'pending' and 'dispatched' statuses for timeout updates.
2026-03-12 16:38:23 +03:00
Israel Abebe
2c6e3b8e6c Merge pull request #201 from vernu/2026-03-11-yigc
implement batch processing for FCM messages in heartbeat check task
2026-03-11 19:54:04 +03:00
isra el
60808db77a refactor(api): implement batch processing for FCM messages in heartbeat check task 2026-03-11 19:49:52 +03:00
Israel Abebe
a43cf11bcd Merge pull request #200 from vernu/2026-03-11-qmsu
update queue configuration to set removal age for completed and failed SMS tasks
2026-03-11 19:41:04 +03:00
isra el
7a56692586 refactor(api): update queue configuration to set removal age for completed and failed SMS tasks 2026-03-11 19:39:58 +03:00