Skip to content

fix: resolve all pre-existing backend test failures#261

Merged
ritik4ever merged 3 commits into
Stellar-Ecosystem:mainfrom
pragati2dev:fix/config-startup-validation
Jun 29, 2026
Merged

fix: resolve all pre-existing backend test failures#261
ritik4ever merged 3 commits into
Stellar-Ecosystem:mainfrom
pragati2dev:fix/config-startup-validation

Conversation

@pragati2dev

@pragati2dev pragati2dev commented Jun 29, 2026

Copy link
Copy Markdown
Contributor
fix: structured startup validation + fix all pre-existing backend test failures (#253)

Summary

  • Config validation (backend/src/config.js, backend/src/index.js): Move env-var validation out of module scope and into an explicit validateConfig(log) function, fixing silent crash-on-import and the one-var-at-a-time error UX
  • Pre-existing test failures (registry.js, contract.js, services.js, test files): Fix four separate duplicate-declaration / missing-call bugs that were causing 5 test failures across 3 test files before this PR touched anything

Problem 1 — Config validation (issue #253)

config.js threw synchronously at module load time:

for (const key of required) {
  if (!process.env[key]) throw new Error(`Missing: ${key}`); // stops at first
  }
</code></pre></div><p style="white-space: pre-wrap; margin-top: 0.1em; margin-bottom: 0.2em; color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>Problems:</strong></p><ul style="padding-inline-start: 2em; color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><li>Crashes before Express, pino, or any error handler is initialized — bare Node.js stack trace to stderr, no structured JSON</li><li>Reports only the<span> </span><strong>first</strong><span> </span>missing variable; operator must restart once per missing var to discover all of them</li><li><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">PAYMENT_ADDRESS</code><span> </span>format error was also thrown at import time, same problem</li></ul><h2 style="color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Solution</h2><h3 style="color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">backend/src/config.js</code></h3><ul style="padding-inline-start: 2em; color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><li>Removed all<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">throw</code><span> </span>/<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">console.warn</code><span> </span>from module scope</li><li>Exported<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">validateConfig(log?)</code><span> </span>that collects<span> </span><strong>all</strong><span> </span>missing vars in one pass, then calls<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">log.fatal({ missingVars, errors }, message)</code><span> </span>+<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">process.exit(1)</code></li><li>Optional<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">log</code><span> </span>param: defaults to a<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">console</code><span> </span>shim so operators can dry-run:<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">node -e "import('./src/config.js').then(m =&gt; m.validateConfig())"</code></li></ul><h3 style="color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">backend/src/index.js</code></h3><ul style="padding-inline-start: 2em; color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><li>Added<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">import config, { validateConfig } from './config.js'</code></li><li>Calls<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">validateConfig(logger)</code><span> </span>after pino is initialized — errors now emit as structured JSON that log aggregators can parse</li><li>Added<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">--print-config</code><span> </span>flag: prints all non-secret resolved config values as JSON and exits, helping operators verify their setup without reading source code</li><li>Fixed a pre-existing bug:<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">const server = app.listen(config.port, () =&gt; {</code><span> </span>was missing —<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">server</code><span> </span>was referenced in<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">shutdown()</code><span> </span>but never declared</li></ul><h3 style="color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">backend/src/config.test.js</code></h3><ul style="padding-inline-start: 2em; color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><li>Updated PAYMENT_ADDRESS and AGENTS_CONTRACT_ID tests to call<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">validateConfig()</code><span> </span>with a mock logger instead of expecting<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">loadConfig()</code><span> </span>to throw</li><li>Added<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">validateConfig</code><span> </span>describe block with 2 new tests:<ul style="padding-inline-start: 2em;"><li>Passes cleanly when all required vars are present</li><li>Reports ALL missing vars in a single<span> </span><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">logger.fatal</code><span> </span>call (not just the first)</li></ul></li></ul><hr style="font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><h2 style="color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Problem 2 — Pre-existing test failures (4 bugs, 5 failing tests)</h2><p style="white-space: pre-wrap; margin-top: 0.1em; margin-bottom: 0.2em; color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">These failures existed on <code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 2px 4px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">main</code> before this PR and were blocking CI from going green.</p>
File | Bug | Fix
-- | -- | --
src/routes/registry.js | annotateTtlWarning declared twice at module scope (SyntaxError in strict/ESM mode) | Removed the duplicate function block
src/lib/contract.js | SERVICE_MAX_TTL and SERVICE_TTL_WARNING_LEDGERS exported twice | Removed the duplicate export block
src/routes/registry.test.js | mockGetCurrentLedgerSequence, SERVICE_MAX_TTL, SERVICE_TTL_WARNING_LEDGERS each declared twice — corrupted vitest's mock registry, causing cascade failures in contract.test.js and agents.test.js | Removed 4 duplicate const declarations
src/routes/services.js | creditPayment() validated all guards but never called recordPaymentOnChain() — the actual on-chain write was missing | Added await recordPaymentOnChain(agentAddress, serviceId, priceStroops, true)

<hr style="font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><h2 style="color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Test results</h2><div class="codeBlockWrapper_-a7MRw" style="position: relative; margin: 8px 0px; color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><button class="copyButton_CEmTFw copyButton_-a7MRw" title="Copy code" aria-label="Copy code to clipboard" style="color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; background: none 0% 0% / auto repeat scroll padding-box border-box rgb(30, 30, 30); border-color: rgba(204, 204, 204, 0.2); border-style: solid; border-width: 1px; border-image: none 100% / 1 / 0 stretch; cursor: pointer; opacity: 0; display: flex; border-radius: 4px; justify-content: center; align-items: center; padding: 4px; transition: opacity 0.15s, background 0.15s; position: absolute; top: 4px; right: 4px;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon" class="copyIcon_CEmTFw"><path fill-rule="evenodd" d="M15.988 3.012A2.25 2.25 0 0 1 18 5.25v6.5A2.25 2.25 0 0 1 15.75 14H13.5v-3.379a3 3 0 0 0-.879-2.121l-3.12-3.121a3 3 0 0 0-1.402-.791 2.252 2.252 0 0 1 1.913-1.576A2.25 2.25 0 0 1 12.25 1h1.5a2.25 2.25 0 0 1 2.238 2.012ZM11.5 3.25a.75.75 0 0 1 .75-.75h1.5a.75.75 0 0 1 .75.75v.25h-3v-.25Z" clip-rule="evenodd"></path><path d="M3.5 6A1.5 1.5 0 0 0 2 7.5v9A1.5 1.5 0 0 0 3.5 18h7a1.5 1.5 0 0 0 1.5-1.5v-5.879a1.5 1.5 0 0 0-.44-1.06L8.44 6.439A1.5 1.5 0 0 0 7.378 6H3.5Z"></path></svg></button><pre style="overflow-x: auto; white-space: pre; box-sizing: border-box; border-radius: 4px; max-width: 100%; margin: 0px; padding: 8px;"><code style="font-family: monospace; color: rgb(215, 186, 125); background-color: rgba(255, 255, 255, 0.1); padding: 0px; border-radius: 3px; word-break: break-word; font-size: 0.9em;">Test Files  12 passed (12)
     Tests  166 passed (166)
</code></pre></div><p style="white-space: pre-wrap; margin-top: 0.1em; margin-bottom: 0.2em; color: rgb(204, 204, 204); font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(37, 37, 38); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Closes #253</p><!--EndFragment-->
</body>
</html>

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * Added a `--print-config` option to output selected configuration values as formatted JSON and exit.
* **Bug Fixes**
  * Configuration validation now runs through a centralized check that reports all missing required values together.
  * Invalid payment address values now produce a clear fatal error and terminate cleanly.
  * Startup warning behavior for optional configuration was adjusted to appear during validation.
* **Improvements**
  * Graceful shutdown more reliably closes the active HTTP server on termination signals.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

- registry.js: remove duplicate annotateTtlWarning function declaration
- contract.js: remove duplicate SERVICE_MAX_TTL/SERVICE_TTL_WARNING_LEDGERS exports
- registry.test.js: remove duplicate const declarations (mockGetCurrentLedgerSequence, SERVICE_MAX_TTL, SERVICE_TTL_WARNING_LEDGERS)
- services.js: add missing recordPaymentOnChain() call in creditPayment() after all guards pass

All 12 test files, 166 tests now pass.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 497d874a-c92f-4c8d-998c-0c2097964842

📥 Commits

Reviewing files that changed from the base of the PR and between 662aa8d and eb1eb0b.

📒 Files selected for processing (4)
  • backend/src/config.js
  • backend/src/index.js
  • backend/src/routes/registry.js
  • backend/src/routes/registry.test.js

📝 Walkthrough

Walkthrough

Moves backend config validation into validateConfig(log), adds a --print-config startup path, updates validation tests, and removes the annotateTtlWarning helper body from registry.js.

Changes

Deferred Config Validation and Startup

Layer / File(s) Summary
validateConfig() implementation
backend/src/config.js
Removes module-load env validation, adds validateConfig(log) with aggregated missing-variable handling, PAYMENT_ADDRESS validation, structured fatal exit, and the AGENTS_CONTRACT_ID warning through the provided logger.
index.js wiring
backend/src/index.js
Imports validateConfig, adds a --print-config branch that prints selected config as JSON and exits, and assigns the listening server instance to the shared shutdown variable.
validateConfig tests
backend/src/config.test.js
Updates PAYMENT_ADDRESS and AGENTS_CONTRACT_ID tests to use validateConfig(log) and adds coverage for valid config and aggregated missing-variable failures.
Registry helper removal
backend/src/routes/registry.js, backend/src/routes/registry.test.js
Deletes the annotateTtlWarning helper body from registry.js and adds a blank line in registry.test.js.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • ritik4ever

🐇 I sniff the config, neat and new,
One validateConfig() to guide me through.
--print-config sparkles bright,
And startup’s tidy in the night.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Removing annotateTtlWarning from registry.js is unrelated to the config-validation issue and appears outside the stated objectives. Revert or separate the registry TTL-warning change unless a linked issue requires it, and keep this PR scoped to config validation and --print-config.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is related to the PR's config-validation and test-fix work, though it understates the new startup and CLI changes.
Linked Issues check ✅ Passed The config validation now runs after logger init, reports all missing vars, exits cleanly, and adds --print-config support.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 OpenGrep (1.23.0)
backend/src/routes/registry.js

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

[00.12][ERROR]: unable to find a config; path .coderabbit-opengrep-fallback.yml does not exist

backend/src/routes/registry.test.js

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

[00.12][ERROR]: unable to find a config; path .coderabbit-opengrep-fallback.yml does not exist

backend/src/config.js

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

[00.14][ERROR]: unable to find a config; path .coderabbit-opengrep-fallback.yml does not exist

  • 1 others

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
backend/src/index.js (1)

19-30: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Whitelist explicit fields in --print-config
stellar and contract are public-only today, but serializing whole objects makes future secret additions easy to expose. Whitelist the exact fields instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/index.js` around lines 19 - 30, The --print-config output is
serializing whole `stellar` and `contract` objects, which can accidentally
expose future secrets; update the config printing logic in
`backend/src/index.js` to whitelist only the explicitly allowed fields. Keep the
existing `x402` field mapping as-is, and limit `stellar` and `contract` to their
current public properties by name so the printed config remains safe even if
those objects gain new secret values later.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/config.js`:
- Around line 163-167: The fatal startup summary in the config validation path
is built only from the missing environment variables, so format/validation
failures like PAYMENT_ADDRESS are reported with an empty “missing required
environment variables” list. Update the aggregated failure message in the config
validation logic to summarize `errors` as well as `missing`, using the existing
`errors.length > 0` block and `log.fatal` call so the fatal output reflects the
actual invalid inputs.

In `@backend/src/index.js`:
- Around line 12-40: The --print-config branch in index.js bypasses
configuration validation and can exit successfully even with invalid settings.
Move validateConfig(logger) so it runs before the early return for
process.argv.includes("--print-config"), or otherwise ensure the same validation
path is executed before printing the config. Keep the existing print-and-exit
behavior in the CLI path, but only after validateConfig has passed.

---

Nitpick comments:
In `@backend/src/index.js`:
- Around line 19-30: The --print-config output is serializing whole `stellar`
and `contract` objects, which can accidentally expose future secrets; update the
config printing logic in `backend/src/index.js` to whitelist only the explicitly
allowed fields. Keep the existing `x402` field mapping as-is, and limit
`stellar` and `contract` to their current public properties by name so the
printed config remains safe even if those objects gain new secret values later.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 91546ae2-b843-4803-9552-18bd3d1ed666

📥 Commits

Reviewing files that changed from the base of the PR and between 33eafbc and 662aa8d.

📒 Files selected for processing (5)
  • backend/src/config.js
  • backend/src/config.test.js
  • backend/src/index.js
  • backend/src/routes/registry.js
  • backend/src/routes/registry.test.js
💤 Files with no reviewable changes (1)
  • backend/src/routes/registry.js

Comment thread backend/src/config.js
Comment on lines +163 to +167
if (errors.length > 0) {
log.fatal(
{ missingVars: missing, errors },
`Server startup failed: missing required environment variables: ${missing.join(', ')}`,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Build the fatal summary from errors, not just missing.

When PAYMENT_ADDRESS is the only invalid input, this logs missing required environment variables: with an empty list even though the real failure is a format error. That makes the new aggregated startup output misleading.

Suggested fix
   if (errors.length > 0) {
+    const summary =
+      missing.length > 0
+        ? `Server startup failed: ${errors.join('; ')}`
+        : `Server startup failed: ${errors[0]}`;
     log.fatal(
       { missingVars: missing, errors },
-      `Server startup failed: missing required environment variables: ${missing.join(', ')}`,
+      summary,
     );
     process.exit(1);
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (errors.length > 0) {
log.fatal(
{ missingVars: missing, errors },
`Server startup failed: missing required environment variables: ${missing.join(', ')}`,
);
if (errors.length > 0) {
const summary =
missing.length > 0
? `Server startup failed: ${errors.join('; ')}`
: `Server startup failed: ${errors[0]}`;
log.fatal(
{ missingVars: missing, errors },
summary,
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/config.js` around lines 163 - 167, The fatal startup summary in
the config validation path is built only from the missing environment variables,
so format/validation failures like PAYMENT_ADDRESS are reported with an empty
“missing required environment variables” list. Update the aggregated failure
message in the config validation logic to summarize `errors` as well as
`missing`, using the existing `errors.length > 0` block and `log.fatal` call so
the fatal output reflects the actual invalid inputs.

Comment thread backend/src/index.js
Comment on lines +12 to +40
if (process.argv.includes("--print-config")) {
console.log(
JSON.stringify(
{
nodeEnv: config.nodeEnv,
port: config.port,
logLevel: config.logLevel,
stellar: config.stellar,
contract: config.contract,
x402: {
facilitatorUrl: config.x402.facilitatorUrl,
searchPrice: config.x402.searchPrice,
weatherPrice: config.x402.weatherPrice,
payTo: config.x402.payTo,
},
corsOrigin: config.corsOrigin,
jsonBodyLimit: config.jsonBodyLimit,
trustProxy: config.trustProxy,
rateLimit: config.rateLimit,
demoRun: config.demoRun,
},
null,
2,
),
);
process.exit(0);
}

validateConfig(logger);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Run validateConfig(logger) before the --print-config early exit.

Right now the new CLI path prints and exits 0 even when the same environment would fail normal startup, so the dry-run path never actually validates config.

Suggested fix
+validateConfig(logger);
+
 if (process.argv.includes("--print-config")) {
   console.log(
     JSON.stringify(
       {
@@
   );
   process.exit(0);
 }
-
-validateConfig(logger);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (process.argv.includes("--print-config")) {
console.log(
JSON.stringify(
{
nodeEnv: config.nodeEnv,
port: config.port,
logLevel: config.logLevel,
stellar: config.stellar,
contract: config.contract,
x402: {
facilitatorUrl: config.x402.facilitatorUrl,
searchPrice: config.x402.searchPrice,
weatherPrice: config.x402.weatherPrice,
payTo: config.x402.payTo,
},
corsOrigin: config.corsOrigin,
jsonBodyLimit: config.jsonBodyLimit,
trustProxy: config.trustProxy,
rateLimit: config.rateLimit,
demoRun: config.demoRun,
},
null,
2,
),
);
process.exit(0);
}
validateConfig(logger);
validateConfig(logger);
if (process.argv.includes("--print-config")) {
console.log(
JSON.stringify(
{
nodeEnv: config.nodeEnv,
port: config.port,
logLevel: config.logLevel,
stellar: config.stellar,
contract: config.contract,
x402: {
facilitatorUrl: config.x402.facilitatorUrl,
searchPrice: config.x402.searchPrice,
weatherPrice: config.x402.weatherPrice,
payTo: config.x402.payTo,
},
corsOrigin: config.corsOrigin,
jsonBodyLimit: config.jsonBodyLimit,
trustProxy: config.trustProxy,
rateLimit: config.rateLimit,
demoRun: config.demoRun,
},
null,
2,
),
);
process.exit(0);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/index.js` around lines 12 - 40, The --print-config branch in
index.js bypasses configuration validation and can exit successfully even with
invalid settings. Move validateConfig(logger) so it runs before the early return
for process.argv.includes("--print-config"), or otherwise ensure the same
validation path is executed before printing the config. Keep the existing
print-and-exit behavior in the CLI path, but only after validateConfig has
passed.

@ritik4ever ritik4ever left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@ritik4ever ritik4ever merged commit 19d1a59 into Stellar-Ecosystem:main Jun 29, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants