fix(otto): preflight org membership before launching Otto (AI-992) - #2208
Open
akshayarora wants to merge 1 commit into
Open
fix(otto): preflight org membership before launching Otto (AI-992)#2208akshayarora wants to merge 1 commit into
akshayarora wants to merge 1 commit into
Conversation
`astro otto` could spawn Otto with a token whose user isn't a member of ASTRO_ORGANIZATION — e.g. a stale ASTRO_ORGANIZATION export, or an org selected under a different login. The mismatch was invisible at launch (the LLM gateway isn't RBAC-gated) and only surfaced later as a confusing "403: organization <id> is forbidden" on the first org-scoped call (hosted skills). Add a launch-time membership preflight in pkg/otto: - Resolve the effective org the way BuildEnv does (context org, else the inherited ASTRO_ORGANIZATION that passes through when the context org is empty) and call GetOrganization with the current token. - On a definitive 403/404, fail fast with actionable guidance that names the signed-in user (astro login / astro organization switch / clear a stale export), and exit quietly like ErrNotLoggedIn. - Fail CLOSED only on 403/404; any transient or inconclusive outcome (request error, 5xx, unexpected shape) lets the launch proceed so the preflight can never become a new way for `astro otto` to break. Adds pkg/otto/preflight_test.go covering member/403/404, the inherited-env org path, self-user lookup failure, skip-when-no-org/token, and fail-open. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Coverage Report for CI Build 29289835256Coverage increased (+0.03%) to 43.918%Details
Uncovered Changes
Coverage Regressions1 previously-covered line in 1 file lost coverage.
Coverage Stats
💛 - Coveralls |
akshayarora
marked this pull request as ready for review
July 23, 2026 17:42
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
astro ottocould launch Otto with a token whose user isn't a member ofASTRO_ORGANIZATION, and the mismatch was invisible until a downstream, RBAC-gated feature failed. A demo/interview user hit it as:Root cause: the org and the token identity are decoupled, and the only place that reconciles them is
astro login(resolveActiveOrg), notastro otto. The org handed to Otto can come from the stored context block, anASTRO_DOMAIN-selected block, or a stale shell-exportedASTRO_ORGANIZATIONthatBuildEnvpasses through when the context org is empty. Core's LLM gateway isn't RBAC-gated, so Otto boots and chats fine; only the first org-scoped, permission-checked call (hosted skills) 403s — reading like a skills bug.Change
A launch-time membership preflight in
pkg/otto(preflight.go), run inStart()right after the login check:BuildEnvdoes (context org, else inheritedASTRO_ORGANIZATION) and callsGetOrganizationwith the current token.astro login/astro organization switch/ clear a stale export) and returnsErrNotOrgMember;cmd/otto.goexits quietly (mirrorsErrNotLoggedIn).astro ottoto break.Testing
pkg/otto/preflight_test.go(12 cases, all green): effective-org resolution; member proceeds silently; 403 and 404 fail closed with user-named guidance; the inherited-env-org path; self-user lookup failure still blocks with a generic subject; skip-when-no-org/token; and fail-open on request-error / 5xx.go build,go vet, and the fullpkg/ottosuite pass.Notes
organization.skills.get. This PR fixes the client so the failure is caught early with a clear message instead of surfacing mid-session.astronomer/ottomakes the skill-fetch 403 self-explain for callers that bypassastro otto(dev scripts, SDK).🤖 Generated with Claude Code