# Security Guide

Security practices for deploying and operating Venue Events Manager.

## Application Hardening

### Production Environment

```env
APP_ENV=production
APP_DEBUG=false
APP_KEY=base64:...   # unique per installation
```

Never commit `.env` or expose `APP_KEY`.

### Session & Cache

On shared hosting without Redis:

```env
SESSION_DRIVER=file
CACHE_STORE=file
QUEUE_CONNECTION=sync
```

Use `database` session driver if file sessions are unreliable on your host.

## File Upload Security

Attachments are handled by `AttachmentService`:

- **Storage location:** `storage/app/attachments` (private, not web-accessible)
- **Random stored filenames** (UUID + extension)
- **Allowlist:** pdf, jpg, jpeg, png, gif, webp, doc, docx, xls, xlsx, txt, csv
- **Blocklist:** php, exe, js, sh, html, svg, and similar executable types
- **MIME validation** in addition to extension checks
- **Size limit** from `attachment_max_size_mb` setting (default 10 MB)
- **Path traversal** rejected in filenames and disk paths
- **Download** via authenticated controller only (no direct URL)

## Web Server Rules

Shipped `.htaccess` files:

| File | Purpose |
|------|---------|
| Root `.htaccess` | Deny sensitive files if document root is misconfigured |
| `public/.htaccess` | Laravel front controller + security headers |
| `storage/.htaccess` | Deny all web access |
| `public/assets/uploads/.htaccess` | Block script execution in uploads |

Enable HTTPS redirect in `public/.htaccess` when SSL is active.

## Authentication & Authorization

- Custom RBAC with permission slugs on routes and policies
- Inactive users blocked by `active` middleware
- Passwords hashed with bcrypt (cost 12)
- Audit log sanitizes password fields

Review [docs/ROLES_AND_PERMISSIONS.md](docs/ROLES_AND_PERMISSIONS.md) before assigning roles.

## Installer Security

- Refuses installation when `storage/app/installed` exists
- Detects partial installs (.env without lock)
- Database password never echoed after submission
- `.env` values escaped; file permissions 0640 where supported
- **Remove `public/install/`** after successful installation

## Database

- Use dedicated MySQL user with privileges only on the application database
- InnoDB + utf8mb4 for all tables
- No raw user input in SQL (installer uses PDO prepared statements for admin user)

## Operational Practices

1. Keep PHP and dependencies updated (`composer update` in controlled releases)
2. Back up database and `storage/app/attachments` regularly
3. Review `storage/logs/laravel.log` for anomalies; disable debug in production
4. Restrict admin accounts; use least-privilege roles for staff
5. Force password changes for default seeded accounts before go-live

## Reporting Issues

Report security vulnerabilities privately to your vendor or system administrator. Do not disclose publicly before a fix is available.
