- P3-2 [H] snapshot retention (7 days): snapshot_retention_days config;
SnapshotRepository::purgeOlderThan (interface + Pdo + double, files-then-rows,
bounded batch); opportunistic purge in the ingest path (Cafe24 has no cron).
- P4-1 [H] index.php sets display_errors=0 + a global exception handler → generic
{"error":"internal"} + error_log (no DSN/db_user leak); ships www/move_detect/.user.ini.
- P4-2 [H] ConfigController + HeartbeatController take an optional rate limiter +
clientIp; pre-auth per-IP anti-flood → 429 (were unthrottled).
- P4-3 [M] PdoNonceRepository::remember + PdoRateLimiterRepository::hit opportunistically
reap expired rows (Cafe24 has no cron; tables grew unbounded).
- P4-4 [M] Router::dispatch rawurldecodes captured params (Korean/space camera_id could
save zones but never load them).
Tests: python green; phpunit 84 green. See docs/delivery-audit.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Xmn8KZWqiQUguEMRtn6rW
20 lines
1.1 KiB
PHP
20 lines
1.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
namespace App;
|
|
|
|
final class Config
|
|
{
|
|
private function __construct(private array $a) {}
|
|
|
|
public static function fromArray(array $a): self { return new self($a); }
|
|
|
|
public function dbDsn(): string { return (string)($this->a['db_dsn'] ?? ''); }
|
|
public function dbUser(): string { return (string)($this->a['db_user'] ?? ''); }
|
|
public function dbPass(): string { return (string)($this->a['db_pass'] ?? ''); }
|
|
public function snapshotDir(): string { return (string)($this->a['snapshot_dir'] ?? __DIR__ . '/../storage/snapshots'); }
|
|
public function nonceTtl(): int { return (int)($this->a['nonce_ttl'] ?? 86400); }
|
|
public function timestampWindow(): int { return (int)($this->a['timestamp_window'] ?? 300); }
|
|
public function rateLimitPerMin(): int { return (int)($this->a['rate_limit_per_min'] ?? 60); }
|
|
public function ingestIpRateLimitPerMin(): int { return (int)($this->a['ingest_ip_rate_limit_per_min'] ?? 300); }
|
|
public function snapshotRetentionDays(): int { return (int)($this->a['snapshot_retention_days'] ?? 7); }
|
|
}
|