Commit Graph

633 Commits

Author SHA1 Message Date
Donal McBreen c2d693fc9a Fix off-by-one date display for UTC-negative timezone users
beginningOfDay() used local timezone methods (getFullYear, getMonth,
getDate) to snap timestamps to midnight. Since the server sends UTC
timestamps, this caused day boundary calculations to be off by one
for users in UTC-negative timezones — cards created after UTC midnight
but before local midnight showed as "yesterday" instead of "today".

Switch to UTC methods (getUTCFullYear, getUTCMonth, getUTCDate) so day
boundaries are calculated consistently with the server's UTC timestamps.

Affects DaysAgoFormatter, DaysAgoOrWeekdayFormatter, TimeOrDateFormatter,
InDaysFormatter, and bubble controller stalled/entropy calculations.
2026-04-03 08:50:25 +01:00
Stanko K.R. 76d00d17c8 Abort conditional mediation when the button disconnects 2026-03-26 16:49:59 +01:00
Stanko K.R. 9614c1ecfb Add a button to sign in with a passkey 2026-03-26 15:59:09 +01:00
Stanko Krtalić 09d5b8c92f Merge pull request #2756 from basecamp/friendly-error-message-on-duplicate-passkey
Show separate error message when adding a Passkey twice
2026-03-26 14:19:35 +01:00
Stanko K.R. 01d66a9463 Change challange expiration based on purpose 2026-03-25 17:31:42 +01:00
Stanko K.R. df7c2678f3 Rename create_options to registration_options 2026-03-25 17:26:49 +01:00
Stanko K.R. 8e4f9ce5e7 Cleanup form helpers 2026-03-25 17:26:49 +01:00
Stanko K.R. 4fb1cddb4c Use WebComponents for buttons
This simplifies the loading and cleanup logic, while providing ubiquitous support across JS frameworks. Buttons can now be added in any way imaginable and still work without requiring additional initialization. The upside of this aproach is that it doesn't require a mutation observer nor a global click listener, and is supported by all browsers that also support passkeys.
2026-03-25 17:26:49 +01:00
Stanko K.R. 134a533e28 Fix Passkey buttons not triggering sometimes 2026-03-24 14:36:52 +01:00
Alexander Zaytsev 6d6f94ce13 Merge branch 'main' into delete-account-improvements 2026-03-19 15:26:31 +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
Stanko Krtalić 5701aad8d7 Merge pull request #2623 from basecamp/passkeys
Passkeys
2026-03-18 14:54:54 +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
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. da69039476 Implement Passkey authentication 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
Mike Dalessio c29e785fc1 Merge pull request #2708 from basecamp/dep-lexxy-082
Configure Lexxy to add extra spacing between block elements
2026-03-17 12:42:17 -04:00
Jay Ohms f029fbfbeb Merge pull request #2683 from basecamp/mobile/bridge-button-slot
Mobile / Bridge button slot
2026-03-17 12:25:36 -04:00
Jay Ohms 2a19bb94a0 Merge branch 'main' into mobile/bridge-button-slot
* main: (33 commits)
  Remove payment/subscription system and card/storage limits
  Conditionally disable peer verification for ZIP streaming
  Prevent HTML injection through filenames
  Revert "Configure Lexxy to add extra spacing between block elements"
  Configure Lexxy to add extra spacing between block elements
  SaaS usage reporting (#2690)
  Update app/models/user/named.rb
  Prevent line breaks in the middle of familiar_name
  Tweak the layout
  Set the list of importable models based on the record sets in the manifest
  Validate polymorphic types against importable models allowlist
  Fix that the "maybe" stream wouldn't be replaced after triaging a card
  Use x_user_agent cookie for platform detection in Hotwire Native
  Add JSON response format to entropy endpoints (#2673)
  Fix path traversal vulnerability in ActiveStorage blob key import
  Enable CORS fetch mode for storage requests
  Revert CORS fetch mode for Active Storage
  Use CORS fetch mode for Active Storage to enable `maxEntrySize` checks
  Only start offline mode when signed in
  Exclude service worker and edit/pin/watch/new pages from main cache
  ...
2026-03-17 11:24:39 -04:00
Mike Dalessio 29a29094bd Configure Lexxy to add extra spacing between block elements
Updating Lexxy to v0.8.5 for the insert-markdown event.
2026-03-17 10:31:46 -04:00
Adrien Maston 780607dddc Merge branch 'main' into mobile/bridge-done-stamp
* main: (43 commits)
  Remove payment/subscription system and card/storage limits
  Conditionally disable peer verification for ZIP streaming
  Prevent HTML injection through filenames
  Revert "Configure Lexxy to add extra spacing between block elements"
  Configure Lexxy to add extra spacing between block elements
  SaaS usage reporting (#2690)
  Update app/models/user/named.rb
  Prevent line breaks in the middle of familiar_name
  Tweak the layout
  Set the list of importable models based on the record sets in the manifest
  Validate polymorphic types against importable models allowlist
  Fix that the "maybe" stream wouldn't be replaced after triaging a card
  Use x_user_agent cookie for platform detection in Hotwire Native
  Add JSON response format to entropy endpoints (#2673)
  Fix path traversal vulnerability in ActiveStorage blob key import
  Enable CORS fetch mode for storage requests
  Revert CORS fetch mode for Active Storage
  Use CORS fetch mode for Active Storage to enable `maxEntrySize` checks
  Only start offline mode when signed in
  Exclude service worker and edit/pin/watch/new pages from main cache
  ...
2026-03-17 15:27:29 +01:00
Jay Ohms 5c1f3a1f4f Refactor stamp component and observe element changes so subsequent "connect" messages will be sent 2026-03-17 08:12:57 -04:00
Adrien Maston 2d1e201946 Add scope selector value 2026-03-17 11:57:59 +01:00
Adrien Maston 0b29a67e17 Change date and closedBy properties for a more generic description 2026-03-17 11:09:37 +01:00
Stanko K.R. 8f6fca94fa Prevent HTML injection through filenames 2026-03-16 17:50:31 +01:00
Mike Dalessio 3959d91148 Revert "Configure Lexxy to add extra spacing between block elements"
This reverts commit d6bf103efd.
2026-03-12 12:24:35 -04:00
Mike Dalessio d6bf103efd Configure Lexxy to add extra spacing between block elements
Updating Lexxy to v0.8.0 for the insert-markdown event.
2026-03-11 22:17:07 -04:00
Alexander Zaytsev c977d03692 Use fire() instead of dispatch()
Addresses Copilot's feedback
2026-03-10 11:45:37 +01:00
Adrien Maston 0483ae5302 Add support for "bridge-slot" parameter 2026-03-10 10:52:47 +01:00
Rosa Gutierrez 99382db720 Only start offline mode when signed in
Gate Turbo.offline.start() behind Current.user so the service worker
is only registered for authenticated users. This avoids errors on
unauthenticated pages where /service-worker.js requires auth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:20:54 +01:00
Rosa Gutierrez 0482670fec Exclude service worker and edit/pin/watch/new pages from main cache
We don't need the service worker to cache itself, or pages that won't
work offline anyway.
2026-03-10 10:20:54 +01:00
Rosa Gutierrez de6d70cc2e Bump turbo-rails for Turbo.offline.clearCache()
Simplify the clear-offline-cache controller to use the new
Turbo.offline.clearCache() API instead of messaging the service
worker directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:20:54 +01:00
Rosa Gutierrez 1c2de6ca79 Clear offline cache on sign-in as well as sign-out
Rename logout controller to clear-offline-cache and attach it to the
magic link verification form so the service worker cache is cleared
when a different user signs in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:20:54 +01:00
Rosa Gutierrez 089fcf94f8 Preload resources after service worker installation
When the service worker is registered for the first time, resources loaded
before it becomes active won't go through the service worker. These resources
may be served from the browser's HTTP cache on subsequent requests, bypassing
the service worker cache entirely.

The new `preload` option accepts a regex pattern. On first visit (when no
controller exists), it waits for the service worker to take control, then
sends a message with URLs from `performance.getEntriesByType("resource")`
that match the pattern. The service worker fetches and caches these resources.
2026-03-10 10:20:54 +01:00
Rosa Gutierrez a949f1e3ae Clear offline cache when logging out
Adds a logout Stimulus controller that sends a message to the service
worker to clear all cached content when the user logs out. This ensures
that cached data from one user isn't accessible after logout.

The implementation:
- Adds logout_controller.js that posts { action: "clearCache" } to the
  service worker via postMessage
- Updates logout buttons to use the controller on form submission

Also fixes data-turbo placement: moved from button to form element where
it actually takes effect for disabling Turbo Drive form submissions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-10 10:20:54 +01:00
Rosa Gutierrez ada4688c4e Take a first stab at offline mode support 2026-03-10 10:20:54 +01:00
Adrien Maston 7974629e20 Rename attribute 2026-03-09 16:42:59 +01:00
Adrien Maston 5a9fd6b975 Coding style 2026-03-09 16:38:22 +01:00
Alexander Zaytsev 0555523747 Merge branch 'main' into delete-account-improvements 2026-03-09 15:48:21 +01:00
Adrien Maston d746b86e70 Remove debug line 2026-03-09 15:43:58 +01:00
Adrien Maston 078597f132 Add bridge component 2026-03-09 15:40:45 +01:00
Alexander Zaytsev eac750912f Reset checkbox when cancellation dialog closes 2026-03-09 09:55:23 +01:00
Alexander Zaytsev 04bf063e3c Make the Delete account dialog more careful 2026-03-06 18:01:23 +01:00
Adrien Maston 920502b590 Scroll column into view when opening its menu 2026-03-04 11:31:45 +01:00
Adrien Maston 9c26e834b7 Don't try to orient column menus 2026-03-04 11:30:42 +01:00
Adrien Maston 8fced550d8 Refactor 2026-03-03 10:31:08 +01:00
Adrien Maston 340d9aa763 Delegate clearing the input to new controller 2026-03-02 14:21:32 +01:00
Jay Ohms 867267890b Update app/javascript/controllers/bridge/buttons_controller.js
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-26 08:05:48 -05:00
Jay Ohms 7427675fc8 PR feedback 2026-02-26 07:53:02 -05:00