Commit Graph

9285 Commits

Author SHA1 Message Date
Stanko K.R. 161efb0b8e Implement basic imports 2026-02-02 12:36:48 +01:00
Stanko K.R. 8953920652 Implement full account exports 2026-02-02 12:36:48 +01:00
Stanko K.R. 6f17e3867d Split Export model into user and whole-account export 2026-02-02 12:36:31 +01:00
Rosa Gutierrez 63d9f29b1e Return internal account ID after signup completion
This matches what we return from `/my/identity` endpoint for each
account.
2026-01-30 13:41:37 +01:00
Rosa Gutierrez 614527e9c2 Add JSON format support to signup flow for native API clients
The magic link verification endpoint now returns `requires_signup_completion`
to indicate whether the client needs to collect a name and complete signup.
The signup completion endpoint now supports JSON responses with the account ID.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:41:37 +01:00
Alp Keser b4e1d74f5d Add json.has_attachments for the card 2026-01-30 13:28:26 +03:00
Mike Dalessio 231fa311c1 Merge pull request #2453 from basecamp/flavorjones/fix-create-card-2
Fix lightbox blocking clicks on page elements
2026-01-28 17:58:21 -05:00
Mike Dalessio 017e1434f1 Reapply "Fix lightbox blocking clicks on page elements"
This reverts commit c70c4b4107.
2026-01-28 17:53:53 -05:00
Mike Dalessio c70c4b4107 Revert "Fix lightbox blocking clicks on page elements"
This reverts commit 17b7af9b92.
2026-01-28 17:53:21 -05:00
Mike Dalessio 17b7af9b92 Fix lightbox blocking clicks on page elements
The CSS change in 39575a0 added `display: flex` to the lightbox dialog
unconditionally, which overrode the browser's default `display: none`
for closed dialogs. This made the invisible lightbox overlay intercept
all clicks on the page.

Move flexbox properties to the `&[open]` selector so they only apply
when the dialog is actually open.

