Repository navigation
feat: a11y route announcer, log redaction, OpenAPI route drift check, compose integration CI (#726, #746, #748, #753) - #873
Merged
devJaja merged 8 commits intoOct 20, 2026
Conversation
SUPPORTED_LANGUAGES includes 'es' but LANGUAGE_OPTIONS did not, so the language switcher read undefined.nativeName and every in-app route fell into the error boundary.
…ode#726) - AppShell moves focus to <main> on client-side navigation and announces the new page title in a polite live region; a fresh load keeps the browser's own focus order - Toast container is the single live region (no nested aria-live) - Task detail page announces task and stream status changes - a11y.navigatedTo string in en, es, zh - Playwright spec covering the skip link and route focus
…#746) - Redact signature, jwt and credential keys; replace prompt, completion and request/response bodies with [REDACTED_BODY]; scrub JWTs from free-text strings - Whitelisting req/res serializers (id, method, path, ip, statusCode) - Sanitize logger.child() bindings, which pino serializes once and never passes through logMethod or formatters.bindings - Canary test logs a known secret through every path and fails if it reaches the output - Document the redaction layers in SECURITY_CHECKLIST.md
…de#748) openapiRouteDiff.test.ts walks the live Express router tree and fails with a two-sided diff (served but undocumented / documented but not served). It runs in npm run test:contract, which CI already calls. Also point the response-contract suite at app.httpServer: createApp() returns a handle, not an Express app, so every request threw 'app.address is not a function'.
- Dockerfile: install from backend's own lockfile (the repo is not an npm workspace), Node 24 (better-sqlite3 13 needs >= 22), skip install scripts (prebuilds ship in the package), writable data dir for the non-root user - .dockerignore keeps host node_modules and dist out of the context - Import package.json so tsc emits it next to dist/src; the bare require only resolved from src/ - copy-migrations.js copies SQL to dist/src/db/migrations, where the compiled loader looks - Horizon and Soroban RPC clients allow http only when STELLAR_NETWORK is local, so the backend can reach the compose standalone node
- docker-compose.yml test profile adds a smoke runner; fix the Stellar healthcheck (it grepped for text Horizon never returns), the SQLite path and volume, and set STELLAR_NETWORK=local for the backend - tests/e2e/compose-smoke.mjs: liveness, signed agent registration, task submit, first SSE event; Node built-ins only - integration-compose CI job: buildx-cached backend image, smoke suite, graceful shutdown check, compose logs uploaded on failure, 20 min timeout, gated by a compose paths filter and wired into ci-gate - Document the profile in tests/e2e/README.md
Resolve docker-compose.yml (keep the test smoke profile and the new monitoring profile) and payment.ts imports (toW3cTraceId plus stellarClientOptions).
Resolve config/index.ts (keep the package.json import and stellarClientOptions, in upstream's single-quote style) and reconciliation.ts imports (fetchWithTimeout plus stellarClientOptions).
|
@ExcelDsigN-tech 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! 🚀 |
|
@ExcelDsigN-tech is attempting to deploy a commit to the Jaja's projects Team on Vercel. A member of the Team first needs to authorize it. |
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #726
Closes #746
Closes #748
Closes #753
This PR covers four issues, each in its own commit. Getting #753 working turned up some things that were already broken on
main. Those fixes are in a separatefix:commit, listed at the end.Changes
#726 Accessibility: skip link, focus and live announcements
AppShellmoves focus to<main>and announces "Navigated to {page}" in a polite live region.aria-live.a11y.navigatedTostring in en, es and zh.frontend/tests/e2e/a11y-skip-link.spec.tscovers:<main>on route change#746 Log redaction for secrets, tokens and API keys
[REDACTED_BODY].req/resserializers now log only these fields: id, method, path (query string dropped), ip and statusCode.logger.child()bindings are sanitized. Pino serializes them once and never passes them throughlogMethodorformatters.bindings, so a secret bound to a child logger used to be written as-is on every line.logger.redaction.test.tslogs a known secret through every logging path and fails if it reaches the output.docs/SECURITY_CHECKLIST.md.#748 Contract-test live routes against the OpenAPI spec in CI
backend/tests/openapiRouteDiff.test.tswalks the live Express router and fails with a two-sided diff:npm run test:contract, which CI already calls.app.httpServer.createApp()returns a handle, not an Express app, so before this every request threwapp.address is not a function.#753 docker-compose integration profile for full-stack CI
docker-compose.ymlgets atestprofile with asmokerunner service.The compose file itself is fixed:
DATABASE_URLwas asqlite://URL, whichresolveDatabasePath()rejects.STELLAR_NETWORK=local.tests/e2e/compose-smoke.mjschecks, in order:It uses Node built-ins only, so there is no install step.
New
integration-composeCI job:It has a 20 min timeout, only runs when a paths filter matches, and is part of
ci-gate.Documented in
tests/e2e/README.md.Fixes for things already broken on
mainThe issues above needed these to work:
npm install --workspace=backend, but the repo has no workspaces. It now installs frombackend/package-lock.json.better-sqlite3@13needs Node 22 or later.--ignore-scripts, because the prebuilt binaries ship in the package..dockerignore: added, so hostnode_modules(glibc builds) never get into the Alpine image.config/index.ts:package.jsonis now imported, so tsc emitsdist/package.json. Before this,npm startafternpm run buildcrashed.copy-migrations.js: it copied SQL todist/db/migrations, but the compiled loader readsdist/src/db/migrations.http://only whenSTELLAR_NETWORK=local, so the backend can reach the compose standalone node. TLS is still required everywhere else.Verification & Testing
npx jest --runInBand, compared withmain(at1d5ccc6, before the latest upstream merge) on the same machine:mainfails here.logger.redaction.test.ts: 29/29 pass.openapiRouteDiff.test.ts: passes.main.a11y-skip-link.spec.ts: 3/3 pass, stable across repeated runs, including after merging the latestmain.docker compose --profile test up --exit-code-from smoke smoke: passes in about 22s against real containers.docker compose stop backendthen exits 0 after a clean graceful shutdown.tsc --noEmitis clean. Frontend has the same 107 type errors as currentmain, and none are new.cargo test/cargo fmt/clippy: N/A, no contract changes.Contributor Checklist
main:main:src/services/venice/client.tshas a syntax error ('catch' or 'finally' expected, line 561) left by a merge. Fixing that exposes 16 more type errors from half-merged Add health-aware Venice fallback key rotation #741 and Apply per-endpoint timeout budgets with AbortController #742 (TIMEOUT_BUDGET_*_MSmissing fromConfig,getVeniceKeyHealthStoreandkeyHealthundefined). Until that's fixed onmain, the backend build, the Docker image andintegration-composewill fail on every PR, including this one. This PR doesn't touch those files.qualityScoreCache.ts, a file this PR doesn't touch.format:check: fails on about 1,184 files onmain. Only files new in this PR were formatted.docs/SECURITY_CHECKLIST.md,tests/e2e/README.md)Follow-ups (not in this PR)
Frontend Docker image is also broken:
--workspaceinstallnpm run build || truehides type errorspreviewscriptOnce it's fixed, the compose smoke run can cover the frontend too.
feat(backend): Add automated OpenAPI contract tests that validate every route against its spec schema #815 contract suite needs seeded fixtures before it can check the documented 200 responses.