---
id: create-schema
agent: data-engineer
title: Desenhar o schema do banco
inputs: [modelo de domínio, story]
outputs: [DDL do schema, docs/data/SCHEMA.md]
elicit: false
modes: [interactive, yolo]
---

# Desenhar o schema do banco

**Objetivo:** transformar o modelo de domínio em DDL concreto — tabelas com baseline, foreign keys
explícitas e constraints que fazem o banco cumprir as regras, mesmo se o código da aplicação falhar.

**Pré-condições:**
- O modelo de domínio existe (saída de `db-domain-modeling`): entidades, relações e padrões de
  acesso. Se não existe, **pare** e rode `db-domain-modeling` primeiro — schema sem domínio é palpite.
- A tecnologia de banco está definida (PostgreSQL/Supabase por padrão). Se indefinida, escalo ao
  @architect — escolha de tecnologia não é minha.

## Passos

1. **Releia o modelo de domínio.** Cada tabela do DDL tem que rastrear a uma entidade do modelo. Sem
   entidade no modelo, sem tabela no schema (Constituição Art. IV).
2. **Crie cada tabela com o baseline obrigatório:** `id` (PK), `created_at`, `updated_at`. Adicione
   `deleted_at` (soft delete) onde a story pede trilha de auditoria. Tabela sem baseline não está
   pronta.
3. **Declare as foreign keys explicitamente**, com `ON DELETE`/`ON UPDATE` coerentes com a relação do
   modelo (cascade, restrict, set null). O lado dono da FK vem do modelo de domínio.
4. **Aplique defesa em profundidade no DDL:** `NOT NULL` onde o domínio exige, `CHECK` para valores
   válidos, `UNIQUE` para identidade de negócio. A aplicação é a última linha, não a única.
5. **Escolha tipos corretos:** `uuid`/`bigint` para PKs, `timestamptz` para datas, `numeric` para
   dinheiro (nunca `float`), `text` em vez de `varchar(n)` arbitrário. Tipo certo é integridade barata.
6. **Escreva DDL idempotente:** `CREATE TABLE IF NOT EXISTS`, `CREATE TYPE`/enum guardados. Rodar duas
   vezes não pode quebrar — esse DDL vai virar migration depois.
7. **Verifique a ordem de dependência:** tabelas referenciadas antes das que as referenciam. Esse
   ordenamento é o que `db-verify-order` vai cobrar na migration.
8. **Documente o schema** em `docs/data/SCHEMA.md`: cada tabela, suas colunas, FKs e constraints, com
   rastro à entidade do domínio. Sinalize que RLS e índices virão em tasks dedicadas
   (`create-rls-policies`, `design-indexes`) — não entrego tabela pública sem RLS.

## Critério de pronto (DoD)

- [ ] Toda tabela rastreia a uma entidade do modelo de domínio
- [ ] Toda tabela tem o baseline (`id`/`created_at`/`updated_at`) + `deleted_at` onde aplicável
- [ ] FKs explícitas com política de `ON DELETE`/`ON UPDATE` coerente
- [ ] Constraints de integridade (`NOT NULL`/`CHECK`/`UNIQUE`) aplicadas
- [ ] DDL idempotente e em ordem de dependência correta
- [ ] `docs/data/SCHEMA.md` escrito; RLS e índices sinalizados como próximos passos

## Falha / recuperação

- **Modelo de domínio incompleto** → paro e volto a `db-domain-modeling`; não preencho a lacuna
  inventando estrutura.
- **DDL exige decisão de arquitetura de sistema** (sharding, escolha de engine) → escalo ao @architect.
- **A story pede código de aplicação/DAL** → delego ao @dev; eu sou dona do banco, não do código acima.
