Skip to content

feat(organizations): limit sub-org adds to parent members - #8967

Merged
emilieschario merged 5 commits into
mainfrom
emilie/suborg-parent-member-invites
Oct 28, 2026
Merged

emilieschario merged 5 commits into
mainfrom
emilie/suborg-parent-member-invites

Conversation

@emilieschario

Copy link
Copy Markdown
Contributor

Summary

  • A sub-organization can invite or add only people who are already members of its parent organization.
  • Add Member search on a sub-org is limited to active parent members, and the add and invite mutations reject anyone else.
  • Accepting a sub-org invitation still requires a current parent membership.

Test plan

  • Parent-member invite, alias match, pending-invite rejection, and accept-after-leaving-parent unit tests
  • Child-org invite router tests
  • Admin addMember rejection and success tests
  • Parent-member search unit tests
  • Mobile error-copy tests

A sub-organization can invite or add only people who already belong to its parent. The add-member search is limited to active parent members, and accept still requires that membership.
@emilieschario emilieschario self-assigned this Oct 27, 2026
The new catalog key failed i18n parity. Unknown invite rejections already use the generic send error.
Comment thread packages/web-shared/src/lib/organizations/organizations.ts
Comment thread apps/web/src/app/admin/components/OrganizationAdmin/AddMemberDialog.tsx Outdated
@kilo-code-bot

kilo-code-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The increment correctly restores transient-failure resilience on the post-deploy lease check: the in-flight renewal is still awaited first, then renew() starts a new fresh read that retries transientRenewalFailures, and the new fixture plus test exercise that retry path. No new issues in the changed lines.

Assumptions: [INFERENCE] Tests were not executed in this read-only review; conclusions come from reading services/auto-routing-benchmark/scripts/deploy.mjs (renewal memoization and finally reset), the fixture, and the new test.

Files Reviewed (3 files)
  • services/auto-routing-benchmark/scripts/deploy.mjs
  • services/auto-routing-benchmark/scripts/deploy.test.mjs
  • services/auto-routing-benchmark/test/fixtures/deploy-wrangler.mjs
Previous Review Summaries (3 snapshots, latest commit 8b8a333)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 8b8a333)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The follow-up commit correctly forces a fresh post-deploy lease read, but the new renewOnce() call bypasses the renewal retry path, so a single transient wrangler/D1 error after a successful deploy now fails the run as unverified.

Assumptions: [INFERENCE] Tests were not executed in this read-only review. The org-gating files from the previous review are unchanged since commit 897a706e8 and were not re-analyzed; the only increment is services/auto-routing-benchmark/scripts/deploy.mjs.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
services/auto-routing-benchmark/scripts/deploy.mjs 306 Post-deploy renewOnce() no longer retries transientRenewalFailures, unlike the previous renew() call
Files Reviewed (1 file)
  • services/auto-routing-benchmark/scripts/deploy.mjs - 1 issue

Previous review (commit 897a706)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The follow-up commit closes both prior findings: a live-parent check now gates the child-org accept and admin add paths, and Add Member uses a bounded server-side parent-member search that excludes existing child members. No new defects were found in the changed code.

Assumptions: [INFERENCE] Tests were not executed in this read-only review; the new SQL was validated by reading it against the schema (unique (organization_id, kilo_user_id) on organization_memberships, non-null is_bot default false, organizations.deleted_at soft delete) rather than by running the suites.

Files Reviewed (8 files)
  • apps/web/src/app/admin/api/organizations/hooks.ts
  • apps/web/src/app/admin/components/OrganizationAdmin/AddMemberDialog.tsx
  • apps/web/src/app/admin/components/OrganizationAdmin/parent-member-search.ts (removed)
  • apps/web/src/app/admin/components/OrganizationAdmin/AddMemberDialog.test.ts (removed)
  • apps/web/src/routers/organizations/organization-admin-router.ts
  • apps/web/src/routers/organizations/organization-admin-router.test.ts
  • packages/web-shared/src/lib/organizations/organizations.ts
  • packages/web-shared/src/lib/organizations/organizations.test.ts

Previous review (commit a5b32bb)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1

Executive Summary

The parent-membership gating is enforced on invite and admin add, but the accept path never re-checks that the parent organization is still live, so an invitation issued before the parent was deleted can still grant child membership.

Assumptions: [INFERENCE] Parent organizations can be deleted while their child organizations remain (confirmed: markOrganizationAsDeleted soft-deletes only the org row and keeps memberships/children); the child-org SSO/seat flows were not exercised.

Issue Details (click to expand)

WARNING

File Line Issue
packages/web-shared/src/lib/organizations/organizations.ts 759 Accept path verifies parent membership but not that the parent org is live, unlike the invite path
apps/web/src/routers/organizations/organization-admin-router.ts 1028 admin.addMember has the same missing live-parent check (noted in the comment above)

SUGGESTION

File Line Issue
apps/web/src/app/admin/components/OrganizationAdmin/AddMemberDialog.tsx 60 Parent search fetches the entire parent org via withMembers and filters client-side
Files Reviewed (11 files)
  • apps/web/src/app/admin/components/OrganizationAdmin/AddMemberDialog.test.ts
  • apps/web/src/app/admin/components/OrganizationAdmin/AddMemberDialog.tsx - 1 issue
  • apps/web/src/app/admin/components/OrganizationAdmin/parent-member-search.ts
  • apps/web/src/components/organizations/OrganizationMembersCard.tsx
  • apps/web/src/components/organizations/members/InviteMemberDialog.tsx
  • apps/web/src/routers/organizations/organization-admin-router.test.ts
  • apps/web/src/routers/organizations/organization-admin-router.ts - same defect noted in the accept-path comment
  • apps/web/src/routers/organizations/organization-members-router.test.ts
  • apps/web/src/routers/organizations/organization-members-router.ts
  • packages/web-shared/src/lib/organizations/organizations.test.ts
  • packages/web-shared/src/lib/organizations/organizations.ts - 1 issue

Fix these issues in Kilo Cloud


Reviewed by deepseek-flash-latest · Input: 35.9K · Output: 5.6K · Cached: 257.2K

Review guidance: REVIEW.md from base branch main

Accept and admin add now reject membership when the parent organization is deleted. Add Member searches a bounded set of live parent members instead of loading the whole parent organization.
An in-flight renewal started during deploy was reused as the post-deploy check, so CI could miss the final pause verification.
Comment thread services/auto-routing-benchmark/scripts/deploy.mjs Outdated
The fresh post-deploy read goes through the renewal retry loop after the in-flight renewal finishes, so a single D1 blip does not fail a completed deploy.

@iscekic iscekic left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bot: Reviewed the membership checks, invitation acceptance, parent-member search, and deployment renewal fix. No actionable findings. The focused deployment regression checks pass, and CI is green.

@emilieschario
emilieschario added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 689e9c8 Oct 28, 2026
85 checks passed
@emilieschario
emilieschario deleted the emilie/suborg-parent-member-invites branch October 28, 2026 12:34
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