Pular para conteúdo

Persistência e segurança

Coleções Firestore

Coleção Escrita principal Leitura cliente
users próprio usuário em campos permitidos; backend para Premium/referral próprio usuário ou Super Admin
partners owner cria/atualiza; Super Admin administra autenticados
stores owner do partner em campos permitidos; Super Admin autenticados
offers partner em oferta regular segura; Functions para ações críticas autenticados
coupon_redemptions somente Admin SDK/Functions dono, Super Admin, owner do partner ou sessão de garçom da unidade
waiters owner da unidade/Super Admin owner da unidade/Super Admin
waiter_sessions somente Functions negada diretamente
campaigns somente Functions não-draft para autenticados; todas para Super Admin
campaign_participations somente Functions partner proprietário ou Super Admin
referral_rewards somente Functions usuário beneficiário ou Super Admin
subscriptions webhook/backend próprio usuário ou Super Admin
stripeEvents webhook/backend Super Admin
settings Super Admin Super Admin
partner_integrations owner do partner autenticados
audit_referrals backend negada diretamente

Ofertas possuem subcoleções privadas:

  • offers/{offerId}/admin_notes — somente Super Admin lê;
  • deletion_context — contexto usado antes do delete, somente Super Admin lê;
  • audit_logs — Super Admin e owner atual do partner leem; backend escreve.

products permanece legível por autenticados, mas write é negado. O catálogo atual usa offers como fonte principal.

Firestore Rules

firestore.rules aplica deny-by-default. Os helpers resolvem ownership por documentos partners e stores, protegem campos curatoriais/Stripe, validam categorias/badges e impedem que clientes modifiquem contadores de cupons.

Regras importantes:

  • clientes nunca escrevem coupon_redemptions, campanhas, participações, rewards ou subscriptions diretamente;
  • parceiros não mudam autoria, tier de visibilidade, campos curatoriais, origem/campanha nem contadores de limite;
  • Super Admin também não altera diretamente os contadores operacionais de limite;
  • ofertas não podem ser deletadas diretamente;
  • fallback global nega toda rota não declarada.

O Admin SDK usado pelas Functions não é limitado por Rules. Cada Function precisa repetir autenticação, role, ownership e validação de estado.

Índices

firestore.indexes.json versiona índices compostos para:

  • cupons por usuário/status, unidade/status/data, partner/status/data, cooldown e expiração;
  • ofertas por status/data, partner/status e combinações de campanha;
  • campanhas por status e datas/prioridade;
  • rewards por usuário/data.

Ao alterar uma query com múltiplos filtros/ordenação, reproduza-a no emulador e mantenha o índice no mesmo commit.

Storage

storage.rules permite leitura pública de imagens e limita escrita a arquivos image/* menores que 8 MiB:

Prefixo Quem escreve
offers/{partnerId}/... owner do partner
stores/{partnerId}/... owner do partner
campaigns/{campaignSlug}/... Super Admin
public/... Super Admin

Qualquer outro caminho é negado. O content type vem do request; consumidores ainda devem tratar arquivos como conteúdo não confiável.

Segredos e identidade

  • Firebase client options em firebase_options.dart identificam o projeto, mas não são credenciais administrativas.
  • Service accounts, .env*, keystores e functions/.secret.local devem permanecer fora do Git.
  • Stripe usa defineSecret; não há fallback seguro para produção sem Secret Manager.
  • super_admin é custom claim, não um campo de tela.
  • O monitor do garçom usa Auth anônimo apenas como identidade de sessão; autorização operacional vem de waiter_sessions criado após e-mail/PIN válidos.

Auditoria

O trigger onOfferWritten usa auth context quando disponível para produzir trilha de criação/alteração/deleção. A deleção callable grava contexto no mesmo batch em que remove a oferta, permitindo ao trigger recuperar metadados.

Logs de aplicação não substituem audit logs persistidos. Evite registrar PIN, tokens, payload completo Stripe ou PII desnecessária em console.*.