Commit Graph

149 Commits

Author SHA1 Message Date
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
Mike Dalessio 14aa95d982 Add migration script to fix misplaced comment events (#2487)
Finds comment events that are on the wrong board (after a card move)
and updates them to the correct board.
2026-02-04 15:27:33 -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
Rosa Gutierrez bf224b19f5 Add rollback script to convert relative URLs back to absolute 2026-01-14 11:01:42 +01:00
Rosa Gutierrez bf6fe75b7c Add a script to migrate existing rich texts to relative URLs 2026-01-14 11:01:42 +01:00
Jeremy Daer 006e61ea58 Allow ActionText embed reuse and safe purge (#2346) 2026-01-12 10:30:18 -08:00
Fernando Álvarez dbb8113080 Extend the number of Beta environments 2025-12-23 12:27:03 +01:00
Jeremy Daer bd6c1cf34f Storage: harden reconcile for concurrent writes and fix board transfer (#2096)
* Storage: harden reconcile for concurrent writes and fix board transfer

Reconcile now uses two-cursor approach: captures cursor before and after
the storage scan, aborting if they differ (entries added during scan).
Job retries 3x with 1-minute waits and limits concurrency to 1 per owner.

Board transfer now correctly moves storage for card description embeds
and comment embeds, not just direct attachments. Uses batched queries
to handle cards with thousands of comments efficiently.

Also fixes N+1 queries in attachment grouping via lookup maps.

* Storage: fix per-attachment reconcile and enforce no blob reuse

The storage ledger tracks per-attachment (not per-blob) as a business
abstraction for quotas. This fixes reconcile to match that model and
adds enforcement to prevent blob reuse in tracked contexts.

* Reconcile now uses joins(:blob).sum() for per-attachment counting
* New validation prevents reusing blobs across tracked attachments
* Race-safe storage_total creation with create_or_find_by
* Job efficiency: skip find_by when object already available
* Backfill script checks per-attachment, not just per-blob
2025-12-19 13:07:32 -08:00
Jorge Manrubia 704fb3590f Merge pull request #2179 from Xeross99/main
Fix assigned but unused variable in identity linking
2025-12-19 11:34:54 +01:00
Samuel Péchèr 6b427ad9b9 Update timestamp 2025-12-18 17:34:47 +00:00
Samuel Péchèr 60dc6927fe Remove attachment detection 2025-12-18 17:34:25 +00:00
Samuel Péchèr d250c256c6 Add paragraph space to seed Card #8 2025-12-18 09:27:56 +00:00
Samuel Péchèr b2017a75cf Add script to separate non-blank sibling <p> 2025-12-18 09:27:56 +00:00
Michał Krzysteczko 89749b824d fix: assigned but unused variable - identity 2025-12-17 12:03:43 +01: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
Jeremy Daer bec46e15a9 Drop defunct Account upload attachments (#2030)
Controller and routes removed in 6a62df470c
2025-12-09 00:36:39 -08:00
Mike Dalessio e174206233 Add backfill script for verified_at timestamps
Identifies users who have demonstrated authentication by looking for
evidence of real activity: owners, content creators (cards, comments,
boards, events), action takers (assigners, closers, postponers,
reactors, pinners, filter creators), board accessors, export requesters,
push subscribers, setup completers, and users with active sessions.

Run this script after deploying the verified_at column to backfill
existing users before enabling the notification guard.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:51:44 -05:00
Jeremy Daer 4e0b83340d Drop defunct user creation script 2025-12-04 10:42:34 -08:00
Jeremy Daer 49139b7a14 SQLite import creates account-scoped tags
References #1879
2025-12-03 15:09:22 -08:00
Jorge Manrubia 9cf223aea1 Fix path 2025-12-03 23:53:18 +01:00
Jorge Manrubia efc809c23e Script to fix misassigned tags
See https://github.com/basecamp/fizzy/pull/1879
2025-12-03 23:46:08 +01:00
Mike Dalessio 6345aa4787 Update seeds to use @example.com
See also https://www.rfc-editor.org/rfc/rfc2606.html
2025-12-03 15:40:58 -05:00
Mike Dalessio edf6b53469 Introduce an "owner" role, and prevent it from being administered
to prevent the owner from being demoted or kicked out.

ref: https://app.fizzy.do/5986089/cards/3213
2025-11-29 14:13:29 -05:00
Jorge Manrubia d195497b76 Remove configure-lb scripts (moved to fizzy-saas gem)
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 16:06:40 +01:00
Jorge Manrubia 499b132b42 Remove script that depends on QB 2025-11-28 15:53:58 +01:00
Fernando Álvarez 91929d7c09 Add extra fizzy lbs 2025-11-28 15:19:51 +01:00
Mike Dalessio 2a88e8aacc Configure beta load balancer
including otel config
2025-11-24 14:21:42 -05:00
Kevin McConnell bd259f7795 Add optimistic pausing to avoid stale reads
Instead of writer pinning, we'll track the last transaction ID of each
write in the session. Then on each read we'll wait for the replica to
report that this transaction is available.

If it doesn't become available within a reasonable timeout, we'll
proceed anyway, and accept the possibility of a stale read.

The hope here is that most of the time, the replica is caught up in the
time between a write request and the following read request. If it's
not, we now have a little tolerance to wait for it, which hopefully
proves enough to stale reads are not encountered in normal use.

We also disable the writer affinity opt-out mechanism that we had
before, since we will no longer be using writer affinity at the load
balancer.
2025-11-24 13:29:52 +00:00
Stanko Krtalić c33802d37b Fix attachemnts (#1627)
* Load keys from tenanted dbs

* Implement sgid swapping

* Fix sgid generation

* Flip the logic to do lookups by tenant and id

* Create missing blobs

* Copy over variations

* fix-active-storage-links: fix mentions

* Fix variant generation

* Fix avatars

* Fix avatars

---------

Co-authored-by: Mike Dalessio <mike@37signals.com>
2025-11-20 11:47:49 -05:00
Stanko K.R. 245c328570 Decode the filename form the URL 2025-11-18 19:39:32 +01:00
Stanko K.R. d574748432 Add script to fix active storage links 2025-11-18 19:24:04 +01:00
David Heinemeier Hansson 43d384961a Add users to the populater too 2025-11-18 17:59:15 +01:00
David Heinemeier Hansson 9cbb6b4569 Broadcasts are slowing things down 2025-11-18 17:59:15 +01:00
David Heinemeier Hansson 8e6e764d58 Fix for an account-aware domain model 2025-11-18 17:44:25 +01:00
David Heinemeier Hansson bfe8d74ccd Fix the populate script and add tags 2025-11-18 17:36:33 +01:00
Stanko K.R. 1bd4a1b4e7 Disable webhooks and email notifications in non-prod envs 2025-11-18 16:16:01 +01:00
Stanko K.R. ab07488fbd Fix int and string overflow during prod import 2025-11-18 16:16:01 +01:00
Kevin McConnell 2661c7ba63 Update LB scripts for production deployment 2025-11-18 12:52:23 +00:00
Stanko K.R. b7404087bd Fix schema incomatibilities with production 2025-11-17 20:31:42 +01:00
Stanko K.R. d915bff326 Fix admin having duplicate user after import 2025-11-17 09:12:41 -05:00
Kevin McConnell 11a38a4526 Initial (wip) staging deployment
This adds an initial configuration for staging. Note that we are doing
this ahead of having the full infrastructure in all 3 DCs. So this
this will result in some cross-DC writes for now (e.g. we have a single cache in
IAD). We'll correct this as the infrastructure becomes available.

We'll also run jobs on every app server, until we split them out to
separate instances.
2025-11-17 09:12:41 -05:00
Stanko K.R. 0a3f91f220 Fix entropy imports 2025-11-17 09:12:41 -05:00
Mike Dalessio fe6df7085f Finish the rollout of account_id to all core data models
Schema:
- add account_id to tables it was missing from
- make account_id a required column everywhere
- add [account_id] indexes, or add `account_id` to existing indices

Models:
- add `belongs_to :account` to all models (default to using a domain
  model's account whenever possible)
- add account_id in all the necessary fixtures
- add account_id to insert_all hashes
- pass account_id to a few initialize calls

Miscellaneous:
- update the import script to set account_id

Note that I'm not adding account_id to the join tables primarily
because I couldn't think of an easy way to populate it without making
it a full Join model, and that was more work than I have time to take
on right now.
2025-11-17 09:12:40 -05:00
Stanko K.R. 8fa9566c07 Update sign up 2025-11-17 09:12:40 -05:00
Stanko K.R. edf837fed3 Drop memberships 2025-11-17 09:12:39 -05:00
Donal McBreen 84d1fb6827 Import steps correctly 2025-11-17 09:12:35 -05:00
Donal McBreen fc56ad9d7c Combine uuid-old and uuid branch changes
- Switch to binary 16 for UUID keys
- Remove AccountScopedRecord base class, all model use binary uuids now
- Fix the search sql to serialize uuids properly
- Patch the MySQL schema dumper to output binary lengths
2025-11-17 09:12:34 -05:00
Kevin McConnell 6c04b56f4b Compact the UUIDs to base36 2025-11-17 09:12:31 -05:00
Mike Dalessio e4011ef211 Update primary keys on customer data to UUIDs
- schema changes to primary and foreign keys
- fixture changes
- customer data models subclass AccountScopedRecord
- import script updated
2025-11-17 09:12:30 -05:00
Stanko K.R. 32d96db7d9 Replace card id with card number 2025-11-17 09:12:15 -05:00