Also fix typo: `innerHtml` → `innerHTML` (capital H).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 17:51:32 -05:00
Mike Dalessio a67dea6347 Merge pull request #2450 from basecamp/flavorjones/coworker-audit-api
saas: Update audits1984 and allow the auditor token for LLM access to audits
2026-01-28 14:34:56 -05: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 4e61b64d9a Update to feature branch of audits1984 2026-01-28 14:13:51 -05:00
Mike Dalessio 3b13c8573e saas: Backfill tests for admin audit endpoints 2026-01-28 12:55:28 -05:00
Mike Dalessio dbcf54de91 saas: Set lifetime of console1984 sessions to 60 days 2026-01-28 12:55:28 -05:00
Adrien Maston 70fba5e48b Merge pull request #2309 from basecamp/mobile/prepare-webviews-2
Mobile/prepare webviews 2
2026-01-28 16:03:54 +01:00
Kevin McConnell 9cd94a7d08 Merge pull request #2445 from basecamp/shorten-public-cache-expiration
Cache public pages for 5 mins, not 1 year
2026-01-28 14:39:33 +00:00
Kevin McConnell 108337e823 Cache public pages for 5 mins, not 1 year
Given these may be cached in CDNs, and they aren't versioned, a shorter
expiration time makes it practical to change them.
2026-01-28 14:30:43 +00:00
Kevin McConnell feaeaf5c68 Merge pull request #2443 from basecamp/remove-zero-padding-from-account-slug
Remove zero-padding from account slug
2026-01-28 14:05:16 +00:00
Jay Ohms 1e92e4b957 Merge pull request #2444 from basecamp/mobile/verify-app-links-debug
Add the Android debug fingerprint for verified app links
2026-01-28 08:56:06 -05:00
Jay Ohms 28fc7148da Fix indentation 2026-01-28 08:51:51 -05:00
Jay Ohms 3fdb79a5a4 Add the Android debug fingerprint for verified app links 2026-01-28 08:48:31 -05:00
Jay Ohms 59f04f4561 Merge pull request #2441 from basecamp/mobile/verify-app-links
Add the public Digital Asset Links file to verify app links on Android
2026-01-28 08:18:20 -05:00
Kevin McConnell a293151220 Add middleware to serve SaaS engine's public files 2026-01-28 12:17:22 +00:00
Kevin McConnell e105ca6fb5 Remove zero-padding from account slug
This shortens URLs in the self-hosted case, where external account ID is
typically a small number.
2026-01-28 11:59:42 +00:00
Jay Ohms 345fd8cdbb Add the public Digital Asset Links file to verify app links on Android 2026-01-28 06:26:33 -05:00
Rosa Gutierrez c059e0b216 Add JSON format support to session destroy for native API clients
This is so that native API clients can get the session record deleted
server-side. They still need to take care of clearing any cookies
they've set in web views.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 19:59:30 +01:00
Adrien Maston fefb28848b Merge branch 'main' into mobile/prepare-webviews-2
* main: (26 commits)
  Add a new Pins section to docs/API.md covering pin/unpin and the pinned cards list response.
  Align board name start so it doesn't get too big
  Clean up card/events header layout
  Sync email to Stripe when user changes email address (#2432)
  Fix IDOR in webhook activation endpoint (#2431)
  Add card reactions to API docs and reactions_url to card JSON (#2427)
  Remove unnecessary claude plan
  Allow boosts on cards (#2411)
  Revert "Fix notification click URL by using correct data property"
  Add migration to remove draft cards from search index
  Guard search indexing with searchable? check
  Forbid comments on draft cards
  prefactor: update search to use published cards
  Fix notification click URL by using correct data property
  Wait for service worker to be active before subscribing
  Fix stuck state when permission granted but no subscription
  Extract Card::Commentable
  Include arm64 build in Docker workflow
  Remove unnecessary `await` in push handler
  Correctly initialise WebPush connection (#2417)
  ...
2026-01-27 17:17:21 +01:00
Denis Svara ec1b8f2fed Merge pull request #2367 from basecamp/pins-api
Pins API
2026-01-27 15:52:50 +01:00
Denis Švara a75d56d243 Merge branch 'main' into pins-api
* main: (127 commits)
  Align board name start so it doesn't get too big
  Clean up card/events header layout
  Sync email to Stripe when user changes email address (#2432)
  Fix IDOR in webhook activation endpoint (#2431)
  Add card reactions to API docs and reactions_url to card JSON (#2427)
  Remove unnecessary claude plan
  Allow boosts on cards (#2411)
  Revert "Fix notification click URL by using correct data property"
  Add migration to remove draft cards from search index
  Guard search indexing with searchable? check
  Forbid comments on draft cards
  prefactor: update search to use published cards
  Fix notification click URL by using correct data property
  Wait for service worker to be active before subscribing
  Fix stuck state when permission granted but no subscription
  Extract Card::Commentable
  Include arm64 build in Docker workflow
  Remove unnecessary `await` in push handler
  Correctly initialise WebPush connection (#2417)
  Update models, views, and fixtures for polymorphic reactions
  ...
2026-01-27 15:37:47 +01:00
Denis Švara 8e24988c6f Add a new Pins section to docs/API.md covering pin/unpin and the pinned cards list response. 2026-01-27 15:37:07 +01:00
Adrien Maston 70fc2a807c Clean iOS text size CSS 2026-01-27 11:38:04 +01:00
Adrien Maston e5bef41c54 Refactor orientation helper to express intent more clearly 2026-01-27 11:21:15 +01:00
Andy Smith 02527349f9 Merge pull request #2435 from basecamp/card-header-alignment
Card header alignment
2026-01-26 13:23:08 -06:00
Andy Smith 8cfcc6fca5 Align board name start so it doesn't get too big 2026-01-26 12:57:26 -06:00
Andy Smith 5beb413c41 Clean up card/events header layout 2026-01-26 12:53:01 -06:00
Jeremy Daer f2ff5af4f5 Sync email to Stripe when user changes email address (#2432)
* Sync owner email to Stripe when changed

When an account owner changes their email address, update the
corresponding Stripe customer record via a background job.

Also handles ownership transfers: when a user becomes the account
owner, their email is synced to Stripe.

Responsibility chain:
- User::NotifiesAccountOfEmailChange triggers on owner identity change
  or when a user becomes owner
- Account::Billing#owner_email_changed enqueues sync job
- Account::SyncStripeCustomerEmailJob performs the update with
  polynomial backoff retries
- Account::Subscription#sync_customer_email_to_stripe calls Stripe API

* Address PR feedback: error handling and test coverage

- Handle Stripe::InvalidRequestError in sync_customer_email_to_stripe
  (mirrors cancel method behavior for deleted customers)
- Add test for deactivated owner (owner with nil identity)
- Add test for deleted Stripe customer scenario
2026-01-25 14:20:39 -08:00
Jeremy Daer 4efa4da809 Fix IDOR in webhook activation endpoint (#2431)
The webhook activation controller was using account-scoped lookup
instead of board-scoped lookup, allowing users to reactivate webhooks
on boards they don't have access to.

This was an oversight when board-scoping was added to the main webhooks
controller - the activations controller was missed in that update.

The fix adds the BoardScoped concern to properly restrict webhook
activation to boards the user has explicit access to.
2026-01-24 17:06:12 -08:00
Mike Dalessio 16745e89d1 Add card reactions to API docs and reactions_url to card JSON (#2427)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 16:55:50 -05:00
Mike Dalessio c822639260 Remove unnecessary claude plan 2026-01-23 13:27:04 -05:00
Mike Dalessio cb61b36715 Allow boosts on cards (#2411)
* Add reactions association to Card model

Adds `has_many :reactions` to Card, matching the implementation in Comment.
This allows cards to be reacted to directly with emoji reactions.

The association:
- Orders reactions chronologically
- Uses polymorphic `:reactable` interface
- Deletes reactions when card is destroyed

Includes test coverage for the new association.

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

* Add reactions UI to card detail view

- Create Cards::ReactionsController with turbo stream responses
- Add card reactions views (reactions list, new form, menu partial)
- Position reaction button flush-right when no reactions exist
- Show reactions on bottom-left when present, with button inline
- Handle narrow viewports by flowing button below meta section
- Add controller tests for card reactions

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

* Add boost count to card preview

Display reaction count alongside comment count on card tiles in board
columns. Introduces a .card__counts wrapper to group both counts with
proper positioning on all viewport sizes.

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

* Consolidate reaction views for cards and comments

Extract shared views to app/views/reactions/ using polymorphic routing.
Both card and comment reactions now render the same partials, with a
helper to compute the correct path prefix for nested routes.

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

* Fix emoji picker width in card reactions

Override .card .popup { inline-size: 260px } for the reaction popup
so the emoji grid displays without horizontal scrollbar.

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

* Hide boost count where comment count is hidden

Add .card__boosts alongside .card__comments in:
- Tray view (display: none)
- Cards with background images (opacity toggle on hover)

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

* Fix reactions button overlap with zoom button in card footer

When a card has a background image, the footer contains both a reactions
button and a zoom button. Previously they would overlap because the
reactions button was absolutely positioned to the bottom-right.

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

* Tighten up previews

* Move card reactions from meta partial to container

Fixes two issues:

1. Reactions were duplicated each time a card was assigned because the
   turbo stream replaced the meta div with the full perma/meta partial,
   which included reactions outside the replaced element.

2. Draft cards incorrectly showed the boost button because the meta
   partial was shared between published and draft containers.

Moving reactions to _container.html.erb (published cards only) fixes
both issues and keeps the meta partial focused on meta content.

Fixes https://app.fizzy.do/5986089/cards/3837
Fixes https://app.fizzy.do/5986089/cards/3835

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

* WIP adjust perma page

* Position and style the footer

* Render the stamp in the card body instead of the footer

* Fix undefined local variable in public cards view

Changed `card` to `@card` when rendering the stamp partial.

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

* Preload card reactions to avoid N+1 queries

Include reactions and their reacters in the preloaded scope, matching
what we already do for comments.

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

* Add model tests for card and comment reaction cleanup

Test that:
- Creating a card reaction touches the card's last_active_at
- Reactions are deleted when their parent comment is destroyed
- Reactions are deleted when their parent card is destroyed

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

* Minor improvements to reactions code

- Use size instead of count in boosts partial to avoid extra SQL query
  on already-loaded collection
- Add else clause to reaction_path_prefix_for to raise ArgumentError
  for unknown reactable types instead of silently returning nil

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

* Bump specificity of reaction popup in the card perma

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Andy Smith <andy@37signals.com>
2026-01-23 13:25:55 -05:00
Rosa Gutierrez ffb2a0b82a Revert "Fix notification click URL by using correct data property"
This reverts commit 4f2308d380.

This was from another branch, shoudln't have been included here.
2026-01-23 19:25:23 +01:00
Mike Dalessio dfa4875a13 Merge pull request #2418 from basecamp/filter-drafts-in-search
Exclude draft cards from search index
2026-01-23 12:17:25 -05:00
Mike Dalessio a9c6bc2a28 Add migration to remove draft cards from search index
One-time script to clean up any search records that were indexed
before the searchable? guard was added.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 12:13:10 -05:00
Mike Dalessio 0d138df952 Guard search indexing with searchable? check
Only index cards and comments if their card is `published?`, using a
new method `searchable?` that is implemented on both Card and Comment.
This prevents draft cards and their comments from being indexed.

When drafts are published, the existing `update_in_search_index`
callback creates the record via `upsert!`, or else ensures unpublished
records are removed from the index.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 12:13:08 -05:00
Adrien Maston 39575a0cb6 Fix lightbox layout and focus 2026-01-23 17:41:33 +01:00
Mike Dalessio f6211dbacc Merge pull request #2423 from basecamp/forbid-comments-on-draft-cards
Forbid comments on draft cards
2026-01-23 11:40:46 -05:00
Mike Dalessio 9aa15e9fb2 Forbid comments on draft cards
- Add Card#commentable? method that returns true only for published cards.
- CardsController#create ensures that the card is commentable.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 11:28:26 -05:00
Mike Dalessio bb2d3a59b5 prefactor: update search to use published cards
We're about to make a change to assert that draft cards are not added
to the search index, and so let's make the intention behind these
tests clear first.
2026-01-23 11:07:43 -05:00
Rosa Gutierrez 4f2308d380 Fix notification click URL by using correct data property
The web push payload sends the URL in data.url but the service
worker was looking for data.path, resulting in undefined URLs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 16:38:45 +01:00