Skip to content

[LFXV2-1311] fix(meetings): resolve committee v2 UID instead of storing v1 SFID#71

Merged
andrest50 merged 1 commit intomainfrom
andrest50/meeting-committee-uid
Mar 20, 2026
Merged

[LFXV2-1311] fix(meetings): resolve committee v2 UID instead of storing v1 SFID#71
andrest50 merged 1 commit intomainfrom
andrest50/meeting-committee-uid

Conversation

@andrest50
Copy link
Contributor

@andrest50 andrest50 commented Mar 20, 2026

Summary

  • When indexing v1_meeting and v1_past_meeting objects, the committee ID was being stored as the v1 Salesforce ID instead of the v2 UID
  • Fixes all affected code paths (meeting update, mapping update/delete, past meeting update, past meeting mapping update/delete) to look up the v2 UID via the committee.sfid.{sfid} mapping before sending to the indexer and access service
  • Fixes meeting.Committees not being populated on the meeting struct before sending the indexer message, and adds a CommitteeUID field to meetingInput for the resolved v2 UID of the primary committee field

Ticket

LFXV2-1311

🤖 Generated with Claude Code

When indexing v1_meeting and v1_past_meeting objects, the committee ID
was being stored as the v1 Salesforce ID instead of the v2 UID. This
fixes all affected code paths (meeting update, mapping update, mapping
delete, past meeting update, past meeting mapping update, past meeting
mapping delete) to look up the v2 UID via the committee.sfid.{sfid}
mapping before sending to the indexer and access service.

Also fixes meeting.Committees not being populated on the meeting struct
before sending the indexer message, and adds a CommitteeUID field to
meetingInput for the resolved v2 UID of the primary committee field.

Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Andres Tobon <andrest2455@gmail.com>
Copilot AI review requested due to automatic review settings March 20, 2026 17:15
@andrest50 andrest50 requested review from a team and emsearcy as code owners March 20, 2026 17:15
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes committee identifier propagation when syncing/indexing v1 meetings by resolving v1 committee SFIDs to v2 committee UIDs before publishing indexer/access messages, and by adding an explicit v2 committee_uid field for the primary committee.

Changes:

  • Add CommitteeUID (committee_uid) to meetingInput and wire it through JSON unmarshalling.
  • Resolve committee SFIDs to v2 UIDs via committee.sfid.<sfid> mappings across meeting and past-meeting update/mapping update/delete flows.
  • Populate meeting.Committees/pastMeeting.Committees so committee UID tags can be emitted during indexing.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
cmd/lfx-v1-sync-helper/models_meetings.go Adds committee_uid to the meeting payload model and unmarshalling so primary committee can be represented as a v2 UID.
cmd/lfx-v1-sync-helper/handlers_meetings.go Resolves committee SFIDs to v2 UIDs when building indexer/access messages and populates committee lists for tagging.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 342 to +347
// Committee is the ID of the committee
// It is a Global Secondary Index on the meeting table.
Committee string `json:"committee"`

// CommitteeUID is the v2 UID of the committee.
CommitteeUID string `json:"committee_uid,omitempty"`
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The struct comment for Committee is now misleading: the code treats meeting.Committee as a v1 committee SFID (it’s used to look up committee.sfid.<sfid>), while CommitteeUID is the v2 UID. Update the Committee field comment to explicitly state it stores the v1 SFID (GSI key) to avoid future misuse.

