Skip to content

Scope local ledger keys by forge host, not bare repoFullName #5563

Description

@JSONbored

Problem: Found during a third-pass gap audit across Miner Waves 1-4. --api-base-url (multi-forge/GitHub-Enterprise support, #4784) lets the miner poll owner/repo on a non-github.com host, but several local SQLite stores that key on repoFullName alone were built before that support existed. Two different forge hosts serving a same-named owner/repo collide in these stores.

Area: AMS / Miner (local stores)

Confirmed collision risk (repoFullName is part of a PRIMARY KEY / UNIQUE constraint):

  • claim-ledger.jsUNIQUE(repo_full_name, issue_number)
  • portfolio-queue.jsPRIMARY KEY (repo_full_name, identifier)
  • governor-state.js's governor_reputation_history table — repo_full_name TEXT PRIMARY KEY
  • run-state.jsrepo_full_name TEXT PRIMARY KEY
  • deny-hook-synthesis.jsPRIMARY KEY (repo_full_name, id)

Known lower-severity residual, out of scope for this issue: event-ledger.js, governor-ledger.js, prediction-ledger.js, and worktree-allocator.js use repo_full_name as a metadata/filter column, not a uniqueness key — cross-tenant rows can mix when filtered by repo, but nothing silently overwrites. replay-snapshot.js's UNIQUE(repo_full_name, commit_sha) has enormous natural collision resistance from the SHA component and is also excluded.

Prior art: #4843 fixed the exact same class of bug for policy-verdict-cache.js, via policyVerdictCacheKey(apiBaseUrl, repoFullName) → \${apiBaseUrl}::${repoFullName}`and renaming the keyed column torepo_scope`. This issue applies that same fix to the five stores above.

Acceptance criteria:

  • Each of the five stores above keys its uniqueness constraint on (apiBaseUrl, repoFullName) (or an equivalent composite scope), not bare repoFullName.
  • Existing on-disk rows migrate safely: a real SQLite table-rebuild backfills https://api.github.com (the pre-De-hardcode discovery from gittensory's own conventions #4784 implicit default) for every pre-existing row, with a regression test proving it.
  • Every call site threads its already-resolved apiBaseUrl through to the store instead of a bare repoFullName.
  • A dedicated cross-host regression test per store, mirroring Add a persisted cross-invocation cache of resolved policy verdicts #4843's own (two hosts, same-named repo, no collision).

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.roadmapOn the Wave-2 agent-layer roadmap board (project 9)

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions