npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mini-baas-sdk

v1.10.4

Published

SDK TypeScript do Mini BaaS com cliente JWT e serviços tipados (auth, projetos, coleções, documentos, arquivos, funções, chaves de API, times, auditoria, RBAC, políticas, RLS, webhooks e realtime via SSE)

Downloads

64

Readme

Mini BaaS SDK

SDK inspirado no Appwrite para consumir o Mini BaaS com uma interface fluente e tipada.

Recursos principais

  • Client central (MiniBaaSClient) com configuração de endpoint, projeto e tokens JWT que são renovados automaticamente ao receber 401.
  • Tipos TypeScript completos para alinhar o SDK à API (ServerlessFunction, FunctionLog, ApiKey, Team, AuditLog, ResourcePermission, ProjectPolicy, ProjectWebhook etc.).
  • Serviços para: autenticação (básica e avançada), projetos (CRUD + export/backup/import), coleções, documentos, arquivos, funções, chaves de API, times, auditoria, RBAC, políticas, RLS e webhooks.
  • Upload multipart tanto com objetos File do browser quanto com buffers/streams em Node.js (via form-data).
  • Conector de eventos Realtime (RealtimeClient) que consome o SSE /realtime/projects/:projectId/stream.
  • Paginação consistente (page, pageSize) com retorno PaginatedResponse<T> nas listagens.

Instalação / build

cd sdk
npm install
npm run build

Instalar via npm (quando publicado):

npm install mini-baas-sdk

Compatibilidade:

  • Funciona em Node.js e browser. Usa cross-fetch internamente.
  • Para RealtimeClient em Node.js, instale um polyfill EventSource (ex.: eventsource).

CLI (provisionamento via API Key)

  • O SDK inclui um CLI para provisionar estruturas usando chave de API do projeto.
  • Requer uma API Key válida do projeto; não usa e‑mail/senha.

Uso (local após build):

node dist/cli/index.js

Comandos:

  • init — gera minibaas.config.json vazio ou com template
  • pull — gera minibaas.config.json a partir do backup do projeto
  • push — sobe as configs do projeto a partir do minibaas.config.json

Exemplos:

# Gerar minibaas.config.json vazio (sempre formatado)
node dist/cli/index.js init \
  --template empty \
  --out ./minibaas.config.json

# Gerar minibaas.config.json com template básico (sempre formatado)
node dist/cli/index.js init \
  --template basic \
  --name NovoNome \
  --out ./minibaas.config.json

# Subir configs para o projeto usando minibaas.config.json
node dist/cli/index.js push \
  --endpoint http://localhost:3000 \
  --project PROJ_ID \
  --apiKey API_KEY

# Alternativa com variável de ambiente (PowerShell)
$env:MINIBAAS_API_KEY = 'API_KEY'
node dist/cli/index.js push \
  --endpoint http://localhost:3000 \
  --project PROJ_ID

# Sem --project (inferido pela API Key)
$env:MINIBAAS_API_KEY = 'API_KEY'
node dist/cli/index.js push \
  --endpoint http://localhost:3000

# Gerar minibaas.config.json com base no backup do projeto (sempre formatado)
node dist/cli/index.js pull \
  --endpoint http://localhost:3000 \
  --project PROJ_ID \
  --apiKey API_KEY \
  --out ./minibaas.config.json

# Omitir --endpoint usando API_URL
$env:API_URL = 'http://localhost:3000'
node dist/cli/index.js pull \
  --apiKey API_KEY \
  --out ./minibaas.config.json

Quando publicado no npm, você poderá usar:

