Run this checklist after each release candidate and before promoting to production.
- Confirm
SEC_USER_AGENTis set to a real SEC-declared contact string such asYour Company Name sec-ops@your-company.com. - Confirm
SEC_USER_AGENTdoes not use placeholder or non-monitored contacts such asexample.com,noreply, or GitHub noreply addresses. - Confirm
MONGO_URLorSPRING_MONGODB_URIpoints to the staging MongoDB instance. - Confirm
SPRING_DATASOURCE_URL,SPRING_DATASOURCE_USERNAME, andSPRING_DATASOURCE_PASSWORDpoint to the staging PostgreSQL instance. - Confirm
SPRING_DATA_REDIS_HOSTandSPRING_DATA_REDIS_PORTpoint to the staging Redis instance. - Confirm
VITE_API_URLpoints to the public backend base URL used by the frontend build. - If security is enabled, confirm
EDGAR4J_SECURITY_ENABLED=trueand bothEDGAR4J_SECURITY_USERNAMEandEDGAR4J_SECURITY_PASSWORDare set explicitly. - If using market data, confirm at least one provider is configured in AppSettings or fallback env/config:
TIINGO_API_TOKENFINNHUB_API_KEYALPHA_VANTAGE_API_KEY
- Backend image/container starts without restart loops.
- Frontend image/container starts without restart loops.
GET /actuator/health/livenessreturns200.GET /actuator/health/readinessreturns200.- If security is enabled:
- unauthenticated
GET /api/settingsreturns401or403 - unauthenticated
GET /actuator/health/readinessstill returns200
- unauthenticated
Example:
curl -i http://<backend-host>/actuator/health/liveness
curl -i http://<backend-host>/actuator/health/readiness
curl -i http://<backend-host>/api/settings
curl -u "$EDGAR4J_SECURITY_USERNAME:$EDGAR4J_SECURITY_PASSWORD" http://<backend-host>/api/settingsGET /api/settingssucceeds with auth when security is enabled.- Response includes insider dashboard and realtime sync fields.
- Response does not expose plaintext SMTP or market-data secrets.
PUT /api/settingspersists a non-secret change and can be read back.
Example payload:
{
"userAgent": "Your Company Name sec-ops@your-company.com",
"autoRefresh": true,
"refreshInterval": 60,
"darkMode": false,
"emailNotifications": false,
"smtpPort": 587,
"smtpStartTlsEnabled": true,
"marketDataProvider": "YAHOOFINANCE",
"insiderPurchaseLookbackDays": 30,
"insiderPurchaseMinMarketCap": 1000000000,
"insiderPurchaseSp500Only": true,
"insiderPurchaseMinTransactionValue": 100000,
"realtimeSyncEnabled": true,
"realtimeSyncForms": "4,3,5",
"realtimeSyncLookbackHours": 1,
"realtimeSyncMaxPages": 10,
"realtimeSyncPageSize": 100
}GET /api/insider-purchases/top?limit=5returns JSON.GET /api/insider-purchases/summary?lookbackDays=30returns JSON.GET /api/insider-purchases?sp500Only=true&minMarketCap=1000000000&size=5returns JSON.GET /api/market-data/prices/AAPLreturns data from the configured provider path.POST /api/market-data/backfill/market-cap?maxTickers=250&lookbackDays=30returns a bounded summary.POST /api/settings/sync/tickersreturns success and logs a manual sync trigger.
Run these after startup and again after the jobs have had time to execute.
sp500_constituentscontains roughly 500 rows/documents.company_market_datais non-empty after market-data sync.- If insider rows exist but
marketCapis still sparse, run the dedicated backfill pass from market-cap-backfill.md untildeferred_tickers=0. - Recent Form 4 data exists in MongoDB.
- Realtime filing sync logs show polling and completion without tight retry loops.
- Changing
realtimeSyncFormsin Settings changes the next poll behavior without restart. - Disabling realtime sync in Settings stops further polling on the next cycle.
Suggested Mongo checks:
db.sp500_constituents.countDocuments()
db.company_market_data.countDocuments()
db.form4.countDocuments({ filedDate: { $gte: ISODate("2026-01-01T00:00:00Z") } })/loads and shows the dashboard widgetTop Insider Purchases./insider-purchasesloads without console errors.- Changing lookback, market cap, transaction value, sort, and S&P 500 filters changes the table results.
- Pagination works on
/insider-purchases. View Allfrom the dashboard navigates to/insider-purchases.- Clicking a company drill-down from the dashboard widget or insider page opens Form 4 search results.
/settingsloads, saves, and reflects:- market-data provider settings
- realtime filing sync settings
- insider purchase default filters
- No repeated authentication failures.
- No repeated SEC throttling failures.
- No
Undeclared Automated Toolblocks from SEC in backend logs. - No repeated Redis, MongoDB, or PostgreSQL connection churn.
- No provider-disable loops for market-data sources.
- No large stack traces during normal dashboard/page loads.
Promote only if all are true:
- Backend tests passed on JDK 25.
- Frontend tests passed.
- Frontend production build passed.
- Probe endpoints are healthy.
- Settings round-trip works.
- Insider purchases API and UI both render live data.
- Scheduled jobs run cleanly in staging for at least one cycle.