This runbook defines the release-readiness, deployment verification, smoke-check, rollback, escalation, and routine-maintenance procedures for the LumenPulse testnet stack.
It covers the monorepo's:
- Backend API
- Web application
- Mobile application
- Data-processing service
- Soroban/Stellar contracts
The runbook is intended for contributors and reviewers preparing a testnet release or diagnosing a failed deployment.
This document describes the repository's current operational interfaces. It does not assume that a service has a deployment platform or rollback mechanism that is not documented in the repository.
The LumenPulse repository is a monorepo containing independent application and contract components.
| Component | Location | Primary runtime | Operational responsibility |
|---|---|---|---|
| Backend | apps/backend |
Node.js / NestJS | API, database access, Redis-backed workloads, Stellar/Horizon integration |
| Webapp | apps/webapp |
Next.js | Browser UI and client-facing API integration |
| Mobile | apps/mobile |
Expo / React Native | Mobile client, wallet and API integration |
| Data processing | apps/data-processing |
Python | News ingestion, sentiment, market analysis, anomaly detection, scheduled processing |
| Contracts | apps/onchain |
Rust / Soroban | On-chain project, contributor, treasury, token, funding and related protocol functionality |
The testnet contract deployment set is represented by:
apps/onchain/testnet-manifest.json
The backend can seed and read this manifest through its deployment-manifest service.
A testnet release should not be considered ready until all applicable gates below pass.
- Git working tree contains only intended release changes.
- Backend CI passes.
- Data-processing CI passes.
- Mobile CI passes.
- On-chain CI passes.
- Webapp tests and build pass.
- Backend migration checks pass.
- Testnet contract manifest validates.
- Backend health checks pass against testnet dependencies.
- Contract health check passes.
- Backend deployment smoke check passes.
- Webapp can reach the configured backend.
- Mobile client points to the intended testnet API and Stellar configuration.
- Data-processing service can reach its configured external dependencies.
- No release-blocking alerts are active.
- Rollback target is known before deployment.
If any release-blocking gate fails, stop the release and investigate before promoting the affected component.
From the repository root:
git status
git branch --show-current
git log -1 --onelineConfirm:
- The intended branch is checked out.
- The working tree does not contain accidental changes.
- The commit being released is the commit that was reviewed.
- CI corresponds to the same commit.
For a release candidate, record the commit SHA:
git rev-parse HEADUse that SHA when comparing deployments, failures, and rollback candidates.
The backend workflow is:
.github/workflows/backend.yml
It runs:
- dependency installation with
npm ci - ESLint
- optional TypeScript type checking
- Jest tests
- NestJS build
- migration safety checks
- migration verification against a clean PostgreSQL database
Run the equivalent local checks:
cd apps/backend
npm ci
npm run lint
npm run test
npm run build
npm run migration:checkFor migration verification:
npm run migration:verifyDo not treat a successful application build as sufficient if database migrations are part of the release.
Start the backend using:
cd apps/backend
npm run start:devThe application exposes Swagger documentation at:
/api/docs
The configured production Swagger server is:
https://api.lumenpulse.io
Do not assume this hostname is currently reachable unless the deployment environment confirms it.
The backend provides several operational endpoints.
GET /health
Expected behavior:
- HTTP
200when the service is healthy or degraded but available. - HTTP
503when a critical health condition is reported.
GET /health/live
GET /health/ready
Readiness should be treated as the deployment gate because it explicitly reports the service as unavailable while graceful shutdown is in progress.
GET /health/contracts
This checks configured Stellar contract reachability and readiness.
GET /health/latency
This reports Horizon and Soroban RPC latency-budget state.
GET /health/smoke
This is the preferred backend release smoke check.
The endpoint verifies:
- required environment variables
- database availability
- Redis availability
- Horizon availability
- configured Soroban contract reachability
The response contains a machine-readable status:
pass
warn
fail
The deployment should not be considered ready when the smoke response reports ready: false.
Example:
Invoke-RestMethod https://<testnet-backend-host>/health/smokeIf the endpoint returns HTTP 503, stop the release and inspect the failing check IDs before continuing.
Treat the following as release blockers:
| Signal | Severity | Action |
|---|---|---|
/health/smoke returns fail |
Critical | Stop release |
/health/ready returns 503 after deployment settles |
Critical | Stop traffic/promotion and investigate |
/health/contracts returns 503 |
Critical | Verify testnet manifest, contract IDs and RPC |
| Database migration fails | Critical | Do not continue deployment |
| Redis unavailable for required workloads | High | Investigate before promotion |
| Horizon unavailable | High | Investigate Stellar dependency |
| Soroban RPC unavailable | High | Investigate RPC dependency |
/health/latency reports hard_down |
High | Do not promote |
| API responds but contract calls fail | Critical | Treat as partial deployment failure |
When escalating, capture:
release commit SHA
affected service
deployment timestamp
endpoint/check that failed
HTTP status
response body
relevant application logs
dependency status
last known-good commit/deployment
Do not paste secrets, wallet secrets, API keys, JWT secrets, or private credentials into issues or chat.
The web application is located at:
apps/webapp
It is a Next.js application.
Run:
cd apps/webapp
npm install
npm run check:api-types
npm test
npm run buildThe API type check is important because the webapp consumes generated types derived from the backend OpenAPI contract.
Run:
npm run generate:api-typesonly when regeneration is intentionally required.
The generated API artifacts should not be manually edited.
The webapp uses:
BACKEND_API_URL
NEXT_PUBLIC_API_URL
NEXT_PUBLIC_STELLAR_EXPLORER_URL
Before a testnet deployment, verify that:
- server-side API calls target the intended testnet backend;
- browser-side API calls target the intended testnet backend;
- Stellar explorer links point to the intended environment;
- no production/mainnet endpoint is accidentally configured.
The webapp configuration is centralized in:
apps/webapp/lib/config.ts
After deployment:
- Open the deployed webapp.
- Confirm the application loads without a server error.
- Confirm the browser can reach the backend.
- Verify a representative API-backed page.
- Verify wallet connection using a testnet wallet.
- Verify that the application identifies the expected testnet environment.
- Verify that transaction/contract links resolve to the expected Stellar testnet explorer.
- Check the browser console for unexpected API, wallet, or hydration failures.
A frontend page loading successfully is not sufficient if API calls are failing.
Rollback or stop promotion when:
- the application cannot load;
- the application points at the wrong backend;
- authentication fails for all test users;
- API requests consistently return
5xx; - wallet connection targets the wrong network;
- testnet contract calls fail consistently;
- a release introduces unrecoverable client-side errors;
- generated API types no longer match the backend contract.
For a frontend-only regression, restore the previous known-good web deployment rather than changing backend or contract state unnecessarily.
If the frontend failure is caused by an API contract change, coordinate the frontend rollback with the backend deployment owner.
The mobile application is located at:
apps/mobile
It uses Expo and React Native.
The repository has mobile workflows under:
.github/workflows/mobile.yml
.github/workflows/mobile-ci.yml
The primary mobile workflow runs:
cd apps/mobile
npm ci
npm run tsc -- --noEmit
npm run test:coverageThe mobile CI configuration should be reviewed carefully when validating release readiness because the repository contains two mobile workflows with different behavior.
Testnet configuration is represented by variables including:
EXPO_PUBLIC_API_URL
EXPO_PUBLIC_TESTNET_API_URL
EXPO_PUBLIC_STELLAR_NETWORK
EXPO_PUBLIC_SOROBAN_RPC_URL
EXPO_PUBLIC_TESTNET_SOROBAN_RPC_URL
EXPO_PUBLIC_TESTNET_CROWDFUND_CONTRACT_ID
EXPO_PUBLIC_STELLAR_EXPLORER_URL
Before a testnet build, verify:
EXPO_PUBLIC_STELLAR_NETWORK=testnet- testnet API URL points to the testnet backend;
- Soroban RPC points to Stellar testnet;
- testnet contract IDs are correct;
- mainnet variables are not accidentally selected.
Perform the following on a test device or emulator:
- Launch the application.
- Confirm the initial screen loads.
- Confirm API connectivity.
- Load the news feed.
- Load portfolio or another API-backed feature.
- Test authentication/session restoration where applicable.
- Connect a testnet wallet using the supported wallet flow.
- Confirm the application remains on testnet.
- Exercise one representative transaction or contract-backed flow when available.
- Confirm failures are presented without leaving the application in a corrupted state.
The mobile README specifies that production builds use the SEP-0007 wallet adapter and that development builds may use a mock adapter when the SEP-0007 wallet is unavailable.
Do not interpret a mock transaction as evidence that a real testnet transaction succeeded.
The data-processing service is located at:
apps/data-processing
It is a Python 3.9+ service responsible for compute-heavy processing including sentiment analysis, market analysis, ingestion, anomaly detection and scheduled jobs.
The workflow is:
.github/workflows/data-processing.yml
Run locally:
cd apps/data-processing
python -m pip install --upgrade pip
pip install flake8 pytest
pip install -r requirements.txt
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
pytestThe service supports a single pipeline execution:
python src/main.py runA successful run should complete the pipeline stages without an exception.
The pipeline processes:
- news;
- price feeds;
- sentiment;
- Stellar on-chain data;
- market analysis;
- anomaly detection;
- ingestion alerting.
A successful process exit alone should not be considered sufficient if the output reports unavailable or invalid upstream data.
The scheduled service can be started with:
python src/main.py serveThe service starts background scheduled processing and exposes worker metrics on port 9091.
The RUN_IMMEDIATELY environment variable can be used to trigger an immediate run when the service starts:
RUN_IMMEDIATELY=true
Use this intentionally during validation; do not enable it merely to compensate for an unknown scheduler state.
The FastAPI service can be started with:
python -m uvicorn src.api.server:app --host 0.0.0.0 --port 8000 --reloadWhen running, inspect:
/docs
for the generated OpenAPI/Swagger interface.
The service also documents security requirements for its API, including API-key protection and rate limiting.
Investigate immediately when:
- the pipeline exits with
success: false; - upstream news/price/Horizon fetches fail repeatedly;
- validation drops unexpected volumes of records;
- database persistence fails;
- scheduled jobs stop executing;
- anomaly detection produces unexplained persistent failures;
- API authentication or rate limiting behaves differently from the documented configuration.
Review:
logs/data_processor.log
and the service's metrics when diagnosing repeated failures.
Contracts live under:
apps/onchain
The workspace contains multiple Soroban contracts.
The active workspace is defined in:
apps/onchain/Cargo.toml
The on-chain workflow is:
.github/workflows/onchain.yml
Run:
cd apps/onchain
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo build --target wasm32-unknown-unknown --release
cargo testA release should not proceed when formatting, Clippy, build, or tests fail.
The authoritative repository testnet deployment metadata is:
apps/onchain/testnet-manifest.json
Validate it with:
cd apps/onchain
node scripts/validate-manifest.jsThe validator requires every expected contract to have either:
- valid deployment metadata containing a Soroban contract ID and WASM hash; or
- a non-empty
reasonexplaining why the contract is intentionally not deployed.
The manifest currently identifies the Stellar testnet RPC as:
https://soroban-testnet.stellar.org:443
Do not replace contract IDs or WASM hashes in the manifest merely to make a smoke check pass.
If a deployed contract's ID or WASM hash changes, update the manifest only after verifying the actual deployment.
Before deploying a contract:
cd apps/onchain
cargo build --target wasm32-unknown-unknown --release
cargo testAfter deployment:
- Record the deployed contract ID.
- Record the resulting WASM hash.
- Verify the deployment against Stellar testnet.
- Update the testnet manifest when the deployment is intentionally part of the release.
- Run:
node scripts/validate-manifest.js- Verify backend contract health:
GET /health/contracts
- Run the backend deployment smoke endpoint:
GET /health/smoke
A contract deployment is not release-ready until the backend can resolve and reach the configured contract.
Smart contracts require a different rollback strategy from web and backend services.
Do not assume that deploying an older WASM binary automatically restores the previous on-chain state.
For the current public testnet configuration:
- deployed contracts are represented by contract IDs and WASM hashes in the testnet manifest;
- several contracts are intentionally not deployed;
- upgradeability is explicitly disabled for the current public deployment according to the manifest.
If a contract release is faulty:
- Stop further promotion.
- Stop frontend/mobile flows that invoke the affected contract.
- Preserve the failing contract ID and transaction/error information.
- Identify the last known-good deployment metadata.
- Determine whether the affected contract supports an approved upgrade path.
- If no safe upgrade path exists, do not attempt an ad-hoc state reset.
- Coordinate any replacement deployment and consumer configuration change.
- Update the deployment manifest only after the replacement deployment has been verified.
- Re-run backend contract health and smoke checks.
For on-chain incidents, preserve transaction hashes and ledger information before attempting remediation.
After all components are deployed, perform the following sequence.
GET /health
GET /health/ready
GET /health/contracts
GET /health/latency
GET /health/smoke
All critical checks must be healthy.
Verify:
- page load;
- API connectivity;
- authentication;
- news data;
- portfolio data;
- wallet connection;
- testnet contract interaction.
Verify:
- application startup;
- API connectivity;
- authentication/session;
- representative data flow;
- testnet wallet connection;
- representative transaction/contract flow.
Run:
cd apps/data-processing
python src/main.py runConfirm that the pipeline completes successfully and that no critical upstream source is unavailable.
Run:
cd apps/onchain
node scripts/validate-manifest.js
cargo testThen confirm:
GET /health/contracts
reports the configured contracts as reachable.
Use the following classification when a smoke test fails.
Examples:
- webapp rendering failure;
- mobile UI regression;
- incorrect frontend environment variable.
Action:
- rollback the affected client;
- leave backend and contracts unchanged unless dependency compatibility is also affected.
Examples:
/health/readyreturns503;- database connection failure;
- Redis failure;
- API contract regression.
Action:
- stop promotion;
- inspect application and dependency logs;
- rollback backend if the previous release is known good.
Examples:
- pipeline cannot fetch required sources;
- persistence failure;
- scheduled worker failure.
Action:
- stop relying on new analytics output;
- investigate upstream dependency and worker logs;
- avoid deleting persisted data while diagnosing.
Examples:
- contract ID cannot be reached;
- incorrect WASM hash;
- contract invocation fails;
- backend contract health fails.
Action:
- stop contract-dependent promotion;
- preserve transaction and ledger evidence;
- do not perform an improvised on-chain rollback.
Examples:
- backend points to a different contract version than the frontend;
- API response shape differs from generated frontend types;
- mobile and webapp use different testnet endpoints;
- contract manifest and backend deployment metadata disagree.
Action:
- stop the release;
- identify the first incompatible boundary;
- restore a consistent last-known-good combination of components.
When a release is confirmed faulty:
- Stop additional deployments.
- Record the failing commit SHA.
- Record the first observed failure time.
- Identify the last known-good release.
- Determine which layer introduced the failure.
- Roll back the smallest affected layer.
- Re-run the full-stack smoke test.
- Confirm that dependent services use compatible versions.
- Document the incident and follow-up work.
Database migrations require special care.
Before applying a migration:
cd apps/backend
npm run migration:checkThe CI pipeline also verifies migrations against a clean PostgreSQL database.
Do not automatically run:
npm run migration:revertduring an incident.
First determine whether the migration has already changed persistent production/testnet data and whether the application version being restored is compatible with the existing schema.
A binary/application rollback does not necessarily imply a database rollback.
For data-processing changes:
- Stop the affected worker if it is producing invalid data.
- Preserve logs and failed records where possible.
- Restore the last known-good application version.
- Verify database connectivity.
- Run a single pipeline execution.
- Confirm that the resulting output is valid before restarting scheduled processing.
Restore the last known-good client build/deployment.
After rollback verify:
- API endpoint configuration;
- authentication;
- wallet network;
- contract IDs;
- representative user flow.
Do not treat contract rollback like application rollback.
For a contract incident:
- stop invoking the affected contract;
- preserve transaction evidence;
- identify the deployed contract and WASM hash;
- determine whether an approved upgrade mechanism exists;
- use a replacement deployment only when the recovery path has been reviewed;
- update consumers and the deployment manifest together.
- Check backend readiness and smoke endpoints.
- Check contract reachability.
- Review recent deployment logs.
- Review data-processing pipeline results.
- Confirm testnet environment configuration.
- Check for stale generated API types.
- Verify the active contract manifest.
- Review failed CI runs.
- Review recurring data-processing failures.
- Review dependency/API failures.
- Check contract WASM-size changes in PRs.
- Review testnet contract metadata.
- Review mobile and webapp environment configuration.
- Check for stale or undocumented operational procedures.
- Run all affected CI workflows.
- Run the relevant local tests.
- Validate the contract manifest.
- Record the release commit SHA.
- Identify the last known-good release.
- Perform the full-stack smoke test.
- Confirm rollback ownership and procedure.
For every failed release or incident, preserve:
Repository:
Commit SHA:
Branch:
Component:
Deployment time:
Environment:
Last known-good release:
Backend:
Health status:
Readiness status:
Contract health:
Smoke status:
Latency status:
Webapp:
URL:
Observed failure:
Browser console errors:
Mobile:
Build/version:
Device:
Observed failure:
Data processing:
Pipeline result:
Relevant logs:
Upstream source failures:
Contracts:
Contract ID:
WASM hash:
Transaction hash:
Ledger:
RPC response/error:
Resolution:
Rollback/recovery action:
Verification result:
Follow-up issue:
Never include private keys, wallet secrets, API tokens, JWT secrets, database passwords, or other credentials in incident records.
Use this checklist in the release PR.
- Correct commit selected.
- Working tree clean.
- CI checks correspond to release commit.
- Lint passes.
- Tests pass.
- Build passes.
- Migration checks pass.
-
/health/readypasses. -
/health/contractspasses. -
/health/smokereports ready. - No critical dependency failures.
- API type check passes.
- Tests pass.
- Production build passes.
- Correct testnet backend configured.
- Wallet flow verified.
- Representative API-backed flow verified.
- Type check passes.
- Unit tests and coverage pass.
- Correct testnet API configured.
- Testnet Stellar configuration verified.
- Wallet flow verified.
- Representative API/contract flow verified.
- Python tests pass.
- Static checks pass.
- Single pipeline run succeeds.
- Required external sources respond.
- Persistence succeeds.
- Scheduled service starts successfully when applicable.
-
cargo fmt --checkpasses. - Clippy passes.
- WASM build passes.
- Contract tests pass.
- Testnet manifest validates.
- Deployed contract IDs are verified.
- WASM hashes are verified.
- Backend contract health passes.
- Full-stack smoke test passes.
- Last known-good release identified.
- Rollback path understood.
- No unresolved release-blocking incident exists.
- Operational evidence is available for the release.
Use these documents for deeper component-specific procedures:
document/LOCAL_SETUP.md— complete local environment setup.document/MOBILE_GUIDE.md— mobile-specific development guidance.document/SMART_CONTRACTS.md— smart-contract documentation.document/ETL_RUNBOOK.md— data/ETL operational procedures.document/BUG_TRIAGE_GUIDE.md— bug investigation and triage.document/INCIDENT_POSTMORTEM_WORKFLOW.md— incident follow-up.doc/testing-strategy.md— repository testing strategy.doc/threat-model.md— security/threat-model context.doc/adr/README.md— architecture decisions.
Update this runbook whenever an operational interface changes, including:
- deployment commands;
- health endpoints;
- CI release gates;
- environment variables;
- contract deployment procedures;
- rollback mechanisms;
- smoke-test requirements;
- service ownership boundaries.
A release procedure that exists only in contributor memory is not considered documented.