# Security and Deployment

Production security is explicit. Iwf provides secure config checks, security
header helpers, and RLS request-context utilities, but the app still owns
secrets, TLS termination, database roles, and deployment infrastructure.

## 1. Production Config

Use:

```idris
config : AppConfig
config =
  productionConfig sessionSecret databaseUrl
```

Then validate before booting:

```idris
case validateProductionConfig config of
  Right _ => pure ()
  Left warnings => traverse_ putStrLn warnings
```

`validateProductionConfig` checks:

- mode is `Production`
- session secret is not the default
- session cookies are secure
- session cookies are HTTP-only

## 2. Security Headers

Use the default production security header policy at the deployment edge or in
the lower-level server boundary when an app needs to wrap raw handlers.

```idris
headers : SecurityHeaders
headers =
  defaultProductionSecurityHeaders
```

Default headers include:

- `Strict-Transport-Security`
- `Content-Security-Policy`
- `Referrer-Policy`
- `X-Frame-Options`
- `X-Content-Type-Options`
- `Permissions-Policy`

Send HSTS only when the app is served through HTTPS.

Use custom headers when needed:

```idris
headers : SecurityHeaders
headers =
  { contentSecurityPolicy := Just "default-src 'self'; img-src 'self' data:" }
    defaultProductionSecurityHeaders
```

## 3. Deployment Validation

Validate app config and headers together:

```idris
case validateDeployment config defaultProductionSecurityHeaders of
  Right _ => start
  Left warnings => fail warnings
```

`deploymentWarnings` returns all warnings without short-circuiting.

## 4. Session Fixation

Iwf stores a framework session id in the signed session under `_session_id`.
The controller lifecycle ensures one exists before handlers render a response.
The controller login and logout helpers create a new signed session, rotate
`_session_id`, and rotate the session-backed CSRF token. This means an anonymous
session cookie is not reused unchanged after authentication, and a logged-out
cookie cannot keep the old authenticated session id.

## 5. Row-Level Security

PostgreSQL RLS is schema-owned. Iwf parses RLS metadata and provides helpers for
request-local context:

- `authenticatedRlsContext`
- `authUserRlsContext`
- `anonymousRlsContext`
- `rlsTransaction`
- `withRlsTransaction`
- `rlsEnabledTables`
- `rlsPoliciesForTable`
- `rlsSchemaRequiresRequestContext`

RLS setup prepends `SET LOCAL ROLE` and `app.current_user_id` before
application SQL inside a transaction.

## 6. Deployment Checklist

Before shipping:

- use `Production` mode
- use a real session secret
- use secure HTTP-only session cookies
- rely on `loginUserInContext`/`logoutUserInContext` or rotate session ids
  explicitly around custom auth flows
- serve through HTTPS before HSTS
- run the app's schema, migration, and typegen check workflow
- run framework and app tests
- confirm migrations and `Application/Schema.sql` match
- confirm generated schema files are build artifacts
- mount Swagger docs only where intended
- protect internal dashboards with auth
- configure upload storage outside ephemeral app disks unless local storage is
  deliberate

## Next

Read [Testing and Debugging](testing-and-debugging.md).
