.ai/principles/distilled/cells-claims.md
Prerequisite: If you haven't already, also read .ai/principles/distilled/cells-fundamentals.md - it contains foundational rules that apply to all cells work.
cells_claims_attribute specifies both a type (bucket type) and a feature_flag (model-specific control flag).cells_claims_metadata with subject_type and subject_key on every claimable model; source_type and source value are inferred automatically.Cells::Claimable in the model before declaring any cells_claims_attribute or cells_claims_metadata.beta feature flag YAML file at config/feature_flags/beta/cells_claims_<model>s.yml with default_enabled: false and group: group::cells infrastructure.beta feature flag YAML file at config/feature_flags/beta/cells_claims_verification_worker_<model_name>.yml with default_enabled: false.Bucket::Type, Subject::Type, and Source::Type entries in Topology Service's proto/claims/v1/messages.proto before using them in Rails.validation.go to prevent incorrect usage.scripts/update-topology-service-gem.sh in the MR branch.delete_all, insert_all, upsert_all, raw SQL) and handle claims for those paths using Cells::BulkClaimsWorker.it_behaves_like 'cells claimable model' and a dedicated spec file in spec/cells/claims/<model>_spec.rb covering creating, deleting, and updating claims.cells_unique_claims) and the model-specific flag (cells_claims_<model>s) for claims to take effect; claims do not work if either flag is disabled.cells_claims_verification_worker_<model_name>) only after the model-specific claiming flag is already active.user, email, route) as <model_name> in verification worker feature flag names.stub_feature_flags(cells_claims_your_model: false) and assert that no claims are created or deleted when the flag is disabled.Cells::Claimable callbacks; Phase 2 enables the verification worker for backfilling and ongoing consistency.if: and cells_claims_scope)if: lambda option on cells_claims_attribute to skip claiming specific values (for example, sub-paths or nil values); the lambda receives the record and must return a boolean.cells_claims_scope with a block returning an ActiveRecord::Relation to exclude rows from verification at the database level; define a block only when database-level exclusion is needed.if: and cells_claims_scope together when per-record save-time filtering and verification-time query filtering are both needed; use if: alone when only instance-level filtering (for example, skipping nil) is required.if: alone to exclude rows from verification scans when a database-level filter is also needed — define cells_claims_scope in that case.Cells::BulkClaimsWorker for code paths that use delete_all, insert_all, upsert_all, or raw SQL, because Cells::Claimable callbacks are bypassed in those paths.destroy_metadata with build_destroy_metadata_for_worker before deleting records, because metadata must be captured while the record still exists.create_record_ids (array of IDs) to Cells::BulkClaimsWorker for inserts; the worker loads records and builds claim metadata from them.Cells::BulkClaimsWorker with run_after_commit to keep claim operations outside the database transaction.Cells::Claimable::BULK_CLAIMS_BATCH_SIZE when scheduling bulk claim jobs.cells_claims_enabled_for_attribute? before scheduling Cells::BulkClaimsWorker.Cells::Claims::VerificationService (triggered by cells_claims_verification_worker_<model_name>) for backfilling existing records and for ongoing drift correction — DO NOT attempt manual backfills.it_behaves_like 'cells claimable model' to the model spec, specifying subject_type, subject_key, source_type, and claiming_attributes.spec/cells/claims/<model>_spec.rb using the shared examples 'creating new claims', 'deleting existing claims', and 'updating existing claims'.claims_records in the shared context when associated models also have claimable attributes (for example, User and its Email association).transform_attributes for the 'updating existing claims' shared example to specify which attributes change and verify old claims are destroyed and new ones are created.'updating existing claims' shared example only when the record can never be updated.gdk psql -d topology_service -c "SELECT * FROM claims;" after creating, updating, or deleting records.cells GDK setup and the cells_unique_claims feature flag are enabled before attempting local validation.For the full picture, see: