Repository navigation
Conversation
org invite ORG INVITEE sends {githubLogin} for a GitHub login (a leading
@ dropped) and {accountId} for a value that starts with cus_ or cannot be
a login, so account-id invites keep working; --login and --account force
a reading. The plan's summary names the reading (githubLogin, accountId)
and the receipt carries github_login. 404 account_not_found asks the
invitee to run `prose cli org list` once; 409 ambiguous_login says to
invite by account id. Both codes and invalid_login are allowlisted.
org invitation list lists the caller's pending invitations, or with ORG
that organization's (admins). org invitation accept INVITATION_ID
accepts by id with a bodyless POST; --token-file still accepts with the
token, and the two are mutually exclusive. A manifest argument `format`
(uuid) keeps the secret rule: on a secret-reading operation a positional
that does not fit never fills the argument and is never echoed.
Members carry github_login (human `member N (@login)`). The service
interaction catalog is re-vendored with the three new organization
routes. Shared cases, both ports, help, guide, SPEC, docs and CHANGELOG.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
This pull request description was written by an AI agent (Claude Code) working on Raymond Weitekamp's behalf. Raymond has not yet reviewed it.
Organization invitations by GitHub login, an invitation inbox and accept by id
This change maps the hosted service's new organization invitation routes. After it, the CLI covers every route the service's organization interaction exports. The new routes are:
GET /organizations/invitationsGET /organizations/{name}/invitationsPOST /organizations/invitations/{id}/acceptCommands
prose cli org invite ORG INVITEEinvites a GitHub login or an account id.@is a login, and the@is dropped.cus_, or that cannot be a GitHub login, is sent as{accountId}. Existing account-id invites therefore keep working.{githubLogin}.--login LOGINand--account ACCOUNT_IDforce a reading. Exactly one of the three must be given.summarynames the reading (githubLoginoraccountId). The human preview prints it on theSummary:line, which replaces the oldAccount:line.github_login. The human receipt names@loginand both ways to accept.prose cli org invitation list [ORG]lists pending invitations. WithoutORGit shows your own. WithORGit shows that organization's, for admins only. The organization id and the issuer's account id are dropped. Human output prints one line per invitation, and your own list ends with theacceptcommand for the first one.--output jsonlprints one record per invitation.prose cli org invitation accept INVITATION_IDaccepts by id with a bodyless POST.--token-filestill accepts with the token.--token-file.org invitation list.org member listandorg member rolecarrygithub_login. The human list printsmember N (@login).Errors
404 account_not_foundbecomesSERVICE_RESOURCE_NOT_FOUNDwithresource {kind: account, id: LOGIN}. The Action reads: "Ask @LOGIN to sign in and runprose cli org listonce, then invite them again." This Action is deliberately the plain public command in every output mode, because the invitee runs it on their own machine.409 ambiguous_loginbecomesSERVICE_WRITE_CONFLICT. The reason explains the ambiguity, and the Action says to invite with--accountinstead.account_not_found,ambiguous_loginandinvalid_loginwere added toerrorClassification.bodyCodesand to the allowlistedserviceCodevalues.org invitation list.Keeping the token secret
Before this change, any positional argument to
org invitation acceptwas presumed to be the token: it was refused and never echoed.acceptnow takes a positionalINVITATION_ID, so the manifest gains an argumentformat(uuid).On an operation with a
secretFileOptionsoption, a positional that does not fit its argument's format never fills that argument. The existing secret rule then refuses it without echoing it. This also covers commands rebuilt by typo correction. For example,accept SOMETOKENstill suggests--token-file -, andaccept UUID SOMETOKENsuggests removing the extra argument.The contract test that required secret-reading operations to take no positionals now requires each of their positionals to declare a format.
Contract files
operations.v1.json:org.invitation.listoperation;org.inviteandorg.invitation.accept;githubLoginandaccountIdsummary fields;operations.schema.json: the argumentformatproperty. Summary body names may now be camelCase, as the service's invitation bodies are.runner-error.schema.json: the new service codes and the two new Actions.service-operation.schema.json: the new summary fields.service/organizations.schema.json:github_login, plusinvitationList,invitationForMeandpendingInvitation.help.v1.json, the agent guide and its generated cases,runner-help.txt, SPEC,docs/service/organizations.mdand the CHANGELOG are updated.The root AGENTS.md convention review does not apply. This change touches no packaging, installation, configuration, credential or state-location plumbing.
Tests
conformance/cases/service/organizations/, covering:@and the forced readings;account_not_foundandambiguous_login, in JSON and human output;formatcheck and the projection ofgithub_login.--token-file, the list projections and membergithub_login.End to end. The behaviour was also exercised end to end against a local fake of the service's organization routes, with fake accounts. No credentials or hosted deployment were used. The Bun developer build drove one flow:
Each exchange was then replayed into the Bun and Rust test-seam builds, and both produced identical output.
Checks
These are the author's local runs; CI is the authority. They ran on macOS arm64 with Rust 1.87.0, Python 3.10.21 and Bun 1.4.4. Bun 1.4.4 is newer than the pinned 1.3.5, which was not available on this machine.
Pass:
--strict--all)--all)Also passing: bun-typecheck, bun-build, rust-format, rust-clippy, rust-clippy-dev-endpoint, public-surface, public-surface-files, workflow-policy, local-runner-tests, architecture-tests, architecture-boundary, release-preflight-tests, release-notes, image-bundle, fake-harness, fake-hosted-service, adapter-oracle, windows-resolution-oracle, real-harness-contract and functional-alpha-live-contract.
Fail, environment only, unrelated to this change:
main. The other failures were process and adapter timing tests, a different set on each run, under a load average of about 24. These tests pass in isolation, apart from one more timing case. No adapter or process code is changed here. The organization unit tests pass, 8 of 8.mainfor comparison.Flaky under load, passed on rerun: rust-tests failed once with a single codex
STARTUP_TIMEOUT, then passed on an unchanged rerun.All of these need a rerun on a CI-equivalent machine before merge.
🤖 Generated with Claude Code