Artifact 7c870e04f07e8364e819ed4aeed64f328b8ca08ea64536d36eb6c8e7ea9465b8:
- File
conformance/horizon_seedrefuse_zit_test.go
— part of check-in
[1afe809b01]
at
2026-10-24 00:37:46
on branch main
— feat(sync): origin refuses a pushed seed by label or shape (#471)
Horizon §5.2.3 as the zit 0.7.1 erratum words it. A pushed control artifact is a seed when its U card is the origin's own label (go-libfossil) or it carries a horizon-seed T card under any label. Full text is judged as it arrives. A delta is judged on its expanded content at the end of the request, so a delta whose base arrives later in the same request is caught. A delta never made readable is not identified and stays a dangling delta.
The refusal is atomic: the request rolls back, and the reply is the single error card "seed refused: a seed is private to the clone that holds it; it is never pushed". The horizon-seed name match is kept as an extra check, and now refuses loudly the same way instead of silently dropping the file.
Conformance cases for HZ-5.2-4 cover full text, a delta against a held base, a late delta, the shape under a foreign label (full and late), and a foreign label with no binding card, which is stored. An HZ-5.7-2 case covers the stale-seed check on a late delta. An interop case has zit 0.7.0 push such an artifact to a go-libfossil origin and get refused. (user: [email protected], size: 3317) [annotate] [blame] [check-ins using] [more...]
package conformance import ( "context" "net/http/httptest" "os" "path/filepath" "strings" "testing" "time" libfossil "github.com/danmestas/go-libfossil/internal/fsltype" "github.com/danmestas/go-libfossil/internal/manifest" "github.com/danmestas/go-libfossil/internal/repo" "github.com/danmestas/go-libfossil/internal/sync" "github.com/danmestas/go-libfossil/internal/tag" "github.com/danmestas/go-libfossil/simio" ) // TestZitHorizonSeedRefuseInterop pushes, from zit, a control artifact // bearing go-libfossil's seed label to a go-libfossil origin, which refuses // the whole push with the seed-refused error card (horizon §5.2.3, zit 0.7.1 // erratum). zit 0.7.0 keeps the seed it holds out of every push, so the // artifact reaches zit as ordinary content: a go-libfossil clone of the // origin writes it, and zit clones that clone. The reverse direction, a // zit origin refusing its own label, waits for zit 0.7.1. func TestZitHorizonSeedRefuseInterop(t *testing.T) { bin := zitHorizonBinary(t) origin, err := repo.Create(filepath.Join(t.TempDir(), "origin.fossil"), "u", simio.CryptoRand{}, "") if err != nil { t.Fatal(err) } defer origin.Close() if _, err := origin.DB().Exec("UPDATE user SET cap='gio' WHERE login='nobody'"); err != nil { t.Fatal(err) } when := time.Date(2026, 10, 1, 0, 0, 0, 0, time.UTC) if _, _, err := manifest.Checkin(origin, manifest.CheckinOpts{Files: []manifest.File{{Name: "c1", Content: []byte("c1\n")}}, Comment: "c1", User: "u", Time: when}); err != nil { t.Fatal(err) } server := httptest.NewServer(&hzRecorder{r: origin}) defer server.Close() dir := t.TempDir() home := filepath.Join(dir, "home") if err := os.Mkdir(home, 0o755); err != nil { t.Fatal(err) } mid, _, err := sync.Clone(context.Background(), filepath.Join(dir, "mid.fossil"), &sync.HTTPTransport{URL: server.URL}, sync.CloneOpts{}) if err != nil { t.Fatal(err) } defer mid.Close() if _, err := mid.DB().Exec("UPDATE user SET cap='gio' WHERE login='nobody'"); err != nil { t.Fatal(err) } var c1 libfossil.FslID if err := mid.DB().QueryRow("SELECT objid FROM event WHERE type='ci'").Scan(&c1); err != nil { t.Fatal(err) } labelled, err := tag.AddTag(mid, tag.TagOpts{TargetRID: c1, TagName: "seedtest", TagType: tag.TagSingleton, Value: "a", User: seedLoginGo, Time: when.Add(time.Hour)}) if err != nil { t.Fatal(err) } var labelledUUID string if err := mid.DB().QueryRow("SELECT uuid FROM blob WHERE rid=?", labelled).Scan(&labelledUUID); err != nil { t.Fatal(err) } midServer := httptest.NewServer(&hzRecorder{r: mid}) defer midServer.Close() zd := filepath.Join(dir, "zdense") zitRun(t, bin, home, dir, "clone", midServer.URL, zd, "--no-open", "--once") out, err := zitCommand(bin, home, zd, "push", server.URL) if err == nil || !strings.Contains(out, "seed refused: a seed is private to the clone that holds it; it is never pushed") { t.Fatalf("zit's push of a go-libfossil-labelled control artifact: %v\n%s", err, out) } // The igot round left a phantom for it, which the origin asked for. var held bool if err := origin.DB().QueryRow("SELECT EXISTS(SELECT 1 FROM blob WHERE uuid=? AND size>=0)", labelledUUID).Scan(&held); err != nil { t.Fatal(err) } if held { t.Fatal("the origin stored the refused artifact") } }