Files
TREK/server/tests/unit/nest/managed.test.ts
T
Maurice 724c88c201 style: format server and shared with prettier
A mechanical prettier --write over server/src, server/tests, server/scripts
and shared/src with the workspaces' .prettierrc; nothing but layout and
import order changes, and every file keeps the same set of imports. shared
is formatted throughout and its format baseline is empty. The server
baseline keeps the 35 files that Prettier would grow past their lint:size
limit (they need a split first, which is not a formatting change), and the
generated entity files stay as their generator writes them.
2026-10-10 21:23:37 +02:00

105 lines
3.6 KiB
TypeScript

/**
* TREK_MANAGED — the switch that says the configuration belongs to whoever runs
* this install rather than to its admin.
*
* Runtime-toggled, exactly like DEMO_MODE: read live on every access, never
* snapshotted into a field or a registerAs token, because roughly sixty tests
* mutate process.env mid-lifetime and a frozen value breaks all of them.
* MANAGED-004 is the case that pins it.
*/
import { deriveManaged } from '../../../src/app-config/derive';
import { RuntimeEnvService } from '../../../src/nest/app-config/runtime-env.service';
import {
isManagedBlocked,
MANAGED_FORBIDDEN,
MANAGED_FORBIDDEN_ERROR,
ManagedForbidden,
} from '../../../src/nest/common/managed';
import { describe, it, expect, afterEach } from 'vitest';
const env = new RuntimeEnvService();
afterEach(() => {
delete process.env.TREK_MANAGED;
});
describe('deriveManaged', () => {
it('MANAGED-001: off when the variable is unset', () => {
expect(deriveManaged({}).enabled).toBe(false);
});
it('MANAGED-002: on for the documented truthy spellings', () => {
for (const value of ['true', 'TRUE', '1', 'yes', 'on']) {
expect(deriveManaged({ TREK_MANAGED: value }).enabled).toBe(true);
}
});
it('MANAGED-003: off for an empty, unparseable or falsy value', () => {
// A typo must not take settings away from an admin who never asked for it,
// so anything that is not recognisably true stays off.
for (const value of ['', 'false', '0', 'no', 'off', 'maybe', 'TREK_MANAGED']) {
expect(deriveManaged({ TREK_MANAGED: value }).enabled).toBe(false);
}
});
});
describe('RuntimeEnvService.isManaged', () => {
it('MANAGED-004: reads the env live, so a toggle takes effect without a restart', () => {
expect(env.isManaged()).toBe(false);
process.env.TREK_MANAGED = 'true';
expect(env.isManaged()).toBe(true);
delete process.env.TREK_MANAGED;
expect(env.isManaged()).toBe(false);
});
});
describe('isManagedBlocked', () => {
it('MANAGED-005: false on a self-hosted install', () => {
expect(isManagedBlocked(env)).toBe(false);
});
it('MANAGED-006: true once the instance is centrally administered', () => {
process.env.TREK_MANAGED = 'true';
expect(isManagedBlocked(env)).toBe(true);
});
});
describe('the shared 403', () => {
it('MANAGED-007: one body, and it does not name a reason', () => {
// Pinned because DEMO_MODE grew two texts for one condition (REST says
// 'Self-host TREK for full functionality.', MCP says something else) and
// neither can now be changed without hunting for the other.
expect(MANAGED_FORBIDDEN_ERROR).toEqual({
error: 'This is configured by the operator of this instance.',
code: 'MANAGED_FORBIDDEN',
});
});
});
describe('ManagedForbidden', () => {
it('MANAGED-008: writes the reason onto the handler for the next reader', () => {
class Controller {
@ManagedForbidden('the operator holds this credential')
handler() {}
}
const meta = Reflect.getMetadata(MANAGED_FORBIDDEN, Controller.prototype.handler);
expect(meta).toEqual({ reason: 'the operator holds this credential', enforcedInHandler: false });
});
it('MANAGED-009: a multipart route stays in the inventory while refusing in its handler', () => {
class Controller {
@ManagedForbidden('restoring a backup replaces state the operator owns', { enforcedInHandler: true })
upload() {}
}
const meta = Reflect.getMetadata(MANAGED_FORBIDDEN, Controller.prototype.upload);
expect(meta.enforcedInHandler).toBe(true);
// The reason is still mandatory: the boot gate refuses an empty one.
expect(meta.reason).not.toBe('');
});
});