Commit Graph

9856 Commits

Author SHA1 Message Date
Stanko Krtalić dac4d9233c Merge pull request #2741 from basecamp/dependabot/bundler/aws-sdk-s3-1.216.0
Bump aws-sdk-s3 from 1.215.0 to 1.216.0
2026-03-25 17:28:50 +01:00
Stanko Krtalić 70c08877b7 Merge pull request #2735 from basecamp/dependabot/bundler/bcrypt-3.1.22
Bump bcrypt from 3.1.21 to 3.1.22
2026-03-25 17:23:26 +01:00
Sean Mitchell 4b4454de89 Update colophon icons 2026-03-24 13:32:39 -07:00
Jason Fried 2c60ddb7c7 Added Basecamp + HEY icons/links 2026-03-24 12:12:33 -07:00
Stanko Krtalić 4551952d05 Merge pull request #2749 from basecamp/potential-windows-hello-on-chrome-fix
Use Same-site: Lax
2026-03-24 15:23:52 +01:00
Stanko K.R. c24d4fd7fd Use Same-site: Lax
This is a guess based on a few articles I read where Windows Hello doesn't play nice with Same-Site: Strict. I have no credible evidence to back this up.
2026-03-24 15:17:05 +01:00
Stanko Krtalić 1f63589d7e Merge pull request #2748 from basecamp/fix-passkey-buttons-not-triggering-sometimes
Fix Passkey buttons not triggering sometimes
2026-03-24 14:51:14 +01:00
Stanko K.R. 134a533e28 Fix Passkey buttons not triggering sometimes 2026-03-24 14:36:52 +01:00
Andy Smith 7632802f18 Merge pull request #2682 from nqst/delete-account-improvements
Delete account: design improvements
2026-03-23 09:38:23 -05:00
Stanko Krtalić e3cd789ede Merge pull request #2746 from basecamp/fix-exports
Permit variant records in imports
2026-03-23 12:50:24 +01:00
Stanko K.R. 49fbb82676 Permit variant records in imports 2026-03-23 12:30:40 +01:00
Zacharias Knudsen 6808250c8f Merge pull request #2745 from basecamp/excert-truncation
Pre-truncate excerpt before running replacement regexes
2026-03-23 10:24:58 +01:00
Zacharias Dyna Knudsen 6c771584d7 Pre-truncate excerpt before running replacement regexes
Also fixes <ol> normalization which was previously a noop.
2026-03-23 10:21:35 +01:00
Mike Dalessio bcf6e92131 Merge pull request #2740 from basecamp/autolink-skip-large-text-nodes
Skip auto-linking in very large text nodes
2026-03-20 20:02:57 -04:00
Mike Dalessio 8c3461a1d6 Remove @regexp_timeout_reported from AutoLinkScrubber
No longer needed since the scrubber is not memoized across calls and the
text node length guard prevents the performance issue.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:53:02 -04:00
github-actions[bot] 940fb2fafc Sync Gemfile.saas.lock 2026-03-20 20:24:28 +00:00
dependabot[bot] 4f0a51785e Bump aws-sdk-s3 from 1.215.0 to 1.216.0
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.215.0 to 1.216.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-version: 1.216.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 20:24:17 +00:00
Mike Dalessio 87c659cd67 Skip auto-linking in very large text nodes
A large comment body was causing Regexp::TimeoutError in production.
The URI regexp isn't catastrophically backtracking — it's linear — but
with a long enough string it exceeds the 1s Regexp.timeout set by
Rails.

Skip scanning text nodes over 10KB, which is well beyond any
reasonable content for auto-linking and still keeps us many orders of
magnitued under the timeout on an unloaded machine.

Fixes FIZZY-Q4

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:18:19 -04:00
Mike Dalessio 95a45aa651 Don't memoize AutoLinkScrubber across format_html calls
The scrubber was memoized on the view helper in b0fa6525 so that
@regexp_timeout_reported would stop scanning remaining text nodes
after a timeout. But memoizing on the helper leaks that flag across
all format_html calls for the entire request — if one comment triggers
a timeout, every subsequent comment on the page loses auto-linking.

