Skip to content

feat(setup): R2-optional deploys + headless service key generation (CLA-107)#37

Merged
JuzzyDee merged 2 commits into
devfrom
juzzydee/cla-107-setupsh-headless-service-key-generation-r2-optional
May 22, 2026
Merged

feat(setup): R2-optional deploys + headless service key generation (CLA-107)#37
JuzzyDee merged 2 commits into
devfrom
juzzydee/cla-107-setupsh-headless-service-key-generation-r2-optional

Conversation

@JuzzyDee

@JuzzyDee JuzzyDee commented May 22, 2026

Copy link
Copy Markdown
Owner

Summary

  • R2 is now optional. wrangler.toml.example ships [[r2_buckets]] commented out, setup.sh prompts the operator, and the worker detects the missing IMAGES binding at runtime — remember_with_image/recall_image are hidden from the MCP tools listing when R2 is absent, and return a clean error if a stale client somehow still calls them. Unblocks deploys on truly free CF accounts (R2 is the only stack component that needs billing enabled, even within its 10GB free tier).
  • setup.sh mints a starter service key on request. New optional Step 4 prompt runs the existing keygen subcommand (with new --quiet flag for scripting), captures the raw key + env entry from stdout, pushes the hash to ONEIRO_API_KEYS, and surfaces the raw key in the final summary with a "store now, unrecoverable" warning. Orient hook (CLA-105), rover, and any non-interactive caller work out of the box from a fresh deploy.
  • Incidental cleanup: removed retired ONEIRO_ADMIN_KEY generation/display/push from setup + the wrangler example (CLA-103 retired its only consumer, the /restore admin endpoint).

CLA-112 tracks the deeper multi-key UX fix (move the hash list to a D1 table so add/list/revoke are first-class DB ops).

Test plan

  • cargo test (127 tests pass — 78 + 49)
  • cargo check --target wasm32-unknown-unknown --lib clean
  • worker-build --release produces the wasm bundle (28KB)
  • bash -n scripts/setup.sh syntax check
  • setup.sh --dry-run decline-both path (R2 skipped, no service key, no ONEIRO_API_KEYS push)
  • setup.sh --dry-run accept-both path (R2 bucket created + [[r2_buckets]] uncommented in wrangler.toml, service key generated, ONEIRO_API_KEYS pushed, raw key block displayed before summary)
  • Smoke-tested cargo run --bin oneiro -- keygen --role rover --quiet — emits raw key + env entry as two parseable stdout lines
  • End-to-end first-run on a fresh CF account (will validate post-merge by re-running on the live deploy)

Closes CLA-107.

Summary by CodeRabbit

  • New Features

    • Optional image storage provisioning during setup
    • Optional starter service API key generation during setup (raw key shown once after deploy)
    • New quiet mode for key generation that emits a machine-parseable key
  • Behavior Changes

    • Image-related tools are shown only when image storage is configured
  • Bug Fixes

    • Clearer messaging when image storage is not configured
  • Chores

    • Updated setup flow and configuration templates

Review Change Stack

…LA-107)

Two first-run convenience gaps bundled because both live in setup-time
ergonomics:

  * Image storage (R2) is now optional. The wrangler.toml.example ships
    [[r2_buckets]] commented out, setup.sh prompts the operator, and
    the worker detects the missing IMAGES binding at runtime —
    remember_with_image and recall_image are hidden from the MCP tools
    listing when R2 is absent, and return a clean error if a stale
    client calls them anyway. This unblocks deploys on truly free CF
    accounts (R2 is the one stack component that needs billing
    enabled, even within its 10GB free tier).

  * setup.sh prompts whether to mint a starter rover service key. If
    yes, runs the existing keygen subcommand (with new --quiet flag
    for scripting), captures the raw key + env entry from stdout,
    pushes the hash to ONEIRO_API_KEYS, and surfaces the raw key in
    the final summary with a "store now, unrecoverable" warning. The
    orient hook (CLA-105), rover, and any non-interactive caller now
    work out of the box from a fresh deploy.

Incidental cleanup: removed ONEIRO_ADMIN_KEY generation, display, and
secret push from setup.sh + wrangler.toml.example. CLA-103 retired the
/restore admin endpoint that was its only consumer; the secret has
been dead weight since.

CLA-112 (backlog) tracks the deeper fix for multi-key UX: moving the
hash list out of the wrangler secret and into a D1 table so add /
list / revoke are first-class DB operations.
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Optional R2 image storage is now opt-in in setup; keygen gains a machine-friendly --quiet output. The worker advertises image tools only when the IMAGES binding exists. The setup script drops ONEIRO_ADMIN_KEY, can create a starter rover API key, updates secrets push, and patches wrangler.toml accordingly.

Changes

Optional R2 and API Key Provisioning

Layer / File(s) Summary
API Key Quiet Output Mode
src/api_key.rs, src/main.rs
Adds print_generated_key_quiet() that emits raw key and env entry to stdout, and a --quiet flag in oneiro keygen to use this machine-parseable output.
Worker Dynamic Tool Listing with Optional R2
src/worker_mcp.rs
dispatch passes Env to handle_tools_list; image tools are appended only when IMAGES R2 binding is present. Image tool handlers now return a clear "feature disabled / enable R2" error when binding is missing.
Configuration Template for Optional R2
wrangler.toml.example
Converts the IMAGES R2 bucket into a commented optional block with guidance and removes the ONEIRO_ADMIN_KEY secret template.
Setup Script: R2 Provisioning and API Key Generation
scripts/setup.sh
Interactive prompt to enable R2 and conditional bucket creation/wrangler.toml patching; removes ONEIRO_ADMIN_KEY from credential output; optional starter rover API key generation (dry-run supported), stores hash in ONEIRO_API_KEYS, conditionally pushes secrets, and prints raw starter key after deploy.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A rabbit found a vault behind the shell,
Asked kindly if the images may dwell,
Quiet keys whispered, two lines to seize,
Tools appear only when bindings please,
Provisioned, patched, a tiny triumph bell 🐇✨

