Skip to content

New landing page - #42

Merged
fakebizprez merged 10 commits into
masterfrom
feature/new-landing-page
Aug 7, 2026
Merged

fakebizprez merged 10 commits into
masterfrom
feature/new-landing-page

Conversation

@fakebizprez

@fakebizprez fakebizprez commented Aug 7, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Branch already contains recent work: health/ops endpoints with hardened auth and webhooks, expanded test suite, temperature calibration and debugging improvements, env var parsing refactor, docker-build CI fix, and .env.example documentation.

Test plan

  • Run for f in test_*.py; do [ "$f" = "test_support.py" ] && continue; python "$f" || break; done
  • Run python -m unittest discover -v -p 'test_*.py'

🤖 Generated with Claude Code

Summary by Sourcery

Introduce a templated landing dashboard, harden configuration/auth/webhook behavior, and expand tests/CI to cover production-like behavior and deployment artifacts.

New Features:

  • Serve the main dashboard from a standalone Jinja2 template with a pixel-art landing page and add a mock Sense HAT driver selectable via USE_MOCK_SENSOR.
  • Expose additional temperature calibration metadata and compensation status via existing JSON APIs and enhance the health endpoint with staleness and compensation signals.

Bug Fixes:

  • Prevent a local Sense HAT stub from shadowing the real hardware driver, ensuring production reads real sensor data unless USE_MOCK_SENSOR is explicitly set.
  • Fix multiple authentication edge cases around bearer token handling, status codes, and error formatting to avoid bypasses and HTML error responses in JSON APIs.
  • Make environment variable parsing for booleans and numerics robust to empty/invalid values and fail-fast with clear messages instead of crashing at import or silently misconfiguring behavior.
  • Ensure webhook configuration and alert threshold invariants are validated both at API level and on env-based startup, rejecting invalid ranges and nulls that would previously be accepted.
  • Correct periodic status update scheduling and startup behavior so timers are initialized consistently, do not drift over time, and respect configuration when the webhook service is created late.
  • Require auth on the metrics endpoint and tighten the health check so it reflects sensor thread liveness and reading staleness instead of always reporting healthy.
  • Stop unbounded log file growth by using rotating logging and ensure Docker images include required templates so the dashboard route works in containerized deployments.
  • Fix webhook retry/backoff and success detection semantics so all 2xx responses are treated as success, cooldowns use a monotonic clock, and recovery notifications clear stale cooldowns.
  • Prevent webhook secrets from leaking via logs by masking URLs and paths in responses and exception messages, and by truncating logged response bodies.

Enhancements:

  • Refactor temp_monitor configuration to centralize environment parsing helpers, calibration constants, and webhook cooldown into clear, test-backed helpers.
  • Extend webhook service behavior with explicit recovery notifications, active-alert tracking, and structured Slack payloads that include fallback and markdown metadata.
  • Harden API models and error schemas so validation errors and 500s return consistent JSON structures with error messages and correlation IDs.
  • Improve sensor math observability by exposing calibration constants and compensation flags via APIs and logging, while documenting known limitations in temperature averaging.
  • Replace the Flask-RESTX root route with a custom API subclass to avoid shadowing the dashboard and make routing order-independent.
  • Document temperature calibration, mock sensor usage, alert cooldown behavior, and testing practices more thoroughly in README, CLAUDE, AGENTS, and GEMINI guidance files.
  • Add a systematic debugging skill and Firecrawl-related skills/metadata for AI coding agents without affecting runtime behavior.

Build:

  • Update Dockerfile to include templates, avoid bundling mock Sense HAT files into the image, and use a curl-free healthcheck compatible with minimal base images.
  • Change docker-compose to load environment variables via env_file instead of binding .env directly, avoiding silent directory creation when the file is missing.
  • Tighten Python dependency versions (Flask/Flask-RESTX/Werkzeug/Jinja2/Waitress) for better compatibility and stability.

CI:

  • Expand CI to run every test file both script-style and via unittest discovery, and add a docker-build job that boots the built image to verify key endpoints in a real container.

