Files
michaelschiemer/docs/claude/chips-cookies.md
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

466 lines
11 KiB
Markdown

# CHIPS Cookies (Cookies Having Independent Partitioned State)
CHIPS Cookie-Unterstützung im Custom PHP Framework für datenschutzfreundliche Third-Party-Cookies.
## Übersicht
CHIPS (Cookies Having Independent Partitioned State) ist ein Browser-Security-Feature, das Third-Party-Cookies **pro Top-Level-Site partitioniert**, um Cross-Site-Tracking zu verhindern.
**Browser-Support**:
- Chrome 114+
- Edge 114+
- Opera 100+
- Safari 16.4+ (partial)
## Was ist CHIPS?
### Problem: Traditional Third-Party Cookies
```
Widget embedded on example.com: cookie=user123
Same widget on test.com: cookie=user123 (SAME COOKIE!)
→ Cross-Site-Tracking möglich
```
### Lösung: CHIPS Partitioned Cookies
```
Widget embedded on example.com: cookie=user123_site_A
Same widget on test.com: cookie=user456_site_B (DIFFERENT!)
→ Kein Cross-Site-Tracking
```
## Requirements
CHIPS Cookies erfordern:
1. **Secure=true** (HTTPS only)
2. **SameSite=None** (Third-Party context)
3. **Partitioned** Attribut
## Verwendung
### CookieService Injection
```php
final readonly class EmbeddedWidgetController
{
public function __construct(
private CookieService $cookieService
) {}
}
```
### Standard Cookie vs. CHIPS Cookie
```php
// ❌ Standard Third-Party Cookie (tracking möglich)
$cookie = $this->cookieService->create(
name: 'analytics',
value: 'user123',
sameSite: SameSite::None,
secure: true
);
// ✅ CHIPS Partitioned Cookie (tracking verhindert)
$cookie = $this->cookieService->createPartitioned(
name: 'analytics',
value: 'user123'
);
```
### Use Case 1: Embedded Chat Widget
```php
#[Route(path: '/widget/chat/init', method: Method::GET)]
public function initChatWidget(HttpRequest $request): JsonResponse
{
$session = $this->chatService->createSession();
// Partitioned session cookie - different per embedding site
$sessionCookie = $this->cookieService->createPartitionedSession(
name: 'chat_session',
value: $session->id,
httpOnly: true
);
// Partitioned state cookie - JavaScript accessible
$stateCookie = $this->cookieService->createPartitioned(
name: 'chat_state',
value: json_encode(['minimized' => false]),
maxAge: Duration::fromDays(7),
httpOnly: false // JS needs access
);
return (new JsonResponse(['session_id' => $session->id]))
->withCookies($sessionCookie, $stateCookie);
}
```
### Use Case 2: Third-Party Analytics
```php
#[Route(path: '/analytics/track', method: Method::POST)]
public function track(HttpRequest $request): JsonResponse
{
$userId = $request->cookies->get('_analytics');
if (!$userId) {
// Create partitioned analytics cookie
$userId = $this->generateUserId();
$cookie = $this->cookieService->createAnalyticsCookie(
userId: $userId,
maxAge: Duration::fromDays(365)
);
return (new JsonResponse(['tracked' => true]))
->withCookie($cookie);
}
$this->analyticsService->track($userId, $request->parsedBody);
return new JsonResponse(['tracked' => true]);
}
```
### Use Case 3: Payment Provider Embed
```php
#[Route(path: '/payment/stripe/embed', method: Method::GET)]
public function embedPaymentForm(HttpRequest $request): ViewResult
{
$checkoutSession = $this->stripeService->createCheckoutSession();
// Partitioned - separate state per merchant site
$sessionCookie = $this->cookieService->createPartitioned(
name: 'stripe_checkout',
value: $checkoutSession->id,
maxAge: Duration::fromMinutes(30),
httpOnly: true
);
return (new ViewResult('payment/stripe-embed', [
'session' => $checkoutSession
]))->withCookie($sessionCookie);
}
```
## CookieService Factory Methods
### Standard Cookies
```php
// Basic cookie
$cookie = $this->cookieService->create(
name: 'session',
value: 'abc123',
maxAge: Duration::fromHours(1),
path: '/',
domain: null,
secure: null, // Auto true in production
httpOnly: true,
sameSite: SameSite::Lax
);
// Session cookie (no expiration)
$cookie = $this->cookieService->createSessionCookie(
name: 'session_id',
value: 'xyz789',
httpOnly: true,
sameSite: SameSite::Lax
);
// Remember-me cookie (30 days default)
$cookie = $this->cookieService->createRememberMeCookie(
value: 'token123',
maxAge: Duration::fromDays(30) // Optional
);
// Delete cookie
$cookie = $this->cookieService->delete('session', path: '/');
```
### CHIPS Partitioned Cookies
```php
// Partitioned cookie
$cookie = $this->cookieService->createPartitioned(
name: 'widget',
value: 'state123',
maxAge: Duration::fromHours(1),
path: '/',
domain: null,
httpOnly: true
);
// Partitioned session cookie
$cookie = $this->cookieService->createPartitionedSession(
name: 'widget_session',
value: 'session123',
httpOnly: true
);
// Partitioned analytics cookie (JS accessible)
$cookie = $this->cookieService->createAnalyticsCookie(
userId: 'user123',
maxAge: Duration::fromDays(365)
);
// Partitioned widget state cookie
$cookie = $this->cookieService->createWidgetStateCookie(
widgetId: 'chat',
state: json_encode(['minimized' => false]),
maxAge: Duration::fromDays(30)
);
```
## Response Integration
### Single Cookie
```php
return (new JsonResponse(['success' => true]))
->withCookie($cookie);
```
### Multiple Cookies
```php
return (new JsonResponse(['success' => true]))
->withCookies($sessionCookie, $stateCookie);
```
## Validation & Helpers
```php
// Validate cookie size (4KB browser limit)
if (!$this->cookieService->validateSize($cookie)) {
throw new \RuntimeException('Cookie exceeds size limit');
}
// Validate cookie name
if (!$this->cookieService->isValidName('user-token')) {
throw new \InvalidArgumentException('Invalid cookie name');
}
```
## Cookie Header Output
### Standard Cookie
```http
Set-Cookie: session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax
```
### CHIPS Partitioned Cookie
```http
Set-Cookie: widget=state123; Path=/; Secure; HttpOnly; SameSite=None; Partitioned
```
## Wann CHIPS verwenden?
### ✅ Use CHIPS für:
1. **Embedded Widgets** - Chat, Support, Social Media embeds
2. **Third-Party Analytics** - Analytics in iframes
3. **Payment Provider Embeds** - Stripe, PayPal checkout forms
4. **OAuth Flows in iframes** - Third-party authentication
5. **Cross-Origin Video Players** - Embedded media players
### ❌ NICHT CHIPS für:
1. **First-Party Session Cookies** - SameSite=Lax reicht
2. **Authentication Cookies** - Nur same-site verwenden
3. **CSRF Tokens** - SameSite=Strict empfohlen
4. **Standard E-Commerce** - First-party cookies ausreichend
## Security Best Practices
### 1. Production Environment
```php
// Secure flag wird in production automatisch gesetzt
$prodEnv = new Environment([EnvKey::APP_ENV->value => 'production']);
$service = new CookieService($prodEnv);
$cookie = $service->create('session', 'value');
// → Secure flag automatisch true in production
```
### 2. HTTPS Required
CHIPS Cookies erfordern HTTPS:
```php
// ✅ Wird in Cookie-Konstruktor validiert
$cookie = new Cookie(
name: 'widget',
value: 'data',
secure: true, // Required
sameSite: SameSite::None, // Required
partitioned: true
);
// ❌ Throws InvalidArgumentException
$cookie = new Cookie(
name: 'widget',
value: 'data',
secure: false, // Invalid!
partitioned: true
);
```
### 3. HttpOnly für Session Cookies
```php
// ✅ HttpOnly für session cookies
$session = $this->cookieService->createPartitionedSession(
name: 'session',
value: 'secret',
httpOnly: true // XSS protection
);
// ❌ Nur wenn JS-Zugriff WIRKLICH notwendig
$widget = $this->cookieService->createPartitioned(
name: 'widget_state',
value: json_encode(['data']),
httpOnly: false // JS accessible
);
```
## Testing
```php
describe('CHIPS Cookie Integration', function () {
it('creates partitioned cookie for widget', function () {
$service = new CookieService($this->environment);
$cookie = $service->createPartitioned(
name: 'widget',
value: 'state123'
);
expect($cookie->partitioned)->toBeTrue();
expect($cookie->secure)->toBeTrue();
expect($cookie->sameSite)->toBe(SameSite::None);
$header = $cookie->toHeaderString();
expect($header)->toContain('Partitioned');
});
});
```
## Framework Integration
### DI Container Initializer
```php
final readonly class CookieServiceInitializer
{
#[Initializer]
public function __invoke(Container $container): CookieService
{
return new CookieService(
environment: $container->get(Environment::class)
);
}
}
```
### Response Trait (Future Enhancement)
```php
trait ResponseWithCookies
{
private array $cookies = [];
public function withCookie(Cookie $cookie): self
{
$new = clone $this;
$new->cookies[] = $cookie;
return $new;
}
public function withCookies(Cookie ...$cookies): self
{
$new = clone $this;
$new->cookies = array_merge($new->cookies, $cookies);
return $new;
}
}
```
## Migration von Standard Third-Party Cookies
### Before (Traditional)
```php
$cookie = new Cookie(
name: 'analytics',
value: 'user123',
secure: true,
sameSite: SameSite::None
);
// Problem: Cross-site tracking möglich
```
### After (CHIPS)
```php
$cookie = $this->cookieService->createPartitioned(
name: 'analytics',
value: 'user123'
);
// Benefit: Privacy-friendly, kein Cross-site tracking
```
## Browser Compatibility Check (Future)
```php
final readonly class ChipsSupportDetector
{
public function supportsChips(UserAgent $userAgent): bool
{
// Chrome/Edge 114+, Safari 16.4+, Opera 100+
return $this->detectBrowserVersion($userAgent);
}
public function getFallbackStrategy(): CookieStrategy
{
// First-party only, localStorage, etc.
return CookieStrategy::FIRST_PARTY_ONLY;
}
}
```
## Troubleshooting
### Cookie wird nicht gesetzt
1. **HTTPS fehlt**: CHIPS erfordert Secure=true → HTTPS
2. **SameSite≠None**: Muss `SameSite::None` sein
3. **Browser-Support**: Prüfe Browser-Version
4. **Cookie-Size**: Max 4KB - nutze `validateSize()`
### Cross-Site funktioniert nicht
1. **Partitioned fehlt**: Nutze `createPartitioned()` statt `create()`
2. **Domain-Mismatch**: Domain-Attribut korrekt setzen
3. **Path-Mismatch**: Path muss übereinstimmen
## Performance Considerations
- **Cookie-Size**: CHIPS Cookies zählen zum 4KB-Limit
- **Anzahl Cookies**: Browser-Limit beachten (typically 50-180)
- **Expiration**: Alte Cookies regelmäßig löschen
## Zusammenfassung
CHIPS Cookies bieten:
**Privacy-Friendly** - Kein Cross-Site-Tracking
**Framework-Compliant** - Value Objects, Readonly, Type Safety
**Developer-Friendly** - Einfache Factory Methods
**Production-Ready** - Automatic Secure Flag, Validation
**Well-Tested** - Comprehensive Pest Test Suite
Das Framework unterstützt CHIPS nativ für moderne, datenschutzfreundliche Third-Party-Integrationen.