Skip to content

feat(cliproxy): restrict Kamino credentials by model family - #3241

Merged
shunkakinoki merged 1 commit into
mainfrom
fix/kamino-credential-model-routing
Oct 29, 2026
Merged

shunkakinoki merged 1 commit into
mainfrom
fix/kamino-credential-model-routing

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Changes

  • Add declarative model_family policies to Kamino credential mappings.
  • Enforce per-OAuth credential model-family exclusions in CLIProxy, preserving operator-authored exclusions.
  • Expose the policy in generated kamino-fleet.json and document the configuration.

Technical details

A model_family: haiku mapping excludes Claude model IDs containing opus, sonnet, or fable, so that credential can only register and route to Haiku models. Unknown families fail closed during Nix evaluation or proxy rendering.

Testing

  • shellspec spec/cliproxyapi_spec.sh spec/kamino_fleet_spec.sh (99 examples, 0 failures)
  • Nix evaluation/build of the Kamino package
  • bash -n, ShellCheck, nixfmt --check, and git diff --check

Generated with Codex.


Summary by cubic

Restricts Kamino tunnel credentials to a declared model family so OAuth credentials can only route to the models they are approved for.

  • Adds an optional model_family field to kamino-tunnels.json; the CLIProxy start script renders it into excluded_models rules on the matching auth file before starting.
  • Validates the family at Nix evaluation and in the proxy renderer; unknown families fail closed instead of silently widening routes.
  • Generates kamino-fleet.json with the same model_family field and strips previously generated exclusions when a policy is removed.
  • Sets the claude-2738f2fb-jangly-bears6h@icloud.com credential to haiku, so it can no longer serve Opus, Sonnet, or Fable models.

Migration

  • Any credential you want restricted needs a model_family entry in kamino-tunnels.json. Credentials without one keep their current behavior.

Written for commit 0497b5f. Summary will update on new commits.

View guided diff Turn on auto-fix

@indent

indent Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Warning

This organization's free trial has ended, so Indent couldn't continue this review. Manage billing to resume reviews on this repository.

CI Checks

All required CI checks passed on 0497b5f.

Review agents

Select any unchecked box below to run or rerun that agent.

Pending (1)
  • Indent Review Agent · This agent has not run.
Full results

Indent Review Agent

  • Summary: This agent has not run.
  • Latest resultNo result — this agent has not run.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@shunkakinoki shunkakinoki added the enhancement Indicates new feature requests. label Oct 29, 2026
@shunkakinoki
shunkakinoki marked this pull request as ready for review October 29, 2026 00:54
@shunkakinoki
shunkakinoki merged commit f029d50 into main Oct 29, 2026
10 checks passed
@shunkakinoki
shunkakinoki deleted the fix/kamino-credential-model-routing branch October 29, 2026 00:54
@linear-code

linear-code Bot commented Oct 29, 2026

Copy link
Copy Markdown

SHUN-33630

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

ℹ️ No critical issues — minor suggestions inline.

Reviewed changes Restricts Kamino tunnel OAuth credentials by model family so each credential can only register and route to its approved Claude family.

  • home-manager/programs/kamino/default.nix — reads kamino-tunnels.json, validates model_family against an allow-list (fail-closed at Nix eval), and writes model_family into kamino-fleet.json per machine.
  • home-manager/services/cliproxyapi/scripts/start.sh — adds model_policy_exclusions() and apply_model_policies(); writes excluded_models plus fleet_model_* markers to matching OAuth auth files; rollback removes only generated exclusions on policy removal. Invoked at start.sh:239.
  • kamino-tunnels.json — sets model_family: "haiku" for the jangly-bears6h Claude credential.
  • home-manager/services/cliproxyapi/README.md — documents model_family configuration.
  • spec/cliproxyapi_spec.sh — tests exclusions definition and apply-to-auth-file behavior.

Implementation is sound: fail-closed Nix validation, marker-based rollback that preserves operator-authored exclusions, and lock coordination matching the existing assign_proxy_urls pattern.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using free | 𝕏

if @jq@ -e 'has("fleet_model_policy") and has("fleet_model_excluded_models")' "$f" >/dev/null 2>&1; then
# shellcheck disable=SC2016
@jq@ 'if has("fleet_model_previous_excluded_models") then .excluded_models = .fleet_model_previous_excluded_models elif .excluded_models == .fleet_model_excluded_models then del(.excluded_models) else . end | del(.fleet_model_policy, .fleet_model_excluded_models, .fleet_model_previous_excluded_models)' "$f" >"$f.tmp" && mv "$f.tmp" "$f"
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.

The removal/rollback path keys on fleet_model_policy and fleet_model_excluded_models markers written into each auth file. CLIProxyAPI rewrites auth files on every token refresh (README.md:74); if it strips unknown JSON fields when re-serializing, these markers—and excluded_models itself—lapse between start.sh runs. The restriction would then only be enforced until the next refresh, and the rollback path wouldn't fire on CLIProxy-rewritten files. This is an external-behavior question, not a confirmed bug.

Technical details

# Marker survival across CLIProxy auth-file rewrites

## Affected sites
- home-manager/services/cliproxyapi/scripts/start.sh:182-185 — removal logic keys on fleet_model_* markers
- home-manager/services/cliproxyapi/scripts/start.sh:175-177 — markers written alongside excluded_models

## Required outcome
- Confirm whether CLIProxy preserves unknown JSON fields (excluded_models, fleet_model_*) when rewriting auth files on token refresh, or document the restriction lapses between start.sh runs.

## Suggested approach (optional)
- Empirically diff an auth file before and after a CLIProxy token refresh to see whether excluded_models survives.
- If CLIProxy strips unknown fields, either re-apply policies on a schedule or note the window in the README.

## Open questions for the human
- Does CLIProxyAPI preserve custom JSON fields in auth files across token refreshes?

if matches == [ ] then { } else { model_family = (builtins.head matches).model_family; };
inventory = pkgs.writeText "kamino-fleet.json" (
builtins.toJSON (
fleet

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.

Nix validation of model_family is case-sensitive (allowedModelFamilies is lowercase), but the shell model_policy_exclusions lowercases its input (${1,,}). A value like "Haiku" would fail Nix evaluation yet pass the shell function in isolation. Not a bug with the current all-lowercase data, but worth aligning for consistency.

Technical details

# Case-sensitivity mismatch between Nix and shell

## Affected sites
- home-manager/programs/kamino/default.nix:26 — case-sensitive elem check against lowercase allowedModelFamilies
- home-manager/services/cliproxyapi/scripts/start.sh:128 — model_policy_exclusions lowercases via ${1,,}

## Required outcome
- Align case handling so Nix and shell agree on accepted model_family values.

## Suggested approach (optional)
- Either lowercase in Nix before the elem check, or drop the lowercase in shell to match Nix (and update the spec test that uses "Haiku").

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

Labels

enhancement Indicates new feature requests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant