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.
Files changed (188) hide show
  1. package/.claude/context.md +76 -0
  2. package/.claude/skills/README.md +25 -0
  3. package/.claude/skills/tdd-debugging/SKILL.md +53 -0
  4. package/.claude/skills/tdd-debugging/references/anti-patterns.md +43 -0
  5. package/.claude/skills/tdd-debugging/references/command-reference.md +46 -0
  6. package/.claude/standards/README.md +51 -0
  7. package/.claude/standards/clean-code.md +75 -0
  8. package/.claude/standards/code-review-checklist.md +61 -0
  9. package/.claude/standards/layered-architecture.md +163 -0
  10. package/.claude/standards/node.md +45 -0
  11. package/.claude/standards/security-owasp.md +114 -0
  12. package/.claude/standards/simplicity.md +42 -0
  13. package/.claude/standards/solid.md +64 -0
  14. package/.claude/standards/testing.md +59 -0
  15. package/.cursor/rules/standards.mdc +17 -0
  16. package/.github/workflows/build-byoc-image.yml +315 -0
  17. package/.github/workflows/deploy-gcp.yml +102 -0
  18. package/.github/workflows/npm-publish.yml +69 -8
  19. package/AGENTS.md +21 -0
  20. package/CHANGELOG.md +69 -0
  21. package/CLAUDE.md +13 -0
  22. package/CLAUDE_CODE_AGENT_INFINITE.md +5 -3
  23. package/Dockerfile +4 -0
  24. package/Dockerfile.full +55 -3
  25. package/README.md +81 -0
  26. package/bin/install.js +16 -5
  27. package/cloudbuild-full.yaml +57 -0
  28. package/docker-compose.yml +5 -3
  29. package/docs/OBSERVABILITY.md +164 -0
  30. package/docs/byoc-agent-image.md +70 -0
  31. package/docs/graphify-packaging-plan.md +133 -0
  32. package/docs/graphify-validation-run-2026-10-28.md +243 -0
  33. package/docs/legacy-connectors.md +268 -0
  34. package/docs/releasing.md +43 -0
  35. package/docs/signed-commands.md +163 -0
  36. package/env.example +30 -0
  37. package/helm/Chart.yaml +2 -2
  38. package/helm/templates/deployment.yaml +13 -3
  39. package/helm/templates/networkpolicy.yaml +22 -0
  40. package/helm/templates/secret.yaml +1 -0
  41. package/helm/values.yaml +13 -14
  42. package/mcp-server.js +4 -1
  43. package/package.json +12 -4
  44. package/scripts/sync-fixtures.mjs +246 -0
  45. package/scripts/upgrade-observability-push.sh +227 -0
  46. package/src/adapters/as400/as400-parser.js +12 -0
  47. package/src/adapters/as400/index.js +134 -0
  48. package/src/adapters/cobol/cobol-parser.js +37 -0
  49. package/src/adapters/cobol/index.js +151 -0
  50. package/src/adapters/ibmmq/ibmmq-parser.js +23 -0
  51. package/src/adapters/ibmmq/index.js +137 -0
  52. package/src/adapters/index.js +79 -0
  53. package/src/adapters/oracle-forms/index.js +145 -0
  54. package/src/adapters/oracle-forms/oracle-forms-parser.js +11 -0
  55. package/src/adapters/sap/index.js +146 -0
  56. package/src/adapters/sap/sap-parser.js +41 -0
  57. package/src/ai-engine.js +22 -22
  58. package/src/config/trusted-signing-keys.json +3 -0
  59. package/src/detectors/build-tool-detector.js +50 -0
  60. package/src/detectors/multi-project-detector.js +22 -22
  61. package/src/detectors/service-detector.js +24 -24
  62. package/src/exec-utils.js +26 -4
  63. package/src/git/base-git-provider.js +117 -117
  64. package/src/git/bitbucket-provider.js +2 -2
  65. package/src/git/git-provider-registry.js +18 -18
  66. package/src/git/github-provider.js +13 -13
  67. package/src/git/multi-repo-pr.js +161 -0
  68. package/src/mcp-http-server.js +32 -16
  69. package/src/observability/bundle-files.js +418 -0
  70. package/src/observability/detect.js +151 -0
  71. package/src/observability/provision.js +212 -0
  72. package/src/observability/render-cli.js +59 -0
  73. package/src/observability/routes.js +88 -0
  74. package/src/patch/patch-engine.js +28 -28
  75. package/src/patch-manager.js +85 -85
  76. package/src/patch_bkp.js +14 -14
  77. package/src/ports.js +4 -4
  78. package/src/routes/workspace.route.js +47 -16
  79. package/src/runtimes/base-runtime.js +75 -75
  80. package/src/runtimes/java/gradle-runtime.js +17 -17
  81. package/src/runtimes/java/java-integrations.js +25 -25
  82. package/src/runtimes/java/maven-runtime.js +34 -34
  83. package/src/runtimes/node/node-integrations.js +1 -1
  84. package/src/runtimes/node/npm-runtime.js +14 -14
  85. package/src/runtimes/node/yarn-runtime.js +4 -4
  86. package/src/runtimes/runtime-registry.js +25 -25
  87. package/src/server-local.js +4 -4
  88. package/src/server.js +1412 -335
  89. package/src/siblings/burst-suppressor.js +89 -0
  90. package/src/siblings/capabilities.js +273 -0
  91. package/src/siblings/env-compat.cjs +58 -0
  92. package/src/siblings/incident-forwarder.js +320 -0
  93. package/src/siblings/logger.js +15 -0
  94. package/src/siblings/metrics.js +94 -0
  95. package/src/utils/agent-auth.js +184 -0
  96. package/src/utils/approval-token.js +56 -0
  97. package/src/utils/bind-host.js +29 -0
  98. package/src/utils/branch-refspec.js +98 -0
  99. package/src/utils/child-env.js +34 -0
  100. package/src/utils/environment-diagnostics.js +55 -55
  101. package/src/utils/exec-policy.js +962 -0
  102. package/src/utils/exec-utils.js +15 -15
  103. package/src/utils/file-count.js +46 -0
  104. package/src/utils/fs-utils.js +10 -10
  105. package/src/utils/multi-repo-open.js +132 -0
  106. package/src/utils/open-gate.js +183 -0
  107. package/src/utils/ranged-read.js +65 -0
  108. package/src/utils/request-guards.js +77 -0
  109. package/src/utils/request-signing.js +342 -0
  110. package/src/utils/root-recovery.js +244 -0
  111. package/src/utils/safe-exec-args.js +58 -0
  112. package/src/utils/sandbox.js +182 -0
  113. package/src/utils/search-outcome.js +56 -0
  114. package/src/utils/workspace-root.js +80 -0
  115. package/src/validators/syntax-validator.js +149 -0
  116. package/src/workspace/detect-port.js +16 -16
  117. package/src/workspace/file-reader.js +1 -1
  118. package/src/workspace/process-manager.js +46 -46
  119. package/src/workspace-manager.js +86 -24
  120. package/test/adapters/as400/as400.test.js +121 -0
  121. package/test/adapters/cobol/cobol.test.js +217 -0
  122. package/test/adapters/ibmmq/ibmmq.test.js +122 -0
  123. package/test/adapters/oracle-forms/oracle-forms.test.js +180 -0
  124. package/test/adapters/registry.test.js +108 -0
  125. package/test/adapters/sap/sap.test.js +142 -0
  126. package/test/agent-auth.test.js +194 -0
  127. package/test/bind-host.test.js +26 -0
  128. package/test/branch-refspec.test.js +224 -0
  129. package/test/burst-suppressor.test.js +60 -0
  130. package/test/capabilities-access.test.js +47 -0
  131. package/test/capabilities.test.js +87 -0
  132. package/test/child-env.test.js +23 -0
  133. package/test/env-compat.test.js +71 -0
  134. package/test/exec-policy.test.js +463 -0
  135. package/test/file-count.test.js +64 -0
  136. package/test/incident-forwarder.test.js +231 -0
  137. package/test/multi-repo-open.test.js +180 -0
  138. package/test/multi-repo-pr.test.js +129 -0
  139. package/test/observability-detect.test.js +199 -0
  140. package/test/open-gate.test.js +341 -0
  141. package/test/ranged-read.test.js +60 -0
  142. package/test/request-guards.test.js +91 -0
  143. package/test/request-signing.test.js +284 -0
  144. package/test/root-recovery-sidecar.test.js +171 -0
  145. package/test/root-recovery.test.js +274 -0
  146. package/test/safe-exec-args.test.js +58 -0
  147. package/test/sandbox.test.js +98 -0
  148. package/test/search-outcome.test.js +50 -0
  149. package/test/workspace-root.test.js +64 -0
  150. package/tools/graphify-validation/README.md +92 -0
  151. package/tools/graphify-validation/config/questions.json +31 -0
  152. package/tools/graphify-validation/config/repos.json +9 -0
  153. package/tools/graphify-validation/config/symbols.json +6 -0
  154. package/tools/graphify-validation/fixtures/spring/expected.json +34 -0
  155. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/AppConfig.java +29 -0
  156. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/AuditLogger.java +15 -0
  157. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/Cache.java +7 -0
  158. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/CheckoutService.java +25 -0
  159. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/InMemoryCache.java +18 -0
  160. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/OrderController.java +22 -0
  161. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/PaymentGateway.java +5 -0
  162. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/PaypalGateway.java +11 -0
  163. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/RefundService.java +14 -0
  164. package/tools/graphify-validation/fixtures/spring/src/main/java/com/example/fx/StripeGateway.java +11 -0
  165. package/tools/graphify-validation/lib/affected_vs_rg.py +81 -0
  166. package/tools/graphify-validation/lib/audit_hook/sitecustomize.py +22 -0
  167. package/tools/graphify-validation/lib/graph_metrics.py +96 -0
  168. package/tools/graphify-validation/lib/gv_common.py +130 -0
  169. package/tools/graphify-validation/lib/licenses.py +47 -0
  170. package/tools/graphify-validation/lib/pip_audit_summary.py +18 -0
  171. package/tools/graphify-validation/lib/recall.py +115 -0
  172. package/tools/graphify-validation/lib/report.py +226 -0
  173. package/tools/graphify-validation/lib/run_all.py +237 -0
  174. package/tools/graphify-validation/lib/run_graphify.py +144 -0
  175. package/tools/graphify-validation/lib/rusage_helper.py +17 -0
  176. package/tools/graphify-validation/lib/sample_edges.py +246 -0
  177. package/tools/graphify-validation/lib/spring_fixture.py +81 -0
  178. package/tools/graphify-validation/requirements-py311.lock +508 -0
  179. package/tools/graphify-validation/requirements-tools.in +1 -0
  180. package/tools/graphify-validation/requirements-tools.lock +371 -0
  181. package/tools/graphify-validation/requirements.in +1 -0
  182. package/tools/graphify-validation/requirements.lock +502 -0
  183. package/tools/graphify-validation/run.sh +43 -0
  184. package/tools/graphify-validation/tests/test_harness.py +151 -0
  185. package/cloudbuild-agent-qa.yaml +0 -43
  186. package/cloudbuild-agent-staging.yaml +0 -40
  187. package/cloudbuild.yaml.deprecated +0 -42
  188. package/src/local-agent-source.tar.gz +0 -0
@@ -0,0 +1,102 @@
1
+ # Deploy local-agent (Node) to GCP Cloud Run (visionhammer) via WIF.
2
+ # Manual-only: this repo has no develop branch and several active feature
3
+ # branches, so deploys are triggered on demand from the Actions tab. Choose the
4
+ # environment input. Replaces the insptechai Cloud Build path.
5
+ name: Deploy Local Agent to GCP
6
+
7
+ on:
8
+ workflow_dispatch:
9
+ inputs:
10
+ environment:
11
+ description: 'Target environment'
12
+ required: true
13
+ default: 'qa'
14
+ type: choice
15
+ options: [qa, prod]
16
+
17
+ concurrency:
18
+ group: deploy-local-agent-${{ github.ref }}-${{ inputs.environment }}
19
+ cancel-in-progress: true
20
+
21
+ permissions:
22
+ contents: read
23
+ id-token: write
24
+
25
+ env:
26
+ GCP_PROJECT: visionhammer
27
+ # EU migration (PLANO-MIGRACAO-EU-PROD.md): PROD moves to europe-west1. The
28
+ # region comes from repo variables (PROD_REGION / QA_REGION); today's value
29
+ # stays the default, so nothing changes until the variable is set.
30
+ GCP_REGION: ${{ inputs.environment == 'prod' && (vars.PROD_REGION || 'us-central1') || (vars.QA_REGION || 'us-central1') }}
31
+ WIF_PROVIDER: projects/1009366917257/locations/global/workloadIdentityPools/github-pool/providers/github-provider
32
+ DEPLOYER_SA: github-deployer@visionhammer.iam.gserviceaccount.com
33
+ AR_IMAGE: us-central1-docker.pkg.dev/visionhammer/visionhammer-docker/local-agent
34
+
35
+ jobs:
36
+ deploy:
37
+ runs-on: ubuntu-latest
38
+ environment: ${{ inputs.environment == 'prod' && 'production' || 'qa' }}
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+
42
+ - name: Resolve target (service + tag)
43
+ id: vars
44
+ run: |
45
+ if [ "${{ inputs.environment }}" = "prod" ]; then
46
+ # PROD only from main: a dispatch from a feature branch must not
47
+ # reach production (QA may still deploy any branch on purpose).
48
+ if [ "${GITHUB_REF}" != "refs/heads/main" ]; then
49
+ echo "::error::PROD deploys only from main (got ${GITHUB_REF})."
50
+ exit 1
51
+ fi
52
+ echo "service=deepdebug-local-agent" >> "$GITHUB_OUTPUT"
53
+ echo "tag=prod-${GITHUB_SHA::8}" >> "$GITHUB_OUTPUT"
54
+ echo "traffic=canary" >> "$GITHUB_OUTPUT"
55
+ else
56
+ echo "service=deepdebug-local-agent-qa" >> "$GITHUB_OUTPUT"
57
+ echo "tag=qa-${GITHUB_SHA::8}" >> "$GITHUB_OUTPUT"
58
+ echo "traffic=live" >> "$GITHUB_OUTPUT"
59
+ fi
60
+
61
+ - name: Authenticate to GCP (WIF)
62
+ uses: google-github-actions/auth@v2
63
+ with:
64
+ workload_identity_provider: ${{ env.WIF_PROVIDER }}
65
+ service_account: ${{ env.DEPLOYER_SA }}
66
+
67
+ - name: Set up gcloud
68
+ uses: google-github-actions/setup-gcloud@v2
69
+
70
+ - name: Configure Docker for Artifact Registry
71
+ run: gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
72
+
73
+ - name: Build & push image (multi-stage Node Dockerfile)
74
+ run: |
75
+ IMG="${AR_IMAGE}:${{ steps.vars.outputs.tag }}"
76
+ docker build --platform=linux/amd64 -t "$IMG" .
77
+ docker push "$IMG"
78
+ echo "IMG=$IMG" >> "$GITHUB_ENV"
79
+
80
+ - name: Deploy to Cloud Run (image only; preserves env/secrets)
81
+ run: |
82
+ # PROD lands at 0% traffic behind a tag (canary); verify the tagged
83
+ # URL, then promote with `gcloud run services update-traffic`.
84
+ # QA keeps deploying live. Mirrors vh-api-gateway deploy-gcp.yml.
85
+ #
86
+ # --vpc-egress is pinned: gcloud 572 flipped the template to
87
+ # all-traffic on an image-only update; with no Cloud NAT that cuts
88
+ # the service's internet egress.
89
+ EXTRA=""
90
+ if [ "${{ steps.vars.outputs.traffic }}" = "canary" ]; then
91
+ EXTRA="--no-traffic --tag ${{ steps.vars.outputs.tag }}"
92
+ fi
93
+ gcloud run deploy "${{ steps.vars.outputs.service }}" \
94
+ --image "$IMG" \
95
+ --project "$GCP_PROJECT" \
96
+ --region "$GCP_REGION" \
97
+ --vpc-egress=private-ranges-only \
98
+ $EXTRA \
99
+ --quiet
100
+
101
+ - name: Summary
102
+ run: echo "Deployed **${{ steps.vars.outputs.service }}** with \`$IMG\`" >> "$GITHUB_STEP_SUMMARY"
@@ -7,12 +7,32 @@ on:
7
7
  - 'src/**'
8
8
  - 'package.json'
9
9
  - 'bin/**'
10
+ # Manual publish (e.g. to ship a security fix that landed while publishing was broken).
11
+ workflow_dispatch:
12
+ inputs:
13
+ version:
14
+ description: 'Exact version to publish (e.g. 1.1.0). Empty = automatic patch bump. Must be greater than the highest existing tag and package.json.'
15
+ required: false
16
+ type: string
17
+
18
+ # One publish at a time: two runs would compute the same next version.
19
+ concurrency:
20
+ group: npm-publish
21
+ cancel-in-progress: false
22
+
23
+ # Auth is npm Trusted Publishing (OIDC): no long-lived NPM_TOKEN to expire or leak
24
+ # (security review 2026-10-11, M13). The NPM_TOKEN secret expired and every publish
25
+ # since 2026-04-29 failed with "E404 PUT .../deepdebug-local-agent".
26
+ # One-time setup on npmjs.com (package owner): deepdebug-local-agent -> Settings ->
27
+ # Trusted Publisher -> GitHub Actions: org VISIONHAMMER, repo deepdebug-local-agent,
28
+ # workflow npm-publish.yml.
10
29
 
11
30
  jobs:
12
31
  publish:
13
32
  runs-on: ubuntu-latest
14
33
  permissions:
15
34
  contents: write
35
+ id-token: write # OIDC token for npm Trusted Publishing (+ provenance)
16
36
 
17
37
  steps:
18
38
  - name: Checkout
@@ -24,9 +44,13 @@ jobs:
24
44
  - name: Setup Node.js
25
45
  uses: actions/setup-node@v4
26
46
  with:
27
- node-version: '20'
47
+ node-version: '24'
28
48
  registry-url: 'https://registry.npmjs.org'
29
49
 
50
+ - name: npm with Trusted Publishing support
51
+ # OIDC publishing needs npm >= 11.5.1.
52
+ run: npm install -g npm@^11.5.1 && npm --version
53
+
30
54
  - name: Install dependencies
31
55
  run: npm install
32
56
 
@@ -40,10 +64,41 @@ jobs:
40
64
  git add package-lock.json || true
