feat: harden enterprise control plane
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,30 @@ export interface BossAdminMenuItem {
|
||||
|
||||
export interface BossAdminBackofficePayload {
|
||||
ok: boolean;
|
||||
surface: "platform" | "enterprise";
|
||||
currentCompany: Record<string, unknown> | null;
|
||||
menuTree: BossAdminMenuItem[];
|
||||
insights: {
|
||||
onboardingSteps: string[];
|
||||
serviceStatuses: Array<Record<string, unknown>>;
|
||||
openingPreview: Array<Record<string, unknown>>;
|
||||
deliveryChecklist: Array<Record<string, unknown>>;
|
||||
recentCompanies: Array<Record<string, unknown>>;
|
||||
customerHealthRows: Array<Record<string, unknown>>;
|
||||
riskAggregates: Array<Record<string, unknown>>;
|
||||
customerFollowups: Array<Record<string, unknown>>;
|
||||
enterpriseGoals: Array<Record<string, unknown>>;
|
||||
organizationUnits: string[];
|
||||
departmentProgress: Array<Record<string, unknown>>;
|
||||
masterAgentSummary: string[];
|
||||
permissionHighlights: string[];
|
||||
agentFlowSteps: string[];
|
||||
skillUsageAudit: Array<Record<string, unknown>>;
|
||||
recoveryActions: string[];
|
||||
backupStatus: Record<string, unknown>;
|
||||
capabilitySummary: Record<string, number>;
|
||||
surface: "platform" | "enterprise";
|
||||
};
|
||||
workbench: {
|
||||
summary: Record<string, number>;
|
||||
companies: Array<Record<string, unknown>>;
|
||||
@@ -36,6 +59,34 @@ export interface BossAdminBackofficePayload {
|
||||
yudaoMapping: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface BossAdminBackupSnapshot {
|
||||
snapshotId: string;
|
||||
fileName: string;
|
||||
absolutePath: string;
|
||||
bytes: number;
|
||||
sha256: string;
|
||||
createdAt: string;
|
||||
actorAccount?: string;
|
||||
reason?: string;
|
||||
schemaVersion?: number;
|
||||
}
|
||||
|
||||
export interface BossAdminBackupStatus {
|
||||
mode: "file";
|
||||
backupDir: string;
|
||||
stateFile: string;
|
||||
restorePointCount: number;
|
||||
lastBackupAt?: string;
|
||||
status: "ready" | "empty" | "error";
|
||||
detail?: string;
|
||||
}
|
||||
|
||||
export interface BossAdminBackupsPayload {
|
||||
ok: boolean;
|
||||
status: BossAdminBackupStatus;
|
||||
snapshots: BossAdminBackupSnapshot[];
|
||||
}
|
||||
|
||||
async function requestJson<T>(url: string, init: RequestInit = {}): Promise<T> {
|
||||
const response = await fetch(url, {
|
||||
credentials: "include",
|
||||
@@ -57,8 +108,8 @@ async function requestJson<T>(url: string, init: RequestInit = {}): Promise<T> {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export async function fetchBossAdminBackoffice(): Promise<BossAdminBackofficePayload> {
|
||||
return requestJson<BossAdminBackofficePayload>("/api/v1/admin/backoffice");
|
||||
export async function fetchBossAdminBackoffice(scope: "platform" | "enterprise" = "platform"): Promise<BossAdminBackofficePayload> {
|
||||
return requestJson<BossAdminBackofficePayload>(`/api/v1/admin/backoffice?scope=${scope}`);
|
||||
}
|
||||
|
||||
export async function postAdminAccess(payload: Record<string, unknown>) {
|
||||
@@ -81,3 +132,27 @@ export async function postSkillLifecycleRequest(payload: Record<string, unknown>
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchAdminBackups(): Promise<BossAdminBackupsPayload> {
|
||||
return requestJson<BossAdminBackupsPayload>("/api/v1/admin/backups");
|
||||
}
|
||||
|
||||
export async function createAdminBackup(reason: string) {
|
||||
return requestJson<Record<string, unknown>>("/api/v1/admin/backups", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
action: "create_snapshot",
|
||||
reason,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function restoreAdminBackup(snapshotId: string) {
|
||||
return requestJson<Record<string, unknown>>("/api/v1/admin/backups", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
action: "restore_snapshot",
|
||||
snapshotId,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,62 +8,109 @@
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-width: 1280px;
|
||||
min-width: 1360px;
|
||||
min-height: 100vh;
|
||||
background:
|
||||
radial-gradient(circle at top left, rgba(16, 185, 129, 0.16), transparent 30%),
|
||||
linear-gradient(135deg, #f7fbf8 0%, #eef4ef 55%, #e8f1ed 100%);
|
||||
linear-gradient(135deg, #f7fbf8 0%, #eef4ef 54%, #e6f0ec 100%);
|
||||
}
|
||||
|
||||
.boss-admin-shell {
|
||||
display: grid;
|
||||
grid-template-columns: 280px 1fr;
|
||||
grid-template-columns: 300px 1fr;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.boss-admin-sidebar {
|
||||
padding: 28px 20px;
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
background: rgba(255, 255, 255, 0.82);
|
||||
border-right: 1px solid rgba(16, 32, 24, 0.08);
|
||||
backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(22px);
|
||||
}
|
||||
|
||||
.boss-admin-brand {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
margin-bottom: 32px;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
.boss-admin-brand-mark {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
color: white;
|
||||
font-weight: 800;
|
||||
font-weight: 900;
|
||||
background: #10b981;
|
||||
border-radius: 16px;
|
||||
border-radius: 17px;
|
||||
box-shadow: 0 14px 28px rgba(16, 185, 129, 0.24);
|
||||
}
|
||||
|
||||
.boss-admin-brand h1 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.boss-admin-brand p,
|
||||
.boss-admin-eyebrow {
|
||||
margin: 0;
|
||||
color: #6b766f;
|
||||
color: #68766e;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.boss-admin-surface-switch {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.boss-admin-surface-card {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
padding: 14px;
|
||||
color: #526158;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
background: rgba(247, 250, 248, 0.78);
|
||||
border: 1px solid rgba(16, 32, 24, 0.08);
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.boss-admin-surface-card span {
|
||||
font-size: 15px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.boss-admin-surface-card small {
|
||||
color: #7b8780;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.boss-admin-surface-card.active {
|
||||
color: #0b6b4c;
|
||||
background: #e5f8ef;
|
||||
border-color: rgba(16, 185, 129, 0.36);
|
||||
box-shadow: 0 12px 30px rgba(16, 185, 129, 0.12);
|
||||
}
|
||||
|
||||
.boss-admin-menu {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.boss-admin-visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.boss-admin-menu-item {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
@@ -93,12 +140,14 @@ body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
.boss-admin-header h2 {
|
||||
margin: 4px 0 0;
|
||||
font-size: 28px;
|
||||
margin: 5px 0 0;
|
||||
font-size: 30px;
|
||||
line-height: 1.15;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.boss-admin-header-actions {
|
||||
@@ -121,47 +170,106 @@ body {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.boss-admin-section-title {
|
||||
grid-column: 1 / -1;
|
||||
color: #25342b;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.boss-admin-hero {
|
||||
grid-column: 1 / -1;
|
||||
overflow: hidden;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(16, 185, 129, 0.16), rgba(255, 255, 255, 0.92)),
|
||||
linear-gradient(135deg, rgba(16, 185, 129, 0.16), rgba(255, 255, 255, 0.94)),
|
||||
white;
|
||||
}
|
||||
|
||||
.boss-admin-hero h3 {
|
||||
margin: 8px 0 20px;
|
||||
font-size: 24px;
|
||||
max-width: 820px;
|
||||
margin: 8px 0 22px;
|
||||
font-size: 25px;
|
||||
line-height: 1.25;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
.boss-admin-metrics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.boss-admin-metrics .ant-statistic {
|
||||
.boss-admin-metrics.compact {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.boss-admin-metric {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 18px;
|
||||
background: rgba(255, 255, 255, 0.76);
|
||||
background: rgba(255, 255, 255, 0.78);
|
||||
border: 1px solid rgba(16, 32, 24, 0.08);
|
||||
border-radius: 18px;
|
||||
}
|
||||
|
||||
.boss-admin-metric span {
|
||||
color: #6a766f;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.boss-admin-metric strong {
|
||||
color: #102018;
|
||||
font-size: 30px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.boss-admin-metric.green strong {
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
.boss-admin-metric.red strong {
|
||||
color: #f04452;
|
||||
}
|
||||
|
||||
.boss-admin-metric.orange strong {
|
||||
color: #f97316;
|
||||
}
|
||||
|
||||
.boss-admin-form {
|
||||
max-width: 520px;
|
||||
max-width: 540px;
|
||||
}
|
||||
|
||||
.boss-admin-form-gap {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.boss-admin-steps {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.boss-admin-step {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
padding: 14px;
|
||||
color: #51625a;
|
||||
background: rgba(255, 255, 255, 0.76);
|
||||
border: 1px solid rgba(16, 32, 24, 0.08);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.boss-admin-step span {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
color: #0f7a55;
|
||||
background: #dbf7ea;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.boss-admin-step.active {
|
||||
color: #0b6b4c;
|
||||
border-color: rgba(16, 185, 129, 0.34);
|
||||
box-shadow: 0 10px 24px rgba(16, 185, 129, 0.12);
|
||||
}
|
||||
|
||||
.boss-admin-action-strip {
|
||||
display: grid;
|
||||
grid-template-columns: 220px 320px 1fr;
|
||||
@@ -169,6 +277,123 @@ body {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.boss-admin-status-list,
|
||||
.boss-admin-check-list,
|
||||
.boss-admin-goal-list {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.boss-admin-status-row,
|
||||
.boss-admin-check-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 14px;
|
||||
background: #f7faf8;
|
||||
border: 1px solid rgba(16, 32, 24, 0.06);
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.boss-admin-check-row {
|
||||
justify-content: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.boss-admin-check-row span {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
color: #f97316;
|
||||
background: #fff7ed;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.boss-admin-check-row span.done {
|
||||
color: #10b981;
|
||||
background: #dcfce7;
|
||||
}
|
||||
|
||||
.boss-admin-goal-row {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 14px;
|
||||
background: #f7faf8;
|
||||
border-radius: 14px;
|
||||
}
|
||||
|
||||
.boss-admin-goal-row > div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.boss-admin-org-grid,
|
||||
.boss-admin-capability-grid,
|
||||
.boss-admin-recovery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.boss-admin-org-node,
|
||||
.boss-admin-recovery-card,
|
||||
.boss-admin-capability-grid > div {
|
||||
padding: 16px;
|
||||
color: #18352a;
|
||||
font-weight: 800;
|
||||
background: #f7faf8;
|
||||
border: 1px solid rgba(16, 32, 24, 0.06);
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.boss-admin-capability-grid span {
|
||||
display: block;
|
||||
color: #68766e;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.boss-admin-capability-grid strong {
|
||||
color: #10b981;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.boss-admin-permission-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.boss-admin-flow {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.boss-admin-flow-node {
|
||||
padding: 14px 16px;
|
||||
color: #0b6b4c;
|
||||
font-weight: 800;
|
||||
background: #e5f8ef;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.boss-admin-flow-arrow {
|
||||
color: #8b9790;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.boss-admin-backup-status {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.ant-card {
|
||||
border-radius: 22px;
|
||||
box-shadow: 0 18px 50px rgba(16, 32, 24, 0.07);
|
||||
}
|
||||
|
||||
.ant-table-wrapper .ant-table {
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user