fix: restore full suite (Pest helper collision + ops-ux spec sync) #130

Merged
ahmido merged 1 commits from fix/pest-makeassignment-collision into dev 2026-02-22 11:36:28 +00:00
3 changed files with 26 additions and 27 deletions

View File

@ -184,7 +184,7 @@ ### Functional Requirements
### Canonical allowed summary keys (single source of truth) ### Canonical allowed summary keys (single source of truth)
The following keys are the ONLY allowed summary keys for Ops-UX rendering: The following keys are the ONLY allowed summary keys for Ops-UX rendering:
`total, processed, succeeded, failed, skipped, compliant, noncompliant, unknown, created, updated, deleted, items, tenants, high, medium, low, findings_created, findings_resolved, findings_reopened, findings_unchanged, errors_recorded, posture_score` `total, processed, succeeded, failed, skipped, compliant, noncompliant, unknown, created, updated, deleted, items, tenants, high, medium, low, findings_created, findings_resolved, findings_reopened, findings_unchanged, errors_recorded, posture_score, report_created, report_deduped, alert_events_produced`
All normalizers/renderers MUST reference this canonical list (no duplicated lists in multiple places). All normalizers/renderers MUST reference this canonical list (no duplicated lists in multiple places).

View File

@ -45,7 +45,7 @@ function readerRoleDef(): array
]; ];
} }
function makeAssignment(string $id, string $roleDefId, string $principalId, string $odataType = '#microsoft.graph.user', string $displayName = 'User', string $scopeId = '/'): array function makeEntraAssignment(string $id, string $roleDefId, string $principalId, string $odataType = '#microsoft.graph.user', string $displayName = 'User', string $scopeId = '/'): array
{ {
return [ return [
'id' => $id, 'id' => $id,
@ -91,8 +91,8 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef(), secAdminRoleDef()], [gaRoleDef(), secAdminRoleDef()],
[ [
makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Admin'), makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Admin'),
makeAssignment('a2', 'def-secadmin', 'user-2', '#microsoft.graph.user', 'Bob SecAdmin'), makeEntraAssignment('a2', 'def-secadmin', 'user-2', '#microsoft.graph.user', 'Bob SecAdmin'),
], ],
); );
@ -128,8 +128,8 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef(), secAdminRoleDef()], [gaRoleDef(), secAdminRoleDef()],
[ [
makeAssignment('a1', 'def-ga', 'user-1'), makeEntraAssignment('a1', 'def-ga', 'user-1'),
makeAssignment('a2', 'def-secadmin', 'user-2'), makeEntraAssignment('a2', 'def-secadmin', 'user-2'),
], ],
); );
@ -152,7 +152,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1')], [makeEntraAssignment('a1', 'def-ga', 'user-1')],
); );
$generator = makeGenerator(); $generator = makeGenerator();
@ -179,7 +179,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
// First scan: user-1 has GA // First scan: user-1 has GA
$payload1 = buildPayload( $payload1 = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1')], [makeEntraAssignment('a1', 'def-ga', 'user-1')],
); );
$generator->generate($tenant, $payload1); $generator->generate($tenant, $payload1);
@ -207,7 +207,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
// Scan 1: create // Scan 1: create
$payload1 = buildPayload( $payload1 = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice')], [makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice')],
); );
$generator->generate($tenant, $payload1); $generator->generate($tenant, $payload1);
@ -218,7 +218,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
// Scan 3: re-assign → re-open // Scan 3: re-assign → re-open
$payload3 = buildPayload( $payload3 = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Reactivated')], [makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Reactivated')],
); );
$result3 = $generator->generate($tenant, $payload3); $result3 = $generator->generate($tenant, $payload3);
@ -242,7 +242,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$assignments = []; $assignments = [];
for ($i = 1; $i <= 6; $i++) { for ($i = 1; $i <= 6; $i++) {
$assignments[] = makeAssignment("a{$i}", 'def-ga', "user-{$i}", '#microsoft.graph.user', "GA User {$i}"); $assignments[] = makeEntraAssignment("a{$i}", 'def-ga', "user-{$i}", '#microsoft.graph.user', "GA User {$i}");
} }
$payload = buildPayload([gaRoleDef()], $assignments); $payload = buildPayload([gaRoleDef()], $assignments);
@ -274,7 +274,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$assignments = []; $assignments = [];
for ($i = 1; $i <= 6; $i++) { for ($i = 1; $i <= 6; $i++) {
$assignments[] = makeAssignment("a{$i}", 'def-ga', "user-{$i}"); $assignments[] = makeEntraAssignment("a{$i}", 'def-ga', "user-{$i}");
} }
$generator->generate($tenant, buildPayload([gaRoleDef()], $assignments)); $generator->generate($tenant, buildPayload([gaRoleDef()], $assignments));
@ -301,7 +301,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1')], [makeEntraAssignment('a1', 'def-ga', 'user-1')],
); );
$generator->generate($tenant, $payload); $generator->generate($tenant, $payload);
@ -321,7 +321,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1')], [makeEntraAssignment('a1', 'def-ga', 'user-1')],
); );
// Scan 1: alert events produced for new finding // Scan 1: alert events produced for new finding
@ -340,7 +340,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Admin')], [makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Admin')],
); );
makeGenerator()->generate($tenant, $payload); makeGenerator()->generate($tenant, $payload);
@ -378,9 +378,9 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[ [
makeAssignment('a1', 'def-ga', 'p-user', '#microsoft.graph.user', 'User'), makeEntraAssignment('a1', 'def-ga', 'p-user', '#microsoft.graph.user', 'User'),
makeAssignment('a2', 'def-ga', 'p-group', '#microsoft.graph.group', 'Group'), makeEntraAssignment('a2', 'def-ga', 'p-group', '#microsoft.graph.group', 'Group'),
makeAssignment('a3', 'def-ga', 'p-sp', '#microsoft.graph.servicePrincipal', 'SP'), makeEntraAssignment('a3', 'def-ga', 'p-sp', '#microsoft.graph.servicePrincipal', 'SP'),
], ],
); );
@ -403,7 +403,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1')], [makeEntraAssignment('a1', 'def-ga', 'user-1')],
); );
makeGenerator()->generate($tenant, $payload); makeGenerator()->generate($tenant, $payload);
@ -425,7 +425,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
// Scan 1: create // Scan 1: create
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1')], [makeEntraAssignment('a1', 'def-ga', 'user-1')],
); );
$generator->generate($tenant, $payload); $generator->generate($tenant, $payload);
@ -454,7 +454,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[gaRoleDef()], [gaRoleDef()],
[makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice', '/administrativeUnits/au-123')], [makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice', '/administrativeUnits/au-123')],
); );
makeGenerator()->generate($tenant, $payload); makeGenerator()->generate($tenant, $payload);
@ -473,7 +473,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator
$payload = buildPayload( $payload = buildPayload(
[readerRoleDef()], [readerRoleDef()],
[makeAssignment('a1', 'def-reader', 'user-1')], [makeEntraAssignment('a1', 'def-reader', 'user-1')],
); );
$result = makeGenerator()->generate($tenant, $payload); $result = makeGenerator()->generate($tenant, $payload);

View File

@ -43,11 +43,10 @@
$body = (string) ($notification->data['body'] ?? ''); $body = (string) ($notification->data['body'] ?? '');
expect($body)->toContain('Summary:'); expect($body)->toContain('Total: 10');
expect($body)->toContain('total: 10'); expect($body)->toContain('Processed: 5');
expect($body)->toContain('processed: 5'); expect($body)->not->toContain('Secrets');
expect($body)->not->toContain('secrets'); expect($body)->not->toContain('Failed:');
expect($body)->not->toContain('failed:');
})->group('ops-ux'); })->group('ops-ux');
it('sanitizes summary_counts values and drops non-whitelisted keys', function (): void { it('sanitizes summary_counts values and drops non-whitelisted keys', function (): void {