41
65
  git diff --staged --quiet || git commit -m "chore: update package-lock.json [skip ci]"
42
66
 
43
- - name: Bump patch version
67
+ - name: Bump version (patch, or the exact dispatch input)
68
+ env:
69
+ INPUT_VERSION: ${{ github.event_name == 'workflow_dispatch' && inputs.version || '' }}
44
70
  run: |
45
- npm version patch -m "ci: auto bump to %s [skip ci]"
46
- git push origin main --follow-tags
71
+ # Bump from max(highest existing tag, package.json) so the new tag can
72
+ # never collide with an already-pushed tag (package.json had drifted
73
+ # behind the tags, which made `npm version patch` fail with
74
+ # "tag vX.Y.Z already exists" on every push to main).
75
+ git fetch --tags --quiet
76
+ LATEST_TAG="$(git tag --sort=-v:refname | head -1)"
77
+ LATEST_TAG="${LATEST_TAG#v}"
78
+ PKG="$(node -p "require('./package.json').version")"
79
+ BASE="$(printf '%s\n%s\n' "${LATEST_TAG:-0.0.0}" "$PKG" | sort -V | tail -1)"
80
+ # Compute the next patch version up front and bump in ONE `npm version`
81
+ # call. A separate `npm version "$BASE" --no-git-tag-version` rewrites
82
+ # package.json/package-lock.json whenever the tag is ahead of
83
+ # package.json, leaving the tree dirty so the following
84
+ # `npm version patch` aborts with "Git working directory not clean".
85
+ NEXT="$(node -e 'const [a,b,c]=process.argv[1].split(".").map(Number); console.log(`${a}.${b}.${c+1}`)' "$BASE")"
86
+ # Release override (workflow_dispatch input `version`, e.g. 1.1.0): used
87
+ # as-is instead of the patch bump, so a minor/major release is not turned
88
+ # into 1.1.1 by the automatic bump. Read from env, never interpolated.
89
+ if [ -n "${INPUT_VERSION}" ]; then
90
+ if ! printf '%s' "$INPUT_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
91
+ echo "::error::version input '$INPUT_VERSION' is not X.Y.Z"; exit 1
92
+ fi
93
+ if [ "$(printf '%s\n%s\n' "$BASE" "$INPUT_VERSION" | sort -V | tail -1)" != "$INPUT_VERSION" ] || [ "$INPUT_VERSION" = "$BASE" ]; then
94
+ echo "::error::version input $INPUT_VERSION must be greater than $BASE (highest existing tag/package.json)"; exit 1
95
+ fi
96
+ NEXT="$INPUT_VERSION"
97
+ fi
98
+ # Commit + tag LOCALLY only. They are pushed after a successful publish, so a
99
+ # failed publish no longer burns a version (1.0.24..1.0.38 were tagged but
100
+ # never published while the token was expired).
101
+ npm version "$NEXT" -m "ci: auto bump to %s [skip ci]"
47
102
 
48
103
  - name: Check if version exists
49
104
  id: version_check
@@ -59,14 +114,20 @@ jobs:
59
114
  echo "Version $PACKAGE_VERSION is new"
60
115
  echo "exists=false" >> $GITHUB_OUTPUT
61
116
  fi
62
- env:
63
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
64
117
 
65
118
  - name: Publish to NPM
66
119
  if: steps.version_check.outputs.exists == 'false'
120
+ # No --provenance: this repository is private and npm rejects provenance
121
+ # statements for private source repositories (E422 "Unsupported GitHub Actions
122
+ # source repository visibility"). Trusted Publishing (OIDC) still authenticates
123
+ # the publish. Re-add --provenance if the repository ever becomes public.
67
124
  run: npm publish --access public
68
- env:
69
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
125
+
126
+ - name: Push version bump and tag
127
+ run: |
128
+ # main may have moved while we published: replay the bump commit on top.
129
+ git pull --rebase origin main
130
+ git push origin main --follow-tags
70
131
 
71
132
  - name: Skip publish (version exists)
72
133
  if: steps.version_check.outputs.exists == 'true'
