From 920d03e1854a3a0eaeaf62c285133f3da6083fc7 Mon Sep 17 00:00:00 2001
From: syn
Date: Thu, 6 Aug 2026 13:24:10 -0500
Subject: [PATCH 1/2] feat(admin): allow anaconda platform admins
---
.../components/PlatformAdminsContent.tsx | 7 ++--
apps/web/src/lib/admin/platform-admin.test.ts | 17 ++++++--
apps/web/src/lib/admin/platform-admin.ts | 16 +++++---
.../src/routers/admin-platform-admins.test.ts | 40 ++++++++++++++++++-
apps/web/src/routers/admin-router.ts | 18 ++++++---
5 files changed, 77 insertions(+), 21 deletions(-)
diff --git a/apps/web/src/app/admin/components/PlatformAdminsContent.tsx b/apps/web/src/app/admin/components/PlatformAdminsContent.tsx
index fd3d502b21..af68859862 100644
--- a/apps/web/src/app/admin/components/PlatformAdminsContent.tsx
+++ b/apps/web/src/app/admin/components/PlatformAdminsContent.tsx
@@ -330,7 +330,7 @@ export function PlatformAdminsContent() {
: rosterError || permissions.isError
? 'Could not determine your permissions. Reload to try again.'
: canManageAdmins
- ? 'Search registered kilocode.ai users who are not already admins. New admins receive no subordinate permissions.'
+ ? 'Search registered kilocode.ai or anaconda.com users who are not already admins. New admins receive no subordinate permissions.'
: 'Superadmin access is required to grant platform admin access or manage permissions.'}
@@ -350,7 +350,8 @@ export function PlatformAdminsContent() {
id="platform-admin-candidate-search-hint"
className="text-muted-foreground text-xs"
>
- Only registered kilocode.ai users who are not already admins can be granted access.
+ Only registered kilocode.ai or anaconda.com users who are not already admins can be
+ granted access.
@@ -366,7 +367,7 @@ export function PlatformAdminsContent() {
) : candidateRows.length === 0 && !isSearching ? (
- No eligible kilocode.ai users matched that search.
+ No eligible kilocode.ai or anaconda.com users matched that search.
) : (
diff --git a/apps/web/src/lib/admin/platform-admin.test.ts b/apps/web/src/lib/admin/platform-admin.test.ts
index 0983d23f25..8f94a90752 100644
--- a/apps/web/src/lib/admin/platform-admin.test.ts
+++ b/apps/web/src/lib/admin/platform-admin.test.ts
@@ -1,9 +1,12 @@
import { isEligibleForPlatformAdmin, shouldAutoProvisionPlatformAdmin } from './platform-admin';
describe('isEligibleForPlatformAdmin', () => {
- it('is eligible for an exact lowercase kilocode.ai email and hosted domain', () => {
- expect(isEligibleForPlatformAdmin('person@kilocode.ai', 'kilocode.ai')).toBe(true);
- });
+ test.each(['kilocode.ai', 'anaconda.com'])(
+ 'is eligible for an exact lowercase %s email and hosted domain',
+ domain => {
+ expect(isEligibleForPlatformAdmin(`person@${domain}`, domain)).toBe(true);
+ }
+ );
it('is not eligible when the hosted domain is a personal/provider placeholder', () => {
expect(isEligibleForPlatformAdmin('person@kilocode.ai', '@@personal@@')).toBe(false);
@@ -13,10 +16,14 @@ describe('isEligibleForPlatformAdmin', () => {
expect(isEligibleForPlatformAdmin('person@kilocode.ai', null)).toBe(false);
});
- it('is not eligible when the hosted domain matches but the email is not a kilocode.ai email', () => {
+ it('is not eligible when the hosted domain matches but the email is not from an allowed domain', () => {
expect(isEligibleForPlatformAdmin('person@example.com', 'kilocode.ai')).toBe(false);
});
+ it('is not eligible when the email and hosted domain belong to different allowed domains', () => {
+ expect(isEligibleForPlatformAdmin('person@anaconda.com', 'kilocode.ai')).toBe(false);
+ });
+
it('is not eligible for uppercase email variants', () => {
expect(isEligibleForPlatformAdmin('Person@Kilocode.ai', 'kilocode.ai')).toBe(false);
});
@@ -27,10 +34,12 @@ describe('isEligibleForPlatformAdmin', () => {
it('is not eligible for a subdomain lookalike', () => {
expect(isEligibleForPlatformAdmin('person@sub.kilocode.ai', 'kilocode.ai')).toBe(false);
+ expect(isEligibleForPlatformAdmin('person@sub.anaconda.com', 'anaconda.com')).toBe(false);
});
it('is not eligible for a registrable-parent-domain lookalike', () => {
expect(isEligibleForPlatformAdmin('person@notkilocode.ai', 'kilocode.ai')).toBe(false);
+ expect(isEligibleForPlatformAdmin('person@notanaconda.com', 'anaconda.com')).toBe(false);
});
it('is not eligible for a fake-login hosted domain even with a kilocode.ai email', () => {
diff --git a/apps/web/src/lib/admin/platform-admin.ts b/apps/web/src/lib/admin/platform-admin.ts
index 66d76a83bb..4ab710a3f7 100644
--- a/apps/web/src/lib/admin/platform-admin.ts
+++ b/apps/web/src/lib/admin/platform-admin.ts
@@ -2,12 +2,17 @@ import 'server-only';
import { hosted_domain_specials } from '@/lib/auth/constants';
+export const platformAdminDomains = [
+ hosted_domain_specials.kilocode_admin,
+ 'anaconda.com',
+] as const;
+
/**
- * Exact eligibility rule for the Kilo production platform-admin domain.
+ * Exact eligibility rule for Kilo production platform-admin domains.
*
* This intentionally preserves current case-sensitive behavior: the hosted
- * domain must equal `kilocode.ai` exactly and the email must end with
- * `@kilocode.ai` exactly. It does not broaden matching to uppercase
+ * domain must equal an allowed corporate domain exactly and the email must
+ * end with that same domain exactly. It does not broaden matching to uppercase
* variants, subdomains, or registrable parent domains.
*
* Used both to gate the production auto-provisioning rule (historically)
@@ -17,9 +22,8 @@ import { hosted_domain_specials } from '@/lib/auth/constants';
* against freshly loaded rows.
*/
export function isEligibleForPlatformAdmin(email: string, hostedDomain: string | null): boolean {
- return (
- hostedDomain === hosted_domain_specials.kilocode_admin &&
- email.endsWith('@' + hosted_domain_specials.kilocode_admin)
+ return platformAdminDomains.some(
+ domain => hostedDomain === domain && email.endsWith(`@${domain}`)
);
}
diff --git a/apps/web/src/routers/admin-platform-admins.test.ts b/apps/web/src/routers/admin-platform-admins.test.ts
index 598348f819..bfeb08e05c 100644
--- a/apps/web/src/routers/admin-platform-admins.test.ts
+++ b/apps/web/src/routers/admin-platform-admins.test.ts
@@ -7,6 +7,7 @@ import { createCallerForUser } from '@/routers/test-utils';
import { hosted_domain_specials } from '@/lib/auth/constants';
const KILO_DOMAIN = hosted_domain_specials.kilocode_admin;
+const ANACONDA_DOMAIN = 'anaconda.com';
async function insertQualifyingAdmin(overrides: Parameters[0] = {}) {
return insertTestUser({
@@ -37,6 +38,17 @@ async function insertEligibleCandidate(overrides: Parameters[0] = {}
+) {
+ return insertTestUser({
+ google_user_email: `candidate-${crypto.randomUUID()}@anaconda.com`,
+ hosted_domain: ANACONDA_DOMAIN,
+ is_admin: false,
+ ...overrides,
+ });
+}
+
async function getUserAdminNotes(userId: string) {
return db.query.user_admin_notes.findMany({
where: eq(user_admin_notes.kilo_user_id, userId),
@@ -111,13 +123,16 @@ describe('admin.users.searchPlatformAdminCandidates', () => {
).rejects.toMatchObject({ code: 'FORBIDDEN' });
});
- test('returns only non-admin users satisfying both exact Kilo eligibility rules', async () => {
+ test('returns only non-admin users satisfying an exact allowed-domain email and hosted-domain pair', async () => {
const searchToken = crypto.randomUUID();
const admin = await insertQualifyingAdmin();
const eligible = await insertEligibleCandidate({
google_user_email: `${searchToken}@kilocode.ai`,
});
+ const anacondaEligible = await insertAnacondaEligibleCandidate({
+ google_user_email: `${searchToken}@anaconda.com`,
+ });
const alreadyAdmin = await insertTestUser({
google_user_email: `${searchToken}-already-admin@kilocode.ai`,
hosted_domain: KILO_DOMAIN,
@@ -138,6 +153,11 @@ describe('admin.users.searchPlatformAdminCandidates', () => {
hosted_domain: KILO_DOMAIN,
is_admin: false,
});
+ const mismatchedAllowedDomainUser = await insertTestUser({
+ google_user_email: `${searchToken}-mismatch@anaconda.com`,
+ hosted_domain: KILO_DOMAIN,
+ is_admin: false,
+ });
const uppercaseEmailUser = await insertTestUser({
google_user_email: `${searchToken.toUpperCase()}@Kilocode.ai`,
hosted_domain: KILO_DOMAIN,
@@ -160,11 +180,13 @@ describe('admin.users.searchPlatformAdminCandidates', () => {
});
const resultIds = results.map(user => user.id);
- expect(resultIds).toEqual([eligible.id]);
+ expect(resultIds).toEqual(expect.arrayContaining([eligible.id, anacondaEligible.id]));
+ expect(resultIds).toHaveLength(2);
expect(resultIds).not.toContain(alreadyAdmin.id);
expect(resultIds).not.toContain(fakeLoginUser.id);
expect(resultIds).not.toContain(wrongDomainUser.id);
expect(resultIds).not.toContain(wrongEmailUser.id);
+ expect(resultIds).not.toContain(mismatchedAllowedDomainUser.id);
expect(resultIds).not.toContain(uppercaseEmailUser.id);
expect(resultIds).not.toContain(subdomainUser.id);
expect(resultIds).not.toContain(lookalikeDomainUser.id);
@@ -228,6 +250,20 @@ describe('admin.users.setPlatformAdminAccess — grant', () => {
expect(notes[0]?.admin_kilo_user_id).toBe(admin.id);
});
+ test('a superadmin can grant an eligible anaconda.com target', async () => {
+ const admin = await insertQualifyingAdmin();
+ const target = await insertAnacondaEligibleCandidate();
+ const caller = await createCallerForUser(admin.id);
+
+ const result = await caller.admin.users.setPlatformAdminAccess({
+ userId: target.id,
+ isAdmin: true,
+ });
+
+ expect(result).toMatchObject({ changed: true, user: { id: target.id, is_admin: true } });
+ expect((await getUser(target.id)).is_admin).toBe(true);
+ });
+
test('rejects granting an ineligible target even if submitted directly', async () => {
const admin = await insertQualifyingAdmin();
const ineligibleTarget = await insertTestUser({
diff --git a/apps/web/src/routers/admin-router.ts b/apps/web/src/routers/admin-router.ts
index caf4ec3109..3affb3506e 100644
--- a/apps/web/src/routers/admin-router.ts
+++ b/apps/web/src/routers/admin-router.ts
@@ -7,8 +7,7 @@ import {
} from '@/lib/trpc/init';
import { userCanViewSessions, userIsSuperadmin } from '@/lib/admin/admin-permissions';
import { userCanManageCredits } from '@/lib/admin/credit-management';
-import { isEligibleForPlatformAdmin } from '@/lib/admin/platform-admin';
-import { hosted_domain_specials } from '@/lib/auth/constants';
+import { isEligibleForPlatformAdmin, platformAdminDomains } from '@/lib/admin/platform-admin';
import { db, type DrizzleTransaction } from '@/lib/drizzle';
import { insertKiloClawSubscriptionChangeLog, type KiloClawSubscription } from '@kilocode/db';
import {
@@ -1586,8 +1585,9 @@ export const adminRouter = createTRPCRouter({
};
}),
- // Server-filtered so results only ever contain non-admin, exact-eligibility
- // kilocode.ai users. Filtering here is a UX convenience, not a security
+ // Server-filtered so results only ever contain non-admin users matching an
+ // exact platform-admin email and hosted-domain pair. Filtering here is a UX
+ // convenience, not a security
// boundary: setPlatformAdminAccess independently re-validates eligibility
// against freshly locked rows before granting.
searchPlatformAdminCandidates: superadminProcedure
@@ -1601,10 +1601,16 @@ export const adminRouter = createTRPCRouter({
.where(
and(
eq(kilocode_users.is_admin, false),
- eq(kilocode_users.hosted_domain, hosted_domain_specials.kilocode_admin),
// Case-sensitive suffix match — `like` (not `ilike`) so search
// eligibility cannot disagree with isEligibleForPlatformAdmin.
- like(kilocode_users.google_user_email, `%@${hosted_domain_specials.kilocode_admin}`),
+ or(
+ ...platformAdminDomains.map(domain =>
+ and(
+ eq(kilocode_users.hosted_domain, domain),
+ like(kilocode_users.google_user_email, `%@${domain}`)
+ )
+ )
+ ),
or(
ilike(kilocode_users.google_user_email, `%${escaped}%`),
ilike(kilocode_users.google_user_name, `%${escaped}%`),
From f8e32642c02c9d8ab241442650295cf01063df70 Mon Sep 17 00:00:00 2001
From: syn
Date: Thu, 6 Aug 2026 15:25:12 -0500
Subject: [PATCH 2/2] chore(ci): retrigger pull request checks