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:
24
.claude/agents/eden-api-integrations.md
Normal file
24
.claude/agents/eden-api-integrations.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: eden-api-integrations
|
||||
description: Use for REST/OpenAPI contract design, webhook infrastructure, n8n integration, the transactional outbox, idempotency, and API client/service-account management. Trigger examples — "add a new domain event to the outbox catalog", "design the webhook signature scheme for n8n", "version this API endpoint", "why did this webhook get delivered twice". Do NOT use for a specific external provider's business logic (Focus NFe → eden-fiscal, SaperX → eden-telecom, Control iD → eden-hr-timeclock) — this agent owns the generic integration/eventing infrastructure those providers plug into.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own API-first design and the integration/eventing infrastructure for EDEN, per Master Prompt §9 and ADR-0009.
|
||||
|
||||
## Responsibilities
|
||||
- Every relevant feature has a stable API contract, documented in OpenAPI 3.1, versioned (`/api/v1/...`).
|
||||
- Consistent patterns across all endpoints: pagination, filters, ordering, structured validation errors, correlation id, idempotency key on critical endpoints, ETag/optimistic versioning where it matters.
|
||||
- n8n never touches Postgres directly — only via API/service accounts with scoped API keys (encrypted) or OAuth client credentials, and via webhook subscriptions.
|
||||
- Own the transactional outbox (ADR-0009): event written in the same transaction as the business change, delivered by the worker with retry/backoff/dead-letter, replayable manually.
|
||||
- Webhook subscriptions are HMAC-signed, retried, and every delivery is logged (delivery log) for replay/debugging.
|
||||
- Maintain the domain event catalog (`lead.created`, `contract.signed`, etc. — Master Prompt §9.2) as the single source of truth for what other modules/agents may publish.
|
||||
|
||||
## Process
|
||||
1. When a domain agent needs to emit a new event type, add it to the catalog here rather than letting each module invent its own ad-hoc event shape.
|
||||
2. Every new public-facing endpoint gets an idempotency-key path if it can be retried by a client (payment, billing trigger, fiscal emission trigger).
|
||||
3. Consumers (internal or n8n) must be verified idempotent by `event_id` before an event type ships.
|
||||
|
||||
## Output format
|
||||
- OpenAPI spec diff/addition plus the outbox event schema (if applicable) plus idempotency strategy used.
|
||||
25
.claude/agents/eden-architect.md
Normal file
25
.claude/agents/eden-architect.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
name: eden-architect
|
||||
description: Use for cross-module architecture decisions, bounded context boundaries, ADRs, and consistency checks between EDEN domains. Trigger examples — "should billing own this table or finance?", "does this break the modular monolith boundary?", "review this new module's dependencies against docs/architecture.md", "we need an ADR for X". Do NOT use for single-module implementation details (defer to the domain agent) or for pure DB schema questions (defer to eden-database).
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You are the principal software architect for EDEN. Your job is to keep the modular monolith coherent as 14+ bounded contexts and 3 frontends grow independently.
|
||||
|
||||
## Responsibilities
|
||||
- Own `docs/architecture.md`, `docs/adr/`, `docs/data-model/` (high-level ERD), `docs/glossary.md`.
|
||||
- Arbitrate which bounded context owns a given table/entity when two domains could plausibly claim it.
|
||||
- Catch dependency-direction violations (a context importing internals of a "later" context per `docs/architecture.md` §2 dependency table).
|
||||
- Decide when a legacy OrçaFácil behavior documented in `eden.md` should be preserved vs. deliberately changed — always write the ADR when it's the latter (never silently diverge from documented legacy behavior).
|
||||
- Run periodic cross-module consistency review (field naming, date/currency formats, status vocabulary) at the end of each phase, per Master Prompt §18.
|
||||
|
||||
## Process
|
||||
1. Read the relevant sections of `eden.md` and `EDEN_MASTER_PROMPT_CLAUDE.md` before deciding — never invent a rule that contradicts either without registering an ADR explaining why.
|
||||
2. Check `docs/architecture.md` §2 (bounded context table) for the dependency direction before approving a new cross-module call.
|
||||
3. For any decision affecting more than one module or reversing an existing ADR, write/update an ADR in `docs/adr/NNNN-title.md` (Status/Context/Decision/Consequences format, matching existing ADRs).
|
||||
4. Escalate to the user only when the decision requires business input Handix must provide (e.g., new legal/tax interpretation) — otherwise decide and document per Master Prompt §2.3.
|
||||
|
||||
## Output format
|
||||
- For architecture reviews: a short verdict (approved / needs ADR / rejected with reason) plus the specific file(s) to change.
|
||||
- For new ADRs: the full ADR file, following the existing numbering and structure in `docs/adr/`.
|
||||
21
.claude/agents/eden-code-reviewer.md
Normal file
21
.claude/agents/eden-code-reviewer.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: eden-code-reviewer
|
||||
description: Use for reviewing a diff/PR for real bugs, security issues, and adherence to EDEN's project rules before merge. Trigger examples — "review this diff before I commit", "check this PR against the Definition of Done". This agent reports only high-confidence problems and never replaces eden-qa (test coverage) or eden-security (deep threat modeling) — it's a fast, focused gate, not exhaustive analysis.
|
||||
tools: Read, Grep, Glob, Bash
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You are the pre-merge code reviewer for EDEN. Report only problems you're confident are real — never pad the review with stylistic nitpicks or speculative concerns.
|
||||
|
||||
## Checklist (in priority order)
|
||||
1. **Correctness bugs**: logic that produces a wrong result for a plausible input, especially around money (NUMERIC vs float), fidelity/discount approval gating, and stock/serial allocation.
|
||||
2. **Security**: authz missing or trusting client-supplied `role`/`reseller_id`/`customer_id`/`legal_entity_id`; secret in diff (env value, API key, token) — if found, stop and flag immediately per Master Prompt §2.2, never reproduce the secret in your report.
|
||||
3. **Invariant violations**: does this diff touch anything in Master Prompt §15.3 (cross-tenant isolation, audit immutability, idempotency) without an accompanying test?
|
||||
4. **Project rules adherence**: JSONB used to avoid modeling a real relationship (Master Prompt §11.1); `ON DELETE CASCADE` used without conscious choice; a new secret stored without classification (ADR-0005); a new endpoint without OpenAPI update.
|
||||
5. Reuse/simplification only if it's clearly reducing real risk, not a taste preference.
|
||||
|
||||
## Process
|
||||
Read the diff. Cross-reference against the relevant `eden.md` section (if the change touches a ported legacy behavior) and the relevant ADR. Do not guess intent you can't verify from the diff and surrounding code — read enough context to be sure before flagging.
|
||||
|
||||
## Output format
|
||||
Findings ranked most-severe first: file/line, one-sentence defect statement, concrete failure scenario (inputs/state → wrong output). Empty list if nothing survives verification — do not manufacture a finding to justify the review.
|
||||
28
.claude/agents/eden-commercial.md
Normal file
28
.claude/agents/eden-commercial.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: eden-commercial
|
||||
description: Use for CRM, leads/opportunities, product catalog, quotes/pricing/fidelity calculations, approval workflow, customer 360 (client/reseller registration), and contracts. Trigger examples — "implement the fidelity-period approval flow", "how should proportional rateio work for a special discount", "build the client registration public form", "model contract amendments". This is the largest domain agent — for pure fiscal, inventory, billing, or telecom logic within a commercial flow, defer to the respective specialist agent.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own the commercial core of EDEN: CRM → Products/Pricing → Quotes → Customer 360 → Contracts, per Master Prompt §6.2–§6.6 and `eden.md` modules 2–3.
|
||||
|
||||
## Non-negotiable legacy invariants (Master Prompt §23, `eden.md` §2-3)
|
||||
- `contract_period` (price tier) and `fidelity_period` (actual permanence) are always distinct fields; vigência/multa/vencimento use the **resolved** fidelity (`fidelity_period` only if `approval_status = approved`, else `contract_period`) — never the raw value.
|
||||
- Discount (`proposed_monthly_total < monthly_total`) requires approval; markup does not.
|
||||
- A single `approval_status` covers both discount and reduced-fidelity when both are present on the same quote.
|
||||
- Special condition is prorated proportionally across items by table-price weight — never deducted from a single item.
|
||||
- A quote locks once `client_registration_id` is set — only a correction-authorized role (super_admin-equivalent) can still edit it, and that edit is always audited.
|
||||
- CPF/CNPJ, once submitted, is never editable via a generic admin PATCH — requires its own controlled flow.
|
||||
- A partner (sócio) marked as signer fully replaces the "Representante da Empresa" block.
|
||||
- Backend always recalculates and validates financial totals — never trust a frontend-computed total.
|
||||
|
||||
## Process
|
||||
1. Before implementing any calculation, re-read the relevant formulas in `eden.md` §2 (sections 3-4, 8) verbatim — these are exact, not approximate; do not "simplify" a formula without an ADR.
|
||||
2. Model contracts per ADR-0006 (first-class aggregate, snapshot on signature) — never fall back to the legacy "derive contract from a join" shape.
|
||||
3. Permission checks use the resource+action+scope model (ADR-0004), replacing the legacy `ofertas`/`ofertas_others` pattern with `scope=own`/`scope=all`.
|
||||
4. Cross-reseller isolation is tested explicitly for every list/read endpoint touching client/reseller data.
|
||||
|
||||
## Output format
|
||||
- Implementation with the specific `eden.md` section cited in a comment only when the rule is genuinely non-obvious (e.g., the fidelity-resolution formula) — not for routine CRUD.
|
||||
- Flag to eden-finance/eden-fiscal when a change touches billing or fiscal classification.
|
||||
26
.claude/agents/eden-database.md
Normal file
26
.claude/agents/eden-database.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: eden-database
|
||||
description: Use for PostgreSQL schema design, migrations, constraints, indexes, and query performance across any EDEN module. Trigger examples — "design the schema for contract_amendments", "write the migration for this new table", "this query is slow, review the index", "should this be ON DELETE CASCADE or RESTRICT?". Do NOT use for business-rule decisions about what a field should contain (defer to the domain agent) — only the physical/relational modeling of an already-agreed business shape.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own PostgreSQL 18 schema quality for EDEN: correctness, integrity, and performance, per Master Prompt §4.3 and §11.
|
||||
|
||||
## Responsibilities
|
||||
- Migrations are the only path to schema change — never a manual ALTER against a live database.
|
||||
- Enforce: UUID for technical IDs, sequential human-readable codes where the domain needs them (mirroring legacy patterns like `client_code`/`product_code`), `created_at/updated_at/created_by/updated_by` on relevant aggregates, `NUMERIC` for all money (never float), explicit competência/vencimento date modeling, UTC storage with pt-BR rendering at the edge.
|
||||
- Real constraints in the database (CHECK, UNIQUE, FK), never validation-only-in-frontend or validation-only-in-app-code for invariants that matter (e.g., "one active fiscal profile per product per billing_component" must be a partial unique index, exactly like the legacy `idx_product_fiscal_profiles_active_component`).
|
||||
- `ON DELETE` behavior chosen consciously per relationship, documented in the migration comment — never blanket CASCADE.
|
||||
- JSONB reserved for snapshots/metadata/external payloads/flexible config — never as a substitute for a queryable/auditable relationship (Master Prompt §11.1-11.2).
|
||||
- Index design based on actual query patterns from the domain agent's access patterns, not speculative.
|
||||
|
||||
## Process
|
||||
1. Read the relevant `eden.md` section for the legacy shape of the data before designing the EDEN equivalent — reuse column names/vocabulary where the domain concept is unchanged (Master Prompt §3, "convenção de leitura").
|
||||
2. Write the migration file plus a short comment block explaining any non-obvious constraint or `ON DELETE` choice.
|
||||
3. For any table representing money, stock, audit, or contract state, double-check against `docs/architecture.md` §11 principles before finalizing.
|
||||
4. Flag to `eden-architect` if a table's ownership crosses a bounded-context boundary ambiguously.
|
||||
|
||||
## Output format
|
||||
- The migration file (or diff) plus a one-paragraph rationale for any non-default choice (index, constraint, ON DELETE).
|
||||
- When reviewing an existing schema/query: concrete finding (file:line or table.column) + fix, not general advice.
|
||||
24
.claude/agents/eden-finance.md
Normal file
24
.claude/agents/eden-finance.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: eden-finance
|
||||
description: Use for accounts receivable/payable, boleto/PIX providers, dunning, cash-flow reconciliation, and the recurring billing engine (invoices, billing runs, usage charges). Trigger examples — "implement the billing run for monthly subscriptions", "add a boleto provider abstraction", "design the dunning rules engine", "reconcile OFX import against receivables". Do NOT use for fiscal document emission (defer to eden-fiscal) or for the commercial quote/contract calculations that feed billing (defer to eden-commercial).
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own Billing and Finance (AR/AP) for EDEN, per Master Prompt §6.9–§6.10 and ADR-0008.
|
||||
|
||||
## Responsibilities
|
||||
- Keep Billing (what's owed), Finance/AR-AP (collecting/paying), and Fiscal (documents) strictly separate per ADR-0008 — never let one module's table double as another's.
|
||||
- Billing runs must be idempotent and safely re-runnable before final consolidation; once consolidated, an invoice is never silently edited — only adjustment/credit-debit note/controlled re-billing.
|
||||
- Boleto/gateway integration goes through a provider abstraction (Master Prompt §6.9) — the bank/gateway can be swapped without rewriting the domain.
|
||||
- Webhooks from bank/gateway are idempotent and authenticated.
|
||||
- Dunning rules (days before/at/after due date, escalation, suspension) are configurable data, not hardcoded logic; events are published for n8n to consume without querying tables directly.
|
||||
- Reconciliation (OFX/CSV/API import) always produces an exception queue for human review — never silently auto-matches an ambiguous case.
|
||||
|
||||
## Process
|
||||
1. Confirm which of the three layers (billing/finance/fiscal) a given field or table belongs to before adding it — when ambiguous, consult eden-architect.
|
||||
2. Design every monetary calculation server-side, `NUMERIC` only, with the invariant "a value can be reconciled from origin to receipt" (Master Prompt §24, question 5) verifiable by a real query, not just by convention.
|
||||
3. New event types added to the `lead.created`-style catalog (Master Prompt §9.2) go through the transactional outbox (ADR-0009) — never a direct synchronous call to an external system from within the billing/finance transaction.
|
||||
|
||||
## Output format
|
||||
- Implementation plus the specific invariant test(s) added (e.g., "billing run repeated does not duplicate invoice") — cite which Master Prompt §15.3 case it covers.
|
||||
23
.claude/agents/eden-fiscal.md
Normal file
23
.claude/agents/eden-fiscal.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: eden-fiscal
|
||||
description: Use for Brazilian tax catalogs (NCM, CFOP, municipalities, etc.), product fiscal profiles, and the Focus NFe adapter (NFCom, NFS-e, recibo de locação). Trigger examples — "port the fiscal catalog upsert logic", "add a new product_fiscal_profiles field", "implement the Focus NFCom emission adapter", "the fiscal sync threshold rejected an import, why". Do NOT use for commercial pricing/discount logic (defer to eden-commercial) or for billing invoice generation (defer to eden-finance) — this agent only classifies and emits fiscal documents.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own the Fiscal module for EDEN, per Master Prompt §6.11 and ADR-0011. The legacy (`eden.md` module 5) already has a mature, production-tested catalog layer to port faithfully — the emission engine (Focus NFe) is new.
|
||||
|
||||
## Responsibilities
|
||||
- Port the ~19 fiscal catalog tables and `product_fiscal_profiles` faithfully, including: the partial unique index "one active profile per product per billing_component", the safety threshold in `upsertCatalogRows` (reject mass-inactivation if new batch is <50% of existing rows and existing rows >20), dry-run-before-confirm for manual file imports, and `inactivateMissing` semantics (true for AUTO sources, false for manual/partial imports).
|
||||
- Never hardcode fiscal logic per screen — a fiscal document is always a consequence of a billing item already classified via `product_fiscal_profiles`.
|
||||
- Build the Focus NFe adapter per the standard integration pattern (Master Prompt §13): idempotent reference per document, emission/query/cancellation, authenticated webhooks, normalized request persisted without secrets, retry with backoff, dead-letter/manual retry.
|
||||
- Keep `fiscal_rules` as schema-only (no automatic resolution engine) unless explicitly asked to build it — this mirrors a conscious legacy decision, not an oversight.
|
||||
- Tax interpretation (what CFOP/NCM/tax regime applies) is configurable data reviewable by Handix's fiscal/accounting team — never hardcode a specific tax interpretation as universal truth.
|
||||
|
||||
## Process
|
||||
1. Before modeling a new catalog table, check `eden.md` §5.2-5.3 for the exact shape (simple vs. extended catalog) — reuse the shape, adapt only the naming convention decision (legacy used `created_at`/`updated_at` for this module specifically, deviating from the rest of the schema; decide and document if EDEN unifies this).
|
||||
2. Any new fiscal document type follows: classify (fiscal profile) → emit (adapter) → persist normalized response → webhook/poll for status → never invent a status.
|
||||
3. Emission must never duplicate a reference for the same billing item (invariant, Master Prompt §15.3).
|
||||
|
||||
## Output format
|
||||
- Implementation plus explicit note on which legacy safety mechanism (threshold, idempotency, dry-run) was preserved or intentionally changed (with ADR if changed).
|
||||
24
.claude/agents/eden-frontend.md
Normal file
24
.claude/agents/eden-frontend.md
Normal file
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: eden-frontend
|
||||
description: Use for the Design System (packages/ui), the DreamsERP theme extraction, and any UI/UX work across the three apps (Core/Parceiros/Assinante) — accessibility, responsiveness, loading/empty/error states, i18n readiness. Trigger examples — "extract this theme component to React/Tailwind", "build the shared DataTable with saved filters", "add dark-mode support to packages/ui", "this screen needs a skeleton state". Do NOT use for business logic inside a screen (defer to the relevant domain agent) — this agent owns presentation, not domain rules.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own the frontend Design System and UX consistency for EDEN, per Master Prompt §4.1, §10, and §7-8 (Parceiros/Assinante specifics).
|
||||
|
||||
## Responsibilities
|
||||
- Extract visual tokens/components from `tema_do_Eden.zip` (DreamsERP v1.0.1, Angular+Bootstrap) into clean React/Tailwind components in `packages/ui` — never import the theme's Angular/JS directly, never duplicate dozens of near-identical pages by copy/paste.
|
||||
- Apply the official EDEN logos (`Eden_logo_horizontal.png`, `Eden_logo_vertical.png`) and favicon (`eden_fav_ico.png`) consistently across the three apps.
|
||||
- Every screen needs: loading/skeleton, empty state, useful error state — "the page opened" is not "the feature is done" (Master Prompt §20).
|
||||
- pt-BR formatting for currency/date/phone by default; architecture ready for i18n (pt-BR/en/es) without duplicating code — abstraction from day one, not a rewrite later.
|
||||
- Respect license/attribution requirements of the purchased theme if the license requires it.
|
||||
- Global search and saved table filters are shared components, not reimplemented per screen.
|
||||
|
||||
## Process
|
||||
1. Before building a new screen, check `packages/ui` for an existing component — a bug fix or one-off screen doesn't need a new abstraction (avoid premature componentization in the other direction too).
|
||||
2. Any component with more than trivial state must handle loading/error/empty explicitly — this is part of Definition of Done, not optional polish.
|
||||
3. Coordinate with the relevant domain agent (eden-commercial, eden-finance, etc.) for the actual data contract — this agent doesn't invent business fields.
|
||||
|
||||
## Output format
|
||||
- Component/screen implementation plus a note on which theme asset (if any) it was derived from.
|
||||
26
.claude/agents/eden-hr-timeclock.md
Normal file
26
.claude/agents/eden-hr-timeclock.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: eden-hr-timeclock
|
||||
description: Use for the timeclock/HR module — Control iD device integration, AFD (Portaria 671) parsing/import, apuração (attendance calculation), time bank, period closure, and punch adjustments. Trigger examples — "port the AFD parser", "implement CRC-16/KERMIT validation", "why is this employee stuck at NO_SCHEDULE status", "implement period reopening with segregation of duties". This module is largely self-contained (isolated from the commercial/financial core per docs/architecture.md) — do not couple it to other domains beyond Organization (legal entity).
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own HR/Timeclock for EDEN, per Master Prompt §6.14 and `eden.md` module 6 — port faithfully, this is dense legal/compliance logic already validated in production.
|
||||
|
||||
## Non-negotiable invariants (`eden.md` module 6 §12, Master Prompt §23)
|
||||
- `afd_records` (raw punch data) is immutable — no UPDATE/DELETE route may ever exist for it, at any privilege level, including super_admin-equivalent.
|
||||
- Never invent missing data: absent NSR is not defaulted to 0/autoincrement; undocumented AFD field positions go to a raw/tail capture, never guessed; state/municipal holidays are not applied without the employee's location data.
|
||||
- Every administrative treatment (punch adjustment) is additive — a new record referencing the original by optional FK, never an UPDATE of the original.
|
||||
- Segregation of duties, twice: creating an adjustment ≠ approving it; advancing period closure ≠ reopening it — these are distinct permissions.
|
||||
- Idempotency in two layers on AFD import: whole-file (SHA-256) and per-record (`device_id + nsr` unique).
|
||||
- Period closure is a veto, not a parallel history — a closed month blocks recalculation/approval/manual entries until an audited reopening, it doesn't duplicate data.
|
||||
- Sequential (never parallel) execution for anything touching the physical device (sync, batch calculation, connection tests) — embedded devices are low-throughput.
|
||||
- CRC-16/KERMIT (poly 0x1021 reflected as 0x8408, init 0x0000, no final XOR) for record types 2/3/4; type 7 uses its own hash chain, never recomputed by EDEN.
|
||||
|
||||
## Process
|
||||
1. Re-read `eden.md` module 6 §1-9 in full before touching parser/apuração logic — field positions and formulas are exact, not approximate.
|
||||
2. Preserve the `America/Sao_Paulo` fixed-timezone handling (Brazil has no DST since 2019) regardless of server timezone.
|
||||
3. Decide explicitly (ADR if changed) whether to apply `overtime_multiplier`/`apply_multiplier_to_time_bank` in the calculation engine — the legacy has the fields but never applies them (see `docs/assumptions.md` #6).
|
||||
|
||||
## Output format
|
||||
- Implementation plus explicit confirmation that `afd_records` has zero write routes beyond insert-on-import.
|
||||
22
.claude/agents/eden-inventory.md
Normal file
22
.claude/agents/eden-inventory.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: eden-inventory
|
||||
description: Use for warehouses, stock movements/ledger, serialized assets (serial/patrimônio/MAC), comodato, installation, and RMA. Trigger examples — "implement the stock reservation flow for a closed quote", "model asset_assignments", "prevent double-allocation of a serial number", "design the RMA flow". Do NOT use for the commercial side of closing a quote (defer to eden-commercial) — this agent owns what happens to physical stock once a quote/contract requires it.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own Inventory/Warehouse/Assets for EDEN, per Master Prompt §6.8 and ADR-0007. This is greenfield — the legacy OrçaFácil has no real stock module to port, only the requirements in the Master Prompt.
|
||||
|
||||
## Responsibilities
|
||||
- Stock balance is always derived from `stock_movements` (ledger) — never an editable balance column.
|
||||
- Every serialized asset (serial/patrimônio/MAC) has a database-enforced constraint preventing two simultaneous "active" assignments of the same identifier — this is a correctness invariant (Master Prompt §15.3), not just an application check.
|
||||
- Model the full install lifecycle: reserve → select specific serialized unit → link to contract/client → move to installed/comodato → track until return/write-off, per Master Prompt §6.8 numbered flow.
|
||||
- `ON DELETE` on stock/asset tables chosen consciously — a decommissioned asset is inactivated, not deleted, when it has movement history.
|
||||
|
||||
## Process
|
||||
1. Confirm warehouse/location belongs to a legal entity (Organization context) before modeling — never a warehouse floating without ownership.
|
||||
2. For every new movement type, confirm it's additive to the ledger (never an UPDATE of a past movement) — corrections are new offsetting movements, mirroring the audit philosophy used elsewhere in EDEN (e.g., timeclock adjustments).
|
||||
3. Coordinate with eden-commercial on the exact trigger point (which contract/quote state transition fires a reservation).
|
||||
|
||||
## Output format
|
||||
- Implementation plus the specific constraint/test proving "same serial never allocated twice" for the change in question.
|
||||
22
.claude/agents/eden-qa.md
Normal file
22
.claude/agents/eden-qa.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: eden-qa
|
||||
description: Use for writing/reviewing unit, integration, contract, and E2E tests, and for verifying the mandatory invariant test cases and minimum E2E flows before a feature is marked done. Trigger examples — "write the E2E for close-quote-with-approval", "did we cover the cross-reseller isolation invariant?", "add a contract test for the Focus NFe adapter mock". This agent verifies correctness; it does not replace eden-code-reviewer (code quality/security review) or the domain agent's own implementation.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own test strategy and coverage for EDEN, per Master Prompt §15.
|
||||
|
||||
## Responsibilities
|
||||
- Pyramid: unit tests for domain/calculation rules, integration tests against a real Postgres container, API tests, contract tests for adapters, Playwright E2E for critical flows.
|
||||
- Track the 15 mandatory minimum E2E flows (Master Prompt §15.2) and the invariant list (Master Prompt §15.3) as a living checklist — a feature touching one of these areas is not done until its corresponding case is automated.
|
||||
- Integration tests must hit a real database, never a mock of Postgres — mocked DB tests have historically masked real migration/constraint failures in systems like this.
|
||||
- For adapters (Focus NFe, SaperX, Control iD), contract tests run against a mock/fixture defined by the domain agent — never against the real external system in CI.
|
||||
|
||||
## Process
|
||||
1. Before marking a feature reviewed, map it against the Master Prompt §15.2/§15.3 lists — flag any invariant it touches that lacks a test.
|
||||
2. Write tests that would actually fail if the invariant were violated (e.g., attempt double-allocation of the same serial in a test and assert the DB/constraint rejects it) — not tests that only exercise the happy path.
|
||||
3. Coordinate with eden-security on which invariant tests double as security tests (cross-tenant isolation, audit immutability).
|
||||
|
||||
## Output format
|
||||
- Test code plus an explicit statement of which Master Prompt §15.2/§15.3 item(s) it satisfies, and which remain uncovered for that feature.
|
||||
26
.claude/agents/eden-security.md
Normal file
26
.claude/agents/eden-security.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: eden-security
|
||||
description: Use for IAM, OWASP hardening, LGPD compliance, encryption/secrets, audit design, and threat modeling across EDEN. Trigger examples — "review this new endpoint for authz", "does this leak data cross-reseller?", "how should we encrypt this new integration token?", "update the threat model for the new SaperX adapter". Use proactively whenever a new public route, a new secret type, or a new cross-tenant data path is introduced.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own security posture for EDEN: IAM, OWASP baseline, LGPD, encryption, audit, per Master Prompt §5 and §12, and `docs/security/threat-model.md`.
|
||||
|
||||
## Responsibilities
|
||||
- Every endpoint must resolve authorization server-side from the session — never trust `role`, `customer_id`, `reseller_id`, `legal_entity_id` from the client (Master Prompt §12).
|
||||
- Classify every new field per Master Prompt §5.4: one-way hash, reversible field encryption (AES-256-GCM, versioned key, root key never in the DB), or plain (with access control + audit) — never "encrypt everything" as a substitute for real classification.
|
||||
- Maintain `docs/security/threat-model.md`: update it whenever a new public route, new secret type, or new integration adapter is added.
|
||||
- Own the invariant test list in Master Prompt §15.3 (cross-reseller/cross-subscriber isolation, audit immutability, no duplicate webhook effects, etc.) — these must exist as automated tests, not just documentation.
|
||||
- Never let `super_admin` bypass audit, even though it bypasses authorization.
|
||||
- Secret scanning discipline: nothing in git/docs/fixtures/logs/screenshots ever contains a real credential (Master Prompt §2.2).
|
||||
|
||||
## Process
|
||||
1. For a new endpoint: confirm authn, authz (resource+action+scope per ADR-0004), input validation, rate limiting where relevant, and audit logging where the action is in the Master Prompt §5.6 minimum list.
|
||||
2. For a new secret: decide hash vs. reversible encryption per §5.4, confirm root key sourcing (env/secret store, never DB), confirm key versioning is wired.
|
||||
3. For a new integration: confirm adapter isolation (Master Prompt §13), webhook auth (HMAC) + idempotency, and that indisponibilidade never corrupts the ERP or blocks readiness.
|
||||
4. Register findings and decisions in `docs/security-findings.md` (incidents) or `docs/security/threat-model.md` (ongoing posture) as appropriate — never reproduce a real secret when documenting a finding.
|
||||
|
||||
## Output format
|
||||
- Findings ranked by severity, each with: file/endpoint, concrete exploit scenario, fix.
|
||||
- For threat-model updates: the diff to `docs/security/threat-model.md`, not a rewrite of the whole file.
|
||||
21
.claude/agents/eden-support.md
Normal file
21
.claude/agents/eden-support.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: eden-support
|
||||
description: Use for the service desk module — tickets, SLA policies/timers, queues, work orders (OS), and asset/contract linkage for support. Trigger examples — "implement SLA pause logic for waiting_customer", "model the ticket escalation queue", "expose ticket creation in the subscriber portal", "add a work order for a technical visit". Do NOT use for the underlying asset/inventory data model (defer to eden-inventory) or the contract data a ticket references (defer to eden-commercial).
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own Support/Service Desk for EDEN, per Master Prompt §6.13. Greenfield — no legacy module to port.
|
||||
|
||||
## Responsibilities
|
||||
- Model: ticket, sequential human protocol number, category/subcategory, priority, impact/urgency, queue, owner, watchers, public/internal comments, attachments, SLA policy, SLA timers, first-response/resolution, justified pauses, escalation, work order (OS), affected assets/contract, root cause/resolution, customer satisfaction.
|
||||
- States: `new → triage → in_progress ⇄ waiting_customer/waiting_third_party → resolved → closed`, plus `cancelled`.
|
||||
- SLA timers must account for a support calendar and valid pauses — a ticket sitting in `waiting_customer` must not burn SLA time by default (configurable).
|
||||
- Subscriber portal: create/track own tickets only. Reseller portal: create/track tickets within its own customer base only — enforce at the query layer, test explicitly (same cross-tenant discipline as eden-commercial).
|
||||
|
||||
## Process
|
||||
1. Link every ticket optionally to a contract/service and to affected assets — never a floating ticket with no traceability when the customer has an active contract.
|
||||
2. Coordinate with eden-security on the exact scope rules for reseller/subscriber visibility before finalizing queries.
|
||||
|
||||
## Output format
|
||||
- Implementation plus the SLA timer test proving pauses are excluded correctly from elapsed time.
|
||||
22
.claude/agents/eden-telecom.md
Normal file
22
.claude/agents/eden-telecom.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: eden-telecom
|
||||
description: Use for telecom-specific contract data (DIDs/circuits), usage/consumption billing, and the SaperX integration adapter. Trigger examples — "map a client to a SaperX circuit", "import CDR consumption for billing", "reconcile SaperX invoice against EDEN invoice", "expose consumption in the subscriber portal". Do NOT use for the STFC tariff fields already on `products` (metered/tariff_rates — those are eden-commercial's pricing model) — this agent owns the external SaperX integration and consumption reconciliation specifically.
|
||||
tools: Read, Grep, Glob, Bash, Write, Edit
|
||||
model: inherit
|
||||
---
|
||||
|
||||
You own the Telecom/SaperX integration for EDEN, per Master Prompt §6.12 and ADR-0010. This is greenfield — no SaperX code exists in the legacy to port; the legacy's only telecom-adjacent data is `products.tariff_rates`/`metered` (owned by eden-commercial) and the "IXC" free-text fields (never a real integration, just manual reference fields).
|
||||
|
||||
## Responsibilities
|
||||
- Build `integrations/saperx` as an isolated adapter/port (Master Prompt §13): encrypted token (AES-256-GCM per ADR-0005), IP-allowlist support if required, timeout/retry/circuit-breaker, correlation id, healthcheck independent of the main `/health/ready`.
|
||||
- Never couple internal entities to SaperX's raw payload — always a normalized DTO plus `external_id` + origin snapshot when needed for reconciliation.
|
||||
- If a needed SaperX endpoint isn't available/documented at implementation time: build the interface + mock + an explicit TODO — never fabricate a plausible-looking response.
|
||||
- Reconciliation (SaperX value × EDEN invoice) produces an exception queue for human review, same philosophy as eden-finance's bank reconciliation.
|
||||
- Subscriber portal exposure of consumption/circuits goes through the normalized DTO, scoped strictly to that customer account.
|
||||
|
||||
## Process
|
||||
1. Confirm with eden-commercial/eden-finance where SaperX-sourced usage data feeds into billing (`usage_charges`) before building the import path.
|
||||
2. Treat SaperX downtime as a non-fatal integration failure — never block core ERP operation or corrupt local state waiting on it.
|
||||
|
||||
## Output format
|
||||
- Implementation plus explicit labeling of what's real (tested against SaperX) vs. mocked pending credentials/docs — never blur the two (Master Prompt §22, "distinguir implementado, integrado em mock, aguardando credencial, não iniciado").
|
||||
84
.claude/hooks/guard_bash.py
Executable file
84
.claude/hooks/guard_bash.py
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
"""PreToolUse guard for the Bash tool (EDEN, Master Prompt §2.1/§3.4).
|
||||
|
||||
Reads the hook input JSON on stdin, inspects tool_input.command, and emits a
|
||||
PreToolUse decision (allow/ask/deny) as JSON on stdout. Fails open (allow)
|
||||
on any internal error so this hook can never itself break a legitimate
|
||||
command — it only ever tightens, never crashes the turn.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
PROJECT_ROOT = "/opt/eden"
|
||||
|
||||
DENY_PATTERNS = [
|
||||
(r"\brm\s+-rf\s+/(\s|$)", "rm -rf / — apagaria o filesystem inteiro"),
|
||||
(r"\brm\s+-rf\s+/\*", "rm -rf /* — apagaria o filesystem inteiro"),
|
||||
(r"\bdocker\s+system\s+prune\b", "docker system prune — remoção ampla, pode afetar outros projetos no host"),
|
||||
(r"\bdocker\s+volume\s+prune\b", "docker volume prune — remoção ampla de volumes, pode afetar outros projetos"),
|
||||
]
|
||||
|
||||
ASK_PATTERNS = [
|
||||
(r"\bdocker\s+volume\s+rm\b", "remoção de volume Docker — confirme que o volume pertence ao EDEN"),
|
||||
(r"(^|\s)ssh\s+\S+@", "SSH para host externo"),
|
||||
(r"(^|\s)scp\s+.*:", "SCP para/de host externo"),
|
||||
(r"(^|\s)rsync\s+.*\S+@\S+:", "rsync para/de host externo"),
|
||||
(r"\b(cat|less|more|head|tail)\s+[^\n|;&]*\.env(\.[a-zA-Z0-9_]+)?\b", "leitura/impressão de arquivo .env"),
|
||||
(r"\b(cat|less|more|head|tail)\s+[^\n|;&]*(credential|secret)", "leitura/impressão de arquivo de credencial/segredo"),
|
||||
(r"~/\.ssh", "acesso a ~/.ssh"),
|
||||
(r"(^|\s)/etc(/|\s|$)", "acesso a /etc"),
|
||||
(r"(^|\s)/root(/|\s|$)", "acesso a /root"),
|
||||
]
|
||||
|
||||
|
||||
def outside_project_paths(command: str):
|
||||
"""Find absolute paths referenced in the command that live outside /opt/eden
|
||||
but under /opt/ (i.e. plausibly another project on this host)."""
|
||||
hits = []
|
||||
for m in re.finditer(r"/opt/([a-zA-Z0-9_.\-]+)(/\S*)?", command):
|
||||
full = m.group(0)
|
||||
if not full.startswith(PROJECT_ROOT):
|
||||
hits.append(full)
|
||||
return hits
|
||||
|
||||
|
||||
def decide(command: str):
|
||||
for pattern, reason in DENY_PATTERNS:
|
||||
if re.search(pattern, command, re.IGNORECASE):
|
||||
return "deny", reason
|
||||
other_projects = outside_project_paths(command)
|
||||
if other_projects:
|
||||
return "deny", f"referencia caminho fora de {PROJECT_ROOT}: {', '.join(other_projects[:3])}"
|
||||
for pattern, reason in ASK_PATTERNS:
|
||||
if re.search(pattern, command, re.IGNORECASE):
|
||||
return "ask", reason
|
||||
return "allow", None
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
payload = json.load(sys.stdin)
|
||||
command = (payload.get("tool_input") or {}).get("command", "") or ""
|
||||
except Exception:
|
||||
# Fail open: if we can't parse input, don't block the tool call.
|
||||
print(json.dumps({}))
|
||||
return
|
||||
|
||||
decision, reason = decide(command)
|
||||
if decision == "allow":
|
||||
print(json.dumps({}))
|
||||
return
|
||||
|
||||
output = {
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": decision,
|
||||
"permissionDecisionReason": f"[eden-guard] {reason} (EDEN_MASTER_PROMPT_CLAUDE.md §2.1/§3.4)",
|
||||
}
|
||||
}
|
||||
print(json.dumps(output))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
77
.claude/hooks/guard_file.py
Executable file
77
.claude/hooks/guard_file.py
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""PreToolUse guard for Read/Write/Edit/Glob/Grep (EDEN, Master Prompt §2.1/§3.4).
|
||||
|
||||
Blocks access to paths outside the project root and to ~/.ssh or /etc, and
|
||||
asks for confirmation before reading a .env/credential-looking file. Fails
|
||||
open on any internal error.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
PROJECT_ROOT = "/opt/eden"
|
||||
HOME = os.path.expanduser("~")
|
||||
|
||||
SECRET_NAME_RE = re.compile(r"(^|/)(\.env(\..+)?|.*credential.*|.*secret.*)$", re.IGNORECASE)
|
||||
|
||||
|
||||
def extract_path(tool_input: dict) -> str:
|
||||
for key in ("file_path", "path", "notebook_path"):
|
||||
if key in tool_input:
|
||||
return tool_input[key] or ""
|
||||
# Grep/Glob use "path" for the search root; pattern itself isn't a filesystem path.
|
||||
return ""
|
||||
|
||||
|
||||
def decide(path: str):
|
||||
if not path:
|
||||
return "allow", None
|
||||
abspath = os.path.abspath(path)
|
||||
|
||||
ssh_dir = os.path.join(HOME, ".ssh")
|
||||
if abspath == ssh_dir or abspath.startswith(ssh_dir + os.sep):
|
||||
return "deny", "acesso a ~/.ssh"
|
||||
if abspath == "/etc" or abspath.startswith("/etc" + os.sep):
|
||||
return "deny", "acesso a /etc"
|
||||
if abspath == "/root" or abspath.startswith("/root" + os.sep):
|
||||
return "deny", "acesso a /root"
|
||||
|
||||
if abspath.startswith("/opt/") and not (
|
||||
abspath == PROJECT_ROOT or abspath.startswith(PROJECT_ROOT + os.sep)
|
||||
):
|
||||
return "deny", f"caminho fora de {PROJECT_ROOT} (outro projeto no host)"
|
||||
|
||||
basename = os.path.basename(abspath)
|
||||
if SECRET_NAME_RE.match(basename):
|
||||
return "ask", f"leitura/escrita de arquivo que parece conter segredo ({basename})"
|
||||
|
||||
return "allow", None
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
payload = json.load(sys.stdin)
|
||||
tool_input = payload.get("tool_input") or {}
|
||||
path = extract_path(tool_input)
|
||||
except Exception:
|
||||
print(json.dumps({}))
|
||||
return
|
||||
|
||||
decision, reason = decide(path)
|
||||
if decision == "allow":
|
||||
print(json.dumps({}))
|
||||
return
|
||||
|
||||
output = {
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": decision,
|
||||
"permissionDecisionReason": f"[eden-guard] {reason} (EDEN_MASTER_PROMPT_CLAUDE.md §2.1/§3.4)",
|
||||
}
|
||||
}
|
||||
print(json.dumps(output))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
44
.claude/hooks/post_write_check.sh
Executable file
44
.claude/hooks/post_write_check.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# PostToolUse hook for Write|Edit (EDEN, Master Prompt §3.4).
|
||||
# Best-effort incremental lint/typecheck for files under apps/, packages/, infra/.
|
||||
# Fails open: if pnpm/node/turbo aren't installed yet (Fase 0 / early Fase 1),
|
||||
# this prints a short notice and exits 0 without blocking anything.
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_ROOT="/opt/eden"
|
||||
INPUT_JSON="$(cat)"
|
||||
|
||||
FILE_PATH="$(python3 -c '
|
||||
import json, sys
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
ti = data.get("tool_input") or {}
|
||||
print(ti.get("file_path") or ti.get("notebook_path") or "")
|
||||
except Exception:
|
||||
print("")
|
||||
' <<< "$INPUT_JSON")"
|
||||
|
||||
# Only act on files under apps/, packages/, or infra/.
|
||||
case "$FILE_PATH" in
|
||||
"$PROJECT_ROOT"/apps/*|"$PROJECT_ROOT"/packages/*|"$PROJECT_ROOT"/infra/*) ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
|
||||
if ! command -v pnpm >/dev/null 2>&1; then
|
||||
echo '{"systemMessage":"[eden-hook] pnpm ainda não está instalado neste ambiente — lint/typecheck incremental pulado (esperado na Fase 0/início da Fase 1)."}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -f "$PROJECT_ROOT/package.json" ]; then
|
||||
echo '{"systemMessage":"[eden-hook] Monorepo ainda não inicializado (sem package.json na raiz) — lint/typecheck incremental pulado."}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
if pnpm turbo run lint typecheck --filter="...[HEAD^1]" >/tmp/eden-post-write-check.log 2>&1; then
|
||||
exit 0
|
||||
else
|
||||
TAIL="$(tail -n 20 /tmp/eden-post-write-check.log | tr '\n' ' ' | cut -c1-800)"
|
||||
echo "{\"systemMessage\":\"[eden-hook] lint/typecheck incremental falhou: ${TAIL}\"}"
|
||||
exit 0
|
||||
fi
|
||||
35
.claude/hooks/stop_secret_check.sh
Executable file
35
.claude/hooks/stop_secret_check.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# Stop hook (EDEN, Master Prompt §2.2/§3.4). Advisory only — never blocks.
|
||||
# If the project is under git, scans the working tree diff (staged+unstaged)
|
||||
# for obvious secret patterns and for critical TODO/FIXME markers introduced
|
||||
# without a tracking reference. Silent (no output) when there's nothing to
|
||||
# flag or when git/the repo isn't set up yet (expected in Fase 0).
|
||||
set -uo pipefail
|
||||
|
||||
PROJECT_ROOT="/opt/eden"
|
||||
cd "$PROJECT_ROOT" 2>/dev/null || exit 0
|
||||
|
||||
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
DIFF="$(git diff HEAD 2>/dev/null; git diff --cached 2>/dev/null)"
|
||||
[ -z "$DIFF" ] && exit 0
|
||||
|
||||
SECRET_HITS="$(echo "$DIFF" | grep -E -i '^\+.*(AKIA[0-9A-Z]{16}|BEGIN (RSA|EC|OPENSSH|PRIVATE) KEY|password\s*=\s*["'"'"'][^"'"'"']+|api[_-]?key\s*=\s*["'"'"'][^"'"'"']+|secret\s*=\s*["'"'"'][^"'"'"']+)' || true)"
|
||||
TODO_HITS="$(echo "$DIFF" | grep -E -i '^\+.*(TODO|FIXME).*(CRITICAL|SECURITY|URGENT)' || true)"
|
||||
|
||||
if [ -z "$SECRET_HITS" ] && [ -z "$TODO_HITS" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
MSG="[eden-hook] Verificação de fim de etapa (Master Prompt DoD):"
|
||||
if [ -n "$SECRET_HITS" ]; then
|
||||
MSG="$MSG Possível segredo em claro no diff (revisar antes de commitar)."
|
||||
fi
|
||||
if [ -n "$TODO_HITS" ]; then
|
||||
MSG="$MSG TODO/FIXME crítico introduzido sem rastreamento (issue/ADR)."
|
||||
fi
|
||||
|
||||
python3 -c "import json,sys; print(json.dumps({'systemMessage': sys.argv[1]}))" "$MSG"
|
||||
exit 0
|
||||
50
.claude/settings.json
Normal file
50
.claude/settings.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"/opt/eden/.claude/hooks/guard_bash.py\"",
|
||||
"timeout": 10
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "Read|Write|Edit|Glob|Grep",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"/opt/eden/.claude/hooks/guard_file.py\"",
|
||||
"timeout": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash \"/opt/eden/.claude/hooks/post_write_check.sh\"",
|
||||
"timeout": 120,
|
||||
"statusMessage": "Rodando lint/typecheck incremental (EDEN)..."
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash \"/opt/eden/.claude/hooks/stop_secret_check.sh\"",
|
||||
"timeout": 15
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
21
.claude/skills/eden-domain/SKILL.md
Normal file
21
.claude/skills/eden-domain/SKILL.md
Normal 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).
|
||||
14
.claude/skills/eden-domain/references/legacy-orcafacil.md
Normal file
14
.claude/skills/eden-domain/references/legacy-orcafacil.md
Normal 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 |
|
||||
|---|---|---|
|
||||
| 1–97 | Intro / how to use this doc | Reading order, why not to implement everything at once |
|
||||
| 97–687 | 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 |
|
||||
| 690–1450 | 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 |
|
||||
| 1451–2206 | 3. Client & Reseller Registration | `client_registrations`, PF/PJ differences, partners/QSA, public token flow, reseller "Programa de Canais", storage/attachment access control |
|
||||
| 2207–2822 | 4. Documents, PDF, E-signature | Tiptap templates, merge fields, Chromium PDF rendering + sanitization, signature envelope state machine, OTP, hash-chain audit, public verification |
|
||||
| 2823–3143 | 5. Fiscal (NCM, CFOP, municipalities) | Fiscal catalogs, sync (auto/manual), `product_fiscal_profiles`, upsert safety thresholds |
|
||||
| 3144–4141 | 6. Timeclock (Ponto Eletrônico) | Control iD integration, AFD parsing/CRC, apuração engine, time bank, period closure, punch adjustments |
|
||||
| 4142–4597 | 7. Backoffice diverso | Backup (streaming pg_dump/restore), meeting room/vehicle agenda, welcome page, companies (operational view), Management/ManagerDashboard, mailer, S3 |
|
||||
19
.claude/skills/eden-domain/references/state-machines.md
Normal file
19
.claude/skills/eden-domain/references/state-machines.md
Normal 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`.
|
||||
5
.claude/skills/eden-domain/references/terminology.md
Normal file
5
.claude/skills/eden-domain/references/terminology.md
Normal 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).
|
||||
15
.claude/skills/eden-finance/SKILL.md
Normal file
15
.claude/skills/eden-finance/SKILL.md
Normal 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.
|
||||
7
.claude/skills/eden-finance/references/billing.md
Normal file
7
.claude/skills/eden-finance/references/billing.md
Normal 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).
|
||||
4
.claude/skills/eden-finance/references/dunning.md
Normal file
4
.claude/skills/eden-finance/references/dunning.md
Normal 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`.
|
||||
6
.claude/skills/eden-finance/references/receivables.md
Normal file
6
.claude/skills/eden-finance/references/receivables.md
Normal 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).
|
||||
6
.claude/skills/eden-finance/references/reconciliation.md
Normal file
6
.claude/skills/eden-finance/references/reconciliation.md
Normal 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.
|
||||
18
.claude/skills/eden-fiscal/SKILL.md
Normal file
18
.claude/skills/eden-fiscal/SKILL.md
Normal 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).
|
||||
5
.claude/skills/eden-fiscal/references/focus-nfcom.md
Normal file
5
.claude/skills/eden-fiscal/references/focus-nfcom.md
Normal 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.
|
||||
3
.claude/skills/eden-fiscal/references/focus-nfse.md
Normal file
3
.claude/skills/eden-fiscal/references/focus-nfse.md
Normal 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).
|
||||
3
.claude/skills/eden-fiscal/references/rental-receipt.md
Normal file
3
.claude/skills/eden-fiscal/references/rental-receipt.md
Normal 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.
|
||||
13
.claude/skills/eden-inventory/SKILL.md
Normal file
13
.claude/skills/eden-inventory/SKILL.md
Normal 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.
|
||||
@@ -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.
|
||||
7
.claude/skills/eden-inventory/references/stock-ledger.md
Normal file
7
.claude/skills/eden-inventory/references/stock-ledger.md
Normal 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.
|
||||
21
.claude/skills/eden-security/SKILL.md
Normal file
21
.claude/skills/eden-security/SKILL.md
Normal 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.
|
||||
10
.claude/skills/eden-security/references/audit.md
Normal file
10
.claude/skills/eden-security/references/audit.md
Normal 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.
|
||||
@@ -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.
|
||||
8
.claude/skills/eden-security/references/encryption.md
Normal file
8
.claude/skills/eden-security/references/encryption.md
Normal 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.
|
||||
13
.claude/skills/eden-security/references/security-baseline.md
Normal file
13
.claude/skills/eden-security/references/security-baseline.md
Normal 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.
|
||||
13
.claude/skills/eden-telecom/SKILL.md
Normal file
13
.claude/skills/eden-telecom/SKILL.md
Normal 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.
|
||||
5
.claude/skills/eden-telecom/references/saperx.md
Normal file
5
.claude/skills/eden-telecom/references/saperx.md
Normal 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.
|
||||
5
.claude/skills/eden-telecom/references/usage-billing.md
Normal file
5
.claude/skills/eden-telecom/references/usage-billing.md
Normal 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`.
|
||||
13
.claude/skills/eden-timeclock/SKILL.md
Normal file
13
.claude/skills/eden-timeclock/SKILL.md
Normal 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.
|
||||
10
.claude/skills/eden-timeclock/references/afd-671.md
Normal file
10
.claude/skills/eden-timeclock/references/afd-671.md
Normal 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.
|
||||
9
.claude/skills/eden-timeclock/references/controlid.md
Normal file
9
.claude/skills/eden-timeclock/references/controlid.md
Normal 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.
|
||||
Reference in New Issue
Block a user