Documentation:

  • Revise README, CLAUDE, AGENTS, and GEMINI documentation to reflect the new landing page, calibration/env var behavior, metrics protection, alert cooldown defaults, and testing workflow.

Tests:

  • Replace the ad-hoc periodic update test script with real unittest cases that exercise production logic via fresh imports and single-loop runs.
  • Greatly expand test coverage for webhooks, env parsing, API models, auth, dashboard routing, health/metrics, sensor math/integrity, and webhook retry/backoff, including end-to-end and regression tests for previously reported bugs.
  • Add shared test helpers for mocking Sense HAT, configuring bearer tokens, and cold-starting temp_monitor in subprocesses to accurately simulate startup scenarios.

Greptile Summary

The PR introduces a standalone landing dashboard and substantially hardens sensor configuration, authenticated APIs, webhook behavior, health reporting, tests, and container deployment.

  • Moves the dashboard into a Jinja2 template and packages it in the production image.
  • Adds explicit mock-sensor selection, calibration metadata, and stronger health and metrics behavior.
  • Centralizes environment parsing and expands webhook validation, retry, cooldown, and recovery handling.
  • Broadens automated coverage and adds container-build verification.

Confidence Score: 4/5

The PR is not yet safe to merge because threshold-only webhook configuration remains hidden by the configuration GET endpoint.

A threshold-only update stores active alert thresholds in WebhookService without creating webhook_config, while GET /api/webhook/config still treats the missing webhook_config as equivalent to a missing service and returns null thresholds.

Files Needing Attention: temp_monitor.py

Important Files Changed

Filename Overview
temp_monitor.py Refactors application initialization, dashboard routing, authentication, sensor processing, webhook configuration, health checks, and metrics.
webhook_service.py Adds configuration invariants and strengthens webhook retries, cooldown handling, recovery notifications, and secret-safe diagnostics.
api_models.py Centralizes API validation around shared configuration ranges and robust partial-update semantics.
templates/index.html Adds the standalone pixel-art landing dashboard rendered by the root route.
Dockerfile Packages templates, excludes mock sensor modules, and adds a minimal-image-compatible health check.
.github/workflows/ci.yml Expands Python test execution and adds a built-container endpoint smoke test.

Reviews (2): Last reviewed commit: "Add .env.example file and update documen..." | Re-trigger Greptile

fakebizprez and others added 10 commits January 23, 2026 12:53
- Moved inline HTML from `temp_monitor.py` to a new `index.html` file in the `templates` directory.
- Updated the `index` function to use `render_template` instead of `render_template_string`.
- Enhanced the styling and layout of the HTML for improved aesthetics and readability.
- Add /health, /metrics, and config endpoints with dedicated tests
- Harden Bearer token auth and sensor data integrity checks
- Improve webhook retry/backoff logic and add regression tests
- Rename sense_hat.py -> mock_sense_hat.py and server.log -> logs/.gitkeep
- Add .dockerignore and CI workflow updates for cleaner ARM builds
- Add handoff skill for agent session handoffs
- Introduced new environment variables: `USE_MOCK_SENSOR`, `TEMP_CPU_FACTOR`, `TEMP_OFFSET_F`, and `HUMIDITY_OFFSET` for improved temperature and humidity calibration.
- Updated `get_compensated_temperature()` to utilize these variables, allowing for dynamic calibration without code changes.
- Enhanced logging to provide calibration details in the API response.
- Added regression tests to ensure calibration parameters are correctly applied and adjustable by operators.
- Introduced centralized parsing functions for boolean and numeric environment variables to ensure consistent handling and error reporting.
- Updated existing environment variable usages in `temp_monitor.py` to utilize the new parsing functions, improving reliability and maintainability.
- Enhanced documentation in `CLAUDE.md` to clarify the expected formats for boolean variables.
- Improved test suite by refactoring test classes to inherit from a base test class, streamlining setup processes.
The docker-build job boots the production image on an x86 GitHub runner,
which has no Sense HAT. temp_monitor.py constructs SenseHat() at import
time, so the real sense-hat package raised "Cannot detect RPi-Sense FB
device" and waitress died before binding port 8080. Every one of the 30
health-check attempts then got connection refused. The job has never
passed since it was added in 98852b8.

