RFC-0005 Authentication and Permissions
Purpose
Authentication identifies users. Permissions control access.
Authentication V1
- email/password
- JWT access tokens
- refresh tokens
- sessions
Password Storage
Passwords are hashed. Plain text passwords are never stored.
User Collection
System-managed users collection.
Fields:
- id
- passwordHash
- role
- createdAt
Roles
Built-in:
- admin
- authenticated
- public
Future:
- custom roles
Collection Permissions
Example:
{
"posts": {
"create": "authenticated",
"update": "owner",
"delete": "owner",
"read": "public"
}
}
Authorization Flow
Request -> JWT Validation -> Permission Check -> Collection Access
Future Authentication Providers
- Apple
- GitHub
- Microsoft
Future Security Features
- MFA
- API keys
- service accounts
- audit logs
Implementation (Milestone 7)
Module Layout
src/core/auth/
types.ts
password.ts
jwt.ts
duration.ts
user-store.ts
session-store.ts
permissions.ts
create-auth-engine.ts
Database Tables
_users— system user store (id,email,password_hash,role,created_at)_sessions— refresh token sessions (id,user_id,refresh_token_hash,expires_at,created_at)- Schema version
2
Endpoints
POST /api/auth/register
POST /api/auth/login
POST /api/auth/refresh
POST /api/auth/logout
Token Model
- Access token: HS256 JWT (
sub,role,exp) - Refresh token: opaque value stored hashed in
_sessions - Refresh rotates sessions; logout revokes the session row
Password Hashing
Bun.password with bcrypt (cost 10).
Collection Permissions
Optional permissions block on CollectionDefinition:
{
"permissions": {
"create": "authenticated",
"read": "public",
"update": "owner",
"delete": "owner"
}
}
Default when omitted: all operations public.
Owner Convention
Collections using the owner rule must define a user_id field (string or relation to users). On create, user_id is auto-set from the authenticated user when the field exists.
Reserved Names
- Collection name
usersis reserved (system auth store) - Relation fields may reference
userswithout a user-defined collection
Events
auth.register— safe user payloadauth.login— safe user payloadauth.logout—{ userId }
Configuration
{
"auth": {
"jwtSecret": "dev-only-change-me",
"accessTokenTtl": "15m",
"refreshTokenTtl": "7d"
}
}
Env: BAKEND_AUTH_JWT_SECRET, BAKEND_ADMIN_EMAIL
Wiring
createAuthEngine() in start(); HTTP server resolves Authorization: Bearer on each request and enforces permissions in record handlers.