Skip to content

Fix audit IP fallback and CLI TypeScript regressions#66

Merged
weroperking merged 1 commit intomainfrom
codex/fix-failing-tests-in-project
Apr 26, 2026
Merged

Fix audit IP fallback and CLI TypeScript regressions#66
weroperking merged 1 commit intomainfrom
codex/fix-failing-tests-in-project

Conversation

@weroperking
Copy link
Copy Markdown
Owner

@weroperking weroperking commented Apr 26, 2026

Motivation

  • Resolve a failing audit test where getClientIp produced a UA fingerprint instead of returning "unknown" when no IP/user-agent headers are present.
  • Fix TypeScript/typecheck regressions caused by use of Bun-only filesystem APIs and an incompatible dynamic prompts import in the CLI init/login flows.

Description

  • Updated getClientIp in packages/server/src/lib/audit.ts to prefer x-forwarded-for, then x-real-ip, and return "unknown" when no proxy or user-agent data exists instead of always generating a UA fingerprint.
  • Replaced unsafe Bun filesystem cleanup logic in packages/cli/src/commands/init.ts with node:fs/promises rm(..., { recursive: true, force: true }) and mkdir(..., { recursive: true }) to avoid Bun-specific APIs that broke typechecking.
  • Replaced dynamic import of prompts in the CLI login flow with the existing inquirer prompt in packages/cli/src/index.ts and ensured the password passed to runApiKeyLogin is always a string.
  • Small housekeeping: adjusted imports/usage to remove runtime/type errors seen during CI and local typechecks.

Testing

  • Ran bun test packages/server/test/audit.test.ts and all audit tests passed.
  • Ran the server test suite with bun run --cwd packages/server test and observed no failures for the server package.
  • Ran CLI TypeScript check with bun run --cwd packages/cli typecheck (tsc -p tsconfig.json --noEmit) and the typecheck passed.

Codex Task

Summary by CodeRabbit

Release Notes

  • New Features

    • Password input is now masked during CLI login
  • Bug Fixes

    • Improved client IP detection in audit logs with better fallback handling
    • Enhanced project initialization cleanup for more reliable directory handling
    • Fixed potential undefined values in login flow

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

Walkthrough

This PR modifies three independent modules: simplifies the init command's directory cleanup from individual file enumeration to recursive removal, switches CLI login password prompting from prompts to inquirer with masking, and updates audit IP extraction to parse x-forwarded-for headers with fallback and missing user-agent handling.

Changes

Cohort / File(s) Summary
CLI Init
packages/cli/src/commands/init.ts
Simplified cleanup logic: replaced file enumeration and incremental deletion with single recursive rmSync() call followed by directory recreation.
CLI Login
packages/cli/src/index.ts
Switched admin password collection from prompts to inquirer with input masking. Added string coercion (password ?? "") before passing to runApiKeyLogin().
Server Audit
packages/server/src/lib/audit.ts
Modified IP extraction: now parses first comma-separated value from x-forwarded-for header, falls back to trimmed x-real-ip. Returns "unknown" if user-agent header is missing/empty; preserves fingerprinting logic when header exists.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #25: CLI login rework includes inquirer-based password prompting changes overlapping with index.ts modifications.
  • PR #59: Modifies init.ts's runInitCommand directory cleanup and overwrite confirmation logic.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: fixing audit IP fallback logic and resolving CLI TypeScript regressions across three files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-failing-tests-in-project

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/commands/init.ts (1)

1341-1347: ⚠️ Potential issue | 🟡 Minor

Swallowed cleanup error proceeds with stale directory.

If rm fails, the catch only logs and falls through to copyIaCTemplate(projectPath). Since copyIaCTemplate calls mkdir(targetDir, { recursive: true }), the EEXIST guard there won't trip, and template files get written on top of whatever survived the failed cleanup — producing a corrupt project. Either rethrow or abort here.

Proposed fix
 				// Clean up existing directory
-				try {
-					await rm(projectPath, { recursive: true, force: true });
-					await mkdir(projectPath, { recursive: true });
-				} catch (err) {
-					logger.error(`Failed to clean directory: ${err}`);
-				}
+				try {
+					await rm(projectPath, { recursive: true, force: true });
+				} catch (err) {
+					const message = err instanceof Error ? err.message : String(err);
+					throw new Error(`Failed to clean directory \`${projectName}\`: ${message}`);
+				}

Note: the subsequent mkdir is redundant — copyIaCTemplate already does mkdir(targetDir, { recursive: true }).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/init.ts` around lines 1341 - 1347, The cleanup
catch currently logs rm(projectPath...) failures and continues, which can leave
a stale directory and corrupt later copyIaCTemplate(projectPath) runs; update
the try/catch around rm(projectPath, { recursive: true, force: true }) so that
on error you abort (rethrow or throw a new Error) instead of falling through to
copyIaCTemplate, and remove the redundant await mkdir(projectPath, { recursive:
true }) since copyIaCTemplate already creates the directory; ensure references
to projectPath, rm, mkdir and copyIaCTemplate are used so the change is applied
in the same block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/index.ts`:
- Around line 569-583: The code should not silently coerce password to "" before
calling runApiKeyLogin; instead, after the inquirer prompt or env check ensure
password is a non-empty string and surface a local error if it's missing.
Replace the `password ?? ""` usage by explicitly validating the `password`
variable (the value read from process.env.ADMIN_PASSWORD or from the inquirer
prompt) and if it is undefined or an empty string throw or exit with a clear
message like "Admin password is required" so the issue is caught locally, then
pass the validated password into runApiKeyLogin (use the validated variable
directly, e.g., password or password! after the explicit check).

