Skip to content

fix: Explain refused org-wide listing and reject org/project names - #360

Merged
0xmc merged 3 commits into
mainfrom
fix/org-scope-all-namespaces-hint
Nov 6, 2026
Merged

0xmc merged 3 commits into
mainfrom
fix/org-scope-all-namespaces-hint

Conversation

@0xmc

@0xmc 0xmc commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Listing a resource across all namespaces at organization scope is refused for every role, yet the get help recommended it and the refusal gave no next step.

The help example now lists across a project, and a refused org-wide listing prints a hint naming the project form and how to find project names.

Passing the org/project form that context listing prints as a project name now fails up front with a hint naming the bare project, instead of failing on discovery errors.

Test plan

  • An org-wide listing across namespaces prints the refusal followed by the hint, in human and JSON error formats
  • Project-scoped listings and org-scoped listings of organization resources print no hint
  • An org/project value for the project flag or environment variable fails with a hint naming the bare project

Fixes #357

🤖 Generated with Claude Code

0xmc and others added 2 commits November 6, 2026 13:53
The authorizer refuses to list a namespaced resource across all
namespaces at organization scope, for every role: an organization's
resources live in one namespace, and project resources live in each
project's own control plane. The get help still recommended that
form, and the refusal printed a bare Forbidden with no next step.

The hint is attached only when the server actually returns Forbidden,
so datumctl does not duplicate the server's rule and will not block
the form if the server ever allows it.

Key changes:
- Show listing across every namespace in a project in the get example
- After a Forbidden for get -A at organization scope, print a hint
  naming the project form and how to find project names
- Carry the hint in the JSON and YAML error envelopes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
'datumctl ctx list' prints project contexts as org/project, and that
form passed to --project or DATUM_PROJECT went straight into the
control plane URL, failing with discovery errors that did not name
the cause. Project names cannot contain "/", so the value is now
refused up front with a hint that names the bare project.

Refusing is preferred over splitting the value: the project control
plane URL carries no organization, so a split would silently ignore
a wrong organization.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@0xmc
0xmc requested a review from a team as a code owner November 6, 2026 18:54
@0xmc
0xmc enabled auto-merge November 6, 2026 19:16

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

Approve.

The project-name check can only reject strings containing "/", which no valid project name has (names are Kubernetes object names), and it never rewrites or redirects scope: a rejected name stops before any request is sent. The new hint output is additive.

  • Validation runs only for --project and DATUM_PROJECT; a project taken from the active context is not checked, so the org/project strings that ctx list prints cannot be mistaken for context-sourced values. The hint's suggested --project web matches the segment the user typed.
  • main.go and root.go touch every command's fatal path only through FatalHint, which returns "" unless a get command at organization scope with -A recorded a hint. For JSON/YAML output, NewUserErrorWithHint(clean, "") renders the same envelope as the old plain error (empty code and hint, same message), so existing consumers see no change for other errors.
  • The get -A hint is attached to any (Forbidden) fatal, not only the cross-namespace refusal. A genuine RBAC denial at organization scope with -A would also be told the list is "not allowed at organization scope", whatever the caller's role.

Follow-ups:

  • Match the refusal's text (the tests already use "cross-namespace queries not allowed for organization-scoped requests") in FatalHint so an ordinary RBAC Forbidden gets no hint.
  • The title says it rejects org names as well, but only --project is validated; --organization acme/web still goes through unchecked.
  • getFatalHint is a package-level variable set by WrapGetCommand. That is fine for a one-shot CLI, but a test or embedder running two get commands in one process will see stale state.

@0xmc
0xmc merged commit 557cf67 into main Nov 6, 2026
2 checks passed
@0xmc
0xmc deleted the fix/org-scope-all-namespaces-hint branch November 6, 2026 20:01
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.

Organization-wide get -A is forbidden and the help text recommends it

2 participants