Files
kandev/apps/backend/internal/office/shared/permissions_test.go
T
2026-05-16 20:07:57 +01:00

177 lines
5.7 KiB
Go

package shared_test
import (
"encoding/json"
"testing"
"github.com/kandev/kandev/internal/office/shared"
)
func TestResolvePermissions_Defaults(t *testing.T) {
perms := shared.ResolvePermissions(shared.AgentRoleCEO, "")
if !shared.HasPermission(perms, shared.PermCanCreateAgents) {
t.Error("CEO should have can_create_agents by default")
}
if !shared.HasPermission(perms, shared.PermCanApprove) {
t.Error("CEO should have can_approve by default")
}
workerPerms := shared.ResolvePermissions(shared.AgentRoleWorker, "")
if shared.HasPermission(workerPerms, shared.PermCanCreateAgents) {
t.Error("Worker should not have can_create_agents by default")
}
if shared.HasPermission(workerPerms, shared.PermCanApprove) {
t.Error("Worker should not have can_approve by default")
}
// Workers can assign tasks — this is required for execution-policy review handoffs.
if !shared.HasPermission(workerPerms, shared.PermCanAssignTasks) {
t.Error("Worker should have can_assign_tasks by default")
}
specialistPerms := shared.ResolvePermissions(shared.AgentRoleSpecialist, "")
if shared.HasPermission(specialistPerms, shared.PermCanAssignTasks) {
t.Error("Specialist should not have can_assign_tasks by default")
}
}
func TestResolvePermissions_Override(t *testing.T) {
overrides := `{"can_create_agents": true, "max_subtask_depth": 5}`
perms := shared.ResolvePermissions(shared.AgentRoleWorker, overrides)
if !shared.HasPermission(perms, shared.PermCanCreateAgents) {
t.Error("override should grant can_create_agents to worker")
}
depth, ok := perms[shared.PermMaxSubtaskDepth]
if !ok {
t.Fatal("max_subtask_depth should be present")
}
depthVal, ok := depth.(float64)
if !ok {
t.Fatalf("expected float64, got %T", depth)
}
if depthVal != 5 {
t.Errorf("max_subtask_depth = %v, want 5", depthVal)
}
// Non-overridden defaults should still be present.
if !shared.HasPermission(perms, shared.PermCanCreateTasks) {
t.Error("worker should retain can_create_tasks default")
}
}
func TestResolvePermissions_InvalidJSON(t *testing.T) {
perms := shared.ResolvePermissions(shared.AgentRoleCEO, "not-json")
if !shared.HasPermission(perms, shared.PermCanCreateAgents) {
t.Error("invalid override JSON should fall back to defaults")
}
}
func TestHasPermission(t *testing.T) {
perms := map[string]interface{}{
"can_create_tasks": true,
"can_approve": false,
"max_subtask_depth": 3,
}
if !shared.HasPermission(perms, "can_create_tasks") {
t.Error("expected true for can_create_tasks")
}
if shared.HasPermission(perms, "can_approve") {
t.Error("expected false for can_approve")
}
if shared.HasPermission(perms, "nonexistent") {
t.Error("expected false for nonexistent key")
}
// Non-bool value should return false.
if shared.HasPermission(perms, "max_subtask_depth") {
t.Error("expected false for int value checked as bool")
}
}
func TestNoEscalation_CallerCanGrant(t *testing.T) {
callerPerms := map[string]interface{}{
"can_create_tasks": true,
"can_create_agents": true,
"max_subtask_depth": float64(3),
}
requested := `{"can_create_tasks": true, "max_subtask_depth": 2}`
if err := shared.ValidateNoEscalation(callerPerms, requested); err != nil {
t.Fatalf("caller should be able to grant owned perms: %v", err)
}
}
func TestNoEscalation_CallerCannotGrant(t *testing.T) {
callerPerms := map[string]interface{}{
"can_create_tasks": true,
"can_create_agents": false,
}
requested := `{"can_create_agents": true}`
err := shared.ValidateNoEscalation(callerPerms, requested)
if err == nil {
t.Fatal("caller without can_create_agents should not grant it")
}
}
func TestNoEscalation_DepthEscalation(t *testing.T) {
callerPerms := map[string]interface{}{
"max_subtask_depth": float64(2),
}
requested := `{"max_subtask_depth": 5}`
err := shared.ValidateNoEscalation(callerPerms, requested)
if err == nil {
t.Fatal("caller should not grant higher depth than it has")
}
}
func TestNoEscalation_EmptyRequest(t *testing.T) {
callerPerms := map[string]interface{}{"can_create_tasks": true}
if err := shared.ValidateNoEscalation(callerPerms, ""); err != nil {
t.Fatalf("empty request should pass: %v", err)
}
if err := shared.ValidateNoEscalation(callerPerms, "{}"); err != nil {
t.Fatalf("empty object should pass: %v", err)
}
}
func TestAllPermissionKeys(t *testing.T) {
keys := shared.AllPermissionKeys()
if len(keys) != 6 {
t.Errorf("expected 6 permission keys, got %d", len(keys))
}
}
func TestDefaultPermissionsRoundTrip(t *testing.T) {
// Ensure DefaultPermissions JSON is valid and round-trips.
raw := shared.DefaultPermissions(shared.AgentRoleCEO)
var m map[string]interface{}
if err := json.Unmarshal([]byte(raw), &m); err != nil {
t.Fatalf("DefaultPermissions produced invalid JSON: %v", err)
}
if len(m) == 0 {
t.Error("CEO should have non-empty default permissions")
}
}
func TestResolvePermissions_NewRoles(t *testing.T) {
cases := []struct {
role shared.AgentRole
wantApprove bool
wantAssign bool
wantCreateAgent bool
}{
{shared.AgentRoleSecurity, true, true, false},
{shared.AgentRoleQA, false, false, false},
{shared.AgentRoleDevOps, false, false, false},
}
for _, tc := range cases {
perms := shared.ResolvePermissions(tc.role, "")
if shared.HasPermission(perms, shared.PermCanApprove) != tc.wantApprove {
t.Errorf("role %s: can_approve = %v, want %v", tc.role, !tc.wantApprove, tc.wantApprove)
}
if shared.HasPermission(perms, shared.PermCanAssignTasks) != tc.wantAssign {
t.Errorf("role %s: can_assign_tasks = %v, want %v", tc.role, !tc.wantAssign, tc.wantAssign)
}
if shared.HasPermission(perms, shared.PermCanCreateAgents) != tc.wantCreateAgent {
t.Errorf("role %s: can_create_agents = %v, want %v", tc.role, !tc.wantCreateAgent, tc.wantCreateAgent)
}
}
}