package/AGENTS.md ADDED
@@ -0,0 +1,21 @@
1
+ # AGENTS.md - deepdebug-local-agent
2
+
3
+ Instructions for AI coding agents (Codex, Cursor, Copilot, Gemini, Claude Code and others).
4
+ Claude Code also reads `CLAUDE.md`; the same rules apply to every agent.
5
+
6
+ ## Read first
7
+
8
+ 1. `.claude/context.md`: what this repo is in the VisionHammer v2 architecture, its
9
+ neighbours, where things live, how to run, test, deploy and roll back, and the gotchas.
10
+ 2. `.claude/standards/README.md`, then the files it lists: `clean-code.md`, `solid.md`,
11
+ `simplicity.md`, `layered-architecture.md`, `security-owasp.md`, `testing.md`,
12
+ `code-review-checklist.md` and `node.md`.
13
+ 3. `CLAUDE.md`: repo rules. They win over the generic standards.
14
+
15
+ ## Always
16
+
17
+ - PRs target `main` (publishes the npm package); Cloud Run deploy is manual.
18
+ - Runs inside customer infrastructure: argument-array process execution, paths confined to the workspace, no LLM calls, no secrets in logs.
19
+ - Never print, log or commit secrets. Provider keys exist only in vh-litellm.
20
+ - Verify on the deployed artefact (curl, revision logs, bundle grep), not only on the diff.
21
+ - Small PRs with one intent each. Open PRs; a human merges them.
package/CHANGELOG.md ADDED
@@ -0,0 +1,69 @@
1
+ # Changelog
2
+
3
+ ## 1.1.0 (prepared, not yet published)
4
+
5
+ Security release (security review 2026-10-11, C1 and H4). The agent now fails
6
+ closed by default. Read "Upgrade" before rolling it out to agents whose
7
+ platform side does not sign commands yet.
8
+
9
+ ### Changed defaults
10
+
11
+ - **Signed commands: `enforce` by default.** `LOCAL_AGENT_SIGNATURE_MODE`
12
+ defaults to `enforce` (was `warn`) and an unrecognised value also means
13
+ `enforce`. A request without a valid `X-VH-*` signature is refused.
14
+ - **Loopback bind by default.** Without `LOCAL_AGENT_BIND_HOST`, the agent binds
15
+ `127.0.0.1` unless a token (`LOCAL_AGENT_TOKEN` / `AGENT_SHARED_SECRET`) or
16
+ Cloud Run is present (or `LOCAL_AGENT_AUTH` is `compat`/`off`).
17
+ - **Helm: token required, NetworkPolicy deny-ingress.** `config.agentToken`
18
+ is required (rendered as `LOCAL_AGENT_TOKEN`; `helm template` fails without
19
+ it). The chart ships a NetworkPolicy that denies all ingress except the peers
20
+ listed in `networkPolicy.allowFrom` (default: none; the agent talks to the
21
+ platform over an outbound tunnel). Chart `version`/`appVersion` are now 1.1.0.
22
+ - **H4: no shell for request text.** `/workspace/search` runs grep through
23
+ `execFile` with an argv list, `/workspace/build-push` validates the workspace
24
+ id and runs tar through `execFile`, and `/setup/run-auth-command` accepts only
25
+ allowlisted interactive logins, spawned without a shell.
26
+ - Already in 1.0.35 and unchanged here: exec policy `enforce`, `LOCAL_AGENT_AUTH`
27
+ loopback/token perimeter (`docs/signed-commands.md`).
28
+
29
+ ### Compatibility with the `X-VH-*` signature
30
+
31
+ Protocol v1 is unchanged (`VH-AGENT-SIG-V1`, Ed25519 over method, path, body
32
+ hash, tenant, workspace, timestamp, nonce; headers `X-VH-Key-Id`,
33
+ `X-VH-Timestamp`, `X-VH-Nonce`, `X-VH-Tenant-Id`, `X-VH-Workspace-Id`,
34
+ `X-VH-Signature`). The trusted key id is `vh-2026-09`; rotation is
35
+ unchanged. A platform that already signs (vh-api-gateway, visionhammer-agents)
36
+ needs no change. `X-Agent-Token` stays as the second factor.
37
+
38
+ ### Build and release
39
+
40
+ - Release procedure for an exact version without the automatic patch bump:
41
+ `docs/releasing.md` (`npm-publish.yml` gains a `version` dispatch input).
42
+ - Optional cosign (keyless) signature, SPDX SBOM and SLSA v1 provenance for the
43
+ `local-agent-full` image, behind `supply_chain` / `BYOC_SUPPLY_CHAIN`
44
+ (off by default; `docs/byoc-agent-image.md`).
45
+ - Helm `values.yaml`: removed a dead duplicate `networkPolicy` block (the later
46
+ key already won; no behaviour change).
47
+
48
+ ### Upgrade
49
+
50
+ 1. Make sure the platform signs requests to this agent (gateway and agents with
51
+ the signing key) before upgrading an agent in production.
52
+ 2. Optional soak: set `LOCAL_AGENT_SIGNATURE_MODE=warn` on the agent, watch
53
+ `[agent-sig] WARN` and `[exec-policy] WARN`, then remove the override.
54
+ 3. Helm: set `config.agentToken` (`--set-file` or an existing secret flow) and,
55
+ if a caller must reach the pod, list it in `networkPolicy.allowFrom`.
56
+ 4. Agents reached directly over the network need a token or
57
+ `LOCAL_AGENT_BIND_HOST`; otherwise they only answer on `127.0.0.1`.
58
+ 5. BYOC: pin the new image as `local-agent-full:1.1.0@sha256:<digest>` in the
59
+ gateway (`BYOC_AGENT_IMAGE`). Existing agents keep their image until
60
+ re-provisioned.
61
+
62
+ ### Rollback
63
+
64
+ - Per agent, without redeploy of the platform: `LOCAL_AGENT_SIGNATURE_MODE=warn`
65
+ (or `off`), `LOCAL_AGENT_BIND_HOST=0.0.0.0` together with a token,
66
+ `networkPolicy.enabled=false` in Helm. These are explicit, logged opt-outs.
67
+ - Version rollback: npm `npm i deepdebug-local-agent@1.0.38`; BYOC image: repin
68
+ the previous `:<semver>@sha256:` (tags are immutable, nothing floats).
69
+ Note 1.0.38 still defaults signatures to `warn` and binds more widely.
package/CLAUDE.md ADDED
@@ -0,0 +1,13 @@
1
+ # CLAUDE.md - deepdebug-local-agent
2
+
3
+ ## Read first
4
+ 1. `.claude/context.md`: what this agent is in the v2 architecture (the platform's hands
5
+ in customer infrastructure), its neighbours, run/test, publish/deploy and gotchas.
6
+ 2. `.claude/standards/`: shared VisionHammer standards (clean code, SOLID, OWASP security,
7
+ layers, simplicity, testing, review checklist, `node.md`).
8
+ 3. `README.md`: features, legacy connectors, configuration.
9
+
10
+ Non-negotiables: no LLM calls and no provider keys here; exec with argument arrays only;
11
+ paths confined to the workspace; never log secrets or raw customer log payloads beyond
12
+ what an incident needs; PRs target `main` (merging publishes the npm package).
13
+ Personal, uncommitted notes go in `CLAUDE.local.md` (gitignored).
@@ -13,7 +13,9 @@ AGENT="https://deepdebug-local-agent-qa-575662086506.us-central1.run.app"
13
13
  GATEWAY="https://deepdebug-gateway-qa-575662086506.us-central1.run.app"
14
14
  GCP_CLIENT="gen-lang-client-0961289539"
15
15
  SA_EMAIL="deepdebug-agent@${GCP_CLIENT}.iam.gserviceaccount.com"
16
- PG="PGPASSWORD='DeepDebugQA@2026' psql -h 35.224.155.29 -U deepdebug -d deepdebug"
16
+ # DB password: never inline it. Read it from Secret Manager (pg-password-qa).
17
+ PG_PASSWORD="$(gcloud secrets versions access latest --secret=pg-password-qa --project=visionhammer)"
18
+ PG="PGPASSWORD=\"$PG_PASSWORD\" psql -h 35.224.155.29 -U deepdebug -d deepdebug"
17
19
  WS_ID="b040f1ae-5f3c-4612-9ce1-0b18a5aea303"
18
20
 
19
21
  log() { echo "[$(date '+%H:%M:%S')] $1"; }
