mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-09 02:12:59 +00:00
feat(host-console): gate Host Console behind Admiral tier (#277)
* feat(host-console): gate Host Console behind Admiral tier Move the Host Console from the Community (free) tier to Admiral, enforcing the gate at every layer: UI nav visibility, AdmiralGate wrapper, POST /api/system/console-token endpoint, and the WebSocket upgrade handler for /api/system/host-console. * test(auth): mock Admiral license for console-token test The console-token endpoint now requires Admiral tier. Mock LicenseService in the test to return pro/team so the happy-path test passes in CI where no license is activated.
This commit is contained in:
@@ -7,6 +7,7 @@ import ErrorBoundary from './ErrorBoundary';
|
||||
import HomeDashboard from './HomeDashboard';
|
||||
import BashExecModal from './BashExecModal';
|
||||
import HostConsole from './HostConsole';
|
||||
import { AdmiralGate } from './AdmiralGate';
|
||||
import ResourcesView from './ResourcesView';
|
||||
import { Button } from './ui/button';
|
||||
import { Input } from './ui/input';
|
||||
@@ -161,13 +162,13 @@ export default function EditorLayout() {
|
||||
{ value: 'dashboard', label: 'Home', icon: Home },
|
||||
{ value: 'fleet', label: 'Fleet', icon: Radar },
|
||||
];
|
||||
if (isAdmin) items.push({ value: 'host-console', label: 'Console', icon: Terminal });
|
||||
items.push(
|
||||
{ value: 'resources', label: 'Resources', icon: HardDrive },
|
||||
{ value: 'templates', label: 'App Store', icon: CloudDownload },
|
||||
{ value: 'global-observability', label: 'Logs', icon: Activity },
|
||||
);
|
||||
if (isPro && license?.variant === 'team') {
|
||||
if (isAdmin) items.push({ value: 'host-console', label: 'Console', icon: Terminal });
|
||||
if (can('system:audit')) items.push({ value: 'audit-log', label: 'Audit', icon: ScrollText });
|
||||
if (isAdmin) items.push({ value: 'scheduled-ops', label: 'Schedules', icon: Clock });
|
||||
}
|
||||
@@ -1479,7 +1480,9 @@ export default function EditorLayout() {
|
||||
) : activeView === 'resources' ? (
|
||||
<ResourcesView />
|
||||
) : activeView === 'host-console' ? (
|
||||
<HostConsole stackName={selectedFile} onClose={() => setActiveView(selectedFile ? 'editor' : 'dashboard')} />
|
||||
<AdmiralGate featureName="Host Console">
|
||||
<HostConsole stackName={selectedFile} onClose={() => setActiveView(selectedFile ? 'editor' : 'dashboard')} />
|
||||
</AdmiralGate>
|
||||
) : !isLoading && selectedFile && activeView === 'editor' ? (
|
||||
<ErrorBoundary>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 items-stretch">
|
||||
|
||||
Reference in New Issue
Block a user