Skip to content

Drop the viewer step for sandbox.user teammates - #4265

Merged
matthewhelmke merged 1 commit into
mainfrom
sandbox-user-without-viewer
Oct 20, 2026
Merged

matthewhelmke merged 1 commit into
mainfrom
sandbox-user-without-viewer

Conversation

@matthewhelmke

Copy link
Copy Markdown
Collaborator

The docs told owners to give sandbox.user teammates the viewer role too, because sandbox.user alone couldn't let chainctl find the organization by name. The role now includes groups.list and apk.list (chainctl iam roles list -o json, 2026-10-20), so that step is no longer needed.

I tested it twice in chainguard.edu on 2026-10-20:

  • A temporary identity bound only to sandbox.user: chainctl checks list and chainctl develop list gave the same result with --parent chainguard.edu as with the organization's ID. Both exited 0.
  • A real teammate: an invite created with --role sandbox.user, limited to one email address, was accepted with chainctl auth login --invite-code. Accepting it created the account's only binding, sandbox.user. That account then ran the same commands by name, and they passed.

I deleted the identity, the binding, and the scratch configs afterward, and the invite was used up.

Changes:

  • Set up Chainguard Checks and Chainguard Workspaces: "Add a teammate" drops from four steps to two, an invite with --role sandbox.user and its acceptance, with no role-binding lookup. The roles table drops the viewer row, and gains an "Inside a session" column and an mcp.tool_user row, because the Chainguard MCP servers in a session need mcp.tool.call. The Starter steps point at the new step 1.
  • chainctl checks reference, Inspect and run checks, and Checks troubleshooting: remove "you also need a role that can see the organization, such as viewer."
  • chainctl develop reference and Workspaces getting started: list sandbox.user alone, and point the grant sentence at the invite.
  • Capabilities reference: add sandbox.user (list) to the apk and groups rows.

🤖 Generated with Claude Code

The sandbox.user role now includes groups.list, so chainctl finds the
organization by name without viewer. A live test on 2026-10-20 showed
it twice: as a static identity bound only to sandbox.user, and as a
real teammate who accepted a sandbox.user invite. Both ran chainctl
checks list and chainctl develop list with --parent set to the
organization's name, and both exited 0, the same as with its ID.

- Set up page: "Add a teammate" is now two steps, an invite with
  --role sandbox.user and its acceptance, because accepting the
  invite grants the role. The roles table drops the viewer row and
  gains a column for what each role allows inside a session, plus
  mcp.tool_user, which the Chainguard MCP servers need there. The
  Starter steps point at the new step 1.
- The checks reference, "Inspect and run checks," Checks
  troubleshooting, the develop reference, and Workspaces getting
  started no longer say sandbox.user needs viewer.
- Capabilities reference: sandbox.user can list apk and groups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@matthewhelmke
matthewhelmke requested a review from a team as a code owner October 20, 2026 15:36
@vercel

vercel Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
chainguard-docs-preview Ready Ready Preview Oct 20, 2026 3:37pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
chainguard-docs Ignored Ignored Oct 20, 2026 3:37pm UTC

Request Review

@matthewhelmke
matthewhelmke merged commit 6c95a2c into main Oct 20, 2026
13 checks passed
@matthewhelmke
matthewhelmke deleted the sandbox-user-without-viewer branch October 20, 2026 15:52
tylerpaxton added a commit that referenced this pull request Oct 21, 2026
This PR addresses the review comments on #4171 and #4172 that arrived
after they merged, except the ones that main already covers. It builds
on #4269 and should merge after it. Until #4269 merges, this PR's diff
also includes #4269's commit, so review only the last commit on the
branch.

Some comments got different wording from what they suggested, because
the code changed after the review or works differently than described.
Those cases are listed under **Not changed**.

## Changes

### Chainguard Checks

- `chainctl-checks-reference.md`:
- New `chainctl checks failures` and `chainctl checks attempts` sections
and table rows, and a pointer from `logs --attempt` to `attempts`.
- A rewritten `chainctl checks cancel` section: `--force` for runs that
GitHub started, who can cancel a run, how to cancel a pull request's
run, and what GitHub shows afterward. It replaces the line that said you
can't cancel pull request runs.
- `migrate` takes an optional `--dry`, and the section says what running
without it does: up to six test runs, which need a role and use the
Checks allowance.
- `accept-terms` says `owner` or `limited_owner`, the `limited_owner`
paragraph also covers `migrate` without `--dry`, and the `--workflow`
rows fit both layouts.
  - An `{#id}` on every heading.
- `configuration.md`:
- The single-file layout can hold more check files beside `ci.yaml`, and
the file table has a row for other `.yaml` files in `.chainguard/`.
- `requested_checks_agent` goes only in `ci.yaml` or
`ci/env/default.yaml`, and `deps.yaml` joins the `develop.yaml` row.
- Packages come from the Wolfi and Extra Packages repositories and your
organization's Private APK Repository.
- New sections: "How commands run," "Variables that Chainguard Checks
sets," and "Git in a check's VM."
- Network access describes HTTPS interception and the cases where the
host's own certificate is kept.
- Triggers states the rule for `needs` and `from` across triggers, with
an example and a `{#triggers}` anchor.
- Advisory checks and Run on request point to the rule that a pull
request can't weaken its own checks.
- Resources says a check's VM has no KVM device, and Timeouts says two
hours.
- `github.md`:
- Closing or merging a pull request doesn't cancel its run, and
`chainctl checks cancel --force` stops it.
- Only checks that don't pass or that report something get their own
GitHub check, and `<file>` is the defining file's name in either layout.
- A pull request keeps the base branch's setting for a check until it
merges, and a stricter change applies on the same pull request.
- A rerun from `chainctl` shows **Re-run requested by *IDENTITY_ID* via
chainctl**.
- `identity-and-trust.md`:
- A check that uses an identity keeps its base branch's `when.expr`
conditions until the pull request merges. This is a new row in "Which
runs get an identity," and the paragraph on what a condition protects is
rewritten.
- Ring `2` for an identity that the default branch doesn't define
applies only when the default branch has a `trust` section.
- A running check loses an identity within about 10 minutes after an
`identities.yaml` change and about 18 minutes after a `trust` change. A
new paragraph says what happens to the check.
- `variations-services-caches.md`: a new "Run Docker" section, a `with`
example that also sets `PGPORT` for the check, the trigger rule for
`from`, and a `root` check that can use the Go build cache.
- `troubleshooting.md`: a new "A check fails with a certificate error"
section, a trigger row that quotes `does not support trigger`, `owner`
or `limited_owner` in the terms row, a cache row that allows `root` with
`gobuild`, and "A check stops after two hours" in place of the 50-minute
section.
- `overview.md`: HTTPS interception, which checks get their own GitHub
check, and the two-hour limit.
- `getting-started.md`: which checks get their own GitHub check, and why
to require only the summary check.
- `migrate-from-github-actions.md`: a Background processes row, the
two-hour limit, a Go cache row for `root` checks, and a link from the
services row to "Run Docker."
- `run-checks.md`: for `the guest is held by another controller`, attach
and run `run-ci`, or run the command again after the session parks. A
session runs on arm64 only if its resource class pins arm64.

### Chainguard Workspaces

- `coding-agents.md`:
- An unattended agent can also push to the checkout's other github.com
remotes where the Chainguard App is installed, with separate advice for
narrowing internet access and push access.
- A new "The session's guide for agents" section, which replaces "brief"
across the page.
- A new "Share skills and instructions from your laptop" section, and a
fix to the paragraph that said `chainctl` doesn't copy them.
- `github-as-you.md`: a workflow that the session pushes gets a
`GITHUB_TOKEN` that can do what the session can't do directly. "Protect
your branches" adds a push ruleset on `.github/workflows/**/*` and
turning off GitHub Actions approvals.
- `manage-sessions.md`:
  - A new "Copy text from a session" section.
- What happens when your laptop sleeps or goes offline, and that a
`--keep` hold starts when you attach.
- Returning to a session that's still parking, and what a park drops and
keeps.
  - The 6-day renewal and what it does to credentials.
- **Share from laptop** and **Status** rows in the session menu table,
and a link to the new session states table.
- `overview.md`: what the `.git` sync sends, how it treats symbolic
links and special files, where packages come from, and a pointer to
clipboard copy.
- `session-environment.md`:
- The environment change reminder applies only to sessions opened from a
local directory.
- `develop.yaml` can name a `gobuild` cache but not `services`, and
`from` names only a check file or an environment file.
  - The warm cache example drops `--check`.
- The order a `--check` session takes its size from, and arm64 only from
a resource class that pins it.
  - Packages come from Chainguard's package repositories.
- `chainctl-develop-reference.md`: a new "Session states" table that
maps each JSON `state` value to the `STATE` column.
- `troubleshooting.md`: a new "Returning to a session takes several
minutes" section, and the `missing: terms.accept` bullet no longer says
"only."

### Get started

- `set-up.md`: accepting terms and `--parent` take `owner` or
`limited_owner`. `init` picks your only Starter or Team organization
whatever your role, then stops with `missing: terms.accept`. A new
prerequisite covers people who already belong to an organization.
- `how-it-works.md`: the 6-day renewal waits while you're attached,
which checks get their own GitHub check, HTTPS interception, and the
glossary entry for a check.

## For the reviewer

- **Changes beyond the comments.** Three things changed in production
after #4172 merged, and the new text would have contradicted the old, so
this PR updates them on every page:
- A run can take up to two hours, not 50 minutes. The troubleshooting
anchor is now `#a-check-stops-after-two-hours`, its one inbound link is
updated, and the error row quotes the current message, `workflow run
exceeded its execution deadline`.
- A check that passes without reporting anything gets no GitHub check of
its own.
- A check that runs as `root` can use the Go build cache without `user:
build`.
- **Share from laptop.** The new section in `coding-agents.md` goes
beyond its comment. The old text said a session never takes your
laptop's skills or `CLAUDE.md`, which is no longer true. Drop the
section if you'd rather document the feature separately.
- **Anchors.** On existing headings, each added `{#id}` matches the slug
Hugo already generates, so no inbound link changes except the renamed
two-hour heading.
- **Examples not run as written.** The Docker service files are adapted
from a working configuration, and the `keytool` command from the VM's
certificate setup, but neither has been run as written in a customer's
check. That `git commit` fails without a Git identity follows from Git's
behavior, and wasn't tried in a check's VM.

## Not changed

- The `viewer` role for `sandbox.user` teammates (#4171, #4172): #4265
already removed it.
- The `chainctl checks failures` paragraph in
`inspect-and-run-checks.md` (#4172): #4203 already added it, so this PR
adds only the reference sections.
- `chainctl develop claude login` (#4171): #4269 documents it.
- The `coding-agents.md` copy of the `held by another controller` advice
(#4171, #4172): #4259 removed it, so the fix is only in `run-checks.md`.
- The attach guide wording (#4171): `chainctl` remembers the first
attach per laptop, not per session, so the page is right.
- Exited terminals and the `R` key (#4171): a terminal closes when its
command exits, as the page says, so `R` has nothing to restart.
- Laptop sleep timings (#4171): the page leaves out the suggested
90-second and 11-to-12-minute figures, because noticing a sleeping
laptop can take several minutes, and a busy session now keeps running
instead of parking.
- Setting a session's architecture in its environment (#4171):
`environment.arch` is still refused, so arm64 comes only from the
resource class.
- Not counting `github-actions[bot]` reviews (#4171): GitHub has no such
setting, and turning off GitHub Actions approvals already stops them.
- The `migrate` flags `--ref`, `--max-proves`, and `--parity` (#4172):
they apply only without `--dry`, which the page advises against during
the beta.
- `failures` as the next step after `run-ci` (#4172): `run-ci` creates
no run for `failures` to read.
- `SHELL` in the variables table (#4172): checks don't get it, because
it's set only for an interactive terminal.
- "Reserved" `CHAINGUARD_` and `CG_` prefixes (#4172): nothing enforces
a reservation, so the page advises against the prefixes instead.
- A GitHub token in the `when.expr` rule (#4172): checks get no GitHub
token during the beta.
- `guardener.admin` in role lists: it also holds `terms.accept`, but
role lists name only `owner` and `limited_owner`.

## Found but not fixed here

- The `chainctl checks list` section says it lists only runs started
with `chainctl checks run`, and several pages say you can't rerun runs
after merging. `chainctl` 0.2.388 lists every run, and Chainguard Checks
reruns the newest finished postsubmit run. The fix touches `github.md`,
`troubleshooting.md`, and `inspect-and-run-checks.md`, and needs a check
of whether **Re-run** on GitHub works for a postsubmit run.
- `set-up.md` says a personal email address can't create a Chainguard
organization. Production has allowed it since October 10.
- `variations-services-caches.md` says only `gobuild` stores data and
that `gobuild: {}` takes no settings. The `gomod` cache and the `key`
and `size` settings are deployed.
- Several pages say a pull request's checks run on the commit GitHub
would create by merging. Chainguard Checks now creates that merge commit
itself.
- `identity-and-trust.md` doesn't cover AWS workload identities, which
are deployed.
- Resource classes in `.chainguard/ci/resources/<name>.yaml` files are
deployed but not documented.

## How this was checked

- Each fix was checked in chainguard-dev/mono: at the `v0.2.388` tag for
`chainctl` commands, flags, and output, and at the commit deployed to
production on October 20 for server behavior, limits, and production
settings. On the released `chainctl` 0.2.388, only `--help` was run.
- Each comment was compared with current main first, so this PR doesn't
repeat fixes from #4203, #4217, #4259, #4263, or #4265.
- The GitHub settings in `github-as-you.md` were checked against
GitHub's documentation.
- A review pass checked each changed page for accuracy and style, and
each accuracy finding was checked in code before it was applied.
- `pre-commit` and `markdownlint-cli2` 0.23.3 pass, and all 537 internal
links and anchors on the Checks, Workspaces, and get-started pages
resolve.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview – chainguard-docs-preview — 5fe165a7 Deployed Oct 20, 2026 by vercel[bot]
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.

2 participants