Set USE_MOCK_SENSOR=1 and bind-mount mock_sense_hat.py from the checkout
rather than adding it to the image. The mock is deliberately excluded
from the image by both the Dockerfile COPY list and .dockerignore, and
this keeps that guarantee intact: the image under test remains
byte-for-byte what ships to the Pi, and the stub lives only as long as
the CI container.

Verified locally against a real build of the image: reproduced the
original OSError, then confirmed the fixed invocation serves GET / and
GET /health with 200 and renders the real dashboard template.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Introduced a new `.env.example` file to provide a template for required and optional environment variables, including `BEARER_TOKEN`, `LOG_FILE`, `CLOUDFLARED_TOKEN`, and webhook configurations.
- Updated `AGENTS.MD`, `CLAUDE.md`, and `README.md` to reflect changes in alert cooldown settings and temperature calibration parameters.
- Enhanced documentation for environment variable parsing and validation to improve clarity and consistency.
- Added tests for environment variable parsing to ensure robustness against invalid configurations.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @fakebizprez, your pull request is larger than the review limit of 150000 diff characters

@sourcery-ai

sourcery-ai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors the temp monitor service to add a new templated landing page, harden environment parsing and authentication, improve health/ops behavior, strengthen webhook configuration/alerting robustness, and significantly expand test coverage and CI to catch regressions (including Docker image verification).

Sequence diagram for PUT webhook config and service initialization

sequenceDiagram
    actor Client
    participant Resource as WebhookConfigResource
    participant Models as api_models
    participant Service as WebhookService
    participant WC as WebhookConfig
    participant AT as AlertThresholds

    Client->>Resource: PUT /api/webhook/config
    Resource->>Resource: parse payload (webhooks_ns.payload)
    Resource->>Models: validate_webhook_config(webhook)
    Models-->>Resource: (is_valid, error_msg)
    alt invalid webhook
      Resource->>Resource: webhooks_ns.abort(400,...)
    end
    Resource->>Models: validate_thresholds(thresholds,current_thresholds)
    Models-->>Resource: (is_valid, error_msg)
    alt invalid thresholds
      Resource->>Resource: webhooks_ns.abort(400,...)
    end
    Resource->>Resource: service_created_by_this_request = (webhook_service is None)
    alt webhook config provided
      opt no existing service
        Resource->>Service: new WebhookService(alert_cooldown)
      end
      Resource->>WC: new WebhookConfig(merged fields)
      WC-->>Resource: may raise ConfigValidationError
      Resource->>Service: set_webhook_config(config)
    end
    alt thresholds provided
      opt no existing service
        Resource->>Service: new WebhookService(alert_thresholds,alert_cooldown)
      end
      Resource->>AT: new AlertThresholds(merged fields)
      AT-->>Resource: may raise ConfigValidationError
      Resource->>Service: set_alert_thresholds(thresholds)
    end
    alt ConfigValidationError
      Resource->>Resource: webhooks_ns.abort(400,str(e))
    end
    alt service_created_by_this_request and status_update_enabled
      Resource->>Resource: last_status_update = time.time()
    end
    Resource-->>Client: 200 SuccessResponse
Loading

File-Level Changes

Change Details Files
Replace the inline HTML landing page with a Jinja2 template, ensure RESTX docs no longer shadow '/', and lock metrics behind auth while tightening health semantics.
  • Swap render_template_string for render_template with a new templates/index.html dashboard and update Docker image to include templates/ plus Jinja2 dependency.
  • Introduce _DashboardSafeApi subclass so Flask-RESTX does not auto-register a root '/' route that 404s over the dashboard, and add tests ensuring no documented route 404s or has duplicate URL rules.
  • Require bearer token on /metrics, keep /health public but change it to return 503 when the sensor thread is dead or readings are stale, and expose only liveness/calibration flags there.
