Skip to content

chore: add external user alias resolver - #2340

Merged
moshloop merged 8 commits into
mainfrom
external-user-alias
Aug 7, 2026
Merged

chore: add external user alias resolver#2340
moshloop merged 8 commits into
mainfrom
external-user-alias

Conversation

@yashmehrotra

@yashmehrotra yashmehrotra commented Aug 3, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Improvements

    • Improved external user recognition across aliases, email addresses, and historical identifiers.
    • Preserved identity continuity when users are renamed, merged, or remapped.
    • Added safer handling for ambiguous or outdated identity mappings.
    • External user information now refreshes automatically when changes are detected.
  • Reliability

    • Improved startup readiness checks and external cache initialization.
    • Cache refresh failures no longer replace valid existing data.
    • Improved handling of stale mappings and merged-user aliases.
    • Improved service shutdown and notification processing.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@yashmehrotra, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 4 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8471df2-5cbb-4f79-997f-c3a6a5bc4356

📥 Commits

Reviewing files that changed from the base of the PR and between 9e32fa0 and 42c9998.

📒 Files selected for processing (1)
  • scrapers/extract_e2e_test.go

Walkthrough

The change adds synchronized external-entity caches, canonical external-user alias and historical-ID resolution, readiness-aware table notifications, periodic cache refreshes, startup error handling, and validation coverage.

Changes

External user alias lifecycle

Layer / File(s) Summary
Alias cache and mapping index
db/external_cache.go
Typed caches now use locking and atomic replacement. User warming loads validated aliases, canonical IDs, and historical redirects. User lookups use cache-only resolution.
Canonical external-user resolution
db/external_entities.go
Resolution normalizes IDs and aliases, follows redirects, detects ambiguity, uses email fallback, preserves historical IDs, and refreshes caches after merges.
Event wiring and alias validation
cmd/server.go, db/external_user_alias_mapping_test.go, db/external_loser_alias_test.go, db/external_entities_test.go, scrapers/external_entities_test.go, scrapers/extract_e2e_test.go
The table listener waits for readiness, refreshes caches on notifications and on a six-hour interval, and handles shutdown. Tests cover stale mappings, failed refreshes, redirects, merge aliases, cache setup, and email fallback.
Startup error propagation and supporting updates
cmd/operator.go, cmd/run.go, db/config.go, go.mod
Startup paths now handle cache-warming and listener errors. Query tracing uses a fixed format string, and dependency versions are updated.

Sequence Diagram(s)

sequenceDiagram
  participant Serve
  participant startTableUpdatesHandler
  participant PostgreSQL
  participant tableUpdatesHandler
  participant RefreshExternalUserCaches
  Serve->>startTableUpdatesHandler: start listener
  startTableUpdatesHandler->>tableUpdatesHandler: launch handler
  startTableUpdatesHandler->>PostgreSQL: probe readiness
  PostgreSQL-->>tableUpdatesHandler: readiness notification
  tableUpdatesHandler-->>startTableUpdatesHandler: readiness confirmation
  Serve->>RefreshExternalUserCaches: warm caches
  PostgreSQL-->>tableUpdatesHandler: external-user update
  tableUpdatesHandler->>RefreshExternalUserCaches: refresh caches
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding an external user alias resolver.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch external-user-alias
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch external-user-alias

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Benchstat

Base: 47526a3b37c122b74061dbb4b4ca98eecfe598e6
Head: 42c99980153f4c24eee2aafd8d3bbc1c1dd7bb59

✅ 1 improvement(s)
Benchmark Base Head Change p-value
RunTemplateBool/largeEnv-4 20.01µ 19.85µ -0.80% 0.041
Full benchstat output
goos: linux
goarch: amd64
pkg: github.com/flanksource/config-db/bench
cpu: AMD EPYC 9V74 80-Core Processor                
                                         │ bench-base.txt │           bench-head.txt           │
                                         │     sec/op     │    sec/op     vs base              │
LocationFilter/smallEnv-4                    18.87µ ± 18%   18.93µ ± 20%       ~ (p=0.485 n=6)
LocationFilter/largeEnv-4                    46.23µ ± 13%   47.73µ ±  8%       ~ (p=0.589 n=6)
RunTemplateBool/smallEnv-4                   10.81µ ±  1%   10.87µ ±  1%       ~ (p=0.394 n=6)
RunTemplateBool/largeEnv-4                   20.01µ ±  2%   19.85µ ±  0%  -0.80% (p=0.041 n=6)
BenchSaveResultsSeed/N=1000-4                 3.580 ± 12%    3.596 ± 11%       ~ (p=0.937 n=6)
BenchSaveResultsUpdateUnchanged/N=1000-4      3.074 ±  3%    3.039 ±  3%       ~ (p=0.180 n=6)
BenchSaveResultsUpdateChanged/N=1000-4        7.327 ±  2%    7.313 ±  3%       ~ (p=0.589 n=6)
geomean                                      3.958m         3.971m        +0.33%

                                         │ bench-base.txt │            bench-head.txt            │
                                         │      B/op      │     B/op      vs base                │
LocationFilter/smallEnv-4                    14.97Ki ± 0%   14.97Ki ± 0%       ~ (p=1.000 n=6) ¹
LocationFilter/largeEnv-4                    20.38Ki ± 0%   20.38Ki ± 0%       ~ (p=0.061 n=6)
RunTemplateBool/smallEnv-4                   8.359Ki ± 0%   8.359Ki ± 0%       ~ (p=1.000 n=6) ¹
RunTemplateBool/largeEnv-4                   10.16Ki ± 0%   10.16Ki ± 0%       ~ (p=0.242 n=6)
BenchSaveResultsSeed/N=1000-4                1.277Gi ± 0%   1.278Gi ± 0%       ~ (p=0.394 n=6)
BenchSaveResultsUpdateUnchanged/N=1000-4     32.20Mi ± 0%   32.20Mi ± 0%       ~ (p=0.699 n=6)
BenchSaveResultsUpdateChanged/N=1000-4       797.1Mi ± 1%   796.7Mi ± 1%       ~ (p=0.818 n=6)
geomean                                      990.3Ki        990.2Ki       -0.00%
¹ all samples are equal

                                         │ bench-base.txt │            bench-head.txt            │
                                         │   allocs/op    │  allocs/op    vs base                │
LocationFilter/smallEnv-4                     278.0 ±  0%    278.0 ±  0%       ~ (p=1.000 n=6) ¹
LocationFilter/largeEnv-4                     522.0 ±  0%    522.0 ±  0%       ~ (p=1.000 n=6) ¹
RunTemplateBool/smallEnv-4                    216.0 ±  0%    216.0 ±  0%       ~ (p=1.000 n=6) ¹
RunTemplateBool/largeEnv-4                    297.0 ±  0%    297.0 ±  0%       ~ (p=1.000 n=6) ¹
BenchSaveResultsSeed/N=1000-4                442.6k ±  0%   442.7k ±  0%       ~ (p=0.699 n=6)
BenchSaveResultsUpdateUnchanged/N=1000-4     396.9k ±  0%   396.9k ±  0%       ~ (p=0.974 n=6)
BenchSaveResultsUpdateChanged/N=1000-4       984.1k ± 13%   984.1k ± 13%       ~ (p=1.000 n=6)
geomean                                      7.703k         7.703k        +0.00%
¹ all samples are equal

                                         │ bench-base.txt │           bench-head.txt           │
                                         │      MB/s      │    MB/s     vs base                │
BenchSaveResultsSeed/N=1000-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
BenchSaveResultsUpdateUnchanged/N=1000-4     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
BenchSaveResultsUpdateChanged/N=1000-4       0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                 ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Gavel summary

