Ensure a root cannot be clobbered #3
Labels
No labels
agent
blocked
agent
new
agent
review
agent
working
complexity
high
complexity
low
priority
high
priority
low
priority
medium
risk
high
risk
low
risk
medium
type
bug
type
chore
type
feature
type
security
No milestone
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
tfks/dropbear#3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A single bucket can serve multiple roots, which should be fine as long as the init command fails if there is already an initialized root on the bucket.
If this functionality already exists, then make sure it's documented in the user ./doc/ somewhere.
Brief — Developer
Phase: simple. Run
fjx dev prompt simplefor the cycle protocol.Ledger for: agent-pm
Status: closed @ 2026-06-04T23:38:38.842Z
Briefs:
Activity
(PM manages this ledger; agent section unused)
Ledger for: agent-dev
Status: review @ 2026-06-03T16:33:37.406Z
Refs: #13
Tasks
dropbear register.Evidence
73361e9 refuse unsafe root bootstrap.just validatepassed under Go 1.26.4 with writable external caches and test temp dirs configured for POSIX permission semantics.Notes
dropbear registernow refuses to initialize a root when objects already exist under the root prefix anddevices/registry.jsonis absent.devices/registry.jsonremain joinable; restore fixtures now seed that sentinel where they model initialized remote roots.I fixed the issue blocking agent-dev. Try again.
Brief - QA
Phase: default. Run
fjx qa prompt defaultfor the cycle protocol.Review PR #13 for issue #3. The change should make
dropbear registerrefuse to bootstrap a root when objects already exist under the configured root prefix butdevices/registry.jsonis absent.Focus on:
devices/registry.jsonstill join normally.Ledger for: agent-qa
Status: fail @ 2026-06-04T06:12:03.688Z
Action Summary
Both runs are on commit
73361e9(42–44 s execution each). Both fail — this is not an infra flake (different trigger types, same outcome).Per-step log access:
fjx qa checksreturns run-level metadata only; there is nofjxsubcommand for step logs.WebFetchof thehtml_url(https://git.tfks.net/tfks/dropbear/actions/runs/20) returned no useful content — private Forgejo instance requires authenticated session. Step-level failure cannot be quoted verbatim; classification relies on local reproduction and diff analysis below.Gap Analysis
The validate workflow runs: secrets → format → vet → lint → units → audit → build. Local execution against this branch:
Critical finding — Go version mismatch: The PR description states validation was run with
GOTOOLCHAIN=go1.26.4. The CI workflow specifiesGO_VERSION: "1.25.10", matching the go.mod (go 1.25.4 / toolchain go1.25.10). The lint step is the most likely CI failure point: golangci-lint on the runner may have a similar Go version mismatch in the opposite direction, or the runner's golangci-lint binary itself has compatibility issues with the Go version installed by setup-go.Code Review
The diff is clean and correct for what it does:
EnsureRootNotInitializedlogic (internal/deviceregistry/registry.go:271): Reads registry first; if it exists → safe, return nil. If not-found error → lists root prefix; returnsErrRootAlreadyInitializedon first non-registry object. Correct early-return pattern.Guard placement (
cmd/dropbear/register.go:113):EnsureRootNotInitializedis called after the object store is constructed but beforedeviceregistry.Registerand beforeconfig.Init. This satisfies the brief's requirement that the guard runs before local root config is written.clean_test.gofix: Correctly replacedrunRegister(...)withconfig.Init(...)to bypass the new guard in tests that seed remote state before callingrunRegister— the register guard would otherwise reject the pre-seeded fake state. The test intent (clean deletes root prefix) is unchanged.Fixture updates (restore_test.go, run_test.go):
seedRegistrycalls added so tests that model a joinable remote root include the registry sentinel. Correct.RootPrefixfunction (internal/objectstore/keys.go): Returnsjoin(prefix, "roots", rootID) + "/". Consistent with existing key format forDeviceRegistryKey(<prefix>/roots/<rootID>/devices/registry.json). Table tests cover empty prefix and slash-wrapped prefix.Tests that were not written (gaps):
EnsureRootNotInitializedwhenstore.Listreturns an error (non-ErrNotFound) on the listing step — the error path at line ~284 is untested.config.Initwrites.dropbear/—TestRegisterRefusesExistingRootStateWithoutRegistrydoes checkos.Stat(.dropbear)is absent, which covers this indirectly.EnsureRootNotInitializedwith an empty root prefix (prefix="") is not tested, thoughRootPrefixis tested for that case.Verdict
fail — CI failed on both runs (PR and push triggers); consistent failure is not an infra flake. The developer validated against Go 1.26.4 while CI requires Go 1.25.10 (per go.mod and workflow
GO_VERSION). The exact failing step is not readable (see gap analysis), but the Go toolchain discrepancy is the most probable root cause.Code logic is sound and would pass review if CI is fixed. Agent-dev should re-run
just validateunder Go 1.25.10 (matching CI) and fix whatever step fails there.