refactor(remote): carry the namespace partition key through the seams
🔍 What
Widens the S13 remote seam contracts in internal/remote to carry the namespace hash-partition key:
HealthStatusReader.HealthStatusandHealthStatusWriter.SetHealthStatusbecome(ctx, namespaceID, repositoryID, ...).- The three
CredentialRepomethods match, andCredentialManager's public methods (CredentialsPresent,SetCredentials,ClearCredentials,ApplyURLChange) widen with them — they are the seam's only callers and must forward the key. - The audit event payloads (
CredentialWriteEvent,HealthTransitionEvent,UpstreamDenialEvent) gain aNamespaceIDfield;CredentialManagerpopulates it on every credential write. RemoteRepositoryRefreorders its fields to the(NamespaceID, RepositoryID)order the seams take, as a reading aid for a consumer scanning the struct top-down. It is a nudge, not a guarantee: declaration order constrains nothing at a call site, so keyed literals remain the actual guard against transposing the two same-typed UUIDs.remotetest.FakeHealthStatusStorerecords the keys of every read and write, andremotetest.FakeCredentialRepogains one ordered call log discriminated by method, so a test can prove a caller forwarded both keys — they never surface in a return value — and, because the log spans all three methods, that the prior-state read preceded the persist. The call records carry the keys only, never a credential value: assertion failures render call records through reflection, bypassing the secret type's redaction. The persisted credential value is witnessed separately, byFakeCredentialRepo.LastSetCredentialsMatch, which compares digests: the fake retains a hash and never the credential, so no cleartext can reach an assertion's failure output or any render of the fake itself.
💡 Why
Every *_remote_repositories table is PARTITION BY HASH (namespace_id). A seam query keyed by repositories.id alone cannot pin the partition key, so it plans an Append over all 64 partitions with no index — the database evidence in !1192 (merged) shows this directly. Carrying namespaceID lets every implementation prune to one partition through the existing UNIQUE (namespace_id, repository_id) index, with no per-format (repository_id) index needed on any table, now or for future formats.
Every call site already holds the namespace: RemoteRepositoryRef carries NamespaceID for the scheduled sweep, and the on-demand probe, resolution, and management flows are namespace-scoped.
⌛ Sequencing
- !1161 (merged) (S13 Step 14 part 3, health monitor) edits the same files; whichever lands second rebases. The merged
SetHealthStatusshape combines this MR's parameters with that MR's(applied bool, err error)compare-and-set return. - !1192 (merged) and !1191 (merged) (S14 Steps 6 and 7) hold for this MR and adapt on rebase, pinning
namespace_idin their queries.
Related to #445 (closed)