Source Pass Fail Skip Duration
api 6 0 0 2ms
aws 98 0 0 7ms
azure 43 0 0 1ms
changes 30 0 0 4.5s
cmd 5 0 0 332.466µs
db 46 0 0 14.2s
devops 208 0 0 15ms
exec 12 0 0 2m1s
extract 45 0 0 446ms
file 9 0 0 287.524µs
gcp 68 0 0 23ms
github 78 0 3 39ms
github.com/flanksource/config-db/api/v1 5 0 0 -
github.com/flanksource/config-db/cmd 4 0 0 9.9s
github.com/flanksource/config-db/cmd/scrapeui 2 0 0 -
github.com/flanksource/config-db/db 22 0 0 -
github.com/flanksource/config-db/scrapers/aws 5 0 0 -
github.com/flanksource/config-db/scrapers/gcp 2 0 0 -
github.com/flanksource/config-db/scrapers/github 6 0 0 -
github.com/flanksource/config-db/scrapers/postgres 2 0 0 -
github.com/flanksource/config-db/scrapers/processors 8 0 0 -
http 28 0 0 20ms
jobs 5 0 0 47.4s
kubernetes 34 0 0 1ms
playwright 9 0 0 508.112µs
scrapers 166 0 0 36.4s
terraform 1 0 0 533ms
tests 2 0 2 5.4s
utils 12 0 0 474.682µs
v1 124 0 0 4ms

Totals: 1085 passed · 0 failed · 5 skipped · 4m0s

View full results

@yashmehrotra
yashmehrotra marked this pull request as ready for review August 6, 2026 05:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (5)
db/external_user_alias_mapping_test.go (1)

140-146: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

This spec does not exercise the path it names.

Line 141 clears only ExternalUserIDCache. The preceding spec at Lines 125-138 called applyExternalUserAliasMapping, and findExternalUserIDsInAliasMapping repopulated ExternalUserCache with historicalID.String() -> canonicalID.

findExternalEntityByID then misses the ID cache, queries external_users for id = historicalID and finds nothing, and falls through to findExternalEntityIDByAliases. That call hits the still-populated ExternalUserCache and returns canonicalID. The spec passes through the alias cache, so it would still pass if the database alias-mapping query were broken.

Clear both caches to force the database path:

