Joystick joins the catalog (Basic client auth, rotatesRefreshTokens), resolves
identity by channel id, and is a streampixels managed-connection provider only:
it is not an identity provider for the profile (ruling signin-waits-for-public-bot).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Soul pass 5, S5-4: the provider-error tests proved only that the word
CANARY was absent, so a message carrying a 16-byte slice of the body (X1,
X2) passed, and the Bifrost success reply was checked with
objectContaining, so a 9-byte body head (X5) rode along. Each provider
error's message is now pinned exactly, the Bifrost success reply is pinned
as exactly status, supportFact and bifrostStatus, and every canary body
starts with the canary, so any prefix of it shows.
S5-5: errorIdentity's class and code filters had no test (X3, X4). Cases
now show a code or class name that carries input, is too long, is not a
string, or comes from a thrown non-Error or null is dropped, and a short
identifier survives.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Soul pass 5, S5-3: auth_completion_created stored completion.code, which
the unauthenticated redeem route turns into the session until it expires
(300 s by default), so the audit trail could redeem a live sign-in. The
two auth_completion_redeemed events (the HTTP redeem route and the private
command plane's redeem by attempt) stored the spent code as well.
All three payloads drop it. Nothing reads audit payloads back: the store
has no audit read, and no repository indexed by VoidBot consumes these
events. The event's sessionId already names the completion (one per
callback), so no replacement key is added. This matches Heimdall's own
witness contract, which says codes are redacted from audit exports.
Tests drive a sign-in through the HTTP redeem route and through the plane,
pin each payload exactly, and check the code appears in no audit event.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Soul pass 4, F1: a provider's 2xx refresh answer that was not JSON made
JSON.parse quote the text around the fault, a refresh-token fragment among
it, and the plane returned that message in the reply's diagnostics. Those
travel outside the sealed envelope and Ghostlight logs them.
The plane's diagnostic is now fixed text plus the error's class and code,
through errorIdentity, which the failed-callback audit event now shares.
Every provider body Heimdall parses goes through readProviderJson: a
non-2xx answer or a body that is not JSON becomes a ProviderResponseError
(status and code, provider_status or provider_body_not_json) and no
parser message survives. This replaces ProviderHttpError and the separate
parses in the Discord guild lookup and the YouTube channel lookup.
Soul's canary probe is committed inverted: a refresh against a malformed
2xx body and against a 400 whose body holds the canary; no byte of it may
appear in the reply or its decoded failure payload.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>