Skip to content

fix(db): match digest subscriptions case-insensitively by login#1524

Open
galuis116 wants to merge 2 commits into
JSONbored:mainfrom
galuis116:fix/digest-subscription-login-case
Open

fix(db): match digest subscriptions case-insensitively by login#1524
galuis116 wants to merge 2 commits into
JSONbored:mainfrom
galuis116:fix/digest-subscription-login-case

Conversation

@galuis116

Copy link
Copy Markdown
Contributor

Summary

Fixes #1523.

upsertDigestSubscription and listDigestSubscriptionsForLogin keyed digest subscriptions on the raw login without case-normalizing it — even though the email is already lowercased, and every sibling subscription/identity path (notification subscriptions, issue-watch, notification deliveries, official-miner detections) lowercases login on both write and read. GitHub logins are case-insensitive, so a subscriber stored as "Foo" was missed on a "foo" lookup, and the [login, email] conflict target accumulated case-variant duplicate rows.

What changed

  • upsertDigestSubscription now stores login: input.login.toLowerCase(), and listDigestSubscriptionsForLogin looks up with login.toLowerCase() — making storage and lookup consistent and the [login, email] dedup effective, exactly like the sibling subscription paths.

Scope

Validation

  • git diff --check
  • npm run typecheck
  • npm run test:coverage locally (4619 passed); both changed lines are covered by a new case-insensitive + dedup test.
  • npm run test:workers
  • npm audit --audit-level=moderate
  • New unit test: mixed-case subscribe + cross-case lookup resolves; re-subscribe under another casing updates the single row (no duplicate).

If any required check was skipped, explain why:

  • OpenAPI/types/migrations unchanged — this normalizes an input before existing queries; the schema and DigestSubscriptionRecord shape are identical.

Safety

  • No secrets, wallets, hotkeys, PATs, trust scores, or private evidence exposed.
  • Public text sanitized and low-noise.
  • No auth/CORS/session change.
  • API/OpenAPI/MCP behavior unchanged.
  • No UI changes.
  • No changelog edit.

Notes

  • Confined to two functions in src/db/repositories.ts; mirrors the existing case-insensitive handling in the notification/issue-watch subscription paths.

@galuis116 galuis116 requested a review from JSONbored as a code owner June 26, 2026 13:01
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Jun 26, 2026
@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.37%. Comparing base (b5d575e) to head (75ef356).
⚠️ Report is 6 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1524   +/-   ##
=======================================
  Coverage   95.37%   95.37%           
=======================================
  Files         199      199           
  Lines       21546    21546           
  Branches     7791     7791           
=======================================
  Hits        20550    20550           
  Misses        416      416           
  Partials      580      580           
Files with missing lines Coverage Δ
src/db/repositories.ts 96.12% <100.00%> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored JSONbored added the gittensor:bug Gittensor-scored bug fix - worth 0.5x multiplier. label Jun 26, 2026
@gittensory-orb

gittensory-orb Bot commented Jun 27, 2026

Copy link
Copy Markdown

Caution

🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥

🛑 Gittensory review — blocked

2 files · 1 AI reviewers · no blockers · readiness 73/100 · CI failing · blocked

🛑 Blocked

Review summary
The change correctly normalizes GitHub login casing on both the write path (`upsertDigestSubscription`) and read path (`listDigestSubscriptionsForLogin`), closing the gap where a subscriber stored as "Foo" was missed on a "foo" lookup and the `[login, email]` conflict target accumulated case-variant duplicate rows. The fix mirrors existing lowercase normalization on sibling subscription paths and is accompanied by a well-structured test covering cross-case lookup and upsert-dedup. The one gap is that no SQL migration normalizes pre-existing rows, so mixed-case `login` values already in the table become unreachable after deploy without a re-upsert.

Blockers

  • src/db/repositories.ts — no schema migration normalizes pre-existing rows with mixed-case `login` values: after deploy, `listDigestSubscriptionsForLogin` (now querying `login.toLowerCase()`) will never return those rows, and a conflicting upsert will insert a new lowercase duplicate instead of updating the original, orphaning existing subscribers silently.

CI checks failing

  • validate
  • lint
Signal Result Evidence
Code review ✅ No blockers 1 reviewers, synthesized
Linked issue ✅ Linked #1523
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Review load ✅ 20/20 Readiness component derived from cached public PR metadata and labels; size label size:XS.
Validation evidence ❌ 5/25 Cached preflight status is hold.
Open PR queue ❌ 3/10 21 open PR(s), 9 likely reviewable, 12 unlinked.
Contributor context ✅ Confirmed Gittensor contributor galuis116; Gittensor profile; 797 PR(s), 154 issue(s).
Gate result ✅ Passing No configured blocker found.
Nits — 3 non-blocking
  • src/db/repositories.ts ~line 1286–1288 — the three-line comment block restates the PR description verbatim; a single `// GitHub logins are case-insensitive; normalize to match sibling paths` keeps the rationale without the noise.
  • Add a SQL migration — `UPDATE digest_subscriptions SET login = LOWER(login)` — to normalize pre-existing rows before or alongside this code change; without it the fix is safe for new writes but leaves existing mixed-case subscribers unreachable.
  • Consider normalizing `login` at the API input-validation boundary rather than inside these two DB functions, so any future accessor on `digestSubscriptions` is protected by default without needing a per-function toLowerCase() call.
Review context
  • Author: galuis116
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: not available
  • Official Gittensor activity: 797 PR(s), 154 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Fix blocker.
  • Expect slower review.
  • Refresh registry data or choose a registered active repo.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Review load = cached public PR metadata such as size labels, changed paths, and preflight status.
  • Open PR queue = repo-wide review pressure; it is not a PR quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
Review details

Generated from public PR metadata and the diff. Advisory only; deterministic signals remain authoritative.

The change correctly normalizes GitHub login casing on both the write path (`upsertDigestSubscription`) and read path (`listDigestSubscriptionsForLogin`), closing the gap where a subscriber stored as "Foo" was missed on a "foo" lookup and the `[login, email]` conflict target accumulated case-variant duplicate rows. The fix mirrors existing lowercase normalization on sibling subscription paths and is accompanied by a well-structured test covering cross-case lookup and upsert-dedup. The one gap is that no SQL migration normalizes pre-existing rows, so mixed-case `login` values already in the table become unreachable after deploy without a re-upsert.

Blockers

  • src/db/repositories.ts — no schema migration normalizes pre-existing rows with mixed-case `login` values: after deploy, `listDigestSubscriptionsForLogin` (now querying `login.toLowerCase()`) will never return those rows, and a conflicting upsert will insert a new lowercase duplicate instead of updating the original, orphaning existing subscribers silently.

Nits (3)

  • src/db/repositories.ts ~line 1286–1288 — the three-line comment block restates the PR description verbatim; a single `// GitHub logins are case-insensitive; normalize to match sibling paths` keeps the rationale without the noise.
  • Add a SQL migration — `UPDATE digest_subscriptions SET login = LOWER(login)` — to normalize pre-existing rows before or alongside this code change; without it the fix is safe for new writes but leaves existing mixed-case subscribers unreachable.
  • Consider normalizing `login` at the API input-validation boundary rather than inside these two DB functions, so any future accessor on `digestSubscriptions` is protected by default without needing a per-function toLowerCase() call.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@gittensory-orb gittensory-orb Bot added the gittensor Gittensor contributor context label Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix - worth 0.5x multiplier. gittensor Gittensor contributor context size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: digest subscriptions are keyed by case-sensitive login (missed lookups + case-variant duplicate rows)

2 participants