K1 Krat One Structure Atlas ENV · lab
Fundação/Modelo de Dados
Core #3 · Data Conventions

Modelo de Dados

O "código civil" das tabelas — o que garante que 5 pilares construídos ao longo de meses pareçam um sistema só.

UUIDv7dinheiro = bigintRLS por workspaceparticionamento por tempo
A

As convenções

RegraConvenção
IDsUUIDv7 (time-ordered) + ID público com prefixo — cont_7f3a…
TemporaisSempre timestamptz em UTC; conversão de fuso só na apresentação
Soft-deletedeleted_at universal; archived_at ≠ delete; hard-delete só p/ LGPD
Dinheirobigint em unidades menores + moeda — nunca float
Enumstext + CHECK (não pg enum, doloroso de alterar)
JSONBSó p/ settings/meta/custom; dado consultável = coluna
ConcorrênciaColuna version p/ optimistic lock
Alto volumeParticionamento por tempo em audit/event/métricas
Custom fieldscustom_field_def tipado + valores em custom jsonb (GIN)
MigrationsDrizzle, forward-only, expand-contract p/ zero-downtime
B

Base Table Template

A assinatura que toda tabela de negócio herda.

-- lei do Core: workspace_id + RLS em toda tabela de negócio
CREATE TABLE <entity> (
  id           uuid PRIMARY KEY DEFAULT uuidv7(),   -- time-ordered
  workspace_id uuid NOT NULL REFERENCES workspace(id),
  client_id    uuid REFERENCES client(id),          -- quando aplicável
  -- … colunas de negócio …
  custom       jsonb NOT NULL DEFAULT '{}',          -- custom fields tipados
  meta         jsonb NOT NULL DEFAULT '{}',
  version      int  NOT NULL DEFAULT 1,              -- optimistic lock
  created_at   timestamptz NOT NULL DEFAULT now(),   -- UTC
  updated_at   timestamptz NOT NULL DEFAULT now(),
  deleted_at   timestamptz                          -- soft-delete
);
ALTER TABLE <entity> ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON <entity>
  USING ( workspace_id = current_setting('app.workspace_id')::uuid );
CREATE INDEX ON <entity> (workspace_id) WHERE deleted_at IS NULL;

Os módulos só acrescentam suas colunas de negócio. Veja o modelo do CRM como primeiro exemplo aplicado.