@fayz-ai/plugin-fiscal-br
v0.2.2
Published
[preview] Brazilian fiscal addon for asynchronous NFC-e emission through PlugNotas
Maintainers
Readme
@fayz-ai/plugin-fiscal-br
Status: preview. Sandbox and SEFAZ homologation only; production emission is intentionally not exposed by this package.
plugin-fiscal-br is the Brazilian fiscal addon hosted by
@fayz-ai/plugin-financial. Its first provider is TecnoSpeed PlugNotas and its
first document journey is NFC-e (model 65) for a completed restaurant order.
npm install @fayz-ai/plugin-fiscal-brOwnership boundary
plugin-financialownsplg_financial_nfe, the fiscal document shown to the operator. There is no second PlugNotas invoice table.plugin-fiscal-browns the provider connection contract, durable command, retry/recovery trail, webhook receipt and emitter claim.- The app owns the Edge Function implementation and the setup panel, because it owns deployment, origins and product-specific composition.
packages/dbownsconnections,ordersanditems. The addon consumes those canonical contracts; it does not recreateplg_connectionsororder_itemsfrom the pre-squash implementation.
Why the command is durable
Sending an NFC-e and losing the HTTP response is ambiguous: the provider may have accepted the document even though the caller timed out. Repeating the POST without first consulting the provider can create a duplicate fiscal effect.
The migration therefore creates plg_fiscalbr_nfce_jobs before any provider
call. The job keeps a frozen order snapshot and a stable idempotency key. A
timeout moves it to waiting; a recovery worker claims it with SKIP LOCKED,
queries PlugNotas and only retries with the same integration id when the
provider confirms the first request does not exist. Webhooks and recovery update
the same job and the same plg_financial_nfe row.
Credential and certificate boundary
The browser stores no PlugNotas API key, A1 bytes, A1 password, CSC code or CSC
token. The setup form uploads the A1 and its password to the app-owned server
boundary over the authenticated request; the boundary forwards them to the
provider and discards them. connections.settings receives only readiness and
non-secret metadata such as expiry and an optional fingerprint.
CSC belongs to the emitter. It must be collected during that tenant's setup and
sent to the server boundary. It is not a pool-wide PLUGNOTAS_CSC_CONFIG_JSON
secret and cannot be shared between tenants. This package deliberately removed
that old draft contract.
The PlugNotas software-house API key remains a server-only deployment secret. No secret value is committed here; the manifest contains names only so deploy and diagnostics can report missing configuration.
Runtime contract
import { createFinancialPlugin } from '@fayz-ai/plugin-financial'
import {
createPlugNotasFinancialProvider,
createPlugNotasPlugin,
} from '@fayz-ai/plugin-fiscal-br'
const fiscalProvider = createPlugNotasFinancialProvider({
base: financialProvider,
gateway: appOwnedPlugNotasGateway,
})
const plugins = [
createFinancialPlugin({
dataProvider: fiscalProvider,
fiscalProvider: {
label: 'PlugNotas',
models: ['nfce'],
requiresOrder: true,
},
}),
createPlugNotasPlugin({ SetupPanel: AppOwnedSetupPanel }),
]The decorator never trusts a transient provider response as the ledger. Issue, refresh and cancel always return the document read back from the database after the server operation. XML, DANFCE and cancellation XML use short-lived URLs resolved on demand instead of durable signed URLs stored on the fiscal row.
What this draft does not authorize
- It does not apply the migration to a Supabase project.
- It does not deploy the Edge Function.
- It does not create or rotate any secret.
- It does not enable production emission.
- It does not claim homologation passed; that needs a real emitter, A1, CSC and an observed issue/status/artifact/cancel journey.
The companion NeoChef PR supplies the application Edge Function and composition.
The full ownership map and rollout gates are documented in
docs/integrations/PLUGNOTAS-NFCE.md.