temp_monitor.py
templates/index.html
Dockerfile
requirements.txt
test_dashboard.py
test_health.py
CLAUDE.md
AGENTS.MD
README.md
Centralize and harden environment variable parsing, sensor driver selection, temperature/humidity calibration, and logging behavior.
  • Add _parse_env_bool/_parse_env_number helpers with consistent truthy/falsy semantics and clear RuntimeError messages, then apply them to USE_MOCK_SENSOR, status update flags/intervals, webhook settings, alert thresholds, calibration constants, and cooldown.
  • Introduce USE_MOCK_SENSOR-controlled import of mock_sense_hat.SenseHat to avoid shadowing the real sense-hat package; log which driver/path was loaded and update tests/README/CLAUDE to describe the calibration procedure and mock usage.
  • Replace basicConfig FileHandler with a RotatingFileHandler on the root logger and add tests to ensure bounded log size and no plain FileHandler is used.
temp_monitor.py
mock_sense_hat.py (referenced only)
test_env_parsing.py
test_sensor_integrity.py
test_sensor_math.py
test_ops.py
CLAUDE.md
AGENTS.MD
README.md
Strengthen temperature/humidity sensing, calibration reporting, and health/staleness tracking semantics.
  • Track current_temp_compensated and last_updated_ts, update them in the sensor loop, and include compensated plus calibration parameters in /api/temp and /api/raw responses.
  • Refactor get_compensated_temperature/get_humidity to use module-level TEMP_CPU_FACTOR/TEMP_OFFSET_F/HUMIDITY_OFFSET, handle CPU temperature unavailability with logging and an uncompensated flag, and document the known bimodal outlier-trim defect in comments and tests.
  • Make /health consider both sensor_thread.is_alive() and staleness_threshold_seconds when deciding healthy vs unhealthy, returning 200 or 503 accordingly and including staleness/age and compensation flags without leaking raw readings.
temp_monitor.py
test_sensor_math.py
test_health.py
CLAUDE.md
AGENTS.MD
README.md
Harden bearer-token authentication, unauthenticated error responses, and WWW-Authenticate behavior across Flask and Flask-RESTX endpoints.
  • Update require_token to use constant-time hmac.compare_digest on UTF-8–encoded tokens, reject malformed Authorization headers like 'Bearer junk', and return 401 (not 403) for invalid tokens.
  • Add a JSON-producing 401 errorhandler plus an after_request hook that ensures WWW-Authenticate: Bearer on all 401 responses, so both plain Flask routes and RESTX resources behave consistently.
  • Add comprehensive tests that exercise auth behavior (success, wrong token, missing header, non-ASCII tokens) and verify every protected endpoint enforces auth and that require_token still raises (abort) rather than returning a Response that marshal_with could silently turn into 200.
  • Update tests that previously expected 403s and README/CLAUDE auth docs accordingly.
temp_monitor.py
test_auth.py
test_webhook_api.py
CLAUDE.md
AGENTS.MD
README.md
Make webhook configuration, alert thresholds, cooldowns, alert recovery, and Slack formatting robust to bad inputs and time anomalies while closing several security/privacy gaps.
  • Add ConfigValidationError, range constants, and post_init invariants to WebhookConfig/AlertThresholds; wire temp_monitor.py to catch ConfigValidationError at env-init and API time and re-raise as RuntimeError/400 with clear messages, and add tests for env handling and dataclass invariants.
  • Refactor webhook_service.WebhookService to accept an alert_cooldown parameter, use time.monotonic for cooldown tracking, track active_alerts, emit resolved notifications on threshold recovery while clearing cooldowns, and treat any 2xx as success with cooldown recording.
  • Introduce _scrub_text/_scrub_exception to strip Slack webhook URLs and paths from response bodies and exception messages before logging, replace fixed timeout log messages with scrubbed versions, and add tests that secrets never leak even when urlparse fails.
  • Extend Slack payloads to include fallback/mrkdwn_in, expose cooldown and recovery semantics via new tests, and wire API-level validation (api_models.validate_webhook_config/validate_thresholds) to share range constants and handle null/partial-update and type errors cleanly.
