PR #3 scrubbed ***REDACTED-LEGACY-PW*** from every env file, compose unit, and
deployment doc but missed scripts/setup-database.sh, which still hard-
coded DB_PASSWORD="***REDACTED-LEGACY-PW***" on line 17. That slipped past
gitleaks because the shell-escaped form (backslash-dollar) does not
match the L@kers?\$?2010 regex committed in .gitleaks.toml -- the
regex was written to catch the *expanded* form, not the source form.
This commit removes the hardcoded default and requires DB_PASSWORD to
be exported by the operator before running the script. Same pattern as
the rest of the PR #3 conversion (fail-fast at boot when a required
secret is unset) so there is no longer any legitimate reason for the
password string to live in the repo.
Verification:
git grep -nE 'L@kers?\\?\$?2010' -- scripts/ # no matches
bash -n scripts/setup-database.sh # clean
Closes the 'e2e tests only hit production; no local full-stack harness'
finding from the review. The existing e2e suite
(scripts/e2e-explorer-frontend.spec.ts) runs against explorer.d-bis.org
and so can't validate a PR before it merges -- it's a production canary,
not a pre-merge gate.
This PR adds a parallel harness that stands the entire stack up locally
(postgres + elasticsearch + redis via docker-compose, backend API, and
a production build of the frontend) and runs a Playwright smoke spec
against it. It is wired into Make and into a dedicated CI workflow.
Changes:
scripts/e2e-full.sh (new, chmod +x):
- docker compose -p explorer-e2e up -d postgres elasticsearch redis.
- Waits for postgres readiness (pg_isready loop).
- Runs database/migrations/migrate.go so schema + seeds including
the new 0016_jwt_revocations table from PR #8 are applied.
- Starts 'go run ./backend/api/rest' on :8080; waits for /healthz.
- Builds + starts 'npm run start' on :3000; waits for a 200.
- npx playwright install --with-deps chromium; runs the full-stack
spec; tears down docker and kills the backend+frontend processes
via an EXIT trap. E2E_KEEP_STACK=1 bypasses teardown for
interactive debugging.
- Generates an ephemeral JWT_SECRET per run so stale tokens don't
bleed across runs (and the fail-fast check from PR #3 passes).
- Provides a dev-safe CSP_HEADER default so PR #3's hardened
production CSP check doesn't reject localhost connections.
scripts/e2e-full-stack.spec.ts (new):
- Playwright spec that exercises public routes + a couple of
backend endpoints. Takes a full-page screenshot of each route
into test-results/screenshots/<route>.png so reviewers can
eyeball the render from CI artefacts.
- Covers: /healthz, /, /blocks, /transactions, /addresses, /tokens,
/pools, /search, /wallet, /routes, /api/v1/access/products (YAML
catalogue from PR #7), /api/v1/auth/nonce (SIWE kickoff).
- Sticks to Track-1 (no wallet auth needed) so it can run in CI
without provisioning a test wallet.
playwright.config.ts:
- Broadened testMatch from a single filename to /e2e-.*\.spec\.ts/
so the new spec is picked up alongside the existing production
canary spec. fullyParallel, worker, timeout, reporter, and
project configuration unchanged.
Makefile:
- New 'e2e-full' target -> ./scripts/e2e-full.sh. Listed in 'help'.
- test-e2e (production canary) left untouched.
.github/workflows/e2e-full.yml (new):
- Dedicated workflow, NOT on every push/PR (the full stack takes
minutes and requires docker). Triggers:
* workflow_dispatch (manual)
* PRs labelled run-e2e-full (opt-in for changes that touch
migrations, auth, or routing)
* nightly schedule (04:00 UTC)
- Uses Go 1.23.x and Node 20 to match PR #5's pinning.
- Uploads two artefacts on every run: e2e-screenshots
(test-results/screenshots/) and playwright-report.
docs/TESTING.md (new):
- Four-tier test pyramid: unit -> static analysis -> production
canary -> full-stack Playwright.
- Env var reference table for e2e-full.sh.
- How to trigger the CI workflow.
Verification:
bash -n scripts/e2e-full.sh clean
The spec imports compile cleanly against the existing @playwright
/test v1.40 declared in the root package.json; no new runtime
dependencies are added.
Existing scripts/e2e-explorer-frontend.spec.ts still matched by
the broadened testMatch regex.
Advances completion criterion 7 (end-to-end coverage): 'make e2e-full
boots the real stack, Playwright runs against it, CI uploads
screenshots, a nightly job catches regressions that only show up
when all services are live.'
backend/api/rest/server.go:
- NewServer() now delegates to loadJWTSecret(), which:
- Rejects JWT_SECRET < 32 bytes (log.Fatal).
- Requires JWT_SECRET when APP_ENV=production or GO_ENV=production.
- Generates a 32-byte crypto/rand ephemeral secret in dev only.
- Treats rand.Read failure as fatal (removes the prior time-based
fallback that was deterministic and forgeable).
- Default Content-Security-Policy rewritten:
- Drops 'unsafe-inline' and 'unsafe-eval'.
- Drops private CIDRs (192.168.11.221:854[5|6]).
- Adds frame-ancestors 'none', base-uri 'self', form-action 'self'.
- CSP_HEADER is required in production; fatal if unset there.
backend/api/rest/server_security_test.go (new):
- Covers the three loadJWTSecret() paths (valid, whitespace-trimmed,
ephemeral in dev).
- Covers isProductionEnv() across APP_ENV / GO_ENV combinations.
- Asserts defaultDevCSP contains no unsafe directives or private CIDRs
and includes the frame-ancestors / base-uri / form-action directives.
scripts/*.sh:
- Removed '***REDACTED-LEGACY-PW***' default value from SSH_PASSWORD / NEW_PASSWORD in
7 helper scripts. Each script now fails with exit 2 and points to
docs/SECURITY.md if the password isn't supplied via env or argv.
EXECUTE_DEPLOYMENT.sh, EXECUTE_NOW.sh:
- Replaced hardcoded DB_PASSWORD='***REDACTED-LEGACY-PW***' with a ':?' guard that
aborts with a clear error if DB_PASSWORD (and, for EXECUTE_DEPLOYMENT,
RPC_URL) is not exported. Other env vars keep sensible non-secret
defaults via ${VAR:-default}.
README.md:
- Removed the hardcoded Database Password / RPC URL lines. Replaced with
an env-variable reference table pointing at docs/SECURITY.md and
docs/DATABASE_CONNECTION_GUIDE.md.
docs/DEPLOYMENT.md:
- Replaced 'PASSWORD: SSH password (default: ***REDACTED-LEGACY-PW***)' with a
required-no-default contract and a link to docs/SECURITY.md.
docs/SECURITY.md (new):
- Full secret inventory keyed to the env variable name and the file that
consumes it.
- Five-step rotation checklist covering the Postgres role, the Proxmox
VM SSH password, JWT_SECRET, vendor API keys, and a gitleaks-based
history audit.
- Explicit note that merging secret-scrub PRs does NOT invalidate
already-leaked credentials; rotation is the operator's responsibility.
Verification:
- go build ./... + go vet ./... pass clean.
- Targeted tests (LoadJWTSecret*, IsProduction*, DefaultDevCSP*) pass.
Advances completion criterion 2 (Secrets & config hardened). Residual
leakage from START_HERE.md / LETSENCRYPT_CONFIGURATION_GUIDE.md is
handled by PR #2 (doc consolidation), which deletes those files.
- Updated branding from "SolaceScanScout" to "Solace" across various files including deployment scripts, API responses, and documentation.
- Changed default base URL for Playwright tests and updated security headers to reflect the new branding.
- Enhanced README and API documentation to include new authentication endpoints and product access details.
This refactor aligns the project branding and improves clarity in the API documentation.
- Added new compliant tokens including Tether EUR, Pound Sterling, and others to the DUAL_CHAIN_TOKEN_LIST.
- Updated version in the token list configuration to 1.2.
- Enhanced Nginx configuration to support token-aggregation API and serve token list and network configurations from specified paths.
Co-authored-by: Cursor <cursoragent@cursor.com>