npx mini-baas init --template empty --out ./minibaas.config.json
npx mini-baas init --template basic --name NovoNome --out ./minibaas.config.json
npx mini-baas push --endpoint http://localhost:3000 --project PROJ_ID --apiKey API_KEY
# ou, via variável de ambiente
# $env:MINIBAAS_API_KEY = 'API_KEY'
# npx mini-baas push --endpoint http://localhost:3000 --project PROJ_ID
# sem --project (inferido pela chave)
# $env:MINIBAAS_API_KEY = 'API_KEY'
# npx mini-baas push --endpoint http://localhost:3000
npx mini-baas pull --endpoint http://localhost:3000 --project PROJ_ID --apiKey API_KEY --out ./minibaas.config.json
# ou, omitindo --endpoint
# $env:API_URL = 'http://localhost:3000'
# npx mini-baas pull --apiKey API_KEY --out ./minibaas.config.json

# Restaurar backup completo (JSON)
npx mini-baas restore --endpoint http://localhost:3000 --apiKey API_KEY --file ./backup.json

Observações:

  • A chave de API deve pertencer ao projeto informado.
  • init aceita --name para renomear o projeto opcionalmente.
  • import usa o arquivo minibaas.config.json no diretório atual.
  • --dry exibe o plano sem executar chamadas na API.
  • Você pode definir MINIBAAS_API_KEY no ambiente e omitir --apiKey.
  • --project é opcional quando usar API Key; se omitido, o CLI infere o projeto da chave.
  • --endpoint pode ser omitido se API_URL estiver definida no ambiente.

