Files
api/services/nginx/app/tests/Unit/Bird/BirdFlowPolicyEvaluatorTest.php
T
Jeppe B a442e70744 Add secure Bird gateway for Pleno Control Plane (#332)
Add the Bird Control Plane gateway, signed webhook ingestion, policy-gated writes, fail-closed production auto-activation, and RSA-OAEP bootstrap credential flow.
2026-07-29 19:59:20 +02:00

59 lines
2.0 KiB
PHP

<?php
app_require('modules/bird/classes/bird_flow_policy_evaluator.php');
use bird\classes\bird_flow_policy_evaluator;
it('returns only deterministic allowlisted Bird Flow actions for an exact rule match', function (): void {
$policy = json_encode([
'version' => 'v1',
'rules' => [[
'id' => 'vip-whatsapp',
'enabled' => true,
'when' => [
'platform' => 'whatsapp',
'contact.segment' => 'vip',
],
'actions' => [
['type' => 'tag', 'value' => 'vip'],
['type' => 'assign', 'value' => 'support-team'],
['type' => 'snooze', 'value' => 'PT15M'],
],
]],
], JSON_THROW_ON_ERROR);
$decision = bird_flow_policy_evaluator::evaluate($policy, [
'platform' => 'whatsapp',
'contact' => ['segment' => 'vip'],
]);
expect($decision)->toMatchArray([
'decision' => 'allow',
'reason' => 'matched_rule',
'policyVersion' => 'v1',
'ruleId' => 'vip-whatsapp',
])->and($decision['actions'])->toHaveCount(3);
});
it('fails closed for absent matches, invalid policy and any non-allowlisted action', function (): void {
$unsafePolicy = json_encode([
'version' => 'v1',
'rules' => [[
'id' => 'unsafe',
'enabled' => true,
'when' => ['platform' => 'email'],
'actions' => [['type' => 'send_message', 'value' => 'hello']],
]],
], JSON_THROW_ON_ERROR);
expect(bird_flow_policy_evaluator::evaluate('', ['platform' => 'email'])['decision'])->toBe('deny')
->and(bird_flow_policy_evaluator::evaluate($unsafePolicy, ['platform' => 'email']))
->toMatchArray([
'decision' => 'deny',
'reason' => 'invalid_rule_actions',
'actions' => [],
])
->and(bird_flow_policy_evaluator::evaluate($unsafePolicy, ['platform' => 'sms'])['decision'])
->toBe('deny');
});