🚥 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 'feat(setup): R2-optional deploys + headless service key generation (CLA-107)' directly and concisely summarizes the two main changes: optional R2 provisioning and new service key generation flow in setup.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch juzzydee/cla-107-setupsh-headless-service-key-generation-r2-optional

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/setup.sh`:
- Around line 366-380: The script currently treats any non-zero result from the
command `wrangler r2 bucket create` (whose output is captured in R2_OUT) as
“likely already exists” and proceeds to enable the `IMAGES` binding; change this
so you inspect R2_OUT for an explicit “already exists” (or equivalent) message
and only proceed with the awk block that enables the `[[r2_buckets]]`/binding
`IMAGES` when that text is present or when the create succeeded; otherwise call
`warn` with the full R2_OUT and exit non-zero to fail fast on real errors
(billing/auth/permission), i.e., update the if/else around `wrangler r2 bucket
create` and gate the awk mv step on that check.
🪄 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: CHILL

Plan: Pro Plus

Run ID: d9dc5578-4ba8-4958-a0b7-4566c437b113

📥 Commits

Reviewing files that changed from the base of the PR and between 89d3f14 and 23b9e02.

📒 Files selected for processing (5)
  • scripts/setup.sh
  • src/api_key.rs
  • src/main.rs
  • src/worker_mcp.rs
  • wrangler.toml.example

Comment thread scripts/setup.sh
…lready-exists (CLA-107)

PR #37 review (CodeRabbit): the previous code treated every non-zero
exit from `wrangler r2 bucket create` as "likely already exists" and
fell through to uncomment the IMAGES binding. That silently masked
the failure mode CLA-107 is specifically designed to handle —
billing not enabled on the Cloudflare account — by enabling the
binding anyway and surfacing the failure two steps later as a
confusing wrangler deploy error.

Now three outcomes: success → proceed, already-exists (detected by
explicit grep on R2_OUT) → proceed with a warning, anything else →
print the full R2_OUT, point at the common causes (billing, R2
permissions), exit 1. The binding-uncomment + ok message only fire
when create actually succeeded or the bucket was already there.

@coderabbitai coderabbitai 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.

Caution

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

⚠️ Outside diff range comments (1)
scripts/setup.sh (1)

551-558: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Discarding stderr hides keygen failures.

Line 551 redirects stderr to /dev/null, so if keygen fails (compilation error, runtime panic, missing dependency), the operator sees only "keygen produced no output" with no diagnostic. Consider capturing stderr or letting it pass through:

-        if KEYGEN_OUT=$(cargo run --quiet --bin oneiro -- keygen --role rover --quiet 2>/dev/null); then
+        if KEYGEN_OUT=$(cargo run --quiet --bin oneiro -- keygen --role rover --quiet 2>&1); then
             RAW_API_KEY=$(printf '%s\n' "$KEYGEN_OUT" | sed -n '1p')
             API_KEY_ENTRY=$(printf '%s\n' "$KEYGEN_OUT" | sed -n '2p')
+        else
+            err "keygen failed:"
+            printf '%s\n' "$KEYGEN_OUT" | sed 's/^/    /'
+            exit 1
         fi

Alternatively, let stderr flow to the terminal (2>&2) and keep stdout capture separate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/setup.sh` around lines 551 - 558, The script hides keygen errors by
redirecting stderr to /dev/null when running "cargo run --bin oneiro -- keygen
--role rover" into KEYGEN_OUT; change the invocation so stderr is preserved or
captured (e.g., allow stderr to flow to the terminal or capture it into a
separate variable/file) and include those stderr contents in the failure path
that logs the error, so when RAW_API_KEY or API_KEY_ENTRY are empty you can
print the actual keygen stderr output alongside the "keygen produced no output"
message; update the block that sets KEYGEN_OUT and the error branch that calls
err and exit to reference KEYGEN_OUT/stderr capture accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/setup.sh`:
- Around line 551-558: The script hides keygen errors by redirecting stderr to
/dev/null when running "cargo run --bin oneiro -- keygen --role rover" into
KEYGEN_OUT; change the invocation so stderr is preserved or captured (e.g.,
allow stderr to flow to the terminal or capture it into a separate
variable/file) and include those stderr contents in the failure path that logs
the error, so when RAW_API_KEY or API_KEY_ENTRY are empty you can print the
actual keygen stderr output alongside the "keygen produced no output" message;
update the block that sets KEYGEN_OUT and the error branch that calls err and
exit to reference KEYGEN_OUT/stderr capture accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f747aa02-ae99-4f81-b1c4-acb59242cde8

📥 Commits

Reviewing files that changed from the base of the PR and between 23b9e02 and c175385.

📒 Files selected for processing (1)
  • scripts/setup.sh

@JuzzyDee JuzzyDee merged commit 1e42af7 into dev May 22, 2026
6 checks passed
@JuzzyDee JuzzyDee deleted the juzzydee/cla-107-setupsh-headless-service-key-generation-r2-optional branch May 22, 2026 23:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant