feat: add deployable alpha silo

This commit is contained in:
2026-07-11 00:25:45 +08:00
parent 44557da499
commit 9e954790dc
57 changed files with 2792 additions and 400 deletions
+41 -1
View File
@@ -16,6 +16,8 @@ export const ORG_ADMIN_ROLES: readonly OrganizationMemberRole[] = ["OWNER", "ADM
export interface AuthContext {
readonly session: SessionPayload;
readonly user: User;
readonly feishuOpenId: string;
readonly authenticationOrganizationId?: string | undefined;
}
export interface OrgAuthContext extends AuthContext {
@@ -55,12 +57,45 @@ export async function requireSession(
await sendError(reply, 401, "unauthenticated", "session invalid or expired");
return null;
}
if ("feishuIdentityId" in session) {
const identity = await deps.prisma.feishuUserIdentity.findUnique({
where: { id: session.feishuIdentityId },
include: {
user: true,
connection: {
select: {
id: true,
status: true,
activeSecretVersion: { select: { connectionId: true, retiredAt: true } },
organization: { select: { id: true, status: true } },
},
},
},
});
if (identity === null || identity.userId !== session.userId ||
identity.connectionId !== session.feishuConnectionId ||
identity.connection.organization.id !== session.feishuOrganizationId ||
identity.connection.status !== "ACTIVE" ||
identity.connection.activeSecretVersion === null ||
identity.connection.activeSecretVersion.connectionId !== identity.connection.id ||
identity.connection.activeSecretVersion.retiredAt !== null ||
identity.connection.organization.status !== "ACTIVE") {
await sendError(reply, 401, "unauthenticated", "session identity not found or inactive");
return null;
}
return {
session,
user: identity.user,
feishuOpenId: identity.openId,
authenticationOrganizationId: identity.connection.organization.id,
};
}
const user = await deps.prisma.user.findUnique({ where: { id: session.userId } });
if (user === null || user.feishuOpenId !== session.feishuOpenId) {
await sendError(reply, 401, "unauthenticated", "session user not found");
return null;
}
return { session, user };
return { session, user, feishuOpenId: user.feishuOpenId };
}
export async function requireOrgRole(
@@ -87,6 +122,11 @@ export async function requireOrgRole(
await sendError(reply, 403, "org_not_active", `organization is ${organization.status}`);
return null;
}
if (auth.authenticationOrganizationId !== undefined &&
auth.authenticationOrganizationId !== organization.id) {
await sendError(reply, 403, "forbidden", "session is scoped to a different organization");
return null;
}
const membership = await deps.prisma.organizationMembership.findFirst({
where: {