54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
export const DEPLOYMENT_ROLES = ['all', 'ops', 'server', 'learner'] as const;
|
|
|
|
export type DeploymentRole = (typeof DEPLOYMENT_ROLES)[number];
|
|
export type DeploymentCapability = 'manage_courses' | 'manage_settings';
|
|
|
|
export function resolveDeploymentRole(
|
|
rawRole: string | undefined,
|
|
nodeEnv: string | undefined,
|
|
): DeploymentRole {
|
|
const normalized = rawRole?.trim().toLowerCase();
|
|
if (DEPLOYMENT_ROLES.includes(normalized as DeploymentRole)) {
|
|
return normalized as DeploymentRole;
|
|
}
|
|
|
|
// Production is fail-closed: an unconfigured build is a learner surface,
|
|
// never an accidental operations console. Local development keeps the
|
|
// historical all-in-one experience.
|
|
return nodeEnv === 'production' ? 'learner' : 'all';
|
|
}
|
|
|
|
export function hasDeploymentCapability(
|
|
role: DeploymentRole,
|
|
capability: DeploymentCapability,
|
|
): boolean {
|
|
switch (capability) {
|
|
case 'manage_courses':
|
|
return role === 'ops' || role === 'all';
|
|
case 'manage_settings':
|
|
return role === 'ops' || role === 'all';
|
|
}
|
|
}
|
|
|
|
/** Non-secret client affordance only; every privileged API checks server-side too. */
|
|
export function isOpsWorkbenchEnabled(): boolean {
|
|
const role = resolveDeploymentRole(
|
|
process.env.NEXT_PUBLIC_OPENMAIC_DEPLOYMENT_ROLE,
|
|
process.env.NODE_ENV,
|
|
);
|
|
return hasDeploymentCapability(role, 'manage_courses');
|
|
}
|
|
|
|
/**
|
|
* Settings are an operator concern. Learner deployments consume the provider
|
|
* and model configuration already supplied by the server and do not expose
|
|
* controls that let a learner replace it.
|
|
*/
|
|
export function isSettingsManagementEnabled(): boolean {
|
|
const role = resolveDeploymentRole(
|
|
process.env.NEXT_PUBLIC_OPENMAIC_DEPLOYMENT_ROLE,
|
|
process.env.NODE_ENV,
|
|
);
|
|
return hasDeploymentCapability(role, 'manage_settings');
|
|
}
|