Enterprise Security with nfyio: Teams, RLS, and Zero-Trust Auth
A deep dive into nfyio's multi-tenant team model, row-level security policies, and the zero-trust authentication layer built on Keycloak.
nfyio Team
Talya Smart & Technoplatz JV
nfyio is built around a zero-trust security model from day one. Every access decision is enforced at the database layer with row-level security (RLS) — not application-level filters that can be bypassed.
This post covers:
- The workspace → project → team hierarchy
- How RLS policies protect per-workspace data
- JWT authentication, MFA, and session management
- Access token scopes and route restrictions
The Multi-tenant Hierarchy
Organization
└── Workspace (isolated billing, data, RLS domain)
└── Project
└── Team (members + roles)
Every object in nfyio — buckets, files, embeddings, agent threads — belongs to a workspace. RLS policies ensure that users in Workspace A can never query data belonging to Workspace B, even if they use a valid JWT.
Row-Level Security Policies
All tables have RLS enabled. Here’s a simplified example of the bucket access policy:
-- Users can only read buckets that belong to their workspace
create policy "workspace_bucket_read"
on public.storage_buckets
for select
to authenticated
using (
workspace_id in (
select workspace_id
from workspace_members
where user_id = auth.uid()
and is_active = true
)
);
nfyio ships with RLS policies for:
storage_buckets— access by workspace membershipstorage_objects— access by bucket permissionsembedding_chunks— access by source object permissionsagent_threads— access by creator or team memberaccess_tokens— access by owner onlybilling_transactions— access by workspace owner only
Authentication Architecture
nfyio uses a layered authentication stack:
Request
│
▼
Rate Limiter (Redis)
│
▼
CSRF Guard
│
▼
JWT Verifier (Keycloak JWKS)
│
▼
Session Decrypter (AES-256-GCM)
│
▼
Access Token Scope Check
│
▼
RLS-Enforced DB Query
Every authenticated request must pass all layers.
MFA Enrollment
# Start TOTP enrollment
curl -X POST http://localhost:3000/api/auth/mfa/enroll \
-H "Authorization: Bearer $YOUR_JWT"
# Response includes QR code URI
{
"type": "totp",
"secret": "BASE32SECRETHERE",
"qrCodeUri": "otpauth://totp/nfyio:user@example.com?secret=...",
"backupCodes": ["abc123", "def456", ...]
}
After enrollment, every login requires a TOTP code:
curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your-password",
"totpCode": "123456"
}'
Access Token Scopes
API access tokens are scoped per workspace and route:
curl -X POST http://localhost:3000/api/access-keys \
-H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-upload-key",
"workspaceId": "ws_abc123",
"scopes": ["storage:write"],
"allowedRoutes": ["/api/storage/**"],
"expiresAt": "2026-12-31T23:59:59Z"
}'
This token can only write to storage endpoints. Attempting to access /api/agents/** returns 403 Forbidden.
Team Roles
| Role | Storage | Embeddings | Agents | Billing | Settings |
|---|---|---|---|---|---|
| Owner | Full | Full | Full | Full | Full |
| Modifier | Read/Write | Read/Write | Run | View | None |
| Viewer | Read | Read | None | None | None |
Invite a team member:
curl -X POST http://localhost:3000/api/teams/$TEAM_ID/invite \
-H "Authorization: Bearer $OWNER_JWT" \
-H "Content-Type: application/json" \
-d '{
"email": "colleague@example.com",
"role": "modifier"
}'
Audit Logging
Every auth event, role change, and data access is logged:
select
event_type,
actor_id,
target_type,
target_id,
ip_address,
created_at
from public.audit_logs
where workspace_id = $1
order by created_at desc
limit 50;
This gives your security team a full trail of who accessed what and when.
Summary
nfyio’s security model gives you:
- RLS everywhere — database-level isolation, not application-level
- Zero-trust JWT — every request verified against Keycloak JWKS
- AES-256-GCM session encryption — sessions encrypted at rest and in transit
- MFA with TOTP — backup codes included
- Fine-grained access tokens — scope to specific routes and operations
- Full audit logs — exportable per workspace
No additional configuration needed. All of this ships in the default Docker Compose setup.
Written by
nfyio Team
Talya Smart & Technoplatz JV
Building the future of web design at Anti-Gravity. Passionate about creating beautiful, accessible experiences.