Serve the vault bearer for a tombstoned main - #155
Merged
Merged
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.
Fixes #154. Two commits: the resolver and catch fix, then the auth-menu quota deps the same census turned up.
The resolver
resolveMainAccessForCustodysits beside the fallback custody resolution inindex.ts, and mirrorsresolveFallbackAccessrather than inventing a second shape:no-handle→blocked→reauth→peek→ expiry, each a named refusal. Peek-only, so the request path still never blocks on the vault; refill stays on the tick.The catch, which you called the actual bug
A custody-owned main now resolves through the resolver and never enters the refresh/catch path at all — the branch that reads
currentAuth.access ?? ''is structurally unreachable for a tombstoned slot.CustodyTombstoneRefreshErrorno longer arrives at a handler written for transient errors, because the refusal is decided before the refresh is attempted rather than caught after it.Custody refusals log at warn on the custody channel with their reason. That is deliberate beyond readability: Claustrum's
auth_eventsonly sees a report if we send one, so an empty-bearer 401 swallowed into a stale-token fallback never reaches the vault side at all — and from their chain, a successfulcredential.getfollowed by an upstream 401 is indistinguishable from a genuine expiry. A silent client does not just fail to inform them, it produces a plausible wrong answer on their side.Fail closed, no local fallback
Your constraint is the one I checked hardest, since it is the invariant the feature rests on. A refused main:
index.ts:3209), so it is excluded rather than degraded:4129) instead of callingsendWithAccessToken, so no empty bearer ever reaches the wirecurrentAuth.access— that assignment lives in the non-custodyelsebranch, so the local slot is unreachable from a custody-owned main under every failure modeCold,
needs_reauth,identity_mismatchandno_handleall land there. The second owner the tombstone exists to prevent cannot be created by this path.Tests
Your red proof is the acceptance gate and it passes. Three mutations, each reverting one change alone:
The refusal test asserts the fallback's bearer on the wire, not that no error was thrown — a refusal that silently served nothing would pass the weaker form. Local mode is pinned byte-identical.
Scope
No general empty-bearer guard here, per your note that you are taking it and holding it so the two do not collide. Worth saying that yours is the stronger of the two fixes: mine stops this defect reaching the wire, yours stops the whole class announcing itself as somebody else's 401.
Gates from the repo root:
build,format:check,lint,types,testall pass. Core 146, opencode 1340 / 1 skip / 0 fail, pi 14.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Fixes #154 by serving the vault bearer for a tombstoned main instead of sending an empty local bearer. A custody-owned main is now resolved through the vault cache before any refresh is attempted; if the cache cannot serve it, the main is refused with a synthetic 401 and excluded from the roster so a fallback can be used.
check-quotasauth-menu path, and local mode remains unchanged.Written for commit fc20beb. Summary will update on new commits.