huge documentaton restructure for docusaurus
This commit is contained in:
127
docs/ops/deployment/docker.md
Normal file
127
docs/ops/deployment/docker.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Docker Deployment Guide
|
||||
|
||||
This guide describes the recommended, repeatable way to run the Fotospiel platform in Docker for production or high-fidelity staging environments. It pairs a multi-stage build (PHP-FPM + asset pipeline) with a Compose stack that includes Nginx, worker processes, Redis, and MySQL.
|
||||
|
||||
> **Dokploy users:** see `docs/ops/deployment/dokploy.md` for service definitions, secrets, and how to wire the same containers (web, queue, scheduler, vsftpd) inside Dokploy. That document builds on the base Docker instructions below.
|
||||
|
||||
## 1. Prerequisites
|
||||
|
||||
- Docker Engine 24+ and Docker Compose v2.
|
||||
- A `.env` file for the application (see step 4).
|
||||
- Optional: an external MySQL/Redis if you do not want to run the bundled containers.
|
||||
|
||||
## 2. Build the application image
|
||||
|
||||
```bash
|
||||
docker compose build app
|
||||
```
|
||||
|
||||
The build performs the following steps:
|
||||
|
||||
1. Installs Node dependencies and runs `npm run build` to produce production assets.
|
||||
2. Installs PHP dependencies with Composer (`--no-dev --no-scripts`).
|
||||
3. Creates a PHP 8.3 FPM image with required extensions (GD, intl, Redis, etc.).
|
||||
4. Stores the compiled application under `/opt/app`; the runtime entrypoint syncs it into the shared volume when a container starts.
|
||||
|
||||
## 3. Configure environment
|
||||
|
||||
Copy the sample Docker environment file and edit the secrets:
|
||||
|
||||
```bash
|
||||
cp docker/.env.docker docker/.env.docker.local
|
||||
```
|
||||
|
||||
Set (at minimum):
|
||||
|
||||
- `APP_KEY` — generate with `docker compose run --rm app php artisan key:generate --show`.
|
||||
- Database credentials (`DB_*`). The provided MySQL service defaults to `fotospiel/secret`.
|
||||
- `STORAGE_ALERT_EMAIL` — recipient for upload failure alerts (optional).
|
||||
|
||||
Point `docker-compose.yml` to the file you created by either renaming it to `docker/.env.docker` or adjusting the `env_file` entries.
|
||||
|
||||
## 4. Boot the stack
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Services started:
|
||||
|
||||
- `app`: PHP-FPM container serving the Laravel application.
|
||||
- `web`: Nginx proxy forwarding requests to PHP-FPM on port `8080` by default (`APP_HTTP_PORT`).
|
||||
- `queue` & `media-storage-worker`: queue consumers (default + media archival).
|
||||
- `scheduler`: runs `php artisan schedule:work`.
|
||||
- `horizon` (optional, disabled unless `--profile horizon` is supplied).
|
||||
- `redis` & `mysql`.
|
||||
|
||||
### Migrations & seeds
|
||||
|
||||
Run once after the first boot or when deploying new schema changes:
|
||||
|
||||
```bash
|
||||
docker compose exec app php artisan migrate --force
|
||||
docker compose exec app php artisan db:seed --class=MediaStorageTargetSeeder --force
|
||||
```
|
||||
|
||||
If you already have data, skip the seeder or seed only new records.
|
||||
|
||||
## 5. Queue & Horizon management
|
||||
|
||||
Worker entrypoints live in `docs/queue-supervisor/`. The Compose services mount the same application volume so code stays in sync. Adjust concurrency by scaling services:
|
||||
|
||||
```bash
|
||||
docker compose up -d --scale queue=2 --scale media-storage-worker=2
|
||||
```
|
||||
|
||||
To enable Horizon (dashboard, smart balancing):
|
||||
|
||||
```bash
|
||||
docker compose --profile horizon up -d horizon
|
||||
```
|
||||
|
||||
## 6. Scheduler & cron jobs
|
||||
|
||||
The compose stack ships a `scheduler` service that runs `php artisan schedule:work`, so all scheduled commands defined in `App\Console\Kernel` stay active. For upload health monitoring, keep the helper script from `cron/upload_queue_health.sh` on the host (or inside a management container) and add a cron entry:
|
||||
|
||||
```
|
||||
*/5 * * * * /var/www/html/cron/upload_queue_health.sh
|
||||
```
|
||||
|
||||
This wrapper logs to `storage/logs/cron-upload-queue-health.log` and executes `php artisan storage:check-upload-queues`, which in turn issues guest-facing upload alerts when queues stall or fail repeatedly. In containerised environments mount the repository so the script can reuse the same PHP binary as the app, or call the artisan command directly via `docker compose exec app php artisan storage:check-upload-queues`.
|
||||
|
||||
The dashboard becomes available at `/horizon` and is protected by the Filament super-admin auth guard.
|
||||
|
||||
## 6. Persistent data & volumes
|
||||
|
||||
- `app-code` — contains the synced application, including the `storage` directory and generated assets.
|
||||
- `mysql-data` — MySQL data files.
|
||||
- `redis-data` — Redis persistence (disabled by default; change the Redis command if you want AOF snapshots).
|
||||
|
||||
Back up the volumes before upgrades to maintain tenant media and database state.
|
||||
|
||||
## 7. Updating the stack
|
||||
|
||||
1. `git pull` the repository (or deploy your release branch).
|
||||
2. `docker compose build app`.
|
||||
3. `docker compose up -d`.
|
||||
4. Run migrations + seeders if required.
|
||||
5. Check logs: `docker compose logs -f app queue media-storage-worker`.
|
||||
|
||||
Because the app image keeps the authoritative copy of the code, each container restart rsyncs fresh sources into the shared volume ensuring reliable updates without lingering artefacts.
|
||||
|
||||
## 8. Production hardening
|
||||
|
||||
- Terminate TLS with a dedicated reverse proxy (Traefik, Caddy, AWS ALB, etc.) in front of the `web` container.
|
||||
- Point `APP_URL` to your public domain and enable trusted proxies.
|
||||
- Externalize MySQL/Redis to managed services for better resilience.
|
||||
- Configure backups for the `storage` directories and database dumps.
|
||||
- Hook into your observability stack (e.g., ship container logs to Loki or ELK).
|
||||
|
||||
## 9. Internal docs publishing
|
||||
|
||||
- Build the static docs site locally or in CI via `./scripts/build-docs-site.sh` (runs `npm ci && npm run build` in `docs/site/` and outputs to `docs/site/build`).
|
||||
- The Nginx container mounts that build directory and serves it at `/internal-docs/`. History fallback is already configured in `docker/nginx/default.conf`.
|
||||
- Access is protected with HTTP Basic Auth. Update `docker/nginx/.htpasswd-docs` with real credentials (`htpasswd -c docker/nginx/.htpasswd-docs <user>`). The repo ships with a weak default for local use—never reuse it in production.
|
||||
- Optionally run the build script inside your CI pipeline before deploying so the static output is always up to date. A typical GitHub Actions job would simply call the script after checkout and upload `docs/site/build` as an artifact or rsync it to the server.
|
||||
|
||||
With the provided configuration you can bootstrap a consistent Docker-based deployment across environments while keeping queue workers, migrations, and asset builds manageable. Adjust service definitions as needed for staging vs. production.
|
||||
129
docs/ops/deployment/dokploy.md
Normal file
129
docs/ops/deployment/dokploy.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# Dokploy Deployment Guide
|
||||
|
||||
Dokploy is our self-hosted PaaS for orchestrating the Fotospiel stack (Laravel app, scheduler, queue workers, Horizon, and the Photobooth FTP pipeline). This guide explains how to provision the services in Dokploy and how to wire the SuperAdmin observability widgets that now talk to the Dokploy API.
|
||||
|
||||
## 1. Services to provision
|
||||
|
||||
| Service | Notes |
|
||||
|---------|-------|
|
||||
| **Laravel App** | Build from this repository. Expose port 8080 (or Dokploy HTTP service). Attach the production `.env`. Health check `/up`. |
|
||||
| **Scheduler** | Clone the app container; command `php artisan schedule:work`. |
|
||||
| **Queue workers** | Use `docs/queue-supervisor/queue-worker.sh` scripts (default, media-storage, media-security). Deploy each as a dedicated Dokploy application or Docker service. |
|
||||
| **Horizon (optional)** | Run `docs/queue-supervisor/horizon.sh` for dashboard + metrics. |
|
||||
| **Redis / Database** | Use managed offerings or self-host in Dokploy. Configure network access for the app + workers. |
|
||||
| **vsftpd container** | Expose port 2121 and mount the shared Photobooth volume. |
|
||||
| **Photobooth Control Service** | Lightweight API (Go/Node/Laravel Octane) that can be redeployed together with vsftpd for ingest controls. |
|
||||
|
||||
### Volumes
|
||||
|
||||
Create persistent volumes inside Dokploy and mount them across the services:
|
||||
|
||||
- `storage-app` – Laravel `storage`, uploads, compiled views.
|
||||
- `photobooth` – shared by vsftpd, the control service, and Laravel for ingest.
|
||||
- Database / Redis volumes if you self-manage those containers.
|
||||
|
||||
## 2. Environment & secrets
|
||||
|
||||
Every Dokploy application should include the regular Laravel secrets (see `.env.example`). Important blocks:
|
||||
|
||||
- `APP_KEY`, `APP_URL`, `DB_*`, `CACHE_DRIVER`, `QUEUE_CONNECTION`, `MAIL_*`.
|
||||
- Photobooth integration (`PHOTOBOOTH_CONTROL_*`, `PHOTOBOOTH_FTP_*`, `PHOTOBOOTH_IMPORT_*`).
|
||||
- AWS / S3 credentials if the tenant media is stored remotely.
|
||||
|
||||
### Dokploy integration variables
|
||||
|
||||
Add the infrastructure observability variables to the Laravel app environment:
|
||||
|
||||
```
|
||||
DOKPLOY_API_BASE_URL=https://dokploy.example.com/api
|
||||
DOKPLOY_API_KEY=pat_xxxxxxxxxxxxxxxxx
|
||||
DOKPLOY_WEB_URL=https://dokploy.example.com
|
||||
DOKPLOY_COMPOSE_IDS={"stack":"cmp_main","ftp":"cmp_ftp"}
|
||||
DOKPLOY_API_TIMEOUT=10
|
||||
```
|
||||
|
||||
- `DOKPLOY_COMPOSE_IDS` ist eine JSON-Map Label → `composeId` (siehe Compose-Detailseite in Dokploy). Diese IDs steuern Widget & Buttons.
|
||||
- Optional kannst du weiterhin `DOKPLOY_APPLICATION_IDS` pflegen, falls du später einzelne Apps statt Compose-Stacks integrieren möchtest.
|
||||
- Die API benötigt Rechte für `compose.one`, `compose.loadServices`, `compose.redeploy`, `compose.stop` etc.
|
||||
|
||||
## 3. Project & server setup
|
||||
|
||||
1. **Register the Docker host** in Dokploy (`Servers → Add Server`). Install the Dokploy agent on the target VM.
|
||||
2. **Create a Project** (e.g., `fotospiel-prod`) to group all services.
|
||||
3. **Attach repositories** using Dokploy Git providers (GitHub / Gitea / GitLab / Bitbucket) or Docker images. Fotospiel uses the source build (Dockerfile at repo root).
|
||||
4. **Networking** – keep all services on the same internal network so they can talk to Redis/DB. Expose the public HTTP service only for the Laravel app (behind Traefik/Let’s Encrypt).
|
||||
|
||||
## 4. Deploy applications
|
||||
|
||||
Follow these steps for each component:
|
||||
|
||||
1. **Laravel HTTP app**
|
||||
- Build from the repo.
|
||||
- `Dockerfile` already exposes port `8080`.
|
||||
- Set branch (e.g. `main`) for automatic deployments.
|
||||
- Add health check `/up`.
|
||||
- Mount `storage-app` and `photobooth` volumes.
|
||||
|
||||
2. **Scheduler**
|
||||
- Duplicate the image.
|
||||
- Override command: `php artisan schedule:work`.
|
||||
- Disable HTTP exposure.
|
||||
|
||||
3. **Queue workers**
|
||||
- Duplicate the image.
|
||||
- Commands:
|
||||
- `docs/queue-supervisor/queue-worker.sh default`
|
||||
- `docs/queue-supervisor/queue-worker.sh media-storage`
|
||||
- `docs/queue-supervisor/queue-worker.sh media-security`
|
||||
- Optionally create a dedicated container for Horizon using `docs/queue-supervisor/horizon.sh`.
|
||||
|
||||
4. **vsftpd + Photobooth control**
|
||||
- Nutze deinen bestehenden Docker-Compose-Stack (z. B. `docker-compose.dokploy.yml`) oder dedizierte Compose-Applikationen.
|
||||
- Mount `photobooth` volume read-write.
|
||||
|
||||
5. **Database/Redis**
|
||||
- Dokploy can provision standard MySQL/Postgres/Redis apps. Configure credentials to match `.env`.
|
||||
|
||||
6. **Apply migrations**
|
||||
- Use Dokploy one-off command to run `php artisan migrate --force` on first deploy.
|
||||
- Seed storage targets if required: `php artisan db:seed --class=MediaStorageTargetSeeder --force`.
|
||||
|
||||
## 5. SuperAdmin observability (Dokploy API)
|
||||
|
||||
Das SuperAdmin-Dashboard nutzt jetzt ausschließlich Compose-Endpunkte:
|
||||
|
||||
1. **Config file** – `config/dokploy.php` liest `DOKPLOY_COMPOSE_IDS`.
|
||||
2. **Client** – `App\Services\Dokploy\DokployClient` kapselt:
|
||||
- `GET /compose.one?composeId=...` für Meta- und Statusinfos (deploying/error/done).
|
||||
- `GET /compose.loadServices?composeId=...` für die einzelnen Services innerhalb des Stacks.
|
||||
- `GET /deployment.allByCompose?composeId=...` für die Deploy-Historie.
|
||||
- `POST /compose.redeploy`, `POST /compose.deploy`, `POST /compose.stop` (Buttons im UI).
|
||||
3. **Widgets / Pages** – `DokployPlatformHealth` zeigt jeden Compose-Stack inkl. Services; die `DokployDeployments`-Seite bietet Redeploy/Stop + Audit-Log (`InfrastructureActionLog`).
|
||||
4. **Auditing** – jede Aktion wird mit User, Payload, Response & HTTP-Code in `infrastructure_action_logs` festgehalten.
|
||||
|
||||
Only SuperAdmins should have access to these widgets. If you rotate the API key, update the `.env` and deploy the app to refresh the cache.
|
||||
|
||||
## 6. Monitoring & alerts
|
||||
|
||||
- Dokploy already produces container metrics and deployment logs. Surface the most important ones (CPU, memory, last deployment) through the widget using the monitoring endpoint.
|
||||
- Configure Dokploy webhooks (Deploy succeeded/failed, health alerts) to call a Laravel route that records incidents in `photobooth_metadata` or sends notifications.
|
||||
- Use Dokploy’s Slack/email integrations for infrastructure-level alerts. Application-specific alerts (e.g., ingest failures) still live inside Laravel notifications.
|
||||
|
||||
## 7. Production readiness checklist
|
||||
|
||||
1. Alle Compose-Stacks in Dokploy laufen mit Health Checks & Volumes.
|
||||
2. `photobooth` volume mounted for Laravel + vsftpd + control service.
|
||||
3. Database/Redis backups scheduled (Dokploy snapshot or external tooling).
|
||||
4. `.env` enthält die Dokploy-API-Credentials und `DOKPLOY_COMPOSE_IDS`.
|
||||
5. Scheduler, Worker, Horizon werden im Compose-Stack überwacht.
|
||||
6. SuperAdmin-Widget zeigt die Compose-Stacks und erlaubt Redeploy/Stop.
|
||||
7. Webhooks/alerts configured for failed deployments or unhealthy containers.
|
||||
|
||||
With this setup the Fotospiel team can manage deployments, restarts, and metrics centrally through Dokploy while Laravel’s scheduler and workers continue to run within the same infrastructure.
|
||||
|
||||
## 8. Internal docs publishing in Dokploy
|
||||
|
||||
- Build the static docs site during CI/CD by running `./scripts/build-docs-site.sh`. Upload the resulting `docs/site/build` directory as part of the deployment artifact or copy it into the Dokploy server before redeploying the stack.
|
||||
- `docker-compose.dokploy.yml` mounts that directory into the Nginx container and exposes it at `/internal-docs/`, protected by HTTP Basic Auth.
|
||||
- Update `docker/nginx/.htpasswd-docs` with production credentials (use `htpasswd -c docker/nginx/.htpasswd-docs <user>` locally, then redeploy). The repository ships with a weak default only for development—always override it in Dokploy.
|
||||
- If Dokploy builds the image itself, add a post-build hook or automation step that runs the docs build and copies it into the shared storage volume before restarting the `web` service.
|
||||
28
docs/ops/deployment/join-token-analytics.md
Normal file
28
docs/ops/deployment/join-token-analytics.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Join Token Analytics & Alerting (SEC-GT-02)
|
||||
|
||||
## Data Sources
|
||||
- Table `event_join_token_events` captures successes, failures, rate-limit hits, and uploads per join token.
|
||||
- Each row records route, device id, IP, HTTP status, and context for post-incident drill downs.
|
||||
- Logged automatically from `EventPublicController` for `/api/v1/events/*` and `/api/v1/gallery/*`.
|
||||
|
||||
- Super Admin: Event resource → “Join Link / QR” modal now summarises total successes/failures, rate-limit hits, 24h volume, and last activity timestamp per token.
|
||||
- Tenant Admin: identical modal surface so operators can monitor invite health.
|
||||
|
||||
## Alert Thresholds (initial)
|
||||
- **Rate limit spike**: >25 `token_rate_limited` entries for a token within 10 minutes → flag in monitoring (Grafana/Prometheus TODO).
|
||||
- **Failure ratio**: failure_count / success_count > 0.5 over rolling hour triggers warning for support follow-up.
|
||||
- **Inactivity**: tokens without access for >30 days should be reviewed; scheduled report TBD.
|
||||
|
||||
Rate-limiter knobs (see `.env.example`):
|
||||
- `JOIN_TOKEN_FAILURE_LIMIT` / `JOIN_TOKEN_FAILURE_DECAY` — repeated invalid attempts before temporary block (default 10 tries per 5 min).
|
||||
- `JOIN_TOKEN_ACCESS_LIMIT` / `JOIN_TOKEN_ACCESS_DECAY` — successful request ceiling per token/IP (default 120 req per minute).
|
||||
- `JOIN_TOKEN_DOWNLOAD_LIMIT` / `JOIN_TOKEN_DOWNLOAD_DECAY` — download ceiling per token/IP (default 60 downloads per minute).
|
||||
|
||||
## Follow-up Tasks
|
||||
1. Wire aggregated metrics into Grafana once metrics pipeline is ready (synthetic monitors pending SEC-GT-03).
|
||||
2. Implement scheduled command to email tenants a weekly digest of token activity and stale tokens.
|
||||
3. Consider anonymising device identifiers before long-term retention (privacy review).
|
||||
|
||||
## Runbook Notes
|
||||
- Analytics table may grow quickly for high-traffic events; plan nightly prune job (keep 90 days).
|
||||
- Use `php artisan tinker` to inspect token activity: `EventJoinTokenEvent::where('event_join_token_id', $id)->latest()->limit(20)->get()`.
|
||||
12
docs/ops/deployment/lokale-podman-adressen.md
Normal file
12
docs/ops/deployment/lokale-podman-adressen.md
Normal file
@@ -0,0 +1,12 @@
|
||||
Services & URLs
|
||||
|
||||
| Service | URL / Port | Notes |
|
||||
|----------------|--------------------------------|-------|
|
||||
| Laravel app | http://localhost:8000 | Default web UI; Horizon dashboard at /horizon if laravel/horizon is installed. |
|
||||
| Vite dev server| http://localhost:5173 | Hot module reload for the marketing/guest frontend. |
|
||||
| Mailpit UI | http://localhost:8025 | No auth; SMTP listening on port 1025. |
|
||||
| Grafana | http://localhost:3000 | Anonymous admin already enabled; dashboards will show Loki logs once you add Loki as a data source (URL http://loki:3100). |
|
||||
| Loki API | http://localhost:3100 | Used by Grafana/Promtail; direct browsing usually not needed. |
|
||||
| Portainer | https://localhost:9443 | First visit prompts you to set an admin password; point it to /var/run/docker.sock (already mounted from the `PODMAN_SOCKET` path). |
|
||||
| Redis | Bound to localhost:6379 | Matches QUEUE_CONNECTION=redis. |
|
||||
| Promtail | Internal only (port 9080) | Tails storage/logs and pushes to Loki. |
|
||||
106
docs/ops/deployment/public-api-incident-playbook.md
Normal file
106
docs/ops/deployment/public-api-incident-playbook.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Public API Incident Response Playbook (SEC-API-02)
|
||||
|
||||
Scope: Guest-facing API endpoints that rely on join tokens and power the guest PWA plus the public gallery. This includes:
|
||||
|
||||
- `/api/v1/events/{token}/*` (stats, tasks, uploads, photos)
|
||||
- `/api/v1/gallery/{token}/*`
|
||||
- Signed download/asset routes generated via `EventPublicController`
|
||||
|
||||
The playbook focuses on abuse, availability loss, and leaked content.
|
||||
|
||||
---
|
||||
|
||||
## 1. Detection & Alerting
|
||||
|
||||
| Signal | Where to Watch | Notes |
|
||||
| --- | --- | --- |
|
||||
| 4xx/5xx spikes | Application logs (`storage/logs/laravel.log`), centralized logging | Look for repeated `Join token access denied` / `token_rate_limited` or unexpected 5xx. |
|
||||
| Rate-limit triggers | Laravel log lines emitted from `EventPublicController::handleTokenFailure` | Contains IP + truncated token preview. |
|
||||
| CDN/WAF alerts | Reverse proxy (if enabled) | Ensure 429/403 anomalies are forwarded to incident channel. |
|
||||
| Synthetic monitors | Planned via `SEC-API-03` | Placeholder until monitors exist. |
|
||||
|
||||
Manual check commands:
|
||||
|
||||
```bash
|
||||
php artisan log:tail --lines=200 | grep "Join token"
|
||||
php artisan log:tail --lines=200 | grep "gallery"
|
||||
```
|
||||
|
||||
## 2. Severity Classification
|
||||
|
||||
| Level | Criteria | Examples |
|
||||
| --- | --- | --- |
|
||||
| SEV-1 | Wide outage (>50% error rate), confirmed data leak or malicious mass-download | Gallery downloads serving wrong event, join-token table compromised. |
|
||||
| SEV-2 | Localised outage (single tenant/event) or targeted brute force attempting to enumerate tokens | Single event returning 500, repeated `invalid_token` from single IP range. |
|
||||
| SEV-3 | Minor functional regression or cosmetic issue | Rate limit misconfiguration causing occasional 429 for legitimate users. |
|
||||
|
||||
Escalate SEV-1/2 immediately to on-call via Slack `#incident-response` and open PagerDuty incident (if configured).
|
||||
|
||||
## 3. Immediate Response Checklist
|
||||
|
||||
1. **Confirm availability**
|
||||
- `curl -I https://app.test/api/v1/gallery/{known_good_token}`
|
||||
- Use tenant-provided test token to validate `/events/{token}` flow.
|
||||
2. **Snapshot logs**
|
||||
- Export last 15 minutes from log aggregator or `storage/logs`. Attach to incident ticket.
|
||||
3. **Assess scope**
|
||||
- Identify affected tenant/event IDs via log context.
|
||||
- Note IP addresses triggering rate limits.
|
||||
4. **Decide mitigation**
|
||||
- Brute force? → throttle/bock offending IPs.
|
||||
- Compromised token? → revoke token via Filament or `php artisan tenant:join-tokens:revoke {id}` (once command exists).
|
||||
- Endpoint regression? → begin rolling fix or feature flag toggle.
|
||||
|
||||
## 4. Mitigation Tactics
|
||||
|
||||
### 4.1 Abuse / Brute force
|
||||
- Increase rate-limiter strictness temporarily by editing `config/limiting.php` (if available) or applying runtime block in the load balancer.
|
||||
- Use fail2ban/WAF rules to block offending IPs. For quick local action:
|
||||
```bash
|
||||
sudo ufw deny from <ip_address>
|
||||
```
|
||||
- Consider temporarily disabling gallery download by setting `PUBLIC_GALLERY_ENABLED=false` (feature flag planned) and clearing cache.
|
||||
|
||||
### 4.2 Token Compromise
|
||||
- Revoke specific token via Filament “Join Tokens” modal (Event → Join Tokens → revoke).
|
||||
- Notify tenant with replacement token instructions.
|
||||
- Audit join-token logs for additional suspicious use and consider rotating all tokens for the event.
|
||||
|
||||
### 4.3 Internal Failure (500s)
|
||||
- Tail logs for stack traces.
|
||||
- If due to downstream storage, fail closed: return 503 with maintenance banner while running `php artisan storage:diagnostics`.
|
||||
- Roll back recent deployment or disable new feature flag if traced to release.
|
||||
|
||||
## 5. Communication
|
||||
|
||||
| Audience | Channel | Cadence |
|
||||
| --- | --- | --- |
|
||||
| Internal on-call | Slack `#incident-response`, PagerDuty | Initial alert, hourly updates. |
|
||||
| Customer Support | Slack `#support` with summary | Once per significant change (mitigation applied, issue resolved). |
|
||||
| Tenants | Email template “Public gallery disruption” (see `resources/lang/*/emails.php`) | Only for SEV-1 or impactful SEV-2 after mitigation. |
|
||||
|
||||
Document timeline, impact, and mitigation in the incident ticket.
|
||||
|
||||
## 6. Verification & Recovery
|
||||
|
||||
After applying mitigation:
|
||||
|
||||
1. Re-run test requests for affected endpoints.
|
||||
2. Validate join-token creation/revocation via Filament.
|
||||
3. Confirm error rates return to baseline in monitoring/dashboard.
|
||||
4. Remove temporary firewall blocks once threat subsides.
|
||||
|
||||
## 7. Post-Incident Actions
|
||||
|
||||
- File RCA within 48 hours including: root cause, detection gaps, follow-up tasks (e.g., enabling synthetic monitors, adding audit fields).
|
||||
- Update documentation if new procedures are required (`docs/prp/11-public-gallery.md`, `docs/prp/03-api.md`).
|
||||
- Schedule backlog items for long-term fixes (e.g., better anomaly alerting, token analytics dashboards).
|
||||
|
||||
## 8. References & Tools
|
||||
|
||||
- Log aggregation: `storage/logs/laravel.log` (local), Stackdriver/Splunk (staging/prod).
|
||||
- Rate limit config: `App\Providers\AppServiceProvider` → `RateLimiter::for('tenant-api')` and `EventPublicController::handleTokenFailure`.
|
||||
- Token management UI: Filament → Events → Join Tokens.
|
||||
- Signed URL generation: `app/Http/Controllers/Api/EventPublicController` (for tracing download issues).
|
||||
|
||||
Keep this document alongside the other deployment runbooks and review quarterly.
|
||||
Reference in New Issue
Block a user