mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-13 14:37:26 +00:00
fix(credentials): one vault per user, in the config dir (#119)
The credential store resolved its base directory against process.cwd(). Running the CLI from inside a git checkout wrote `.logicsrc/credentials` into that repo's working tree — a directory containing `vault/`, the one place raw credential values touch disk — untracked, unignored, and one `git add -A` from being committed. Two such directories were sitting in unrelated repos on the machine this was found on. A per-directory store is also the wrong shape for what the store is for. It is the record of what was rotated and what the prior values were, and a record that forks per project folder is several records that disagree. There is one user, one identity, one vault. Everything now hangs off a single logicsrcHome(): $LOGICSRC_HOME, else $XDG_CONFIG_HOME/logicsrc, else ~/.config/logicsrc. The credential store, the identity and the CLI config all read it rather than each deriving their own answer — three separate derivations is how the vault ended up somewhere the config never was. ~/.logicsrc is migrated rather than abandoned. It holds the X25519 secret key, and losing that loses access to every team vault the member was ever given, so it is moved on first use; a move that fails says so on stderr instead of leaving someone silently logged out with a key still on disk somewhere they were not told about. If the new directory already exists it wins and the old one is left untouched, because two directories both claiming to be the identity is how a login writes one and a read finds the other. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
87266bb815
commit
36236eb1a3
12 changed files with 223 additions and 27 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@logicsrc/cli",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"description": "LogicSRC OpenSpec CLI.",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { logicsrcHome } from "@logicsrc/plugin-credential-sharing";
|
||||
|
||||
export type JsonObject = Record<string, unknown>;
|
||||
|
||||
|
|
@ -21,8 +21,14 @@ export const defaultConfig: JsonObject = {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The same one directory the identity and the vault use.
|
||||
*
|
||||
* Shared rather than re-derived: three copies of "where does logicsrc keep
|
||||
* things" is how the vault ended up somewhere the config never was.
|
||||
*/
|
||||
export function configPath() {
|
||||
return join(homedir(), ".logicsrc", "config.json");
|
||||
return join(logicsrcHome(), "config.json");
|
||||
}
|
||||
|
||||
export function readConfig() {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { spawnSync } from "node:child_process";
|
|||
import { readFileSync } from "node:fs";
|
||||
import { evaluateAccountPolicy, scoreAccountActionRisk } from "@logicsrc/account-core";
|
||||
import { Command } from "commander";
|
||||
import { createCredentialEngine, listCredentialProviders, type CredentialEndpoint } from "@logicsrc/plugin-credential-sharing";
|
||||
import { createCredentialEngine, listCredentialProviders, logicsrcHome, type CredentialEndpoint } from "@logicsrc/plugin-credential-sharing";
|
||||
import { listEmailAccountProviders } from "@logicsrc/plugin-email-accounts";
|
||||
import { discoverFeeds, listFeedProviders, probeSite, renderDiscoveryOutput, validateFeed, type FeedKind, type FeedOutputFormat } from "@logicsrc/plugin-feed-discovery";
|
||||
import { listSocialAccountProviders } from "@logicsrc/plugin-social-accounts";
|
||||
|
|
@ -822,12 +822,14 @@ program
|
|||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
console.log(`Updated. Install root: ${installHome()} — config preserved at ~/.logicsrc`);
|
||||
console.log(`Updated. Install root: ${installHome()} — config preserved at ${logicsrcHome()}`);
|
||||
});
|
||||
|
||||
program.command("remove").alias("uninstall").option("--purge", "Remove config and auth tokens").description("Remove local LogicSRC CLI.").action((options) => {
|
||||
console.log("Removed LogicSRC CLI.");
|
||||
console.log(options.purge ? "Removed config and auth tokens from $HOME/.logicsrc." : "Preserved config at $HOME/.logicsrc. Run with --purge to remove config and auth tokens.");
|
||||
console.log(options.purge
|
||||
? `Removed config and auth tokens from ${logicsrcHome()}.`
|
||||
: `Preserved config at ${logicsrcHome()}. Run with --purge to remove config and auth tokens.`);
|
||||
});
|
||||
|
||||
function validateFile(kindArg: string, file: string) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
defaultApiUrl,
|
||||
resolveApiUrl,
|
||||
createCredentialEngine,
|
||||
identityPath,
|
||||
unwrapVaultKey,
|
||||
wrapVaultKey,
|
||||
type CredentialEndpoint
|
||||
|
|
@ -280,7 +281,7 @@ export async function loginAction(options: { apiUrl?: string; token?: string; de
|
|||
|
||||
export async function logoutAction(): Promise<void> {
|
||||
await updateIdentity({ apiToken: undefined, email: undefined, userId: undefined });
|
||||
console.error("Logged out (local token cleared; revoke the key at /settings). Identity key retained — delete ~/.logicsrc/identity.json to remove it.");
|
||||
console.error(`Logged out (local token cleared; revoke the key at /settings). Identity key retained — delete ${identityPath()} to remove it.`);
|
||||
}
|
||||
|
||||
export async function whoamiAction(format: OutputFormat): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export type UpdateStatus = {
|
|||
latestCommit: string | null;
|
||||
};
|
||||
|
||||
/** Install root the installer uses (not the config dir, which is ~/.logicsrc). */
|
||||
/** Install root the installer uses (not the config dir, which is ~/.config/logicsrc). */
|
||||
export function installHome(env: NodeJS.ProcessEnv = process.env): string {
|
||||
return env.LOGICSRC_HOME || join(env.HOME || homedir(), ".logicsrc-cli");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue