-
Notifications
You must be signed in to change notification settings - Fork 0
🔐 Password Reset Feature (Production Test Phase 1) #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Features: - Password reset request endpoint with email enumeration protection - Password reset confirmation with token validation - Rate-limiting on both endpoints (5/hour) to prevent brute-force - Token expiry (60 minutes) and one-time use enforcement - Secure token hashing (bcrypt) in database Implementation: - TDD approach: 13 tests, 44 assertions, 100% passing - Security: Rate-limiting, token hashing, email enumeration protection - Validation: Email format, password requirements (min 8 chars, confirmed) - Edge cases: Expired tokens, invalid tokens, one-time use Tests: - tests/Feature/Auth/PasswordResetRequestTest.php (5 tests) - tests/Feature/Auth/PasswordResetTest.php (8 tests) - All logout tests passing (5 tests) Technical Debt: - Fixed PHPStan Sanctum type inference issue (see ISSUE_PHPSTAN_SANCTUM_TYPES.md) - Documented workaround with explicit type hints - Issue tracked for upstream resolution Factory: - database/factories/PersonFactory.php with TenantKey auto-generation - GDPR-compliant encryption pattern (email_plain → email_enc) Documentation: - docs/PRODUCTION_TEST_PASSWORD_RESET.md - comprehensive test report - docs/ISSUE_PHPSTAN_SANCTUM_TYPES.md - technical debt tracking - Discovered 7 critical documentation gaps (see production test report) Security Review: ✅ Rate-limiting (5 attempts/hour) ✅ Token hashing (bcrypt) ✅ Email enumeration protection ✅ Token expiry (60 min) ✅ One-time use ✅ Password validation ✅ PHPStan lint-free Discovered Violations (Production Test): 1. DDEV environment undocumented 2. GDPR encryption patterns missing 3. Pest-only policy unclear 4. User vs Person model confusion 5. Tenant encryption complexity undocumented 6. Carbon diffInMinutes() gotcha 7. Rate-limiting missing (security vulnerability - FIXED) Related: - Branch: docs/add-ddev-and-encryption-patterns (documentation PR) - Follows TDD methodology (RED → GREEN → REFACTOR) - Adheres to 'leave code better than found' principle
💡 Tip: Consider Using Draft PRsBenefits of opening PRs as drafts initially:
How to convert:
This is just a friendly reminder - feel free to continue as is! 😊 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a complete password reset feature using Test-Driven Development (TDD), adding request and reset endpoints with comprehensive security measures. The implementation follows Laravel best practices and includes rate limiting, token expiry, and email enumeration protection.
Key Changes:
- Added password reset request and confirmation endpoints with rate limiting
- Created comprehensive test coverage (13 tests covering happy paths, security, and edge cases)
- Updated documentation with production test report, PHPStan workaround, and Copilot reminder patterns
- Added PersonFactory with encryption-aware setup for testing
- Simplified boost.json configuration by removing duplicated guidelines
Reviewed Changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Feature/Auth/PasswordResetTest.php | Comprehensive tests for password reset confirmation endpoint (8 tests) |
| tests/Feature/Auth/PasswordResetRequestTest.php | Tests for password reset request endpoint (5 tests) |
| app/Http/Controllers/AuthController.php | Implements passwordResetRequest() and passwordReset() methods |
| routes/api.php | Adds two new authenticated routes with rate limiting middleware |
| database/factories/PersonFactory.php | Factory with encryption and tenant key setup |
| app/Models/Person.php | Adds HasFactory trait and PHPDoc annotations |
| docs/PRODUCTION_TEST_PASSWORD_RESET.md | Detailed production test report |
| docs/ISSUE_PHPSTAN_SANCTUM_TYPES.md | Documents PHPStan workaround for Sanctum types |
| docs/COPILOT_REMINDER_PATTERNS.md | Developer reminders for core principles |
| DEVELOPMENT.md | Adds core principles section referencing Copilot patterns |
| .github/copilot-instructions.md | Updates Laravel Boost guidelines and test enforcement |
| boost.json | Simplifies configuration by removing redundant guidelines |
- Convert PasswordResetTest.php from PHPUnit to Pest functional syntax - Convert PasswordResetRequestTest.php from PHPUnit to Pest functional syntax - Fix Laravel code style: if (!x) to if (! x) - Fix rate-limit comments: per hour to per 60 minutes - Remove note_enc from PersonFactory (encryption handled by model) - Remove withPassword() from PersonFactory (Person has no password field) - Use assertOk() instead of assertStatus(200) - Use collect()->each() for cleaner loop testing Addresses Copilot PR review comments on #74
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.
- Remove unused Log import from AuthController - Fix token length consistency (64 chars everywhere) - Delete .bak backup file (should not be committed) - Fix Pint code style issues (spacing, imports, PHPDoc)
- Create PasswordResetRequestRequest for /auth/password/reset-request - Create PasswordResetRequest for /auth/password/reset - Update AuthController to use Form Requests (following TokenRequest pattern) - Addresses Copilot review feedback about inline validation
Root cause analysis shows agent missed issues because: 1. Self-review only checked "tests pass", not "matches patterns" 2. Quality tools (Pint, PHPStan) not run locally before commit 3. No comparison with existing code patterns 4. No cleanup step for temporary files This checklist addresses all gaps with: - Phase 1: Functional review (tests, linters) - Phase 2: Pattern review (compare with existing code) - Phase 3: Cleanup review (unused imports, temp files) - Phase 4: Consistency check (before writing new code) - Phase 5: Pre-commit final check Includes examples and common mistakes to avoid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 8 comments.
- Add blank lines around fenced code blocks in list items - Fixes 5 MD031/blanks-around-fences violations
- Add @var annotation for PasswordResetRequest validated array - Fixes PHPStan argument.type errors for Hash::check() and Hash::make() - Form Request validated() returns generic array, needs explicit typing
- Extract PASSWORD_RESET_EXPIRY constant (60 minutes) - Define named rate limiter 'password-reset' (5 per 60min) - Simplify diffInMinutes() without abs() - Cache TenantKey in PersonFactory to prevent N+1 - Add comment to empty boost.json guidelines array - All changes follow Self-Review Checklist Phase 5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
💡 Tip: Consider Using Draft PRsBenefits of opening PRs as drafts initially:
How to convert:
This is just a friendly reminder - feel free to continue as is! 😊 |
…n into automation SPDX-FileCopyrightText: 2025 SecPal SPDX-License-Identifier: AGPL-3.0-or-later WHY: Critical learnings from PR #74 were documented in SELF_REVIEW_CHECKLIST.md but NOT integrated into automated quality gates. This created a gap where the same Pint false-confidence issue could happen again. WHAT CHANGED: 1. scripts/preflight.sh - Pint Workflow (CRITICAL FIX): - OLD: Only runs "pint --dirty" (auto-fix) - NEW: Runs "pint --test --dirty" → "pint --dirty" → "pint --test --dirty" - Matches documented workflow from SELF_REVIEW_CHECKLIST.md - Ensures CI parity (CI uses --test flag) - Prevents false confidence from auto-fix hiding issues 2. .pre-commit-config.yaml - Add Pint Hook: - Added local hook for Laravel Pint with --dirty flag - Auto-fixes code style on commit - Works in tandem with preflight.sh verification 3. scripts/preflight.sh - CHANGELOG Validation: - Checks for [Unreleased] section on feature/fix/refactor branches - Warns if section is empty - Exempts docs/* and chore/* branches - Enforces org-wide CHANGELOG policy automatically IMPACT: - Prevents PR #74 Pint issue from recurring (auto-fix masking problems) - Reduces reliance on AI/human discipline - Enforces CHANGELOG updates before push - All documented best practices now automated TESTING: Ran ./scripts/preflight.sh successfully: - Pint check-fix-verify workflow executed correctly - All 127 tests passing - CHANGELOG validation working
…n into automation SPDX-FileCopyrightText: 2025 SecPal SPDX-License-Identifier: AGPL-3.0-or-later WHY: Critical learnings from PR #74 were documented in SELF_REVIEW_CHECKLIST.md but NOT integrated into automated quality gates. This created a gap where the same Pint false-confidence issue could happen again. WHAT CHANGED: 1. scripts/preflight.sh - Pint Workflow (CRITICAL FIX): - OLD: Only runs "pint --dirty" (auto-fix) - NEW: Runs "pint --test --dirty" → "pint --dirty" → "pint --test --dirty" - Matches documented workflow from SELF_REVIEW_CHECKLIST.md - Ensures CI parity (CI uses --test flag) - Prevents false confidence from auto-fix hiding issues 2. .pre-commit-config.yaml - Add Pint Hook: - Added local hook for Laravel Pint with --dirty flag - Auto-fixes code style on commit - Works in tandem with preflight.sh verification 3. scripts/preflight.sh - CHANGELOG Validation: - Checks for [Unreleased] section on feature/fix/refactor branches - Warns if section is empty - Exempts docs/* and chore/* branches - Enforces org-wide CHANGELOG policy automatically IMPACT: - Prevents PR #74 Pint issue from recurring (auto-fix masking problems) - Reduces reliance on AI/human discipline - Enforces CHANGELOG updates before push - All documented best practices now automated TESTING: Ran ./scripts/preflight.sh successfully: - Pint check-fix-verify workflow executed correctly - All 127 tests passing - CHANGELOG validation working
* feat(quality): integrate Pint --test workflow and CHANGELOG validation into automation SPDX-FileCopyrightText: 2025 SecPal SPDX-License-Identifier: AGPL-3.0-or-later WHY: Critical learnings from PR #74 were documented in SELF_REVIEW_CHECKLIST.md but NOT integrated into automated quality gates. This created a gap where the same Pint false-confidence issue could happen again. WHAT CHANGED: 1. scripts/preflight.sh - Pint Workflow (CRITICAL FIX): - OLD: Only runs "pint --dirty" (auto-fix) - NEW: Runs "pint --test --dirty" → "pint --dirty" → "pint --test --dirty" - Matches documented workflow from SELF_REVIEW_CHECKLIST.md - Ensures CI parity (CI uses --test flag) - Prevents false confidence from auto-fix hiding issues 2. .pre-commit-config.yaml - Add Pint Hook: - Added local hook for Laravel Pint with --dirty flag - Auto-fixes code style on commit - Works in tandem with preflight.sh verification 3. scripts/preflight.sh - CHANGELOG Validation: - Checks for [Unreleased] section on feature/fix/refactor branches - Warns if section is empty - Exempts docs/* and chore/* branches - Enforces org-wide CHANGELOG policy automatically IMPACT: - Prevents PR #74 Pint issue from recurring (auto-fix masking problems) - Reduces reliance on AI/human discipline - Enforces CHANGELOG updates before push - All documented best practices now automated TESTING: Ran ./scripts/preflight.sh successfully: - Pint check-fix-verify workflow executed correctly - All 127 tests passing - CHANGELOG validation working * refactor: improve CHANGELOG validation robustness (Copilot feedback) SPDX-FileCopyrightText: 2025 SecPal SPDX-License-Identifier: AGPL-3.0-or-later Address 3 Copilot review comments on PR #77: 1. Magic number 3 → MIN_CHANGELOG_LINES variable with comment 2. Hardcoded branch pattern → CHANGELOG_EXEMPT_PREFIXES config 3. Fragile sed/grep → Robust line-number-based extraction Changes: - Extract config variables to top of CHANGELOG validation block - Add ci/* and test/* to exempt branch prefixes - Rewrite content extraction to handle [Unreleased] as last section - Update CHANGELOG.md with new features from this PR
🔐 Password Reset Feature (Production Test Phase 1)
Implements password reset functionality with TDD methodology and security best practices.
📊 Production Test Results
See full report:
docs/PRODUCTION_TEST_PASSWORD_RESET.md✨ Features
🧪 Tests (13 passing)
tests/Feature/Auth/PasswordResetRequestTest.php(5 tests)tests/Feature/Auth/PasswordResetTest.php(8 tests)🔒 Security
📝 Documentation
docs/PRODUCTION_TEST_PASSWORD_RESET.mddocs/ISSUE_PHPSTAN_SANCTUM_TYPES.mddocs/COPILOT_REMINDER_PATTERNS.md🔗 Related PRs
docs/add-ddev-and-encryption-patterns📦 Review Strategy (Large PR: 1087 lines)
docs/PRODUCTION_TEST_PASSWORD_RESET.mdfirst (270 lines) - comprehensive context✅ Quality Checks