💚 Proposed fix
 	It("resolves direct references to a historical user ID", func() {
-		ExternalUserIDCache.Delete(historicalID.String())
+		ExternalUserIDCache.Flush()
+		ExternalUserCache.Flush()
 		resolved, err := findExternalEntityByID[dutymodels.ExternalUser](ctx, historicalID)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@db/external_user_alias_mapping_test.go` around lines 140 - 146, Update the
“resolves direct references to a historical user ID” spec to clear both
ExternalUserIDCache and ExternalUserCache before calling findExternalEntityByID,
ensuring the assertion exercises the database lookup path rather than stale
alias-cache data.
db/external_entities.go (1)

326-328: 🩺 Stability & Availability | 🔵 Trivial | 🏗️ Heavy lift

An ambiguous alias fails the entire external-entity sync.

This error propagates through resolveExternalUsers at Line 366 into syncExternalEntities, which returns immediately. One upstream identity whose keys resolve to two canonical users therefore blocks the sync of all users, all groups, all roles, and all user-group linkages for that scrape.

The surrounding code handles bad identity data differently. resolveExternalUsers skips a user with no ID and no aliases and increments skipped at Lines 368-372. resolveExternalUserGroups drops unresolvable rows and reports a v1.Warning. Ambiguity is upstream data, not a programming fault, so it fits the same posture.

Skip the ambiguous user, count it, and surface it as a warning instead of aborting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@db/external_entities.go` around lines 326 - 328, Update the external-user
resolution flow around the mappedIDs ambiguity check and resolveExternalUsers so
users resolving to multiple canonical IDs are skipped rather than returned as
errors. Increment the existing skipped count and emit a v1.Warning for the
ambiguous identity, allowing syncExternalEntities to continue processing all
other users, groups, roles, and linkages.
db/external_cache.go (2)

306-318: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the duplicated alias-validation join.

This join block is identical to the one in warmExternalUserAliasMappings at Lines 168-173. The two copies must stay in sync, because both enforce the same "index row is valid only while the alias is still in external_users.aliases" rule. Extract one helper that returns the scoped *gorm.DB, then add the differing Where clause at each call site.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@db/external_cache.go` around lines 306 - 318, Extract the shared
external-user alias validation JOIN from warmExternalUserAliasMappings and the
current mapping query into one helper returning the scoped *gorm.DB. Replace
both duplicated join blocks with that helper, while keeping each call site’s
distinct Where clause applied afterward.

120-129: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Cache the external_user_aliases existence check.

externalUserAliasTableExists runs a catalog query on every call. findExternalUserIDsInAliasMapping calls it once per unresolved external user during a scrape, so a large scrape adds one extra round trip per user. Memoize the result with a short TTL or refresh it in RefreshExternalUserCaches. Do not memoize a false result forever, because a later Duty migration can add the table at runtime.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@db/external_cache.go` around lines 120 - 129, Cache the result of
externalUserAliasTableExists with a short TTL, or refresh it from
RefreshExternalUserCaches, so repeated calls avoid querying the catalog for
every unresolved user. Ensure cached true and false results expire or are
refreshed, allowing a later Duty migration to detect the newly created table;
preserve the existing nil-database and query-error behavior.
db/external_loser_alias_test.go (1)

97-112: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Do not swallow the existence-check error, and clean up the index rows.

Two points on this block:

  1. Line 97 treats an error from externalUserAliasTableExists the same as an absent table. A database error therefore skips every assertion and the spec still passes. Assert the error separately so a real failure is visible.

  2. The deferred cleanup at Lines 47-49 deletes only external_users rows. Nothing deletes the external_user_aliases rows that the merge created. If the Duty schema has no cascade from external_users to that index, each run leaves orphan index rows whose external_user_id points to a deleted user.

💚 Proposed fix
-		if hasAliasIndex, err := externalUserAliasTableExists(DefaultContext.DB()); err == nil && hasAliasIndex {
+		hasAliasIndex, err := externalUserAliasTableExists(DefaultContext.DB())
+		Expect(err).NotTo(HaveOccurred())
+		if hasAliasIndex {
 			migratedAlias := sharedAlias

Extend the existing deferred cleanup at Lines 47-49:

defer func() {
	DefaultContext.DB().Exec(
		"DELETE FROM external_user_aliases WHERE external_user_id IN ?",
		[]uuid.UUID{winnerID, loserID, bridgeID},
	)
	DefaultContext.DB().Unscoped().Delete(&dutymodels.ExternalUser{}, "id IN ?", []uuid.UUID{winnerID, loserID, bridgeID})
}()

Guard the added delete so it does not fail when the table is absent, or run it inside the same existence check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@db/external_loser_alias_test.go` around lines 97 - 112, Update the external
alias test cleanup defer to delete rows from external_user_aliases for winnerID,
loserID, and bridgeID before removing the external users, while safely handling
an absent table. In the externalUserAliasTableExists check, assert the returned
error separately so database failures fail the test instead of skipping
assertions; only run alias assertions when the table exists.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@db/external_cache.go`:
- Around line 376-384: Update the alias filtering in
findAllExternalEntityIDsByAliases to distinguish aliases resolved by this call
from entries added concurrently to aliasCache. When dropping an alias because
its cache entry exists, add that cached ID to seen; only retain aliases for
fallback when they remain unresolved by both the call’s mappedIDs and the cache.
- Around line 166-178: Update the cache-warming query in the
external_user_aliases lookup to normalize eua.alias with trimming and
lowercasing before comparing it to the normalized source alias. Preserve the
existing deleted-record filters and cache error handling while ensuring both
sides of the EXISTS comparison use the same normalized representation.

In `@db/external_entities.go`:
- Around line 332-344: Reapply the existing ambiguity validation after the email
fallback updates mappedIDs in the external-user resolution flow. Ensure multiple
IDs from findCachedExternalUserIDs or findExternalUserIDsInAliasMapping return
the same ambiguity error as the earlier stronger-key path before the subsequent
len(mappedIDs) == 1 handling.

---

Nitpick comments:
In `@db/external_cache.go`:
- Around line 306-318: Extract the shared external-user alias validation JOIN
from warmExternalUserAliasMappings and the current mapping query into one helper
returning the scoped *gorm.DB. Replace both duplicated join blocks with that
helper, while keeping each call site’s distinct Where clause applied afterward.
- Around line 120-129: Cache the result of externalUserAliasTableExists with a
short TTL, or refresh it from RefreshExternalUserCaches, so repeated calls avoid
querying the catalog for every unresolved user. Ensure cached true and false
results expire or are refreshed, allowing a later Duty migration to detect the
newly created table; preserve the existing nil-database and query-error
behavior.

In `@db/external_entities.go`:
- Around line 326-328: Update the external-user resolution flow around the
mappedIDs ambiguity check and resolveExternalUsers so users resolving to
multiple canonical IDs are skipped rather than returned as errors. Increment the
existing skipped count and emit a v1.Warning for the ambiguous identity,
allowing syncExternalEntities to continue processing all other users, groups,
roles, and linkages.

In `@db/external_loser_alias_test.go`:
- Around line 97-112: Update the external alias test cleanup defer to delete
rows from external_user_aliases for winnerID, loserID, and bridgeID before
removing the external users, while safely handling an absent table. In the
externalUserAliasTableExists check, assert the returned error separately so
database failures fail the test instead of skipping assertions; only run alias
assertions when the table exists.

In `@db/external_user_alias_mapping_test.go`:
- Around line 140-146: Update the “resolves direct references to a historical
user ID” spec to clear both ExternalUserIDCache and ExternalUserCache before
calling findExternalEntityByID, ensuring the assertion exercises the database
lookup path rather than stale alias-cache data.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d400787-4652-4291-9c44-1c1e66ebb0a3

📥 Commits

Reviewing files that changed from the base of the PR and between eb696cb and 6d8fd49.

📒 Files selected for processing (5)
  • cmd/server.go
  • db/external_cache.go
  • db/external_entities.go
  • db/external_loser_alias_test.go
  • db/external_user_alias_mapping_test.go

Comment thread db/external_cache.go
Comment thread db/external_cache.go Outdated
Comment thread db/external_entities.go
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@socket-security

socket-security Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedgolang/​github.com/​flanksource/​commons@​v1.53.1 ⏵ v1.55.072 +1100100100100
Updatedgolang/​github.com/​flanksource/​duty@​v1.0.1352 ⏵ v1.0.135975 +1100100100100

View full report

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
cmd/server.go (1)

84-98: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Probe loop is correct, but the first probe can race the listener registration.

The loop sends the readiness probe before the router has registered the LISTEN. That first probe is lost, and the 100 ms ticker retries until readiness or timeout, so the handshake still converges. The lastErr capture keeps the last probe failure in the timeout message.

One detail: if ctx.DB().Exec fails on every iteration, the function still waits the full 10 s before reporting. Consider returning early after a fixed number of consecutive probe failures so a broken connection surfaces faster.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/server.go` around lines 84 - 98, Update the readiness probe loop around
ctx.DB().Exec to track consecutive probe failures and return an error after a
fixed threshold, rather than waiting for the full timeout when every probe
fails. Preserve the existing retry behavior for transient failures,
readiness-channel success, context cancellation, and timeout reporting with the
last probe error.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@db/external_cache.go`:
- Around line 310-312: Restore deterministic database recovery for external-user
cache misses: at db/external_cache.go lines 310-312, replace the unconditional
ExternalUser early return with a database lookup of the persisted external user,
while retaining cache fallback behavior for stale misses. Apply the same
recovery to the user alias-lookup path. cmd/run.go lines 98-100 requires no
direct change; its startup cache warming is evidence that later scrapers need
the database fallback.

In `@db/external_user_alias_mapping_test.go`:
- Around line 63-68: Update the AfterAll cleanup to delete external_user_aliases
by external_user_id using canonicalID rather than the incomplete mappingIDs
list, ensuring all trigger-created rows are removed. Since mappingIDs is then
only needed for BeforeAll assertions, remove the staleMappingID append in the
setup.
- Around line 80-95: Replace the inline defer in the spec around
RefreshExternalUserCaches with Ginkgo’s DeferCleanup, registering the rename
from external_user_aliases_unavailable back to external_user_aliases immediately
after the initial rename. Preserve the existing cleanup assertion and ensure it
runs even when later expectations in the test fail.

In `@go.mod`:
- Around line 8-10: Update the github.com/flanksource/commons dependency in
go.mod from the unavailable v1.55.0 to a published version such as v1.54.1,
while leaving the github.com/flanksource/deps and github.com/flanksource/duty
requirements unchanged.

---

Nitpick comments:
In `@cmd/server.go`:
- Around line 84-98: Update the readiness probe loop around ctx.DB().Exec to
track consecutive probe failures and return an error after a fixed threshold,
rather than waiting for the full timeout when every probe fails. Preserve the
existing retry behavior for transient failures, readiness-channel success,
context cancellation, and timeout reporting with the last probe error.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4b6bae37-86b0-458b-8b9e-3b0b4c775484

📥 Commits

Reviewing files that changed from the base of the PR and between 47526a3 and 2c7a99e.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (11)
  • cmd/operator.go
  • cmd/run.go
  • cmd/server.go
  • db/external_cache.go
  • db/external_entities.go
  • db/external_entities_test.go
  • db/external_loser_alias_test.go
  • db/external_user_alias_mapping_test.go
  • go.mod
  • scrapers/cron.go
  • scrapers/external_entities_test.go
💤 Files with no reviewable changes (1)
  • scrapers/cron.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • db/external_loser_alias_test.go
  • db/external_entities.go

Comment thread db/external_cache.go
Comment thread db/external_user_alias_mapping_test.go
Comment thread db/external_user_alias_mapping_test.go
Comment thread go.mod

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scrapers/extract_e2e_test.go`:
- Around line 362-368: Register the fixture cleanup immediately after creating
scraperModel, before the conditional RefreshExternalUserCaches call or any other
setup that can fail. Ensure the cleanup removes the database rows and scraper
records even when cache warming fails, while preserving the existing refresh
behavior.
- Around line 365-367: Update the fixture setup condition around
ExternalUserGroups to refresh the global external-user cache whenever external
users are pre-populated, including fixtures with users but no groups. In the
cleanup path for those pre-populated external users, invoke
RefreshExternalUserCaches again after deletion so later fixtures cannot observe
stale aliases.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8be9766f-ded6-4605-a4ac-177707bdc796

📥 Commits

Reviewing files that changed from the base of the PR and between 2c7a99e and fad99d8.

📒 Files selected for processing (2)
  • db/config.go
  • scrapers/extract_e2e_test.go

Comment thread scrapers/extract_e2e_test.go
Comment thread scrapers/extract_e2e_test.go
@moshloop
moshloop merged commit f94ac9c into main Aug 7, 2026
18 checks passed
@moshloop
moshloop deleted the external-user-alias branch August 7, 2026 15:51
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.

2 participants