You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#11870 (merged in #11891) and #11892 (merged in #11893) removed RegistrationPolicyBucket#key as the identity mechanism used internally by signup simulation, occupancy checks, and editing correlation. What's left is external: the browser-based registration policy editor (RegistrationPolicyEditor/RegistrationBucketRow, rendered via RegistrationPolicyItemInput on the event edit form) never sends bucket id at all, for either existing or new buckets.
This isn't just an internal-cleanup gap -- it's the one remaining reason RegistrationPolicyBucket#key still needs to be a real, persisted, unique database column:
RegistrationPolicy#sync_buckets_from_hash! already prefers matching an incoming bucket hash by id, falling back to key only when no id is supplied (app/models/registration_policy.rb). Every edit made through the current UI takes that fallback path, because the UI never supplies an id.
The reason the browser never sees a bucket's id in the first place: RegistrationPolicyBucket#as_json (used to populate form_response_attrs_json, the only way the edit form receives registration policy data) deliberately omits id, and the frontend's EditingRegistrationBucket type (app/javascript/RegistrationPolicy/RegistrationBucketRow.tsx) explicitly excludes id from its editing state.
Separately, RegistrationPolicyBucketType#key (the bucket's own read-only GraphQL field, app/graphql/types/registration_policy_bucket_type.rb) is queried and used as a business-logic lookup key (not just displayed) in several other frontend query paths, unrelated to the editor:
Almost all of these are find/lookup/Object.fromEntries/React key= prop usages, directly convertible to bucket.id. A few (RunSignupsTable.tsx, RunEmailList.tsx, BucketKeyRemappingModal.tsx) fall back to bucket.name ?? bucket.key for display text -- since name is a NOT NULL database column, that fallback branch is already dead code and can just become bucket.name.
Proposed Change
RegistrationPolicyBucket#as_json (app/models/registration_policy_bucket.rb): add "id" => id to the hash. This also changes the shape of future FormResponseChange audit records (additive only -- existing readers that only look at key/name/etc. are unaffected).
RegistrationPolicyEditor.tsx/RegistrationBucketRow.tsx/app/javascript/RegistrationPolicy/RegistrationPolicy.ts: extend EditingRegistrationBucket (and the add/update/remove helpers) to carry an optional id -- undefined for a bucket added in the current edit session, the real id for anything loaded from the server. Thread it through into the hash sent back as form_response_attrs_json.
Convert the business-logic lookups in the file list above from bucket.key to bucket.id. Fix the bucket.name ?? bucket.key display fallbacks to just bucket.name.
Changes the shape of future FormResponseChange audit JSON (adds an id key) -- additive, but worth calling out since a prior comment on RegistrationPolicy#as_json was explicit about protecting that shape.
This is a real frontend state-management change (not just a mechanical rename) across several components; should be reviewed carefully for regressions in the registration policy editor, bucket key remapping modal, and signup admin bucket pickers.
Background
#11870 (merged in #11891) and #11892 (merged in #11893) removed
RegistrationPolicyBucket#keyas the identity mechanism used internally by signup simulation, occupancy checks, and editing correlation. What's left is external: the browser-based registration policy editor (RegistrationPolicyEditor/RegistrationBucketRow, rendered viaRegistrationPolicyItemInputon the event edit form) never sends bucketidat all, for either existing or new buckets.This isn't just an internal-cleanup gap -- it's the one remaining reason
RegistrationPolicyBucket#keystill needs to be a real, persisted, unique database column:RegistrationPolicy#sync_buckets_from_hash!already prefers matching an incoming bucket hash byid, falling back tokeyonly when no id is supplied (app/models/registration_policy.rb). Every edit made through the current UI takes that fallback path, because the UI never supplies an id.RegistrationPolicy#build_from_hashandIGNORED_BUCKET_HASH_KEYSalready keep a bucket'sidif the incoming hash has one -- this was built for exactly this purpose in Correlate registration policy buckets by id instead of key when editing/simulating policy changes #11870, but nothing has fed it real data yet.idin the first place:RegistrationPolicyBucket#as_json(used to populateform_response_attrs_json, the only way the edit form receives registration policy data) deliberately omitsid, and the frontend'sEditingRegistrationBuckettype (app/javascript/RegistrationPolicy/RegistrationBucketRow.tsx) explicitly excludesidfrom its editing state.Separately,
RegistrationPolicyBucketType#key(the bucket's own read-only GraphQL field,app/graphql/types/registration_policy_bucket_type.rb) is queried and used as a business-logic lookup key (not just displayed) in several other frontend query paths, unrelated to the editor:app/javascript/EventsApp/ScheduleGrid/queries.graphql->AvailabilityUtils.tsxapp/javascript/EventsApp/EventPage/queries.graphql->buildSignupOptions.ts,EventPageRunCard.tsx,CreateModeratedSignupModal.tsx,RunCapacityGraphBucket.tsx,EventCapacityDisplay.tsx,RunCapacityGraph.tsxapp/javascript/EventsApp/MySignupQueue/queries.graphql->UserSignupQueueItem.tsxapp/javascript/EventsApp/SignupAdmin/queries.graphql->SignupUtils.ts(findBucket),BucketInput.tsx,route.tsx,RunSignupsTable.tsx,RunEmailList.tsxapp/javascript/SignupModeration/queries.graphql->CreateSignupRunCard.tsx,SignupModerationQueue.tsxapp/javascript/EventAdmin/queries.graphql->BucketKeyRemappingModal.tsx,useBucketKeyRemapping.tsxapp/javascript/Reports/queries.graphql->Tables/BucketChangeCell.tsx(viaSignupUtils.ts)Almost all of these are
find/lookup/Object.fromEntries/Reactkey=prop usages, directly convertible tobucket.id. A few (RunSignupsTable.tsx,RunEmailList.tsx,BucketKeyRemappingModal.tsx) fall back tobucket.name ?? bucket.keyfor display text -- sincenameis aNOT NULLdatabase column, that fallback branch is already dead code and can just becomebucket.name.Proposed Change
RegistrationPolicyBucket#as_json(app/models/registration_policy_bucket.rb): add"id" => idto the hash. This also changes the shape of futureFormResponseChangeaudit records (additive only -- existing readers that only look atkey/name/etc. are unaffected).RegistrationPolicyEditor.tsx/RegistrationBucketRow.tsx/app/javascript/RegistrationPolicy/RegistrationPolicy.ts: extendEditingRegistrationBucket(and the add/update/remove helpers) to carry an optionalid--undefinedfor a bucket added in the current edit session, the real id for anything loaded from the server. Thread it through into the hash sent back asform_response_attrs_json.bucket.keytobucket.id. Fix thebucket.name ?? bucket.keydisplay fallbacks to justbucket.name.Benefits
sync_buckets_from_hash!'s key-based fallback is load-bearing for the liveupdateEventmutation.Tradeoffs
FormResponseChangeaudit JSON (adds anidkey) -- additive, but worth calling out since a prior comment onRegistrationPolicy#as_jsonwas explicit about protecting that shape.References
registration_policy_buckets.key; see Deprecate and remove the remaining bucket key-based GraphQL/Liquid surface (phase 2 of dropping RegistrationPolicyBucket#key) #11896, Retire RegistrationPolicyBucket#key as an identity mechanism in the app layer (phase 3 of dropping RegistrationPolicyBucket#key) #11897, Drop the registration_policy_buckets.key column (phase 4 of dropping RegistrationPolicyBucket#key) #11898Issue drafted by Claude