openpalm 0.11.0-beta.1 → 0.11.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openpalm",
3
- "version": "0.11.0-beta.1",
3
+ "version": "0.11.0-beta.2",
4
4
  "type": "module",
5
5
  "license": "MPL-2.0",
6
6
  "description": "OpenPalm CLI — install and manage a self-hosted OpenPalm stack",
@@ -28,7 +28,7 @@
28
28
  "build:windows-arm64": "bun build src/main.ts --compile --target=bun-windows-arm64 --outfile dist/openpalm-cli-windows-arm64.exe"
29
29
  },
30
30
  "dependencies": {
31
- "@openpalm/lib": "0.11.0",
31
+ "@openpalm/lib": "0.11.0-beta.1",
32
32
  "citty": "^0.2.1",
33
33
  "yaml": "^2.8.0"
34
34
  }
@@ -285,10 +285,12 @@ async function runFileInstall(filePath: string, noStart: boolean): Promise<void>
285
285
  throw new Error('Setup config must contain a "capabilities" object (llm, embeddings).');
286
286
  }
287
287
 
288
- // Resolve security.adminToken from environment when not in spec
288
+ // Resolve security.uiLoginPassword from environment when not in spec.
289
+ // Phase 4 (auth/proxy refactor) renamed the env var to OP_UI_LOGIN_PASSWORD
290
+ // and the spec field to security.uiLoginPassword.
289
291
  const security = (config.security ?? {}) as Record<string, unknown>;