Copilot uses AI. Check for mistakes.
// Resolve the primary committee SFID to its v2 UID.
if meeting.Committee != "" {
committeeMappingKey := fmt.Sprintf("committee.sfid.%s", meeting.Committee)
if entry, err := mappingsKV.Get(ctx, committeeMappingKey); err == nil {
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CommitteeUID resolution silently ignores mappingsKV.Get failures. If the mapping is missing or there’s a transient KV error, CommitteeUID stays empty with no signal, which can cause downstream indexing/access updates to lose committee association. Consider distinguishing not-found vs other errors and at least logging the error (or returning an error on non-notfound) so this doesn’t fail silently.

Suggested change
if entry, err := mappingsKV.Get(ctx, committeeMappingKey); err == nil {
entry, err := mappingsKV.Get(ctx, committeeMappingKey)
if err != nil {
slog.Error("failed to resolve committee UID from SFID",
"committee_sfid", meeting.Committee,
"mapping_key", committeeMappingKey,
"error", err,
)
} else {

Copilot uses AI. Check for mistakes.
Comment on lines +333 to +345
// Resolve each committee's v1 SFID to its v2 UID via the committee.sfid mapping.
for _, cm := range committeeMappings {
committeeMappingKey := fmt.Sprintf("committee.sfid.%s", cm.CommitteeID)
if entry, err := mappingsKV.Get(ctx, committeeMappingKey); err == nil {
committeeUID := string(entry.Value())
committees = append(committees, committeeUID)
meeting.Committees = append(meeting.Committees, Committee{
UID: committeeUID,
AllowedVotingStatuses: cm.CommitteeFilters,
})
} else {
funcLogger.With("committee_sfid", cm.CommitteeID).WarnContext(ctx, "committee SFID not found in mappings, skipping")
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Committee SFID->UID lookups treat any mappingsKV.Get error as “not found” and continue. That means a transient KV issue can result in sending an indexer/access update with an incomplete committees list (effectively dropping committee tags/permissions). Consider handling non-notfound errors separately (log the error and abort this update), and include the underlying error in the log to aid debugging.

Copilot uses AI. Check for mistakes.
Comment on lines 1294 to 1301
// Try to get committee mappings from the index first
var committees []string
pastMeeting.Committees = []Committee{}
committeeMappings := make(map[string]mappingCommittee)
indexKey := fmt.Sprintf("v1-mappings.past-meeting-mappings.%s", uid)
indexEntry, err := mappingsKV.Get(ctx, indexKey)
if err == nil && indexEntry != nil {
if err := json.Unmarshal(indexEntry.Value(), &committeeMappings); err != nil {
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In handleZoomPastMeetingUpdate, committee resolution/population happens after the indexer message + tags are already sent earlier in the function. That means the past-meeting document is still indexed with the original (likely v1 SFID) committee IDs or with no committee tags, and only the access message benefits from the resolved v2 UIDs. Move committee resolution (and getPastMeetingTags) before sendIndexerMessage so indexing and access updates stay consistent.

Copilot uses AI. Check for mistakes.
Comment on lines +665 to +679
// Build the committee list from the now-complete index, resolving each v1 SFID to its v2 UID.
committees := []string{}
meeting.Committees = []Committee{}
for _, committee := range committeeMappings {
committees = append(committees, committee.CommitteeID)
meeting.Committees = append(meeting.Committees, Committee{
UID: committee.CommitteeID,
AllowedVotingStatuses: committee.CommitteeFilters,
})
committeeMappingKey := fmt.Sprintf("committee.sfid.%s", committee.CommitteeID)
if entry, err := mappingsKV.Get(ctx, committeeMappingKey); err == nil {
committeeUID := string(entry.Value())
committees = append(committees, committeeUID)
meeting.Committees = append(meeting.Committees, Committee{
UID: committeeUID,
AllowedVotingStatuses: committee.CommitteeFilters,
})
} else {
funcLogger.With("committee_sfid", committee.CommitteeID).WarnContext(ctx, "committee SFID not found in mappings, skipping")
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This committee-resolution block performs one KV lookup per committee and duplicates the same SFID->UID resolution logic in several handlers (meeting update/mapping update/delete, past-meeting equivalents). Consider extracting a small helper that resolves SFIDs with a per-handler cache and shared error handling; this will reduce JetStream KV round-trips and keep behavior consistent across code paths.

Copilot uses AI. Check for mistakes.
@andrest50 andrest50 merged commit 9623516 into main Mar 20, 2026
8 checks passed
@andrest50 andrest50 deleted the andrest50/meeting-committee-uid branch March 20, 2026 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants