evOo-local/apps/api/src/env.test.ts
cynarAI 2c6b5c3d7b
chore: remove legacy orchestrator, trading and one-off leftovers (#109)
* chore: remove legacy orchestrator, trading and one-off script leftovers

The repository still carried the pre-evOo prototype: a Python orchestrator,
the old HTML "evoo-platform" cockpit (whose test ran in the root unit
suite), an apex-trading package, the hot-reload deploy.sh for it, a
permissions manifest, an architecture note with local file links, agent
handoff notes, a Steve Jobs persona template and about ninety one-off
scripts that probe a developer database with hard-coded local URLs. None
of it is used by the product, CI or the real deploy in ops/evo-deploy.

Delete those files, drop the evoo-platform test glob from the root vitest
config, the Cockpit section from .env.example and the dead biome and
gitignore entries, and update the docs that listed the removed tools.
scripts/start-tmux.sh no longer starts the removed sentinel and resolves
the checkout from its own location instead of a machine-specific path;
scripts/seed-ollama.ts requires DATABASE_URL instead of falling back to a
local URL with a username.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u

* fix(web): drop trading and persona prompts from the conversation shell

The web shell still showed leftovers from the trading prototype: composer
chips with German trading and "Steve Jobs" prompts, trading suggestion
chips under the empty conversation line, a German trading hero for the
empty transcript, and a German "data protection" status panel in the
sidebar. They suggested actions the product does not have and added
persistent chrome.

Remove the composer chips and their helper, the empty-state chips and the
hero (the empty conversation keeps its existing one-line start hint), the
sidebar trading indicator and the data trust panel. The new-bot E2E now
asserts the plain empty state; the sidebar spec no longer expects the
trading status, and the placeholder Steve Jobs spec with no assertions is
gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u

Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>

* refactor: remove the trading bot status integration

With the sidebar trading indicator gone, the only remaining consumer of
the trading bot status was a banner in General settings that reused the
same component. evOo is a personal assistant; a status proxy and poller
for one external trading service, configured through service-specific
TRADING_BOT_URL and VITE_TRADING_BOT_URL variables, does not belong in
the core product.

Remove the settings banner and its prop plumbing, the web poller, the
indicator component, the /api/trading-bot/status proxy, the shared core
contract, the env loading and both variables from .env.example, together
with their tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u

* chore: remove one-off database scripts and a stale review note

packages/db carried four hand-run scripts outside the package build that
query or seed a developer database with a hard-coded connection string,
one of them for a specific account. docs/VOICE-FIRST-REVIEW.md was a
one-time verification note for a workflow that no longer exists and
named private machines and local paths. Nothing references them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u

* chore: replace machine-specific paths and addresses with placeholders

ORIGIN.md pinned the intended checkout to an absolute path under a
personal home directory, docs/LOCAL-SETUP.md listed folders on one
developer's machine, and two tests used what looks like a real tailnet
address. Use a home-relative path, drop the machine-specific folder list,
and use 100.100.100.100 in the tests; it is still inside 100.64.0.0/10,
so both tests check the same thing as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u

* test(web): drop the trading status from the shell contrast test

main's contrast test now waits for the sidebar trading status before
measuring; this branch removes that status.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: cynarAI <cynarAI@users.noreply.github.com>
2026-10-04 01:13:52 +02:00

215 lines
7.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { loadEnv } from "./env.js";
const base = {
DATABASE_URL: "postgres://rakazo:rakazo@127.0.0.1:5433/rakazo",
NODE_ENV: "test",
};
describe("loadEnv", () => {
it("defaults the product path to Pi, Docker, and Graphile Worker", () => {
const env = loadEnv(base);
expect(env.agentRuntime).toBe("pi");
expect(env.sandboxProvider).toBe("docker");
expect(env.wakeupDriver).toBe("graphile");
expect(env.apiHost).toBe("127.0.0.1");
expect(env.nodeEnv).toBe("test");
});
it("defaults Pi JSONL session recording to off", () => {
expect(loadEnv(base).piSessionRecording).toBe(false);
expect(loadEnv({ ...base, PI_SESSION_RECORDING: "false" }).piSessionRecording).toBe(false);
expect(loadEnv({ ...base, PI_SESSION_RECORDING: "1" }).piSessionRecording).toBe(false);
expect(loadEnv({ ...base, PI_SESSION_RECORDING: "true" }).piSessionRecording).toBe(true);
});
it("keeps explicit emulator settings for pnpm test", () => {
const env = loadEnv({
...base,
AGENT_RUNTIME: "scripted",
SANDBOX_PROVIDER: "fake",
WAKEUP_DRIVER: "memory",
});
expect(env.agentRuntime).toBe("scripted");
expect(env.sandboxProvider).toBe("fake");
expect(env.wakeupDriver).toBe("memory");
});
it("keeps the onboarding scan off the host unless a scan home is configured", () => {
expect(loadEnv(base).onboardingScanHome).toBeUndefined();
expect(loadEnv({ ...base, ONBOARDING_SCAN_HOME: " /srv/home " }).onboardingScanHome).toBe(
"/srv/home",
);
});
it("loads an optional integrations catalog mirror", () => {
expect(loadEnv(base).integrationsCatalogUrl).toBeUndefined();
expect(
loadEnv({ ...base, INTEGRATIONS_CATALOG_URL: " https://catalog.example.test/feed " })
.integrationsCatalogUrl,
).toBe("https://catalog.example.test/feed");
});
it("falls back to none when a remote provider key is missing", () => {
expect(
loadEnv({
...base,
SANDBOX_PROVIDER: "e2b",
}).sandboxProvider,
).toBe("none");
expect(
loadEnv({
...base,
SANDBOX_PROVIDER: "none",
}).sandboxProvider,
).toBe("none");
expect(
loadEnv({
...base,
SANDBOX_PROVIDER: "",
}).sandboxProvider,
).toBe("none");
});
it("loads provider-specific Daytona configuration", () => {
const env = loadEnv({
...base,
SANDBOX_PROVIDER: "daytona",
DAYTONA_API_KEY: "test-daytona-key",
DAYTONA_API_URL: "https://daytona.test/api",
DAYTONA_TARGET: "test-target",
});
expect(env).toMatchObject({
sandboxProvider: "daytona",
daytonaApiKey: "test-daytona-key",
daytonaApiUrl: "https://daytona.test/api",
daytonaTarget: "test-target",
});
});
it("loads provider-specific Box configuration", () => {
const env = loadEnv({
...base,
SANDBOX_PROVIDER: "box",
BOX_API_KEY: "test-box-key",
BOX_API_URL: "https://box.test/api/v1",
});
expect(env).toMatchObject({
sandboxProvider: "box",
boxApiKey: "test-box-key",
boxApiUrl: "https://box.test/api/v1",
});
});
it("throws when production omits secrets", () => {
expect(() =>
loadEnv({
DATABASE_URL: base.DATABASE_URL,
NODE_ENV: "production",
}),
).toThrow(/BETTER_AUTH_SECRET/);
});
it("throws when production uses placeholder secrets", () => {
expect(() =>
loadEnv({
DATABASE_URL: base.DATABASE_URL,
NODE_ENV: "production",
BETTER_AUTH_SECRET: "dev-secret-change-me-please-32chars",
ENCRYPTION_KEY: "real-encryption-key-value",
SANDBOX_SUPERVISOR_TOKEN: "real-supervisor-token-with-enough-length",
SCREEN_PROXY_SECRET: "real-screen-proxy-secret-with-enough-length",
}),
).toThrow(/BETTER_AUTH_SECRET/);
});
it("loads real secrets in production", () => {
const env = loadEnv({
DATABASE_URL: base.DATABASE_URL,
NODE_ENV: "production",
BETTER_AUTH_SECRET: "prod-auth-secret-with-enough-length",
ENCRYPTION_KEY: "prod-encryption-key-with-enough-length",
SCREEN_PROXY_SECRET: "prod-screen-proxy-secret-with-enough-length",
SANDBOX_PROVIDER: "e2b",
API_HOST: "0.0.0.0",
});
expect(env.authSecret).toBe("prod-auth-secret-with-enough-length");
expect(env.encryptionKey).toBe("prod-encryption-key-with-enough-length");
expect(env.sandboxSupervisorToken).toBeUndefined();
expect(env.screenProxySecret).toBe("prod-screen-proxy-secret-with-enough-length");
expect(env.apiHost).toBe("0.0.0.0");
});
it("falls back to none in production when Docker has no supervisor token", () => {
const env = loadEnv({
DATABASE_URL: base.DATABASE_URL,
NODE_ENV: "production",
BETTER_AUTH_SECRET: "prod-auth-secret-with-enough-length",
ENCRYPTION_KEY: "prod-encryption-key-with-enough-length",
SCREEN_PROXY_SECRET: "prod-screen-proxy-secret-with-enough-length",
SANDBOX_PROVIDER: "docker",
});
expect(env.sandboxProvider).toBe("none");
expect(env.sandboxSupervisorToken).toBeUndefined();
});
it("requires a dedicated supervisor token when Docker stays selected", () => {
expect(() =>
loadEnv({
DATABASE_URL: base.DATABASE_URL,
NODE_ENV: "production",
BETTER_AUTH_SECRET: "prod-auth-secret-with-enough-length",
ENCRYPTION_KEY: "prod-encryption-key-with-enough-length",
SCREEN_PROXY_SECRET: "prod-screen-proxy-secret-with-enough-length",
SANDBOX_PROVIDER: "docker",
SANDBOX_SUPERVISOR_TOKEN: "too-short",
}),
).toThrow(/SANDBOX_SUPERVISOR_TOKEN/);
});
it("exposes a deployed git revision when GIT_SHA is set", () => {
expect(loadEnv(base).gitSha).toBeUndefined();
expect(loadEnv({ ...base, GIT_SHA: " 3c6e209 " }).gitSha).toBe("3c6e209");
expect(loadEnv({ ...base, RAKAZO_GIT_SHA: "abc1234" }).gitSha).toBe("abc1234");
});
it("loads optional updater sidecar wiring without requiring the token at boot", () => {
expect(loadEnv(base).updaterUrl).toBeUndefined();
expect(loadEnv(base).updaterToken).toBeUndefined();
const env = loadEnv({
...base,
RAKAZO_UPDATER_URL: " http://updater:7092 ",
RAKAZO_UPDATER_TOKEN: " fake-review-updater-token-000000000000 ",
});
expect(env.updaterUrl).toBe("http://updater:7092");
expect(env.updaterToken).toBe("fake-review-updater-token-000000000000");
});
it("loads SMTP configuration and keeps the email emulator out of production", () => {
expect(
loadEnv({
...base,
SMTP_URL: " smtps://user:secret@smtp.example.test:465 ",
EMAIL_FROM: " Rakazo <no-reply@example.test> ",
EMAIL_EMULATOR: "true",
}),
).toMatchObject({
smtpUrl: "smtps://user:secret@smtp.example.test:465",
emailFrom: "Rakazo <no-reply@example.test>",
emailEmulator: true,
});
expect(
loadEnv({
...base,
NODE_ENV: "production",
BETTER_AUTH_SECRET: "prod-auth-secret-with-enough-length",
ENCRYPTION_KEY: "prod-encryption-key-with-enough-length",
SCREEN_PROXY_SECRET: "prod-screen-proxy-secret-with-enough-length",
SANDBOX_PROVIDER: "none",
EMAIL_EMULATOR: "true",
}).emailEmulator,
).toBe(false);
expect(loadEnv({ ...base, NODE_ENV: "development" }).nodeEnv).toBe("development");
});
});