mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-13 22:37:29 +00:00
fix(cli): point logicsrc login at the real app + add device-code login
`logicsrc login` defaulted to http://localhost:4010 — a dev origin that doesn't exist on an installed machine, so the printed authorize URL went nowhere. It now defaults to the hosted credentials app (apps/pwa), reads the documented $LOGICSRC_API, and only reuses a stored apiUrl once that identity has actually completed a login (which is how machines got stuck pointing at localhost). Note logicsrc.com is the marketing site and has no /cli routes. The loopback flow is also unusable over SSH: redirect_uri is http://127.0.0.1:<port>/callback, which resolves to the *browser's* machine, not the CLI's. Added a device-authorization flow — the CLI prints a short user_code, the human approves it from any browser: POST /cli/device/code mint device_code + user_code (10 min TTL) GET /cli/device approve page (login required; typo-tolerant) POST /cli/device approve/deny (CSRF-guarded browser form) POST /cli/device/token CLI polls -> lsk_ API key device_code is stored sha256-hashed, single-use, with authorization_pending / slow_down / access_denied / expired_token poll semantics. The CLI picks the flow automatically (SSH/CI/no-DISPLAY -> device), with --device/--web to force it and a fallback to loopback against servers without /cli/device. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
eaf0a6162b
commit
cf475f0f4c
7 changed files with 311 additions and 16 deletions
|
|
@ -38,8 +38,37 @@ export function identityPath(): string {
|
|||
: join(logicsrcHome(), "identity.json");
|
||||
}
|
||||
|
||||
/**
|
||||
* The hosted LogicSRC credentials app (`apps/pwa`) — where `logicsrc login`
|
||||
* goes when nothing else is configured. This is deliberately NOT logicsrc.com:
|
||||
* that origin serves the marketing site and has no /cli routes.
|
||||
*/
|
||||
export const DEFAULT_API_URL = "https://logicsrc-credentials-production.up.railway.app";
|
||||
|
||||
/** An explicitly configured API origin, if any. `LOGICSRC_API` is the documented one. */
|
||||
export function envApiUrl(): string | undefined {
|
||||
return (
|
||||
process.env.LOGICSRC_API ||
|
||||
process.env.LOGICSRC_API_URL ||
|
||||
// Legacy: CommandBoard is a different service, so this is the last resort.
|
||||
process.env.COMMANDBOARD_API_URL ||
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
export function defaultApiUrl(): string {
|
||||
return process.env.COMMANDBOARD_API_URL || process.env.LOGICSRC_API_URL || "http://localhost:4010";
|
||||
return envApiUrl() || DEFAULT_API_URL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the API origin for a command: an explicit `--api-url` wins, then the
|
||||
* environment, then whatever a *logged-in* identity was registered against.
|
||||
* A stored URL from an identity that never completed login is ignored — that
|
||||
* is how machines got stuck pointing at a dev `localhost` server.
|
||||
*/
|
||||
export function resolveApiUrl(identity?: Pick<LocalIdentity, "apiUrl" | "apiToken">, override?: string): string {
|
||||
const stored = identity?.apiToken ? identity.apiUrl : undefined;
|
||||
return (override || envApiUrl() || stored || DEFAULT_API_URL).replace(/\/+$/, "");
|
||||
}
|
||||
|
||||
function writeSecure(file: string, data: unknown): void {
|
||||
|
|
@ -96,7 +125,7 @@ export async function updateIdentity(
|
|||
export function requireAuth(file = identityPath()): LocalIdentity & { apiToken: string; email: string } {
|
||||
const identity = readIdentity(file);
|
||||
if (!identity?.apiToken || !identity.email) {
|
||||
throw new Error('Not logged in. Run "logicsrc login --email you@example.com" first.');
|
||||
throw new Error('Not logged in. Run "logicsrc login" first.');
|
||||
}
|
||||
return identity as LocalIdentity & { apiToken: string; email: string };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ export {
|
|||
identityPath,
|
||||
logicsrcHome,
|
||||
defaultApiUrl,
|
||||
envApiUrl,
|
||||
resolveApiUrl,
|
||||
DEFAULT_API_URL,
|
||||
type LocalIdentity
|
||||
} from "./identity.js";
|
||||
export {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue