Information flows
Eight real flows and five failure scenarios, built from the code of the gateway, business-contabeleza and accounting.
Flow player
🧭How to use
- Pick a scenario, then press ▶ Play — or step with Next ▶ / ◀ Prev (← / → keys work once the player has focus).
- Click any arrow in the diagram, or any step in the list below it, to jump there; the note explains what happens and shows payloads.
- Solid arrow = request (RPC) · dashed = asynchronous message/webhook · dotted = reply. Components are explained in Architecture — components.
Communication patterns
Eight ways information moves. Each card shows who starts the exchange (highlighted) and the kind of link.
Client → platform
Apps call one public host (api.contabeleza.com.br) with JSON:API, a bearer token and ilm-business.
Gateway → service RPC
A RabbitMQ message with a reply queue and correlation id; the gateway waits up to 15 s for the reply.
Tenant wrapper → accounting
business-contabeleza checks that the business/professional belongs to the tenant, then forwards to accounting with the same context.
Stored callback
The caller tells accounting which service / controller#action to notify; accounting calls it on every status change.
Self-message
Slow checks are queued back to the same service so the request returns at once.
Provider webhook
Providers call a public route; accounting applies the status. A worker polls as a safety net.
n8n webhook
Status changes are posted to n8n with the record and its changes; failures are logged, never raised.
n8n postback
n8n reports the outcome of a manual step through public postback routes that reuse the normal actions.
Consistency
🔒Strong
Inside one service call: the write and the response come from PostgreSQL in the same request.
⏱️Eventual (providers)
NFS-e status, credential validation, DAS, diagnosis areas and revenue depend on external systems: the API returns a pending/processing state and the record is completed later.
🗃️Cache
Cacheable GETs are cached per business in the gateway and invalidated by the writing controller. Fiscal reads that change in the background (diagnosis, revenue) are declared cache: false.
🧾Cached provider data
accounting keeps its own copy of provider data (DAS, MEI areas, monthly revenue) and refreshes it on demand or when a month closes, so reads stay fast and cheap.
Context propagation
The context built by the gateway (business_id, account_id, professional_id, author_type/author_id, permissions, request id) travels with every message — including business-contabeleza → accounting calls, which add source: contabeleza — so authorship, tenancy and the platform of origin stay consistent across services. Sentry correlates the hops.
Failure handling
What happens when something goes wrong — from a validation error to a lost provider webhook. Red arrows are failures (✕), dash-dot arrows are retries or compensations.
🧭How to read
- Same controls as the flow player. Each scenario ends with the recovery path and what a client should do.
↩️Errors are passed through
The gateway returns the service error as-is: status + { title, code, status, detail }.
⌛504 ≠ not done
The gateway gives up after 15 s; the service keeps going. Re-read before retrying a write.
🔁Workers close the gaps
The invoice sync worker recovers lost eNotas webhooks; the revenue cleanup re-queues stuck months.
🔑Credentials fail late
Storing a credential always succeeds; read validation_status / emission_status to know if it works.
📣Webhooks don't block
n8n webhooks and email notifications never fail the user request.