Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/coverage-unreachable.php
Original file line number Diff line number Diff line change
Expand Up @@ -271,14 +271,14 @@
219, 240, 241, 242, 243,
],

// 373-377: the ip_ban-side initialization catch. Every collaborator
// 457-461: the ip_ban-side initialization catch. Every collaborator
// inside the try fails open or swallows: RateLimitHandler::
// initializeRedis wraps scriptLoad in its own catch, initializeIpBan
// only assigns the manager, IpBanManager::initializeRedis migrates
// legacy keys under its own catch, and CloudManager::initializeRedis
// refreshes through the single-flight path that logs its own
// failures - no input steers a Throwable out of the block.
'src/Engine/GuardEngine.php' => [
373, 374, 375, 376, 377,
457, 458, 459, 460, 461,
],
];
7 changes: 6 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ jobs:
REDIS_HOST: 127.0.0.1
run: php bin/test_config_fields.php

- name: test_events_parity
env:
REDIS_HOST: 127.0.0.1
run: php bin/test_events_parity.php

conformance-pipeline:
name: Conformance pipeline (php ${{ matrix.php }})
runs-on: ubuntu-latest
Expand Down Expand Up @@ -235,7 +240,7 @@ jobs:
run: |
mkdir -p build
php .github/coverage-runner.php --collect bin/test_state.php build/coverage-test_state.php --integration
for suite in test_parity_seam test_ratelimit test_geo_rate_limits test_pipeline test_m3b test_m4 test_behavior test_m3c conformance conformance_safety conformance_events conformance_redis test_nfkc test_binary_noise_gate test_recon_context_gate test_recon_raw_view_scan test_body_form_scan test_json_walk test_exempt_ips test_excluded_headers test_cors test_geo_country test_geo_lifecycle test_event_bus test_security_headers test_large_body test_support test_redos_gates test_performance_monitor test_enrichment test_composite_handlers test_json_logging test_pattern_registry test_config_fields; do
for suite in test_parity_seam test_ratelimit test_geo_rate_limits test_pipeline test_m3b test_m4 test_behavior test_m3c conformance conformance_safety conformance_events conformance_redis test_nfkc test_binary_noise_gate test_recon_context_gate test_recon_raw_view_scan test_body_form_scan test_json_walk test_exempt_ips test_excluded_headers test_cors test_geo_country test_geo_lifecycle test_event_bus test_security_headers test_large_body test_support test_redos_gates test_performance_monitor test_enrichment test_composite_handlers test_json_logging test_pattern_registry test_config_fields test_events_parity; do
php .github/coverage-runner.php --collect "bin/${suite}.php" "build/coverage-${suite}.php"
done

Expand Down
13 changes: 11 additions & 2 deletions bin/test_enrichment.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,17 @@ public function healthCheck(): bool
$engine->setAgentHandler($composite);
$blocked = new SimpleGuardRequest(method: 'GET', urlPath: '/data', headers: [], clientHost: '203.0.113.99');
$engine->execute($blocked);
$t->same(1, count($sink->events), 'blocked request emitted exactly one event');
$emitted = $sink->events[0] ?? null;
// The block event plus the security_headers_applied tick the blocked
// response carries (the reference emits both: the block through the bus,
// the headers through the response factory's headers manager).
$t->same(2, count($sink->events), 'blocked request emitted the block event and the headers tick');
$emitted = null;
foreach ($sink->events as $candidate) {
if ($candidate->eventType !== EventTypes::EVENT_SECURITY_HEADERS_APPLIED) {
$emitted = $candidate;
break;
}
}
$t->truthy($emitted !== null && isset($emitted->metadata[EventTypes::ENRICHMENT_KEY_THREAT_SCORE]), 'emitted event carries a threat score');
$t->truthy($emitted !== null && ($emitted->metadata[EventTypes::ENRICHMENT_KEY_THREAT_SCORE] ?? 0) === ThreatScorer::scoreFor($emitted->eventType), 'emitted threat score matches the event type map');
$t->truthy($emitted !== null && ($emitted->metadata[EventTypes::ENRICHMENT_KEY_SERVICE_NAME] ?? '') === 'edge-svc', 'emitted event carries the service name');
Expand Down
5 changes: 4 additions & 1 deletion bin/test_event_bus.php
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,10 @@ public function __construct(
$emergencyEngine->eventBus()->setAgentHandler($emergencyAgent);
$allowedEmergencyRequest = new SimpleGuardRequest(method: 'GET', urlPath: '/status', headers: [], clientHost: '10.0.0.1');
$t->same(null, $emergencyEngine->execute($allowedEmergencyRequest), 'a whitelisted ip passes emergency mode');
$t->same([], $emergencyAgent->received, 'the whitelisted pass emitted nothing');
// The pass now carries exactly the security_headers_applied tick (the
// reference headers manager emits for the response the adapter sends).
$emergencyTypes = array_map(static fn (object $e): string => $e->eventType, $emergencyAgent->received);
$t->same([EventTypes::EVENT_SECURITY_HEADERS_APPLIED], $emergencyTypes, 'the whitelisted pass emits only the headers tick');
$emergencyRequest = new SimpleGuardRequest(method: 'GET', urlPath: '/status', headers: [], clientHost: '203.0.113.22');
$t->same(503, $emergencyEngine->execute($emergencyRequest)?->statusCode(), 'emergency mode blocks non-whitelisted ips');
$emergencyTypes = array_map(static fn (object $e): string => $e->eventType, $emergencyAgent->received);
Expand Down
Loading
Loading