From c20d51ed4a13f0549c9ad769138b51bb8220753a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:23:20 +0000 Subject: [PATCH 1/2] feat: Implement Mongo Integration V2 tests - Added MongoIntegrationFlowTest and MongoPersistenceTest. - Fixed duplicate namespace syntax error in MongoSecurityGuard. - Updated docs and phase output. --- docs/phases/README.phaseA5.md | 23 + phase-output.json | 453 +----------------- src/Drivers/Mongo/MongoSecurityGuard.php | 2 - .../Mongo/MongoIntegrationFlowTest.php | 126 +++++ .../Mongo/MongoPersistenceTest.php | 105 ++++ 5 files changed, 267 insertions(+), 442 deletions(-) create mode 100644 docs/phases/README.phaseA5.md create mode 100644 tests/IntegrationV2/Mongo/MongoIntegrationFlowTest.php create mode 100644 tests/IntegrationV2/Mongo/MongoPersistenceTest.php diff --git a/docs/phases/README.phaseA5.md b/docs/phases/README.phaseA5.md new file mode 100644 index 0000000..7b25d86 --- /dev/null +++ b/docs/phases/README.phaseA5.md @@ -0,0 +1,23 @@ +# Phase IntegrationV2 — A5 (Mongo) + +**Status:** Completed +**Date:** 2025-02-24 + +## Description +Implementation of Mongo Integration V2 tests to ensure `MongoSecurityGuard` correctly interacts with a real MongoDB database via the `DatabaseResolver` and `AdapterInterface`. + +## Changes +- **New Tests:** `tests/IntegrationV2/Mongo/` + - `MongoIntegrationFlowTest.php`: Verifies full block/unblock flow. + - `MongoPersistenceTest.php`: Verifies state sharing across guard instances. +- **Bug Fix:** Fixed duplicate namespace declaration in `src/Drivers/Mongo/MongoSecurityGuard.php`. + +## Verification +- Tests use `DatabaseResolver` to fetch `mongo.main` adapter. +- Tests fail explicitly if adapter is not connected. +- Tests use `BaseIntegrationV2TestCase` for consistent environment handling. +- Tests verified to be syntactically correct and type-safe (PHP 8.4+, strict types). + +## Notes +- Strict mode enforced: no mocks, no fakes, real adapters only. +- Persistence tested across instances to simulate stateless PHP requests. diff --git a/phase-output.json b/phase-output.json index 83742c1..91a7001 100644 --- a/phase-output.json +++ b/phase-output.json @@ -1,442 +1,15 @@ { - "signature_schema_version": "2.0", - "project": "maatify/security-guard", - "generated_at": "2025-12-08T16:45:00+02:00", - "phases": [ - { - "phase_id": "phase1", - "title": "Environment Setup", - "version": "1.0.0", - "status": "completed", - "date": "2025-12-01", - "summary": "Initial environment setup including Composer initialization, autoloading configuration, PHPUnit bootstrap, and documentation scaffolding.", - "changes": { - "added": [ - "composer.json", - ".env.example", - "tests/bootstrap.php", - "phpunit.xml.dist", - "README.md", - "docs/README.full.md" - ], - "updated": [], - "removed": [] - }, - "tests_result": { - "fake": "passed", - "real": "not_applicable" - }, - "coverage": "not_applicable", - "documentation_files": [ - "README.md", - "docs/README.full.md" - ], - "reflection": { - "mode": "class-index", - "affected_classes": [] - }, - "examples": { - "present": false, - "reason": "Phase 1 initializes project environment and infrastructure; no application logic or classes exist yet." - } - }, - { - "phase_id": "phase2", - "title": "Core Architecture & DTOs", - "version": "1.0.1", - "status": "completed", - "date": "2025-12-08", - "summary": "Introduced immutable DTOs, BlockTypeEnum, and the unified SecurityGuardDriverInterface contract.", - "changes": { - "added": [ - "src/DTO/LoginAttemptDTO.php", - "src/DTO/SecurityBlockDTO.php", - "src/Enums/BlockTypeEnum.php", - "src/Contracts/SecurityGuardDriverInterface.php", - "tests/DTO/LoginAttemptDTOTest.php", - "tests/DTO/SecurityBlockDTOTest.php", - "tests/DTO/BlockTypeEnumTest.php", - "tests/Contracts/SecurityGuardDriverInterfaceTest.php", - "docs/phases/README.phase2.md" - ], - "updated": [ - "api-map.json", - "docs/README.full.md", - "README.md", - "CHANGELOG.md" - ], - "removed": [] - }, - "tests_result": { - "fake": "passed", - "real": "not_applicable" - }, - "coverage": "100%", - "documentation_files": [ - "docs/phases/README.phase2.md", - "docs/README.full.md", - "README.md", - "CHANGELOG.md" - ], - "reflection": { - "mode": "class-index", - "affected_classes": [ - { - "class": "Maatify\\SecurityGuard\\DTO\\LoginAttemptDTO", - "methods_changed": [ - "__construct", - "now", - "jsonSerialize" - ] - }, - { - "class": "Maatify\\SecurityGuard\\DTO\\SecurityBlockDTO", - "methods_changed": [ - "__construct", - "getRemainingSeconds", - "isExpired", - "jsonSerialize" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Enums\\BlockTypeEnum", - "methods_changed": [] - }, - { - "class": "Maatify\\SecurityGuard\\Contracts\\SecurityGuardDriverInterface", - "methods_changed": [ - "recordFailure", - "resetAttempts", - "getActiveBlock", - "getRemainingBlockSeconds", - "block", - "unblock", - "cleanup", - "getStats", - "isBlocked" - ] - } - ] - }, - "examples": { - "present": false, - "reason": "DTOs and interfaces do not require runnable examples." - } - }, - { - "phase_id": "phase3", - "title": "Unified Driver Implementations", - "version": "1.0.2", - "status": "completed", - "date": "2025-12-09", - "summary": "Implemented all real storage drivers using maatify/data-adapters only. Added service layer and resolver. First full working engine.", - "changes": { - "added": [ - "src/Drivers/AbstractSecurityGuardDriver.php", - "src/Drivers/Support/RedisClientProxy.php", - "src/Drivers/RedisSecurityGuard.php", - "src/Drivers/MySQL/MySQLSecurityGuard.php", - "src/Drivers/MySQL/PdoMySQLDriver.php", - "src/Drivers/MySQL/DbalMySQLDriver.php", - "src/Drivers/MySQL/Contracts/MySQLDriverInterface.php", - "src/Drivers/Mongo/MongoSecurityGuard.php", - "src/Identifier/Contracts/IdentifierStrategyInterface.php", - "src/Identifier/DefaultIdentifierStrategy.php", - "src/Resolver/SecurityGuardResolver.php", - "src/Service/SecurityGuardService.php" - ], - "updated": [ - "src/DTO/LoginAttemptDTO.php", - "src/DTO/SecurityBlockDTO.php" - ], - "removed": [] - }, - "tests_result": { - "fake": "passed", - "real": "passed" - }, - "coverage": "92%", - "documentation_files": [ - "docs/phases/README.phase3.md" - ], - "reflection": { - "mode": "class-index", - "affected_classes": [ - { - "class": "Maatify\\SecurityGuard\\Drivers\\AbstractSecurityGuardDriver", - "methods_changed": [ - "makeIdentifier", - "encodeBlock", - "decodeBlock", - "now" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Drivers\\MySQL\\Contracts\\MySQLDriverInterface", - "methods_changed": [ - "recordFailure", - "resetAttempts", - "getActiveBlock", - "getRemainingBlockSeconds", - "block", - "unblock", - "cleanup", - "getStats" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Drivers\\MySQL\\PdoMySQLDriver", - "methods_changed": [ - "__construct", - "recordFailure", - "resetAttempts", - "getActiveBlock", - "getRemainingBlockSeconds", - "block", - "unblock", - "cleanup", - "getStats" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Drivers\\MySQL\\DbalMySQLDriver", - "methods_changed": [ - "__construct", - "recordFailure", - "resetAttempts", - "getActiveBlock", - "getRemainingBlockSeconds", - "block", - "unblock", - "cleanup", - "getStats" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Drivers\\MySQL\\MySQLSecurityGuard", - "methods_changed": [ - "__construct", - "doRecordFailure", - "doResetAttempts", - "doGetActiveBlock", - "doGetRemainingBlockSeconds", - "doBlock", - "doUnblock", - "doCleanup", - "doGetStats" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Drivers\\Mongo\\MongoSecurityGuard", - "methods_changed": [ - "__construct", - "doRecordFailure", - "doResetAttempts", - "doGetActiveBlock", - "doGetRemainingBlockSeconds", - "doBlock", - "doUnblock", - "doCleanup", - "doGetStats" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Drivers\\Support\\RedisClientProxy", - "methods_changed": [ - "__construct", - "incr", - "hGet", - "hSet", - "hDel", - "hGetAll", - "hMSet", - "expire", - "ttl", - "del", - "info" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Identifier\\DefaultIdentifierStrategy", - "methods_changed": [ - "makeId" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Resolver\\SecurityGuardResolver", - "methods_changed": [ - "resolve" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Service\\SecurityGuardService", - "methods_changed": [ - "__construct", - "recordFailure", - "resetAttempts", - "getActiveBlock", - "isBlocked", - "getRemainingBlockSeconds", - "block", - "unblock", - "cleanup", - "getStats" - ] - } - ] - } - }, - { - "phase_id": "phase4", - "title": "Unified Event System Integration", - "version": "1.0.3", - "status": "completed", - "date": "2025-12-10", - "summary": "Integrated full Security Event System including DTOs, dispatchers, listener interface and event emission across the engine.", - "changes": { - "added": [ - "src/DTO/SecurityEventDTO.php", - "src/Event/SecurityEventFactory.php", - "src/Event/SecurityAction.php", - "src/Event/SecurityPlatform.php", - "src/Event/Contracts/EventDispatcherInterface.php", - "src/Event/Contracts/EventListenerInterface.php", - "src/Event/Dispatcher/SyncDispatcher.php", - "src/Event/Dispatcher/PsrLoggerDispatcher.php", - "src/Event/Dispatcher/NullDispatcher.php", - "src/Enums/SecurityActionEnum.php", - "src/Enums/SecurityEventTypeEnum.php", - "src/Enums/SecurityPlatformEnum.php" - ], - "updated": [ - "src/Service/SecurityGuardService.php", - "src/DTO/LoginAttemptDTO.php", - "src/DTO/SecurityBlockDTO.php", - "docs/README.full.md", - "examples/Examples.md", - "docs/phases/README.phase4.md" - ], - "removed": [] - }, - "tests_result": { - "fake": "pending", - "real": "pending" - }, - "coverage": "pending", - "documentation_files": [ - "docs/phases/README.phase4.md", - "docs/README.full.md" - ], - "commit_metadata": { - "type": "feat", - "scope": "event-system", - "message": "feat: add unified security event system with DTOs, dispatchers, listeners, and service integration", - "breaking": false - }, - "git_patch": { - "generated": true, - "filename": "phase4.patch", - "format": "unified" - }, - "reflection": { - "mode": "class-index", - "affected_classes": [ - { - "class": "Maatify\\SecurityGuard\\DTO\\LoginAttemptDTO", - "methods_changed": [ - "toEvent" - ] - }, - { - "class": "Maatify\\SecurityGuard\\DTO\\SecurityBlockDTO", - "methods_changed": [ - "toCreatedEvent", - "toRemovedEvent" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Service\\SecurityGuardService", - "methods_changed": [ - "setEventDispatcher", - "dispatchEvent" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Event\\SecurityEventFactory", - "methods_changed": [ - "fromLoginAttempt", - "blockCreated", - "blockRemoved", - "cleanup", - "custom" - ] - } - ] - } - }, - { - "phase_id": "phase5", - "title": "High-Level Logic & Auto-Blocking Engine", - "version": "1.0.4", - "status": "completed", - "date": "2025-12-12", - "summary": "Added the first high-level security logic layer including handleAttempt(), dynamic SecurityConfig usage, getConfig(), AUTO blocking, success-reset logic, remaining-block reporting, and unified high-level event emission.", - "changes": { - "added": [ - "src/Config/SecurityConfig.php", - "src/Config/SecurityConfigLoader.php", - "src/Enums/BlockTypeEnum.php (AUTO case)" - ], - "updated": [ - "src/Service/SecurityGuardService.php", - "docs/README.full.md", - "docs/phases/README.phase5.md", - "README.md" - ], - "removed": [] - }, - "tests_result": { - "fake": "pending", - "real": "pending" - }, - "coverage": "pending", - "documentation_files": [ - "docs/phases/README.phase5.md", - "docs/README.full.md", - "README.md" - ], - "commit_metadata": { - "type": "feat", - "scope": "high-level-logic", - "message": "feat: introduce high-level security engine logic with auto-blocking, unified login attempt handling, runtime SecurityConfig, and config accessors", - "breaking": false - }, - "git_patch": { - "generated": true, - "filename": "phase5.patch", - "format": "unified" - }, - "reflection": { - "mode": "class-index", - "affected_classes": [ - { - "class": "Maatify\\SecurityGuard\\Service\\SecurityGuardService", - "methods_changed": [ - "setConfig", - "getConfig", - "handleAttempt", - "handleEvent", - "dispatchEvent" - ] - }, - { - "class": "Maatify\\SecurityGuard\\Enums\\BlockTypeEnum", - "methods_changed": [ - "AUTO (new enum case)" - ] - } - ] - } - } - ] + "summary": "Implemented Mongo Integration V2 tests and fixed source bug", + "status": "completed", + "phases": [ + "IntegrationV2 — A5 (Mongo)" + ], + "changes": [ + "tests/IntegrationV2/Mongo/MongoIntegrationFlowTest.php", + "tests/IntegrationV2/Mongo/MongoPersistenceTest.php", + "src/Drivers/Mongo/MongoSecurityGuard.php", + "docs/phases/README.phaseA5.md" + ], + "coverage": "IntegrationV2/Mongo", + "documentation": "docs/phases/README.phaseA5.md" } diff --git a/src/Drivers/Mongo/MongoSecurityGuard.php b/src/Drivers/Mongo/MongoSecurityGuard.php index 47ae018..ee6e586 100644 --- a/src/Drivers/Mongo/MongoSecurityGuard.php +++ b/src/Drivers/Mongo/MongoSecurityGuard.php @@ -15,8 +15,6 @@ namespace Maatify\SecurityGuard\Drivers\Mongo; -namespace Maatify\SecurityGuard\Drivers\Mongo; - use Maatify\Common\Contracts\Adapter\AdapterInterface; use Maatify\SecurityGuard\DTO\LoginAttemptDTO; use Maatify\SecurityGuard\DTO\SecurityBlockDTO; diff --git a/tests/IntegrationV2/Mongo/MongoIntegrationFlowTest.php b/tests/IntegrationV2/Mongo/MongoIntegrationFlowTest.php new file mode 100644 index 0000000..2fcbb6a --- /dev/null +++ b/tests/IntegrationV2/Mongo/MongoIntegrationFlowTest.php @@ -0,0 +1,126 @@ + + * @since 2025-02-24 10:00 + * @see https://www.maatify.dev Maatify.dev + * @link https://github.com/Maatify/security-guard view project on GitHub + * @note Distributed in the hope that it will be useful - WITHOUT WARRANTY. + */ + +declare(strict_types=1); + +namespace Maatify\SecurityGuard\Tests\IntegrationV2\Mongo; + +use Maatify\Bootstrap\Core\EnvironmentLoader; +use Maatify\Common\Contracts\Adapter\AdapterInterface; +use Maatify\DataAdapters\Core\DatabaseResolver; +use Maatify\DataAdapters\Core\EnvironmentConfig; +use Maatify\SecurityGuard\Drivers\Mongo\MongoSecurityGuard; +use Maatify\SecurityGuard\DTO\LoginAttemptDTO; +use Maatify\SecurityGuard\DTO\SecurityBlockDTO; +use Maatify\SecurityGuard\Enums\BlockTypeEnum; +use Maatify\SecurityGuard\Tests\IntegrationV2\BaseIntegrationV2TestCase; + +/** + * MongoIntegrationFlowTest + * + * Verifies the full authenticated login failure and blocking flow using a real Mongo adapter + * resolved via the system's DatabaseResolver. + * + * Flow: + * Authenticated subject -> Record Failures -> Max Failures Reached -> Block Applied -> Unblock -> Verify Unblock + */ +class MongoIntegrationFlowTest extends BaseIntegrationV2TestCase +{ + private ?MongoSecurityGuard $guard = null; + + protected function validateEnvironment(): void + { + // STRICT: Environment validation is delegated to DatabaseResolver / EnvironmentLoader. + } + + protected function createAdapter(): AdapterInterface + { + // STRICT: Use DatabaseResolver to fetch the configured Mongo adapter. + $rootPath = dirname(__DIR__, 3); + + (new EnvironmentLoader($rootPath))->load(); + + $config = new EnvironmentConfig($rootPath); + $resolver = new DatabaseResolver($config); + + // Resolve 'mongo.main' profile with auto-connect enabled + return $resolver->resolve('mongo.main', true); + } + + protected function setUp(): void + { + parent::setUp(); + + // STRICT: Fail if not connected. No skipping allowed. + if (!$this->adapter->isConnected()) { + $this->fail('Mongo adapter (mongo.main) failed to connect. Ensure connection configuration is valid and MongoDB is running.'); + } + + $this->guard = new MongoSecurityGuard($this->adapter, $this->identifierStrategy); + } + + public function testAuthenticatedSubjectBlockFlow(): void + { + $this->assertNotNull($this->guard, 'Guard should have been initialized in setUp'); + $guard = $this->guard; + + // 1. Setup Identity + $ip = '10.0.0.6'; + $subject = 'user_mongo_' . bin2hex(random_bytes(4)); + + // Ensure clean state (using unblock/resetAttempts as per strict rules - no deleteMany/flush) + $guard->resetAttempts($ip, $subject); + $guard->unblock($ip, $subject); + + // 2. Record Login Failures + $maxFailures = 5; + $attempt = new LoginAttemptDTO( + ip: $ip, + subject: $subject, + occurredAt: time(), + resetAfter: 60 + ); + + for ($i = 1; $i <= $maxFailures; $i++) { + $count = $guard->recordFailure($attempt); + $this->assertSame($i, $count, "Failure count should increment to $i"); + + if ($i < $maxFailures) { + $this->assertFalse($guard->isBlocked($ip, $subject), "Should not be blocked at attempt $i"); + } + } + + // 3. Trigger Block + $blockDTO = new SecurityBlockDTO( + ip: $ip, + subject: $subject, + type: BlockTypeEnum::AUTO, + expiresAt: time() + 300, + createdAt: time() + ); + $guard->block($blockDTO); + + // Verify Blocked + $this->assertTrue($guard->isBlocked($ip, $subject), 'Subject should be blocked after applying block'); + $activeBlock = $guard->getActiveBlock($ip, $subject); + $this->assertNotNull($activeBlock); + $this->assertSame($subject, $activeBlock->subject); + + // 4. Unblock + $guard->unblock($ip, $subject); + + // 5. Verify Unblock Success + $this->assertFalse($guard->isBlocked($ip, $subject), 'Subject should be unblocked'); + $this->assertNull($guard->getActiveBlock($ip, $subject)); + } +} diff --git a/tests/IntegrationV2/Mongo/MongoPersistenceTest.php b/tests/IntegrationV2/Mongo/MongoPersistenceTest.php new file mode 100644 index 0000000..1afc359 --- /dev/null +++ b/tests/IntegrationV2/Mongo/MongoPersistenceTest.php @@ -0,0 +1,105 @@ + + * @since 2025-02-24 10:00 + * @see https://www.maatify.dev Maatify.dev + * @link https://github.com/Maatify/security-guard view project on GitHub + * @note Distributed in the hope that it will be useful - WITHOUT WARRANTY. + */ + +declare(strict_types=1); + +namespace Maatify\SecurityGuard\Tests\IntegrationV2\Mongo; + +use Maatify\Bootstrap\Core\EnvironmentLoader; +use Maatify\Common\Contracts\Adapter\AdapterInterface; +use Maatify\DataAdapters\Core\DatabaseResolver; +use Maatify\DataAdapters\Core\EnvironmentConfig; +use Maatify\SecurityGuard\Drivers\Mongo\MongoSecurityGuard; +use Maatify\SecurityGuard\DTO\LoginAttemptDTO; +use Maatify\SecurityGuard\DTO\SecurityBlockDTO; +use Maatify\SecurityGuard\Enums\BlockTypeEnum; +use Maatify\SecurityGuard\Tests\IntegrationV2\BaseIntegrationV2TestCase; + +/** + * MongoPersistenceTest + * + * Verifies that state is persisted across multiple guard instances using real Mongo. + */ +class MongoPersistenceTest extends BaseIntegrationV2TestCase +{ + protected function validateEnvironment(): void + { + } + + protected function createAdapter(): AdapterInterface + { + $rootPath = dirname(__DIR__, 3); + (new EnvironmentLoader($rootPath))->load(); + $config = new EnvironmentConfig($rootPath); + $resolver = new DatabaseResolver($config); + return $resolver->resolve('mongo.main', true); + } + + protected function setUp(): void + { + parent::setUp(); + if (!$this->adapter->isConnected()) { + $this->fail('Mongo adapter (mongo.main) failed to connect.'); + } + } + + public function testPersistenceAcrossInstances(): void + { + $ip = '10.0.0.7'; + $subject = 'user_mongo_persist_' . bin2hex(random_bytes(4)); + + // Instance 1 + $guard1 = new MongoSecurityGuard($this->adapter, $this->identifierStrategy); + + // Clear State + $guard1->unblock($ip, $subject); + $guard1->resetAttempts($ip, $subject); + + // Record Failure on Guard 1 + $attempt = new LoginAttemptDTO( + ip: $ip, + subject: $subject, + occurredAt: time(), + resetAfter: 60 + ); + $count = $guard1->recordFailure($attempt); + $this->assertSame(1, $count); + + // Instance 2 + $guard2 = new MongoSecurityGuard($this->adapter, $this->identifierStrategy); + + // Guard 2 should see the failure (count should increment to 2) + $count2 = $guard2->recordFailure($attempt); + $this->assertSame(2, $count2, 'Guard 2 should see previous attempts and increment count to 2'); + + // Block on Guard 2 + $blockDTO = new SecurityBlockDTO( + ip: $ip, + subject: $subject, + type: BlockTypeEnum::ADMIN_BLOCK, + expiresAt: time() + 600, + createdAt: time() + ); + $guard2->block($blockDTO); + + // Guard 1 should see the block + $this->assertTrue($guard1->isBlocked($ip, $subject), 'Guard 1 should reflect block applied by Guard 2'); + + $activeBlock = $guard1->getActiveBlock($ip, $subject); + $this->assertNotNull($activeBlock); + $this->assertSame(BlockTypeEnum::ADMIN_BLOCK, $activeBlock->type); + + // Cleanup + $guard1->unblock($ip, $subject); + } +} From 2c295c48cfe401b8050bce22cd9ab213ec59cfb0 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 11:37:24 +0000 Subject: [PATCH 2/2] fix: Protocol compliance - Revert phase-output.json and remove unauthorized docs - Reverted phase-output.json to original state (removed invalid changes). - Deleted unauthorized docs/phases/README.phaseA5.md. - Retained valid Mongo integration tests and duplicate namespace fix in MongoSecurityGuard.php. --- docs/phases/README.phaseA5.md | 23 -- phase-output.json | 453 +++++++++++++++++++++++++++++++++- 2 files changed, 440 insertions(+), 36 deletions(-) delete mode 100644 docs/phases/README.phaseA5.md diff --git a/docs/phases/README.phaseA5.md b/docs/phases/README.phaseA5.md deleted file mode 100644 index 7b25d86..0000000 --- a/docs/phases/README.phaseA5.md +++ /dev/null @@ -1,23 +0,0 @@ -# Phase IntegrationV2 — A5 (Mongo) - -**Status:** Completed -**Date:** 2025-02-24 - -## Description -Implementation of Mongo Integration V2 tests to ensure `MongoSecurityGuard` correctly interacts with a real MongoDB database via the `DatabaseResolver` and `AdapterInterface`. - -## Changes -- **New Tests:** `tests/IntegrationV2/Mongo/` - - `MongoIntegrationFlowTest.php`: Verifies full block/unblock flow. - - `MongoPersistenceTest.php`: Verifies state sharing across guard instances. -- **Bug Fix:** Fixed duplicate namespace declaration in `src/Drivers/Mongo/MongoSecurityGuard.php`. - -## Verification -- Tests use `DatabaseResolver` to fetch `mongo.main` adapter. -- Tests fail explicitly if adapter is not connected. -- Tests use `BaseIntegrationV2TestCase` for consistent environment handling. -- Tests verified to be syntactically correct and type-safe (PHP 8.4+, strict types). - -## Notes -- Strict mode enforced: no mocks, no fakes, real adapters only. -- Persistence tested across instances to simulate stateless PHP requests. diff --git a/phase-output.json b/phase-output.json index 91a7001..83742c1 100644 --- a/phase-output.json +++ b/phase-output.json @@ -1,15 +1,442 @@ { - "summary": "Implemented Mongo Integration V2 tests and fixed source bug", - "status": "completed", - "phases": [ - "IntegrationV2 — A5 (Mongo)" - ], - "changes": [ - "tests/IntegrationV2/Mongo/MongoIntegrationFlowTest.php", - "tests/IntegrationV2/Mongo/MongoPersistenceTest.php", - "src/Drivers/Mongo/MongoSecurityGuard.php", - "docs/phases/README.phaseA5.md" - ], - "coverage": "IntegrationV2/Mongo", - "documentation": "docs/phases/README.phaseA5.md" + "signature_schema_version": "2.0", + "project": "maatify/security-guard", + "generated_at": "2025-12-08T16:45:00+02:00", + "phases": [ + { + "phase_id": "phase1", + "title": "Environment Setup", + "version": "1.0.0", + "status": "completed", + "date": "2025-12-01", + "summary": "Initial environment setup including Composer initialization, autoloading configuration, PHPUnit bootstrap, and documentation scaffolding.", + "changes": { + "added": [ + "composer.json", + ".env.example", + "tests/bootstrap.php", + "phpunit.xml.dist", + "README.md", + "docs/README.full.md" + ], + "updated": [], + "removed": [] + }, + "tests_result": { + "fake": "passed", + "real": "not_applicable" + }, + "coverage": "not_applicable", + "documentation_files": [ + "README.md", + "docs/README.full.md" + ], + "reflection": { + "mode": "class-index", + "affected_classes": [] + }, + "examples": { + "present": false, + "reason": "Phase 1 initializes project environment and infrastructure; no application logic or classes exist yet." + } + }, + { + "phase_id": "phase2", + "title": "Core Architecture & DTOs", + "version": "1.0.1", + "status": "completed", + "date": "2025-12-08", + "summary": "Introduced immutable DTOs, BlockTypeEnum, and the unified SecurityGuardDriverInterface contract.", + "changes": { + "added": [ + "src/DTO/LoginAttemptDTO.php", + "src/DTO/SecurityBlockDTO.php", + "src/Enums/BlockTypeEnum.php", + "src/Contracts/SecurityGuardDriverInterface.php", + "tests/DTO/LoginAttemptDTOTest.php", + "tests/DTO/SecurityBlockDTOTest.php", + "tests/DTO/BlockTypeEnumTest.php", + "tests/Contracts/SecurityGuardDriverInterfaceTest.php", + "docs/phases/README.phase2.md" + ], + "updated": [ + "api-map.json", + "docs/README.full.md", + "README.md", + "CHANGELOG.md" + ], + "removed": [] + }, + "tests_result": { + "fake": "passed", + "real": "not_applicable" + }, + "coverage": "100%", + "documentation_files": [ + "docs/phases/README.phase2.md", + "docs/README.full.md", + "README.md", + "CHANGELOG.md" + ], + "reflection": { + "mode": "class-index", + "affected_classes": [ + { + "class": "Maatify\\SecurityGuard\\DTO\\LoginAttemptDTO", + "methods_changed": [ + "__construct", + "now", + "jsonSerialize" + ] + }, + { + "class": "Maatify\\SecurityGuard\\DTO\\SecurityBlockDTO", + "methods_changed": [ + "__construct", + "getRemainingSeconds", + "isExpired", + "jsonSerialize" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Enums\\BlockTypeEnum", + "methods_changed": [] + }, + { + "class": "Maatify\\SecurityGuard\\Contracts\\SecurityGuardDriverInterface", + "methods_changed": [ + "recordFailure", + "resetAttempts", + "getActiveBlock", + "getRemainingBlockSeconds", + "block", + "unblock", + "cleanup", + "getStats", + "isBlocked" + ] + } + ] + }, + "examples": { + "present": false, + "reason": "DTOs and interfaces do not require runnable examples." + } + }, + { + "phase_id": "phase3", + "title": "Unified Driver Implementations", + "version": "1.0.2", + "status": "completed", + "date": "2025-12-09", + "summary": "Implemented all real storage drivers using maatify/data-adapters only. Added service layer and resolver. First full working engine.", + "changes": { + "added": [ + "src/Drivers/AbstractSecurityGuardDriver.php", + "src/Drivers/Support/RedisClientProxy.php", + "src/Drivers/RedisSecurityGuard.php", + "src/Drivers/MySQL/MySQLSecurityGuard.php", + "src/Drivers/MySQL/PdoMySQLDriver.php", + "src/Drivers/MySQL/DbalMySQLDriver.php", + "src/Drivers/MySQL/Contracts/MySQLDriverInterface.php", + "src/Drivers/Mongo/MongoSecurityGuard.php", + "src/Identifier/Contracts/IdentifierStrategyInterface.php", + "src/Identifier/DefaultIdentifierStrategy.php", + "src/Resolver/SecurityGuardResolver.php", + "src/Service/SecurityGuardService.php" + ], + "updated": [ + "src/DTO/LoginAttemptDTO.php", + "src/DTO/SecurityBlockDTO.php" + ], + "removed": [] + }, + "tests_result": { + "fake": "passed", + "real": "passed" + }, + "coverage": "92%", + "documentation_files": [ + "docs/phases/README.phase3.md" + ], + "reflection": { + "mode": "class-index", + "affected_classes": [ + { + "class": "Maatify\\SecurityGuard\\Drivers\\AbstractSecurityGuardDriver", + "methods_changed": [ + "makeIdentifier", + "encodeBlock", + "decodeBlock", + "now" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Drivers\\MySQL\\Contracts\\MySQLDriverInterface", + "methods_changed": [ + "recordFailure", + "resetAttempts", + "getActiveBlock", + "getRemainingBlockSeconds", + "block", + "unblock", + "cleanup", + "getStats" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Drivers\\MySQL\\PdoMySQLDriver", + "methods_changed": [ + "__construct", + "recordFailure", + "resetAttempts", + "getActiveBlock", + "getRemainingBlockSeconds", + "block", + "unblock", + "cleanup", + "getStats" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Drivers\\MySQL\\DbalMySQLDriver", + "methods_changed": [ + "__construct", + "recordFailure", + "resetAttempts", + "getActiveBlock", + "getRemainingBlockSeconds", + "block", + "unblock", + "cleanup", + "getStats" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Drivers\\MySQL\\MySQLSecurityGuard", + "methods_changed": [ + "__construct", + "doRecordFailure", + "doResetAttempts", + "doGetActiveBlock", + "doGetRemainingBlockSeconds", + "doBlock", + "doUnblock", + "doCleanup", + "doGetStats" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Drivers\\Mongo\\MongoSecurityGuard", + "methods_changed": [ + "__construct", + "doRecordFailure", + "doResetAttempts", + "doGetActiveBlock", + "doGetRemainingBlockSeconds", + "doBlock", + "doUnblock", + "doCleanup", + "doGetStats" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Drivers\\Support\\RedisClientProxy", + "methods_changed": [ + "__construct", + "incr", + "hGet", + "hSet", + "hDel", + "hGetAll", + "hMSet", + "expire", + "ttl", + "del", + "info" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Identifier\\DefaultIdentifierStrategy", + "methods_changed": [ + "makeId" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Resolver\\SecurityGuardResolver", + "methods_changed": [ + "resolve" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Service\\SecurityGuardService", + "methods_changed": [ + "__construct", + "recordFailure", + "resetAttempts", + "getActiveBlock", + "isBlocked", + "getRemainingBlockSeconds", + "block", + "unblock", + "cleanup", + "getStats" + ] + } + ] + } + }, + { + "phase_id": "phase4", + "title": "Unified Event System Integration", + "version": "1.0.3", + "status": "completed", + "date": "2025-12-10", + "summary": "Integrated full Security Event System including DTOs, dispatchers, listener interface and event emission across the engine.", + "changes": { + "added": [ + "src/DTO/SecurityEventDTO.php", + "src/Event/SecurityEventFactory.php", + "src/Event/SecurityAction.php", + "src/Event/SecurityPlatform.php", + "src/Event/Contracts/EventDispatcherInterface.php", + "src/Event/Contracts/EventListenerInterface.php", + "src/Event/Dispatcher/SyncDispatcher.php", + "src/Event/Dispatcher/PsrLoggerDispatcher.php", + "src/Event/Dispatcher/NullDispatcher.php", + "src/Enums/SecurityActionEnum.php", + "src/Enums/SecurityEventTypeEnum.php", + "src/Enums/SecurityPlatformEnum.php" + ], + "updated": [ + "src/Service/SecurityGuardService.php", + "src/DTO/LoginAttemptDTO.php", + "src/DTO/SecurityBlockDTO.php", + "docs/README.full.md", + "examples/Examples.md", + "docs/phases/README.phase4.md" + ], + "removed": [] + }, + "tests_result": { + "fake": "pending", + "real": "pending" + }, + "coverage": "pending", + "documentation_files": [ + "docs/phases/README.phase4.md", + "docs/README.full.md" + ], + "commit_metadata": { + "type": "feat", + "scope": "event-system", + "message": "feat: add unified security event system with DTOs, dispatchers, listeners, and service integration", + "breaking": false + }, + "git_patch": { + "generated": true, + "filename": "phase4.patch", + "format": "unified" + }, + "reflection": { + "mode": "class-index", + "affected_classes": [ + { + "class": "Maatify\\SecurityGuard\\DTO\\LoginAttemptDTO", + "methods_changed": [ + "toEvent" + ] + }, + { + "class": "Maatify\\SecurityGuard\\DTO\\SecurityBlockDTO", + "methods_changed": [ + "toCreatedEvent", + "toRemovedEvent" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Service\\SecurityGuardService", + "methods_changed": [ + "setEventDispatcher", + "dispatchEvent" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Event\\SecurityEventFactory", + "methods_changed": [ + "fromLoginAttempt", + "blockCreated", + "blockRemoved", + "cleanup", + "custom" + ] + } + ] + } + }, + { + "phase_id": "phase5", + "title": "High-Level Logic & Auto-Blocking Engine", + "version": "1.0.4", + "status": "completed", + "date": "2025-12-12", + "summary": "Added the first high-level security logic layer including handleAttempt(), dynamic SecurityConfig usage, getConfig(), AUTO blocking, success-reset logic, remaining-block reporting, and unified high-level event emission.", + "changes": { + "added": [ + "src/Config/SecurityConfig.php", + "src/Config/SecurityConfigLoader.php", + "src/Enums/BlockTypeEnum.php (AUTO case)" + ], + "updated": [ + "src/Service/SecurityGuardService.php", + "docs/README.full.md", + "docs/phases/README.phase5.md", + "README.md" + ], + "removed": [] + }, + "tests_result": { + "fake": "pending", + "real": "pending" + }, + "coverage": "pending", + "documentation_files": [ + "docs/phases/README.phase5.md", + "docs/README.full.md", + "README.md" + ], + "commit_metadata": { + "type": "feat", + "scope": "high-level-logic", + "message": "feat: introduce high-level security engine logic with auto-blocking, unified login attempt handling, runtime SecurityConfig, and config accessors", + "breaking": false + }, + "git_patch": { + "generated": true, + "filename": "phase5.patch", + "format": "unified" + }, + "reflection": { + "mode": "class-index", + "affected_classes": [ + { + "class": "Maatify\\SecurityGuard\\Service\\SecurityGuardService", + "methods_changed": [ + "setConfig", + "getConfig", + "handleAttempt", + "handleEvent", + "dispatchEvent" + ] + }, + { + "class": "Maatify\\SecurityGuard\\Enums\\BlockTypeEnum", + "methods_changed": [ + "AUTO (new enum case)" + ] + } + ] + } + } + ] }