TenantAtlas/apps/platform/tests/Unit/Support/TenantConfiguration/Spec435ExchangeHashInputReadinessTest.php
ahmido a09cc6ca8d Spec 435: Exchange structured output readiness (#502)
## Summary

- Add Spec 435 backend-only Exchange structured output envelope and target normalizer readiness helpers for transportRule, remoteDomain, and inboundConnector.
- Add deterministic hash input/readiness handling and no-promotion guard coverage.
- Add Spec 435 spec, plan, tasks, checklist, and implementation report artifacts.

## Validation

- git diff --cached --check
- cd apps/platform && php artisan test --filter=Spec435 --compact

## Product Surface / Deployment

- Livewire v4 compliance unchanged.
- Filament provider registration unchanged under apps/platform/bootstrap/providers.php.
- Global search unchanged; no resources added or modified.
- Destructive/high-impact actions: none.
- Asset strategy: none; no filament:assets requirement for this slice.
- Browser proof: N/A - no rendered UI surface changed.
- Deployment impact: no env vars, migrations, queues, scheduler, storage, assets, or Dokploy runtime behavior changes.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #502
2026-07-08 14:33:23 +00:00

76 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
use App\Services\TenantConfiguration\ExchangePowerShellCommandContracts;
use App\Services\TenantConfiguration\ExchangePowerShellHashInputBuilder;
use App\Services\TenantConfiguration\ExchangePowerShellTargetEvidenceNormalizer;
it('Spec435 hash input includes target and normalizer metadata while excluding raw runtime context', function (): void {
$builder = app(ExchangePowerShellHashInputBuilder::class);
$input = $builder->build(
resourceType: 'transportRule',
sourceSurface: ExchangePowerShellCommandContracts::SOURCE_SURFACE,
commandContractName: 'Get-TransportRule',
commandContractVersion: ExchangePowerShellCommandContracts::COMMAND_CONTRACT_VERSION,
payloadShapeVersion: ExchangePowerShellTargetEvidenceNormalizer::PAYLOAD_SHAPE_VERSION,
normalizerVersion: 'exchange-transport-rule-readiness-v1',
normalizedPayload: [
'canonical_type' => 'transportRule',
'material' => ['enabled' => true],
],
);
$json = $builder->canonicalJson($input);
expect($input)->toMatchArray([
'resource_type' => 'transportRule',
'source_surface' => ExchangePowerShellCommandContracts::SOURCE_SURFACE,
'command_contract_name' => 'Get-TransportRule',
'command_contract_version' => ExchangePowerShellCommandContracts::COMMAND_CONTRACT_VERSION,
'payload_shape_version' => ExchangePowerShellTargetEvidenceNormalizer::PAYLOAD_SHAPE_VERSION,
'normalizer_version' => 'exchange-transport-rule-readiness-v1',
])
->and($json)
->not->toContain('raw_stdout')
->not->toContain('raw_stderr')
->not->toContain('operation_run')
->not->toContain('credential')
->not->toContain('permission');
});
it('Spec435 hash previews change when normalizer version or target type changes', function (): void {
$builder = app(ExchangePowerShellHashInputBuilder::class);
$payload = ['canonical_type' => 'transportRule', 'material' => ['enabled' => true]];
$first = $builder->hash($builder->build(
resourceType: 'transportRule',
sourceSurface: ExchangePowerShellCommandContracts::SOURCE_SURFACE,
commandContractName: 'Get-TransportRule',
commandContractVersion: ExchangePowerShellCommandContracts::COMMAND_CONTRACT_VERSION,
payloadShapeVersion: ExchangePowerShellTargetEvidenceNormalizer::PAYLOAD_SHAPE_VERSION,
normalizerVersion: 'exchange-transport-rule-readiness-v1',
normalizedPayload: $payload,
));
$versionChanged = $builder->hash($builder->build(
resourceType: 'transportRule',
sourceSurface: ExchangePowerShellCommandContracts::SOURCE_SURFACE,
commandContractName: 'Get-TransportRule',
commandContractVersion: ExchangePowerShellCommandContracts::COMMAND_CONTRACT_VERSION,
payloadShapeVersion: ExchangePowerShellTargetEvidenceNormalizer::PAYLOAD_SHAPE_VERSION,
normalizerVersion: 'exchange-transport-rule-readiness-v2',
normalizedPayload: $payload,
));
$targetChanged = $builder->hash($builder->build(
resourceType: 'remoteDomain',
sourceSurface: ExchangePowerShellCommandContracts::SOURCE_SURFACE,
commandContractName: 'Get-RemoteDomain',
commandContractVersion: ExchangePowerShellCommandContracts::COMMAND_CONTRACT_VERSION,
payloadShapeVersion: ExchangePowerShellTargetEvidenceNormalizer::PAYLOAD_SHAPE_VERSION,
normalizerVersion: 'exchange-transport-rule-readiness-v1',
normalizedPayload: $payload,
));
expect($first)->not->toBe($versionChanged)
->and($first)->not->toBe($targetChanged);
});