mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-14 06:47:28 +00:00
`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>
104 lines
3.3 KiB
TypeScript
104 lines
3.3 KiB
TypeScript
import type { PluginDefinition } from "@logicsrc/plugin-core";
|
|
import { credentialSharingManifest } from "./manifest.js";
|
|
import { CredentialEngine, type CredentialEngineOptions } from "./engine.js";
|
|
import { listCredentialProviderManifests } from "./providers/index.js";
|
|
|
|
export const credentialSharingPlugin: PluginDefinition = {
|
|
manifest: credentialSharingManifest,
|
|
configDefaults: {
|
|
enabled: true,
|
|
default_policy: "approval_required_for_destructive",
|
|
credential_home: "${LOGICSRC_CREDENTIAL_HOME}"
|
|
},
|
|
routes: [
|
|
{ method: "GET", path: "/api/credentials/providers", capability: "credentials.providers.list" },
|
|
{ method: "GET", path: "/api/credentials/inspect", capability: "credentials.inspect" },
|
|
{ method: "POST", path: "/api/credentials/diff", capability: "credentials.diff" },
|
|
{ method: "POST", path: "/api/credentials/plans", capability: "credentials.plan" },
|
|
{ method: "POST", path: "/api/credentials/plans/:id/approve", capability: "credentials.approve" },
|
|
{ method: "POST", path: "/api/credentials/plans/:id/sync", capability: "credentials.sync" },
|
|
{ method: "POST", path: "/api/credentials/runs/:id/rollback", capability: "credentials.rollback" },
|
|
{ method: "GET", path: "/api/credentials/runs/:id/audit", capability: "credentials.audit.read" }
|
|
],
|
|
permissions: [
|
|
"credentials:inspect",
|
|
"credentials:diff",
|
|
"credentials:plan",
|
|
"credentials:approve",
|
|
"credentials:sync",
|
|
"credentials:rollback",
|
|
"credentials:audit:read"
|
|
],
|
|
tuiPanels: [{ id: "credential-sharing", title: "Credential Sharing" }]
|
|
};
|
|
|
|
/** Factory mirroring the LogicSRC Credential Sharing SDK spec. */
|
|
export function createCredentialEngine(options: CredentialEngineOptions = {}): CredentialEngine {
|
|
return new CredentialEngine(options);
|
|
}
|
|
|
|
/** Provider listing without constructing an engine (used by the CLI `providers` command). */
|
|
export function listCredentialProviders() {
|
|
return listCredentialProviderManifests();
|
|
}
|
|
|
|
export { credentialSharingManifest };
|
|
export { CredentialEngine, DEFAULT_CREDENTIAL_POLICY, endpointLabel } from "./engine.js";
|
|
export type { CredentialEngineOptions } from "./engine.js";
|
|
export {
|
|
credentialProviders,
|
|
credentialProviderRegistry,
|
|
listCredentialProviderManifests,
|
|
envProvider,
|
|
dopplerProvider,
|
|
railwayProvider,
|
|
githubSecretsProvider,
|
|
teamProvider,
|
|
parseEnv,
|
|
applyEnv
|
|
} from "./providers/index.js";
|
|
export {
|
|
TeamClient,
|
|
TeamApiError,
|
|
type TeamClientOptions,
|
|
type RemoteUser,
|
|
type RemoteTeam,
|
|
type RemoteMember,
|
|
type RemoteVault,
|
|
type RemoteSecret,
|
|
type RemoteGrantRow
|
|
} from "./client.js";
|
|
export {
|
|
generateIdentityKeyPair,
|
|
generateVaultKey,
|
|
wrapVaultKey,
|
|
unwrapVaultKey,
|
|
encryptValue,
|
|
decryptValue,
|
|
publicKeyForSecret,
|
|
type IdentityKeyPair,
|
|
type SealedValue
|
|
} from "./crypto.js";
|
|
export {
|
|
loadOrCreateIdentity,
|
|
readIdentity,
|
|
saveIdentity,
|
|
updateIdentity,
|
|
requireAuth,
|
|
verifyIdentityIntegrity,
|
|
identityPath,
|
|
logicsrcHome,
|
|
defaultApiUrl,
|
|
envApiUrl,
|
|
resolveApiUrl,
|
|
DEFAULT_API_URL,
|
|
type LocalIdentity
|
|
} from "./identity.js";
|
|
export {
|
|
createFileCredentialStore,
|
|
createMemoryCredentialStore,
|
|
defaultCredentialHome,
|
|
type CredentialStore
|
|
} from "./store.js";
|
|
export { fingerprintValue, fingerprintsEqual } from "./fingerprint.js";
|
|
export * from "./types.js";
|