chadtmiller.com/knotless
git that lives in your Atmosphere account
An organization's admins set its repositories' secrets
MergedThis adds an optional owner to putSecret and deleteSecret. The new managed check accepts a named owner only when org_admits is true, and returns 403 otherwise. listSecrets now treats an admin who joined the organization like the owner. The CLI sends the repository's owner and falls back to the logged-in account when it is not logged in as the owner.
I found no bugs. org_admits already returns true for the owner itself, so the list branch behaves as before for owners. An owner equal to the caller skips the admin check. Values are still bound to the organization's DID, so runners open them unchanged. The changeset, API, CLI, MCP, security and runner docs, and the lexicons all moved with the code. The new tests cover an admin setting, listing and opening a secret, and a stranger being refused on put and delete.
I did not read CI results. The pull leaves them to CI, so check that they pass before it lands.
Round 2: the only new commits are a small test fix, "Bind the stranger's secret before putting it", and a merge of main. My earlier review found no bugs and asked for nothing, so there is nothing to re-check. I did not examine the test fix in detail.
CI is mostly still running. check (fmt and clippy) passed. test, e2e, lexicons, docs and web were queued or running when I looked. Let those finish green before it lands. The pull is already in the merge queue, which should hold it until they do.
9 passed, 1 skipped
- Org admins and runners on the owner's account can't use sealed secrets area/cliarea/servearea/lexicons
What changes
Admins manage an organization's secrets.
knotless secret <url> set,lsandrm, and the MCPsecrettool, work on a repository an organization owns when logged in as an admin who joined it. When the CLI is not logged in as the owner it acts from the account that is, and the appview decides.The methods name the owner.
dev.knotless.putSecretanddeleteSecrettake an optionalowner, absent meaning the caller as before. Naming another account is allowed only when the caller is an admin who joined it as an organization (org_admits, the gateway's own check), and is 403 otherwise.listSecretsanswers such an admin as it does the owner: every name, and values only of those sealed to the caller.Values are sealed as the organization's, as they were, so runners open them unchanged.
Why
Fixes Org admins and runners on the owner's account can't use sealed secrets. Its other half, a runner logged in as the owner opening its own secrets, landed in 4a698634. This half: an admin's service token is their own, so the appview stored their puts under the admin's DID, where no runner of the organization's repository looked, and an admin needed the organization's own login.
The check is the appview's, from the organization index it already keeps, as the issue proposed. Secrets live only at the appview, so no gateway write as the organization is needed.
How it was checked
organizations_invite_and_members_joinhas an admin set a secret on the organization's repository from their own login, list it, and the runner open it as bound to the organization, while the runner, not an admin, is refused removing it.secrets_reach_only_their_runnerhas a stranger naming the owner refused on put and delete. The rest is left to CI.Shortcomings
The settings page still shows the Secrets section, like the whole Settings tab, only to the owner: that is An org's admins can't change its repositories' settings. The methods already take an admin's pages login, so the page needs only the tab.
A runner being added or removed by
knotless runnersis still the owner's alone, so the secrets that follow it are too.