---

Outside diff comments:
In `@packages/cli/src/commands/init.ts`:
- Around line 1341-1347: The cleanup catch currently logs rm(projectPath...)
failures and continues, which can leave a stale directory and corrupt later
copyIaCTemplate(projectPath) runs; update the try/catch around rm(projectPath, {
recursive: true, force: true }) so that on error you abort (rethrow or throw a
new Error) instead of falling through to copyIaCTemplate, and remove the
redundant await mkdir(projectPath, { recursive: true }) since copyIaCTemplate
already creates the directory; ensure references to projectPath, rm, mkdir and
copyIaCTemplate are used so the change is applied in the same block.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a2b58f17-3e65-478e-98d0-c733e27c687f

📥 Commits

Reviewing files that changed from the base of the PR and between 606c7e5 and 670e1a8.

📒 Files selected for processing (3)
  • packages/cli/src/commands/init.ts
  • packages/cli/src/index.ts
  • packages/server/src/lib/audit.ts

Comment thread packages/cli/src/index.ts
Comment on lines 569 to +583
let password = process.env.ADMIN_PASSWORD;
if (!password) {
const { default: prompts } = await import("prompts");
const result = await prompts({
type: "password",
name: "password",
message: "Admin password:",
validate: (p: string) => p.length >= 1,
});
const { default: inquirer } = await import("inquirer");
const result = await inquirer.prompt<{ password: string }>([
{
type: "password",
name: "password",
message: "Admin password:",
mask: "*",
validate: (value: string) => value.length >= 1 || "Password is required",
},
]);
password = result.password;
}
await runApiKeyLogin({ serverUrl: opts.url, email: opts.email, password });
await runApiKeyLogin({ serverUrl: opts.url, email: opts.email, password: password ?? "" });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Tighten the password type narrowing instead of ?? "".

password ?? "" is only there to satisfy TS narrowing (process.env.ADMIN_PASSWORD is string | undefined). With the inquirer validate enforcing length ≥ 1, an empty string is logically unreachable — but if the env-var branch ever sets ADMIN_PASSWORD="", the truthy check on Line 570 sends control into the prompt block, so that's also covered. The ?? "" therefore silently swallows any future bug where password legitimately becomes undefined and forwards "" to the server, which will fail z.string().min(1) with an opaque 400.

Prefer narrowing explicitly so a regression surfaces locally rather than as a server-side validation error:

Proposed narrowing
-			if (opts.email) {
-				const { runApiKeyLogin } = await import("./commands/login");
-				let password = process.env.ADMIN_PASSWORD;
-				if (!password) {
+			if (opts.email) {
+				const { runApiKeyLogin } = await import("./commands/login");
+				let password: string | undefined = process.env.ADMIN_PASSWORD;
+				if (!password) {
 					const { default: inquirer } = await import("inquirer");
 					const result = await inquirer.prompt<{ password: string }>([
 						{
 							type: "password",
 							name: "password",
 							message: "Admin password:",
 							mask: "*",
 							validate: (value: string) => value.length >= 1 || "Password is required",
 						},
 					]);
 					password = result.password;
 				}
-				await runApiKeyLogin({ serverUrl: opts.url, email: opts.email, password: password ?? "" });
+				if (!password) {
+					logger.error("Password is required");
+					process.exit(1);
+				}
+				await runApiKeyLogin({ serverUrl: opts.url, email: opts.email, password });
 			} else {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let password = process.env.ADMIN_PASSWORD;
if (!password) {
const { default: prompts } = await import("prompts");
const result = await prompts({
type: "password",
name: "password",
message: "Admin password:",
validate: (p: string) => p.length >= 1,
});
const { default: inquirer } = await import("inquirer");
const result = await inquirer.prompt<{ password: string }>([
{
type: "password",
name: "password",
message: "Admin password:",
mask: "*",
validate: (value: string) => value.length >= 1 || "Password is required",
},
]);
password = result.password;
}
await runApiKeyLogin({ serverUrl: opts.url, email: opts.email, password });
await runApiKeyLogin({ serverUrl: opts.url, email: opts.email, password: password ?? "" });
let password: string | undefined = process.env.ADMIN_PASSWORD;
if (!password) {
const { default: inquirer } = await import("inquirer");
const result = await inquirer.prompt<{ password: string }>([
{
type: "password",
name: "password",
message: "Admin password:",
mask: "*",
validate: (value: string) => value.length >= 1 || "Password is required",
},
]);
password = result.password;
}
if (!password) {
logger.error("Password is required");
process.exit(1);
}
await runApiKeyLogin({ serverUrl: opts.url, email: opts.email, password });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/index.ts` around lines 569 - 583, The code should not
silently coerce password to "" before calling runApiKeyLogin; instead, after the
inquirer prompt or env check ensure password is a non-empty string and surface a
local error if it's missing. Replace the `password ?? ""` usage by explicitly
validating the `password` variable (the value read from
process.env.ADMIN_PASSWORD or from the inquirer prompt) and if it is undefined
or an empty string throw or exit with a clear message like "Admin password is
required" so the issue is caught locally, then pass the validated password into
runApiKeyLogin (use the validated variable directly, e.g., password or password!
after the explicit check).

@weroperking weroperking merged commit 2388ce5 into main Apr 26, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant