covenant-invoica: capability-gated, audit-logged connector for Invoice + settlement#113
Open
mizuki0x wants to merge 1 commit into
Open
covenant-invoica: capability-gated, audit-logged connector for Invoice + settlement#113mizuki0x wants to merge 1 commit into
mizuki0x wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
covenant-invoica, a read-only-first connector that exposes Invoica as native, capability-gated, audit-logged Covenant tools. Covenant scopes, brokers, and audits the call; Invoica keeps the money and compliance rail. Nothing here touches settlement custody.What it adds
Four MCP tools, all off by default (
COVENANT_INVOICA_ENABLED+ an API key required):invoica.invoice.create: create an invoice (amountin dollars,customerEmail,customerName, optionalcurrency/chain/buyerCountryCode/companyId)invoica.invoice.get: fetch by idinvoica.invoice.list: list with status/paging filtersinvoica.settlement.check: settlement status for an invoiceThe daemon brokers the API key: it lives in the client, injected as
Authorization: Bearer, and never enters config, the operator token, or the audit log. Every call is capability-gated (tool.call.invoica.*) and lands on the audit chain through the daemon's generic tool path, so there is no bespoke dispatcher.Contract targeted
Built against the backend
openapi.jsonrather than the published@invoica/sdk, because the SDK is missing the/v1/mandates*(PACT) and/api/x402/*surface the live backend exposes. Env values are trimmed at the boundary, arguments are validated before any HTTP call, GET retries a cold-starting gateway and honorsRetry-After, create is single-shot (a created invoice is not idempotent), and an empty or null success body surfaces as an error rather than a null invoice. 20 tests, clippy clean, fmt clean. Verified end to end through the real daemon and acovenantCLI against an OpenAPI-accurate mock, and separately by a cold-user pass that confirmed the key never appears in tool output.Blocked on / open questions for @SkinGem
Live validation is not yet possible and the contract has some internal drift worth confirming:
api.invoica.aiis returning 502 on every endpoint (health,/v1/invoices,/api/x402/*,/v1/mandates), held for 25s+ so it reads as a dead upstream, not a cold start.app.invoica.aiis 200. A working API and a devnet/test key would let us validate live.openapi.json(last updated May 19) andbackend/src/routes/invoices.ts(June 12) disagree on the create-invoice body. The spec lists requiredcustomerEmail/customerName/amountwithchainoptional; the handler destructuresinvoiceNumber/amount/currency/customerEmail/customerName/companyIdand never readschainorbuyer*. Which is canonical? The connector currently follows the spec.amountunit: confirmed dollars from the handler (parseFloat, no x100); the OpenAPI leaves it undescribed. Flagging so it stays that way./api/x402/settle(orsettlement.*webhooks).invoica.settlement.checkcurrently projects status fromGET /v1/invoices/:id; the paid path is Phase 2.Not in this PR (Phase 2+)
Provenance envelope per payment, live x402 + SAP escrow, tax (
/api/x402/tax, paid), and the PACT-mandate to capability directional mapping.