Document the webhook contract in the README
I maintainer di solito rispondono entro 2 giorni
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 70/100
- Tipo di issue
- Documentazione
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- nodejs, typescript
- Ambito
- backend, documentation
Direzione di ricerca
Start by reading the webhook source the issue names: backend/src/modules/webhooks/dispatcher.ts for the envelope and signature, and backend/src/modules/submissions/verdict.ts for when the events fire. Then replace the two-line note at README.md lines 230-231 with a ### Webhooks section, and check the receiver snippet against openssl dgst -sha256 -hmac. Done when each statement matches the cited file and line, the acceptance criteria are met, and git diff --stat shows only README.md.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
The README lists webhook event names and a header name in two lines, and nothing else. A marketplace integrating with Verity cannot tell what the payload looks like, how to verify the signature, whether a failed delivery is retried, which URLs are accepted, or which verdicts send nothing. Write a short webhook reference that is accurate to the code.
Background
A marketplace (or any account that submits work) can register webhook URLs to be told when a submission's status changes (README "API"; docs/ARCHITECTURE.md, "Backend", modules/webhooks/). README "Known limits" already says "webhooks are delivered once with no retry". Because the payload is signed with a shared secret, receivers must verify it, and a wrong description in the README would lead integrators to trust or reject the wrong bytes.
Current behaviour
README.md lines 230-231 (the whole current documentation):
Webhooks (HMAC-SHA256 in `x-verity-signature`): `submission.verified`,
`submission.slashed`, `submission.disputed`.
Facts to document, each verified in the code (re-find line numbers by function name if they have moved):
- Registration:
POST /v1/marketplaces/:id/webhooks,backend/src/modules/marketplaces/routes.tsline 26. Requires a bearer token. Body:url(string, valid URL),secret(string, at least 8 characters),events(non-empty array of strings). The caller must be the marketplace's own account, otherwise 403{ "error": "only the marketplace's own account can manage its webhooks" }. The URL is checked withassertPublicHttpUrl(line 40) and the row is returned with 201. Event names are not validated against a list: a subscription only receives events whose name is in itseventsarray (dispatcher.tsline 14). - Which marketplace: a submission belongs to the marketplace of the account that submitted it.
POST /v1/submissionscallsfindOrCreateMarketplaceForAccount(agent)(backend/src/modules/submissions/routes.tslines 158 and 56-68 of marketplaces/routes.ts), which creates a marketplace named after the account's address on first use.POST /v1/marketplaces(line 8) returns the existing marketplace for the caller if there is one, so a webhook is subscribed on behalf of the account that submits the work. - Events and when they fire:
submission.verifiedandsubmission.slashed:recordTerminalVerdictinbackend/src/modules/submissions/verdict.ts, lines 58-64, only on the call that actually moves the submission into that status (transitioned), so once per submission. Payloaddata:{ submission_id, status, tx_hash }wheresubmission_idis Verity's own UUID for the submission,statusis"verified"or"slashed", andtx_hashis the finalize or resolve transaction hash, ornullwhen the transition was observed by the reconcile pass.submission.disputed:backend/src/workers/indexer.ts, casechallenge_opened, dispatched only when the challenge row is newly inserted.data:{ submission_id, status: "disputed", tx_hash }with the hash of the challenge transaction.expired_unverifiedsends nothing: the condition on verdict.ts line 58 isterminal === "verified" || terminal === "slashed". A verdict ofverifiedcan be a "verified by default" window outcome; the event name does not say how it was reached (the submission'sresolution_method, fromGET /v1/submissions/:id, does).
- Request:
backend/src/modules/webhooks/dispatcher.ts. Method POST, headerscontent-type: application/jsonandx-verity-signature, bodyJSON.stringify({ event: eventType, data: payload })(line 15), so the envelope is{ "event": "submission.verified", "data": { ... } }. - Signature (line 16):
createHmac("sha256", sub.secret).update(body).digest("hex"). It is the lowercase hex HMAC-SHA256 of the exact request body string, keyed with thesecretgiven at registration. Verify against the raw body bytes, not a re-serialised object. - Delivery: one attempt, no retry (
attempts: 1is written on both the success and the failure path).fetchusesredirect: "error"(line 27), so a redirect fails the delivery. A request that does not finish within 30 seconds is aborted by the global fetch timeout inbackend/src/config/net.ts. A 2xx response is recordeddelivered, anything elsefailed, in thewebhook_deliverytable; there is no API to read those rows. The webhook is dispatched inline during verdict handling and its failure is only logged. - URL rule:
backend/src/modules/webhooks/url-guard.ts,assertPublicHttpUrl. Onlyhttp:andhttps:; the host must resolve, and an address in a private, loopback or link-local range is refused with 400 (webhook host <host> resolves to a non-public address). The check runs at registration and again at send time. Describe it as "public addresses only" without listing every range.
Expected behaviour
The README has a webhook reference section, linked from the API section, that an integrator can implement a receiver from, including a signature check.
Proposed approach
- Read the source locations in the list above.
- In
README.mdreplace the two-line webhook note (lines 230-231) with a subsection (suggested### Webhooks) containing: how to register (request body, auth, who may register, which account's submissions it covers); a table of the three events with when each fires and thedatafields; the example envelope{"event":"submission.verified","data":{"submission_id":"<uuid>","status":"verified","tx_hash":"<hash or null>"}}clearly marked as a shape example with placeholders (no fabricated real ids); the signature rule (fact 5) and a short Node receiver snippet usingcreateHmacandtimingSafeEqual; the delivery rules (fact 6); the URL rule (fact 7); and the sentence thatexpired_unverifiedsends no webhook. - Test your signature snippet yourself: compute the expected signature for a sample body with both your snippet and
openssl dgst -sha256 -hmac "<secret>"and confirm they match. Say in the PR how you checked. - Keep the "Known limits" bullet about no retry as it is; make sure the new section agrees with it.
- Pitfalls:
submission_idis the Verity UUID, not the on-chain numeric id; do not call the signature "base64"; do not claim retries, a delivery log API, or a delivery guarantee; do not imply thatsubmission.verifiedalways means consensus.
Files
README.md: replace the two-line webhook note with a reference section; no other edits.
Acceptance criteria
- The three events are listed with their trigger and
datafields, and it is stated thatexpired_unverifiedsends nothing. - The envelope
{ event, data: { submission_id, status, tx_hash } }is documented, with a note thatsubmission_idis Verity's UUID andtx_hashcan benull. - The signature is described as hex HMAC-SHA256 over the raw body with the registration secret, in the
x-verity-signatureheader, with a receiver snippet you tested. - No retry, one attempt, no redirects, and the 30 second timeout are stated.
- The public-address-only URL rule and the registration requirements (auth, own account,
secretat least 8 characters,eventsnon-empty) are stated. - The text says the event name does not say whether a
verifiedverdict was reached by consensus or by the window elapsing. - No other part of the README changed.
How to verify
- Re-read each statement against the file and line named above.
- Run the snippet against a sample body and compare with
printf '%s' '<body>' | openssl dgst -sha256 -hmac '<secret>'. - Optionally run
pnpm dev, register a webhook withPOST /v1/marketplaces/:id/webhookspointing at a public request-catcher URL you control, and confirm the payload and header (needs a funded testnet account; skip if you cannot and say so). git diff --statshows onlyREADME.md.
Out of scope
- Adding retries, a delivery log endpoint, new events, or changing the payload or signature scheme.
- Documenting other endpoints or the attestation format (separate issues).
- Changes to
url-guard.tsor the dispatcher.
Notes
Difficulty: medium; the facts are listed, the work is accuracy and a tested snippet. Merge-conflict hotspot: three documentation issues edit README.md (this one, the attestation verification section and the API auth/error table). Edit only your own section and rebase if another lands first. Line numbers refer to the working tree when this issue was written.
- Lingua principale
- TypeScript
- Stelle
- 0
- Fork
- 1
- Merge medio
- 1g 22h
- PR unite (30g)
- 106
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Issue simili
-
area:frontend kind:bug priority:p2 ready
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
handsontable/hyperformula#1879 ·
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
RunestoneInteractive/rs#1661 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
capricorn86/happy-dom#2594 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
I maintainer di solito rispondono entro 1 giorno