Skip to content
quarry Artifact [978652fe44]
Login

Artifact [978652fe44]

Artifact 978652fe4482b08a4a43fdf9b040c8601460c67b53675d52d5209eb6e580eb14:


package api

import (
	"bytes"
	"context"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"log"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"strings"
	"sync"
	"testing"
	"time"

	"craftdesign.group/quarry/internal/cisecret"
	"craftdesign.group/quarry/internal/oltp"
	"craftdesign.group/quarry/internal/ops"
)

// missLimiter is the sign-in limiter's shape for a test: five free
// misses per name and per address, then held until release.
type missLimiter struct {
	mu   sync.Mutex
	miss map[string]int
	held bool
}

func (l *missLimiter) Allowed(user, ip string) (bool, time.Duration) {
	l.mu.Lock()
	defer l.mu.Unlock()
	if l.miss["a:"+ip] > 5 {
		return false, 30 * time.Second
	}
	return true, 0
}
func (l *missLimiter) Failed(user, ip string) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.miss["u:"+user]++
	l.miss["a:"+ip]++
}
func (l *missLimiter) Succeeded(user, ip string) {
	l.mu.Lock()
	defer l.mu.Unlock()
	delete(l.miss, "u:"+user)
	delete(l.miss, "a:"+ip)
}
func (l *missLimiter) release() {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.miss = map[string]int{}
}

type pickupRig struct {
	db   *oltp.DB
	deps Deps
	r    *ops.Registry
	h    http.Handler
	coll *PickupCollector
	lim  *missLimiter
	eng  *workerEngine
	rec  *settingRecorder
	ctx  context.Context
}

func newPickupRig(t *testing.T) pickupRig { return newPickupRigWith(t, nil) }

