Skip to content

feat(demo): reject unsupported capabilities with typed 503 - #1526

Merged
greatest0fallt1me merged 1 commit into
CalloraOrg:mainfrom
Gabriel-123-diamond:feat/issue-1515-demo-capability-guard
Oct 24, 2026
Merged

greatest0fallt1me merged 1 commit into
CalloraOrg:mainfrom
Gabriel-123-diamond:feat/issue-1515-demo-capability-guard

Conversation

@Gabriel-123-diamond

@Gabriel-123-diamond Gabriel-123-diamond commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1515

Demo requests for PostgreSQL or Soroban capabilities return an immediate 503 DEMO_MODE_UNSUPPORTED envelope with the request ID and details.feature, without Retry-After. The seeded SQLite catalog remains available, and /api/health reports data.mode (demo or standard).

DEMO_MODE is validated centrally. The billing client is never constructed in demo mode, including injected factories, and the lazy shared PostgreSQL pool rejects demo access before constructing a pool. Optional Horizon/RPC health probes are disabled in demo mode. No raw process.env.DEMO_MODE reads remain in application source.

The exported DEMO_UNSUPPORTED_ROUTES table is the single source of truth. Tests verify each entry against the mounted Express route tree, with export configuration enabled for the conditional export routes.

Prefix, including subpaths Methods
/api/billing, /api/invoices All
/api/usage, /api/exports All
/api/admin/usage, /api/admin/db/explain All
/api/vault/deposit/prepare POST
/api/vault/onchain, /api/vault/balance GET, HEAD
/api/audit POST, PUT, PATCH, DELETE
/api/credits, /api/refunds All
/api/health/health, /api/health/dependencies GET, HEAD

Standard-mode routing, authentication, exports and vault behavior are preserved. App wiring, configuration and envelope code use smaller modules to meet the contribution workspace's 250-line source-file limit; generated error codes retain their generator format.

Current-main integration

Rebased onto 5150bee72289229300d109fe7f52eceea19d7932, including #1550. The split modules preserve the restored database field names, testnet passphrase, StrKey validation, network/passphrase and secret/source-account consistency checks, production restrictions, and safe environment error reporting. They also retain the newer export configuration/storage validation, scheduled exports, idempotency lease/sweeper settings, settlement retry settings, and vault-reader wiring.

The newer Soroban-backed vault reads are included in the demo guard so they cannot call RPC in demo mode; standard-mode controller behavior remains covered. A configuration comparison against current main confirms all 145 existing environment fields and 47 settings were carried across, with only the intended demo-mode additions/conditions.

Validation

Node 20.19.0 on x86_64 macOS, against current main above:

Focused demo/config/database/vault checks: 5 suites, 56 tests PASS
demoGuard.ts: 100% statements / branches / functions / lines
npm run build: PASS (includes error-codes:check and validate:openapi)
npm run build:vercel: PASS
git diff origin/main --check: PASS
Gitleaks contribution commit: PASS, no leaks

The full suite was run, with limitations reproduced on a separate unchanged checkout of current main using the same installed dependencies:

  • Contribution: 188 suites passed, 4 failed, 2 skipped; 2,776 tests passed, 17 failed, 3 skipped. These failures are the four PostgreSQL Testcontainers suites (revenueLedgerIndexer, integration idempotencySweeper, settlementStoreSchema, and quotaNotifier): no working container runtime is available on this Mac. The contribution run uses SQLITE_PATH=:memory: to isolate SQLite.
  • Unchanged main: 183 suites passed, 5 failed, 2 skipped; 2,731 tests passed, 18 failed, 3 skipped. It has the same container-runtime failures plus one timing assertion in restRateLimit.test.ts, which passes on the contribution.
  • npm run lint: blocked on both by ESLint's missing ajv/lib/refs/json-schema-draft-04.json.
  • npm run typecheck: fails on both with the same 254 diagnostic locations/codes; no added diagnostic files/codes. Application compilation passes.

Dependencies, lockfile, workflows and quarantine configuration are unchanged relative to current main. The full suite, lint and typecheck are not claimed as passing; remote CI must be assessed separately.

Original regression proof: billing/invoices and health integration checks failed before the demo implementation. Current coverage also verifies no pool connections/queries or billing factory calls in demo mode, method/path boundaries, seeded catalog access, standard health shape, production security checks in both modes, and no injected vault-reader calls for guarded demo requests.

Remote CI

At head 002a0233c31e2a15183d9c8af92d7e2fe01de3bd, openapi-compat fails because Optic treats adding the issue-required DEMO_MODE_UNSUPPORTED member to the shared response ErrorCode enum as a breaking contract change. This is a contribution-specific compatibility-policy failure, distinct from the local baseline limitations above. The required enum addition and compatibility gate are retained for maintainer review; CI is not claimed green.

@drips-wave

drips-wave Bot commented Oct 19, 2026

Copy link
Copy Markdown

@Gabriel-123-diamond Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@greatest0fallt1me

Copy link
Copy Markdown
Contributor

Held: this large refactor (splitting app.ts, env.ts and config/index.ts) conflicts with about 7 newer commits on main, including the security-check restoration in #1550. Please rebase onto the current main and port those changes into the new modules.

Centralize demo configuration, return typed capability errors, prevent
external database/client initialization, and expose the runtime health mode.
Add route-table, configuration, lazy-pool and application regression tests.

Closes CalloraOrg#1515
@Gabriel-123-diamond
Gabriel-123-diamond force-pushed the feat/issue-1515-demo-capability-guard branch from a2958f2 to 002a023 Compare October 24, 2026 15:08
@Gabriel-123-diamond

Copy link
Copy Markdown
Contributor Author

@greatest0fallt1me Rebased onto current main 5150bee (including #1550) and pushed 002a023. The split modules now retain the newer configuration/security validation, corrected database keys and testnet passphrase, export storage validation and scheduled exports, idempotency/sweeper and settlement settings, and vault-reader wiring. The newer RPC-backed vault reads are guarded in demo mode; standard-mode behavior is preserved.

Validation: 56 focused tests pass with 100% guard coverage; both builds and Gitleaks pass. Full run: 2,776 passing / 17 failing tests; all failures are the four PostgreSQL Testcontainers suites, also failing on unchanged main because this Mac lacks a working container runtime. Lint startup and the same 254 typecheck diagnostic locations/codes are reproduced on unchanged main. The PR description includes the baseline comparison.

GitHub now reports the PR as mergeable. One remaining contribution-specific CI blocker: openapi-compat rejects the issue-required addition of DEMO_MODE_UNSUPPORTED to the shared response ErrorCode enum as a breaking change. I have retained the contract addition and gate for your review rather than suppressing the result. Implementation complete and ready for review; CI is not claimed green.

@greatest0fallt1me
greatest0fallt1me merged commit 68cab6a into CalloraOrg:main Oct 24, 2026
1 of 3 checks passed
greatest0fallt1me added a commit that referenced this pull request Oct 24, 2026
…1552)

#1526 added the demo guard, which returns DEMO_MODE_UNSUPPORTED (503) for
routes that need a database. Update the Vercel bundle smoke check to match.

Co-authored-by: greatest0fallt1me <greatest0fallt1me@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

Return a typed 503 DEMO_MODE_UNSUPPORTED for Postgres and Soroban-backed routes when DEMO_MODE is on

2 participants