Initiative follows a principle of least privilege — every user should only have access to the minimum data required for their role. Despite being built for casual groups and small teams, we take data isolation seriously. Your gaming group's campaign notes shouldn't be visible to another group on the same instance.
This philosophy is enforced at multiple layers:
PostgreSQL Row Level Security (RLS) enforces access boundaries at the database layer, not just in application code. Even if an application bug bypasses a check, the database itself prevents unauthorized data access.
- Guild isolation: Users can only see data in guilds they belong to. This is the primary tenancy boundary — each guild's data is invisible to other guilds.
- Initiative isolation: A second restrictive RLS layer ensures users can only see data within initiatives they are members of, providing isolation between teams within the same guild. Guild admins and superadmins bypass this layer when needed for administration.
Within an already-secured initiative, teams can fine-tune who sees what using project and document permissions:
- Owner, write, and read levels per user or per initiative role
- Independent per-resource — projects and documents have separate permission tables, so access to one doesn't imply access to another
DAC is enforced through application-level permission checks (database rows), not through database policies. RLS guarantees the security boundary; DAC lets teams decide exactly who sees what within that boundary.
app_user— Used for all user-facing API queries. This role has noBYPASSRLSprivilege, so RLS policies are always enforced.app_admin— Used for migrations, startup seeding, and background jobs. HasBYPASSRLSfor administrative operations.
- HttpOnly cookie sessions: Web sessions use
SameSite=Laxcookies instead oflocalStorage, eliminating XSS token theft risk. Native (Capacitor) apps use device tokens stored in secure platform storage. - OpenID Connect (OIDC) SSO: Enterprise identity provider integration with PKCE support and automatic claim-to-role mapping.
- Encryption at rest: Sensitive fields (AI API keys, OIDC secrets, SMTP passwords, email addresses) are encrypted using Fernet (AES-128-CBC) derived from
SECRET_KEY. - Minimal token scope: JWTs carry only the claims needed for authentication; guild and role context is resolved server-side per request.
When contributing, treat any path where a user could access data outside their scope as a security issue, not a bug.
| Version | Supported |
|---|---|
| latest | Yes |
We recommend always running the latest release. This project hasn't reached a stable v1.0.0 yet, so only the latest version receives fixes.
If you discover a security vulnerability, please report it responsibly. Do not open a public GitHub issue.
Email security@morelitea.com with:
- A description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (optional)
- Acknowledgment within 48 hours
- An estimated timeline for a fix
- Notification when the vulnerability is resolved
- Credit in the release notes (unless you prefer to remain anonymous)
This policy covers:
- Backend API (
backend/) - Frontend SPA (
frontend/) - Docker configuration and deployment scripts
- GitHub Actions workflows
Third-party dependencies are out of scope, but we appreciate reports about vulnerable transitive dependencies.