Commit Graph

708 Commits

Author SHA1 Message Date
Thiago Youssef bd0a749f22 Bump rails requestjs version 2025-12-17 20:18:38 -03:00
Jeremy Daer c691d39ecf Integrate fizzy-saas as vendored gem at saas/
- Update Gemfile.saas to use path: "saas" instead of GitHub source
- Update config/database.yml to reference local saas/ directory
- Update bin/setup to source saas/bin/setup directly
- Remove redundant dotfiles (ruby-version, gitignore, rubocop, github workflows)
- Add saas/db exclusions to root rubocop config
2025-12-16 12:25:22 -08:00
Jeremy Daer 97ffe00672 My life for a trailing comma 2025-12-16 09:54:04 -08:00
Jeremy Daer a68bd2775d Fix Tailscale host match. Rails wraps the regexp in its own anchors and port-match. 2025-12-16 09:35:26 -08:00
Jorge Manrubia ee80b87c8c Add billing system with Stripe
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Jason Zimdars <jz@37signals.com>
2025-12-16 16:44:20 +01:00
Kevin McConnell 741eff7bdc Revert "Merge pull request #1865 from basecamp/public-avatar-caching"
This reverts commit c628f14c01, reversing
changes made to 4bafc73236.
2025-12-15 13:07:13 +00:00
Kevin McConnell c628f14c01 Merge pull request #1865 from basecamp/public-avatar-caching
Serve own avatar from its own endpoint
2025-12-15 12:20:28 +00:00
Mike Dalessio e9cb2956ee Lightbox uses Stimulus target callbacks instead of data-action
Remove data-action from the sanitizer allowlist to disallow injection
of potentially malicious Stimulus actions in user-provided
content. The lightbox controller now uses imageTarget callbacks to
handle clicks on image links.

