Add record-level authorization for system accounts

Record mutations (create, update, delete) no longer require admin role.
Authorization rules:
  - admin: full access (unchanged)
  - system mcp-agent: create/delete any record
  - system account α: create/delete records named α only
  - human users: read-only (unchanged)

Zone mutations remain admin-only. Both REST and gRPC paths enforce the
same rules. Update checks authorization against both old and new names.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 15:52:43 -07:00
parent baa058d4a4
commit 871b1fb8f4
7 changed files with 120 additions and 21 deletions

View File

@@ -42,6 +42,7 @@ func createTestZone(t *testing.T, database *db.DB) *db.Zone {
}
// newChiRequest builds a request with chi URL params injected into the context.
// An admin TokenInfo is added so that handler-level authorization passes.
func newChiRequest(method, target string, body string, params map[string]string) *http.Request {
var r *http.Request
if body != "" {
@@ -51,14 +52,21 @@ func newChiRequest(method, target string, body string, params map[string]string)
}
r.Header.Set("Content-Type", "application/json")
ctx := r.Context()
if len(params) > 0 {
rctx := chi.NewRouteContext()
for k, v := range params {
rctx.URLParams.Add(k, v)
}
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
ctx = context.WithValue(ctx, chi.RouteCtxKey, rctx)
}
return r
// Inject admin TokenInfo for handler-level authorization.
ctx = context.WithValue(ctx, tokenInfoKey, &mcdslauth.TokenInfo{
Username: "testadmin",
IsAdmin: true,
})
return r.WithContext(ctx)
}
// decodeJSON decodes the response body into v.