290
- if (!security.adminToken && process.env.OP_UI_TOKEN) {
291
- security.adminToken = process.env.OP_UI_TOKEN;
292
+ if (!security.uiLoginPassword && process.env.OP_UI_LOGIN_PASSWORD) {
293
+ security.uiLoginPassword = process.env.OP_UI_LOGIN_PASSWORD;
292
294
  config.security = security;
293
295
  }
294
296
 
@@ -105,7 +105,7 @@ function makeSetupSpec(): Record<string, unknown> {
105
105
  version: 2,
106
106
  llm: { provider: 'ollama', model: 'qwen2.5-coder:3b', baseUrl: 'http://host.docker.internal:11434' },
107
107
  embedding: { provider: 'ollama', model: 'nomic-embed-text:latest', dims: 768, baseUrl: 'http://host.docker.internal:11434' },
108
- security: { adminToken: 'test-admin-token-12345' },
108
+ security: { uiLoginPassword: 'test-admin-token-12345' },
109
109
  owner: { name: 'Test', email: 'test@test.com' },
110
110
  connections: [{
111
111
  id: 'ollama',
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { join } from 'node:path';
10
10
  import { existsSync } from 'node:fs';
11
- import { resolveOpenPalmHome, resolveConfigDir, resolveUiBuildDir, createLogger } from '@openpalm/lib';
11
+ import { resolveOpenPalmHome, resolveConfigDir, resolveUiBuildDir, createLogger, readStackEnv } from '@openpalm/lib';
12
12
  import { ensureValidState } from './cli-state.ts';
13
13
  import { startOpenCodeSubprocess, type OpenCodeSubprocess } from './opencode-subprocess.ts';
14
14
  import { openBrowser } from './browser.ts';
@@ -63,11 +63,14 @@ export async function startUIServer(opts: UIServerOptions = {}): Promise<void> {
63
63
  }
64
64
 
65
65
  const state = ensureValidState();
66
- const { adminToken } = state;
67
- // OP_UI_TOKEN is unset during first-run install the SvelteKit hooks
68
- // detect that and redirect /* to /setup, where the wizard generates
69
- // the token. Don't short-circuit here, or the install wizard can
70
- // never come up.
66
+ // OP_UI_LOGIN_PASSWORD is unset during first-run install — the SvelteKit
67
+ // hooks detect that and redirect /* to /setup, where the wizard sets
68
+ // it. Don't short-circuit here, or the install wizard can never come up.
69
+ const stackEnv = readStackEnv(state.stackDir);
70
+ const uiLoginPassword =
71
+ process.env.OP_UI_LOGIN_PASSWORD
72
+ ?? stackEnv.OP_UI_LOGIN_PASSWORD
73
+ ?? '';
71
74
 
72
75
  // Start OpenCode subprocess (non-fatal — UI still works without it)
73
76
  let openCodeSub: OpenCodeSubprocess | null = null;
@@ -99,11 +102,11 @@ export async function startUIServer(opts: UIServerOptions = {}): Promise<void> {
99
102
  // Pass resolved absolute OP_HOME so the child doesn't re-resolve a
100
103
  // relative value (e.g. `.dev` from a repo-root .env) against its
101
104
  // own cwd (packages/ui/build/).
102
- OP_HOME: homeDir,
103
- HOST: '127.0.0.1',
104
- PORT: String(port),
105
- ORIGIN: `http://127.0.0.1:${port}`,
106
- OP_UI_TOKEN: adminToken,
105
+ OP_HOME: homeDir,
106
+ HOST: '127.0.0.1',
107
+ PORT: String(port),
108
+ ORIGIN: `http://127.0.0.1:${port}`,
109
+ OP_UI_LOGIN_PASSWORD: uiLoginPassword,
107
110
  ...(openCodeBaseUrl ? { OP_OPENCODE_URL: openCodeBaseUrl } : {}),
108
111
  },
109
112
  stdout: 'inherit',
package/src/main.test.ts CHANGED
@@ -19,7 +19,7 @@ function writeMinimalSetupSpec(dir: string): string {
19
19
  ' model: text-embedding-3-small',
20
20
  ' dims: 1536',
21
21
  'security:',
22
- ' adminToken: test-admin-token-12345',
22
+ ' uiLoginPassword: test-admin-token-12345',
23
23
  'owner:',
24
24
  ' name: Test User',
25
25
  ' email: test@example.com',
@@ -113,7 +113,7 @@ describe('cli main', () => {
113
113
  const originalWarn = console.warn;
114
114
  const originalHome = process.env.OP_HOME;
115
115
  const originalWorkDir = process.env.OP_WORK_DIR;
116
- const originalAdminToken = process.env.OP_UI_TOKEN;
116
+ const originalLoginPassword = process.env.OP_UI_LOGIN_PASSWORD;
117
117
 
118
118
  afterEach(() => {
119
119
  globalThis.fetch = originalFetch;
@@ -122,7 +122,7 @@ describe('cli main', () => {
122
122
  restoreDockerCli();
123
123
  process.env.OP_HOME = originalHome;
124
124
  process.env.OP_WORK_DIR = originalWorkDir;
125
- process.env.OP_UI_TOKEN = originalAdminToken;
125
+ process.env.OP_UI_LOGIN_PASSWORD = originalLoginPassword;
126
126
  });
127
127
 
128
128
  it('runs bootstrap install directly without admin delegation', async () => {
@@ -133,7 +133,7 @@ describe('cli main', () => {
133
133
 
134
134
  process.env.OP_HOME = base;
135
135
  process.env.OP_WORK_DIR = workDir;
136
- delete process.env.OP_UI_TOKEN;
136
+ delete process.env.OP_UI_LOGIN_PASSWORD;
137
137
 
138
138
  mockDockerCli();
139
139
  const fetchedUrls: string[] = [];
@@ -255,7 +255,7 @@ describe('cli main', () => {
255
255
  // carries forward existing content.
256
256
  mkdirSync(join(base, 'state'), { recursive: true });
257
257
  mkdirSync(join(base, 'config', 'stack'), { recursive: true });
258
- writeFileSync(join(base, 'config', 'stack', 'stack.env'), 'OP_UI_TOKEN=existing-token\n');
258
+ writeFileSync(join(base, 'config', 'stack', 'stack.env'), 'OP_UI_LOGIN_PASSWORD=existing-password\n');
259
259
  writeFileSync(stackConfig, 'llm: old\n');
260
260
 
261
261
  process.env.OP_HOME = base;
@@ -284,7 +284,7 @@ describe('cli main', () => {
284
284
  const backups = readdirSync(backupsDir);
285
285
  expect(backups.length).toBeGreaterThan(0);
286
286
  expect(readFileSync(join(backupsDir, backups[0], 'config', 'stack.yml'), 'utf8')).toContain('llm: old');
287
- expect(readFileSync(join(backupsDir, backups[0], 'config', 'stack', 'stack.env'), 'utf8')).toContain('OP_UI_TOKEN=existing-token');
287
+ expect(readFileSync(join(backupsDir, backups[0], 'config', 'stack', 'stack.env'), 'utf8')).toContain('OP_UI_LOGIN_PASSWORD=existing-password');
288
288
  } finally {
289
289
  rmSync(base, { recursive: true, force: true });
290
290
  }
@@ -304,7 +304,7 @@ describe('cli main', () => {
304
304
  mkdirSync(chatAddonDir, { recursive: true });
305
305
  writeFileSync(coreCompose, 'services:\n assistant:\n image: test\n');
306
306
  writeFileSync(join(adminAddonDir, 'compose.yml'), 'services:\n admin:\n image: admin\n');
307
- writeFileSync(join(adminAddonDir, '.env.schema'), 'OP_UI_TOKEN=\n');
307
+ writeFileSync(join(adminAddonDir, '.env.schema'), 'OP_UI_LOGIN_PASSWORD=\n');
308
308
  writeFileSync(join(chatAddonDir, 'compose.yml'), 'services:\n chat:\n image: chat\n environment:\n CHANNEL_NAME: "Chat"\n CHANNEL_ID: "chat"\n');
309
309
  writeFileSync(join(chatAddonDir, '.env.schema'), 'CHANNEL_CHAT_SECRET=\n');
310
310
  writeFileSync(guardianEnv, '# Guardian channel HMAC secrets — managed by openpalm\n');
@@ -411,7 +411,7 @@ describe('validate command', () => {
411
411
  const tempHome = mkdtempSync(join(tmpdir(), 'openpalm-test-'));
412
412
  const stackDir = join(tempHome, 'config', 'stack');
413
413
  mkdirSync(stackDir, { recursive: true });
414
- writeFileSync(join(stackDir, 'stack.env'), 'OP_UI_TOKEN=abc\nOP_ASSISTANT_TOKEN=def\n');
414
+ writeFileSync(join(stackDir, 'stack.env'), 'OP_UI_LOGIN_PASSWORD=abc\n');
415
415
 
416
416
  const originalHome = process.env.OP_HOME;
417
417
  const originalExit = process.exit;
@@ -436,7 +436,7 @@ describe('scan command', () => {
436
436
  const tempHome = mkdtempSync(join(tmpdir(), 'openpalm-test-'));
437
437
  const stackDir = join(tempHome, 'config', 'stack');
438
438
  mkdirSync(stackDir, { recursive: true });
439
- writeFileSync(join(stackDir, 'stack.env'), 'OP_UI_TOKEN=abc\nOPENAI_API_KEY=sk-test\n');
439
+ writeFileSync(join(stackDir, 'stack.env'), 'OP_UI_LOGIN_PASSWORD=abc\nOPENAI_API_KEY=sk-test\n');
440
440
 
441
441
  const originalHome = process.env.OP_HOME;
442
442
  const originalExit = process.exit;
@@ -553,8 +553,8 @@ describe('install image tag pinning', () => {
553
553
  });
554
554
 
555
555
  it('preserves export prefix when upserting a key', () => {
556
- expect(upsertEnvValue('export OP_UI_TOKEN=old\n', 'OP_UI_TOKEN', 'new')).toBe(
557
- 'export OP_UI_TOKEN=new\n',
556
+ expect(upsertEnvValue('export OP_UI_LOGIN_PASSWORD=old\n', 'OP_UI_LOGIN_PASSWORD', 'new')).toBe(
557
+ 'export OP_UI_LOGIN_PASSWORD=new\n',
558
558
  );
559
559
  });
560
560