Simplify config loading: fix TOCTOU, eager init, remove dead code

- Rust: replace exists() check with direct read + NotFound handling
- TS: load config eagerly at module init instead of lazy per-request
- TS: remove unused resetAppConfigCache() export

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-02 23:24:39 -05:00
parent 1cebe29fad
commit d93785ae83
2 changed files with 11 additions and 16 deletions

View file

@ -28,11 +28,7 @@ const API_DEFAULTS: ApiConfig = {
authentication_strategy: "jwt",
};
let cached: AppConfig | null = null;
export function getAppConfig(): AppConfig {
if (cached) return cached;
function loadAppConfig(): AppConfig {
const configPath = join(homedir(), ".arc", "arc.toml");
let raw: Record<string, unknown> = {};
@ -45,15 +41,15 @@ export function getAppConfig(): AppConfig {
const rawAuth = (raw.auth ?? {}) as Partial<AuthConfig>;
const rawApi = (raw.api ?? {}) as Partial<ApiConfig>;
cached = {
return {
auth: { ...AUTH_DEFAULTS, ...rawAuth },
api: { ...API_DEFAULTS, ...rawApi },
};
return cached;
}
/** Reset cached config (for testing). */
export function resetAppConfigCache(): void {
cached = null;
/** Loaded once at module init; restart the server to pick up changes. */
const appConfig: AppConfig = loadAppConfig();
export function getAppConfig(): AppConfig {
return appConfig;
}

View file

@ -72,12 +72,11 @@ pub fn load_app_config() -> anyhow::Result<AppConfig> {
return Ok(AppConfig::default());
};
let path = home.join(".arc").join("arc.toml");
if !path.exists() {
return Ok(AppConfig::default());
match std::fs::read_to_string(&path) {
Ok(contents) => Ok(toml::from_str(&contents)?),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(AppConfig::default()),
Err(e) => Err(e.into()),
}
let contents = std::fs::read_to_string(&path)?;
let config: AppConfig = toml::from_str(&contents)?;
Ok(config)
}
/// Resolve the data directory: config value > default `~/.arc`.