webhook_service.py
api_models.py
temp_monitor.py
test_webhook.py
test_api_models.py
test_config_endpoint.py
CLAUDE.md
AGENTS.MD
Fix and extend periodic status update scheduling, including environment-driven configuration, startup behavior, and interaction with webhook creation via API.
  • Replace ad hoc test script with a unittest-based test_periodic_updates that imports the real module logic (including env parsing and in-loop scheduling) via a run_fresh_import helper and drives update_sensor_data through a single iteration with mocks.
  • Anchor status update scheduling at (previous_last_status_update + interval) rather than current_time to prevent drift, clamp STATUS_UPDATE_INTERVAL only when status_update_enabled is true, and ensure webhook services created later via PUT /api/webhook/config start their timers without spuriously honoring STATUS_UPDATE_ON_STARTUP.
  • Introduce alert_cooldown_seconds from ALERT_COOLDOWN_SECONDS env, pass it consistently when instantiating WebhookService both at module-init and via the config endpoint, and test that newly-created services pick up the configured cooldown rather than defaulting silently.
temp_monitor.py
test_periodic_updates.py
test_config_endpoint.py
CLAUDE.md
AGENTS.MD
Improve CI to run tests in both script and discover modes and add a Docker-build job that verifies the shipped image actually serves the dashboard and health endpoints.
  • Change the GitHub Actions 'tests' job to loop over all test_*.py (excluding shared helpers) and run each directly, then also run unittest discover to catch tests that a file’s custom main() doesn’t register or that only fail under one invocation style.
  • Add a docker-build job that builds the image, runs a container with USE_MOCK_SENSOR and a bind-mounted mock_sense_hat.py, waits for /health to come up, and checks that GET / returns 200 and that /health returns 200, logging container output for debugging.
  • Update Dockerfile to copy templates into the image, remove sense_hat.py from the build, switch HEALTHCHECK to use urllib instead of requests, and adjust start_production.sh to call waitress-serve with the wsgi:app positional form.
.github/workflows/ci.yml
Dockerfile
start_production.sh
CLAUDE.md
AGENTS.MD
Expand and consolidate shared test infrastructure and documentation for agents (Claude/Gemini) and firecrawl integration.
  • Add test_support.py with shared BEARER_TOKEN setup, sense_hat mocking, a BaseAPITestCase, and a run_fresh_import helper, and refactor multiple test files to use it instead of inlining boilerplate mocks/import hacks.
  • Add several new test modules (test_dashboard.py, test_env_parsing.py, test_sensor_integrity.py, test_ops.py, test_sensor_math.py, test_webhook_retry.py, test_auth.py, test_config_endpoint.py, test_health.py) to cover dashboard routing, env parsing, sensor mocking behavior, ops endpoints, calibration math, retry behavior, auth, config endpoint semantics, and health behavior.
  • Add GEMINI.md, firecrawl skill descriptors and wiring (.agents/skills/firecrawl-agent, .codex/.cursor hooks), and systematic-debugging skill docs under .agents/skills/systematic-debugging to guide AI agents working on this repo, and update CLAUDE.md/AGENTS.MD/README to reflect new env vars, endpoints, calibration guidance, and test/CI commands.
test_support.py
test_dashboard.py
test_env_parsing.py
test_sensor_integrity.py
test_ops.py
test_sensor_math.py
test_webhook_retry.py
test_auth.py
test_config_endpoint.py
test_health.py
GEMINI.md
.agents/skills/systematic-debugging/*
.agents/skills/firecrawl-agent/SKILL.md
.codex/skills/firecrawl
.cursor/skills/firecrawl
CLAUDE.md
AGENTS.MD
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@fakebizprez

Copy link
Copy Markdown
Member Author

@coderabbitai review

@fakebizprez

Copy link
Copy Markdown
Member Author

@greptileai review

@fakebizprez
fakebizprez merged commit ea9fbe2 into master Aug 7, 2026
6 checks passed
@fakebizprez
fakebizprez deleted the feature/new-landing-page branch August 7, 2026 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant