Skip to content

fix: guard cliproxyapi auth on restart - #545

Merged
shunkakinoki merged 1 commit into
mainfrom
fix/cliproxyapi-auth-guard
Jan 11, 2026
Merged

fix: guard cliproxyapi auth on restart#545
shunkakinoki merged 1 commit into
mainfrom
fix/cliproxyapi-auth-guard

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Jan 11, 2026

Copy link
Copy Markdown
Owner

Changes

Technical Details

  • If S3 creds exist and the local auth cache is empty, hydrate from s3://$OBJECTSTORE_BUCKET/auths and backup/auths, then re-sync back to S3 to avoid deletions on restart
  • Pass awscli into the Nix start script so the guard can run

Testing

  • shellspec spec/cliproxyapi_spec.sh spec/cliproxyapi_backup_spec.sh

🤖 Generated with Codex CLI by GPT-5


Summary by cubic

Protect CLIProxyAPI auth cache on restart by hydrating from S3 when the local cache is empty, then re-syncing to avoid deletions. Also wires awscli into the start script and makes small CI tweaks.

  • Bug Fixes

    • Add pre-start S3 hydrate + re-sync guard in start.sh for auths when OBJECTSTORE_* env vars are set.
  • Dependencies

    • Pass awscli2 into the Nix start script.
    • Pin actions/download-artifact to v6 and add nix-nixos to the CI matrix.

Written for commit fe4a9da. Summary will update on new commits.

Copilot AI review requested due to automatic review settings January 11, 2026 19:55
@coderabbitai

coderabbitai Bot commented Jan 11, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@shunkakinoki has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 56 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 41ef00a and fe4a9da.

📒 Files selected for processing (4)
  • .github/workflows/docker.yml
  • .github/workflows/nix.yml
  • home-manager/services/cliproxyapi/default.nix
  • home-manager/services/cliproxyapi/scripts/start.sh
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/cliproxyapi-auth-guard

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.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @shunkakinoki, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a critical fix for the cliproxyapi service to ensure the persistence and integrity of its authentication cache across restarts. By integrating AWS CLI into the service's startup process, it establishes a robust pre-start synchronization mechanism with S3, preventing potential data loss and ensuring consistent authentication states.

Highlights

  • S3 Auth Cache Guard: Implemented a pre-start guard for the cliproxyapi authentication cache. This mechanism hydrates the local cache from S3 if it's empty and then re-syncs it back to S3 to prevent data loss on service restarts.
  • AWS CLI Integration: The awscli2 package is now wired into the cliproxyapi start script, enabling S3 operations within the script.
  • CI/CD Updates: Pinned download-artifact to v6 and added nix-nixos to the CI matrix.
Ignored Files
  • Ignored by pattern: .github/workflows/** (2)
    • .github/workflows/docker.yml
    • .github/workflows/nix.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@mesa-dot-dev

mesa-dot-dev Bot commented Jan 11, 2026

Copy link
Copy Markdown

Mesa Description

TL;DR

Added a pre-start S3 hydrate and re-sync guard for the cliproxyapi authentication cache to prevent data loss on restart.

What changed?

  • Implemented a pre-start S3 hydrate and re-sync guard for the cliproxyapi auth cache.
  • Integrated awscli into the start script for the guard's functionality.
  • Updated CI: pinned download-artifact to v6 and extended the matrix with nix-nixos.

Description generated by Mesa. Update settings

@shunkakinoki shunkakinoki added the bug Indicates an unexpected problem or unintended behavior. label Jan 11, 2026
@shunkakinoki
shunkakinoki merged commit 74eb9e9 into main Jan 11, 2026
30 of 31 checks passed
@shunkakinoki
shunkakinoki deleted the fix/cliproxyapi-auth-guard branch January 11, 2026 19:56

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a pre-start guard in the cliproxyapi start script to handle S3 authentication cache hydration and synchronization, preventing data loss on restart. The changes are logical and correctly implement the described workaround. I have one suggestion to refactor the new shell script logic to improve its readability and maintainability by reducing code duplication.

Comment on lines +30 to +69
if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ]; then
mkdir -p "$AUTH_DIR"

if [ -z "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
echo "⚠️ Local auth cache empty; hydrating from S3" >&2
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/auths/" \
"$AUTH_DIR/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" \
"$AUTH_DIR/" || true
fi

if [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/auths/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" || true
fi
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The new logic for S3 synchronization contains significant code duplication, especially for the aws s3 sync commands and the AWS credentials. This can be refactored to improve readability and maintainability.

I suggest defining a helper function for the s3 sync operation and exporting the AWS credentials once at the beginning of the block. This will make the script cleaner, less error-prone, and easier to understand.

if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ]; then
  export AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY"
  export AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY"

  s3_sync() {
    @aws@ s3 sync --endpoint-url="$OBJECTSTORE_ENDPOINT" --no-progress "$@" || true
  }

  mkdir -p "$AUTH_DIR"

  if [ -z "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
    echo "⚠️  Local auth cache empty; hydrating from S3" >&2
    s3_sync "s3://${OBJECTSTORE_BUCKET}/auths/" "$AUTH_DIR/"
    s3_sync "s3://${OBJECTSTORE_BUCKET}/backup/auths/" "$AUTH_DIR/"
  fi

  if [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
    s3_sync "$AUTH_DIR/" "s3://${OBJECTSTORE_BUCKET}/auths/"
    s3_sync "$AUTH_DIR/" "s3://${OBJECTSTORE_BUCKET}/backup/auths/"
  fi
fi

@mesa-dot-dev mesa-dot-dev Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Performed full review of 41ef00a...fe4a9da

Analysis

  1. Silent Error Handling: The implementation uses || true for AWS CLI commands, which masks failures including authentication issues and network problems, creating debugging challenges and potential data loss when empty directories sync back to S3.

  2. Race Conditions: The guard logic lacks synchronization mechanisms, putting deployments at risk when multiple instances start simultaneously - they could corrupt data by racing to download and upload without coordination.

  3. Data Consistency Risk: The re-sync logic runs regardless of hydration success, potentially overwriting valid S3 data with empty local directories. Additionally, without --delete flags, removed auth tokens remain in S3.

  4. Technical Debt: This "temporary workaround" lacks proper tracking mechanisms (TODO comments, follow-up tickets) to ensure it doesn't become permanent, creating future maintenance challenges.

  5. Unexplained CI Changes: The artifact downgrade from v7 to v6 appears unrelated to the main fix and has no documented rationale, suggesting potential compatibility issues.

Tip

Help

Slash Commands:

  • /review - Request a full code review
  • /review latest - Review only changes since the last review
  • /describe - Generate PR description. This will update the PR body or issue comment depending on your configuration
  • /help - Get help with Mesa commands and configuration options

0 files reviewed | 3 comments | Edit Agent SettingsRead Docs

"$AUTH_DIR/" || true
fi

if [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium

This condition checks if AUTH_DIR has files after the hydration attempts, but both hydration commands used || true (lines 41, 49). If both S3 syncs failed silently, this block will still execute and sync an empty directory back to S3, potentially overwriting valid remote data. Consider checking the exit status of the hydration commands before proceeding with the re-sync.

Agent: 🏛 Architecture • Fix in Cursor • Fix in Claude

Prompt for Agent
Task: Address review feedback left on GitHub.
Repository: shunkakinoki/dotfiles#545
File: home-manager/services/cliproxyapi/scripts/start.sh#L52
Action: Open this file location in your editor, inspect the highlighted code, and resolve the issue described below.

Feedback:
This condition checks if AUTH_DIR has files after the hydration attempts, but both hydration commands used `|| true` (lines 41, 49). If both S3 syncs failed silently, this block will still execute and sync an empty directory back to S3, potentially overwriting valid remote data. Consider checking the exit status of the hydration commands before proceeding with the re-sync.

--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/auths/" \
"$AUTH_DIR/" || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium

The || true here silently ignores all S3 sync failures, including authentication errors, network issues, or misconfigured endpoints. Consider logging the error and potentially failing fast if S3 credentials are provided but the sync fails, as this could indicate a configuration problem that will persist.

Agent: 🏛 Architecture • Fix in Cursor • Fix in Claude

Prompt for Agent
Task: Address review feedback left on GitHub.
Repository: shunkakinoki/dotfiles#545
File: home-manager/services/cliproxyapi/scripts/start.sh#L41
Action: Open this file location in your editor, inspect the highlighted code, and resolve the issue described below.

Feedback:
The `|| true` here silently ignores all S3 sync failures, including authentication errors, network issues, or misconfigured endpoints. Consider logging the error and potentially failing fast if S3 credentials are provided but the sync fails, as this could indicate a configuration problem that will persist.

MANAGEMENT_PASSWORD="${CLIPROXY_MANAGEMENT_PASSWORD:-}"
export OBJECTSTORE_ENDPOINT OBJECTSTORE_BUCKET OBJECTSTORE_ACCESS_KEY OBJECTSTORE_SECRET_KEY MANAGEMENT_PASSWORD

if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium

If multiple instances of this service start simultaneously (e.g., during a deployment rollout), they could all detect an empty AUTH_DIR and race to sync from/to S3, potentially causing conflicts or data corruption. Consider adding a lock mechanism or using S3's conditional operations to prevent concurrent modifications.

Agent: 🏛 Architecture • Fix in Cursor • Fix in Claude

Prompt for Agent
Task: Address review feedback left on GitHub.
Repository: shunkakinoki/dotfiles#545
File: home-manager/services/cliproxyapi/scripts/start.sh#L30
Action: Open this file location in your editor, inspect the highlighted code, and resolve the issue described below.

Feedback:
If multiple instances of this service start simultaneously (e.g., during a deployment rollout), they could all detect an empty AUTH_DIR and race to sync from/to S3, potentially causing conflicts or data corruption. Consider adding a lock mechanism or using S3's conditional operations to prevent concurrent modifications.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a temporary workaround for a CLIProxyAPI auth cache issue by adding S3 hydration and re-sync guards directly in the start script, while also improving CI configuration.

Changes:

  • Adds auth cache hydration and sync logic to start.sh to prevent auth loss on restart
  • Wires awscli2 into the Nix start script via replaceVars
  • Pins GitHub Actions download-artifact to v6 for compatibility with upload-artifact v6
  • Adds nix-nixos job to the CI dependency check matrix

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
home-manager/services/cliproxyapi/scripts/start.sh Adds AUTH_DIR definition and implements S3 hydration/sync guard logic when auth cache is empty
home-manager/services/cliproxyapi/default.nix Wires awscli2 binary path into start script via replaceVars
.github/workflows/docker.yml Pins download-artifact action to v6 for compatibility with upload-artifact v6
.github/workflows/nix.yml Adds nix-nixos job to the nix-check dependency list

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +53 to +67
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/auths/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" || true

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

This duplicates the backup logic already present in backup.sh (lines 38-52). This creates maintenance burden as changes to the sync logic need to be made in multiple places. Consider calling the existing backup.sh script instead of duplicating the logic, or extract this into a shared function.

Suggested change
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/auths/" || true
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" || true
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
backup_script="${script_dir}/backup.sh"
if [ ! -x "$backup_script" ]; then
echo "Expected backup script not found or not executable: $backup_script" >&2
exit 1
fi
OBJECTSTORE_ENDPOINT="$OBJECTSTORE_ENDPOINT" \
OBJECTSTORE_BUCKET="$OBJECTSTORE_BUCKET" \
OBJECTSTORE_ACCESS_KEY="$OBJECTSTORE_ACCESS_KEY" \
OBJECTSTORE_SECRET_KEY="$OBJECTSTORE_SECRET_KEY" \
AUTH_DIR="$AUTH_DIR" \
"$backup_script"

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +67
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/auths/" \
"$AUTH_DIR/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" \
"$AUTH_DIR/" || true
fi

if [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/auths/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" || true

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

The || true at the end of each aws s3 sync command ensures the script continues even if syncs fail. While this provides resilience, failed syncs are completely silent with no error logging. Consider adding error logging after failed syncs to aid debugging, for example: || echo "⚠️ Failed to sync from/to S3 [location]" >&2

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +68
if [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/auths/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" || true
fi

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

On every restart when the auth cache is not empty, four S3 sync operations are performed (lines 55-67). This happens even if the local and remote are already in sync. The aws s3 sync command is efficient and only uploads changed files, but the overhead of establishing connections and checking every file on each restart could add startup latency. Consider adding a timestamp check or other mechanism to skip syncing if a recent sync has already occurred.

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +69
if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ]; then
mkdir -p "$AUTH_DIR"

if [ -z "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
echo "⚠️ Local auth cache empty; hydrating from S3" >&2
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/auths/" \
"$AUTH_DIR/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" \
"$AUTH_DIR/" || true
fi

if [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/auths/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"$AUTH_DIR/" \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" || true
fi
fi

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

The new auth guard logic (lines 30-69) lacks test coverage. While hydrate.sh and backup.sh have tests in spec/cliproxyapi_backup_spec.sh, the conditional logic for checking if AUTH_DIR is empty, hydrating, and syncing back should be tested. Consider adding test cases to spec/cliproxyapi_spec.sh that verify: 1) hydration occurs when AUTH_DIR is empty, 2) hydration is skipped when AUTH_DIR has files, 3) sync back occurs after hydration, and 4) proper handling when S3 credentials are missing.

Copilot uses AI. Check for mistakes.
MANAGEMENT_PASSWORD="${CLIPROXY_MANAGEMENT_PASSWORD:-}"
export OBJECTSTORE_ENDPOINT OBJECTSTORE_BUCKET OBJECTSTORE_ACCESS_KEY OBJECTSTORE_SECRET_KEY MANAGEMENT_PASSWORD

if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ]; then

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

The condition should also check that OBJECTSTORE_BUCKET is not empty. While it defaults to "cliproxyapi" on line 24, it's possible for the variable to be explicitly set to an empty string in the environment, which would result in invalid S3 paths like "s3:///auths/".

Suggested change
if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ]; then
if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ] && [ -n "$OBJECTSTORE_BUCKET" ]; then

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +50
if [ -z "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
echo "⚠️ Local auth cache empty; hydrating from S3" >&2
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/auths/" \
"$AUTH_DIR/" || true

AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 sync \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
--no-progress \
"s3://${OBJECTSTORE_BUCKET}/backup/auths/" \
"$AUTH_DIR/" || true
fi

Copilot AI Jan 11, 2026

Copy link

Choose a reason for hiding this comment

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

This duplicates the hydration logic already present in hydrate.sh (lines 33-47). This creates maintenance burden as changes to the sync logic need to be made in multiple places. Consider calling the existing hydrate.sh script instead of duplicating the logic, or extract this into a shared function.

Copilot uses AI. Check for mistakes.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 4 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="home-manager/services/cliproxyapi/scripts/start.sh">

<violation number="1" location="home-manager/services/cliproxyapi/scripts/start.sh:31">
P2: Auth cache directory is created/populated without restrictive permissions, leaving OAuth tokens potentially world-readable</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

export OBJECTSTORE_ENDPOINT OBJECTSTORE_BUCKET OBJECTSTORE_ACCESS_KEY OBJECTSTORE_SECRET_KEY MANAGEMENT_PASSWORD

if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ]; then
mkdir -p "$AUTH_DIR"

@cubic-dev-ai cubic-dev-ai Bot Jan 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Auth cache directory is created/populated without restrictive permissions, leaving OAuth tokens potentially world-readable

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/services/cliproxyapi/scripts/start.sh, line 31:

<comment>Auth cache directory is created/populated without restrictive permissions, leaving OAuth tokens potentially world-readable</comment>

<file context>
@@ -26,6 +27,47 @@ OBJECTSTORE_SECRET_KEY="$(strip_quotes "${OBJECTSTORE_SECRET_KEY:-}")"
 export OBJECTSTORE_ENDPOINT OBJECTSTORE_BUCKET OBJECTSTORE_ACCESS_KEY OBJECTSTORE_SECRET_KEY MANAGEMENT_PASSWORD
 
+if [ -n "$OBJECTSTORE_ENDPOINT" ] && [ -n "$OBJECTSTORE_ACCESS_KEY" ] && [ -n "$OBJECTSTORE_SECRET_KEY" ]; then
+  mkdir -p "$AUTH_DIR"
+
+  if [ -z "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Indicates an unexpected problem or unintended behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants