Bootstrap EDEN: Fase 0 (arquitetura) e Fase 1 (monorepo + infra)

Fase 0 — descoberta e arquitetura:
- Inventário do projeto, glossário de domínio, arquitetura com bounded
  contexts e topologia de containers, threat model inicial.
- 12 ADRs cobrindo modular monolith, topologia de containers (Postgres
  isolado + eden-core/parceiros/assinante em containers e portas
  distintos), auth/sessões, modelo de permissões, criptografia/segredos,
  contrato first-class, stock ledger, separação billing/finance/fiscal,
  outbox transacional, adapters SaperX e Focus NFe, e identidade
  compartilhada entre as 3 apps.
- 14 subagentes e 7 skills especializados por domínio em .claude/.
- Hooks de segurança (PreToolUse/PostToolUse/Stop) testados via pipe.

Fase 1 — plataforma (em andamento):
- Monorepo pnpm workspaces + Turborepo: apps/{api,worker,core-web,
  reseller-web,subscriber-web} + 9 packages compartilhados.
- apps/api: NestJS mínimo com /health/live e /health/ready (checando
  Postgres real via @eden/database).
- 3 frontends Vite + React + TypeScript + Tailwind, com o favicon
  oficial do EDEN.
- packages/database: migration baseline (node-pg-migrate) criando
  roles/role_permissions/applications/users/user_applications/sessions/
  audit_log — audit log append-only com hash-chain, testado ao vivo
  (UPDATE/DELETE bloqueados pelo trigger).
- compose.yaml implementando a topologia da ADR-0002, validada de ponta
  a ponta: os 6 containers sobem e ficam saudáveis com um único
  `docker compose up`.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-03 08:01:14 -03:00
commit 44510bd019
149 changed files with 13006 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
---
name: eden-domain
description: Core EDEN business vocabulary and legacy OrçaFácil behavior reference. Load when implementing or reviewing any commercial/customer/contract logic to check exact legacy terminology and state machines before inventing new ones.
---
# EDEN domain skill
Use this skill whenever implementing a feature that has a legacy equivalent in `eden.md`, to avoid reinventing vocabulary or state machines that already exist and were battle-tested in production.
## When to use
- Naming a new field/entity that might already have an established name in the legacy system (check `references/terminology.md` first).
- Implementing a status/workflow transition — check `references/state-machines.md` for the exact legacy machine before designing a new one.
- Needing the full legacy behavior for a module — read `references/legacy-orcafacil.md` for the section map, then go to `eden.md` directly for the exact section (this skill indexes, it does not duplicate the 4600-line source).
## References
- `references/terminology.md` — canonical field/concept names from the legacy system, PT-BR, to preserve (see also `docs/glossary.md` at the project root, which is the authoritative version — this file exists for quick in-skill lookup).
- `references/state-machines.md` — the state machines that must be preserved or deliberately superseded via ADR (quote deal_status, client/reseller registration_status, contract states, signature envelope states, timeclock period closure).
- `references/legacy-orcafacil.md` — section index of `eden.md` (which line range covers which module) so you know where to read the exact rule instead of guessing.
## Rule
Never invent a business rule that `eden.md` already documents. If a legacy rule seems wrong or worth changing, write an ADR (`docs/adr/`) explaining why — don't silently diverge or silently copy a known gap (Master Prompt §1).

View File

@@ -0,0 +1,14 @@
# eden.md — section index
Full source: `/opt/eden/eden.md` (4597 lines). Read the exact section directly — this is a navigation index, not a summary substitute.
| Lines | Module | Key topics |
|---|---|---|
| 197 | Intro / how to use this doc | Reading order, why not to implement everything at once |
| 97687 | 1. Auth, Users, Roles, Permissions, Security | `users`, `roles`, `role_permissions`, `companies`, role weight, feature-key permission model, JWT, password reset, bcrypt/JWT/rate-limit specifics |
| 6901450 | 2. Products, Quotes, Pricing/Fidelity, Contracts | `products` price tiers, `quotes`, fidelity vs contract_period, discount/markup approval, proportional rateio, financial formulas, "contract" as derived join |
| 14512206 | 3. Client & Reseller Registration | `client_registrations`, PF/PJ differences, partners/QSA, public token flow, reseller "Programa de Canais", storage/attachment access control |
| 22072822 | 4. Documents, PDF, E-signature | Tiptap templates, merge fields, Chromium PDF rendering + sanitization, signature envelope state machine, OTP, hash-chain audit, public verification |
| 28233143 | 5. Fiscal (NCM, CFOP, municipalities) | Fiscal catalogs, sync (auto/manual), `product_fiscal_profiles`, upsert safety thresholds |
| 31444141 | 6. Timeclock (Ponto Eletrônico) | Control iD integration, AFD parsing/CRC, apuração engine, time bank, period closure, punch adjustments |
| 41424597 | 7. Backoffice diverso | Backup (streaming pg_dump/restore), meeting room/vehicle agenda, welcome page, companies (operational view), Management/ManagerDashboard, mailer, S3 |

