Conversation
panghy
force-pushed
the
fix/invite-owner-self-join
branch
2 times, most recently
from
September 19, 2026 10:53
8fffa36 to
a85aabc
Compare
panghy
marked this pull request as ready for review
September 19, 2026 11:17
🤖 Augment PR SummarySummary: This PR prevents a host owner from joining their own host through a guest invite.
🤖 Was this summary useful? React with 👍 or 👎 |
panghy
force-pushed
the
fix/invite-owner-self-join
branch
from
September 19, 2026 14:35
a85aabc to
8445adf
Compare
panghy
force-pushed
the
fix/invite-owner-self-join
branch
2 times, most recently
from
September 19, 2026 19:01
819e109 to
994c8ba
Compare
panghy
added a commit
to intent-hq/cloudlands-fe
that referenced
this pull request
Sep 20, 2026
…te flow intentd refuses a join whose proven or presented identity is the host owner's own account with error.data.code owner-self-join (intent-hq/intentd#1986), so the guest never receives a credential for the primary principal. Add the code to the closed InviteErrorCode set and give it its own failure sentence in every locale: the owner is told to open the host from its paired daemons instead of the generic "refused the invite" text. On invite.accept the code propagates like workspace-full (no proof fallback).
panghy
added a commit
to intent-hq/cloudlands-fe
that referenced
this pull request
Sep 20, 2026
…te flow intentd refuses a join whose proven or presented identity is the host owner's own account with error.data.code owner-self-join (intent-hq/intentd#1986), so the guest never receives a credential for the primary principal. Add the code to the closed InviteErrorCode set and give it its own failure sentence in every locale: the owner is told to open the host from its paired daemons instead of the generic "refused the invite" text. On invite.accept the code propagates like workspace-full (no proof fallback).
panghy
added a commit
that referenced
this pull request
Sep 20, 2026
… member `v["result"].is_null()` also passes for an envelope that wrongly carries `"result": null`; the e2e now asserts the member is absent, which is what the JSON-RPC error shape requires. Addresses the Deep Code Review thread on #1986.
panghy
force-pushed
the
fix/invite-owner-self-join
branch
from
September 20, 2026 09:06
994c8ba to
4c7548c
Compare
panghy
added this pull request to stack #2028
September 20, 2026 12:50
panghy
added a commit
that referenced
this pull request
Sep 20, 2026
… member `v["result"].is_null()` also passes for an envelope that wrongly carries `"result": null`; the e2e now asserts the member is absent, which is what the JSON-RPC error shape requires. Addresses the Deep Code Review thread on #1986.
panghy
force-pushed
the
fix/invite-owner-self-join
branch
from
September 20, 2026 14:10
4c7548c to
9f90e54
Compare
github-merge-queue
Bot
removed this pull request from the merge queue because a pull request earlier in the stack was removed
Sep 20, 2026
A join whose proven GitHub account is the primary principal's own (same account on host and guest) is refused with the new `InviteErrorKind::OwnerSelfJoin` (`error.data.code` `owner-self-join`, -32602) at `invite.prove` and `invite.accept`, before any credential is minted. The store's join transaction guards the same invariant (`InviteJoinOutcome::OwnerSelfJoin`) so the `is_primary` row never receives a per-principal credential; the invite stays open. Motivation: a guest whose account matched the host owner's joined as the primary principal and its window listed every workspace on the host with owner actions.
Store, services and WSS e2e regressions: a prove/accept with the primary principal's github_user_id answers `owner-self-join`, creates no principal or principal_credential row, and leaves the invite open for the pinned guest.
… member `v["result"].is_null()` also passes for an envelope that wrongly carries `"result": null`; the e2e now asserts the member is absent, which is what the JSON-RPC error shape requires. Addresses the Deep Code Review thread on #1986.
panghy
force-pushed
the
fix/invite-owner-self-join
branch
from
September 20, 2026 15:29
9f90e54 to
f5e5b2d
Compare
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.
Root cause
A guest whose GitHub account is the same account as the host owner's joined
via invite → gist proof.
complete_invite_joinresolved the provengithub_user_idto the existing primary principal row (is_primary = 1) andminted a per-principal credential for it. The guest window's
/wsconnectionthen authenticated as the primary:
gated_collaborator_callernarrows onlynon-administrator Wire callers to their memberships, and the primary owns
every workspace it created — so
workspace.listreturned every workspace onthe host with
myRole: "owner"and the owner-only actions were offered.Fix
InviteErrorKind::OwnerSelfJoin— wireerror.data.codeowner-self-join(-32602), message "the host owner cannot join its own host as a guest".
invite.prove/invite.acceptrefuse as soon as the identity is known(at prove: right after the gist proof resolves the account; at accept: when
the presented credential's principal is the primary). No credential is minted,
the invite stays open.
join_workspace_by_inviteguards the same invariant inside thetransaction (
InviteJoinOutcome::OwnerSelfJoin), so theis_primaryrow cannever receive a
principal_credentialrow through a join.WorkspaceApi::invite_prove/invite_accepttrait docs and theprotocol.rscatalog module doc name the new kind.Tests (commit
86a51bf1)intent-storetests.rs:join_workspace_by_invitewith the primary'sidentity answers
OwnerSelfJoin, principal count unchanged, no credential row.intent-servicesinvite_ops/tests.rs: prove and accept with the owner'sgithub_user_idanswerowner-self-join; noprincipal_credentialrow.intentde2e_wss_invite_join.rs(real WSS): the owner's own gist proof ona pinned invite is
-32602/owner-self-joinwith noresult; the inviteremains open and the pinned guest joins it afterwards.
capability::tests::visibility_by_rolealready asserts acollaborator Wire caller sees only its member workspaces on
workspace.list.Gates
cargo fmt --check,cargo clippy --workspace --all-targets -D warnings,scoped nextest (117 passed: store/services/transport invite + capability),
e2e_wss_invite_join(8 passed), source lints (92 passed).Protocol docs
docs/protocol/in the monorepo does not enumerateInviteErrorKindcodes as atable; the catalog module doc in
protocol.rsis updated here. If the monorepodocs/protocol/methodsinvite section should listowner-self-join, that is afollow-up monorepo docs PR.