remove the dead multi-user surface
Officer is single-user: the server owner is the only account, created once by /auth/bootstrap. Everything that existed to serve additional users was unreachable, so it is gone rather than left looking like it does something. Accounts: drop the invite / resend-invite / delete / list-users routes and the Users settings screen, the inert /auth/signup handler, and the account verification chain it fed (verify, resend-verification, VerifyScreen, the UserInvite + VerifyAdmin + VerifyRegistration templates). /auth/verify-token survives for password resets only, and now requires a reset-password token rather than accepting any signed JWT. Roles: drop the users.role column and the four-value USER_ROLES enum. The permissions table granted every role identical methods, and every role === 'Super Admin' check was permanently true. The JWT no longer carries a role claim. Sandbox: remove sidecar/sandbox.ts and its five call sites. bwrap was selected only for non-Super-Admin users, so it never ran. It was also not a usable agent jail as written — --share-net, the project root (with .env) bound read-only, and runuser dropping to the server's own uid. Rebuilding it for agent containment would be a different construction, and git history keeps this one. getHomeDir keeps its DATA_PATH meaning; the new getOwnerHomeDir resolves the owner's real login home, which is what terminals, chats and task runs use. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
92de996412
commit
044aacf4d5
@@ -17,9 +17,6 @@ export const channelsRouter = createRouter();
|
||||
// ── Admin: Discord config ──
|
||||
|
||||
channelsRouter.get('/discord/config', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const integration = await getServerIntegration('discord');
|
||||
if (!integration) return ctx.json({ configured: false });
|
||||
|
||||
@@ -36,9 +33,6 @@ channelsRouter.get('/discord/config', async (ctx) => {
|
||||
});
|
||||
|
||||
channelsRouter.put('/discord/config', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const body = ctx.get('body') as Record<string, unknown>;
|
||||
const botToken = body.botToken as string | undefined;
|
||||
const enabled = body.enabled as boolean | undefined;
|
||||
@@ -131,9 +125,6 @@ channelsRouter.delete('/discord/connection', async (ctx) => {
|
||||
// ── Admin: Telegram config ──
|
||||
|
||||
channelsRouter.get('/telegram/config', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const integration = await getServerIntegration('telegram');
|
||||
if (!integration) return ctx.json({ configured: false });
|
||||
|
||||
@@ -150,9 +141,6 @@ channelsRouter.get('/telegram/config', async (ctx) => {
|
||||
});
|
||||
|
||||
channelsRouter.put('/telegram/config', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const body = ctx.get('body') as Record<string, unknown>;
|
||||
const botToken = body.botToken as string | undefined;
|
||||
const enabled = body.enabled as boolean | undefined;
|
||||
@@ -245,9 +233,6 @@ channelsRouter.delete('/telegram/connection', async (ctx) => {
|
||||
// ── Admin: WhatsApp config ──
|
||||
|
||||
channelsRouter.get('/whatsapp/config', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const integration = await getServerIntegration('whatsapp');
|
||||
|
||||
return ctx.json({
|
||||
@@ -259,9 +244,6 @@ channelsRouter.get('/whatsapp/config', async (ctx) => {
|
||||
});
|
||||
|
||||
channelsRouter.put('/whatsapp/config', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const body = ctx.get('body') as Record<string, unknown>;
|
||||
const enabled = body.enabled as boolean | undefined;
|
||||
|
||||
@@ -295,9 +277,6 @@ channelsRouter.get('/whatsapp/status', async (ctx) => {
|
||||
});
|
||||
|
||||
channelsRouter.get('/whatsapp/qr', async (ctx) => {
|
||||
const user = ctx.get('user');
|
||||
if (user.role !== 'Super Admin') return ctx.json({ error: 'Forbidden' }, 403);
|
||||
|
||||
const qr = getWhatsAppQR();
|
||||
return ctx.json({
|
||||
qr,
|
||||
|
||||
@@ -13,7 +13,6 @@ type SendAndAwaitParams = {
|
||||
context: string;
|
||||
contextId: string;
|
||||
model?: string;
|
||||
role?: string;
|
||||
};
|
||||
|
||||
type SendAndAwaitResult = {
|
||||
@@ -83,7 +82,6 @@ export async function sendAndAwait(params: SendAndAwaitParams): Promise<SendAndA
|
||||
prompt: params.prompt,
|
||||
sessionKey: sessionId,
|
||||
model,
|
||||
role: params.role,
|
||||
});
|
||||
} finally {
|
||||
releaseLock!();
|
||||
|
||||
@@ -9,7 +9,6 @@ type ClaudeCodeParams = {
|
||||
prompt: string;
|
||||
sessionKey: string;
|
||||
model?: string;
|
||||
role?: string;
|
||||
};
|
||||
|
||||
type ClaudeCodeResult = {
|
||||
@@ -38,7 +37,6 @@ type ClaudeCodeStreamingParams = {
|
||||
sessionKey: string;
|
||||
cwd?: string;
|
||||
model?: string;
|
||||
role?: string;
|
||||
resumeSessionId?: string;
|
||||
onEvent: (event: ChatEvent) => void;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user