Auth completo (Argon2id + JWT/refresh rotativo), permissões, Companies e OpenAPI
- Auth (apps/api/src/auth/): Argon2id com parâmetros versionados
(ADR-0005), access token JWT de 15min, refresh token opaco de 256 bits
com rotação e detecção de replay (reuso de token já rotacionado revoga
toda a cadeia de sessões do usuário). Endpoints /api/v1/auth/
{login,refresh,logout,me}.
- Permissões resource+action+scope (ADR-0004) via PermissionGuard,
resolvidas do banco a cada request (nunca cacheadas no JWT) — mudança
de papel tem efeito imediato. super_admin com bypass hardcoded,
espelhando a trava já existente no banco.
- Companies (migration + CRUD): leitura aberta a qualquer autenticado,
escrita restrita a companies:manage; validação de CNPJ via
packages/domain-shared (dígito verificador).
- SeedService: cria o primeiro super_admin a partir de
EDEN_SUPERADMIN_EMAIL/PASSWORD só quando `users` está vazia.
- OpenAPI/Swagger em /api/docs; ValidationPipe global com
whitelist+forbidNonWhitelisted (proteção contra mass-assignment).
- packages/database: repositórios (roles/users/sessions/audit/companies)
reutilizáveis por api e worker.
Validado manualmente contra a stack real (não só typecheck): login com
senha errada → 401 genérico; refresh rotaciona e invalida o token
anterior; reuso do token antigo → replay detectado, cadeia revogada;
logout idempotente; audit log com a sequência completa de eventos;
CNPJ inválido rejeitado; mass-assignment rejeitado.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
54
packages/database/migrations/1788437478189_companies.cjs
Normal file
54
packages/database/migrations/1788437478189_companies.cjs
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Organization bounded context, first slice: companies (legal entities
|
||||
* that issue contracts/documents) — Master Prompt §6.1. Shape ported
|
||||
* faithfully from the legacy (eden.md §1.4), since this is validated,
|
||||
* production-tested data. Warehouses/branches/cost centers land in a
|
||||
* later migration once Inventory/Finance need them — Master Prompt §6.1
|
||||
* explicitly warns against leaving `companies` isolated forever, but
|
||||
* that linkage is real work for those later phases, not invented now.
|
||||
*/
|
||||
|
||||
exports.shorthands = undefined;
|
||||
|
||||
exports.up = (pgm) => {
|
||||
pgm.sql(`
|
||||
CREATE TABLE companies (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
created_by UUID REFERENCES users(id),
|
||||
company_name TEXT NOT NULL,
|
||||
trade_name TEXT,
|
||||
cnpj TEXT,
|
||||
state_registration TEXT,
|
||||
municipal_registration TEXT,
|
||||
address_zip TEXT,
|
||||
address_street TEXT,
|
||||
address_number TEXT,
|
||||
address_complement TEXT,
|
||||
address_neighborhood TEXT,
|
||||
address_city TEXT,
|
||||
address_state TEXT,
|
||||
address_country TEXT NOT NULL DEFAULT 'Brasil',
|
||||
phone TEXT,
|
||||
email TEXT,
|
||||
website TEXT,
|
||||
legal_rep_name TEXT,
|
||||
legal_rep_cpf TEXT,
|
||||
legal_rep_role TEXT,
|
||||
legal_rep_email TEXT,
|
||||
is_active BOOLEAN NOT NULL DEFAULT true
|
||||
);
|
||||
COMMENT ON TABLE companies IS
|
||||
'Empresa(s) emissora(s) de contrato/documento — eden.md §1.4. Leitura aberta a qualquer autenticado (não sensível), escrita restrita à permissão companies:manage.';
|
||||
|
||||
CREATE TRIGGER trg_companies_updated_at BEFORE UPDATE ON companies
|
||||
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
||||
|
||||
CREATE INDEX idx_companies_active ON companies(is_active);
|
||||
`);
|
||||
};
|
||||
|
||||
exports.down = (pgm) => {
|
||||
pgm.sql(`DROP TABLE IF EXISTS companies;`);
|
||||
};
|
||||
Reference in New Issue
Block a user