Iwf Guide
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:
config : AppConfig
config =
productionConfig sessionSecret databaseUrl
Then validate before booting:
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.
headers : SecurityHeaders
headers =
defaultProductionSecurityHeaders
Default headers include:
Strict-Transport-SecurityContent-Security-PolicyReferrer-PolicyX-Frame-OptionsX-Content-Type-OptionsPermissions-Policy
Send HSTS only when the app is served through HTTPS.
Use custom headers when needed:
headers : SecurityHeaders
headers =
{ contentSecurityPolicy := Just "default-src 'self'; img-src 'self' data:" }
defaultProductionSecurityHeaders
3. Deployment Validation
Validate app config and headers together:
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:
authenticatedRlsContextauthUserRlsContextanonymousRlsContextrlsTransactionwithRlsTransactionrlsEnabledTablesrlsPoliciesForTablerlsSchemaRequiresRequestContext
RLS setup prepends SET LOCAL ROLE and app.current_user_id before application SQL inside a transaction.
6. Deployment Checklist
Before shipping:
- use
Productionmode - use a real session secret
- use secure HTTP-only session cookies
- rely on
loginUserInContext/logoutUserInContextor 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.sqlmatch - 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.