feat(meta): gate deferred Fleet tabs behind SENCHO_EXPERIMENTAL flag (#886)

Hide the Traffic / Routing, Deployments, Federation and Secrets Fleet
tabs by default. They re-appear when the operator opts in by setting
SENCHO_EXPERIMENTAL=true. Backend routes and database tables are
unchanged; this is a UI discovery gate only.

The /api/meta endpoint now returns experimental as a boolean. A new
useExperimental hook reads it once per page load and feeds the four
tab triggers and tab content panels in FleetView.
This commit is contained in:
Anso
2026-05-02 18:01:06 -04:00
committed by GitHub
parent b6b154cb99
commit d69fb9f1da
5 changed files with 174 additions and 52 deletions
+51
View File
@@ -39,3 +39,54 @@ describe('GET /api/health', () => {
expect(res.status).not.toBe(403);
});
});
describe('GET /api/meta experimental flag', () => {
it('reports experimental=false by default', async () => {
const prev = process.env.SENCHO_EXPERIMENTAL;
delete process.env.SENCHO_EXPERIMENTAL;
try {
const res = await request(app).get('/api/meta');
expect(res.status).toBe(200);
expect(res.body.experimental).toBe(false);
} finally {
if (prev !== undefined) process.env.SENCHO_EXPERIMENTAL = prev;
}
});
it('reports experimental=true when SENCHO_EXPERIMENTAL=true', async () => {
const prev = process.env.SENCHO_EXPERIMENTAL;
process.env.SENCHO_EXPERIMENTAL = 'true';
try {
const res = await request(app).get('/api/meta');
expect(res.status).toBe(200);
expect(res.body.experimental).toBe(true);
} finally {
if (prev === undefined) delete process.env.SENCHO_EXPERIMENTAL;
else process.env.SENCHO_EXPERIMENTAL = prev;
}
});
it('treats any non-"true" value as false', async () => {
const prev = process.env.SENCHO_EXPERIMENTAL;
process.env.SENCHO_EXPERIMENTAL = '1';
try {
const res = await request(app).get('/api/meta');
expect(res.body.experimental).toBe(false);
} finally {
if (prev === undefined) delete process.env.SENCHO_EXPERIMENTAL;
else process.env.SENCHO_EXPERIMENTAL = prev;
}
});
it('treats an empty string as false', async () => {
const prev = process.env.SENCHO_EXPERIMENTAL;
process.env.SENCHO_EXPERIMENTAL = '';
try {
const res = await request(app).get('/api/meta');
expect(res.body.experimental).toBe(false);
} finally {
if (prev === undefined) delete process.env.SENCHO_EXPERIMENTAL;
else process.env.SENCHO_EXPERIMENTAL = prev;
}
});
});
+1
View File
@@ -22,6 +22,7 @@ metaRouter.get('/meta', (_req: Request, res: Response): void => {
version: getSenchoVersion(),
capabilities: getActiveCapabilities(),
startedAt: processStartedAt,
experimental: process.env.SENCHO_EXPERIMENTAL === 'true',
...(updateError ? { updateError } : {}),
});
});