Skip to content

Fix arbiter appeal page auth and chat session creation - #781

Merged
joemarct merged 2 commits into
masterfrom
fix/arbiter-appeal-chat-and-auth
Sep 27, 2026
Merged

joemarct merged 2 commits into
masterfrom
fix/arbiter-appeal-chat-and-auth

Conversation

@joemarct

@joemarct joemarct commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Summary

Opening an arbiter appeal deep-link (e.g. #/apps/exchange/arbiter/appeals/1802/) produced 401 No auth credentials provided errors and left the page on skeleton loaders forever. Opening the chat tab then produced 404/400 errors and never loaded messages.

Also fixes the opencode GitHub workflow, which failed with 404 Cannot find any route matching [POST] https://opencode.ai/zen/v1/chat/completions.

Changes

  • Explicit arbiter auth on arbiter-area requests. The companion requests on the appeal page (order, contract, fees, ad snapshot, transactions, members, status, feedback, verify-release/refund, pending actions) used authorize: true. resolveRequestUserType only classifies URLs matching a small arbiter pattern set, so these fell through to ramp/getUser (empty on arbiter deep-links) and defaulted to peer, sending no/peer token. They now pass authorize: 'arbiter', matching the already-correct fetchAppeal.
  • Refetch on re-login. appeal.vue now listens for the relogged bus event and reloads, so the page recovers after a silent arbiter re-login instead of staying on the skeleton.
  • Create the chat session when missing. fetchChatSession resolves null on 404 rather than rejecting, but ChatDialog only set createSession = true inside .catch() — dead code. Absence is now detected from the resolved value, so createChatSession/updateChatMembers actually run.
  • opencode workflow. Switch model opencode/kimi-k2.6 -> opencode/glm-5.3 (Kimi 404s on the zen chat-completions route; GLM routes) and grant issues: write so the action can comment/react. Mirrors the proven fix in engagement-hub.

Notes

  • Verified against commercehub: the appeal chat session was absent (session 404, messages 400 "No chat ref provided or found") while the arbiter chat identity exists (id 780), confirming the missing-session path.
  • src/pages/apps/exchange/peer_to_peer/order.vue:2012 has the same dead-code pattern for the peer-side fallback; left out of this PR to keep the scope on the reported arbiter bug.
  • Lint reports only pre-existing issues in the touched files.

- Send explicit authorize:'arbiter' on arbiter appeal and chat API calls so companion requests no longer fall through to the peer user type and return 401
- Refetch appeal data on the relogged event so the page leaves the skeleton state
- Create the chat session in ChatDialog when fetchChatSession resolves null, instead of relying on a rejection that never fires
@paytaca paytaca deleted a comment from github-actions Bot Sep 27, 2026
- Switch model to opencode/glm-5.3: opencode zen's POST /zen/v1/chat/completions returns 404 "Cannot find any route matching" for kimi-k2.6, while glm-5.3 routes successfully
- Grant issues: write so the action can create comments and reactions
- Mirrors the proven fix in engagement-hub
@github-actions

Copy link
Copy Markdown

PR #781 Review — Fix arbiter appeal page auth and chat session creation

Root-cause analysis verified

1. Auth classification (authorize: 'arbiter') — Confirmed against resolveRequestUserType (src/exchange/backend.js:22-49). The order-scoped URLs (/order/{id}, /contract/, /contract/transactions/, /contract/fees/, /ad/snapshot/, /members/, /status/) match none of the arbiter regexes, so with authorize: true they fell through to ramp/getUser (empty on deep-links) → peer → no/wrong token → 401. The explicit override (backend.js:24) is the right fix.

2. Component usage scoping — All hard coded components (AppealDetail, AppealFeedbackDialog, AppealTransfer, OrderStatusDialog, TransactionHistoryDialog) are imported only by the arbiter appeal.vue — no peer-side usage, so hardcoding 'arbiter' is safe. Correctly, ChatDialog and AdSnapshotDialog (shared with the peer order page) were left on authorize: true.

3. Chat session dead code — Confirmed fetchChatSession resolves null on both 403 and 404 (src/exchange/chat/index.js:241-246) and the full axios response on success. The old createSession = true inside .catch() on 404 was unreachable; the new .then(session => { createSession = !session }) is correct (truthy response → false, null → true). Downstream 403s from createChatSession/updateChatMembers are silently handled. Also confirmed the PR note: the identical dead pattern exists at peer order.vue:2012-2021.

4. relogged handler — Emitted by RampLogin.loadUser() after successful (re)login (RampLogin.vue:142); the handler matches the established pattern (appeals.vue:26, order.vue:961).

5. Lint — Ran ESLint on the 7 touched files on both base and PR branch: identical results, all pre-existing. Confirms the PR claim.

Security review (per AGENTS.md)

No changes to entropy, key derivation, signing, transaction construction, or secret storage. The diff only affects which stored token (peer vs arbiter) is attached to watchtower REST calls, and the scoping is verifiably correct (arbiter-only components). No secrets logged, no new endpoints, no new dependencies. The workflow change (issues: write, model swap) is benign infrastructure.

Minor findings (non-blocking)

  1. Dead 403 branch — ChatDialog.vue:586-589: fetchChatSession never rejects with 403, so the remaining createSession = false in .catch() is unreachable (and false is already the default). Slightly misleading to keep.
  2. Listener leak — appeal.vue:291 registers bus.on('relogged', this.onRelogged) but beforeUnmount (appeal.vue:310-312) only closes websockets — no bus.off. Consistent with existing listeners in this file, but onRelogged → loadData() can fire on an unmounted instance. Low severity.
  3. Recovery is partial — onRelogged (appeal.vue:576-580) reloads data but, unlike mounted() (appeal.vue:301-308), doesn't call updateOrderReadAt()/setupWebsocket(). After recovering from the 401 skeleton state, live websocket updates stay inactive until remount. Also, resetting _loadingData = false while an in-flight loadData still awaits can produce two concurrent runs (duplicate fetches, idempotent). Low severity.

Verdict

The changes are correct, well-scoped, and the root-cause analysis in the PR body checks out against the code. Approve — the minor findings above are worth a follow-up but none block this fix.

New%20session%20-%202026-09-27T07%3A39%3A21.989Z
opencode session  |  github run

@joemarct
joemarct merged commit 4f84257 into master Sep 27, 2026
1 check passed
@joemarct
joemarct deleted the fix/arbiter-appeal-chat-and-auth branch September 27, 2026 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant