- Module path: dappco.re/go/agent - Core import: dappco.re/go/core v0.4.7 - Process service re-enabled with new Core API - Plugin bumped to v0.11.0 - Directory flattened from go/ to root Co-Authored-By: Virgil <virgil@lethean.io>
248 lines
6.6 KiB
Markdown
248 lines
6.6 KiB
Markdown
# Production Push Polish Template
|
|
|
|
**Use when:** Preparing a codebase for production deployment after feature development is complete.
|
|
|
|
**Purpose:** Ensure all routes work correctly, render meaningful content, handle errors gracefully, and meet security/performance standards.
|
|
|
|
---
|
|
|
|
## How to Request This Task
|
|
|
|
When asking an agent to create a prod push polish task, include:
|
|
|
|
```
|
|
Create a production push polish task following the template at:
|
|
resources/plan-templates/prod-push-polish.md
|
|
|
|
Focus areas: [list any specific concerns]
|
|
Target deployment date: [date if applicable]
|
|
```
|
|
|
|
---
|
|
|
|
## Task Structure
|
|
|
|
### Phase 1: Public Route Tests
|
|
|
|
Every public route must have a test that:
|
|
1. Asserts HTTP 200 OK status
|
|
2. Asserts meaningful HTML content renders (title, headings, key elements)
|
|
3. Does NOT just use `assertOk()` alone
|
|
|
|
**Pattern:**
|
|
```php
|
|
it('renders [page name] with [key content]', function () {
|
|
$this->get('/route')
|
|
->assertOk()
|
|
->assertSee('Expected heading')
|
|
->assertSee('Expected content')
|
|
->assertSee('Expected CTA');
|
|
});
|
|
```
|
|
|
|
**Why:** A page can return 200 with blank body, PHP errors, or broken layout. Content assertions catch these.
|
|
|
|
### Phase 2: Authenticated Route Tests
|
|
|
|
Every authenticated route must have a test that:
|
|
1. Uses `actingAs()` with appropriate user type
|
|
2. Asserts the Livewire component renders
|
|
3. Asserts key UI elements are present
|
|
|
|
**Pattern:**
|
|
```php
|
|
it('renders [page name] for authenticated user', function () {
|
|
$this->actingAs($this->user)
|
|
->get('/hub/route')
|
|
->assertOk()
|
|
->assertSeeLivewire('component.name')
|
|
->assertSee('Expected heading')
|
|
->assertSee('Expected widget');
|
|
});
|
|
```
|
|
|
|
### Phase 3: Error Page Verification
|
|
|
|
Error pages must:
|
|
1. Use consistent brand styling (not default Laravel)
|
|
2. Provide helpful messages
|
|
3. Include navigation back to safe pages
|
|
4. Not expose stack traces in production
|
|
|
|
**Test pattern:**
|
|
```php
|
|
it('renders 404 with helpful message', function () {
|
|
$this->get('/nonexistent-route')
|
|
->assertNotFound()
|
|
->assertSee('Page not found')
|
|
->assertSee('Go to homepage')
|
|
->assertDontSee('Exception');
|
|
});
|
|
```
|
|
|
|
### Phase 4: Security Headers
|
|
|
|
Verify these headers are present on all responses:
|
|
|
|
| Header | Value | Purpose |
|
|
|--------|-------|---------|
|
|
| `X-Frame-Options` | `DENY` or `SAMEORIGIN` | Prevent clickjacking |
|
|
| `X-Content-Type-Options` | `nosniff` | Prevent MIME sniffing |
|
|
| `Referrer-Policy` | `strict-origin-when-cross-origin` | Control referrer info |
|
|
| `Content-Security-Policy` | (varies) | Prevent XSS |
|
|
| `X-Powered-By` | (removed) | Don't expose stack |
|
|
|
|
**Middleware pattern:**
|
|
```php
|
|
class SecurityHeaders
|
|
{
|
|
public function handle(Request $request, Closure $next): Response
|
|
{
|
|
$response = $next($request);
|
|
|
|
$response->headers->set('X-Frame-Options', 'DENY');
|
|
$response->headers->set('X-Content-Type-Options', 'nosniff');
|
|
$response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
$response->headers->remove('X-Powered-By');
|
|
|
|
return $response;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Phase 5: Performance Baseline
|
|
|
|
Document response times for key routes:
|
|
|
|
| Route Type | Target | Acceptable | Needs Investigation |
|
|
|------------|--------|------------|---------------------|
|
|
| Static marketing | <200ms | <400ms | >600ms |
|
|
| Dynamic public | <300ms | <500ms | >800ms |
|
|
| Authenticated dashboard | <500ms | <800ms | >1200ms |
|
|
| Data-heavy pages | <800ms | <1200ms | >2000ms |
|
|
|
|
**Test pattern:**
|
|
```php
|
|
it('responds within performance target', function () {
|
|
$start = microtime(true);
|
|
|
|
$this->get('/');
|
|
|
|
$duration = (microtime(true) - $start) * 1000;
|
|
|
|
expect($duration)->toBeLessThan(400); // ms
|
|
});
|
|
```
|
|
|
|
**N+1 detection:**
|
|
```php
|
|
it('has no N+1 queries on listing page', function () {
|
|
DB::enableQueryLog();
|
|
|
|
$this->get('/hub/social/posts');
|
|
|
|
$queries = DB::getQueryLog();
|
|
|
|
// With 10 posts, should be ~3 queries (posts, accounts, user)
|
|
// not 10+ (one per post)
|
|
expect(count($queries))->toBeLessThan(10);
|
|
});
|
|
```
|
|
|
|
### Phase 6: Final Verification
|
|
|
|
Pre-deployment checklist:
|
|
|
|
- [ ] `./vendor/bin/pest` — 0 failures
|
|
- [ ] `npm run build` — 0 errors
|
|
- [ ] `npm run test:smoke` — Playwright passes
|
|
- [ ] Error pages reviewed manually
|
|
- [ ] Security headers verified via browser dev tools
|
|
- [ ] Performance baselines documented
|
|
|
|
---
|
|
|
|
## Acceptance Criteria Template
|
|
|
|
Copy and customise for your task:
|
|
|
|
```markdown
|
|
### Phase 1: Public Route Tests
|
|
- [ ] AC1: Test for `/` asserts page title and hero content
|
|
- [ ] AC2: Test for `/pricing` asserts pricing tiers display
|
|
- [ ] AC3: Test for `/login` asserts form fields render
|
|
[Add one AC per route]
|
|
|
|
### Phase 2: Authenticated Route Tests
|
|
- [ ] AC4: Test for `/hub` asserts dashboard widgets render
|
|
- [ ] AC5: Test for `/hub/profile` asserts form with user data
|
|
[Add one AC per authenticated route]
|
|
|
|
### Phase 3: Error Page Verification
|
|
- [ ] AC6: 404 page renders with brand styling
|
|
- [ ] AC7: 403 page renders with access denied message
|
|
- [ ] AC8: 500 page renders without stack trace
|
|
|
|
### Phase 4: Security Headers
|
|
- [ ] AC9: X-Frame-Options header present
|
|
- [ ] AC10: X-Content-Type-Options header present
|
|
- [ ] AC11: Referrer-Policy header present
|
|
- [ ] AC12: X-Powered-By header removed
|
|
|
|
### Phase 5: Performance Baseline
|
|
- [ ] AC13: Homepage <400ms response time
|
|
- [ ] AC14: No N+1 queries on listing pages
|
|
- [ ] AC15: Performance baselines documented
|
|
|
|
### Phase 6: Final Verification
|
|
- [ ] AC16: Full test suite passes
|
|
- [ ] AC17: Build completes without errors
|
|
- [ ] AC18: Smoke tests pass
|
|
```
|
|
|
|
---
|
|
|
|
## Common Issues to Check
|
|
|
|
### Blank Pages
|
|
- Missing `return` in controller
|
|
- Livewire component `render()` returns nothing
|
|
- Blade `@extends` pointing to missing layout
|
|
|
|
### Broken Layouts
|
|
- Missing Flux UI components
|
|
- CSS not loaded (Vite build issue)
|
|
- Alpine.js not initialised
|
|
|
|
### Authentication Redirects
|
|
- Middleware order incorrect
|
|
- Session not persisting
|
|
- CSRF token mismatch
|
|
|
|
### Performance Problems
|
|
- Eager loading missing (N+1)
|
|
- Large datasets not paginated
|
|
- Expensive queries in loops
|
|
- Missing database indexes
|
|
|
|
### Security Gaps
|
|
- Debug mode enabled in production
|
|
- Sensitive data in logs
|
|
- Missing CSRF protection
|
|
- Exposed .env or config values
|
|
|
|
---
|
|
|
|
## File Locations
|
|
|
|
| Purpose | Location |
|
|
|---------|----------|
|
|
| Route tests | `tests/Feature/PublicRoutesTest.php`, `tests/Feature/HubRoutesTest.php` |
|
|
| Error pages | `resources/views/errors/` |
|
|
| Security middleware | `app/Http/Middleware/SecurityHeaders.php` |
|
|
| Performance tests | `tests/Feature/PerformanceBaselineTest.php` |
|
|
| Smoke tests | `tests/Browser/smoke/` |
|
|
|
|
---
|
|
|
|
*This template ensures production deployments don't ship broken pages.*
|