feat(inbound): log every message that arrives, and on which inbox - #105
Merged
Conversation
Two inboxes run in parallel -- the worker (authenticated as the VTA DID) and the approver (a distinct did:key) -- and the mediator routes inbound by the authenticating DID. Nothing logged an arrival on either, so a message delivered to the wrong inbox and a message never sent at all produced identical console output: none. That ambiguity cost real time. Chasing "the approver is never prompted" came down to proving a negative in the extension while the sender insisted it had pushed correctly; the console could not distinguish "nothing arrived" from "arrived and was mishandled". Log type, id, from and to at the top of the handler, before anything can drop the message, tagged with which inbox received it. `to` is the field that matters: a task-consent/request is addressed to the approver DID, so seeing one land on the worker inbox is a routing bug rather than a missing message -- previously indistinguishable. Logging only; no behaviour change. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
stormer78
added a commit
that referenced
this pull request
Aug 7, 2026
) parseTaskConsentRequest returned "not-a-task-consent-request" for two completely different situations: a message not addressed to this handler, and a genuine consent request whose payload is unusable. dispatchInbound keys on that reason to decide whether to stay quiet: if (consent.reason !== "not-a-task-consent-request") { warn; return; } // Anything else is ignored. <- silent So a malformed consent request was discarded in total silence -- no prompt, no log -- and handleInbound's finally then cleared its pending record. The result is indistinguishable from a message that never arrived, which is how it presented: arrival logged by #105, then nothing at all, and a pending-approval badge (#110) that counted zero because the record was already gone. Malformed payloads now return "malformed-payload", so the existing warn path reports them with their detail. The silent reason keeps its single honest meaning: not addressed to this handler. The test that pinned the old shared reason now pins the distinction and the detail, with the reasoning recorded -- it was asserting the exact behaviour that hid this. Signed-off-by: Glenn Gore <glenn.g@affinidi.com>
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.
Two inboxes run in parallel — the worker (authenticated as the VTA DID) and the approver (a distinct
did:key) — and the mediator routes inbound by the authenticating DID. Nothing logged an arrival on either.So a message delivered to the wrong inbox and a message never sent at all produced identical console output: none.
Why
Chasing a live "the approver is never prompted" report came down to proving a negative inside the extension while the sender's logs insisted it had pushed correctly. The console could not distinguish "nothing arrived" from "arrived and was mishandled", and that ambiguity took several rounds of cross-service log comparison to resolve.
What changed
type,id,fromandtoare logged at the top ofonInboundMessage, before anything can drop the message, tagged with which inbox received it.tois the field that earns its place: atask-consent/request/0.1is addressed to the approver DID, so one landing on the worker inbox is a routing bug — and was previously indistinguishable from a message that never existed.Logging only. No behaviour change.
Follow-up, deliberately not in this PR
The plugin never queries the mediator queue: it enables live delivery via the library and sees only what arrives while connected. There is no
status-request/delivery-requestpath, so a backlog queued before connect is never fetched.Draining it properly is larger than it first appears. Per
mediator-transport.js, live delivery pushes bare inner JWEs as raw text frames — the mediator "does NOT re-wrap it in a forward". Adelivery-requestinstead replies with apickup/3.0/deliveryenvelope carrying attachments, a shape the transport never unwraps. So it needs: the resolved mediator endpoint surfaced onMediatorConnection,requestStatus/requestDeliveryonMediatorClient, attachment unwrapping, then feed-through toonInboundMessageand ack viamessages-received.The ordering there is load-bearing and is why this is not being rushed:
pending.tsdocuments that atask-consent/requestlost between delivery and durable storage is unrecoverable — the challenge and payloadDigest are gone, and the executor waits for a decision that can never arrive. Ack-before-store loses messages silently.Expiry for that drain has to be read from the payload, not the transport: neither DIDComm (
expires_timedeliberately unset) nor TSP (no expiry field at all) carries one here, sotask-consent/request/0.1's ownexpiresAtis the only source. An expired request should be acked and dropped without prompting — showing a code for a request the executor has already forgotten would fail asno_pendingand train the operator to approve whatever appears.