Also add the file name as a caption in the light box, and fix the
caption color for dark mode visibility.
2025-12-13 17:06:03 -05:00
nu-wa 472dbeee8c SMTP: support SMTPS on port 465 (#2132)
* Add more configuration options for the SMTP connection

* Add SMTP_TLS option for implicit TLS connections

For SMTPS servers (typically port 465), set SMTP_TLS=true.
Port auto-defaults to 465 when TLS is enabled, 587 otherwise.
STARTTLS is used by default and automatically disabled when TLS is on.

Fixes boolean conversion bug in original PR (string "false" is truthy)
and removes insecure default for certificate verification.

---------

Co-authored-by: Jeremy Daer <jeremy@37signals.com>
2025-12-13 10:57:08 -08:00
Mike Dalessio db4c8c1138 Introduce Vips configuration 2025-12-13 12:41:37 -05:00
Jeremy Daer 82626f020d Tailscale serve support (#2126)
Ensure we can serve the app from multiple hosts without breaking links.
* Switch unnecessary full URLs to paths
* Drop default host/port URL options for controllers

Shell 1
```bash
bin/dev
```

Shell 2
```bash
tailscale serve http://fizzy.localhost:3006
```
2025-12-13 09:29:50 -08:00
Mike Dalessio 7d6cf62665 CSP config to allow Minio in development 2025-12-12 17:00:17 -05:00
Kevin McConnell 4218f2e161 Document Docker image deployment
Also split the README a bit, to move the details under /docs.
2025-12-12 17:26:50 +00:00
Kevin McConnell 0c2d3cccb1 Merge pull request #2084 from basecamp/disable-ssl-env
Add `DSIABLE_SSL` env option
2025-12-12 09:40:21 +00:00
Kevin McConnell eec96ff384 Serve own avatar from its own endpoint
This allows us to have different cache controls depending on whether
you're viewing your own avatar, or someone else's. Your own avatar will
always be fresh, while other folks' avatars can be pulled from the CDN.
2025-12-12 09:03:35 +00:00
Jeremy Daer 586015c3f9 Bundle drift detection and correction (#2101)
Gemfile.saas evals Gemfile, so shared gems should have identical versions
in both lockfiles. This adds bin/bundle-drift to detect and fix drift:

* `bin/bundle-drift check` compares shared gem versions
* `bin/bundle-drift correct` seeds Gemfile.lock from Gemfile.saas.lock
  and re-locks, letting Bundler prune SaaS-only gems while preserving
  shared versions

Adds drift check to bin/ci and GitHub CI. Corrects existing drift.
2025-12-11 21:32:34 -08:00
Javier Valencia 8f68e13707 Fix indentation in multi_db.rb initializer (#2082) 2025-12-11 20:37:28 -08:00
Kevin McConnell 154a3d79ee Add DSIABLE_SSL env option
`assume_ssl` and `force_ssl` are often used together:

- When running behind a terminating proxy (including Thruster) you'll
  want both.
- When running without SSL (like on localhost) you'll want neither.

To simplify setup for those cases, we add the `DISABLE_SSL` option. When
set to `true` all SSL-related behaviour is turned off. When left as the
default, it's on.

We can still use `ASSUME_SSL` and `FORCE_SSL` to set those separately
if required.
2025-12-11 16:11:18 +00:00
Thiago Youssef 36419c3600 Bump rails version to remove svg renderer patch (#2081) 2025-12-11 15:15:54 +01:00
Kevin McConnell 193a28f6c8 Merge pull request #2035 from harisadam/single_tenant
Add env-configurable option to disable public signups
2025-12-11 13:08:19 +00:00
Kevin McConnell 06bfe2c982 Scope the config option
Also use a `configure` block to set it up.
2025-12-11 11:28:32 +00:00
Kevin McConnell 0e443d3602 Use initializer to configure tenant mode 2025-12-11 11:20:43 +00:00
Stanko K.R. 5ee10800a2 Allow direct uploads via API 2025-12-11 11:52:38 +01:00
Adam Haris f76309d116 Merge branch 'main' into single_tenant 2025-12-11 06:08:01 +01:00
Jeremy Daer 22da6dc19d CSP: full config with env vars per source (#2069)
* Configure all sources with CSP_* vars. Space separated source list.
* Fall back to `config.x.content_security_policy.*`
* Move our sources to fizzy-saas

References https://github.com/basecamp/fizzy-saas/pull/24
2025-12-10 17:21:09 -08:00
Jeremy Daer 761d0b4a76 Speedy, auditable, deadlock-resistant storage tracking (#2026)
An append-only storage ledger replaces deadlock-prone synchronous
counter updates and drift-prone async updates.

All content storage (card images, card/comment/board description embeds)
is tracked. Account exports (which expire) and avatars are not tracked.

Storage is accounted for by Account and Board. Both consume the same
event stream independently: no bubble-up storage bumps triggering
deadlocks due to lock sequencing. Each calculates its own total from
the underlying ledger with independent cursors and materialization.

* Storage::Entry: Append-only ledger recording attach/detach/transfer
  events with delta bytes. Single event stream indexed for both
  Account and Board cursor queries.

* Storage::Total: Polymorphic snapshot cache with cursor (last_entry_id)
  tracking which entries have been materialized.

* Storage::Totaled concern: Provides bytes_used (fast snapshot) and
  bytes_used_exact (snapshot + pending) query modes, plus
  materialize_storage! to roll up pending entries.

* Storage::Tracked concern: For models owning attachments (Card,
  Comment, Board). Provides board_for_storage_tracking for models
  where board is determined differently (Board returns self).
  Handles board transfers by recording transfer_out/transfer_in entries.

* Storage::AttachmentTracking: Hooks ActiveStorage::Attachment lifecycle
  to record attach/detach entries. Handles ActionText::RichText embeds
  by traversing to the actual model. Snapshots context in before_destroy
  to handle cascading deletes where parent record may be gone by
  after_destroy_commit.

* MaterializeJob: Rolls up pending entries into snapshot. Concurrency
  limited per owner to prevent duplicate work.

* ReconcileJob: On-demand reconciliation against actual attachment
  storage for support/debugging. Compares ledger total to real bytes
  from card images, card embeds, comment embeds, and board embeds.

Usage:
* account.bytes_used / board.bytes_used: fast, slightly stale bytesize
* account.bytes_used_exact / board.bytes_used_exact: real-time bytesize
* Storage::Entry: audit trail for debugging and point-in-time queries
2025-12-10 16:04:30 -08:00
Hosmel Quintana df9a4b255c make MySQL SSL mode configurable via env var (#2036) 2025-12-10 13:22:38 -08:00
Kevin McConnell 858439a5de Merge pull request #2051 from basecamp/run-jobs-by-default
In non-SaaS, run jobs in container by default
2025-12-10 16:59:24 +00:00
Stanko Krtalić 754aaa5a76 Merge pull request #1766 from basecamp/basic-api
Add basic API
2025-12-10 15:43:58 +01:00
Kevin McConnell 2a3fda02f4 Merge pull request #1939 from hosmelq/active-storage-env-config
Make Active Storage service configurable
2025-12-10 14:36:47 +00:00
Adam Haris eb8655dc8e refactor: use MULTI_TENANT env variable, model concern instead of controller (#accepting_signups?) 2025-12-10 15:14:22 +01:00
Stanko K.R. 5ce71bf941 Move Identities to My::Identities 2025-12-10 15:13:35 +01:00
Kevin McConnell a5396bbb1a Don't overwrite storage service from engine 2025-12-10 14:08:08 +00:00
Kevin McConnell 6f002b66d8 In non-SaaS, run jobs in container by default 2025-12-10 12:32:35 +00:00
Jay Ohms 26fc9ecad4 Add an /identity.json endpoint to obtain the identity accounts and users 2025-12-10 09:23:52 +01:00
Jay Ohms 680f9c0c4d Add top-level API index support for tags 2025-12-10 09:23:52 +01:00
David Heinemeier Hansson 88902485e1 Access tokens are strictly personal 2025-12-10 09:23:52 +01:00
Jason Zimdars 073d1af862 List, create, and revoke access tokens 2025-12-10 09:23:52 +01:00
Adam Haris 0780b5168f add env variable to disable multi-tenancy 2025-12-09 15:40:01 +01:00
Kevin McConnell 0430ce0620 Merge pull request #1911 from harisadam/main
Configure email delivery in production using environment variables
2025-12-09 12:56:03 +00:00
Kevin McConnell 99bee0e0e0 Make SMTP config conditional on SMTP_ADDRESS
- If `SMTP_ADDRESS` is set, configure Action Mailer to use it, along
  with additional optional SMTP-related settings.
- Otherwise, don't set config (for compatibility with engines like
  fizzy-saas).
- Remove sendmail env setup, since by default there is no sendmail in
  the container, and custom deployment can use whatever config the want
  directly. If we end up needing this, we can bring it back via its
  own env.
2025-12-09 12:44:36 +00:00
Adam Haris 9de59ca37b default to smtp 2025-12-09 11:54:45 +00:00
Adam Haris 1d5654cafa configurable actionmailer settings (ENV) 2025-12-09 11:54:44 +00:00
Jorge Manrubia da2bd2f2ec Merge pull request #2024 from basecamp/immediate-variant-locally
Process blob variants using local files
2025-12-09 12:17:12 +01:00
Lewis Buckley a2d4f3431e Merge pull request #2018 from basecamp/ssl-config
Allow configuring SSL in production with ENV vars
2025-12-09 00:51:08 -08:00
Jeremy Daer 8eb01da057 Process blob variants using local files
Rails does post-upload variant processing using the same file upload
in https://github.com/rails/rails/pull/56327

Unrelated Lexxy bump:
Pulls in https://github.com/basecamp/lexxy/pull/493 to work around `dom_id`
removal from ActionText tag in https://github.com/rails/rails/pull/51238
2025-12-08 23:41:15 -08:00
Jeremy Daer 08896deb32 bin/ci: run OSS suite in SAAS mode for full coverage (#2029) 2025-12-08 23:33:46 -08:00
Hosmel Quintana 2eeeda9bad rename Active Storage service to s3 and add checksum env 2025-12-08 18:33:27 -06:00
Hosmel Quintana ac1f935d53 Update config/environments/production.rb
Co-authored-by: Alex Ghiculescu <alex@tanda.co>
2025-12-08 18:33:27 -06:00
Hosmel Quintana b3bc0bb2ff allow configuring Active Storage service and add AWS S3 definition 2025-12-08 18:33:27 -06:00