test: share a scoped token builder and tidy the branch tests
Adds scopedToken in place of name2, renames the e2e anyRepo token, and drops the SchemaVersion pin that the upgrade subtest already covers.
- commit
- 8d436fd961e95d385dd0be6e4a7080360c763cd1
- author
- brice · · 2026-10-12 16:14 UTC
- parent
- 160bcbb
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +13 -20
M internal/adapters/kvstore/store_test.go +0 -1
| @@ -197,7 +197,6 @@ func TestSchema(t *testing.T) { | |||
| 197 | 197 | require.NoError(t, err) | |
| 198 | 198 | require.NoError(t, s.Close(ctx)) | |
| 199 | 199 | assert.Equal(t, uint32(kvstore.SchemaVersion), readSchema(t, dir)) | |
| 200 | - | assert.Equal(t, uint32(2), uint32(kvstore.SchemaVersion), "branch prefixes need schema 2") | |
| 201 | 200 | }) | |
| 202 | 201 | ||
| 203 | 202 | t.Run("current is accepted and kept", func(t *testing.T) { | |
| @@ -197,7 +197,6 @@ func TestSchema(t *testing.T) { | |||||
| 197 | require.NoError(t, err) | 197 | require.NoError(t, err) | ||
| 198 | require.NoError(t, s.Close(ctx)) | 198 | require.NoError(t, s.Close(ctx)) | ||
| 199 | assert.Equal(t, uint32(kvstore.SchemaVersion), readSchema(t, dir)) | 199 | assert.Equal(t, uint32(kvstore.SchemaVersion), readSchema(t, dir)) | ||
| 200 | - | assert.Equal(t, uint32(2), uint32(kvstore.SchemaVersion), "branch prefixes need schema 2") | |||
| 201 | }) | 200 | }) | ||
| 202 | 201 | ||||
| 203 | t.Run("current is accepted and kept", func(t *testing.T) { | 202 | t.Run("current is accepted and kept", func(t *testing.T) { | ||
M internal/app/e2e_branches_test.go +4 -4
| @@ -105,12 +105,12 @@ func TestAC5BranchLimitedToken(t *testing.T) { | |||
| 105 | 105 | out, err = h.git(wt, "push", "-q", h.urlAuth(secret, "/brand-new.git"), "agent/claude/x") | |
| 106 | 106 | require.Error(t, err, out) | |
| 107 | 107 | assert.NoDirExists(t, h.repoDir("brand-new")) | |
| 108 | - | unlimited, _ := h.branchToken(scopes(domain.ScopeRepoWrite), []string{"agent/claude/"}) // not limited to a repository | |
| 109 | - | out, err = h.git(wt, "push", "-q", h.urlAuth(unlimited, "/brand-new.git"), "agent/claude/x") | |
| 108 | + | anyRepo, _ := h.branchToken(scopes(domain.ScopeRepoWrite), []string{"agent/claude/"}) // not limited to a repository | |
| 109 | + | out, err = h.git(wt, "push", "-q", h.urlAuth(anyRepo, "/brand-new.git"), "agent/claude/x") | |
| 110 | 110 | require.Error(t, err, out) | |
| 111 | 111 | assert.NoDirExists(t, h.repoDir("brand-new")) | |
| 112 | - | assert.Equal(t, 404, h.statusAuth("GET", "/brand-new.git/info/refs?service=git-receive-pack", unlimited)) | |
| 113 | - | _, err = h.api(unlimited).repo.CreateRepo(h.ctx, connect.NewRequest(&pb.CreateRepoRequest{Name: "via-api"})) | |
| 112 | + | assert.Equal(t, 404, h.statusAuth("GET", "/brand-new.git/info/refs?service=git-receive-pack", anyRepo)) | |
| 113 | + | _, err = h.api(anyRepo).repo.CreateRepo(h.ctx, connect.NewRequest(&pb.CreateRepoRequest{Name: "via-api"})) | |
| 114 | 114 | assert.Equal(t, "permission_denied", codeName(err)) | |
| 115 | 115 | assert.NoDirExists(t, h.repoDir("via-api")) | |
| 116 | 116 | // The same token without prefixes does both. | |
| @@ -105,12 +105,12 @@ func TestAC5BranchLimitedToken(t *testing.T) { | |||||
| 105 | out, err = h.git(wt, "push", "-q", h.urlAuth(secret, "/brand-new.git"), "agent/claude/x") | 105 | out, err = h.git(wt, "push", "-q", h.urlAuth(secret, "/brand-new.git"), "agent/claude/x") | ||
| 106 | require.Error(t, err, out) | 106 | require.Error(t, err, out) | ||
| 107 | assert.NoDirExists(t, h.repoDir("brand-new")) | 107 | assert.NoDirExists(t, h.repoDir("brand-new")) | ||
| 108 | - | unlimited, _ := h.branchToken(scopes(domain.ScopeRepoWrite), []string{"agent/claude/"}) // not limited to a repository | 108 | + | anyRepo, _ := h.branchToken(scopes(domain.ScopeRepoWrite), []string{"agent/claude/"}) // not limited to a repository |
| 109 | - | out, err = h.git(wt, "push", "-q", h.urlAuth(unlimited, "/brand-new.git"), "agent/claude/x") | 109 | + | out, err = h.git(wt, "push", "-q", h.urlAuth(anyRepo, "/brand-new.git"), "agent/claude/x") |
| 110 | require.Error(t, err, out) | 110 | require.Error(t, err, out) | ||
| 111 | assert.NoDirExists(t, h.repoDir("brand-new")) | 111 | assert.NoDirExists(t, h.repoDir("brand-new")) | ||
| 112 | - | assert.Equal(t, 404, h.statusAuth("GET", "/brand-new.git/info/refs?service=git-receive-pack", unlimited)) | 112 | + | assert.Equal(t, 404, h.statusAuth("GET", "/brand-new.git/info/refs?service=git-receive-pack", anyRepo)) |
| 113 | - | _, err = h.api(unlimited).repo.CreateRepo(h.ctx, connect.NewRequest(&pb.CreateRepoRequest{Name: "via-api"})) | 113 | + | _, err = h.api(anyRepo).repo.CreateRepo(h.ctx, connect.NewRequest(&pb.CreateRepoRequest{Name: "via-api"})) |
| 114 | assert.Equal(t, "permission_denied", codeName(err)) | 114 | assert.Equal(t, "permission_denied", codeName(err)) | ||
| 115 | assert.NoDirExists(t, h.repoDir("via-api")) | 115 | assert.NoDirExists(t, h.repoDir("via-api")) | ||
| 116 | // The same token without prefixes does both. | 116 | // The same token without prefixes does both. | ||
M internal/usecase/repos_test.go +9 -15
| @@ -191,8 +191,10 @@ func TestCreate(t *testing.T) { | |||
| 191 | 191 | }) | |
| 192 | 192 | } | |
| 193 | 193 | ||
| 194 | - | func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal { | |
| 195 | - | tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}} | |
| 194 | + | // scopedToken is the principal of a token with one scope, limited to the | |
| 195 | + | // repositories and to the branch prefixes given (none means no limit). | |
| 196 | + | func scopedToken(s domain.Scope, prefixes []string, repos ...string) domain.Principal { | |
| 197 | + | tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}, BranchPrefixes: prefixes} | |
| 196 | 198 | for _, r := range repos { | |
| 197 | 199 | n, err := domain.ParseRepoName(r) | |
| 198 | 200 | if err != nil { | |
| @@ -203,22 +205,14 @@ func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal { | |||
| 203 | 205 | return domain.TokenPrincipal(tok) | |
| 204 | 206 | } | |
| 205 | 207 | ||
| 208 | + | func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal { | |
| 209 | + | return scopedToken(s, nil, repos...) | |
| 210 | + | } | |
| 211 | + | ||
| 206 | 212 | // branchLimited is a token with one scope, optionally limited to repositories, | |
| 207 | 213 | // and limited to the branches under "agent/". | |
| 208 | 214 | func branchLimited(s domain.Scope, repos ...string) domain.Principal { | |
| 209 | - | tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}, BranchPrefixes: []string{"agent/"}} | |
| 210 | - | for _, r := range repos { | |
| 211 | - | tok.Repos = append(tok.Repos, name2(r)) | |
| 212 | - | } | |
| 213 | - | return domain.TokenPrincipal(tok) | |
| 214 | - | } | |
| 215 | - | ||
| 216 | - | func name2(s string) domain.RepoName { | |
| 217 | - | n, err := domain.ParseRepoName(s) | |
| 218 | - | if err != nil { | |
| 219 | - | panic(err) | |
| 220 | - | } | |
| 221 | - | return n | |
| 215 | + | return scopedToken(s, []string{"agent/"}, repos...) | |
| 222 | 216 | } | |
| 223 | 217 | ||
| 224 | 218 | func TestGetAndListAccess(t *testing.T) { | |
| @@ -191,8 +191,10 @@ func TestCreate(t *testing.T) { | |||||
| 191 | }) | 191 | }) | ||
| 192 | } | 192 | } | ||
| 193 | 193 | ||||
| 194 | - | func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal { | 194 | + | // scopedToken is the principal of a token with one scope, limited to the |
| 195 | - | tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}} | 195 | + | // repositories and to the branch prefixes given (none means no limit). |
| 196 | + | func scopedToken(s domain.Scope, prefixes []string, repos ...string) domain.Principal { | |||
| 197 | + | tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}, BranchPrefixes: prefixes} | |||
| 196 | for _, r := range repos { | 198 | for _, r := range repos { | ||
| 197 | n, err := domain.ParseRepoName(r) | 199 | n, err := domain.ParseRepoName(r) | ||
| 198 | if err != nil { | 200 | if err != nil { | ||
| @@ -203,22 +205,14 @@ func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal { | |||||
| 203 | return domain.TokenPrincipal(tok) | 205 | return domain.TokenPrincipal(tok) | ||
| 204 | } | 206 | } | ||
| 205 | 207 | ||||
| 208 | + | func tokenPrincipal(s domain.Scope, repos ...string) domain.Principal { | |||
| 209 | + | return scopedToken(s, nil, repos...) | |||
| 210 | + | } | |||
| 211 | + | ||||
| 206 | // branchLimited is a token with one scope, optionally limited to repositories, | 212 | // branchLimited is a token with one scope, optionally limited to repositories, | ||
| 207 | // and limited to the branches under "agent/". | 213 | // and limited to the branches under "agent/". | ||
| 208 | func branchLimited(s domain.Scope, repos ...string) domain.Principal { | 214 | func branchLimited(s domain.Scope, repos ...string) domain.Principal { | ||
| 209 | - | tok := domain.Token{ID: "t", Scopes: []domain.Scope{s}, BranchPrefixes: []string{"agent/"}} | 215 | + | return scopedToken(s, []string{"agent/"}, repos...) |
| 210 | - | for _, r := range repos { | |||
| 211 | - | tok.Repos = append(tok.Repos, name2(r)) | |||
| 212 | - | } | |||
| 213 | - | return domain.TokenPrincipal(tok) | |||
| 214 | - | } | |||
| 215 | - | ||||
| 216 | - | func name2(s string) domain.RepoName { | |||
| 217 | - | n, err := domain.ParseRepoName(s) | |||
| 218 | - | if err != nil { | |||
| 219 | - | panic(err) | |||
| 220 | - | } | |||
| 221 | - | return n | |||
| 222 | } | 216 | } | ||
| 223 | 217 | ||||
| 224 | func TestGetAndListAccess(t *testing.T) { | 218 | func TestGetAndListAccess(t *testing.T) { | ||