docs: map existing codebase
This commit is contained in:
281
.planning/codebase/INTEGRATIONS.md
Normal file
281
.planning/codebase/INTEGRATIONS.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# External Integrations
|
||||
|
||||
**Analysis Date:** 2026-02-13
|
||||
|
||||
## APIs & External Services
|
||||
|
||||
**Next.js Frontend Site Revalidation:**
|
||||
- Service: Custom webhook to Next.js `/api/revalidate`
|
||||
- What it's used for: Trigger static site regeneration when articles, pages, or documents change
|
||||
- SDK/Client: Guzzle HTTP client (`guzzlehttp/guzzle`)
|
||||
- Implementation: `app/Services/SiteRevalidationService.php`
|
||||
- Methods:
|
||||
- `SiteRevalidationService::revalidateArticle(?slug)` - Trigger article cache invalidation
|
||||
- `SiteRevalidatService::revalidatePage(?slug)` - Trigger page cache invalidation
|
||||
- `SiteRevalidationService::revalidateDocument(?slug)` - Trigger document cache invalidation
|
||||
- Triggered by: `app/Observers/DocumentObserver.php` on article/page create/update/delete
|
||||
- Timeout: 5 seconds
|
||||
- Error handling: Logged as warning, does not fail request
|
||||
|
||||
**Email Service Provider (Configurable):**
|
||||
- Services supported: SMTP, Mailgun, Postmark, AWS SES
|
||||
- SDK/Client: Laravel Mail facades
|
||||
- Implementation: Controllers use `Mail::to($email)->queue(MailClass::class)`
|
||||
- Auth: `MAIL_HOST`, `MAIL_PORT`, `MAIL_USERNAME`, `MAIL_PASSWORD`, or API keys
|
||||
- Dev/Test: Mailpit on `localhost:1025` (configured in `.env.example`)
|
||||
- Queue integration: All mail uses async queue for better performance
|
||||
|
||||
## Data Storage
|
||||
|
||||
**Primary Database:**
|
||||
- Type/Provider: MySQL (production) or SQLite (development)
|
||||
- Connection config: `config/database.php`
|
||||
- Connection env vars:
|
||||
- `DB_CONNECTION` - Type: `mysql` or `sqlite`
|
||||
- `DB_HOST` - Database server (e.g., `127.0.0.1`)
|
||||
- `DB_PORT` - Port (default 3306 for MySQL)
|
||||
- `DB_DATABASE` - Database name
|
||||
- `DB_USERNAME` - Username
|
||||
- `DB_PASSWORD` - Password
|
||||
- ORM/Client: Laravel Eloquent (built-in)
|
||||
- Encryption: AES-256-CBC via `config/app.php` cipher
|
||||
- Notable tables:
|
||||
- `users` - System users (staff, admin)
|
||||
- `members` - Member profiles (encrypted national IDs)
|
||||
- `finance_documents` - Finance approvals with multi-tier workflows
|
||||
- `payments` - Member fee payments
|
||||
- `articles`, `pages`, `categories`, `tags` - CMS content
|
||||
- `documents` - Document library entries
|
||||
- `roles`, `permissions`, `model_has_roles` - Spatie permission tables
|
||||
- `settings` - System-wide configuration (cached)
|
||||
|
||||
**File Storage:**
|
||||
- Databases: Local disk and S3 configurable
|
||||
- Private files: `storage/app/` (served via controller)
|
||||
- Public files: `storage/app/public/` (served via `/storage/...` URL)
|
||||
- S3 Config: `config/filesystems.php` → `disks.s3`
|
||||
- S3 env vars:
|
||||
- `AWS_ACCESS_KEY_ID`
|
||||
- `AWS_SECRET_ACCESS_KEY`
|
||||
- `AWS_DEFAULT_REGION`
|
||||
- `AWS_BUCKET`
|
||||
- `AWS_URL` (optional CDN)
|
||||
- `AWS_ENDPOINT` (optional for S3-compatible services)
|
||||
|
||||
**Caching:**
|
||||
- Providers: File (default), Redis, Memcached, DynamoDB
|
||||
- Config: `config/cache.php`
|
||||
- Default driver: `file` (suitable for single-server, can switch to Redis)
|
||||
- Used for: `settings()` helper caching, query result caching
|
||||
- Cache prefix: `laravel_cache_` (configurable via `CACHE_PREFIX` env)
|
||||
- Settings cache: Automatically cleared on `SystemSetting` model mutation
|
||||
|
||||
**Session Storage:**
|
||||
- Providers: File (default), Database, Redis
|
||||
- Config: `config/session.php`
|
||||
- Default driver: `file`
|
||||
- Lifetime: 120 minutes (configurable via `SESSION_LIFETIME` env)
|
||||
- CSRF tokens: Protected via Laravel middleware
|
||||
|
||||
## Authentication & Identity
|
||||
|
||||
**Auth Provider:**
|
||||
- Type: Custom (Session-based)
|
||||
- Implementation: Built-in Laravel authentication with `User` model
|
||||
- Guard: `web` (session-based)
|
||||
- Config: `config/auth.php`
|
||||
- Provider: Eloquent user provider (`App\Models\User`)
|
||||
|
||||
**API Token Authentication:**
|
||||
- Service: Laravel Sanctum
|
||||
- Implementation: `config/sanctum.php`
|
||||
- For: Public API endpoints (`/api/v1/*`)
|
||||
- Stateful domains: `localhost`, `127.0.0.1`, custom domain (via `SANCTUM_STATEFUL_DOMAINS` env)
|
||||
- Token prefix: Customizable via `SANCTUM_TOKEN_PREFIX` env
|
||||
- Expiration: No default expiration (tokens live indefinitely unless custom set)
|
||||
|
||||
**Role-Based Access Control (RBAC):**
|
||||
- Service: Spatie Laravel Permission
|
||||
- Package: `spatie/laravel-permission@^6.23`
|
||||
- Config: `config/permission.php`
|
||||
- Models: `Spatie\Permission\Models\Role`, `Spatie\Permission\Models\Permission`
|
||||
- Tables:
|
||||
- `roles` - Available roles
|
||||
- `permissions` - Available permissions
|
||||
- `model_has_roles` - User-to-role assignments
|
||||
- `model_has_permissions` - User-to-permission direct assignments
|
||||
- `role_has_permissions` - Role-to-permission assignments
|
||||
- Core roles (seeded in `database/seeders/`):
|
||||
- `admin` - Full system access
|
||||
- `finance_requester` - Submit finance documents
|
||||
- `finance_cashier` - Tier 1 approvals (small amounts)
|
||||
- `finance_accountant` - Tier 2 approvals (medium amounts) and ledger recording
|
||||
- `finance_chair` - Tier 2 approvals (medium amounts)
|
||||
- `finance_board_member` - Tier 3 approvals (large amounts)
|
||||
- `secretary_general` - CMS management, member management
|
||||
- `membership_manager` - Member lifecycle management
|
||||
|
||||
**Identity/National ID Encryption:**
|
||||
- Encryption: AES-256 via Laravel's encryption
|
||||
- Fields in `members` table:
|
||||
- `national_id_encrypted` - Stores encrypted national ID
|
||||
- `national_id_hash` - SHA256 hash for searching (indexed)
|
||||
- `national_id` - Virtual accessor (decrypts on read)
|
||||
- Location: `app/Models/Member.php`
|
||||
|
||||
## Webhooks & Callbacks
|
||||
|
||||
**Incoming Webhooks:**
|
||||
- Site revalidation endpoint: `/api/revalidate` (public, requires valid token)
|
||||
- Token: `NEXTJS_REVALIDATE_TOKEN` env var
|
||||
- Method: `POST`
|
||||
- Payload: `{ type: 'article'|'page'|'document', slug?: string }`
|
||||
|
||||
**Outgoing Webhooks:**
|
||||
- Next.js site revalidation: `POST {NEXTJS_REVALIDATE_URL}`
|
||||
- URL: `NEXTJS_REVALIDATE_TOKEN` env var
|
||||
- Token header: `x-revalidate-token`
|
||||
- Payload: `{ type: 'article'|'page'|'document', slug?: string }`
|
||||
- Triggered on: Article/Page/Document create/update/delete
|
||||
- Implementation: `app/Services/SiteRevalidationService.php`
|
||||
- Timeout: 5 seconds, failures logged but do not block request
|
||||
|
||||
## Monitoring & Observability
|
||||
|
||||
**Error Tracking:**
|
||||
- Service: Spatie Ignition (error page companion)
|
||||
- Package: `spatie/laravel-ignition@^2.0`
|
||||
- Used in: Development and error page debugging
|
||||
- Config: `config/app.php` → providers
|
||||
|
||||
**Logging:**
|
||||
- Framework: Monolog (via Laravel)
|
||||
- Config: `config/logging.php`
|
||||
- Default channel: `stack` (multi-handler)
|
||||
- Channels available:
|
||||
- `single` - Single log file: `storage/logs/laravel.log`
|
||||
- `daily` - Rotate daily, keep 14 days
|
||||
- `slack` - Send logs to Slack webhook (env: `LOG_SLACK_WEBHOOK_URL`)
|
||||
- `papertrail` - Syslog UDP to Papertrail (env: `PAPERTRAIL_URL`, `PAPERTRAIL_PORT`)
|
||||
- `stderr` - Output to stderr
|
||||
- `syslog` - System syslog
|
||||
- `errorlog` - PHP error_log
|
||||
- `log` - File channel with custom naming
|
||||
- `array` - In-memory (testing only)
|
||||
- Log level: `debug` (default, configurable via `LOG_LEVEL` env)
|
||||
- Deprecations channel: Null by default (can redirect via `LOG_DEPRECATIONS_CHANNEL` env)
|
||||
|
||||
**Audit Logging:**
|
||||
- Service: Custom audit logger
|
||||
- Implementation: `app/Support/AuditLogger.php`
|
||||
- Usage: `AuditLogger::log($action, $auditable, $metadata)`
|
||||
- Tracked: Model mutations (create/update/delete) for compliance
|
||||
- Storage: Appended to audit log entries
|
||||
|
||||
## CI/CD & Deployment
|
||||
|
||||
**Hosting:**
|
||||
- Platform: Dedicated servers, Docker (Laravel Sail), or cloud (AWS, etc.)
|
||||
- Port: API typically runs on port 8001 (not 8000 - that's often occupied)
|
||||
|
||||
**Build Process:**
|
||||
- Frontend assets: `npm run build` (Vite compilation)
|
||||
- Backend: `composer install` (or `composer install --no-dev` for production)
|
||||
- Migrations: `php artisan migrate --force`
|
||||
- Cache: `php artisan config:cache`, `php artisan view:cache`
|
||||
|
||||
**Code Quality (Pre-commit):**
|
||||
- Linter: Laravel Pint (PSR-12)
|
||||
- Run: `./vendor/bin/pint`
|
||||
- Fixes style issues automatically
|
||||
- Static analysis: PHPStan
|
||||
- Run: `./vendor/bin/phpstan analyse`
|
||||
- Config: `phpstan.neon` (if present)
|
||||
|
||||
**Testing:**
|
||||
- Unit & Feature Tests: PHPUnit
|
||||
- Run: `php artisan test`
|
||||
- Run specific: `php artisan test --filter=ClassName`
|
||||
- Config: `phpunit.xml`
|
||||
- Browser/E2E Tests: Laravel Dusk
|
||||
- Run: `php artisan dusk`
|
||||
- Uses Chrome/Chromium driver
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
**Required Environment Variables:**
|
||||
|
||||
Core:
|
||||
- `APP_NAME` - Application name
|
||||
- `APP_ENV` - Environment: `local`, `production`
|
||||
- `APP_DEBUG` - Boolean: enable/disable debug mode
|
||||
- `APP_KEY` - Base64 encryption key (auto-generated)
|
||||
- `APP_URL` - Full URL: `https://member.usher.org.tw` (production)
|
||||
|
||||
Database:
|
||||
- `DB_CONNECTION` - `mysql` (default) or `sqlite`
|
||||
- `DB_HOST` - Database server
|
||||
- `DB_PORT` - Port (3306 for MySQL)
|
||||
- `DB_DATABASE` - Database name
|
||||
- `DB_USERNAME` - Username
|
||||
- `DB_PASSWORD` - Password
|
||||
|
||||
Mail:
|
||||
- `MAIL_MAILER` - `smtp` (default), `mailgun`, `postmark`, `ses`, `log`
|
||||
- `MAIL_HOST` - SMTP host
|
||||
- `MAIL_PORT` - SMTP port (587 typical)
|
||||
- `MAIL_USERNAME` - SMTP username
|
||||
- `MAIL_PASSWORD` - SMTP password
|
||||
- `MAIL_ENCRYPTION` - `tls`, `ssl`, or null
|
||||
- `MAIL_FROM_ADDRESS` - From email address
|
||||
- `MAIL_FROM_NAME` - From name
|
||||
|
||||
Caching & Queuing:
|
||||
- `CACHE_DRIVER` - `file` (default), `redis`, `memcached`, `dynamodb`
|
||||
- `QUEUE_CONNECTION` - `sync` (default), `database`, `redis`, `sqs`
|
||||
- `SESSION_DRIVER` - `file` (default), `database`, `redis`
|
||||
|
||||
Feature Toggles:
|
||||
- `REGISTRATION_ENABLED` - Boolean: allow public registration (`false` by default)
|
||||
|
||||
Frontend Integration:
|
||||
- `NEXTJS_REVALIDATE_URL` - Full URL to Next.js revalidation endpoint
|
||||
- `NEXTJS_REVALIDATE_TOKEN` - Bearer token for revalidation requests
|
||||
- `NEXTJS_PUBLIC_PATH` - Optional: path to Next.js `public/` directory (for local asset sync)
|
||||
|
||||
**Secrets Location:**
|
||||
- Method: Environment variables (`.env` file, never committed)
|
||||
- Production: Use hosted secrets manager or CI/CD environment variables
|
||||
- Never commit: Passwords, API keys, encryption keys, tokens
|
||||
|
||||
## Optional: Redis
|
||||
|
||||
**If using Redis for caching/sessions/queue:**
|
||||
- Config: `config/database.php` → `redis`
|
||||
- Env vars:
|
||||
- `REDIS_HOST` - `127.0.0.1` (default)
|
||||
- `REDIS_PORT` - `6379` (default)
|
||||
- `REDIS_PASSWORD` - Password (null by default)
|
||||
- `REDIS_CLIENT` - `phpredis` (default)
|
||||
- `REDIS_CLUSTER` - `redis` (default)
|
||||
- Databases:
|
||||
- Default: 0 (primary connection)
|
||||
- Cache: 1 (separate database for cache keys)
|
||||
|
||||
## Optional: AWS Integration
|
||||
|
||||
**If using AWS S3 for file storage:**
|
||||
- Config: `config/filesystems.php` → `disks.s3`
|
||||
- Env vars: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_DEFAULT_REGION`, `AWS_BUCKET`
|
||||
|
||||
**If using AWS SES for email:**
|
||||
- Config: `config/mail.php` → `mailers.ses`
|
||||
- Env vars: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_DEFAULT_REGION`
|
||||
|
||||
**If using AWS SQS for queue:**
|
||||
- Config: `config/queue.php` → `connections.sqs`
|
||||
- Env vars: AWS credentials + `SQS_PREFIX`, `SQS_QUEUE`, `SQS_SUFFIX`
|
||||
|
||||
---
|
||||
|
||||
*Integration audit: 2026-02-13*
|
||||
Reference in New Issue
Block a user