deepdebug-local-agent 1.0.22 → 1.1.0
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/.claude/context.md +76 -0
- package/.claude/skills/README.md +25 -0
- package/.claude/skills/tdd-debugging/SKILL.md +53 -0
- package/.claude/skills/tdd-debugging/references/anti-patterns.md +43 -0
- package/.claude/skills/tdd-debugging/references/command-reference.md +46 -0
- package/.claude/standards/README.md +51 -0
- package/.claude/standards/clean-code.md +75 -0
- package/.claude/standards/code-review-checklist.md +61 -0
- package/.claude/standards/layered-architecture.md +163 -0
- package/.claude/standards/node.md +45 -0
- package/.claude/standards/security-owasp.md +114 -0
- package/.claude/standards/simplicity.md +42 -0
- package/.claude/standards/solid.md +64 -0
- package/.claude/standards/testing.md +59 -0
- package/.cursor/rules/standards.mdc +17 -0
- package/.github/workflows/build-byoc-image.yml +315 -0
- package/.github/workflows/deploy-gcp.yml +102 -0
- package/.github/workflows/npm-publish.yml +69 -8
- package/AGENTS.md +21 -0
- package/CHANGELOG.md +69 -0
- package/CLAUDE.md +13 -0
- package/CLAUDE_CODE_AGENT_INFINITE.md +5 -3
- package/Dockerfile +4 -0
- package/Dockerfile.full +55 -3
- package/README.md +81 -0
- package/bin/install.js +16 -5
- package/cloudbuild-full.yaml +57 -0
- package/docker-compose.yml +5 -3
- package/docs/OBSERVABILITY.md +164 -0
- package/docs/byoc-agent-image.md +70 -0
- package/docs/graphify-packaging-plan.md +133 -0
- package/docs/graphify-validation-run-2026-10-28.md +243 -0
- package/docs/legacy-connectors.md +268 -0
- package/docs/releasing.md +43 -0
- package/docs/signed-commands.md +163 -0
- package/env.example +30 -0
- package/helm/Chart.yaml +2 -2
- package/helm/templates/deployment.yaml +13 -3
- package/helm/templates/networkpolicy.yaml +22 -0
- package/helm/templates/secret.yaml +1 -0
- package/helm/values.yaml +13 -14
- package/mcp-server.js +4 -1
- package/package.json +12 -4
- package/scripts/sync-fixtures.mjs +246 -0
- package/scripts/upgrade-observability-push.sh +227 -0
- package/src/adapters/as400/as400-parser.js +12 -0
- package/src/adapters/as400/index.js +134 -0
- package/src/adapters/cobol/cobol-parser.js +37 -0
- package/src/adapters/cobol/index.js +151 -0
- package/src/adapters/ibmmq/ibmmq-parser.js +23 -0
- package/src/adapters/ibmmq/index.js +137 -0
- package/src/adapters/index.js +79 -0
- package/src/adapters/oracle-forms/index.js +145 -0
- package/src/adapters/oracle-forms/oracle-forms-parser.js +11 -0
- package/src/adapters/sap/index.js +146 -0
- package/src/adapters/sap/sap-parser.js +41 -0
- package/src/ai-engine.js +22 -22
- package/src/config/trusted-signing-keys.json +3 -0
- package/src/detectors/build-tool-detector.js +50 -0
- package/src/detectors/multi-project-detector.js +22 -22
- package/src/detectors/service-detector.js +24 -24
- package/src/exec-utils.js +26 -4
- package/src/git/base-git-provider.js +117 -117
- package/src/git/bitbucket-provider.js +2 -2
- package/src/git/git-provider-registry.js +18 -18
- package/src/git/github-provider.js +13 -13
- package/src/git/multi-repo-pr.js +161 -0
- package/src/mcp-http-server.js +32 -16
- package/src/observability/bundle-files.js +418 -0
- package/src/observability/detect.js +151 -0
- package/src/observability/provision.js +212 -0
- package/src/observability/render-cli.js +59 -0
- package/src/observability/routes.js +88 -0
- package/src/patch/patch-engine.js +28 -28
- package/src/patch-manager.js +85 -85
- package/src/patch_bkp.js +14 -14
- package/src/ports.js +4 -4
- package/src/routes/workspace.route.js +47 -16
- package/src/runtimes/base-runtime.js +75 -75
- package/src/runtimes/java/gradle-runtime.js +17 -17
- package/src/runtimes/java/java-integrations.js +25 -25
- package/src/runtimes/java/maven-runtime.js +34 -34
- package/src/runtimes/node/node-integrations.js +1 -1
- package/src/runtimes/node/npm-runtime.js +14 -14
- package/src/runtimes/node/yarn-runtime.js +4 -4
- package/src/runtimes/runtime-registry.js +25 -25
- package/src/server-local.js +4 -4
- package/src/server.js +1412 -335
- package/src/siblings/burst-suppressor.js +89 -0
- package/src/siblings/capabilities.js +273 -0
- package/src/siblings/env-compat.cjs +58 -0
- package/src/siblings/incident-forwarder.js +320 -0
- package/src/siblings/logger.js +15 -0
- package/src/siblings/metrics.js +94 -0
- package/src/utils/agent-auth.js +184 -0
- package/src/utils/approval-token.js +56 -0
- package/src/utils/bind-host.js +29 -0
- package/src/utils/branch-refspec.js +98 -0
- package/src/utils/child-env.js +34 -0
- package/src/utils/environment-diagnostics.js +55 -55
- package/src/utils/exec-policy.js +962 -0
- package/src/utils/exec-utils.js +15 -15
- package/src/utils/file-count.js +46 -0
- package/src/utils/fs-utils.js +10 -10
- package/src/utils/multi-repo-open.js +132 -0
- package/src/utils/open-gate.js +183 -0
- package/src/utils/ranged-read.js +65 -0
- package/src/utils/request-guards.js +77 -0
- package/src/utils/request-signing.js +342 -0
- package/src/utils/root-recovery.js +244 -0
- package/src/utils/safe-exec-args.js +58 -0
- package/src/utils/sandbox.js +182 -0
- package/src/utils/search-outcome.js +56 -0
- package/src/utils/workspace-root.js +80 -0
- package/src/validators/syntax-validator.js +149 -0
- package/src/workspace/detect-port.js +16 -16
- package/src/workspace/file-reader.js +1 -1
- package/src/workspace/process-manager.js +46 -46
- package/src/workspace-manager.js +86 -24
- package/test/adapters/as400/as400.test.js +121 -0
- package/test/adapters/cobol/cobol.test.js +217 -0
- package/test/adapters/ibmmq/ibmmq.test.js +122 -0
- package/test/adapters/oracle-forms/oracle-forms.test.js +180 -0
- package/test/adapters/registry.test.js +108 -0
- package/test/adapters/sap/sap.test.js +142 -0
- package/test/agent-auth.test.js +194 -0
- package/test/bind-host.test.js +26 -0
- package/test/branch-refspec.test.js +224 -0
- package/test/burst-suppressor.test.js +60 -0
- package/test/capabilities-access.test.js +47 -0
- package/test/capabilities.test.js +87 -0
- package/test/child-env.test.js +23 -0
- package/test/env-compat.test.js +71 -0
- package/test/exec-policy.test.js +463 -0
- package/test/file-count.test.js +64 -0
- package/test/incident-forwarder.test.js +231 -0
- package/test/multi-repo-open.test.js +180 -0
- package/test/multi-repo-pr.test.js +129 -0
- package/test/observability-detect.test.js +199 -0
- package/test/open-gate.test.js +341 -0
- package/test/ranged-read.test.js +60 -0
- package/test/request-guards.test.js +91 -0
- package/test/request-signing.test.js +284 -0
- package/test/root-recovery-sidecar.test.js +171 -0
- package/test/root-recovery.test.js +274 -0
- package/test/safe-exec-args.test.js +58 -0
- package/test/sandbox.test.js +98 -0
- package/test/search-outcome.test.js +50 -0
- package/test/workspace-root.test.js +64 -0
- package/tools/graphify-validation/README.md +92 -0
- package/tools/graphify-validation/config/questions.json +31 -0
- package/tools/graphify-validation/config/repos.json +9 -0
- package/tools/graphify-validation/config/symbols.json +6 -0
- package/tools/graphify-validation/fixtures/spring/expected.json +34 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/AppConfig.java +29 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/AuditLogger.java +15 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/Cache.java +7 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/CheckoutService.java +25 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/InMemoryCache.java +18 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/OrderController.java +22 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/PaymentGateway.java +5 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/PaypalGateway.java +11 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/RefundService.java +14 -0
- package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/StripeGateway.java +11 -0
- package/tools/graphify-validation/lib/affected_vs_rg.py +81 -0
- package/tools/graphify-validation/lib/audit_hook/sitecustomize.py +22 -0
- package/tools/graphify-validation/lib/graph_metrics.py +96 -0
- package/tools/graphify-validation/lib/gv_common.py +130 -0
- package/tools/graphify-validation/lib/licenses.py +47 -0
- package/tools/graphify-validation/lib/pip_audit_summary.py +18 -0
- package/tools/graphify-validation/lib/recall.py +115 -0
- package/tools/graphify-validation/lib/report.py +226 -0
- package/tools/graphify-validation/lib/run_all.py +237 -0
- package/tools/graphify-validation/lib/run_graphify.py +144 -0
- package/tools/graphify-validation/lib/rusage_helper.py +17 -0
- package/tools/graphify-validation/lib/sample_edges.py +246 -0
- package/tools/graphify-validation/lib/spring_fixture.py +81 -0
- package/tools/graphify-validation/requirements-py311.lock +508 -0
- package/tools/graphify-validation/requirements-tools.in +1 -0
- package/tools/graphify-validation/requirements-tools.lock +371 -0
- package/tools/graphify-validation/requirements.in +1 -0
- package/tools/graphify-validation/requirements.lock +502 -0
- package/tools/graphify-validation/run.sh +43 -0
- package/tools/graphify-validation/tests/test_harness.py +151 -0
- package/cloudbuild-agent-qa.yaml +0 -43
- package/cloudbuild-agent-staging.yaml +0 -40
- package/cloudbuild.yaml.deprecated +0 -42
- package/src/local-agent-source.tar.gz +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { isAuthorized, publicCapabilities, fullCapabilities } from '../src/siblings/capabilities.js';
|
|
4
|
+
|
|
5
|
+
const MANIFEST = {
|
|
6
|
+
mode: 'SPLIT_PLANE', reason: 'partial local capability',
|
|
7
|
+
source_available: false, toolchains: ['git', 'python3'],
|
|
8
|
+
container_runtime: 'docker', docker_sock: false, egress: { gateway: true },
|
|
9
|
+
build_capable: false, test_capable: false, runtimes: [],
|
|
10
|
+
};
|
|
11
|
+
const STATUS = { contract_ok: false, contract_preflight: { ok: false, reason: 'missing_internal_token' }, stats: {} };
|
|
12
|
+
|
|
13
|
+
const SENSITIVE = ['toolchains', 'container_runtime', 'docker_sock', 'egress', 'source_available'];
|
|
14
|
+
|
|
15
|
+
test('unauthenticated view exposes health only, no topology inventory', () => {
|
|
16
|
+
const v = publicCapabilities(MANIFEST, STATUS, 42);
|
|
17
|
+
assert.equal(v.authenticated, false);
|
|
18
|
+
assert.equal(v.mode, 'SPLIT_PLANE');
|
|
19
|
+
assert.equal(v.contract.ok, false);
|
|
20
|
+
assert.equal(v.contract.preflight_reason, 'missing_internal_token'); // the C1 signal
|
|
21
|
+
assert.equal(v.uptime_s, 42);
|
|
22
|
+
for (const k of SENSITIVE) assert.ok(!(k in v), `${k} must be redacted when unauthenticated`);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('authenticated view adds the client-infra inventory', () => {
|
|
26
|
+
const v = fullCapabilities(MANIFEST, STATUS, 42);
|
|
27
|
+
assert.equal(v.authenticated, true);
|
|
28
|
+
for (const k of SENSITIVE) assert.ok(k in v, `${k} must be present when authenticated`);
|
|
29
|
+
assert.deepEqual(v.toolchains, ['git', 'python3']);
|
|
30
|
+
assert.equal(v.container_runtime, 'docker');
|
|
31
|
+
// health still present
|
|
32
|
+
assert.equal(v.mode, 'SPLIT_PLANE');
|
|
33
|
+
assert.equal(v.contract.ok, false);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('isAuthorized: correct bearer passes, wrong/absent fails', () => {
|
|
37
|
+
const tok = 'AGENT_API_KEY_123';
|
|
38
|
+
assert.equal(isAuthorized({ headers: { authorization: `Bearer ${tok}` } }, tok), true);
|
|
39
|
+
assert.equal(isAuthorized({ headers: { authorization: 'Bearer wrong' } }, tok), false);
|
|
40
|
+
assert.equal(isAuthorized({ headers: {} }, tok), false);
|
|
41
|
+
assert.equal(isAuthorized({ headers: { authorization: tok } }, tok), false); // missing "Bearer "
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('isAuthorized fails closed when no token is configured', () => {
|
|
45
|
+
assert.equal(isAuthorized({ headers: { authorization: 'Bearer anything' } }, null), false);
|
|
46
|
+
assert.equal(isAuthorized({ headers: { authorization: 'Bearer anything' } }, ''), false);
|
|
47
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { buildManifest, deriveMode, computeCapabilityManifest } from '../src/siblings/capabilities.js';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const loadFixture = (name) =>
|
|
10
|
+
JSON.parse(fs.readFileSync(path.join(__dirname, 'fixtures', 'capabilities', name), 'utf-8'));
|
|
11
|
+
|
|
12
|
+
test('pull-only Docker host derives SPLIT_PLANE, not FULL_LOCAL', () => {
|
|
13
|
+
const fx = loadFixture('pull-only-docker.json');
|
|
14
|
+
const m = buildManifest(fx);
|
|
15
|
+
|
|
16
|
+
assert.equal(m.mode, 'SPLIT_PLANE');
|
|
17
|
+
assert.notEqual(m.mode, 'FULL_LOCAL');
|
|
18
|
+
// Evidence the fixture was interpreted as intended:
|
|
19
|
+
assert.equal(m.source_available, false);
|
|
20
|
+
assert.equal(m.build_capable, false);
|
|
21
|
+
assert.equal(m.test_capable, false);
|
|
22
|
+
assert.deepEqual(m.toolchains.sort(), ['git', 'python3']);
|
|
23
|
+
assert.match(m.reason, /no source working tree/);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('full toolchain + source on disk derives FULL_LOCAL', () => {
|
|
27
|
+
const m = buildManifest({
|
|
28
|
+
diag: { tools: {
|
|
29
|
+
git: { installed: true }, java: { installed: true }, maven: { installed: true },
|
|
30
|
+
node: { installed: true }, npm: { installed: true },
|
|
31
|
+
} },
|
|
32
|
+
sourceAvailable: true,
|
|
33
|
+
egress: { gateway: true },
|
|
34
|
+
conclusive: true,
|
|
35
|
+
});
|
|
36
|
+
assert.equal(m.mode, 'FULL_LOCAL');
|
|
37
|
+
assert.equal(m.build_capable, true);
|
|
38
|
+
assert.equal(m.test_capable, true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('inconclusive detection NEVER defaults to FULL_LOCAL', () => {
|
|
42
|
+
const m = buildManifest({
|
|
43
|
+
diag: { tools: { java: { installed: true }, maven: { installed: true }, git: { installed: true } } },
|
|
44
|
+
sourceAvailable: true, // even with "everything", inconclusive must degrade
|
|
45
|
+
egress: { gateway: true },
|
|
46
|
+
conclusive: false,
|
|
47
|
+
});
|
|
48
|
+
assert.equal(m.mode, 'DETECT_ONLY');
|
|
49
|
+
assert.match(m.reason, /inconclusive/);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('no source, no toolchain, no git/egress derives DETECT_ONLY', () => {
|
|
53
|
+
const { mode } = deriveMode({
|
|
54
|
+
source_available: false, build_capable: false, test_capable: false,
|
|
55
|
+
hasGit: false, egress: {}, conclusive: true,
|
|
56
|
+
});
|
|
57
|
+
assert.equal(mode, 'DETECT_ONLY');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('computeCapabilityManifest degrades to DETECT_ONLY when diagnostics throw', async () => {
|
|
61
|
+
const throwingDiagnostics = { diagnose: async () => { throw new Error('boom'); } };
|
|
62
|
+
const m = await computeCapabilityManifest({
|
|
63
|
+
diagnostics: throwingDiagnostics,
|
|
64
|
+
runtimeRegistry: { runtimes: new Map() },
|
|
65
|
+
probes: { sourceAvailable: true, dockerSock: false, containerRuntime: 'docker', egress: { gateway: true } },
|
|
66
|
+
});
|
|
67
|
+
assert.equal(m.mode, 'DETECT_ONLY');
|
|
68
|
+
assert.match(m.reason, /inconclusive/);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('computeCapabilityManifest honours injected probes + diagnostics (pull-only)', async () => {
|
|
72
|
+
const fx = loadFixture('pull-only-docker.json');
|
|
73
|
+
const diagnostics = { diagnose: async () => fx.diag };
|
|
74
|
+
const m = await computeCapabilityManifest({
|
|
75
|
+
diagnostics,
|
|
76
|
+
runtimeRegistry: { runtimes: new Map() },
|
|
77
|
+
probes: {
|
|
78
|
+
sourceAvailable: fx.sourceAvailable,
|
|
79
|
+
dockerSock: fx.dockerSock,
|
|
80
|
+
containerRuntime: fx.containerRuntime,
|
|
81
|
+
egress: fx.egress,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
assert.equal(m.mode, 'SPLIT_PLANE');
|
|
85
|
+
assert.equal(m.container_runtime, 'docker');
|
|
86
|
+
assert.equal(m.docker_sock, false);
|
|
87
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// test/child-env.test.js — model-authored commands must not see the agent's secrets.
|
|
2
|
+
import { test, describe } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { sanitizedChildEnv, isSecretEnvName } from '../src/utils/child-env.js';
|
|
5
|
+
|
|
6
|
+
describe('sanitizedChildEnv', () => {
|
|
7
|
+
test('strips token/secret/password/key variables, keeps the rest and extras', () => {
|
|
8
|
+
const env = {
|
|
9
|
+
PATH: '/usr/bin', HOME: '/home/x', JAVA_HOME: '/opt/java',
|
|
10
|
+
AUTH_TOKEN: 'a', DEEPDEBUG_API_KEY: 'b', AGENT_SHARED_SECRET: 'c', LOCAL_AGENT_TOKEN: 'd',
|
|
11
|
+
GITHUB_TOKEN: 'e', DB_PASSWORD: 'f', AWS_SECRET_ACCESS_KEY: 'g', LOCAL_AGENT_SIGNING_KEY: 'h',
|
|
12
|
+
GIT_TERMINAL_PROMPT: '0', GIT_ASKPASS: 'echo', UNDEFINED: undefined,
|
|
13
|
+
};
|
|
14
|
+
const out = sanitizedChildEnv(env, { FORCE_COLOR: '0' });
|
|
15
|
+
assert.deepEqual(out, { PATH: '/usr/bin', HOME: '/home/x', JAVA_HOME: '/opt/java', GIT_TERMINAL_PROMPT: '0', GIT_ASKPASS: 'echo', FORCE_COLOR: '0' });
|
|
16
|
+
});
|
|
17
|
+
test('isSecretEnvName', () => {
|
|
18
|
+
assert.equal(isSecretEnvName('NPM_TOKEN'), true);
|
|
19
|
+
assert.equal(isSecretEnvName('npm_config_registry'), false);
|
|
20
|
+
assert.equal(isSecretEnvName('GIT_SSH_COMMAND'), false);
|
|
21
|
+
assert.equal(isSecretEnvName('MAVEN_OPTS'), false);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const { applyEnvCompat, LEGACY_MAP } = require('../src/siblings/env-compat.cjs');
|
|
7
|
+
|
|
8
|
+
test('legacy fallback works when canonical is unset', () => {
|
|
9
|
+
const env = { DEEPDEBUG_API_URL: 'https://gw' };
|
|
10
|
+
const warnings = [];
|
|
11
|
+
const mapped = applyEnvCompat(env, (m) => warnings.push(m));
|
|
12
|
+
assert.equal(env.GATEWAY_URL, 'https://gw');
|
|
13
|
+
assert.deepEqual(mapped, ['GATEWAY_URL']);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('canonical wins when both are set (no mapping, no warning)', () => {
|
|
17
|
+
const env = { GATEWAY_URL: 'https://canonical', DEEPDEBUG_API_URL: 'https://legacy' };
|
|
18
|
+
const warnings = [];
|
|
19
|
+
const mapped = applyEnvCompat(env, (m) => warnings.push(m));
|
|
20
|
+
assert.equal(env.GATEWAY_URL, 'https://canonical');
|
|
21
|
+
assert.equal(mapped.length, 0);
|
|
22
|
+
assert.equal(warnings.length, 0);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('warning is emitted exactly once per mapped legacy var, naming it', () => {
|
|
26
|
+
const env = { DEEPDEBUG_API_URL: 'https://gw' };
|
|
27
|
+
const warnings = [];
|
|
28
|
+
applyEnvCompat(env, (m) => warnings.push(m));
|
|
29
|
+
assert.equal(warnings.length, 1);
|
|
30
|
+
assert.match(warnings[0], /DEEPDEBUG_API_URL/);
|
|
31
|
+
assert.match(warnings[0], /GATEWAY_URL/);
|
|
32
|
+
assert.match(warnings[0], /DEPRECATION/);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('neither set is handled (no mapping, no warning)', () => {
|
|
36
|
+
const env = {};
|
|
37
|
+
const warnings = [];
|
|
38
|
+
const mapped = applyEnvCompat(env, (m) => warnings.push(m));
|
|
39
|
+
assert.equal(mapped.length, 0);
|
|
40
|
+
assert.equal(warnings.length, 0);
|
|
41
|
+
assert.equal(env.GATEWAY_URL, undefined);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('empty-string canonical is treated as unset (legacy fills it)', () => {
|
|
45
|
+
const env = { TENANT_ID: '', DEEPDEBUG_TENANT_ID: 't-123' };
|
|
46
|
+
applyEnvCompat(env, () => {});
|
|
47
|
+
assert.equal(env.TENANT_ID, 't-123');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('all three mappings apply independently, one warning each', () => {
|
|
51
|
+
const env = {
|
|
52
|
+
DEEPDEBUG_API_URL: 'https://gw',
|
|
53
|
+
DEEPDEBUG_TENANT_ID: 't-1',
|
|
54
|
+
DEEPDEBUG_WORKSPACE_PATH: '/workspace',
|
|
55
|
+
};
|
|
56
|
+
const warnings = [];
|
|
57
|
+
const mapped = applyEnvCompat(env, (m) => warnings.push(m));
|
|
58
|
+
assert.deepEqual(mapped.sort(), ['GATEWAY_URL', 'TENANT_ID', 'WORKSPACE_ROOT']);
|
|
59
|
+
assert.equal(warnings.length, 3);
|
|
60
|
+
assert.equal(env.GATEWAY_URL, 'https://gw');
|
|
61
|
+
assert.equal(env.TENANT_ID, 't-1');
|
|
62
|
+
assert.equal(env.WORKSPACE_ROOT, '/workspace');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('LEGACY_MAP is the canonical 3-pair mapping', () => {
|
|
66
|
+
assert.deepEqual(LEGACY_MAP, [
|
|
67
|
+
['DEEPDEBUG_API_URL', 'GATEWAY_URL'],
|
|
68
|
+
['DEEPDEBUG_TENANT_ID', 'TENANT_ID'],
|
|
69
|
+
['DEEPDEBUG_WORKSPACE_PATH', 'WORKSPACE_ROOT'],
|
|
70
|
+
]);
|
|
71
|
+
});
|