Variáveis de ambiente (CLI)

  • API_URL: base da API (ex.: http://localhost:3000). Usada quando --endpoint é omitido.
  • MINIBAAS_API_KEY: chave de API do projeto. Usada quando --apiKey é omitido.
  • Fontes lidas automaticamente pelo CLI: .env, web/.env e ../web/.env (somente preenche variáveis ausentes do processo).
  • Em Windows PowerShell, defina com: $env:API_URL='http://localhost:3000', $env:MINIBAAS_API_KEY='...'.

Fluxos comuns

  • init: gerar minibaas.config.json vazio ou com template básico.
  • push: provisionar projeto a partir de minibaas.config.json (com --dry para simular).
  • pull: gerar minibaas.config.json com base no backup atual do projeto.
  • restore: importar backup JSON completo.

Segurança

  • Não exponha chaves em variáveis públicas do frontend (NEXT_PUBLIC_*).
  • Não versione arquivos .env com segredos; preferir variáveis de ambiente por máquina ou secrets do CI.
  • Restrinja a permissão da API Key conforme necessário (ex.: papéis admin para provisionamento).

Troubleshooting

  • Mensagem: “Parâmetros obrigatórios: API Key …”. Solução: definir MINIBAAS_API_KEY ou usar --apiKey.
  • Mensagem: “Endpoint … pode vir de API_URL”. Solução: definir API_URL ou passar --endpoint.
  • Erro 401/403: chave inválida, revogada ou sem permissão. Verifique papéis e escopos da API Key.
  • Falhas ao importar: valide o JSON (minibaas.config.json) e os nomes/IDs referenciados.

Formato do minibaas.config.json

{
  "project": { "name": "novo-nome-opcional" },
  "collections": [
    {
      "name": "Produtos",
      "schema": {
        "title": { "type": "string", "required": true },
        "price": { "type": "number", "required": true },
        "description": { "type": "string" }
      },
      "documents": [
        { "data": { "title": "Camiseta", "price": 59.9, "description": "Algodão" } }
      ]
    }
  ],
  "auth_users": [
    { "email": "[email protected]", "name": "Usuário" }
  ]
}

Notas:

  • Campos são opcionais; inclua apenas o que deseja importar.
  • O campo schema é livre, aceite objetos JSON.
  • Você pode usar diretamente o JSON gerado por pull (backup completo) como base.

Cliente base

import { MiniBaaSClient } from 'mini-baas-sdk';

const client = new MiniBaaSClient()
  .setEndpoint('http://localhost:3000')
  .setProject('meu-projeto');

client.setTokens({ accessToken: 'jwt', refreshToken: 'refresh-jwt' });
  • setEndpoint normaliza o endereço e remove barras finais.
  • setProject define o contexto usado pelos serviços (várias chamadas recebem projectId).
  • setTokens guarda os tokens JWT e renova automaticamente quando o servidor responde com 401.
  • getTokens() retorna os tokens atuais para você persistir em storage.

Persistência de tokens (ex.: browser):

// Após login:
client.setTokens({ accessToken, refreshToken });
localStorage.setItem('mb.tokens', JSON.stringify({ accessToken, refreshToken }));

// Ao iniciar o app:
const saved = localStorage.getItem('mb.tokens');
if (saved) {
  const tokens = JSON.parse(saved);
  client.setTokens(tokens);
}

Autenticação básica

import { MiniBaaSClient, AuthService } from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000');
const auth = new AuthService(client);

// Cadastro e login
const { user: newUser } = await auth.signup({ email: '[email protected]', password: 'Senha123', name: 'User' });
const { user, accessToken, refreshToken } = await auth.login({ email: '[email protected]', password: 'Senha123' });
client.setTokens({ accessToken, refreshToken });

// Perfil
const me = await auth.me();

Paginação

  • Todas as listagens aceitam { page?, pageSize? } e retornam PaginatedResponse<T>.
  • Exemplos de listagem paginada: ProjectsService.list, CollectionsService.list, DocumentsService.list, FilesService.list, FunctionsService.list, AuditService.list, UsersService.list (com search).

Serviços e métodos

| Serviço | Rotas cobertas | | --- | --- | | AuthService | signup, login, refresh, me, verifyEmail, resendVerificationEmail, requestEmailVerification, forgotPassword, requestPasswordReset, resetPassword | | ProjectsService | list, create, get, update, delete, export, backup, filesBackup, import, importBackup, importFileBackup | | CollectionsService | list, create, get, update, delete | | DocumentsService | list, create, get, update, delete | | FilesService | list, upload, get, delete | | FunctionsService | functions (list, create, update, delete, logs), schedules, execução | | ApiKeysService | api-keys (list, create, revoke) | | TeamsService | teams (CRUD + membros, escopo por projeto) | | AuditService | audit-logs | | RbacService | rbac/permissions (list, create, update, delete) | | PolicyServiceSdk | policy (get, update) | | RlsService | rls/policies (list, create, update, delete) | | WebhooksService | webhooks (list, events, create, update, delete, deliveries, test) |

Serviços

import {
  MiniBaaSClient,
  AuthService,
  ProjectsService,
  CollectionsService,
  DocumentsService,
  FilesService,
  FunctionsService,
  ApiKeysService,
  TeamsService,
  AuditService,
  RbacService,
  PolicyServiceSdk,
  RlsService,
  RealtimeClient
} from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000').setProject('projeto-x');

const auth = new AuthService(client);
const projects = new ProjectsService(client);
const collections = new CollectionsService(client);
const documents = new DocumentsService(client);
const files = new FilesService(client);
const functions = new FunctionsService(client);
const apiKeys = new ApiKeysService(client);
const teams = new TeamsService(client);
const audit = new AuditService(client);
const rbac = new RbacService(client);
const policy = new PolicyServiceSdk(client);
const rls = new RlsService(client);
const realtime = new RealtimeClient(client);
  • AuthService: cadastro, login, refresh, perfil, verificação e reset de senha
  • ProjectsService: CRUD de projeto, export/backup/import e arquivos de backup
  • CollectionsService: CRUD de coleções por projeto
  • DocumentsService: CRUD de documentos por coleção
  • FilesService: listar, upload multipart, obter e excluir arquivo
  • FunctionsService: CRUD, execução, logs e agendamentos de funções
  • ApiKeysService: listar, criar e revogar chaves de API
  • TeamsService: CRUD de times e gerenciamento de membros
  • AuditService: listagem de auditoria por projeto
  • RbacService: permissões por recurso/ação e sujeito (user/team/role)
  • PolicyServiceSdk: políticas de projeto (CORS, rate limit, IPs)
  • RlsService: policies de Row-Level Security por tabela
  • RealtimeClient: SSE para eventos em tempo real por projeto

Funções serverless

import { FunctionsService, MiniBaaSClient } from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000').setProject('projeto-x');
const functions = new FunctionsService(client);

const fn = await functions.create('projeto-x', {
  name: 'processar-relatorio',
  runtime: 'nodejs',
  entrypoint: 'handler',
  sourceCode: "exports.handler = () => ({ message: 'ok' });",
  httpMethod: 'POST',
  httpPath: '/api/processar',
  timeout: 30,
  memory: 256
});

await functions.createSchedule('projeto-x', fn.id, {
  cronExpression: '0 */6 * * *',
  timezone: 'America/Sao_Paulo'
});

const logs = await functions.listLogs('projeto-x', fn.id, { pageSize: 5 });
await functions.execute('projeto-x', fn.id, { payload: { foo: 'bar' } });

// Atualizar, apagar e operar logs/schedules
await functions.update('projeto-x', fn.id, { timeout: 60 });
await functions.purgeLogs('projeto-x', fn.id, 100);
const schedules = await functions.listSchedules('projeto-x', fn.id);
if (schedules[0]) {
  await functions.triggerSchedule('projeto-x', fn.id, schedules[0].id, { run: true });
}
// await functions.delete('projeto-x', fn.id);

Para acionar a função fora do dashboard, use executeWithApiKey passando a chave gerada por ApiKeysService:

const functions = new FunctionsService(client);
await functions.executeWithApiKey('fun-123', 'sk_live_abc', { payload: { source: 'webhook' } });

API Keys e times

import { ApiKeysService, TeamsService } from 'mini-baas-sdk';

const apiKeys = new ApiKeysService(client);
const key = await apiKeys.create('projeto-x', { name: 'Webhook key', role: 'reader' });
console.log('Use esta chave em headers X-API-KEY:', key.token);
await apiKeys.revoke('projeto-x', key.id);

const teams = new TeamsService(client);
const team = await teams.create('projeto-x', { name: 'Infra' });
await teams.addMember('projeto-x', team.id, { email: '[email protected]', roleInTeam: 'developer' });
const members = await teams.listMembers('projeto-x', team.id);
await teams.update('projeto-x', team.id, { name: 'Plataforma' });
// await teams.removeMember('projeto-x', team.id, members[0].user.id);
// await teams.delete('projeto-x', team.id);

Realtime e auditoria

import { AuditService, MiniBaaSClient, RealtimeClient } from 'mini-baas-sdk';

const audit = new AuditService(client);
const events = new RealtimeClient(client);

const stream = events.connect('projeto-x', (event) => {
  if (event.type === 'function.log') {
    console.log('Log realtime:', event.payload);
  }
}, (error) => {
  console.error('Stream error', error);
});

// Para encerrar a conexão SSE
// stream.close();

const auditPage = await audit.list('projeto-x', { pageSize: 20 });

RealtimeClient usa EventSource; em Node.js importe um polyfill como eventsource antes de conectar.

Exemplo Node.js:

import 'eventsource';
import { MiniBaaSClient, RealtimeClient } from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000').setProject('projeto-x');
client.setTokens({ accessToken: 'jwt', refreshToken: 'refresh' });
const realtime = new RealtimeClient(client);
const source = realtime.connect('projeto-x', (evt) => console.log(evt));
// source.close();

RBAC (permissões)

  • Controle fino de acesso por resourceType, resourceId (opcional), lista de ações (read, write, update, delete, execute) e sujeitos (user, team, role).
import { RbacService } from 'mini-baas-sdk';

const rbac = new RbacService(client);

await rbac.create('projeto-x', {
  resourceType: 'documents',
  action: ['read'],
  subjectType: 'role',
  subjectId: 'users',
  allow: true
});

const rules = await rbac.list('projeto-x', { resourceType: 'documents', action: 'read' });

// Atualizar e remover regra
if (rules[0]) {
  await rbac.update('projeto-x', rules[0].id, { allow: false });
  await rbac.remove('projeto-x', rules[0].id);
}

Políticas do projeto

  • Defina CORS, rate limiting por IP e listas de ipAllow/ipDeny.
import { PolicyServiceSdk } from 'mini-baas-sdk';

const policies = new PolicyServiceSdk(client);

const current = await policies.get('projeto-x');
await policies.update('projeto-x', {
  corsOrigins: ['http://localhost:3001'],
  rateLimitPerMinute: 120,
  ipAllow: [],
  ipDeny: []
});

RLS (Row-Level Security)

  • Defina policies por tabela (documents, collections, files) com comandos SELECT, INSERT, UPDATE, DELETE, e cláusulas USING/WITH CHECK.
import { MiniBaaSClient, RlsService } from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000').setProject('projeto-x');
const rls = new RlsService(client);

// Listar policies da tabela de documentos
const policies = await rls.listPolicies('projeto-x', 'documents');

// Criar policy
await rls.createPolicy('projeto-x', {
  table: 'documents',
  policyName: 'Somente do usuário',
  command: 'SELECT',
  using: "user_id = current_setting('app.user_id')::uuid"
});

// Editar policy (WITH CHECK)
await rls.updatePolicy('projeto-x', 'documents', 'Somente do usuário', {
  withCheck: "user_id = current_setting('app.user_id')::uuid"
});

// Excluir policy
await rls.deletePolicy('projeto-x', 'documents', 'Somente do usuário');

Webhooks

  • Cadastre webhooks por projeto, filtre por tipos de evento e consulte entregas (inclui assinatura HMAC sha256).
import { WebhooksService } from 'mini-baas-sdk';

const webhooks = new WebhooksService(client);

const { id } = await webhooks.create('projeto-x', {
  url: 'https://minha-app.com/webhook',
  secret: 'secret',
  eventTypes: ['function.log']
});

const events = await webhooks.events('projeto-x');
const deliveries = await webhooks.deliveries('projeto-x', id);
await webhooks.test('projeto-x', id, { ping: 'ok' });

// Atualizar e remover webhook
await webhooks.update('projeto-x', id, { url: 'https://minha-app.com/webhook2' });
await webhooks.remove('projeto-x', id);

Export, backup e import de projeto

  • Exporte metadados e dados, faça backup com conteúdo de arquivos e reimporte tudo.
import { ProjectsService } from 'mini-baas-sdk';

const projects = new ProjectsService(client);

const metadata = await projects.export('projeto-x');
const backup = await projects.backup('projeto-x');
const files = await projects.filesBackup('projeto-x');

await projects.import('projeto-x', {
  project: { name: 'novo-nome' },
  collections: metadata.collections,
  files: metadata.files,
  auth_users: metadata.auth_users
});

await projects.importBackup('projeto-x', backup);
await projects.importFileBackup('projeto-x', files.files.map(f => ({
  object_key: f.object_key,
  filename: f.filename,
  content_type: f.content_type,
  content: f.content || ''
})));

Autenticação avançada

  • Verificação de e-mail, solicitação de verificação, recuperação e redefinição de senha.
import { AuthService } from 'mini-baas-sdk';

const auth = new AuthService(client);

await auth.requestEmailVerification({ email: '[email protected]' });
await auth.resendVerificationEmail({ email: '[email protected]' });
await auth.verifyEmail('token');

await auth.forgotPassword({ email: '[email protected]' });
await auth.requestPasswordReset({ email: '[email protected]' });
await auth.resetPassword('token', 'NovaSenhaSegura123');

Projetos (CRUD)

import { MiniBaaSClient, ProjectsService } from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000');
const projects = new ProjectsService(client);

// Listar e criar
const page = await projects.list({ pageSize: 20 });
const created = await projects.create({ name: 'projeto-x' });

// Consultar, atualizar e excluir
const current = await projects.get(created.id);
await projects.update(created.id, { name: 'projeto-renomeado' });
await projects.delete(created.id);

Coleções e documentos

import { MiniBaaSClient, CollectionsService, DocumentsService } from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000').setProject('projeto-x');
const collections = new CollectionsService(client);
const documents = new DocumentsService(client);

// Criar coleção
const collection = await collections.create('projeto-x', {
  name: 'Produtos',
  schema: { title: 'object', properties: { nome: { type: 'string' }, preco: { type: 'number' } } }
});

// Obter/atualizar/excluir coleção
const got = await collections.get(collection.id);
await collections.update(collection.id, { name: 'Itens' });
// await collections.delete(collection.id);

// Criar documento
const doc = await documents.create(collection.id, { data: { nome: 'Camiseta', preco: 59.9 } });

// Listar documentos
const docPage = await documents.list(collection.id, { pageSize: 50 });

// Obter/atualizar/excluir documento
const gotDoc = await documents.get(doc.id);
await documents.update(doc.id, { data: { nome: 'Camiseta P', preco: 49.9 } });
// await documents.delete(doc.id);

Arquivos

import { MiniBaaSClient, FilesService } from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000').setProject('projeto-x');
const files = new FilesService(client);

// Upload no browser (File)
// const fileInput: HTMLInputElement = ...
// const file = fileInput.files![0];
// await files.upload('projeto-x', file, file.name);

// Upload em Node.js (Buffer ou Readable)
import fs from 'node:fs';
const buffer = fs.readFileSync('./logo.png');
const uploaded = await files.upload('projeto-x', buffer, 'logo.png');

// Obter metadados e URL de download
const { url, file } = await files.get(uploaded.id);

// Excluir
// await files.delete(uploaded.id);

Observações:

  • No browser, passe um File ou Blob e opcionalmente o nome do arquivo.
  • Em Node.js, o SDK usa form-data internamente para upload; você pode passar Buffer ou Readable.
  • FilesService.get(fileId) retorna { url, file } com URL presignada para download.

Tratamento de erros

Todas as chamadas lançam Error quando a resposta não é 2xx.

try {
  const page = await projects.list({ pageSize: 10 });
} catch (err: any) {
  console.error('Falha na API', err.message);
}

Quando possível, o SDK tenta converter o corpo de erro em texto/JSON e inclui em err.message.

Quickstart

import {
  MiniBaaSClient,
  AuthService,
  ProjectsService,
  CollectionsService,
  DocumentsService
} from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint('http://localhost:3000');
const auth = new AuthService(client);
const projects = new ProjectsService(client);
const collections = new CollectionsService(client);
const documents = new DocumentsService(client);

const { accessToken, refreshToken } = await auth.login({ email: '[email protected]', password: 'Senha123' });
client.setTokens({ accessToken, refreshToken });

const created = await projects.create({ name: 'projeto-x' });
client.setProject(created.id);

const col = await collections.create(created.id, { name: 'Produtos', schema: { type: 'object' } });
await documents.create(col.id, { data: { nome: 'Camiseta', preco: 59.9 } });

Uso com React/Next.js

  • Inicialize o cliente no topo da aplicação e injete tokens após login.
  • Em SSR/Server Components, evite localStorage; passe tokens via cookies ou variáveis de ambiente.
// Ex.: hook simples
import { MiniBaaSClient, ProjectsService } from 'mini-baas-sdk';

const client = new MiniBaaSClient().setEndpoint(process.env.API_URL!).setProject('projeto-x');
export async function listProjects() {
  const svc = new ProjectsService(client);
  return svc.list({ pageSize: 20 });
}

Boas práticas

  • Armazene API Keys com segurança; o token bruto é retornado apenas na criação.
  • Use rate limiting e policy do projeto para proteger endpoints públicos.
  • Prefira RLS e RBAC para políticas de acesso detalhadas.