Skip to content

feat(d1): github org claim and repo-topic link repositories (2/5) - #13

Merged
TOMOKI977 merged 2 commits into
mainfrom
feat/github-alerts-d1
Sep 24, 2026
Merged

TOMOKI977 merged 2 commits into
mainfrom
feat/github-alerts-d1

Conversation

@TOMOKI977

Copy link
Copy Markdown
Contributor

Summary

Second PR of the github-alerts chain. It adds the D1 adapters behind the PR 1 ports. They are not wired into the composition root yet (that is PR 4), so there is no user-visible change.

  • createD1GithubOrgClaimRepo:
    • findTeamByOrg is the only intentional cross-team lookup.
    • isClaimedBy is tenant-scoped.
    • Both match the org case-insensitively.
  • createD1RepoTopicLinkRepo:
    • get, upsert, remove and list are all scoped by team_id.
    • upsert is a single atomic INSERT ... ON CONFLICT DO UPDATE, so re-linking moves a repo to the new topic.
  • All SQL is parameterized. D1 errors propagate unchanged, so the webhook route can answer 500 as the spec requires.

Size exception: about 920 lines. Production code is about 130 of them; the rest is tests, the updated fakes and the apply-progress notes.

Review

Full review with four lenses, since the diff is over 400 lines and concerns tenant isolation. No blockers. One critical finding was confirmed and fixed:

  • upsert ignored its tenant-scoping teamId argument and wrote under link.teamId. This broke the "TeamId first" isolation rule the ports are built around, and the in-memory fake did the opposite, so domain tests could not catch it. Now the argument is authoritative, and a mismatch throws TenantMismatchError before any write. Because this error is not listed in any command's errorReplies, it surfaces as a 500 rather than a friendly reply.

Warnings were also fixed:

  • A tenant-isolation test for remove.
  • The fake isClaimedBy was case-sensitive while D1 was not. A test now pins the D1 behavior.
  • D1-failure propagation tests for both adapters, using a failing binding stub.

A scoped fix-delta validator approved the correction.

Test plan

  • npx vitest run: 260/260 pass
  • npx tsc --noEmit: no errors

Operator

The org claim (tasks.md 6.3) is already done in production. The next operator step is the webhook secret, after PR 3.

D1 adapters for GithubOrgClaimRepo and RepoTopicLinkRepo with tenant-scoped, parameterized SQL. upsert treats its teamId argument as authoritative and rejects a mismatched link with TenantMismatchError before writing. The in-memory fakes now match the adapters (case-insensitive org matching, same mismatch check).
@TOMOKI977 TOMOKI977 added the size:exception PR over the 400-line review budget, accepted explicitly label Sep 24, 2026
@TOMOKI977
TOMOKI977 merged commit 5b6d4f4 into main Sep 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:exception PR over the 400-line review budget, accepted explicitly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant