Complete autonomous recovery controls
This commit is contained in:
@@ -29,6 +29,11 @@ type Project struct {
|
||||
Repo string `json:"repo,omitempty"`
|
||||
WorktreeRoot string `json:"worktree_root,omitempty"`
|
||||
QualityGate string `json:"quality_gate,omitempty"`
|
||||
// SafeOperations is an audited, deliberately small allow-list for work
|
||||
// inside this project's task worktree. It documents what workers may
|
||||
// perform without an operator grant; network, secrets, destructive Git,
|
||||
// and paths outside the worktree are never represented here.
|
||||
SafeOperations []string `json:"safe_operations,omitempty"`
|
||||
}
|
||||
type Machine struct {
|
||||
ID string `json:"id"`
|
||||
@@ -131,6 +136,13 @@ func New(c Config) (Registry, error) {
|
||||
if len(p.MachineAffinity) == 0 {
|
||||
return Registry{}, fmt.Errorf("project %q: %w", p.ID, ErrNoAffinity)
|
||||
}
|
||||
for _, op := range p.SafeOperations {
|
||||
switch op {
|
||||
case "read", "edit", "test", "git":
|
||||
default:
|
||||
return Registry{}, fmt.Errorf("project %q: unsafe operation %q is not policy-configurable", p.ID, op)
|
||||
}
|
||||
}
|
||||
r.projects[p.ID] = p
|
||||
}
|
||||
for _, m := range c.Machines {
|
||||
|
||||
@@ -34,3 +34,13 @@ func TestNewRejectsBrokenReferences(t *testing.T) {
|
||||
t.Fatalf("err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectSafeOperationsAreNarrowAndAudited(t *testing.T) {
|
||||
_, err := New(Config{Projects: []Project{{ID: "p", MachineAffinity: []string{"m"}, SafeOperations: []string{"read", "network"}}}, Machines: []Machine{{ID: "m", Address: "m:1"}}})
|
||||
if err == nil {
|
||||
t.Fatal("network operation was accepted into no-grant policy")
|
||||
}
|
||||
if _, err := New(Config{Projects: []Project{{ID: "p", MachineAffinity: []string{"m"}, SafeOperations: []string{"read", "edit", "test", "git"}}}, Machines: []Machine{{ID: "m", Address: "m:1"}}}); err != nil {
|
||||
t.Fatalf("safe policy rejected: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user