Use a fresh scrubber per call. The @regexp_timeout_reported flag still
works within a single document's scrub, which is the intended scope.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:03:47 -04:00
Jorge Manrubia 8c46ff52b4 Bump Lexxy to 0.9.0.beta (#2739) 2026-03-20 17:37:09 +01:00
Zacharias Knudsen 743b60d393 Merge pull request #2737 from basecamp/remember-regexp-timeout
Stop scrubbing after first regexp timeout
2026-03-20 12:16:34 +01:00
Zacharias Dyna Knudsen b0fa6525fe Stop scrubbing after first regexp timeout 2026-03-20 12:13:17 +01:00
Zacharias Knudsen 8479be3976 Merge pull request #2736 from basecamp/rescue-regexp-timeout
Rescue regexp timeout
2026-03-20 11:58:14 +01:00
Zacharias Dyna Knudsen 7399ec5bd9 Rescue regexp timeout 2026-03-20 11:55:00 +01:00
github-actions[bot] 6097ac79cc Sync Gemfile.saas.lock 2026-03-19 18:58:13 +00:00
dependabot[bot] a0c0fd3b1f Bump bcrypt from 3.1.21 to 3.1.22
Bumps [bcrypt](https://github.com/bcrypt-ruby/bcrypt-ruby) from 3.1.21 to 3.1.22.
- [Release notes](https://github.com/bcrypt-ruby/bcrypt-ruby/releases)
- [Changelog](https://github.com/bcrypt-ruby/bcrypt-ruby/blob/master/CHANGELOG)
- [Commits](https://github.com/bcrypt-ruby/bcrypt-ruby/compare/v3.1.21...v3.1.22)

---
updated-dependencies:
- dependency-name: bcrypt
  dependency-version: 3.1.22
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-19 18:57:58 +00:00
dependabot[bot] 6538cf80a9 Bump json from 2.19.1 to 2.19.2 (#2730)
* Bump json from 2.19.1 to 2.19.2

Bumps [json](https://github.com/ruby/json) from 2.19.1 to 2.19.2.
- [Release notes](https://github.com/ruby/json/releases)
- [Changelog](https://github.com/ruby/json/blob/master/CHANGES.md)
- [Commits](https://github.com/ruby/json/compare/v2.19.1...v2.19.2)

---
updated-dependencies:
- dependency-name: json
  dependency-version: 2.19.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Sync Gemfile.saas.lock

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-19 09:35:47 -07:00
Jorge Manrubia 1c4bf3e1e0 Add per-account storage exceptions for SaaS (#2733)
Allow granting specific accounts more storage via an
account_storage_exceptions table in the saas DB, without
relying on the blanket staff bypass.
2026-03-19 15:36:36 +01:00
Alexander Zaytsev 6d6f94ce13 Merge branch 'main' into delete-account-improvements 2026-03-19 15:26:31 +01:00
Alexander Zaytsev 754e2e3673 Cancel → Delete 2026-03-19 15:06:37 +01:00
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
Mike Dalessio 11df9c3589 Fix back navigation from activity page to cards (#2727)
Three changes needed to support navigating back from a card to the
activity page:

- Add root_path to the prefer_referrer allowlist on the card show page
- Switch event links from HTML target="_top" to data-turbo-frame="_top"
  so Turbo handles the navigation and turbo:before-visit fires to save
  the referrer
- Normalize trailing slashes in the referrer path comparison so
  /account_id and /account_id/ both match

ref: https://app.fizzy.do/5986089/cards/2390
2026-03-18 22:03:36 -04:00
Mike Dalessio 248fc5d3e7 Fix back navigation from filter views to cards (#2725)
* test: update sign_in_as system test helper to be more generic

and support fixture users with more than one board

* test: backfill a test for the card "back link"

when coming from a board filter page

* Fix back navigation to filter views from cards

When navigating from a filter view to a card, the back link now shows
the filter's label and navigates back to the filter URL instead of the
card's board.

The turbo-navigation Stimulus controller stores the page title alongside
the referrer URL in sessionStorage. On the card show page, a
referrerBackLink target rewrites the back link's href and label from the
stored values. This is scoped only to the card show page to avoid
navigation loops in multi-level deep pages.

* Add referrer allowlist to prevent stale referrer rewrites

The back link is only rewritten when the stored referrer's path matches
an allowlist of paths passed via prefer_referrer. This prevents stale
referrers from unrelated pages (e.g., settings) from overriding the
card's back link.

* Move back link navigation tests to dedicated system test file

Extract back link tests from smoke_test.rb into their own file since
they test specific JavaScript behavior that needs regression coverage.
Move sign_in_as helper to ApplicationSystemTestCase for reuse.

* Move markdown paste tests to dedicated system test file
2026-03-18 17:03:13 -04:00
Daniel Pinto ad1b10368d Fix export size doubling from re-exporting prior export blobs (#2707)
* Exclude export/import blobs and attachments from account exports

Export and import file blobs were being assigned the account's
account_id (via the Current.account default), causing subsequent
exports to include previous export/import ZIP files in the data.
This roughly doubled the export size each time and made imports
fail with an IntegrityError on unrecognized "Account::Export"
record type.

Filter out blobs attached to Export/Import records in
BlobRecordSet, FileRecordSet, and a new AttachmentRecordSet.

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

* Use STI base type for export blob exclusion filter

Rails polymorphic_name returns base_class.name for STI models,
so ActiveStorage stores record_type as "Export" rather than the
concrete subclass names. Filter on the base type accordingly.

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

* Fix export filtering for mixed-use Active Storage blobs

Exclude only internal-only blobs for account export metadata/file sets, scope attachment subqueries by account, and add regression coverage for blobs shared between user records and export attachments.

* Simplify export blob filtering

Exports always create fresh blobs, so a blob can never be legitimately
shared between an Export/Import and a real account record. Replace the
internal_only/external split with a single excluded_blob_ids subquery
and drop the contrived shared-blob test.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 11:41:22 -04:00
Peter Baker e0d66b2fd0 Fix ambiguous column in SQLite FTS multi-term search (#2688)
* Fix multi-term SQLite FTS5 search causing a 500 error

When filtering cards by more than one term, `matching` was called
once per term via an association join. Rails did not deduplicate
association joins, resulting in two JOINs to `search_records_fts`
in a single query. SQLite FTS5 then raised "ambiguous column name"
when evaluating the MATCH condition.

Fix by using a string join instead, which Rails deduplicates so
only one JOIN to `search_records_fts` is generated regardless of
how many terms are searched.

Fixes: https://github.com/basecamp/fizzy/discussions/2354

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: verify multi-term search requires ALL terms to match

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Mike Dalessio <mike@37signals.com>
2026-03-18 11:38:06 -04:00
Stanko Krtalić 5701aad8d7 Merge pull request #2623 from basecamp/passkeys
Passkeys
2026-03-18 14:54:54 +01:00
Stanko K.R. 14f938dbf9 Add demo video for creating a Passkey 2026-03-18 14:48:00 +01:00
Stanko K.R. 1cf1f598e1 Require resident keys by default 2026-03-18 12:14:17 +01:00
Andy Smith 1e245fbe45 Add onboarding card 2026-03-18 12:04:30 +01:00
Stanko K.R. 017bcc9ce1 Polish up Passkey interface
- Fix indentation
- Split awkward initializer into separate methods
- Rename credentials to passkeys
- Simplify authenticator registry loading
- Flatten nested errors under ActionPack::WebAuthn
- Set passkey current params only requests that use it
- Inline anemic methods
- Replace custom validation with ActiveModel::Validation
- Rename identity to holder in Passkey
- Rename credentials to passkeys in JS
- Extract framework library out of controllers
- Pass params hashes down to ActionPack
- Attempt to simplify public interface
- Push data decoding down to the classes representing the data
- Introduce has_passkeys
- Add CBOR bigint support
- Rename ActionPack::WebAuthn::Passkey to ActionPack::Passkey
- Add create_passkey_button helper
- Rename public-key to creation-options
- Add sign_in_with_passkey_button helper
- Dispatch events for the whole Passkey lifecycle
- Add ED25519 support
- Prevent crash on missing meta tag
- Validate resident key options
- Don't clobber existing ActionPack config options
- Validate cryptographic params
- Move CurrentWebAuthnRequest into ActionPack::Passkey
- Use ActiveModel::Attributes for Options objects
- Implement expiring challanges
- Add lifecycle events
- Extract param helpers into Request
- Add passkey_creation_options and passkey_request_options helpers
- Add create_passkey_challenge to make it easier to override the create method if needed
- Prefix all view helpers with passkey_
- Auto-include ActionPack::Passkey::Holder
- Make the passkey challange url configurable
- Add a reminder about Passkeys to the magic link email
2026-03-18 11:51:10 +01:00
Andy Smith f4fbe17b22 Nicer passkey styles 2026-03-18 11:51:09 +01:00
Andy Smith ee7fc3495d Move passkeys button below profile area 2026-03-18 11:51:09 +01:00
Stanko K.R. fbe9252db1 Auto-suggest name for new Passkeys
- Use plain client data json everywhere
- Expose AAGUID and backed_up on Credentials
- Make attestation verifiers configurable
- Auto-suggest names for passkeys and show icons
2026-03-18 11:49:59 +01:00
Stanko K.R. b23660d897 Fix --tailscale not printing hostname 2026-03-18 11:49:59 +01:00
Stanko K.R. da69039476 Implement Passkey authentication 2026-03-18 11:49:23 +01:00
Andy Smith 70c19e4881 Style polish 2026-03-18 11:49:23 +01:00
Stanko K.R. 6c58fd9bdd Implement Passkey registration
- Create Identity credentials
- Add management UI and registration flow
2026-03-18 11:48:52 +01:00
Stanko K.R. 4bb0a2929c Implement WebAuthn protocol
- Add a CBOR decoder
- Add public key credential options
- Add COSE key decoder
- Add authenticator attestation and assertion
- Add credentials
- Add exclude_credentials
2026-03-18 11:47:48 +01:00
Mike Dalessio ba6fc495da ci: fix bin/bundle-drift forward to support native gems (#2723)
See #2704 where only the ruby platform gem for thruster was replaced.
2026-03-17 22:29:47 -04:00
Mike Dalessio fd7986391d Merge pull request #2722 from basecamp/flavorjones/gemfile-lock-drift
dep: fix Gemfile.saas gemfile drift
2026-03-17 22:14:48 -04:00