func newPickupRigWith(t *testing.T, tweak func(*Deps)) pickupRig {
	t.Helper()
	db, err := oltp.Open(filepath.Join(t.TempDir(), "o.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { db.Close() })
	if err := db.AddAccount("jva", "a-long-enough-password", false); err != nil {
		t.Fatal(err)
	}
	if err := db.AddAccount("jva-bot", "a-long-enough-password", false); err != nil {
		t.Fatal(err)
	}
	if err := db.SetOperator("jva-bot", "jva"); err != nil {
		t.Fatal(err)
	}
	eng := &workerEngine{}
	rec := &settingRecorder{}
	holds := func(string, string) CapSet { return oltp.CapSet("a") }
	deps := Deps{Version: "v", WorkerTokens: eng, SettingLog: rec, SecretBox: testBox(t),
		Repos:    NewRepos(map[string]*Repo{"test": {Index: wikiIndex(t), Code: "code-test"}}),
		Accounts: adminAdapter{acctAdapter{db}}, SignOffs: testSignOffs{db}, CapsFor: holds}
	if tweak != nil {
		tweak(&deps)
	}
	r := ops.NewRegistry()
	if err := RegisterAll(r, deps); err != nil {
		t.Fatal(err)
	}
	h, err := RouterWithCaps(r, "v", holds, nil)
	if err != nil {
		t.Fatal(err)
	}
	lim := &missLimiter{miss: map[string]int{}}
	ctx := ops.WithToken(ops.WithUser(context.Background(), "jva-bot"), ops.TokenAuth{ID: "T", Caps: func(string) ops.Caps { return oltp.CapSet("a") }})
	return pickupRig{db: db, deps: deps, r: r, h: h, coll: NewPickupCollector(deps, lim, nil), lim: lim, eng: eng, rec: rec, ctx: ctx}
}

func newPickupKey(t *testing.T) (key, code string) {
	t.Helper()
	raw := make([]byte, 32)
	if _, err := rand.Read(raw); err != nil {
		t.Fatal(err)
	}
	return base64.RawURLEncoding.EncodeToString(raw), PickupCodeOf(raw)
}

// ask files a worker-token request as the agent, bound to code when it
// names one, and returns its id.
func (g pickupRig) ask(t *testing.T, label, code string) (int, string) {
	t.Helper()
	req := httptest.NewRequest("POST", "/api/v1/r/test/ci/worker-tokens", strings.NewReader(`{"label":"`+label+`"}`)).WithContext(g.ctx)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Quarry-Ask", "a runner")
	if code != "" {
		req.Header.Set("Quarry-Pickup", code)
	}
	w := httptest.NewRecorder()
	g.h.ServeHTTP(w, req)
	var asked struct {
		SignOff SignOffRequest `json:"signoff"`
	}
	_ = json.Unmarshal(w.Body.Bytes(), &asked)
	return w.Code, asked.SignOff.ID
}

func (g pickupRig) decide(t *testing.T, id string, approve bool) {
	t.Helper()
	if _, err := g.r.Invoke(asUser("jva"), "signoff.decide", signOffDecideIn{ID: id, Approve: approve}); err != nil {
		t.Fatal(err)
	}
}

// collect sends the collect call with an Authorization header, and
// returns the status and the body.
func (g pickupRig) collect(auth, path, query string) (int, string) {
	req := httptest.NewRequest("POST", path+query, nil)
	if auth != "" {
		req.Header.Set("Authorization", auth)
	}
	req.RemoteAddr = "192.0.2.7:4000"
	if i := strings.Index(path, "/r/"); i >= 0 {
		parts := strings.Split(strings.Trim(path[i:], "/"), "/")
		req.SetPathValue("repo", parts[1])
	}
	w := httptest.NewRecorder()
	g.coll.ServeHTTP(w, req)
	return w.Code, w.Body.String()
}

const collectPath = "/api/v1/pickups/collect"

// A request asked with a pickup code is approved and collected with the
// key exactly once; the asker's own signoff.get never has the secret,
// before or after; every other answer is the RFC's.
func TestAPickupBoundRequestIsCollectedOnceAndNeverThroughSignoffGet(t *testing.T) {
	var logs bytes.Buffer
	log.SetOutput(&logs)
	defer log.SetOutput(log.Writer())
	g := newPickupRig(t)
	key, code := newPickupKey(t)
	auth := "Pickup " + key
	status, id := g.ask(t, "one", code)
	if status != 202 || id == "" {
		t.Fatalf("FAIL: asking with a pickup code: %d", status)
	}
	row, _, _ := g.db.SignOffByID(id)
	if row.Pickup != code {
		t.Fatalf("FAIL: the request does not hold the code")
	}
	if got, err := g.r.Invoke(asUser("jva"), "signoff.get", signOffGetIn{ID: id}); err != nil || got.(signOffGetOut).Request.Pickup != code {
		t.Errorf("FAIL: the owner's view of the request lacks the bound code: %v", err)
	}

	// Not yet decided: the key holder is told it waits; a wrong key,
	// an unknown code and a malformed header are one answer.
	if st, body := g.collect(auth, collectPath, ""); st != 202 || strings.Contains(body, key) {
		t.Errorf("FAIL: undecided: %d", st)
	}
	wrong, _ := newPickupKey(t)
	wrongSt, wrongBody := g.collect("Pickup "+wrong, collectPath, "")
	for name, a := range map[string]string{"short": "Pickup abc", "scheme": "Bearer " + key, "none": "", "junk": "Pickup !!!!"} {
		if st, body := g.collect(a, collectPath, ""); st != wrongSt || body != wrongBody {
			t.Errorf("FAIL: %s answered %d %s, a wrong key %d %s", name, st, body, wrongSt, wrongBody)
		}
	}
	if wrongSt != 404 {
		t.Errorf("FAIL: a wrong key answered %d", wrongSt)
	}
	// A key in a query string is refused before it is read.
	if st, _ := g.collect("", collectPath, "?key="+key); st != 400 {
		t.Errorf("FAIL: a query string answered %d", st)
	}

	g.decide(t, id, true)
	// signoff.get by the asker never has the secret, and leaves it.
	for i := 0; i < 2; i++ {
		got, err := g.r.Invoke(asUser("jva-bot"), "signoff.get", signOffGetIn{ID: id})
		if err != nil || len(got.(signOffGetOut).Secret) != 0 || strings.Contains(string(got.(signOffGetOut).Result), "s3cret-bearer-value") {
			t.Fatalf("FAIL: signoff.get gave the asker the secret: %v %+v", err, got)
		}
	}
	g.lim.release()
	// The wrong key still gets the generic answer and takes nothing.
	if st, body := g.collect("Pickup "+wrong, collectPath, ""); st != wrongSt || body != wrongBody {
		t.Errorf("FAIL: a wrong key after approval: %d %s", st, body)
	}
	st, body := g.collect(auth, collectPath, "")
	var out struct {
		Request string          `json:"request"`
		Op      string          `json:"op"`
		Agent   string          `json:"agent"`
		Owner   string          `json:"owner"`
		Repo    string          `json:"repo"`
		Secret  json.RawMessage `json:"secret"`
	}
	if err := json.Unmarshal([]byte(body), &out); err != nil || st != 200 || out.Request != id || out.Agent != "jva-bot" || out.Owner != "jva" || out.Op != "ci.worker.token.new" || out.Repo != "test" ||
		!strings.Contains(string(out.Secret), "s3cret-bearer-value") {
		t.Fatalf("FAIL: collecting: %d %s", st, body)
	}
	st, body = g.collect(auth, collectPath, "")
	if st != 410 || strings.Contains(body, "s3cret-bearer-value") || !strings.Contains(body, `"collected"`) {
		t.Errorf("FAIL: collecting twice: %d %s", st, body)
	}
	after, _ := g.r.Invoke(asUser("jva-bot"), "signoff.get", signOffGetIn{ID: id})
	if len(after.(signOffGetOut).Secret) != 0 {
		t.Errorf("FAIL: signoff.get gave the secret after collection")
	}
	// Nothing for a lapse to revoke once collected.
	if n, err := g.deps.LapseSignOffSecrets(time.Now().Add(48 * time.Hour)); err != nil || n != 0 || len(g.eng.revoked) != 0 {
		t.Errorf("FAIL: a sweep after collection: %d %v revoked %v", n, err, g.eng.revoked)
	}
	for _, secret := range []string{key, strings.TrimRight(key, "=")} {
		if strings.Contains(logs.String(), secret) {
			t.Errorf("FAIL: the key is in the log")
		}
	}
	if strings.Contains(logs.String(), "s3cret-bearer-value") {
		t.Errorf("FAIL: the value is in the log")
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// Denied, an uncollected lapse, the sync URL's route and an unfinished
// ask, each as the key holder is told.
func TestAPickupAnswersForADeniedALapsedAndAMisdirectedRequest(t *testing.T) {
	g := newPickupRig(t)
	denyKey, denyCode := newPickupKey(t)
	_, denied := g.ask(t, "deny", denyCode)
	g.decide(t, denied, false)
	if st, body := g.collect("Pickup "+denyKey, collectPath, ""); st != 410 || !strings.Contains(body, `"denied"`) {
		t.Errorf("FAIL: a denied request: %d %s", st, body)
	}
	if st, body := g.collect("Pickup "+denyKey, collectPath, ""); st != 410 {
		t.Errorf("FAIL: a denied request again: %d %s", st, body)
	}

	key, code := newPickupKey(t)
	_, id := g.ask(t, "lapse", code)
	g.decide(t, id, true)
	// The sync URL's route: a repository the credential does not reach
	// consumes nothing; the one it was minted for collects.
	if st, _ := g.collect("Pickup "+key, "/r/elsewhere/pickup", ""); st != 409 {
		t.Errorf("FAIL: a repository the credential does not reach: %d", st)
	}
	if row, _, _ := g.db.SignOffByID(id); row.Secret == "" || row.Collected != "" {
		t.Fatalf("FAIL: a refused route consumed the secret")
	}
	// Uncollected past its limit: revoked exactly as an unbound one is,
	// and the key holder is told it lapsed.
	if n, err := g.deps.LapseSignOffSecrets(time.Now().Add(25 * time.Hour)); err != nil || n != 1 {
		t.Fatalf("FAIL: the sweep cleared %d (%v)", n, err)
	}
	if len(g.eng.revoked) != 1 {
		t.Errorf("FAIL: revoked %v", g.eng.revoked)
	}
	lapses := 0
	for _, row := range g.rec.rows {
		if strings.Contains(row.now, "lapsed uncollected") && strings.Contains(row.now, id) {
			lapses++
		}
	}
	if lapses != 1 {
		t.Errorf("FAIL: %d lapse rows", lapses)
	}
	if st, body := g.collect("Pickup "+key, collectPath, ""); st != 410 || !strings.Contains(body, `"lapsed"`) || strings.Contains(body, "s3cret-bearer-value") {
		t.Errorf("FAIL: a lapsed request: %d %s", st, body)
	}
	if st, _ := g.collect("Pickup "+key, "/r/elsewhere/pickup", ""); st != 410 {
		t.Errorf("FAIL: a lapsed request on a repository it does not reach: %d, want 410", st)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// The sync URL's route collects for a repository the credential reaches.
func TestAPickupCollectsOnASyncURLForTheRepositoryItReaches(t *testing.T) {
	g := newPickupRig(t)
	key, code := newPickupKey(t)
	_, id := g.ask(t, "sync", code)
	g.decide(t, id, true)
	if st, body := g.collect("Pickup "+key, "/r/test/pickup", ""); st != 200 || !strings.Contains(body, "s3cret-bearer-value") {
		t.Errorf("FAIL: collecting on the repository's own URL: %d %s", st, body)
	}
	if st, _ := g.collect("Pickup "+key, "/r/test/pickup", ""); st != 410 {
		t.Errorf("FAIL: collecting twice: %d", st)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// Holds fall on wrong keys alone: past the free misses an address's
// wrong keys are held (429), and the right key is still served, since a
// held address is shared and a key cannot be guessed.
func TestAPickupHoldsFallOnMissesNotOnTheRightKey(t *testing.T) {
	g := newPickupRig(t)
	key, code := newPickupKey(t)
	_, id := g.ask(t, "limit", code)
	g.decide(t, id, true)
	for i := 0; i < 6; i++ {
		bad, _ := newPickupKey(t)
		if st, _ := g.collect("Pickup "+bad, collectPath, ""); st != 404 {
			t.Fatalf("FAIL: wrong key %d answered %d", i, st)
		}
	}
	bad, _ := newPickupKey(t)
	if st, _ := g.collect("Pickup "+bad, collectPath, ""); st != 429 {
		t.Errorf("FAIL: a wrong key from a held address: %d", st)
	}
	if st, body := g.collect("Pickup "+key, collectPath, ""); st != 200 || !strings.Contains(body, "s3cret-bearer-value") {
		t.Errorf("FAIL: the right key from a held address: %d %s", st, body)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// The plain rates bind every call, a right key too: ten a minute from
// one address and six a minute for one key, each clearing with the
// window.
func TestAPickupCallsAreRateLimited(t *testing.T) {
	g := newPickupRig(t)
	at := time.Now()
	g.coll.now = func() time.Time { return at }
	key, code := newPickupKey(t)
	_, id := g.ask(t, "rate", code)
	for i := 0; i < pickupPerCode; i++ {
		if st, _ := g.collect("Pickup "+key, collectPath, ""); st != 202 {
			t.Fatalf("FAIL: poll %d answered %d", i, st)
		}
	}
	if st, _ := g.collect("Pickup "+key, collectPath, ""); st != 429 {
		t.Errorf("FAIL: a poll past the per-key rate: %d", st)
	}
	// Misses spend the address's ten; a right key does not.
	g.lim.release()
	for i := 0; i < pickupPerAddress; i++ {
		other, _ := newPickupKey(t)
		g.lim.release()
		if st, _ := g.collect("Pickup "+other, collectPath, ""); st != 404 {
			t.Fatalf("FAIL: miss %d: %d", i, st)
		}
	}
	other, _ := newPickupKey(t)
	if st, _ := g.collect("Pickup "+other, collectPath, ""); st != 429 {
		t.Errorf("FAIL: a miss past the per-address rate: %d", st)
	}
	otherKey, otherCode := newPickupKey(t)
	_, oid := g.ask(t, "second", otherCode)
	g.decide(t, oid, true)
	if st, _ := g.collect("Pickup "+otherKey, collectPath, ""); st != 200 {
		t.Errorf("FAIL: a right key from an address whose misses are spent: %d", st)
	}
	g.coll.now = func() time.Time { return at.Add(2 * time.Minute) }
	g.decide(t, id, true)
	if st, _ := g.collect("Pickup "+key, collectPath, ""); st != 200 {
		t.Errorf("FAIL: after the window: %d", st)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// countingSignOffs counts the takes, the only write a collect makes.
type countingSignOffs struct {
	testSignOffs
	takes *int
}

func (c countingSignOffs) TakePickupSecret(code string, now time.Time) (PickupTake, error) {
	*c.takes++
	return c.testSignOffs.TakePickupSecret(code, now)
}

// Pending and every closed state are answered from a read: the take,
// which opens a write transaction, is made only for an approved request
// that holds a secret.
func TestAPickupOnlyTakesWhenThereIsASecretToTake(t *testing.T) {
	g := newPickupRig(t)
	takes := 0
	d := g.deps
	d.SignOffs = countingSignOffs{testSignOffs{g.db}, &takes}
	g.coll = NewPickupCollector(d, g.lim, nil)
	pendKey, pendCode := newPickupKey(t)
	g.ask(t, "pending", pendCode)
	denyKey, denyCode := newPickupKey(t)
	_, denied := g.ask(t, "denied", denyCode)
	g.decide(t, denied, false)
	if st, _ := g.collect("Pickup "+pendKey, collectPath, ""); st != 202 {
		t.Errorf("FAIL: pending: %d", st)
	}
	if st, _ := g.collect("Pickup "+denyKey, collectPath, ""); st != 410 {
		t.Errorf("FAIL: denied: %d", st)
	}
	if takes != 0 {
		t.Errorf("FAIL: %d takes for requests with nothing to take", takes)
	}
	key, code := newPickupKey(t)
	_, id := g.ask(t, "ready", code)
	g.decide(t, id, true)
	g.collect("Pickup "+key, collectPath, "")
	g.collect("Pickup "+key, collectPath, "")
	if takes != 1 {
		t.Errorf("FAIL: %d takes for one secret collected twice", takes)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// A sealed value the forge cannot open is not consumed: the collector
// is told of a fault, the row keeps its secret and its references, and
// the lapse revokes it.
func TestAPickupDoesNotTakeWhatItCannotUnseal(t *testing.T) {
	g := newPickupRig(t)
	key, code := newPickupKey(t)
	_, id := g.ask(t, "broken", code)
	g.decide(t, id, true)
	if err := g.db.FinishSignOff(id, `{}`, "sealed:AAAA"); err != nil {
		t.Fatal(err)
	}
	if st, _ := g.collect("Pickup "+key, collectPath, ""); st != 500 {
		t.Errorf("FAIL: an unopenable value answered %d", st)
	}
	row, _, _ := g.db.SignOffByID(id)
	if row.Secret == "" || row.Collected != "" {
		t.Errorf("FAIL: the value was consumed")
	}
	if n, err := g.deps.LapseSignOffSecrets(time.Now().Add(25 * time.Hour)); err != nil || n != 1 || len(g.eng.revoked) != 1 {
		t.Errorf("FAIL: the lapse did not revoke it: %d %v %v", n, err, g.eng.revoked)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// The code is checked where it enters and fixed at the first ask: the
// same code again is the same request; another code, or one where there
// was none, or none where there was one, is refused and the request
// stands as it was; a code in use is refused in the one sentence.
func TestAPickupCodeIsCheckedAndFixedAtTheAsk(t *testing.T) {
	g := newPickupRig(t)
	if st, _ := g.ask(t, "bad", "not-a-code"); st != 400 {
		t.Errorf("FAIL: a malformed code was admitted: %d", st)
	}
	_, code := newPickupKey(t)
	_, other := newPickupKey(t)
	st, id := g.ask(t, "same", code)
	if st != 202 {
		t.Fatalf("FAIL: %d", st)
	}
	if st, again := g.ask(t, "same", code); st != 202 || again != id {
		t.Errorf("FAIL: asking again with the same code: %d %s", st, again)
	}
	if st, _ := g.ask(t, "same", other); st != 400 {
		t.Errorf("FAIL: asking again with another code: %d", st)
	}
	if st, _ := g.ask(t, "same", ""); st != 400 {
		t.Errorf("FAIL: asking again with no code where one is bound: %d", st)
	}
	if row, _, _ := g.db.SignOffByID(id); row.Pickup != code {
		t.Errorf("FAIL: the code changed")
	}
	// Unbound, then asked again with a code: refused, and the secret
	// stays the asker's own.
	if st, plain := g.ask(t, "plain", ""); st != 202 || plain == "" {
		t.Fatalf("FAIL: %d", st)
	}
	if st, _ := g.ask(t, "plain", other); st != 400 {
		t.Errorf("FAIL: an unbound request re-asked with a code: %d", st)
	}
	if st, _ := g.ask(t, "second", code); st != 400 {
		t.Errorf("FAIL: one code bound to two requests: %d", st)
	}
	// The plan op takes it as a field.
	if _, err := g.r.Invoke(g.ctx, planOp, planIn{Title: "t", Pickup: "short", Steps: []planStepIn{{Op: "ci.worker.token.new", Input: json.RawMessage(`{"repo":"test","label":"p"}`)}}}); err == nil {
		t.Errorf("FAIL: a plan with a malformed code was admitted")
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// A pickup code without the ask header is refused before the call runs.
func TestAPickupCodeWithoutAskingIsRefusedBeforeTheCallRuns(t *testing.T) {
	g := newPickupRig(t)
	_, code := newPickupKey(t)
	req := httptest.NewRequest("POST", "/api/v1/r/test/ci/worker-tokens", strings.NewReader(`{"label":"x"}`)).WithContext(g.ctx)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Quarry-Pickup", code)
	w := httptest.NewRecorder()
	g.h.ServeHTTP(w, req)
	if w.Code != 400 || g.eng.mints != 0 {
		t.Errorf("FAIL: %d, %d tokens minted", w.Code, g.eng.mints)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// runAs sends a worker-token call as account who with the ask and pickup
// headers, and returns the recorder.
func (g pickupRig) runAs(who, label, code string) *httptest.ResponseRecorder {
	ctx := ops.WithToken(ops.WithUser(context.Background(), who), ops.TokenAuth{ID: "T", Caps: func(string) ops.Caps { return oltp.CapSet("a") }})
	req := httptest.NewRequest("POST", "/api/v1/r/test/ci/worker-tokens", strings.NewReader(`{"label":"`+label+`"}`)).WithContext(ctx)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Quarry-Ask", "a runner")
	req.Header.Set("Quarry-Pickup", code)
	w := httptest.NewRecorder()
	g.h.ServeHTTP(w, req)
	return w
}

// A call its caller may make outright, sent with a pickup code, parks
// its credential: 202 and no secret anywhere in the answer, the key
// collects the value once, signoff.get never has it, and uncollected it
// lapses and the credential is revoked.
func TestAPickupParksTheSecretOfACallThatRunsOutright(t *testing.T) {
	var logs bytes.Buffer
	log.SetOutput(&logs)
	defer log.SetOutput(log.Writer())
	g := newPickupRig(t)
	key, code := newPickupKey(t)
	w := g.runAs("jva", "parked", code)
	if w.Code != 202 || g.eng.mints != 1 || w.Header().Get("Quarry-Pickup") != "parked" || strings.Contains(w.Body.String(), "s3cret-bearer-value") {
		t.Fatalf("FAIL: %d, %d minted, header %q, body %s", w.Code, g.eng.mints, w.Header().Get("Quarry-Pickup"), w.Body)
	}
	var asked struct {
		SignOff SignOffRequest `json:"signoff"`
	}
	if err := json.Unmarshal(w.Body.Bytes(), &asked); err != nil || asked.SignOff.ID == "" || asked.SignOff.State != oltp.SignOffRan || asked.SignOff.Pickup != code {
		t.Fatalf("FAIL: the parked request: %v %+v", err, asked.SignOff)
	}
	row, _, _ := g.db.SignOffByID(asked.SignOff.ID)
	if !strings.HasPrefix(row.Secret, sealedPrefix) || strings.Contains(row.Secret, "s3cret-bearer-value") {
		t.Errorf("FAIL: the parked secret is not sealed")
	}
	gotGet, err := g.r.Invoke(asUser("jva"), "signoff.get", signOffGetIn{ID: asked.SignOff.ID})
	if err != nil || len(gotGet.(signOffGetOut).Secret) != 0 {
		t.Errorf("FAIL: signoff.get gave the parked secret: %v", err)
	}
	st, body := g.collect("Pickup "+key, collectPath, "")
	var got200 map[string]any
	_ = json.Unmarshal([]byte(body), &got200)
	if st != 200 || !strings.Contains(body, "s3cret-bearer-value") || got200["parked"] != true || got200["answerable"] != "jva" || got200["owner"] != nil {
		t.Errorf("FAIL: collecting the parked value: %d %s", st, body)
	}
	if list, err := g.r.Invoke(asUser("jva"), "signoff.list", signOffListIn{}); err != nil {
		t.Error(err)
	} else {
		waiting, ran := 0, 0
		for _, q := range list.(signOffListOut).Requests {
			if q.State == "pending" {
				waiting++
			}
			if q.State == oltp.SignOffRan {
				ran++
			}
		}
		if waiting != 0 || ran != 1 {
			t.Errorf("FAIL: the owner's list shows %d waiting and %d ran", waiting, ran)
		}
	}
	if st, _ := g.collect("Pickup "+key, collectPath, ""); st != 410 {
		t.Errorf("FAIL: collecting twice: %d", st)
	}
	// Uncollected: lapses and is revoked.
	_, code2 := newPickupKey(t)
	if w := g.runAs("jva", "lapsing", code2); w.Code != 202 {
		t.Fatalf("FAIL: %d %s", w.Code, w.Body)
	}
	if n, err := g.deps.LapseSignOffSecrets(time.Now().Add(25 * time.Hour)); err != nil || n != 1 || len(g.eng.revoked) != 1 || g.eng.revoked[0] != "new-2" {
		t.Errorf("FAIL: the lapse: %d %v revoked %v", n, err, g.eng.revoked)
	}
	if strings.Contains(logs.String(), "s3cret-bearer-value") {
		t.Errorf("FAIL: the value is in the log")
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// A code another agent's request holds is refused before the call runs;
// the caller's own pending ask with it is answered as that ask, never
// run; and a call that runs but cannot be parked (here, no secret key to
// seal with) has its credential revoked at once, the caller told it was
// undone, without the secret.
func TestAPickupParkingFailureRevokesAndARefusedCodeNeverRuns(t *testing.T) {
	g := newPickupRig(t)
	_, taken := newPickupKey(t)
	if st, _ := g.ask(t, "holder", taken); st != 202 {
		t.Fatalf("FAIL: %d", st)
	}
	if w := g.runAs("jva", "refused", taken); w.Code != 400 || g.eng.mints != 0 {
		t.Errorf("FAIL: a held code: %d, %d minted before it was refused", w.Code, g.eng.mints)
	}
	_, mine := newPickupKey(t)
	if _, err := g.db.RequestSignOff(oltp.SignOff{Agent: "jva", Owner: "jva", Op: "x", Input: "{}", Summary: "x", Pickup: mine}); err != nil {
		t.Fatal(err)
	}
	if w := g.runAs("jva", "own", mine); w.Code != 400 || g.eng.mints != 0 {
		t.Errorf("FAIL: the caller's own pending code: %d, %d minted", w.Code, g.eng.mints)
	}
	// No secret key: sealing fails after the mint.
	b := newPickupRigWith(t, func(d *Deps) { d.SecretBox = cisecret.Box{} })
	_, code := newPickupKey(t)
	w := b.runAs("jva", "undone", code)
	if w.Code != 503 || b.eng.mints != 1 || len(b.eng.revoked) != 1 || strings.Contains(w.Body.String(), "s3cret-bearer-value") || !strings.Contains(w.Body.String(), "revoked") {
		t.Errorf("FAIL: parking failure: %d, %d minted, revoked %v, body %s", w.Code, b.eng.mints, b.eng.revoked, w.Body)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// Two callers presenting one free code at once: exactly one parks, and
// every credential minted for the other is revoked or never minted, so
// none is left live that nobody may collect.
func TestAPickupTwoCallersOneCodeLeaveExactlyOneLive(t *testing.T) {
	g := newPickupRig(t)
	_, code := newPickupKey(t)
	const callers = 8
	codes := make([]int, callers)
	var wg sync.WaitGroup
	for i := 0; i < callers; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			codes[i] = g.runAs("jva", "c"+string(rune('a'+i)), code).Code
		}()
	}
	wg.Wait()
	parked := 0
	for _, c := range codes {
		if c == 202 {
			parked++
		} else if c != 400 {
			t.Errorf("FAIL: a caller was answered %d", c)
		}
	}
	g.eng.mu.Lock()
	live := g.eng.mints - len(g.eng.revoked)
	g.eng.mu.Unlock()
	if parked != 1 || live != 1 {
		t.Errorf("FAIL: %d parked, %d credentials live", parked, live)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// Only the ops whose credential a lapse can revoke are parkable, and
// that is read from the one table, not kept by hand: of the ops that answer a
// once-shown secret, the lapseOps names are parkable and the rest are
// refused.
func TestAPickupParkableOpsAreTheOnesALapseCanRevoke(t *testing.T) {
	g := newPickupRig(t)
	var once, parkableOps []string
	for _, d := range g.r.All() {
		if d.HasOnceSecret() {
			once = append(once, d.Name)
			if pickupAllowedFor(d) == nil {
				parkableOps = append(parkableOps, d.Name)
			}
		}
	}
	// Every once-shown secret is either one a lapse can revoke (in
	// lapseOps) or on this named list of those it cannot. A new op that
	// answers a secret fails here until it is placed in one of the two.
	cannotRevoke := map[string]bool{"me.sync.token": true, "account.invite": true, "account.agent": true}
	for _, n := range once {
		if lapseOps[n] == nil && !cannotRevoke[n] {
			t.Errorf("FAIL: %s answers a once-shown secret but is neither in lapseOps nor named as one a lapse cannot revoke", n)
		}
	}
	for n := range cannotRevoke {
		if lapseOps[n] != nil {
			t.Errorf("FAIL: %s is named as one a lapse cannot revoke but lapseOps revokes it", n)
		}
	}
	if len(parkableOps) != len(lapseOps) {
		t.Errorf("FAIL: parkable %v, lapse table has %d", parkableOps, len(lapseOps))
	}
	for _, n := range parkableOps {
		if lapseOps[n] == nil {
			t.Errorf("FAIL: %s is parkable but nothing can revoke it", n)
		}
	}
	for _, n := range []string{"me.sync.token", "account.invite"} {
		if d, ok := g.r.Lookup(n); !ok || pickupAllowedFor(d) == nil {
			t.Errorf("FAIL: %s is not refused", n)
		}
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// A flood of random keys from one address leaves the limiter's memory
// bounded and charges nothing to a key it did not find; a right key from
// another address is served.
func TestAPickupAFloodOfKeysLeavesBoundedState(t *testing.T) {
	g := newPickupRig(t)
	key, code := newPickupKey(t)
	_, id := g.ask(t, "flood", code)
	g.decide(t, id, true)
	for i := 0; i < 20000; i++ {
		bad, _ := newPickupKey(t)
		g.collect("Pickup "+bad, collectPath, "")
	}
	if n := g.coll.rates.size(); n > 2 {
		t.Errorf("FAIL: %d rate entries after a flood of keys from one address, want the address's alone", n)
	}
	// The map is bounded even for many addresses.
	at := time.Now()
	for i := 0; i < 20000; i++ {
		g.coll.rates.allow("a:"+newPickupAddr(i), pickupPerAddress, at)
	}
	if n := g.coll.rates.size(); n > pickupRatesCap {
		t.Errorf("FAIL: %d rate entries, cap %d", n, pickupRatesCap)
	}
	req := httptest.NewRequest("POST", collectPath, nil)
	req.Header.Set("Authorization", "Pickup "+key)
	req.RemoteAddr = "198.51.100.9:1"
	w := httptest.NewRecorder()
	g.coll.ServeHTTP(w, req)
	if w.Code != 200 {
		t.Errorf("FAIL: a right key from another address: %d", w.Code)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

func newPickupAddr(i int) string {
	return "10.0." + string(rune('a'+i%26)) + "." + string(rune('a'+(i/26)%26)) + string(rune('a'+(i/676)%26))
}

// A pickup code on a call whose answer holds no credential is refused
// before the call runs.
func TestAPickupCodeOnACallWithNothingToCollectIsRefusedBeforeItRuns(t *testing.T) {
	g := newPickupRig(t)
	_, code := newPickupKey(t)
	ctx := ops.WithToken(ops.WithUser(context.Background(), "jva"), ops.TokenAuth{ID: "T", Caps: func(string) ops.Caps { return oltp.CapSet("a") }})
	req := httptest.NewRequest("POST", "/api/v1/agents", strings.NewReader(`{"name":"zz-bot"}`)).WithContext(ctx)
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Quarry-Ask", "x")
	req.Header.Set("Quarry-Pickup", code)
	w := httptest.NewRecorder()
	g.h.ServeHTTP(w, req)
	if w.Code != 400 {
		t.Errorf("FAIL: %d %s", w.Code, w.Body)
	}
	if _, ok := g.deps.accountNamed("zz-bot"); ok {
		t.Errorf("FAIL: the call ran")
	}
	if !t.Failed() {
		t.Log("ok")
	}
}