test: sign in to an account this process did not create
Every sign-in test in this repository signed up first, in the same process, over a database that did not exist a moment earlier — including the real-engine browser walk. That covers the ceremony and covers nothing about durability, and they are different promises. A deployed instance restarts on every release, so the only sign-in that matters to a real person is the one on the far side of a restart they never saw. The gap surfaced the way gaps do: a sign-in failed on the canary while the whole suite was green. A suite that only ever signs into an account it just made cannot tell "the ceremony works" from "the ceremony works and the account is still there afterwards". So: sign up against a named file, build a second app over the same file — new process, same disk, same pepper, which is what a redeploy is — and sign in through it. Then fetch bootstrap with the resulting session, because a sign-in that mints a cookie over wraps that no longer open is a pass that means nothing. It passes, which is the useful part: it rules the code out. What it cannot rule out is the instance's own state, and that is where the canary's failure actually lives.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+59
−0
internal/contratest/auth_test.go+59 −0
diff --git a/internal/contratest/auth_test.go b/internal/contratest/auth_test.go| index 16ca10b..19a8c3a 100644 |
| --- a/internal/contratest/auth_test.go |
| +++ b/internal/contratest/auth_test.go |
| @@ -10,6 +10,7 @@ import ( |
| "encoding/json" |
| "net/http" |
| "net/http/httptest" |
| + "path/filepath" |
| "strings" |
| "testing" |
| @@ -517,3 +518,61 @@ func TestStoredWrapsStillOpen(t *testing.T) { |
| } |
| } |
| } |
| + |
| +// TestSignInSurvivesARestart signs in to an account the running process did |
| +// not create. |
| +// |
| +// EVERY OTHER SIGN-IN TEST IN THIS REPOSITORY SIGNS UP FIRST, in the same |
| +// process, over a database that did not exist a moment ago. That covers the |
| +// ceremony and covers nothing about durability: a deployed instance restarts |
| +// on every release, and the only sign-in that matters to a real person is the |
| +// one on the far side of a restart they never saw. |
| +// |
| +// Written on 2026-09-05 after a sign-in failed on the canary while the whole |
| +// suite, including a real-engine browser walk of signup-then-sign-in, was |
| +// green. A test that only ever signs into an account it just made cannot tell |
| +// the difference between "the ceremony works" and "the ceremony works and the |
| +// account is still there afterwards", and those are different promises. |
| +// |
| +// The second app is built over the same file with the same config, which is |
| +// what a redeploy is: new process, same disk, same pepper. |
| +func TestSignInSurvivesARestart(t *testing.T) { |
| + dbPath := filepath.Join(t.TempDir(), "restart.db") |
| + |
| + const email = "restart-person@example.invalid" |
| + const passphrase = "a generated test passphrase 8f3a1c" |
| + |
| + first, _, _ := newAppAt(t, dbPath) |
| + a := doSignup(t, first, email, passphrase) |
| + |
| + // The restart. Nothing is carried across but the file. |
| + second, _, _ := newAppAt(t, dbPath) |
| + |
| + rec := doSignIn(t, second, a.email, a.passphrase) |
| + if rec.Code != http.StatusOK { |
| + t.Fatalf("sign in after a restart: status %d, body %s — an account "+ |
| + "created before this process started could not sign in, which is "+ |
| + "every account on a deployed instance", |
| + rec.Code, rec.Body.String()) |
| + } |
| + if rec.Header().Get("Set-Cookie") == "" { |
| + t.Fatal("sign in after a restart minted no session cookie") |
| + } |
| + |
| + // And the wraps the first process sealed still open under the second's |
| + // view of the world, which is the part a changed pepper or a changed |
| + // database file would break. |
| + req := httptest.NewRequest(http.MethodGet, "/api/bootstrap", nil) |
| + req.Header.Set("Cookie", strings.SplitN(rec.Header().Get("Set-Cookie"), ";", 2)[0]) |
| + boot := httptest.NewRecorder() |
| + second.ServeHTTP(boot, req) |
| + if boot.Code != http.StatusOK { |
| + t.Fatalf("bootstrap after a restart: status %d, body %s", |
| + boot.Code, boot.Body.String()) |
| + } |
| + if !strings.Contains(boot.Body.String(), "wrap") && |
| + !strings.Contains(boot.Body.String(), "vault") { |
| + t.Errorf("bootstrap after a restart returned nothing to unlock with: %s", |
| + boot.Body.String()) |
| + } |
| +} |