mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ed79bf489c
commit
208b51d5d2
@@ -10,6 +10,7 @@ import {
|
||||
} from '../../store/deepLinkAuthState';
|
||||
import { getStoredCoreMode } from '../configPersistence';
|
||||
import {
|
||||
authStoreFailureUserMessage,
|
||||
classifyAuthStoreFailure,
|
||||
registerAuthDeepLinkState,
|
||||
setupDesktopDeepLinkListener,
|
||||
@@ -396,3 +397,36 @@ describe('classifyAuthStoreFailure', () => {
|
||||
expect(classifyAuthStoreFailure(bare)).not.toBe('other');
|
||||
});
|
||||
});
|
||||
|
||||
describe('authStoreFailureUserMessage (issue #3025)', () => {
|
||||
const CLOUD_KINDS = [
|
||||
'auth_me_timeout',
|
||||
'auth_me_unauthorized',
|
||||
'auth_me_gateway',
|
||||
'network',
|
||||
'other',
|
||||
];
|
||||
|
||||
// Local / unset mode always keeps the plain retry message — the failure there
|
||||
// is a transient embedded-core/backend blip that retrying can clear.
|
||||
it.each(['local', null] as const)('stays generic for mode=%s', mode => {
|
||||
for (const kind of CLOUD_KINDS) {
|
||||
expect(authStoreFailureUserMessage(kind, mode)).toBe('Sign-in failed. Please try again.');
|
||||
}
|
||||
});
|
||||
|
||||
it('points cloud-mode users at the remote runtime, not a dead-end retry', () => {
|
||||
for (const kind of CLOUD_KINDS) {
|
||||
const msg = authStoreFailureUserMessage(kind, 'cloud');
|
||||
expect(msg).not.toBe('Sign-in failed. Please try again.');
|
||||
expect(msg.toLowerCase()).toContain('remote');
|
||||
}
|
||||
});
|
||||
|
||||
it('gives kind-specific cloud hints (401 token, gateway/timeout BACKEND_URL)', () => {
|
||||
expect(authStoreFailureUserMessage('auth_me_unauthorized', 'cloud')).toContain('RPC token');
|
||||
expect(authStoreFailureUserMessage('auth_me_gateway', 'cloud')).toContain('BACKEND_URL');
|
||||
expect(authStoreFailureUserMessage('auth_me_timeout', 'cloud')).toContain('BACKEND_URL');
|
||||
expect(authStoreFailureUserMessage('network', 'cloud')).toContain('online');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -285,7 +285,7 @@ const handleAuthDeepLink = async (parsed: URL, requireStateNonce = true) => {
|
||||
fingerprint: ['deep-link-auth', 'session-store-failed', kind],
|
||||
});
|
||||
console.warn('[DeepLink][auth] session store failed — staying on signin (kind=%s)', kind);
|
||||
failDeepLinkAuthProcessing('Sign-in failed. Please try again.');
|
||||
failDeepLinkAuthProcessing(authStoreFailureUserMessage(kind, getStoredCoreMode()));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -321,6 +321,48 @@ export const classifyAuthStoreFailure = (message: string): string => {
|
||||
return 'other';
|
||||
};
|
||||
|
||||
/**
|
||||
* Build the user-facing message for an auth-*store* failure (issue #3025).
|
||||
*
|
||||
* `auth_store_session` makes the core validate the freshly minted session token
|
||||
* against the backend `GET /auth/me` before persisting it. In **cloud mode**
|
||||
* that validation runs on the user's *remote* `openhuman-core`, so the dominant
|
||||
* failure is the remote runtime being unable to reach/authenticate against the
|
||||
* backend (misconfigured `BACKEND_URL`, offline, or an older core that predates
|
||||
* `allowPendingBackendValidation`) — not a problem the desktop can retry away.
|
||||
* The old blanket "Sign-in failed. Please try again." gave cloud users no path
|
||||
* forward; point them at the remote runtime instead. Local mode keeps the plain
|
||||
* retry message (a transient embedded-core/backend blip that retrying can fix).
|
||||
*/
|
||||
export const authStoreFailureUserMessage = (
|
||||
kind: string,
|
||||
mode: 'local' | 'cloud' | null
|
||||
): string => {
|
||||
if (mode !== 'cloud') {
|
||||
return 'Sign-in failed. Please try again.';
|
||||
}
|
||||
switch (kind) {
|
||||
case 'auth_me_unauthorized':
|
||||
return (
|
||||
'Your remote (cloud) runtime rejected the sign-in. Check the RPC token in ' +
|
||||
'Settings and that the runtime points at the correct backend, then try again.'
|
||||
);
|
||||
case 'auth_me_timeout':
|
||||
case 'auth_me_gateway':
|
||||
case 'network':
|
||||
return (
|
||||
'Your remote (cloud) runtime could not reach the backend to finish sign-in. ' +
|
||||
'Check that the runtime is online and its BACKEND_URL is configured, then try again.'
|
||||
);
|
||||
default:
|
||||
return (
|
||||
'Your remote (cloud) runtime could not complete sign-in. Verify it is running ' +
|
||||
'and configured correctly (RPC URL/token in Settings, backend connectivity), ' +
|
||||
'then try again.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle `openhuman://payment/success?session_id=...` deep links.
|
||||
* Fired when a Stripe checkout session completes and the browser redirects
|
||||
|
||||
@@ -399,6 +399,31 @@ Restart the desktop app. The provider chain in `App.tsx` will route all RPC
|
||||
calls to the remote core; nothing else changes. Public `http://` hosts are
|
||||
rejected by the app picker; use HTTPS for any publicly reachable core.
|
||||
|
||||
### Troubleshooting: sign-in fails after OAuth on a cloud runtime
|
||||
|
||||
Symptom: OAuth in the browser completes ("close this and return to the app"),
|
||||
but the desktop then shows a sign-in error — while the **same** account signs in
|
||||
fine on the local (embedded) runtime (issue #3025).
|
||||
|
||||
Root cause is almost always the **remote** core, not the desktop. `auth_store_session`
|
||||
makes the core validate the fresh session token against the backend
|
||||
(`GET /auth/me`) before persisting it; on a cloud runtime that call runs on your
|
||||
server, so it fails if the remote core can't reach/authenticate the backend:
|
||||
|
||||
- **`BACKEND_URL` unset or wrong.** It is required (see the env table above) and
|
||||
must be `https://api.tinyhumans.ai` for prod (or the staging URL). A missing
|
||||
value is the most common cause — one reporter's failure was exactly this.
|
||||
- **Backend unreachable from the server** (egress firewall, DNS, TLS interception)
|
||||
→ the core sees a gateway/timeout on `/auth/me`.
|
||||
- **Outdated core.** Older cores predate `allowPendingBackendValidation` and
|
||||
validate synchronously with no grace; update the server to a current release.
|
||||
- **Wrong RPC token.** A token mismatch surfaces as HTTP 401 on `/rpc`; re-paste
|
||||
the token (see "Rotating the bearer token").
|
||||
|
||||
Check the remote core logs for `Session validation failed (GET /auth/me)` and the
|
||||
status/reason. The desktop now reports a cloud-specific, actionable message for
|
||||
these instead of a generic "try again" (issue #3025).
|
||||
|
||||
---
|
||||
|
||||
## Named-volume ownership and the Docker entrypoint
|
||||
|
||||
Reference in New Issue
Block a user