39 Commits

Author SHA1 Message Date
Jorge Manrubia cf10dbd91e Add 1GB storage cap with staff bypass (#2729)
Re-applies the storage limit from #2713 (reverted in #2715) with an
exception for staff identities so our own account isn't blocked.
2026-03-19 12:38:39 +01:00
Jorge Manrubia 0be8041953 Revert "Add 1GB storage cap with self-host notice" 2026-03-17 17:51:07 +01:00
Jorge Manrubia a761d809ae Add 1GB storage limit with self-host notice for SaaS
Limit free storage to 1GB on the SaaS version. When exceeded, card
publishing, comment creation, and JSON card creation are blocked,
and the card footer shows a "self-host Fizzy for unlimited storage"
notice instead of the create buttons. A nearing-limit warning
appears when usage exceeds 500MB.

Uses the same SaaS engine patterns as the removed billing system:
model concern on Account, controller concerns included via
config.to_prepare, view partials in saas/ with Fizzy.saas? guards
in the main app.
2026-03-17 12:21:32 +01:00
Jorge Manrubia 964915bc66 Remove payment/subscription system and card/storage limits
Fizzy is now free. Remove the entire Stripe billing system,
subscription management, and card/storage limit enforcement.

Removes from saas/: Plan model, Account::Billing, Account::Subscription,
Account::Limited, Account::OverriddenLimits, Account::BillingWaiver,
all subscription/billing controllers and views, Stripe webhook handler,
card creation/publishing limit enforcement, admin account override UI,
usage report rake task, and all related tests.

Removes from main app: Fizzy.saas? guards for subscription panel,
SaaS card footer override, near-limit notices, and saas.css stylesheet.

Adds migration to drop billing tables from the SaaS database.

Non-billing SaaS features (push notifications, signup, authorization,
telemetry, console1984/audits1984) are preserved.
2026-03-17 09:22:04 +01:00
Rosa Gutierrez 53df0e405b Move devices endpoint from /devices to /my/devices
Keep legacy /devices routes for backwards compatibility with mobile
apps not yet updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:30:41 +01:00
Adrien Maston 0caf9b057b Update empty state test 2026-03-02 10:20:58 +01:00
Rosa Gutierrez abef50c503 Fix devices_path route helper in native devices partial
The manage devices link used `devices_path` but the route is defined in
the saas engine, so it needs `saas.devices_path`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 19:31:13 +01:00
Rosa Gutierrez 1b53396050 Make devices controller untenanted with engine routes
- Add disallow_account_scope to skip tenant requirement
- Move routes to saas/config/routes.rb (engine routes)
- Use saas.devices_path/saas.device_path for engine route helpers
- Update tests to work without tenant context

Devices belong to Identity (global), not Account, so they don't
need tenant context in the URL.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-25 19:31:13 +01:00
Rosa Gutierrez 555132bbef Change device ownership from User to Identity
Devices now belong to Identity instead of User, allowing a single
device registration to work across all accounts an identity has
access to.

- Move User::Devices to Identity::Devices
- Update DevicesController to use Current.identity
- Update NotificationPusher::Native to use user.identity.devices
- Clean up tests to use @identity directly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Fix reference to `user.devices`, left-over from the identity switch
2026-02-25 19:31:13 +01:00
Rosa Gutierrez d3cc79a5bc Simplify device routes and use ActiveRecord validations
- Use RESTful DELETE /devices/:id where :id can be token or database ID
- Remove redundant unregister collection route
- Remove old Users::DevicesController
- Return 404 when device not found instead of silently succeeding
- Return 422 for invalid platform via ActiveRecord validation
- Update action_push_native to main branch (includes validate: true on enum)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-25 19:31:13 +01:00
Rosa Gutierrez 9d32f3e845 Refactor devices controller and extract registration to model
- Remove Users namespace from DevicesController (now just DevicesController)
- Create ApplicationPushDevice model extending ActionPushNative::Device
- Move device registration logic (find_or_initialize + update) to model
- Update User::Devices concern to use ApplicationPushDevice
- Fix push notification tests (endpoint validation, job count expectations)
- Update push_config_test to use ActionPushNative.config

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-25 19:31:13 +01:00
Fernando Olivares 29d3960a3c Remove UUID requirement from push notification device registration
- Remove UUID column from devices table entirely
- Update unique index from (owner, uuid) to (owner, token)
- Simplify create action to just create device records
- Add token-based unregister route for API clients
- Consolidate error handling with rescue_from
- Update fixtures to remove uuid references

Devices are now identified by (owner, token) instead of UUID.
This simplifies the client-side registration flow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-25 19:31:13 +01:00
Fernando Olivares 3c54cd84fc Add native push notification infrastructure
- Add action_push_native gem and SaaS configuration
- Add device registration API and UI
- Add User::Devices concern
- Add NotificationPusher::Native for push delivery
- Add tests and fixtures for native push
2026-02-25 19:31:13 +01:00
Mike Dalessio 89d2f2d0fc saas: Add bearer token authentication for audit console
- Rename SaasAdminController to Admin::AuditController
- Override require_authentication to support bearer tokens alongside
  session auth, allowing API access to audit console
- Add migration for audits1984_auditor_tokens table
- Add controller tests for authentication scenarios including staff
  validation on token-based access

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 14:13:54 -05:00
Mike Dalessio 3b13c8573e saas: Backfill tests for admin audit endpoints 2026-01-28 12:55:28 -05:00
Jorge Manrubia f58a1aeb31 Use a dedicated resource for showing cards in draft mode
Mobile team needs this. Also, this lets us get rid from some conditionals for handling
both modes with a single template.

https://3.basecamp.com/2914079/buckets/44843469/messages/9437287330
2026-01-08 10:40:21 +01:00
Jorge Manrubia 766cde4775 Tidy up test 2025-12-19 15:15:00 +01:00
Jorge Manrubia 7bf701095c Fix tests after the UI/copy changes 2025-12-18 10:05:13 +01:00
Jorge Manrubia 0f9d1df31b Format 2025-12-18 10:05:13 +01:00
Jorge Manrubia 00cab8ad7a Add tests for subscription-related messaging 2025-12-18 10:04:15 +01:00
Jorge Manrubia 4e6274d59a Consider storage when preventing backend card creation and publishing too 2025-12-18 10:04:15 +01:00
Jorge Manrubia 68cec74436 Extract parent class, validate plans can be downgraded/upgraded 2025-12-18 10:04:15 +01:00
Jorge Manrubia c56dbb5f1e Add upgrade/downgrade options 2025-12-18 10:04:15 +01:00
Jorge Manrubia 8205823588 Add button to buy extra-storage subscriptions 2025-12-18 10:04:15 +01:00
Jorge Manrubia 3c197debd2 Format 2025-12-16 12:00:46 +01:00
Jorge Manrubia 3395b8d6ed Grab and show the next amount to pay from Stripe 2025-12-16 12:00:23 +01:00
Jorge Manrubia 8dd31e3635 Add system to comp accounts 2025-12-16 12:00:23 +01:00
Jorge Manrubia 3ef5e4eeef Add record to track overridden limits
Before, we were relying on just changing the cards_count in account, but this
could create problems where the system to calculate the next card number fails due
to the unique constraint.
2025-12-16 12:00:23 +01:00
Jorge Manrubia c8330a7be8 Don't prevent creating drafts, or you won't get to see the upgrade banner
Instead:

- Always let you create drafts when pressing "Add card"
- Prevent creations of published cards via API
- Prevent publication of cards in all cases when the limit is exceeded
2025-12-16 12:00:23 +01:00
Jorge Manrubia 5be4dca80e Refresh the subscription instead of relying on event payloads
Events can land out of order. See https://github.com/basecamp/fizzy-saas/pull/23#discussion_r2609909558
2025-12-16 12:00:23 +01:00
Jorge Manrubia 984a5dd4ce Add Stripe-based billing system
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Jason Zimdars <jz@37signals.com>
2025-12-16 12:00:23 +01:00
Mike Dalessio d82d68fcd0 Restrict logins to employees in staging
as inferred from the email domain, which must be "@37signals.com" or
"@basecamp.com".
2025-12-12 15:07:16 -05:00
Stanko K.R. 43bf226444 Remove duplicate test 2025-11-29 11:16:01 +01:00
Jorge Manrubia 3d849a202a Move signup code back to the app, leave only queenbee hooks 2025-11-27 12:52:12 +01:00
Jorge Manrubia ebc212c1d7 Fix: the queenbe mocks were not really being applied 2025-11-24 16:26:41 +01:00
Jorge Manrubia 8019aa154f Stub QB requests in tests 2025-11-24 15:59:09 +01:00
Jorge Manrubia 2e4478ffe5 Remove empty dir 2025-11-24 15:43:29 +01:00
Jorge Manrubia 38d0e362aa Move test to the private gem 2025-11-24 15:16:17 +01:00
Jorge Manrubia db57a7ba0f Initial commit: Move fizzy-saas to separate repository 2025-11-23 06:04:20 +01:00