home / skills / hoangnguyen0403 / agent-skills-standard / security-isolation
This skill enforces strict multi-tenant isolation using PostgreSQL RLS and centralized validation to protect child data.
npx playbooks add skill hoangnguyen0403/agent-skills-standard --skill security-isolationReview the files below or copy the command above to add this skill to your agents.
---
name: Data Isolation & RLS Security
description: Standards for enforcing multi-tenant isolation and PostgreSQL Row Level Security (RLS) across child-centric domains.
metadata:
labels: [security, rls, isolation, authorization, postgresql]
triggers:
files: ['src/modules/**', 'SECURITY.md', 'src/migrations/**']
keywords: [RLS, Row Level Security, childId, isolation, access policy]
---
## **Priority: P0 (CRITICAL)**
Strict multi-tenant isolation. All child-centric data must be secured via PostgreSQL RLS and service-level validation.
## RLS Enforcement Workflow
1. **Migration**: Create tables with `ENABLE ROW LEVEL SECURITY`. Define policies using `current_setting('app.current_user_id')`.
2. **Entity Logic**: Add `@Security` JSDoc to the entity class.
3. **Security Doc**: Update `SECURITY.md` with the new table and its access logic.
4. **Service Validation**: Call `childrenService.validateChildAccess(childId, userId)` before any persistence operation.
## Core Guidelines
1. **Mandatory RLS**: Every new table linking to a `child` or `family` MUST have RLS enabled in its creation migration.
2. **Centralized Validation**: Never reimplement access logic. Use `ChildrenService` for child/family membership checks.
3. **Traceable Security**: `SECURITY.md` is the source of truth. Any change to RLS policies must be reflected there immediately.
4. **Nested Route Constraint**: Data isolation is enforced at the controller level via nested routes: `/children/:childId/...`.
5. **No Direct Entity exposure**: Use Response DTOs to prevent leaking internal database IDs or metadata that could bypass security filters.
## Anti-Patterns
- **No Public Tables**: Don't create child-linked tables without RLS.
- **No Manual Policy Checks**: Don't write raw SQL access checks in services. Use the centralized validator.
- **No Stale Docs**: Don't merge RLS changes without updating `SECURITY.md` and entity JSDoc.
- **No Root IDs**: Don't use `/domain/:id` for child data. Always scope by `:childId`.
## Reference & Examples
- [Implementation Patterns](references/implementation-patterns.md)
- [RLS Migration Patterns](references/rls-patterns.md)
- [Centralized Auth Logic](references/auth-logic.md)
This skill defines standards for enforcing strict multi-tenant isolation and PostgreSQL Row Level Security (RLS) across child-centric domains. It prescribes migration patterns, service-level validation, and documentation practices to prevent unauthorized cross-tenant data access. The goal is predictable, auditable access rules and a single source of truth for child/family checks.
Migrations must create tables with ENABLE ROW LEVEL SECURITY and policies that reference current_setting('app.current_user_id') to bind DB queries to the active user context. Entities carry @Security JSDoc annotations and all access logic delegates to a centralized ChildrenService (childrenService.validateChildAccess) before persistence. SECURITY.md documents each table’s policies so policy changes are immediately traceable. Controllers expose data through nested routes (/children/:childId/...) and Response DTOs to avoid leaking internal identifiers.
What if I need a public table with child-related metadata?
Avoid public child-linked tables. If truly necessary, separate public metadata into a table with no child FK and enforce association logic at the service layer while preserving RLS on any table that contains child identifiers.
Can I implement access checks directly in SQL within services?
No. Centralize checks through ChildrenService and RLS policies. Manual SQL checks create duplication, risk divergence, and bypass the single source of truth for authorization.