guardrail-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/autopilot.test.d.ts +7 -0
- package/dist/__tests__/autopilot.test.d.ts.map +1 -0
- package/dist/__tests__/autopilot.test.js +156 -0
- package/dist/__tests__/tier-config.test.d.ts +9 -0
- package/dist/__tests__/tier-config.test.d.ts.map +1 -0
- package/dist/__tests__/tier-config.test.js +230 -0
- package/dist/__tests__/utils/hash-inline.test.d.ts +2 -0
- package/dist/__tests__/utils/hash-inline.test.d.ts.map +1 -0
- package/dist/__tests__/utils/hash-inline.test.js +62 -0
- package/dist/__tests__/utils/hash.test.d.ts +3 -0
- package/dist/__tests__/utils/hash.test.d.ts.map +1 -0
- package/dist/__tests__/utils/hash.test.js +95 -0
- package/dist/__tests__/utils/simple.test.d.ts +1 -0
- package/dist/__tests__/utils/simple.test.d.ts.map +1 -0
- package/dist/__tests__/utils/simple.test.js +10 -0
- package/dist/__tests__/utils/utils-simple.test.d.ts +1 -0
- package/dist/__tests__/utils/utils-simple.test.d.ts.map +1 -0
- package/dist/__tests__/utils/utils-simple.test.js +6 -0
- package/dist/__tests__/utils/utils.test.d.ts +15 -0
- package/dist/__tests__/utils/utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils/utils.test.js +172 -0
- package/dist/autopilot/autopilot-runner.d.ts +33 -0
- package/dist/autopilot/autopilot-runner.d.ts.map +1 -0
- package/dist/autopilot/autopilot-runner.js +479 -0
- package/dist/autopilot/index.d.ts +6 -0
- package/dist/autopilot/index.d.ts.map +1 -0
- package/dist/autopilot/index.js +25 -0
- package/dist/autopilot/types.d.ts +102 -0
- package/dist/autopilot/types.d.ts.map +1 -0
- package/dist/autopilot/types.js +18 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +22 -0
- package/dist/cache/redis-cache.d.ts +145 -0
- package/dist/cache/redis-cache.d.ts.map +1 -0
- package/dist/cache/redis-cache.js +459 -0
- package/dist/ci/github-actions.d.ts +77 -0
- package/dist/ci/github-actions.d.ts.map +1 -0
- package/dist/ci/github-actions.js +277 -0
- package/dist/ci/index.d.ts +12 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +27 -0
- package/dist/ci/pre-commit.d.ts +65 -0
- package/dist/ci/pre-commit.d.ts.map +1 -0
- package/dist/ci/pre-commit.js +286 -0
- package/dist/entitlements.d.ts +149 -0
- package/dist/entitlements.d.ts.map +1 -0
- package/dist/entitlements.js +464 -0
- package/dist/env.d.ts +113 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +204 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts +7 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts.map +1 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.js +250 -0
- package/dist/fix-packs/generate-fix-packs.d.ts +15 -0
- package/dist/fix-packs/generate-fix-packs.d.ts.map +1 -0
- package/dist/fix-packs/generate-fix-packs.js +505 -0
- package/dist/fix-packs/index.d.ts +8 -0
- package/dist/fix-packs/index.d.ts.map +1 -0
- package/dist/fix-packs/index.js +23 -0
- package/dist/fix-packs/types.d.ts +113 -0
- package/dist/fix-packs/types.d.ts.map +1 -0
- package/dist/fix-packs/types.js +71 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/metrics/prometheus.d.ts +99 -0
- package/dist/metrics/prometheus.d.ts.map +1 -0
- package/dist/metrics/prometheus.js +306 -0
- package/dist/quota-ledger.d.ts +119 -0
- package/dist/quota-ledger.d.ts.map +1 -0
- package/dist/quota-ledger.js +462 -0
- package/dist/rbac/__tests__/permissions.test.d.ts +8 -0
- package/dist/rbac/__tests__/permissions.test.d.ts.map +1 -0
- package/dist/rbac/__tests__/permissions.test.js +350 -0
- package/dist/rbac/index.d.ts +9 -0
- package/dist/rbac/index.d.ts.map +1 -0
- package/dist/rbac/index.js +32 -0
- package/dist/rbac/permissions.d.ts +71 -0
- package/dist/rbac/permissions.d.ts.map +1 -0
- package/dist/rbac/permissions.js +247 -0
- package/dist/rbac/types.d.ts +69 -0
- package/dist/rbac/types.d.ts.map +1 -0
- package/dist/rbac/types.js +213 -0
- package/dist/tier-config.d.ts +203 -0
- package/dist/tier-config.d.ts.map +1 -0
- package/dist/tier-config.js +675 -0
- package/dist/types.d.ts +365 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/utils.d.ts +36 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +127 -0
- package/dist/verified-autofix/__tests__/format-validator.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/format-validator.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/format-validator.test.js +285 -0
- package/dist/verified-autofix/__tests__/pipeline.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/pipeline.test.js +389 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.js +236 -0
- package/dist/verified-autofix/__tests__/workspace.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/workspace.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/workspace.test.js +314 -0
- package/dist/verified-autofix/format-validator.d.ts +101 -0
- package/dist/verified-autofix/format-validator.d.ts.map +1 -0
- package/dist/verified-autofix/format-validator.js +446 -0
- package/dist/verified-autofix/index.d.ts +14 -0
- package/dist/verified-autofix/index.d.ts.map +1 -0
- package/dist/verified-autofix/index.js +39 -0
- package/dist/verified-autofix/pipeline.d.ts +68 -0
- package/dist/verified-autofix/pipeline.d.ts.map +1 -0
- package/dist/verified-autofix/pipeline.js +330 -0
- package/dist/verified-autofix/repo-fingerprint.d.ts +56 -0
- package/dist/verified-autofix/repo-fingerprint.d.ts.map +1 -0
- package/dist/verified-autofix/repo-fingerprint.js +396 -0
- package/dist/verified-autofix/workspace.d.ts +83 -0
- package/dist/verified-autofix/workspace.d.ts.map +1 -0
- package/dist/verified-autofix/workspace.js +454 -0
- package/dist/verified-autofix.d.ts +182 -0
- package/dist/verified-autofix.d.ts.map +1 -0
- package/dist/verified-autofix.js +1021 -0
- package/dist/visualization/dependency-graph.d.ts +79 -0
- package/dist/visualization/dependency-graph.d.ts.map +1 -0
- package/dist/visualization/dependency-graph.js +399 -0
- package/dist/visualization/index.d.ts +5 -0
- package/dist/visualization/index.d.ts.map +1 -0
- package/dist/visualization/index.js +20 -0
- package/package.json +29 -0
- package/src/__tests__/autopilot.test.ts +196 -0
- package/src/__tests__/tier-config.test.ts +289 -0
- package/src/__tests__/utils/hash-inline.test.ts +76 -0
- package/src/__tests__/utils/hash.test.ts +119 -0
- package/src/__tests__/utils/simple.test.ts +10 -0
- package/src/__tests__/utils/utils-simple.test.ts +5 -0
- package/src/__tests__/utils/utils.test.ts +203 -0
- package/src/autopilot/autopilot-runner.ts +503 -0
- package/src/autopilot/index.ts +6 -0
- package/src/autopilot/types.ts +119 -0
- package/src/cache/index.ts +7 -0
- package/src/cache/redis-cache.d.ts +155 -0
- package/src/cache/redis-cache.d.ts.map +1 -0
- package/src/cache/redis-cache.ts +517 -0
- package/src/ci/github-actions.ts +335 -0
- package/src/ci/index.ts +12 -0
- package/src/ci/pre-commit.ts +338 -0
- package/src/db/usage-schema.prisma +114 -0
- package/src/entitlements.ts +570 -0
- package/src/env.d.ts +68 -0
- package/src/env.d.ts.map +1 -0
- package/src/env.ts +247 -0
- package/src/fix-packs/__tests__/generate-fix-packs.test.ts +317 -0
- package/src/fix-packs/generate-fix-packs.ts +577 -0
- package/src/fix-packs/index.ts +8 -0
- package/src/fix-packs/types.ts +206 -0
- package/src/index.d.ts +7 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +12 -0
- package/src/metrics/prometheus.d.ts +104 -0
- package/src/metrics/prometheus.d.ts.map +1 -0
- package/src/metrics/prometheus.ts +446 -0
- package/src/quota-ledger.ts +548 -0
- package/src/rbac/__tests__/permissions.test.ts +446 -0
- package/src/rbac/index.ts +46 -0
- package/src/rbac/permissions.ts +301 -0
- package/src/rbac/types.ts +298 -0
- package/src/tier-config.json +157 -0
- package/src/tier-config.ts +815 -0
- package/src/types.d.ts +365 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.ts +441 -0
- package/src/utils.d.ts +36 -0
- package/src/utils.d.ts.map +1 -0
- package/src/utils.ts +140 -0
- package/src/verified-autofix/__tests__/format-validator.test.ts +335 -0
- package/src/verified-autofix/__tests__/pipeline.test.ts +419 -0
- package/src/verified-autofix/__tests__/repo-fingerprint.test.ts +241 -0
- package/src/verified-autofix/__tests__/workspace.test.ts +373 -0
- package/src/verified-autofix/format-validator.ts +517 -0
- package/src/verified-autofix/index.ts +63 -0
- package/src/verified-autofix/pipeline.ts +403 -0
- package/src/verified-autofix/repo-fingerprint.ts +459 -0
- package/src/verified-autofix/workspace.ts +531 -0
- package/src/verified-autofix.ts +1187 -0
- package/src/visualization/dependency-graph.d.ts +85 -0
- package/src/visualization/dependency-graph.d.ts.map +1 -0
- package/src/visualization/dependency-graph.ts +495 -0
- package/src/visualization/index.ts +5 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RBAC Permission Tests
|
|
4
|
+
*
|
|
5
|
+
* Tests for role-based access control permission checking logic.
|
|
6
|
+
* Validates acceptance criteria for different roles.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
const permissions_1 = require("../permissions");
|
|
10
|
+
const types_1 = require("../types");
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// TEST HELPERS
|
|
13
|
+
// =============================================================================
|
|
14
|
+
function createContext(role, tier) {
|
|
15
|
+
return {
|
|
16
|
+
userId: 'user_123',
|
|
17
|
+
teamId: 'team_456',
|
|
18
|
+
role,
|
|
19
|
+
permissions: (0, permissions_1.getEffectivePermissions)(role),
|
|
20
|
+
tier,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// ROLE VALIDATION TESTS
|
|
25
|
+
// =============================================================================
|
|
26
|
+
describe('Role Validation', () => {
|
|
27
|
+
test('isValidRole returns true for valid roles', () => {
|
|
28
|
+
expect((0, permissions_1.isValidRole)('owner')).toBe(true);
|
|
29
|
+
expect((0, permissions_1.isValidRole)('admin')).toBe(true);
|
|
30
|
+
expect((0, permissions_1.isValidRole)('dev')).toBe(true);
|
|
31
|
+
expect((0, permissions_1.isValidRole)('viewer')).toBe(true);
|
|
32
|
+
expect((0, permissions_1.isValidRole)('compliance-auditor')).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
test('isValidRole returns false for invalid roles', () => {
|
|
35
|
+
expect((0, permissions_1.isValidRole)('superadmin')).toBe(false);
|
|
36
|
+
expect((0, permissions_1.isValidRole)('')).toBe(false);
|
|
37
|
+
expect((0, permissions_1.isValidRole)('ADMIN')).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
test('parseRole returns role for valid input', () => {
|
|
40
|
+
expect((0, permissions_1.parseRole)('owner')).toBe('owner');
|
|
41
|
+
expect((0, permissions_1.parseRole)('admin')).toBe('admin');
|
|
42
|
+
});
|
|
43
|
+
test('parseRole returns null for invalid input', () => {
|
|
44
|
+
expect((0, permissions_1.parseRole)('invalid')).toBeNull();
|
|
45
|
+
expect((0, permissions_1.parseRole)('')).toBeNull();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// PERMISSION VALIDATION TESTS
|
|
50
|
+
// =============================================================================
|
|
51
|
+
describe('Permission Validation', () => {
|
|
52
|
+
test('isValidPermission returns true for valid permissions', () => {
|
|
53
|
+
expect((0, permissions_1.isValidPermission)('manage_team')).toBe(true);
|
|
54
|
+
expect((0, permissions_1.isValidPermission)('view_audit')).toBe(true);
|
|
55
|
+
expect((0, permissions_1.isValidPermission)('run_autopilot')).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
test('isValidPermission returns false for invalid permissions', () => {
|
|
58
|
+
expect((0, permissions_1.isValidPermission)('invalid_permission')).toBe(false);
|
|
59
|
+
expect((0, permissions_1.isValidPermission)('')).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
// =============================================================================
|
|
63
|
+
// ROLE HIERARCHY TESTS
|
|
64
|
+
// =============================================================================
|
|
65
|
+
describe('Role Hierarchy', () => {
|
|
66
|
+
test('compareRoles returns correct hierarchy order', () => {
|
|
67
|
+
expect((0, permissions_1.compareRoles)('owner', 'admin')).toBeGreaterThan(0);
|
|
68
|
+
expect((0, permissions_1.compareRoles)('admin', 'dev')).toBeGreaterThan(0);
|
|
69
|
+
expect((0, permissions_1.compareRoles)('dev', 'viewer')).toBeGreaterThan(0);
|
|
70
|
+
expect((0, permissions_1.compareRoles)('viewer', 'owner')).toBeLessThan(0);
|
|
71
|
+
expect((0, permissions_1.compareRoles)('admin', 'admin')).toBe(0);
|
|
72
|
+
});
|
|
73
|
+
test('isRoleAtLeast correctly compares roles', () => {
|
|
74
|
+
expect((0, permissions_1.isRoleAtLeast)('owner', 'admin')).toBe(true);
|
|
75
|
+
expect((0, permissions_1.isRoleAtLeast)('owner', 'owner')).toBe(true);
|
|
76
|
+
expect((0, permissions_1.isRoleAtLeast)('admin', 'owner')).toBe(false);
|
|
77
|
+
expect((0, permissions_1.isRoleAtLeast)('dev', 'viewer')).toBe(true);
|
|
78
|
+
expect((0, permissions_1.isRoleAtLeast)('viewer', 'dev')).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
// =============================================================================
|
|
82
|
+
// PERMISSION CHECKING TESTS
|
|
83
|
+
// =============================================================================
|
|
84
|
+
describe('Permission Checking', () => {
|
|
85
|
+
test('roleHasPermission returns correct values', () => {
|
|
86
|
+
expect((0, permissions_1.roleHasPermission)('owner', 'manage_billing')).toBe(true);
|
|
87
|
+
expect((0, permissions_1.roleHasPermission)('admin', 'manage_billing')).toBe(false);
|
|
88
|
+
expect((0, permissions_1.roleHasPermission)('viewer', 'view_dashboard')).toBe(true);
|
|
89
|
+
expect((0, permissions_1.roleHasPermission)('viewer', 'run_autopilot')).toBe(false);
|
|
90
|
+
});
|
|
91
|
+
test('hasPermission returns allowed for valid permissions', () => {
|
|
92
|
+
const ownerContext = createContext('owner');
|
|
93
|
+
const result = (0, permissions_1.hasPermission)(ownerContext, 'manage_billing');
|
|
94
|
+
expect(result.allowed).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
test('hasPermission returns denied with reason for missing permissions', () => {
|
|
97
|
+
const viewerContext = createContext('viewer');
|
|
98
|
+
const result = (0, permissions_1.hasPermission)(viewerContext, 'manage_team');
|
|
99
|
+
expect(result.allowed).toBe(false);
|
|
100
|
+
expect(result.reason).toContain('manage_team');
|
|
101
|
+
expect(result.requiredPermissions).toContain('manage_team');
|
|
102
|
+
});
|
|
103
|
+
test('hasAllPermissions requires all permissions', () => {
|
|
104
|
+
const adminContext = createContext('admin');
|
|
105
|
+
const allPresent = (0, permissions_1.hasAllPermissions)(adminContext, ['manage_team', 'run_autopilot']);
|
|
106
|
+
expect(allPresent.allowed).toBe(true);
|
|
107
|
+
const someMissing = (0, permissions_1.hasAllPermissions)(adminContext, ['manage_team', 'manage_billing']);
|
|
108
|
+
expect(someMissing.allowed).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
test('hasAnyPermission allows with any matching permission', () => {
|
|
111
|
+
const devContext = createContext('dev');
|
|
112
|
+
const onePresent = (0, permissions_1.hasAnyPermission)(devContext, ['run_scan', 'manage_billing']);
|
|
113
|
+
expect(onePresent.allowed).toBe(true);
|
|
114
|
+
const nonePresent = (0, permissions_1.hasAnyPermission)(devContext, ['manage_billing', 'admin_settings']);
|
|
115
|
+
expect(nonePresent.allowed).toBe(false);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
// =============================================================================
|
|
119
|
+
// ACCEPTANCE CRITERIA TESTS
|
|
120
|
+
// =============================================================================
|
|
121
|
+
describe('Acceptance Criteria: Compliance Auditor', () => {
|
|
122
|
+
const auditorContext = createContext('compliance-auditor');
|
|
123
|
+
test('can view audit logs', () => {
|
|
124
|
+
const result = (0, permissions_1.hasPermission)(auditorContext, 'view_audit');
|
|
125
|
+
expect(result.allowed).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
test('can export audit logs', () => {
|
|
128
|
+
const result = (0, permissions_1.hasPermission)(auditorContext, 'export_audit');
|
|
129
|
+
expect(result.allowed).toBe(true);
|
|
130
|
+
});
|
|
131
|
+
test('cannot edit policies', () => {
|
|
132
|
+
const result = (0, permissions_1.hasPermission)(auditorContext, 'manage_policies');
|
|
133
|
+
expect(result.allowed).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
test('cannot manage team', () => {
|
|
136
|
+
const result = (0, permissions_1.hasPermission)(auditorContext, 'manage_team');
|
|
137
|
+
expect(result.allowed).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
test('cannot run autopilot', () => {
|
|
140
|
+
const result = (0, permissions_1.hasPermission)(auditorContext, 'run_autopilot');
|
|
141
|
+
expect(result.allowed).toBe(false);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
describe('Acceptance Criteria: Viewer', () => {
|
|
145
|
+
const viewerContext = createContext('viewer');
|
|
146
|
+
test('can see dashboard', () => {
|
|
147
|
+
const result = (0, permissions_1.hasPermission)(viewerContext, 'view_dashboard');
|
|
148
|
+
expect(result.allowed).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
test('can view reports', () => {
|
|
151
|
+
const result = (0, permissions_1.hasPermission)(viewerContext, 'view_reports');
|
|
152
|
+
expect(result.allowed).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
test('cannot run Reality Mode', () => {
|
|
155
|
+
const result = (0, permissions_1.hasPermission)(viewerContext, 'run_reality');
|
|
156
|
+
expect(result.allowed).toBe(false);
|
|
157
|
+
});
|
|
158
|
+
test('cannot run Autopilot', () => {
|
|
159
|
+
const result = (0, permissions_1.hasPermission)(viewerContext, 'run_autopilot');
|
|
160
|
+
expect(result.allowed).toBe(false);
|
|
161
|
+
});
|
|
162
|
+
test('cannot run scans', () => {
|
|
163
|
+
const result = (0, permissions_1.hasPermission)(viewerContext, 'run_scan');
|
|
164
|
+
expect(result.allowed).toBe(false);
|
|
165
|
+
});
|
|
166
|
+
test('cannot manage policies', () => {
|
|
167
|
+
const result = (0, permissions_1.hasPermission)(viewerContext, 'manage_policies');
|
|
168
|
+
expect(result.allowed).toBe(false);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('Acceptance Criteria: Developer', () => {
|
|
172
|
+
const devContext = createContext('dev');
|
|
173
|
+
test('can run scans', () => {
|
|
174
|
+
const result = (0, permissions_1.hasPermission)(devContext, 'run_scan');
|
|
175
|
+
expect(result.allowed).toBe(true);
|
|
176
|
+
});
|
|
177
|
+
test('can run Reality Mode', () => {
|
|
178
|
+
const result = (0, permissions_1.hasPermission)(devContext, 'run_reality');
|
|
179
|
+
expect(result.allowed).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
test('can run fixes', () => {
|
|
182
|
+
const result = (0, permissions_1.hasPermission)(devContext, 'run_fix');
|
|
183
|
+
expect(result.allowed).toBe(true);
|
|
184
|
+
});
|
|
185
|
+
test('cannot run Autopilot', () => {
|
|
186
|
+
const result = (0, permissions_1.hasPermission)(devContext, 'run_autopilot');
|
|
187
|
+
expect(result.allowed).toBe(false);
|
|
188
|
+
});
|
|
189
|
+
test('cannot manage team', () => {
|
|
190
|
+
const result = (0, permissions_1.hasPermission)(devContext, 'manage_team');
|
|
191
|
+
expect(result.allowed).toBe(false);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
describe('Acceptance Criteria: Admin', () => {
|
|
195
|
+
const adminContext = createContext('admin');
|
|
196
|
+
test('can manage team', () => {
|
|
197
|
+
const result = (0, permissions_1.hasPermission)(adminContext, 'manage_team');
|
|
198
|
+
expect(result.allowed).toBe(true);
|
|
199
|
+
});
|
|
200
|
+
test('can run Autopilot', () => {
|
|
201
|
+
const result = (0, permissions_1.hasPermission)(adminContext, 'run_autopilot');
|
|
202
|
+
expect(result.allowed).toBe(true);
|
|
203
|
+
});
|
|
204
|
+
test('can manage policies', () => {
|
|
205
|
+
const result = (0, permissions_1.hasPermission)(adminContext, 'manage_policies');
|
|
206
|
+
expect(result.allowed).toBe(true);
|
|
207
|
+
});
|
|
208
|
+
test('cannot manage billing', () => {
|
|
209
|
+
const result = (0, permissions_1.hasPermission)(adminContext, 'manage_billing');
|
|
210
|
+
expect(result.allowed).toBe(false);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
describe('Acceptance Criteria: Owner', () => {
|
|
214
|
+
const ownerContext = createContext('owner');
|
|
215
|
+
test('has all permissions', () => {
|
|
216
|
+
const permissions = [
|
|
217
|
+
'manage_team',
|
|
218
|
+
'manage_billing',
|
|
219
|
+
'run_autopilot',
|
|
220
|
+
'manage_policies',
|
|
221
|
+
'admin_settings',
|
|
222
|
+
];
|
|
223
|
+
for (const permission of permissions) {
|
|
224
|
+
const result = (0, permissions_1.hasPermission)(ownerContext, permission);
|
|
225
|
+
expect(result.allowed).toBe(true);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
// =============================================================================
|
|
230
|
+
// ROLE ASSIGNMENT TESTS
|
|
231
|
+
// =============================================================================
|
|
232
|
+
describe('Role Assignment', () => {
|
|
233
|
+
test('owner can assign any role', () => {
|
|
234
|
+
expect((0, permissions_1.canAssignRole)('owner', 'admin').allowed).toBe(true);
|
|
235
|
+
expect((0, permissions_1.canAssignRole)('owner', 'dev').allowed).toBe(true);
|
|
236
|
+
expect((0, permissions_1.canAssignRole)('owner', 'viewer').allowed).toBe(true);
|
|
237
|
+
expect((0, permissions_1.canAssignRole)('owner', 'compliance-auditor').allowed).toBe(true);
|
|
238
|
+
});
|
|
239
|
+
test('admin can assign lower roles', () => {
|
|
240
|
+
expect((0, permissions_1.canAssignRole)('admin', 'dev').allowed).toBe(true);
|
|
241
|
+
expect((0, permissions_1.canAssignRole)('admin', 'viewer').allowed).toBe(true);
|
|
242
|
+
});
|
|
243
|
+
test('admin cannot assign admin or owner', () => {
|
|
244
|
+
expect((0, permissions_1.canAssignRole)('admin', 'admin').allowed).toBe(false);
|
|
245
|
+
expect((0, permissions_1.canAssignRole)('admin', 'owner').allowed).toBe(false);
|
|
246
|
+
});
|
|
247
|
+
test('dev cannot assign roles', () => {
|
|
248
|
+
expect((0, permissions_1.canAssignRole)('dev', 'viewer').allowed).toBe(false);
|
|
249
|
+
});
|
|
250
|
+
test('viewer cannot assign roles', () => {
|
|
251
|
+
expect((0, permissions_1.canAssignRole)('viewer', 'viewer').allowed).toBe(false);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
// =============================================================================
|
|
255
|
+
// MEMBER REMOVAL TESTS
|
|
256
|
+
// =============================================================================
|
|
257
|
+
describe('Member Removal', () => {
|
|
258
|
+
test('owner can remove any non-owner member', () => {
|
|
259
|
+
expect((0, permissions_1.canRemoveMember)('owner', 'admin').allowed).toBe(true);
|
|
260
|
+
expect((0, permissions_1.canRemoveMember)('owner', 'dev').allowed).toBe(true);
|
|
261
|
+
expect((0, permissions_1.canRemoveMember)('owner', 'viewer').allowed).toBe(true);
|
|
262
|
+
});
|
|
263
|
+
test('nobody can remove owner', () => {
|
|
264
|
+
expect((0, permissions_1.canRemoveMember)('owner', 'owner').allowed).toBe(false);
|
|
265
|
+
expect((0, permissions_1.canRemoveMember)('admin', 'owner').allowed).toBe(false);
|
|
266
|
+
});
|
|
267
|
+
test('admin can remove lower roles', () => {
|
|
268
|
+
expect((0, permissions_1.canRemoveMember)('admin', 'dev').allowed).toBe(true);
|
|
269
|
+
expect((0, permissions_1.canRemoveMember)('admin', 'viewer').allowed).toBe(true);
|
|
270
|
+
});
|
|
271
|
+
test('admin cannot remove admin', () => {
|
|
272
|
+
expect((0, permissions_1.canRemoveMember)('admin', 'admin').allowed).toBe(false);
|
|
273
|
+
});
|
|
274
|
+
test('dev cannot remove members', () => {
|
|
275
|
+
expect((0, permissions_1.canRemoveMember)('dev', 'viewer').allowed).toBe(false);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
// =============================================================================
|
|
279
|
+
// PERMISSION MATRIX TESTS
|
|
280
|
+
// =============================================================================
|
|
281
|
+
describe('Permission Matrix', () => {
|
|
282
|
+
test('generatePermissionMatrix returns valid structure', () => {
|
|
283
|
+
const matrix = (0, permissions_1.generatePermissionMatrix)();
|
|
284
|
+
expect(matrix.roles).toEqual(types_1.ROLES);
|
|
285
|
+
expect(matrix.permissions.length).toBeGreaterThan(0);
|
|
286
|
+
expect(typeof matrix.matrix).toBe('object');
|
|
287
|
+
});
|
|
288
|
+
test('matrix contains all role-permission combinations', () => {
|
|
289
|
+
const matrix = (0, permissions_1.generatePermissionMatrix)();
|
|
290
|
+
for (const role of types_1.ROLES) {
|
|
291
|
+
expect(matrix.matrix[role]).toBeDefined();
|
|
292
|
+
for (const permission of matrix.permissions) {
|
|
293
|
+
expect(typeof matrix.matrix[role][permission]).toBe('boolean');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
test('matrix values match roleHasPermission', () => {
|
|
298
|
+
const matrix = (0, permissions_1.generatePermissionMatrix)();
|
|
299
|
+
for (const role of types_1.ROLES) {
|
|
300
|
+
for (const permission of matrix.permissions) {
|
|
301
|
+
const matrixValue = matrix.matrix[role][permission];
|
|
302
|
+
const functionValue = (0, permissions_1.roleHasPermission)(role, permission);
|
|
303
|
+
expect(matrixValue).toBe(functionValue);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
// =============================================================================
|
|
309
|
+
// MINIMUM ROLE TESTS
|
|
310
|
+
// =============================================================================
|
|
311
|
+
describe('Minimum Role for Permission', () => {
|
|
312
|
+
test('getMinimumRoleForPermission returns correct minimum role', () => {
|
|
313
|
+
expect((0, permissions_1.getMinimumRoleForPermission)('view_dashboard')).toBe('viewer');
|
|
314
|
+
expect((0, permissions_1.getMinimumRoleForPermission)('view_audit')).toBe('compliance-auditor');
|
|
315
|
+
expect((0, permissions_1.getMinimumRoleForPermission)('run_scan')).toBe('dev');
|
|
316
|
+
expect((0, permissions_1.getMinimumRoleForPermission)('manage_team')).toBe('admin');
|
|
317
|
+
expect((0, permissions_1.getMinimumRoleForPermission)('manage_billing')).toBe('owner');
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
// =============================================================================
|
|
321
|
+
// EFFECTIVE PERMISSIONS TESTS
|
|
322
|
+
// =============================================================================
|
|
323
|
+
describe('Effective Permissions', () => {
|
|
324
|
+
test('getEffectivePermissions returns array for each role', () => {
|
|
325
|
+
for (const role of types_1.ROLES) {
|
|
326
|
+
const permissions = (0, permissions_1.getEffectivePermissions)(role);
|
|
327
|
+
expect(Array.isArray(permissions)).toBe(true);
|
|
328
|
+
expect(permissions.length).toBeGreaterThan(0);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
test('owner has more permissions than admin', () => {
|
|
332
|
+
const ownerPerms = (0, permissions_1.getEffectivePermissions)('owner');
|
|
333
|
+
const adminPerms = (0, permissions_1.getEffectivePermissions)('admin');
|
|
334
|
+
expect(ownerPerms.length).toBeGreaterThan(adminPerms.length);
|
|
335
|
+
});
|
|
336
|
+
test('admin has more permissions than dev', () => {
|
|
337
|
+
const adminPerms = (0, permissions_1.getEffectivePermissions)('admin');
|
|
338
|
+
const devPerms = (0, permissions_1.getEffectivePermissions)('dev');
|
|
339
|
+
expect(adminPerms.length).toBeGreaterThan(devPerms.length);
|
|
340
|
+
});
|
|
341
|
+
test('viewer has fewest permissions', () => {
|
|
342
|
+
const viewerPerms = (0, permissions_1.getEffectivePermissions)('viewer');
|
|
343
|
+
for (const role of types_1.ROLES) {
|
|
344
|
+
if (role !== 'viewer') {
|
|
345
|
+
const otherPerms = (0, permissions_1.getEffectivePermissions)(role);
|
|
346
|
+
expect(viewerPerms.length).toBeLessThanOrEqual(otherPerms.length);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RBAC Module - Role-Based Access Control
|
|
3
|
+
*
|
|
4
|
+
* Exports all RBAC types, permissions, and utilities.
|
|
5
|
+
*/
|
|
6
|
+
export type { Permission, PermissionCheck, PermissionMatrix, RBACContext, Role, RoleAssignment, RoleMetadata, TeamInvitation, TeamMemberWithRole, } from './types';
|
|
7
|
+
export { PERMISSIONS, ROLE_HIERARCHY, ROLE_METADATA, ROLE_PERMISSIONS, ROLES, } from './types';
|
|
8
|
+
export { canAssignRole, canRemoveMember, checkTierAndPermission, compareRoles, generatePermissionMatrix, getEffectivePermissions, getMinimumRoleForPermission, hasAllPermissions, hasAnyPermission, hasPermission, isRoleAtLeast, isValidPermission, isValidRole, parseRole, roleHasPermission, } from './permissions';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rbac/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,YAAY,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,IAAI,EACJ,cAAc,EACd,YAAY,EACZ,cAAc,EACd,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,WAAW,EACX,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,KAAK,GACN,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,YAAY,EACZ,wBAAwB,EACxB,uBAAuB,EACvB,2BAA2B,EAC3B,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,iBAAiB,GAClB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RBAC Module - Role-Based Access Control
|
|
4
|
+
*
|
|
5
|
+
* Exports all RBAC types, permissions, and utilities.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.roleHasPermission = exports.parseRole = exports.isValidRole = exports.isValidPermission = exports.isRoleAtLeast = exports.hasPermission = exports.hasAnyPermission = exports.hasAllPermissions = exports.getMinimumRoleForPermission = exports.getEffectivePermissions = exports.generatePermissionMatrix = exports.compareRoles = exports.checkTierAndPermission = exports.canRemoveMember = exports.canAssignRole = exports.ROLES = exports.ROLE_PERMISSIONS = exports.ROLE_METADATA = exports.ROLE_HIERARCHY = exports.PERMISSIONS = void 0;
|
|
9
|
+
// Values
|
|
10
|
+
var types_1 = require("./types");
|
|
11
|
+
Object.defineProperty(exports, "PERMISSIONS", { enumerable: true, get: function () { return types_1.PERMISSIONS; } });
|
|
12
|
+
Object.defineProperty(exports, "ROLE_HIERARCHY", { enumerable: true, get: function () { return types_1.ROLE_HIERARCHY; } });
|
|
13
|
+
Object.defineProperty(exports, "ROLE_METADATA", { enumerable: true, get: function () { return types_1.ROLE_METADATA; } });
|
|
14
|
+
Object.defineProperty(exports, "ROLE_PERMISSIONS", { enumerable: true, get: function () { return types_1.ROLE_PERMISSIONS; } });
|
|
15
|
+
Object.defineProperty(exports, "ROLES", { enumerable: true, get: function () { return types_1.ROLES; } });
|
|
16
|
+
// Permission checking
|
|
17
|
+
var permissions_1 = require("./permissions");
|
|
18
|
+
Object.defineProperty(exports, "canAssignRole", { enumerable: true, get: function () { return permissions_1.canAssignRole; } });
|
|
19
|
+
Object.defineProperty(exports, "canRemoveMember", { enumerable: true, get: function () { return permissions_1.canRemoveMember; } });
|
|
20
|
+
Object.defineProperty(exports, "checkTierAndPermission", { enumerable: true, get: function () { return permissions_1.checkTierAndPermission; } });
|
|
21
|
+
Object.defineProperty(exports, "compareRoles", { enumerable: true, get: function () { return permissions_1.compareRoles; } });
|
|
22
|
+
Object.defineProperty(exports, "generatePermissionMatrix", { enumerable: true, get: function () { return permissions_1.generatePermissionMatrix; } });
|
|
23
|
+
Object.defineProperty(exports, "getEffectivePermissions", { enumerable: true, get: function () { return permissions_1.getEffectivePermissions; } });
|
|
24
|
+
Object.defineProperty(exports, "getMinimumRoleForPermission", { enumerable: true, get: function () { return permissions_1.getMinimumRoleForPermission; } });
|
|
25
|
+
Object.defineProperty(exports, "hasAllPermissions", { enumerable: true, get: function () { return permissions_1.hasAllPermissions; } });
|
|
26
|
+
Object.defineProperty(exports, "hasAnyPermission", { enumerable: true, get: function () { return permissions_1.hasAnyPermission; } });
|
|
27
|
+
Object.defineProperty(exports, "hasPermission", { enumerable: true, get: function () { return permissions_1.hasPermission; } });
|
|
28
|
+
Object.defineProperty(exports, "isRoleAtLeast", { enumerable: true, get: function () { return permissions_1.isRoleAtLeast; } });
|
|
29
|
+
Object.defineProperty(exports, "isValidPermission", { enumerable: true, get: function () { return permissions_1.isValidPermission; } });
|
|
30
|
+
Object.defineProperty(exports, "isValidRole", { enumerable: true, get: function () { return permissions_1.isValidRole; } });
|
|
31
|
+
Object.defineProperty(exports, "parseRole", { enumerable: true, get: function () { return permissions_1.parseRole; } });
|
|
32
|
+
Object.defineProperty(exports, "roleHasPermission", { enumerable: true, get: function () { return permissions_1.roleHasPermission; } });
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RBAC Permission Checker
|
|
3
|
+
*
|
|
4
|
+
* Core permission checking logic for role-based access control.
|
|
5
|
+
* Provides functions to verify user permissions against required permissions.
|
|
6
|
+
*/
|
|
7
|
+
import { Tier } from '../tier-config';
|
|
8
|
+
import { Permission, PermissionCheck, PermissionMatrix, RBACContext, Role } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Check if a role has a specific permission
|
|
11
|
+
*/
|
|
12
|
+
export declare function roleHasPermission(role: Role, permission: Permission): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Check if a user has a specific permission based on their role
|
|
15
|
+
*/
|
|
16
|
+
export declare function hasPermission(context: RBACContext, permission: Permission): PermissionCheck;
|
|
17
|
+
/**
|
|
18
|
+
* Check if a user has ALL of the specified permissions
|
|
19
|
+
*/
|
|
20
|
+
export declare function hasAllPermissions(context: RBACContext, permissions: Permission[]): PermissionCheck;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a user has ANY of the specified permissions
|
|
23
|
+
*/
|
|
24
|
+
export declare function hasAnyPermission(context: RBACContext, permissions: Permission[]): PermissionCheck;
|
|
25
|
+
/**
|
|
26
|
+
* Compare two roles and return their relative hierarchy
|
|
27
|
+
* Returns positive if role1 > role2, negative if role1 < role2, 0 if equal
|
|
28
|
+
*/
|
|
29
|
+
export declare function compareRoles(role1: Role, role2: Role): number;
|
|
30
|
+
/**
|
|
31
|
+
* Check if role1 is higher than or equal to role2 in the hierarchy
|
|
32
|
+
*/
|
|
33
|
+
export declare function isRoleAtLeast(role: Role, minimumRole: Role): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Get the minimum role required for a specific permission
|
|
36
|
+
*/
|
|
37
|
+
export declare function getMinimumRoleForPermission(permission: Permission): Role;
|
|
38
|
+
/**
|
|
39
|
+
* Get all permissions for a role (including inherited)
|
|
40
|
+
*/
|
|
41
|
+
export declare function getEffectivePermissions(role: Role): Permission[];
|
|
42
|
+
/**
|
|
43
|
+
* Check if a tier allows a specific operation with RBAC
|
|
44
|
+
*/
|
|
45
|
+
export declare function checkTierAndPermission(context: RBACContext, permission: Permission, requiredTier: Tier): PermissionCheck;
|
|
46
|
+
/**
|
|
47
|
+
* Generate a permission matrix for UI display
|
|
48
|
+
*/
|
|
49
|
+
export declare function generatePermissionMatrix(): PermissionMatrix;
|
|
50
|
+
/**
|
|
51
|
+
* Check if a user can assign a specific role to another user
|
|
52
|
+
* Users can only assign roles lower than their own
|
|
53
|
+
*/
|
|
54
|
+
export declare function canAssignRole(assignerRole: Role, targetRole: Role): PermissionCheck;
|
|
55
|
+
/**
|
|
56
|
+
* Check if a user can remove another user from the team
|
|
57
|
+
*/
|
|
58
|
+
export declare function canRemoveMember(removerRole: Role, targetRole: Role): PermissionCheck;
|
|
59
|
+
/**
|
|
60
|
+
* Validate if a string is a valid role
|
|
61
|
+
*/
|
|
62
|
+
export declare function isValidRole(role: string): role is Role;
|
|
63
|
+
/**
|
|
64
|
+
* Validate if a string is a valid permission
|
|
65
|
+
*/
|
|
66
|
+
export declare function isValidPermission(permission: string): permission is Permission;
|
|
67
|
+
/**
|
|
68
|
+
* Get role from string with validation
|
|
69
|
+
*/
|
|
70
|
+
export declare function parseRole(role: string): Role | null;
|
|
71
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/rbac/permissions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAc,MAAM,gBAAgB,CAAC;AAClD,OAAO,EACL,UAAU,EAEV,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,IAAI,EAIL,MAAM,SAAS,CAAC;AAMjB;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAG7E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,UAAU,GACrB,eAAe,CAqBjB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,UAAU,EAAE,GACxB,eAAe,CAkBjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,UAAU,EAAE,GACxB,eAAe,CAYjB;AAMD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,OAAO,CAEpE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAYxE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,EAAE,CAEhE;AAMD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,IAAI,GACjB,eAAe,CAqBjB;AAMD;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,gBAAgB,CAe3D;AAMD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,IAAI,EAClB,UAAU,EAAE,IAAI,GACf,eAAe,CAsBjB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,IAAI,GACf,eAAe,CA0BjB;AAMD;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,IAAI,CAEtD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,IAAI,UAAU,CAE9E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEnD"}
|