Commit Graph

9950 Commits

Author SHA1 Message Date
Stanko K.R. f66fa886bc Return apostrophes to our preferred style 2026-04-15 17:31:10 +02:00
Rob Zolkos abd59567e3 Add indexed_by=maybe to cards (#2827)
* Add indexed_by=maybe to cards
2026-04-14 17:35:41 -04:00
Rob Zolkos 89a1cf43fb Add timeout to system package install step (#2839)
* Add timeout to reusable test workflow

* Add timeout to system package install step

* Retry CI

* Retry CI again
2026-04-14 13:51:55 -04:00
Rob Zolkos bb54b859dc Add workflow column filtering to cards (#2787) 2026-04-14 13:14:14 -04:00
Jorge Manrubia dd42f0a098 Add script to reindex stale search records (#2843)
The data import path (Account::DataTransfer) uses insert_all! which
bypasses ActiveRecord callbacks, so imported cards and comments never
get search records created and are invisible to search and card-table
filtering.

This script reindexes all published cards and comments created before
a cutoff date (default 2026-04-01). The reindex method is an upsert
so already-indexed records get a harmless update.

Usage:
  bin/rails runner script/maintenance/reindex_stale_search_records.rb
  bin/rails runner script/maintenance/reindex_stale_search_records.rb 2026-01-01
2026-04-14 18:37:52 +02:00
Stanko Krtalić 127156e23a Merge pull request #2829 from basecamp/remove-tag-attachable
Remove dead Tag::Attachable code and tags prompt
2026-04-10 09:05:48 +02:00
Mike Dalessio f3f9aec547 Fix missing partial when editing comments with @mentions (#2828)
Edge Rails introduced ActionText::Attachable#to_editor_content_attachment_partial_path
which defaults to to_partial_path ("users/user"). Override it in User::Mentionable to
delegate to to_attachable_partial_path ("users/attachable"), matching the existing
display rendering path.
2026-04-09 17:29:30 -04:00
Mike Dalessio 975b8998ef Remove ActionText::Attachable from Tag
Tag was never actually embedded as an action-text-attachment in
persisted rich text. It was only used in the Fizzy Do command prompt
input which was not stored. The data transfer tests happened to use Tag
as a convenient fixture — switch them to User, which is genuinely
attachable via mentions.
2026-04-09 17:17:29 -04:00
Mike Dalessio 151787a864 Remove dead Tag::Attachable code and tags prompt
The tags prompt was added for the Fizzy Do command system, but became
dead code when commands were removed in 89af9066. The commands_prompt
was cleaned up but tags_prompt was missed.

Remove the Tag::Attachable concern, Prompts::TagsController, its views
and route, and the tags_prompt helper. Tag still includes
ActionText::Attachable directly, which is needed by the data transfer
system.
2026-04-09 17:13:41 -04:00
Mike Dalessio 56f47361f9 Fix flaky web push test and deduplicate DNS stub helper (#2825)
* Extract shared DnsTestHelper from duplicated stub_dns_resolution methods

* Fix flaky WebTest by stubbing DNS resolution for push subscription creation
2026-04-09 14:03:45 -04:00
Mike Dalessio e16b52bbba dep: bump ruby to 3.4.8 (from 3.4.7) (#2823) 2026-04-09 13:55:33 -04:00
Mike Dalessio 732126b5df Update bundle-drift to handle subdependencies (#2824) 2026-04-09 13:46:37 -04:00
Mike Dalessio 2d9a00ed05 dep: fix dependency drift 2026-04-09 13:39:00 -04:00
dependabot[bot] 0c30fa7937 Bump kamal from 2.10.1 to 2.11.0 (#2767)
* Bump kamal from 2.10.1 to 2.11.0

Bumps [kamal](https://github.com/basecamp/kamal) from 2.10.1 to 2.11.0.
- [Release notes](https://github.com/basecamp/kamal/releases)
- [Commits](https://github.com/basecamp/kamal/compare/v2.10.1...v2.11.0)

---
updated-dependencies:
- dependency-name: kamal
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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-04-09 13:19:30 -04:00
dependabot[bot] b64c1e8895 Bump aws-sdk-s3 from 1.216.0 to 1.218.0 (#2768) 2026-04-09 13:18:47 -04:00
Rob Zolkos e422d5b37e Add a JSON cards endpoint for workflow columns (#2800)
* Add JSON endpoint for cards in workflow columns

* Add cards URL to column JSON responses

* Add coverage for column cards authorization
2026-04-09 13:17:02 -04:00
Jorge Manrubia 1c6141c131 Update lexxy to 0.9.5.beta (#2820)
* Update lexxy to 0.9.5.beta

* Fix syntax highlight controller for lexxy 0.9.5.beta

The highlightAll export was renamed to highlightCode.

---------

Co-authored-by: Mike Dalessio <mike@37signals.com>
2026-04-09 13:06:59 -04:00
Rob Zolkos 69daae79f1 Add board membership read endpoint (#2799)
* Add board membership read endpoint

* Paginate board membership read endpoint
2026-04-09 12:54:25 -04:00
Mike Dalessio e70047ca0f Default development environment to app.fizzy.localhost (#2822)
Using fizzy.localhost causes CORS errors when using minio for Active
Storage because the minio endpoint is at minio.fizzy.localhost — a
sibling subdomain, not a subdomain of the app host. Switching to
app.fizzy.localhost makes both hosts subdomains of fizzy.localhost,
resolving the CORS issue. See #2814 for the related minio CORS fix.

fizzy.localhost will continue to work if people want to use it, but all
docs and scripts have been updated to point to app.fizzy.localhost.
2026-04-09 12:43:01 -04:00
Mike Dalessio b07f592aaf Fix broken background image after removal (#2817)
ActiveStorage::Record and ApplicationRecord used separate connection
pools (from separate `connects_to` calls). This meant `belongs_to
touch: true` on attachments silently failed — the card couldn't join the
attachment's transaction to receive the deferred touch, so fragment
caches were never invalidated after image removal.

Fix by delegating `connection_pool` from ActiveStorage::Record to
ApplicationRecord so they share a single pool.
2026-04-09 12:33:27 -04:00
Mike Dalessio 759e6079e8 Update bin/bundle-drift to catch dependency requirement diffs (#2821)
* Detect dependency requirement drift in bin/bundle-drift

The checker only compared resolved spec versions between Gemfile.lock
and Gemfile.saas.lock. When dependabot bumped solid_queue from ~> 1.3
to ~> 1.4, the forward command patched the resolved version but left
the stale dependency requirement. The checker didn't catch it because
both lockfiles resolved to the same version.

Now find_drift also compares dependency requirements for shared direct
dependencies, and forward patches the DEPENDENCIES section too.

Includes built-in self-test (bin/bundle-drift self-test).

* Sync solid_queue dependency requirement in Gemfile.saas.lock

Updates ~> 1.3 to ~> 1.4 to match Gemfile.lock.
2026-04-09 12:19:52 -04:00
dependabot[bot] 659ec1e6e6 Bump solid_queue from 1.3.2 to 1.4.0 (#2766)
* Bump solid_queue from 1.3.2 to 1.4.0

Bumps [solid_queue](https://github.com/rails/solid_queue) from 1.3.2 to 1.4.0.
- [Release notes](https://github.com/rails/solid_queue/releases)
- [Commits](https://github.com/rails/solid_queue/compare/v1.3.2...v1.4.0)

---
updated-dependencies:
- dependency-name: solid_queue
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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-04-09 11:16:29 -04:00
Mike Dalessio 3a30d7796f style: formalize preference for if/unless in rubocop (#2816) 2026-04-09 11:14:52 -04:00
Donal McBreen d562e79440 Merge pull request #2813 from robzolkos/fix/active-storage-bearer-downloads
Allow bearer auth for Active Storage download endpoints
2026-04-09 15:31:43 +01:00
Mike Dalessio 45d165749f Fix CORS issues when using minio in development (#2814)
Move MinIO from minio.localhost to minio.fizzy.localhost, which makes
it same-site with the app, so the CORS redirect succeeds.

The service worker fetches Active Storage URLs with `mode: "cors"` so
it can inspect response sizes for offline caching. Active Storage's
redirect controller returns a 302 to the MinIO presigned URL. When
that redirect crosses site boundaries (from fizzy.localhost to
minio.localhost), the browser sets the Origin header to "null" on the
redirected request per the Fetch spec, which fails the CORS check and
produces net::ERR_FAILED.
2026-04-08 16:06:38 -04:00
dependabot[bot] 7bd3df33b8 Bump rack from 3.2.5 to 3.2.6 (#2784)
* Bump rack from 3.2.5 to 3.2.6

Bumps [rack](https://github.com/rack/rack) from 3.2.5 to 3.2.6.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v3.2.5...v3.2.6)

---
updated-dependencies:
- dependency-name: rack
  dependency-version: 3.2.6
  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-04-08 15:48:11 -04:00
dependabot[bot] 6ddb04766a Bump loofah from 2.25.0 to 2.25.1 (#2726)
* Bump loofah from 2.25.0 to 2.25.1

Bumps [loofah](https://github.com/flavorjones/loofah) from 2.25.0 to 2.25.1.
- [Release notes](https://github.com/flavorjones/loofah/releases)
- [Changelog](https://github.com/flavorjones/loofah/blob/main/CHANGELOG.md)
- [Commits](https://github.com/flavorjones/loofah/compare/v2.25.0...v2.25.1)

---
updated-dependencies:
- dependency-name: loofah
  dependency-version: 2.25.1
  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-04-08 15:47:08 -04:00
Mike Dalessio 8908ee46f8 Upgrade addressable to 2.9.0 (#2815)
* Upgrade addressable from 2.8.9 to 2.9.0

Security release fixing ReDoS vulnerabilities in Addressable::Template#match.
No application impact — fizzy does not use Addressable::Template directly.

* dep: fix saas drift
2026-04-08 15:45:23 -04:00
Rob Zolkos 4a91e45aa5 Cover bearer-authenticated export download URLs 2026-04-08 15:03:25 -04:00
Rob Zolkos 5e154a767f Allow bearer auth on Active Storage downloads 2026-04-08 14:37:24 -04:00
Rob Zolkos dd67f4171d Add regression tests for bearer-authenticated blob downloads 2026-04-08 14:36:34 -04:00
Zoltán Hosszú 0ef9c56bf5 Merge pull request #2811 from basecamp/lexxy-toolbar-fixes
Fix icon color and chevron size
2026-04-08 15:13:15 +02:00
Rob Zolkos 1975a04f14 Add JSON API support for email address changes (#2807) 2026-04-08 09:09:36 -04:00
Zoltan Hosszu d7040388fa Fix icon color and chevron size 2026-04-08 15:09:29 +02:00
Rob Zolkos d08aa11bfb Add JSON API support for timezone update (#2806)
* Add JSON API support for timezone update

* Simplify timezone controller to just head :no_content

* Use PUT instead of PATCH in timezone tests to match docs

* Use PATCH instead of PUT for timezone endpoint

Reverts tests to use patch and updates docs heading to PATCH
for consistency.
2026-04-08 08:41:34 -04:00
Rob Zolkos 6a71856b3d Add JSON activities API endpoint (#2783)
* Add JSON events API endpoint

* Add regression test for event particulars defaults

* Move JSON events API to a dedicated ActivitiesController

The events endpoint served both the HTML day timeline and the JSON API
feed, but the two paths shared no data or behavior — the HTML side uses
DayTimelinesScoped while the JSON side built its own query. Splitting
into ActivitiesController gives the API its own home at
GET /:account/activities.json without dragging in the timeline
before_actions.

Also preloads comment creator in Event.preloaded to avoid an N+1 when
rendering comment eventables in the JSON feed.
2026-04-08 08:39:36 -04:00
Rob Zolkos 2a4adf3a2b Add board settings fields to board JSON responses (#2788)
* Add board settings fields to board JSON responses

* Move public_description fields to board partial, gate on published

* Add index test for public_description fields on published boards

* Update app/views/boards/show.json.jbuilder

Prefer `unless` to `if !`

---------

Co-authored-by: Mike Dalessio <mike.dalessio@gmail.com>
2026-04-08 08:31:52 -04:00
Rob Zolkos 8201c2a4bd Add JSON API support for user data exports (#2786) 2026-04-08 08:17:24 -04:00
Rob Zolkos 98b6bdcfb7 Document undocumented API endpoints (#2805)
* Document avatar removal API endpoint

* Document notification settings API endpoints

* Document access token list and delete API endpoints

* Document join code API endpoints

* Fix access token delete URL parameter name in docs
2026-04-07 15:56:43 -04:00
Rob Zolkos 21981898d2 Add JSON API for webhook deliveries (#2785)
* Add JSON API for webhook deliveries

* Extract sanitized_request method on Webhook::Delivery

* Extract response_summary method on Webhook::Delivery
2026-04-07 15:08:27 -04:00
dependabot[bot] f3bacffe2b Bump lexxy from 0.9.0.beta to 0.9.1.beta (#2796)
* Bump lexxy from 0.9.0.beta to 0.9.1.beta

Bumps [lexxy](https://github.com/basecamp/lexxy) from 0.9.0.beta to 0.9.1.beta.
- [Release notes](https://github.com/basecamp/lexxy/releases)
- [Commits](https://github.com/basecamp/lexxy/compare/v0.9.0.beta...v0.9.1.beta)

---
updated-dependencies:
- dependency-name: lexxy
  dependency-version: 0.9.1.beta
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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-04-07 11:36:12 -07:00
dependabot[bot] b2021e1e74 Bump trilogy from 2.10.0 to 2.11.1 (#2794)
* Bump trilogy from 2.10.0 to 2.11.1

Bumps [trilogy](https://github.com/trilogy-libraries/trilogy) from 2.10.0 to 2.11.1.
- [Release notes](https://github.com/trilogy-libraries/trilogy/releases)
- [Changelog](https://github.com/trilogy-libraries/trilogy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/trilogy-libraries/trilogy/compare/v2.10.0...v2.11.1)

---
updated-dependencies:
- dependency-name: trilogy
  dependency-version: 2.11.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

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-04-07 10:09:41 -07:00
dependabot[bot] dc6139a75e Bump sigstore/cosign-installer in the github-actions group (#2795)
Bumps the github-actions group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `sigstore/cosign-installer` from 4.1.0 to 4.1.1
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/ba7bc0a3fef59531c69a25acd34668d6d3fe6f22...cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-version: 4.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 10:09:30 -07:00
dependabot[bot] adc1b02d7a Bump thruster from 0.1.19 to 0.1.20 (#2797)
* Bump thruster from 0.1.19 to 0.1.20

Bumps [thruster](https://github.com/basecamp/thruster) from 0.1.19 to 0.1.20.
- [Changelog](https://github.com/basecamp/thruster/blob/v0.1.20/CHANGELOG.md)
- [Commits](https://github.com/basecamp/thruster/compare/v0.1.19...v0.1.20)

---
updated-dependencies:
- dependency-name: thruster
  dependency-version: 0.1.20
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

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-04-07 10:08:59 -07:00
Rob Zolkos cdd13c1a61 Split API docs into per-resource sections under docs/api/ (#2793)
* Split docs/API.md into per-resource sections under docs/api/

* Move API endpoints index above authentication in docs/api/README.md

* Fix trailing comma in boards.md JSON example

* Fix trailing comma in cards.md, add Response label to identity.md, add Rich Text to endpoint index
2026-04-06 14:00:17 -04:00
Donal McBreen 00a5c6ef14 Merge pull request #2804 from basecamp/fix-account-destroy-cascade-gaps
Fix account destroy cascade gaps
2026-04-06 10:15:31 +01:00
Donal McBreen e51f0bfee7 Fix account destroy cascade gaps
Account incineration could leave orphaned records due to missing cascade
declarations and async jobs failing when the account was already gone.

Cascade fixes:
- Add Account::Searchable concern to clean up Search::Query (delete_all)
  and Search::Record (destroy_all, respects SQLite FTS dependent: :destroy)
- Add before_destroy in Account::Storage to delete storage entries
- Suppress storage entry recording during incineration so attachment
  purge callbacks don't create entries or enqueue materialize jobs
- Guard Access#clean_inaccessible_data_later with unless user.destroyed?
  to avoid enqueuing pointless jobs during user cascade

Job tenancy:
- Extract AccountTenanted concern from the global ActiveJob initializer
  into ApplicationJob (include) with targeted prepends for
  ActionMailer::MailDeliveryJob and Turbo broadcast jobs
- Defer account resolution from deserialize to perform so that missing
  accounts raise DeserializationError inside the execution path where
  discard_on can handle it

Tests:
- Comprehensive incineration test covering 35 model types with
  before/after assertions and full enqueued job processing
- Mailer deliver_later test verifying account context survives job
  serialization for multi-account users
- Turbo broadcast test verifying account-scoped URLs in rendered partials
2026-04-06 10:04:24 +01:00
Donal McBreen d9f176aeb0 Merge pull request #2803 from basecamp/fix-timezone-date-display
Fix timezone handling for day timeline and card dates
2026-04-06 09:27:49 +01:00
Donal McBreen 6d71385846 Fix timezone handling for day timeline and card dates
Revert beginningOfDay() to use local timezone methods — the UTC change
from #2790 caused cards created earlier the same day to show "yesterday"
for users in UTC-negative timezones after their local 7 PM.

Add Time.zone.name to day timeline fragment cache keys so
timezone-different renders don't collide.
2026-04-06 09:21:03 +01:00
Donal McBreen e1426af06c Merge pull request #2791 from basecamp/fix-export-column-colors
Fix export/import losing custom column colors
2026-04-03 10:08:37 +01:00