TenantAtlas/apps/platform/tests/Unit/Support/TenantConfiguration/Spec422ExchangeTeamsRedactionTest.php
ahmido 13d363c8b8 feat: complete spec 422 exchange teams comparable renderable pack (#489)
## Summary

This PR completes spec 422 exchange teams comparable renderable pack with comparable diffing, renderable summary builders, and comprehensive test updates.

## Commit
- 4c1e14c6 feat: complete spec 422 exchange teams comparable renderable pack

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #489
2026-06-30 04:20:13 +00:00

114 lines
5.3 KiB
PHP

<?php
declare(strict_types=1);
use App\Services\TenantConfiguration\ExchangeTeamsCoverageComparator;
use App\Services\TenantConfiguration\ExchangeTeamsRenderableSummaryBuilder;
it('Spec422 keeps unsafe Exchange/Teams values out of render and compare output', function (): void {
$payload = [
'DisplayName' => 'Spec422 Redaction Meeting',
'AllowTranscription' => true,
'clientSecret' => 'spec422-client-secret',
'privateKey' => 'spec422-private-key',
'headers' => ['Authorization' => 'Bearer spec422-auth-token'],
'cookies' => ['session' => 'spec422-cookie'],
'rawPayload' => ['secret' => 'spec422-raw-payload'],
'providerResponse' => ['body' => 'spec422-provider-response-body'],
'messageBody' => 'spec422-mail-message-body',
'chatContent' => 'spec422-chat-content',
'fileContent' => 'spec422-file-content',
'recordingTranscript' => 'spec422-recording-transcript',
'operationRunContext' => ['access_token' => 'spec422-run-token'],
'auditMetadata' => ['raw_payload' => ['secret' => 'spec422-audit-secret']],
];
$summary = app(ExchangeTeamsRenderableSummaryBuilder::class)->build('meetingPolicy', $payload);
$compare = app(ExchangeTeamsCoverageComparator::class)->compare('meetingPolicy', $payload, [
...$payload,
'modifiedDateTime' => '2026-06-28T12:00:00Z',
]);
$encoded = json_encode([$summary, $compare], JSON_THROW_ON_ERROR);
expect($encoded)->not->toContain('spec422-client-secret')
->and($encoded)->not->toContain('spec422-private-key')
->and($encoded)->not->toContain('spec422-auth-token')
->and($encoded)->not->toContain('spec422-cookie')
->and($encoded)->not->toContain('spec422-raw-payload')
->and($encoded)->not->toContain('spec422-provider-response-body')
->and($encoded)->not->toContain('spec422-mail-message-body')
->and($encoded)->not->toContain('spec422-chat-content')
->and($encoded)->not->toContain('spec422-file-content')
->and($encoded)->not->toContain('spec422-recording-transcript')
->and($encoded)->not->toContain('spec422-run-token')
->and($encoded)->not->toContain('spec422-audit-secret')
->and($summary['redacted_fields'])->toContain(
'clientSecret',
'privateKey',
'headers.Authorization',
'cookies',
'rawPayload',
'providerResponse',
'messageBody',
'chatContent',
'fileContent',
'recordingTranscript',
'operationRunContext',
'auditMetadata.raw_payload',
);
});
it('Spec422 keeps content-bearing transport rule condition values out of render and compare output', function (): void {
$before = [
'DisplayName' => 'Spec422 Content Rule',
'Enabled' => true,
];
$after = [
'DisplayName' => 'Spec422 Content Rule',
'Enabled' => true,
'SubjectContainsWords' => ['spec422-root-subject-secret'],
'Conditions' => [
'SubjectOrBodyContainsWords' => ['spec422-mail-body-secret'],
'AttachmentContainsWords' => ['spec422-file-attachment-secret'],
'HeaderContainsWords' => ['spec422-header-secret'],
'HeaderMatchesPatterns' => ['spec422-header-pattern-secret'],
],
'Actions' => [
'ApplyHtmlDisclaimerText' => 'spec422-disclaimer-secret',
'PrependSubject' => 'spec422-prepend-subject-secret',
'SetHeaderValue' => 'spec422-set-header-secret',
],
];
$summary = app(ExchangeTeamsRenderableSummaryBuilder::class)->build('transportRule', $after);
$compare = app(ExchangeTeamsCoverageComparator::class)->compare('transportRule', $before, $after);
$encoded = json_encode([$summary, $compare], JSON_THROW_ON_ERROR);
$materialClassifications = collect($compare['changes'])
->filter(fn (array $change): bool => in_array($change['classification'] ?? null, ['added', 'removed', 'changed'], true))
->pluck('classification')
->values();
expect($encoded)->not->toContain('spec422-root-subject-secret')
->and($encoded)->not->toContain('spec422-mail-body-secret')
->and($encoded)->not->toContain('spec422-file-attachment-secret')
->and($encoded)->not->toContain('spec422-header-secret')
->and($encoded)->not->toContain('spec422-header-pattern-secret')
->and($encoded)->not->toContain('spec422-disclaimer-secret')
->and($encoded)->not->toContain('spec422-prepend-subject-secret')
->and($encoded)->not->toContain('spec422-set-header-secret')
->and($encoded)->not->toContain('[redacted]')
->and($summary['redacted_fields'])->toContain(
'SubjectContainsWords',
'Conditions.SubjectOrBodyContainsWords',
'Conditions.AttachmentContainsWords',
'Conditions.HeaderContainsWords',
'Conditions.HeaderMatchesPatterns',
'Actions.ApplyHtmlDisclaimerText',
'Actions.PrependSubject',
'Actions.SetHeaderValue',
)
->and(collect($compare['changes'])->pluck('classification'))->toContain('redacted')
->and($compare['changed'])->toBeFalse()
->and($materialClassifications)->toBeEmpty();
});