@@ -517,7 +519,7 @@ while [ "$AGENT_DONE" = "false" ]; do
517
519
 
518
520
  # ─── CHECK A3: Clone com token real ───
519
521
  log "CHECK A3: Clone com token real"
520
- GIT_TOKEN=$(PGPASSWORD='DeepDebugQA@2026' psql -h 35.224.155.29 -U deepdebug -d deepdebug -t -c \
522
+ GIT_TOKEN=$(PGPASSWORD="$PG_PASSWORD" psql -h 35.224.155.29 -U deepdebug -d deepdebug -t -c \
521
523
  "SELECT t.access_token FROM oauth_tokens t JOIN tenants tn ON tn.id::text=t.tenant_id WHERE t.provider='GITHUB' LIMIT 1;" \
522
524
  | tr -d ' \n')
523
525
 
@@ -537,7 +539,7 @@ while [ "$AGENT_DONE" = "false" ]; do
537
539
 
538
540
  # ─── CHECK A4: /workspace/build-push com SA real ───
539
541
  log "CHECK A4: build-push com SA key real"
540
- SA_KEY_ENC=$(PGPASSWORD='DeepDebugQA@2026' psql -h 35.224.155.29 -U deepdebug -d deepdebug -t -c \
542
+ SA_KEY_ENC=$(PGPASSWORD="$PG_PASSWORD" psql -h 35.224.155.29 -U deepdebug -d deepdebug -t -c \
541
543
  "SELECT service_account_key FROM oauth_tokens WHERE tenant_id='63922779-7321-4e79-b0f0-63890cd0d98e' AND provider='GCP';" \
542
544
  | tr -d ' \n')
543
545
  ENC_KEY=$(gcloud secrets versions access latest --secret=encryption-key-qa --project=insptechai 2>/dev/null)
package/Dockerfile CHANGED
@@ -120,6 +120,10 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
120
120
  ENV NODE_ENV=production
121
121
  ENV PORT=5055
122
122
  ENV WORKSPACES_MOUNT=/mnt/workspaces
123
+ # env-compat preload: maps legacy env names (DEEPDEBUG_API_URL/TENANT_ID/
124
+ # WORKSPACE_PATH) to the canonical GATEWAY_URL/TENANT_ID/WORKSPACE_ROOT before
125
+ # server.js is evaluated. --require (CJS) runs before the ESM entry module.
126
+ ENV NODE_OPTIONS="--require /app/src/siblings/env-compat.cjs"
123
127
 
124
128
  EXPOSE 5055
125
129
 
package/Dockerfile.full CHANGED
@@ -33,8 +33,51 @@ RUN apt-get update && \
33
33
  ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
34
34
  ENV PATH=$PATH:$JAVA_HOME/bin:/usr/share/maven/bin
35
35
 
36
+ # Swift 5.10 toolchain — enables `swift build` for SwiftPM projects and
37
+ # `swiftc -typecheck` / `swiftc -parse` for iOS/Xcode projects whose imports
38
+ # Linux can resolve. Apple-framework imports (UIKit/SwiftUI/Combine/etc.)
39
+ # still need macOS — handled gracefully in src/exec-utils.js by falling
40
+ # back to `swiftc -parse` (syntax-only validation).
41
+ # Image-size cost: ~1.5 GB decompressed. Accepted for the BYOC full-tools
42
+ # agent image; not pulled by the lean Cloud Run QA path (uses Dockerfile).
43
+ # Note on platform mismatch: base is node:20-slim (Debian 12/bookworm), but
44
+ # swift.org does not publish a debian12 tarball for 5.10. Ubuntu 22.04 build
45
+ # runs cleanly on Debian 12 (newer glibc is backward-compatible with the
46
+ # ubuntu2204 binary), so we install the ubuntu22.04 tarball + Debian 12
47
+ # runtime deps. swift --version smoke-test catches any glibc mismatch at
48
+ # build time.
49
+ ARG SWIFT_VERSION=5.10
50
+ ARG SWIFT_PLATFORM=ubuntu22.04
51
+ ARG SWIFT_PLATFORM_DIR=ubuntu2204
52
+ RUN apt-get update && \
53
+ apt-get install -y --no-install-recommends \
54
+ binutils \
55
+ libc6-dev \
56
+ libcurl4-openssl-dev \
57
+ libedit2 \
58
+ libgcc-12-dev \
59
+ libncurses6 \
60
+ libpython3.11 \
61
+ libsqlite3-0 \
62
+ libstdc++-12-dev \
63
+ libxml2-dev \
64
+ libz3-dev \
65
+ pkg-config \
66
+ tzdata \
67
+ uuid-dev \
68
+ zlib1g-dev \
69
+ && rm -rf /var/lib/apt/lists/* \
70
+ && cd /tmp \
71
+ && curl -fsSL "https://download.swift.org/swift-${SWIFT_VERSION}-release/${SWIFT_PLATFORM_DIR}/swift-${SWIFT_VERSION}-RELEASE/swift-${SWIFT_VERSION}-RELEASE-${SWIFT_PLATFORM}.tar.gz" -o swift.tar.gz \
72
+ && tar xzf swift.tar.gz \
73
+ && mv "swift-${SWIFT_VERSION}-RELEASE-${SWIFT_PLATFORM}" /opt/swift \
74
+ && rm swift.tar.gz \
75
+ && ln -s /opt/swift/usr/bin/swift /usr/local/bin/swift \
76
+ && ln -s /opt/swift/usr/bin/swiftc /usr/local/bin/swiftc \
77
+ && swift --version
78
+
36
79
  # Verify all tools are installed
37
- RUN java -version && mvn -version && node -v && git --version
80
+ RUN java -version && mvn -version && node -v && git --version && swift --version
38
81
 
39
82
  # Git safe directory for NFS mounted workspaces
40
83
  RUN git config --global --add safe.directory '*'
@@ -55,9 +98,18 @@ RUN mkdir -p /home/deepdebug/.m2 && chown -R deepdebug:deepdebug /home/deepdebug
55
98
  # Workspace mount point
56
99
  RUN mkdir -p /mnt/workspaces && chown -R deepdebug:deepdebug /mnt/workspaces
57
100
 
58
- EXPOSE 8080
101
+ # Port aligned to 5055 to match Dockerfile, docker-compose, Helm and the
102
+ # server.js default (PORT || LOCAL_AGENT_PORT || 5055). 8080 here conflicted.
103
+ EXPOSE 5055
59
104
 
60
105
  ENV NODE_ENV=production
61
- ENV PORT=8080
106
+ ENV PORT=5055
107
+ # env-compat preload (see Dockerfile): legacy->canonical env mapping before eval.
108
+ ENV NODE_OPTIONS="--require /app/src/siblings/env-compat.cjs"
109
+
110
+ # SECURITY (2026-10-11): the slim Dockerfile already drops to the unprivileged
111
+ # user; this image ran everything (model-authored commands included) as root.
112
+ RUN su deepdebug -c "git config --global --add safe.directory '*'"
113
+ USER deepdebug
62
114
 
63
115
  CMD ["node", "src/server.js"]
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # DeepDebug Local Agent
2
+
3
+ AI-powered on-prem ingestion arm of the VisionHammer / DeepDebug pipeline. The
4
+ local agent watches application logs, surfaces incidents, and forwards them to
5
+ the gateway for downstream analysis.
6
+
7
+ - **Runtime:** Node.js 18+ (pure ESM, `"type": "module"`)
8
+ - **Test runner:** `node:test` (Node built-in)
9
+ - **Distribution:** `npm install` for development; `pkg`-bundled binaries for
10
+ production install (`npm run build:all`)
11
+ - **Package:** `deepdebug-local-agent@1.0.21`
12
+
13
+ ## Quick start
14
+
15
+ ```bash
16
+ npm install
17
+ npm test # runs node --test (52 tests across adapters + registry)
18
+ npm start # boots the agent (default port 5055; MCP bridge on 5056)
19
+ ```
20
+
21
+ Configuration lives in `~/.deepdebug/config.json` and via env vars (`PORT`,
22
+ `MCP_PORT`, `GATEWAY_URL`, `DEEPDEBUG_API_KEY`, `TENANT_ID`,
23
+ `DISABLE_WS_TUNNEL`, `LEGACY_STACKS`).
24
+
25
+ Companion docs:
26
+
27
+ - [QUICKSTART.md](./docs/QUICKSTART.md) — end-user install + first-run
28
+ - [ENTERPRISE_DEPLOYMENT_GUIDE.md](./docs/ENTERPRISE_DEPLOYMENT_GUIDE.md)
29
+ - [SECURITY_WHITEPAPER.md](./docs/SECURITY_WHITEPAPER.md)
30
+ - [docs/legacy-connectors.md](./docs/legacy-connectors.md) — **Phase 2** legacy
31
+ stack ingestion reference
32
+
33
+ ## Features
34
+
35
+ - Real-time application log ingestion via `processManager.on('log', ...)`
36
+ - AI-driven patch generation (`AIVibeCodingEngine`) wired to the gateway
37
+ - Workspace-scoped operations via the workspace manager
38
+ - Backup / restore with disk-indexed history
39
+ - WebSocket reverse tunnel to the gateway (`startWebSocketTunnel`)
40
+ - MCP HTTP bridge (`startMCPHttpServer` on port 5056)
41
+ - **Legacy connectors** — five EventEmitter adapters for legacy on-prem stacks
42
+ (see below)
43
+
44
+ ## Legacy connectors
45
+
46
+ DeepDebug Local Agent ships five EventEmitter adapters for legacy on-prem
47
+ stacks, behind a single `LEGACY_STACKS` env var:
48
+
49
+ - **SAP** (`src/adapters/sap/`) — watches SAP NetWeaver `dev_w*` work-process
50
+ traces + `SLOG*` system logs
51
+ - **IBM MQ** (`src/adapters/ibmmq/`) — watches `AMQERR0[1-3].LOG` files
52
+ - **AS/400** (`src/adapters/as400/`) — polls DSPLOG via SSH with auto-reconnect
53
+ - **Oracle Forms** (`src/adapters/oracle-forms/`) — watches `*.trc` trace files
54
+ (Latin-1 tolerant)
55
+ - **COBOL/Mainframe** (`src/adapters/cobol/`) — watches JES2 spool exports
56
+ (CRLF + 80-col tolerant)
57
+
58
+ Each adapter emits `error` events with a frozen 6-key shape:
59
+ `{adapter, errorCode, file, message, source, timestamp}`.
60
+
61
+ To enable: set `LEGACY_STACKS=sap,cobol` (comma-separated subset of
62
+ `sap,ibmmq,as400,oracle-forms,cobol`) in the agent's environment. When unset,
63
+ the adapters are not loaded and the local-agent boot path is byte-for-byte
64
+ unchanged.
65
+
66
+ Full configuration + troubleshooting reference:
67
+ [docs/legacy-connectors.md](./docs/legacy-connectors.md).
68
+
69
+ ## Development
70
+
71
+ ```bash
72
+ npm test # full suite (52 tests)
73
+ npm run sync-fixtures # refresh test/fixtures/<stack>/ from example repos
74
+ # (requires ~/.config/visionhammer/github-pat)
75
+ npm run lint # eslint src/
76
+ npm run dev # NODE_ENV=development node src/server.js
77
+ ```
78
+
79
+ ## License
80
+
81
+ Proprietary — InspTech AI.
package/bin/install.js CHANGED
@@ -17,7 +17,7 @@ import fs from 'fs';
17
17
  import path from 'path';
18
18
  import os from 'os';
19
19
  import crypto from 'crypto';
20
- import { spawn, execSync } from 'child_process';
20
+ import { spawn, execSync, execFileSync } from 'child_process';
21
21
  import readline from 'readline';
22
22
 
23
23
  // ============================================
@@ -26,7 +26,14 @@ import readline from 'readline';
26
26
  const CONFIG_DIR = path.join(os.homedir(), '.deepdebug');
27
27
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
28
28
  const MACHINE_ID_FILE = path.join(CONFIG_DIR, 'machine-id');
29
- const API_BASE_URL = process.env.DEEPDEBUG_API_URL || 'https://deepdebug-gateway-lszyf7c4ia-uc.a.run.app';
29
+ // Single-sourced default, consistent with docker-compose / Helm / env.example /
30
+ // canonical prod host. Verified against DNS + Cloud Run domain mapping:
31
+ // api.visionhammer.io -> ghs.googlehosted.com (Cloud Run mapping for the prod
32
+ // deepdebug-gateway service). api.deepdebug.ai has NO DNS record and did not
33
+ // answer during the audit, so it must NOT be the default. The previous default
34
+ // was also a stale, now-dead QA run.app hash (deepdebug-gateway-lszyf7c4ia).
35
+ // Override per environment with DEEPDEBUG_API_URL.
36
+ const API_BASE_URL = process.env.DEEPDEBUG_API_URL || 'https://api.visionhammer.io';
30
37
  const DOCKER_IMAGE = 'williambella/deepdebug-local-agent:latest';
31
38
 
32
39
  // ============================================
@@ -421,7 +428,7 @@ function startDockerAgent(config) {
421
428
  } catch {}
422
429
 
423
430
  logInfo('Pulling latest DeepDebug Local Agent image...');
424
- execSync(`docker pull ${DOCKER_IMAGE}`, { stdio: 'inherit' });
431
+ execFileSync('docker', ['pull', DOCKER_IMAGE], { stdio: 'inherit' });
425
432
 
426
433
  // Prepare paths for Docker
427
434
  let configMount = CONFIG_DIR;
@@ -436,7 +443,9 @@ function startDockerAgent(config) {
436
443
  const dockerArgs = [
437
444
  'run', '-d',
438
445
  '--name', 'deepdebug-agent',
439
- '-p', '5055:5055',
446
+ // SECURITY: publish on loopback only. '5055:5055' exposed the agent
447
+ // (shell exec + workspace write API) on every host interface.
448
+ '-p', '127.0.0.1:5055:5055',
440
449
  '-v', `${configMount}:/home/deepdebug/.deepdebug:ro`,
441
450
  '-v', `${projectsMount}:/workspace:rw`,
442
451
  '-e', `GATEWAY_URL=${config.gatewayUrl}`,
@@ -448,7 +457,9 @@ function startDockerAgent(config) {
448
457
  ];
449
458
 
450
459
  logInfo('Starting Docker container with workspace mounted...');
451
- execSync(`docker ${dockerArgs.join(' ')}`, { stdio: 'inherit' });
460
+ // execFileSync (no shell): paths/config values are passed verbatim, so a
461
+ // projects path with spaces or shell metacharacters cannot break out.
462
+ execFileSync('docker', dockerArgs, { stdio: 'inherit' });
452
463
  logSuccess('DeepDebug Local Agent started successfully!');
453
464
  return true;
454
465
  } catch (error) {
@@ -0,0 +1,57 @@
1
+ # Manual fallback for the BYOC "full" agent image (the primary path is the
2
+ # GitHub Actions workflow .github/workflows/build-byoc-image.yml).
3
+ # Replaces cloudbuild-full-v3.yaml, which pushed a floating :v3 tag to the
4
+ # deactivated insptechai project.
5
+ #
6
+ # Usage (from a clean checkout of main; both substitutions are required):
7
+ # gcloud builds submit --project visionhammer --config cloudbuild-full.yaml \
8
+ # --substitutions=_VERSION=1.0.31,_GIT_SHA=$(git rev-parse HEAD) .
9
+ #
10
+ # Pushes :<_VERSION> and :<_GIT_SHA> — never a floating tag. Pin the gateway to
11
+ # the resulting digest (deepdebug.byoc.agent-image in vh-api-gateway).
12
+ substitutions:
13
+ _IMAGE: 'us-central1-docker.pkg.dev/visionhammer/visionhammer-docker-public/local-agent-full'
14
+ _VERSION: ''
15
+ _GIT_SHA: ''
16
+
17
+ steps:
18
+ - id: guard
19
+ name: 'gcr.io/cloud-builders/gcloud'
20
+ entrypoint: 'bash'
21
+ args:
22
+ - '-c'
23
+ - |
24
+ set -euo pipefail
25
+ [ -n "${_VERSION}" ] && [ -n "${_GIT_SHA}" ] || { echo "_VERSION and _GIT_SHA are required"; exit 1; }
26
+ if gcloud artifacts docker images describe "${_IMAGE}:${_VERSION}" >/dev/null 2>&1; then
27
+ echo "${_IMAGE}:${_VERSION} already exists; bump the version instead of overwriting"; exit 1
28
+ fi
29
+
30
+ - id: build
31
+ name: 'gcr.io/cloud-builders/docker'
32
+ args:
33
+ - 'build'
34
+ - '--platform=linux/amd64'
35
+ - '-f'
36
+ - 'Dockerfile.full'
37
+ - '--label'
38
+ - 'org.opencontainers.image.revision=${_GIT_SHA}'
39
+ - '--label'
40
+ - 'org.opencontainers.image.version=${_VERSION}'
41
+ - '-t'
42
+ - '${_IMAGE}:${_VERSION}'
43
+ - '-t'
44
+ - '${_IMAGE}:${_GIT_SHA}'
45
+ - '.'
46
+ timeout: '3000s'
47
+
48
+ images:
49
+ - '${_IMAGE}:${_VERSION}'
50
+ - '${_IMAGE}:${_GIT_SHA}'
51
+
52
+ options:
53
+ logging: CLOUD_LOGGING_ONLY
54
+ machineType: 'E2_HIGHCPU_32'
55
+ diskSizeGb: 50
56
+
57
+ timeout: '3600s'
@@ -63,9 +63,11 @@ services:
63
63
  environment:
64
64
  - NODE_ENV=production
65
65
  - PORT=5055
66
- - DEEPDEBUG_API_URL=${DEEPDEBUG_API_URL:-https://api.deepdebug.ai}
67
- - DEEPDEBUG_TENANT_ID=${DEEPDEBUG_TENANT_ID}
68
- - DEEPDEBUG_WORKSPACE_PATH=/workspace
66
+ # Names aligned to what src/server.js actually reads (server.js is frozen):
67
+ # GATEWAY_URL (server.js:73), TENANT_ID (:7505), WORKSPACE_ROOT (:637).
68
+ - GATEWAY_URL=${GATEWAY_URL:-https://api.deepdebug.ai}
69
+ - TENANT_ID=${TENANT_ID}
70
+ - WORKSPACE_ROOT=/workspace
69
71
  - LOG_LEVEL=${LOG_LEVEL:-info}
70
72
 
71
73
  # ─────────────────────────────────────────