fix(cli): generate a UI password for bare --ui-password in daemon/serve mode
The grand tunnel restructuring removed the CLI's auto-generated UI password, so `openchamber -d --ui-password` (no value) silently started an unauthenticated server instead of creating a password as in 1.8.1. Restore generation for an explicit --ui-password flag without a value: the password is generated before either launch path, passed to the daemon/foreground process via OPENCHAMBER_UI_PASSWORD, persisted in the instance state file, and surfaced once in human/quiet/json output. Refs OPE-216
This commit is contained in:
@@ -34,12 +34,14 @@ import {
|
||||
discoverRunningInstances,
|
||||
discoverUnconfirmedRegistryInstanceOnPort,
|
||||
ensureTunnelProfilesMigrated,
|
||||
generateUiPassword,
|
||||
getInstanceFilePath,
|
||||
getPidFilePath,
|
||||
isOpenchamberCmdline,
|
||||
isOpenchamberProcessRunning,
|
||||
parseArgs,
|
||||
resolveServeHost,
|
||||
resolveServeUiPassword,
|
||||
} from './cli.js';
|
||||
|
||||
async function withTempOpenChamberDataDir(fn) {
|
||||
@@ -692,6 +694,43 @@ describe('network-exposed auth validation', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('serve UI password resolution', () => {
|
||||
it('keeps a configured password untouched', () => {
|
||||
expect(resolveServeUiPassword({ uiPassword: 'secret', explicitUiPassword: true }))
|
||||
.toEqual({ password: 'secret', generated: false });
|
||||
});
|
||||
|
||||
it('generates a password for an explicit --ui-password flag without a value', () => {
|
||||
const resolved = resolveServeUiPassword({ uiPassword: '', explicitUiPassword: true });
|
||||
expect(resolved.generated).toBe(true);
|
||||
expect(typeof resolved.password).toBe('string');
|
||||
expect(resolved.password.length).toBe(16);
|
||||
});
|
||||
|
||||
it('does not generate a password when the flag is absent', () => {
|
||||
expect(resolveServeUiPassword({ uiPassword: undefined, explicitUiPassword: false }))
|
||||
.toEqual({ password: undefined, generated: false });
|
||||
});
|
||||
|
||||
it('generates passwords from an ambiguity-free charset', () => {
|
||||
const resolved = resolveServeUiPassword({ uiPassword: '', explicitUiPassword: true });
|
||||
expect(resolved.password).toMatch(/^[A-HJ-NP-Za-km-z2-9]{16}$/);
|
||||
expect(resolved.password).not.toMatch(/[0O1Il]/);
|
||||
});
|
||||
|
||||
it('generates distinct passwords on repeated calls', () => {
|
||||
const a = generateUiPassword();
|
||||
const b = generateUiPassword();
|
||||
expect(a).not.toBe(b);
|
||||
});
|
||||
|
||||
it('parses --ui-password without a value as explicit but empty', () => {
|
||||
const parsed = parseArgs(['serve', '--ui-password']);
|
||||
expect(parsed.options.explicitUiPassword).toBe(true);
|
||||
expect(parsed.options.uiPassword).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('serve host resolution', () => {
|
||||
it('uses OPENCHAMBER_HOST when --host is not provided', () => {
|
||||
const previous = process.env.OPENCHAMBER_HOST;
|
||||
|
||||
Reference in New Issue
Block a user