View File

@@ -0,0 +1,19 @@
# EDEN state machines to preserve or deliberately supersede (with ADR)
## Quote `deal_status`
`orcamento → fechado → (perdido)`. `fechado` only via the close-deal flow (creates/links a client registration in the same transaction). Reversal only by the correction-authorized role.
## Client / Reseller `registration_status`
`rascunho → pendente_validacao → ativo ⇄ bloqueado/inativo`. No dedicated transition endpoints in legacy for client (generic PATCH); reseller has dedicated approve/block/reactivate actions. EDEN should keep the vocabulary identical across both entities.
## Contract states (EDEN-new, per ADR-0006)
`draft → pending_signature → active → suspended/cancelled/terminated/expired → renewed`.
## Signature envelope status (19 states)
`DRAFT → READY → SENT → VIEWED → IDENTITY_PENDING → CONSENT_PENDING → OTP_PENDING → OTP_SENT → OTP_VERIFIED → READY_TO_SIGN → SIGNING → SIGNED → FINALIZING → COMPLETED`, with `CANCELLED/EXPIRED/DECLINED/SUPERSEDED/ERROR` as terminal off-ramps. Port verbatim — this is validated, audited legal-tech logic (see `eden.md` §4.5.1).
## Timeclock period closure
`ABERTO → EM_CONFERENCIA → FECHADO`, with `/reopen` going directly `FECHADO → ABERTO` (skips EM_CONFERENCIA), gated by a separate permission from the forward transition (segregation of duties).
## Support ticket (EDEN-new, per Master Prompt §6.13)
`new → triage → in_progress ⇄ waiting_customer/waiting_third_party → resolved → closed`, plus `cancelled`.

View File

@@ -0,0 +1,5 @@
# EDEN terminology (canonical, PT-BR, from legacy)
See `docs/glossary.md` at the project root for the authoritative, maintained version. This file is a quick lookup mirror — if the two ever diverge, `docs/glossary.md` wins and this file should be updated to match.
Key terms not to rename without an ADR: `contract_period`, `fidelity_period`, `approval_status`, `deal_status` vs `status` (quote), `client_registration_id` (quote lock trigger), `registration_status` (rascunho/pendente_validacao/ativo/bloqueado/inativo), `role weight`, `feature key` → EDEN's resource+action+scope, `envelope_number`/`verification_id` (signature), `NSR`/`AFD` (timeclock).

View File

@@ -0,0 +1,15 @@
---
name: eden-finance
description: Billing, receivables, and reconciliation conventions for EDEN. Load when implementing billing runs, invoices, AR/AP, boleto/PIX, dunning, or bank reconciliation.
---
# EDEN finance skill
## When to use
- Designing a billing run or invoice consolidation flow → `references/billing.md`.
- Modeling receivables/boleto/dunning → `references/receivables.md`.
- Bank/OFX reconciliation → `references/reconciliation.md`.
- Dunning rule engine specifics → `references/dunning.md`.
## Rule
Billing (what's owed) ≠ Finance/AR-AP (collecting) ≠ Fiscal (documents) — see ADR-0008. Never let one module's table double as another's; never let a consolidated invoice be silently edited.

View File

@@ -0,0 +1,7 @@
# Billing engine conventions (ADR-0008, Master Prompt §6.10)
- Entities: `billing_accounts`, `billing_cycles`, `subscriptions/services`, `charge_components`, `usage_charges`, `invoices`, `invoice_items`, `invoice_adjustments`, `billing_runs`, `billing_run_logs`.
- Supports: mensalidade, pró-rata, implantação, locação, SaaS por usuário, franquia, consumo de telefonia, serviços avulsos, descontos contratados, ajustes manuais auditados.
- A billing run must be idempotent and safely re-runnable **before** final consolidation.
- After consolidation, an invoice is never silently edited — use adjustment/credit-debit note or a controlled re-billing flow instead.
- Test explicitly: billing run repeated does not duplicate an invoice (Master Prompt §15.3).

View File

@@ -0,0 +1,4 @@
# Dunning / cobrança conventions (Master Prompt §6.9)
- Configurable rules as data, not hardcoded logic: X days before due date, on due date, X days after, escalations, suspension/alert where policy allows, channels and templates.
- n8n consumes dunning events without querying tables directly — publish via the transactional outbox (ADR-0009), event catalog owned by `eden-api-integrations`.

View File

@@ -0,0 +1,6 @@
# Accounts receivable conventions (Master Prompt §6.9)
- A receivable title carries: parcela, competência, emissão, vencimento, juros, multa, desconto, baixa (full/partial), estorno, negociação, status, origem, cliente, contrato, fatura, conta bancária/gateway.
- Boleto: provider abstraction from day one — the bank/gateway must be swappable without rewriting the domain. Store nosso-id, provider, external id, linha digitável, código de barras, PDF/URL, PIX copia-e-cola/QR when the provider offers it, status, provider events, timestamps.
- Webhooks from bank/gateway: idempotent and authenticated, always.
- Test explicitly: a repeated webhook never duplicates a payment (Master Prompt §15.3).

View File

@@ -0,0 +1,6 @@
# Reconciliation conventions (Master Prompt §6.9)
- Import OFX/CSV and/or bank API.
- Automatic matching by value/date/document; anything ambiguous goes to an exception queue for human review — never silently auto-match an ambiguous case.
- Keep a reconciliation trail (what matched what, when, by whom/what process).
- Same philosophy applies to SaperX × EDEN invoice reconciliation (see `eden-telecom` skill) — reuse the exception-queue pattern rather than inventing a second one.

View File

@@ -0,0 +1,18 @@
---
name: eden-fiscal
description: Fiscal catalog and Focus NFe integration conventions for EDEN (NCM/CFOP/municipality catalogs, product fiscal profiles, NFCom/NFS-e/recibo de locação). Load when implementing any fiscal classification or emission logic.
---
# EDEN fiscal skill
## When to use
- Porting or extending a fiscal catalog table → `references/focus-nfcom.md` / `references/focus-nfse.md` for emission specifics; see `eden.md` §5.2-5.3 (via `eden-domain` skill's index) for the exact catalog shapes.
- Implementing recibo de locação → `references/rental-receipt.md`.
## References
- `references/focus-nfcom.md`
- `references/focus-nfse.md`
- `references/rental-receipt.md`
## Rule
A fiscal document is always a consequence of a billing item already classified via `product_fiscal_profiles` — never hardcoded per screen (ADR-0011, Master Prompt §6.11).

View File

@@ -0,0 +1,5 @@
# Focus NFCom adapter (Master Prompt §6.11, ADR-0011)
Implement: adapter, unique/idempotent reference per document, emission, query, cancellation, webhooks, persistence of the normalized request without secrets, response/status, keys/identifiers, XML/PDF artifacts when available, retries with backoff, dead-letter/manual retry.
Classification comes from `product_fiscal_profiles` (`document_type = 'NFCOM'`, `nfcom_cclass_id`, etc.) — never inferred ad hoc at emission time.

View File

@@ -0,0 +1,3 @@
# Focus NFS-e adapter (Master Prompt §6.11, ADR-0011)
Asynchronous flow: envio → status processando → consulta/webhook → autorizada/rejeitada → cancelamento/substituição where applicable. Municipal particularities isolated in configuration/adapter, never hardcoded in the domain (municipalities vary widely — reuse the legacy's `fiscal_nfse_trib_nacional`/`fiscal_nfse_trib_municipal` catalog split).

View File

@@ -0,0 +1,3 @@
# Recibo de locação (Master Prompt §6.11)
Own document type for locação billing when that's the legal/tax classification defined by Handix/contabilidade — not a generic invoice. Versioned template, numbering, issuing legal entity, locatário, competência, itens, valores, and linkage to contract/invoice. Never encode a specific tax interpretation as universal — this classification must be reviewable by Handix's fiscal/accounting team.

View File

@@ -0,0 +1,13 @@
---
name: eden-inventory
description: Stock ledger and serialized asset conventions for EDEN. Load when implementing warehouse, stock movement, or serial/patrimônio/MAC tracking logic.
---
# EDEN inventory skill
## When to use
- Modeling any stock movement → `references/stock-ledger.md`.
- Modeling serialized assets (equipment tracked individually) → `references/serialized-assets.md`.
## Rule
Stock balance is always derived from the movement ledger, never an editable column (ADR-0007). A serial/MAC/patrimônio is never allocated to two simultaneously-active assets — enforce with a database constraint, not just application logic.

View File

@@ -0,0 +1,7 @@
# Serialized asset conventions (Master Prompt §6.8)
Track per unit: serial do fabricante, número de patrimônio, MAC address(es), marca/modelo, produto, warehouse/localização atual, status, cliente/contrato/serviço onde instalado, datas de movimentação, garantia, histórico completo.
Install lifecycle: reservar estoque → selecionar unidade serializada específica → vincular ao contrato/cliente → movimentar para instalado/comodato → manter rastreabilidade até devolução/baixa.
Invariant: never allow the same serial/MAC/patrimônio to be simultaneously active on two assets — enforce at the database layer.

View File

@@ -0,0 +1,7 @@
# Stock ledger conventions (ADR-0007, Master Prompt §6.8)
Entities: `warehouses`, `warehouse_locations`, `stock_items`, `stock_lots` (when needed), `stock_movements`, `stock_reservations`, `inventory_counts`, `transfers`, `receipts`, `issues`, `returns`, `rma`.
Movement types: entrada compra, ajuste entrada/saída, transferência, reserva, liberação de reserva, saída venda, saída instalação, comodato, devolução, RMA, baixa patrimonial.
Balance is always `SUM(movements)` — never a stored, directly-editable number.

View File

@@ -0,0 +1,21 @@
---
name: eden-security
description: Security baseline, data classification, encryption, and audit conventions for EDEN. Load before implementing any new endpoint, secret, cross-tenant data path, or audit-logged action.
---
# EDEN security skill
## When to use
- Adding a new endpoint (check `references/security-baseline.md` for the OWASP checklist that applies to every route).
- Adding a new field that might hold sensitive data (check `references/data-classification.md` before deciding hash vs. encrypt vs. plain).
- Adding a new reversible secret (API key, integration token) — check `references/encryption.md` for the AES-256-GCM + key-versioning pattern.
- Adding an action that should be audited — check `references/audit.md` for the minimum audited-action list and the append-only hash-chain pattern.
## References
- `references/security-baseline.md`
- `references/data-classification.md`
- `references/encryption.md`
- `references/audit.md`
## Rule
See `docs/security/threat-model.md` at the project root for the living, authoritative threat model — this skill packages the reusable conventions; the threat model tracks current, module-specific risk decisions.

View File

@@ -0,0 +1,10 @@
# Audit conventions — EDEN
Minimum audited actions (Master Prompt §5.6): login/logout/MFA, user/role/permission changes, discount approval, contract changes, price changes, stock movement, serial/MAC/asset link-unlink, fiscal document issue/cancel, financial write-off/reversal, boleto/billing changes, timeclock period reopening, subscription actions, integration secret/config changes.
Rules:
- Append-only, enforced at the database level (trigger rejecting UPDATE/DELETE outside an explicit, itself-audited escape hatch) — never rely on "the application just never calls UPDATE."
- Order of events defined by a monotonic sequence (serial/bigserial), never by timestamp alone (timestamps can collide within a transaction — see the legacy signature audit chain's `seq` column).
- Never write a raw secret into audit metadata, ever.
- `super_admin`-equivalent bypasses authorization but never bypasses audit.
- For hash-chained audit trails (e.g., signature envelopes): version the canonicalization algorithm explicitly (`hash_algorithm_version`) so a future bug fix doesn't retroactively invalidate old, correctly-recorded events — treat linkage failures as always-real tampering, content failures on outdated algorithm versions as a legacy warning, not a failure.

View File

@@ -0,0 +1,8 @@
# Data classification — decide before writing a new column
Per Master Prompt §5.4. Three buckets, decide explicitly, never default to "encrypt everything":
1. **One-way hash**: passwords, refresh tokens, public tokens that never need recovery. Argon2id for passwords (ADR-0005); SHA-256/HMAC-SHA256 for tokens depending on entropy (see `encryption.md`).
2. **Reversible field encryption (AES-256-GCM)**: anything the application must recover in plaintext to function — integration API keys/tokens (SaperX, Focus NFe, AI providers), device credentials (Control iD), gateway secrets. Root key never in the database; versioned.
3. **Personal data (LGPD)**: minimize collection, access-control + audit + TLS + storage encryption by default; field-level encryption only for items the threat model flags as high-risk (not blanket).
4. **Credit card**: never store CVV; tokenize via PSP; store only token/brand/last-4/non-sensitive metadata. No homegrown card vault.

View File

@@ -0,0 +1,8 @@
# Encryption patterns — EDEN
See ADR-0005 for the full decision. Quick reference:
- **Reversible field encryption**: AES-256-GCM, random 96-bit IV per operation, auth tag verified on decrypt. Storage format: `{iv_b64}:{authTag_b64}:{ciphertext_b64}` in a single TEXT column (legacy-proven pattern from Control iD credential storage). Root key derived via SHA-256 of an env-provided secret, normalizing any-length input to 32 bytes. Every encrypted value also stores a `key_version` for rotation.
- **OTP**: HMAC-SHA256 with a server secret (never plain SHA-256 — OTP space is only 10^6, needs secret-based rainbow-table resistance). 6 digits, 5-minute TTL, single use, max attempts with lockout, invalidate-on-new-request.
- **Public link tokens** (client/reseller registration, signature invite): CSPRNG, ≥96 bits for registration tokens, 256 bits for signature invite tokens. Stored as SHA-256 hash only (plain hash sufficient given the token's own entropy — no HMAC needed here, unlike OTP).
- **Passwords**: Argon2id, versioned parameters (see ADR-0005), re-hash on next successful login when parameters change.

View File

@@ -0,0 +1,13 @@
# Security baseline — every EDEN endpoint
Checklist (Master Prompt §12):
- Security headers (helmet-equivalent) + adequate CSP.
- CORS by allowlist per environment (legacy had none configured — deliberate improvement).
- Server-side input validation, output encoding, parameterized queries only (never string-concat SQL).
- File upload: real MIME validation, size limits, stored outside webroot, malware-scan hook point.
- Rate limiting: by IP AND by identity/token for sensitive routes (never just one dimension — legacy pattern, keep it).
- Anti-enumeration on auth flows (forgot-password always returns success regardless of whether the email exists).
- Authorization resolved server-side from session — never trust `role`/`customer_id`/`reseller_id`/`legal_entity_id` from the client.
- Mass-assignment protection (explicit field allowlist on every PATCH, mirroring the legacy pattern of CPF/CNPJ never being in the admin-PATCH allowlist).
- SSRF prevention on anything that renders external content (PDF renderer must never navigate the network — `setContent` only, block all outgoing requests).
- Request size limits, secure cookie/token handling, dependency scanning, secret scanning in CI.

View File

@@ -0,0 +1,13 @@
---
name: eden-telecom
description: SaperX integration and telecom usage-billing conventions for EDEN. Load when implementing circuit/DID mapping, consumption import, or SaperX×EDEN reconciliation.
---
# EDEN telecom skill
## When to use
- Building/extending the SaperX adapter → `references/saperx.md`.
- Modeling usage-based billing (CDR/consumption feeding `usage_charges`) → `references/usage-billing.md`.
## Rule
Never couple internal entities to SaperX's raw payload — always a normalized DTO + `external_id` + origin snapshot (ADR-0010). If an endpoint isn't available/documented, build interface + mock + explicit TODO, never a fabricated response.

View File

@@ -0,0 +1,5 @@
# SaperX adapter conventions (ADR-0010, Master Prompt §6.12)
Requirements: per-environment config, encrypted token (AES-256-GCM), IP-allowlist support if required, timeout, safe retries, local rate limiting, correlation id, logs never containing the token, circuit breaker where appropriate, independent healthcheck.
Goals: associate EDEN customer ↔ SaperX customer/circuit; import/query circuits; import DIDs/numbers when the API allows; fetch invoices/closings; fetch components (mensalidade, ligações, SVA); import consumption/CDR for billing/audit when needed; reconcile SaperX value × EDEN invoice; expose the permitted view in the subscriber portal.

View File

@@ -0,0 +1,5 @@
# Usage-based billing conventions (telecom)
Consumption (CDR, minutes, franquia usage) imported from SaperX feeds `usage_charges` in the billing engine (see `eden-finance` skill's `billing.md`). Coordinate the exact mapping with `eden-finance` before building the import path — this skill owns the *source* of usage data, not the billing calculation itself.
Legacy pricing fields to preserve on `products` (owned by `eden-commercial`, referenced here for context): `metered`, `minutes_allowance`, `tariff_rates` (`{tipo: {normal, reduced}}` for LC/LDN/VC1/VC2/VC3/LDI), `has_ldi`.

View File

@@ -0,0 +1,13 @@
---
name: eden-timeclock
description: Control iD device integration and AFD (Portaria 671) conventions for EDEN's timeclock module. Load when implementing device communication, AFD parsing, or attendance calculation logic.
---
# EDEN timeclock skill
## When to use
- Implementing/reviewing Control iD device communication → `references/controlid.md`.
- Implementing/reviewing AFD parsing, CRC validation, or the apuração engine → `references/afd-671.md`.
## Rule
`afd_records` (raw punch data) is immutable — no UPDATE/DELETE route, ever, at any privilege level. See `eden-hr-timeclock` agent for the full non-negotiable invariant list.

View File

@@ -0,0 +1,10 @@
# AFD (Portaria MTP 671/2021) conventions
- Layout version 004, ISO-8859-1 text, `\r\n` line separators. Each line: 9-digit NSR + 1-digit record type.
- Only decode fields with an exactly-documented byte position; anything undocumented goes into a raw-tail capture — never guessed.
- CRC-16/KERMIT (poly 0x1021 reflected as 0x8408, init 0x0000, no final XOR) validates record types 2/3/4. Type 7 uses its own hash chain (never recomputed). Types 1/5/6/9 have no validatable CRC.
- CPF normalization: take the last 11 numeric digits of the raw field (never assume exact formatting) — same rule used to match against `timeclock_employees.cpf` and to relink orphaned records.
- Idempotency: whole-file (SHA-256) at import time, per-record (`device_id + nsr` unique) at insert time.
- `afd_records` is immutable — invalid/unsupported-layout rows are still inserted (never discarded), just excluded from the apuração calculation (`validation_status IN ('VALID','WARNING')` filter).
- Apuração timezone is always fixed `America/Sao_Paulo`, independent of server timezone (Brazil has had no DST since 2019).
- Tolerance (Art. 58 §1º CLT): per-event tolerance capped by a daily aggregate budget, both configurable per work schedule, not hardcoded.

View File

@@ -0,0 +1,9 @@
# Control iD (REP iDClass) integration conventions
- Transport quirk: the device's firmware sends LF-only line terminators for most headers but still closes with `\r\n\r\n` before the body — this breaks strict HTTP/1.1 parsers (Node's `llhttp`). Communicate via raw socket (`net`/`tls`), building the request manually, with a tolerant response parser trying multiple header/body boundary separators.
- Credential storage: AES-256-GCM, reversible (the app must recover the plaintext password to authenticate against the device on demand) — see `eden-security` skill's `encryption.md`.
- No persistent device session — login fresh on every operation.
- CPF is the device's own user identifier (mode 671) — no separate "controlid_user_id" concept.
- CPF travels as a `Number` in the Control iD API (loses leading zeros by design of their API) — always re-pad to 11 digits when reading back.
- All device operations run sequentially, never in parallel — embedded devices are low-throughput; batch operations (test-all-connections, sync-all-employees) iterate one device/employee at a time.
- Categorize errors (auth/timeout/http/invalid-response/unreachable/tls/unknown) and translate to a user-facing message — never leak raw technical error text to the end user.