Skip to content

fix(desktop): carry typed OAuth failure reasons from main-process producers - #4887

Draft
orangeCatDeveloper wants to merge 11 commits into
apache:mainfrom
orangeCatDeveloper:fix/oauth-failure-reasons
Draft

fix(desktop): carry typed OAuth failure reasons from main-process producers#4887
orangeCatDeveloper wants to merge 11 commits into
apache:mainfrom
orangeCatDeveloper:fix/oauth-failure-reasons

Conversation

@orangeCatDeveloper

Copy link
Copy Markdown
Contributor

Summary

Stacked on #4551; review the last commit only.

subscriptionResultMessage matches two English Host messages with regexes to localize OAuth login failures. One of the three regex families — did not present OAuth|no matching OAuth presentation — describes failures produced by Desktop itself, not the Host: the presentation timeout and the absent-request throw in runtime-host-oauth-presentation.ts. This PR gives those producers a typed error (OAuthPresentationError with presentation_timeout / presentation_absent) and maps it, along with the Host's operation_conflict, to typed reasons on the get-auth-url failure envelope:

  • operation_conflictlogin_in_progress
  • OAuthPresentationErrorpresentation_failed
  • operation_unavailableexperimental_disabled (unchanged)

The renderer catalog maps the two new reasons per locale and the prose regex is deleted. The enrollment is disabled and already in progress fallbacks stay: their producers live in the Runtime Host, which may be remote and older than this client — that is a version-skew fallback, not dead code. loginConflict / browserPresentFailed ad-hoc keys are folded into resultCodes (same wording).

Refs #2672

Verification

apps/desktop typecheck (4 tsconfigs):   0 errors
oauth-result-copy.test.ts:              6 pass (2 new: typed reasons per locale; regex-removal pin)
focused desktop suites:                 pass
renderer architecture check:            passed
biome (changed files):                  clean
protocol epoch guard:                   no protocol changes

Not run: Electron e2e with a live Host login flow.

AI use

  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code traced the producer→presenter path, implemented the typed error and reason mapping, removed the regex, added the tests, and wrote this description. Commit carries Generated-by: Claude Code.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — login-conflict and browser-presentation failures now render the same catalog copy via typed reasons instead of English prose matching.

@github-actions github-actions Bot added the effort/XL Under 2500 readable lines label Sep 6, 2026
Settings-area producers (memory, data, permission center, connection
test, computer-use health, dev dialogs, Copilot import) emitted zh prose
that reached en users verbatim, and presenters sniffed CJK to decide
whether to show it. Producers now return stable codes and redact probe
detail at the source; each settings catalog maps its codes per locale
with complete message templates and an explicit unknown fallback. One
capability reason catalog serves the Health center and the Permission
Center, bot reasons resolve through the bot catalog, and the memory and
Copilot results carry a single code field.

Generated-by: Claude Code
Generated-by: OpenCode
Remove the rebase-duplicated 429 branch that shadowed shared.rateLimit
behind shared.rateLimited and drop the now-dead rateLimited copy rows.
Finish the permission-center guidance-block removal: delete the unused
locale keys, empty the storybook fixture guidance, and fix the comment
that still described the block. Log capability probe failures before
collapsing them to permission_probe_failed. Drop redundant
cu_backend_status re-checks after the early return and shorthand the
locale pass-through in command actions.

Generated-by: Claude Code
…rthand

The `locale: locale` → `locale` shorthand in app-shell-command-actions.ts
drops two non-trivia tokens; regenerate the architecture ledger.

Generated-by: Claude Code
The storybook smoke failed on product-settings-pages--about-update-failed
across every CI run of this branch: the story pins
net::ERR_CONNECTION_RESET, classifyGeneralizedError did not recognize the
Chromium prefix (it only matches Node errno spellings), so the PR's new
[settings] operation failed console.error fired on a story that renders
normally, and the smoke treats console.error as fatal. Empty-commit
retriggers could not fix it.

Classify the net::ERR_ prefix as network_error so the update row renders
Network error / 网络错误 instead of the unknown-error fallback, which also
removes the diagnostic for this expected story path. Cover the prefix and
its per-locale rendering in the classifier tests.

Generated-by: Claude Code
The permission-center guidance list was removed in 02604e2 (no
producer fills guidance; apache#4526's layered rows carry the actionable
lines), but the snapshot-side plumbing survived: the
CapabilitySnapshot.guidance field, staticCapability's guidance input,
botCapability's empty array, and the fixtures' guidance: [] entries.
Every future producer had to keep feeding a write-only field.

Delete the field, the producer parameter, the botCapability entry, and
the fixture entries; fix the permission-center comment that still named
the removed guidance list.

Generated-by: Claude Code
…esult-copy

subscription-result-message.ts no longer exists — the module moved into
settings-provider-copy.ts beside the catalog it renders, so the old test
file name referenced nothing. Fold its two assertions (Traditional
Chinese rejects raw Simplified backend prose; the generalized classifier
still answers network failures) into oauth-result-copy.test.ts, which
already drives subscriptionResultMessage.

Also drop the unused lookupCopy import from settings-health-copy.ts.

Generated-by: Claude Code
The inline { type X } form counts as a value import in the renderer
architecture analysis, so the ledger recorded an @maka/core/ui-locale
dependency edge and CI's --base check failed against main, which uses
the type-only form. Restore import type and regenerate the ledger.

Generated-by: Claude Code
…ducers

get-auth-url maps the Host's operation_conflict to a typed
login_in_progress reason and Desktop-owned presentation failures
(OAuthPresentationError: presentation_timeout / presentation_absent)
to presentation_failed, instead of relying on English prose matching
in the renderer. The did-not-present / no-matching-request regex in
subscriptionResultMessage goes away; the enrollment-disabled and
already-in-progress fallbacks stay as Host version-skew fallbacks
for producers that predate the typed codes.

Refs apache#2672

Generated-by: Claude Code
… boundary

The renderer catalog tests proved the copy lookup for the new typed
reasons; nothing proved the main process emits them. Throw the three
producer-side failures through the real handler — OAuthPresentationError
→ presentation_failed, RuntimeHostOperationError('operation_conflict')
→ login_in_progress, RuntimeHostOperationError('operation_unavailable')
→ experimental_disabled — and assert the exact failure envelope for
each, so a rename or an instanceof-order regression fails here.

Generated-by: Claude Code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XL Under 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant