diff --git a/audits/sparkyfitness-source-reads-2026-10-05/entrypoint-source-read.txt b/audits/sparkyfitness-source-reads-2026-10-05/entrypoint-source-read.txt new file mode 100644 index 0000000..6b1ddf0 --- /dev/null +++ b/audits/sparkyfitness-source-reads-2026-10-05/entrypoint-source-read.txt @@ -0,0 +1,32 @@ +# SparkyFitness v0.17.3 — start-time switches, read in upstream SOURCE at the tag (docker/), NOT inside the image +# backend docker/Dockerfile.backend: no entrypoint script; CMD ["./node_modules/.bin/tsx", "index.ts"] +47:HEALTHCHECK --interval=5s --timeout=10s --retries=5 CMD ["/usr/bin/curl", "-f", "http://127.0.0.1:3010/api/health"] +50:CMD ["./node_modules/.bin/tsx", "index.ts"] +# frontend docker/Dockerfile.frontend: CMD /docker-entrypoint.sh; its switches: +41:# Copy and set up the entrypoint script +42:COPY docker/docker-entrypoint.sh /docker-entrypoint.sh +43:RUN chmod +x /docker-entrypoint.sh \ +59:HEALTHCHECK --interval=5s --timeout=10s --retries=5 CMD curl -f http://127.0.0.1:${NGINX_LISTEN_PORT:-$([ "$(id -u)" -eq 0 ] && echo 80 || echo 8080)} +61:# Start with our custom entrypoint +62:CMD ["/docker-entrypoint.sh"] +6: export NGINX_LISTEN_PORT=${NGINX_LISTEN_PORT:-80} +7: export NGINX_ACCESS_LOG=${NGINX_ACCESS_LOG:-/var/log/nginx/access.log} +8: export NGINX_ERROR_LOG=${NGINX_ERROR_LOG:-/var/log/nginx/error.log} +11: export NGINX_LISTEN_PORT=${NGINX_LISTEN_PORT:-8080} +12: export NGINX_ACCESS_LOG=${NGINX_ACCESS_LOG:-/dev/stdout} +13: export NGINX_ERROR_LOG=${NGINX_ERROR_LOG:-/dev/stderr} +26:echo "Starting SparkyFitness Frontend as ${NGINX_PERMISSION_MODE} with environment variables:" +27:echo " SPARKY_FITNESS_SERVER_HOST=${SPARKY_FITNESS_SERVER_HOST}" +28:echo " SPARKY_FITNESS_SERVER_PORT=${SPARKY_FITNESS_SERVER_PORT}" +29:echo " NGINX_RATE_LIMIT=${NGINX_RATE_LIMIT:-5r/s}" +30:echo " NGINX_LISTEN_PORT=${NGINX_LISTEN_PORT}" +31:echo " NGINX_ACCESS_LOG=${NGINX_ACCESS_LOG}" +32:echo " NGINX_ERROR_LOG=${NGINX_ERROR_LOG}" +33:echo " NGINX_DUMP_CONFIG=${NGINX_DUMP_CONFIG:-false}" +34:echo " SPARKY_FITNESS_FRONTEND_URL=${SPARKY_FITNESS_FRONTEND_URL}" +38:envsubst "\$SPARKY_FITNESS_SERVER_HOST \$SPARKY_FITNESS_SERVER_PORT \$NGINX_RATE_LIMIT \$SPARKY_FITNESS_FRONTEND_URL \$NGINX_LISTEN_PORT \$NGINX_ACCESS_LOG \$NGINX_ERROR_LOG" < /etc/nginx/templates/default.conf.template > /etc/nginx/conf.d/default.conf +42:if ! grep -q "${SPARKY_FITNESS_SERVER_HOST}:${SPARKY_FITNESS_SERVER_PORT}" /etc/nginx/conf.d/default.conf; then +44: echo "Expected to find: ${SPARKY_FITNESS_SERVER_HOST}:${SPARKY_FITNESS_SERVER_PORT}" +53:if [[ "${NGINX_DUMP_CONFIG}" == "true" ]]; then +59:if ! nginx "${NGINX_TEST_CONFIG_ARG}"; then +67:echo "Backend will be proxied to: ${SPARKY_FITNESS_SERVER_HOST}:${SPARKY_FITNESS_SERVER_PORT}" diff --git a/audits/sparkyfitness-source-reads-2026-10-05/server-env-reads.txt b/audits/sparkyfitness-source-reads-2026-10-05/server-env-reads.txt new file mode 100644 index 0000000..bee30a0 --- /dev/null +++ b/audits/sparkyfitness-source-reads-2026-10-05/server-env-reads.txt @@ -0,0 +1,102 @@ +# SparkyFitness v0.17.3 — env reads of the SERVER, read in upstream SOURCE at the tag (not inside the image) +# source: https://codeload.github.com/CodeWithCJ/SparkyFitness/tar.gz/refs/tags/v0.17.3, read 2026-10-05 (night burn-down, catalog lane) +# command: grep -rhoE 'process\.env\.[A-Z0-9_]+' --include=*.ts --include=*.js SparkyFitnessServer | sort -u + +AI_PHOTO_ESTIMATE_MAX_IMAGES +ALLOW_PRIVATE_NETWORK_CORS +BACKUP_DIR +BETTER_AUTH_SECRET +BETTER_AUTH_URL +DEV_TOOLS_ENABLED +EMAIL_PASS +EMAIL_USER +EXISTING_VAR +EXISTING_VAR_FILE +GARMIN_MICROSERVICE_URL +HTTPS_PROXY +HTTP_PROXY +NODE_ENV +NO_PROXY +OLLAMA_MODEL +OLLAMA_URL +PROMPT +SKIP_RLS_MATRIX +SPARKY_FITNESS_ADMIN_EMAIL +SPARKY_FITNESS_API_ENCRYPTION_KEY +SPARKY_FITNESS_API_KEY_RATELIMIT_MAX_REQUESTS +SPARKY_FITNESS_API_KEY_RATELIMIT_WINDOW_MS +SPARKY_FITNESS_APP_DB_PASSWORD +SPARKY_FITNESS_APP_DB_USER +SPARKY_FITNESS_CUSTOM_BACKUP_DIRECTORY +SPARKY_FITNESS_CUSTOM_TEMP_DIRECTORY +SPARKY_FITNESS_CUSTOM_UPLOADS_DIRECTORY +SPARKY_FITNESS_DB_HOST +SPARKY_FITNESS_DB_NAME +SPARKY_FITNESS_DB_PASSWORD +SPARKY_FITNESS_DB_PORT +SPARKY_FITNESS_DB_USER +SPARKY_FITNESS_DISABLE_EMAIL_LOGIN +SPARKY_FITNESS_DISABLE_SIGNUP +SPARKY_FITNESS_EMAIL_FROM +SPARKY_FITNESS_EMAIL_HOST +SPARKY_FITNESS_EMAIL_PASS +SPARKY_FITNESS_EMAIL_PORT +SPARKY_FITNESS_EMAIL_SECURE +SPARKY_FITNESS_EMAIL_USER +SPARKY_FITNESS_EXTRA_TRUSTED_ORIGINS +SPARKY_FITNESS_FITBIT_DATA_SOURCE +SPARKY_FITNESS_FORCE_EMAIL_LOGIN +SPARKY_FITNESS_FRONTEND_URL +SPARKY_FITNESS_GOOGLE_HEALTH_DATA_SOURCE +SPARKY_FITNESS_HEVY_DATA_SOURCE +SPARKY_FITNESS_LOG_LEVEL +SPARKY_FITNESS_OIDC_AUTH_ENABLED +SPARKY_FITNESS_OIDC_AUTO_REDIRECT +SPARKY_FITNESS_OIDC_AUTO_REGISTER +SPARKY_FITNESS_OIDC_CLIENT_ID +SPARKY_FITNESS_OIDC_CLIENT_SECRET +SPARKY_FITNESS_OIDC_DOMAIN +SPARKY_FITNESS_OIDC_ID_TOKEN_SIGNED_ALG +SPARKY_FITNESS_OIDC_ISSUER_URL +SPARKY_FITNESS_OIDC_LOGO_URL +SPARKY_FITNESS_OIDC_PROVIDER_NAME +SPARKY_FITNESS_OIDC_PROVIDER_SLUG +SPARKY_FITNESS_OIDC_SCOPE +SPARKY_FITNESS_OIDC_TIMEOUT +SPARKY_FITNESS_OIDC_TOKEN_AUTH_METHOD +SPARKY_FITNESS_OIDC_USERINFO_SIGNED_ALG +SPARKY_FITNESS_POLAR_DATA_SOURCE +SPARKY_FITNESS_PUBLIC_API_DOCS +SPARKY_FITNESS_SAVE_MOCK_DATA +SPARKY_FITNESS_SERVER_PORT +SPARKY_FITNESS_STRAVA_DATA_SOURCE +SPARKY_FITNESS_UPLOADS_DIR +SPARKY_FITNESS_WITHINGS_DATA_SOURCE +TEST_SECRET +TEST_SECRET_FILE + +# the key/secret/token/pem/password subset (checklist 1.6), with what the template does with each: + 4 BETTER_AUTH_SECRET + 1 EMAIL_PASS + 2 SPARKY_FITNESS_API_ENCRYPTION_KEY + 1 SPARKY_FITNESS_API_KEY_RATELIMIT_MAX_REQUESTS + 1 SPARKY_FITNESS_API_KEY_RATELIMIT_WINDOW_MS + 3 SPARKY_FITNESS_APP_DB_PASSWORD + 6 SPARKY_FITNESS_DB_PASSWORD + 1 SPARKY_FITNESS_EMAIL_PASS + 5 SPARKY_FITNESS_OIDC_CLIENT_SECRET + 2 SPARKY_FITNESS_OIDC_ID_TOKEN_SIGNED_ALG + 2 SPARKY_FITNESS_OIDC_TOKEN_AUTH_METHOD + 3 TEST_SECRET + 3 TEST_SECRET_FILE + +BETTER_AUTH_SECRET set: ${BETTER_AUTH_SECRET} (generated, data_key) +SPARKY_FITNESS_API_ENCRYPTION_KEY set: ${API_ENCRYPTION_KEY} (generated, data_key) +SPARKY_FITNESS_DB_PASSWORD set: ${DB_PASSWORD} (generated) +SPARKY_FITNESS_APP_DB_PASSWORD set: ${APP_DB_PASSWORD} (generated) +SPARKY_FITNESS_OIDC_CLIENT_SECRET unset: read only when SPARKY_FITNESS_OIDC_AUTH_ENABLED (unset = off); no sign-in provider is offered +SPARKY_FITNESS_EMAIL_PASS / EMAIL_PASS unset: mail is not mapped (no smtp_mapping); the relay takes no login anyway +SPARKY_FITNESS_API_KEY_RATELIMIT_* not a secret (rate-limit numbers) +SPARKY_FITNESS_OIDC_*_ALG / _METHOD not a secret (OIDC algorithm names; OIDC off) +TEST_SECRET / TEST_SECRET_FILE test code only +=> no key or secret the server reads is left at an image default or empty on a route the template enables. diff --git a/onboarding/sparkyfitness.md b/onboarding/sparkyfitness.md index 39f57da..517c3a8 100644 --- a/onboarding/sparkyfitness.md +++ b/onboarding/sparkyfitness.md @@ -25,8 +25,8 @@ catalog): felhom.eu/documentation/audits/visitors-2026-10-01/C/box/sparky-box.tx 1.3 | done | app-catalog-felhom.eu/templates/sparkyfitness/docker-compose.yml — postgres:18 mounted at /var/lib/postgresql 1.4 | done | felhom.eu/documentation/audits/visitors-2026-10-01/C/bench/move/evidence/MV-sparkyfitness/verdict.json ; felhom.eu/documentation/audits/visitors-2026-10-01/C/bench/move/evidence/MV-sparkyfitness/migration-lines.txt — v0.17.2 seeded, stepped INTO v0.17.3, the server ran its own migrations, read back; the undo came back in 31.3 s with the data 1.5 | done | felhom.eu/documentation/audits/visitors-2026-10-01/C/box/sparky-box.txt — node (tsx) runs the server; nginx serves the frontend -1.6 | open | the env names the server reads were not listed from its source; the set ones are the two DB passwords, API_ENCRYPTION_KEY, BETTER_AUTH_SECRET -1.7 | open | the image's entrypoint was not read +1.6 | done | app-catalog-felhom.eu/audits/sparkyfitness-source-reads-2026-10-05/server-env-reads.txt — every env read of the server source at v0.17.3 listed (2026-10-05, R-786); the keys and secrets it reads are set (BETTER_AUTH_SECRET, API_ENCRYPTION_KEY, both DB passwords) or belong to a route the template leaves off (OIDC client secret, mail password) +1.7 | open | read in upstream SOURCE at the tag only (app-catalog-felhom.eu/audits/sparkyfitness-source-reads-2026-10-05/entrypoint-source-read.txt, 2026-10-05): the server has no entrypoint script (CMD tsx index.ts); the frontend's switches are NGINX_LISTEN_PORT (set 80), NGINX_RATE_LIMIT, NGINX_DUMP_CONFIG and the log paths (defaults) — the read INSIDE the image is still owed (R-786) 1.8 | done | felhom.eu/documentation/audits/visitors-2026-10-01/C/box/sparky-box.txt — an unknown page answers the app's own page (200, the SPA), an unknown API 401; no stack trace 1.9 | done | app-catalog-felhom.eu/templates/sparkyfitness/.felhom.yml — API_ENCRYPTION_KEY and BETTER_AUTH_SECRET carry data_key with the reason 2.1 | open | re-sweep 2026-10-02 with the fixed gate (felhom.eu/documentation/audits/persistence-sweep-2026-10-02/A/sweep/TABLE.md): UNDETERMINED — the server's backup and uploads volumes stay empty after the seed (it writes only to the database); nothing written outside a preserved folder (R-807). The 2026-10-01 CLEAN came from start-time writes alone