Skip to content

docs: monitoring links for both environments, and a correctness pass on the README - #160

Merged
aditeyabaral merged 7 commits into
pesu-dev:devfrom
aditeyabaral:docs/deployment-links
Sep 15, 2026
Merged

aditeyabaral merged 7 commits into
pesu-dev:devfrom
aditeyabaral:docs/deployment-links

Conversation

@aditeyabaral

@aditeyabaral aditeyabaral commented Sep 14, 2026

Copy link
Copy Markdown
Member

📌 Description

The deployment section at the top of the README listed one monitoring link — production's health
check page — and four unlabelled status badges. It now covers both environments, and one factual
error is corrected.

All monitoring in one table, keyed by environment and check, so a reader can tell what each
badge is measuring. The four production badges were previously bare images in a row with nothing
saying which check or which environment they belonged to.

Environment Check Status
Production Docs · Health · Authentication · Authentication with Profile Data 4 badges
Staging the same four checks 4 badges (new)
Both Detailed metrics and KPIs Grafana badge (new)

Links added. Staging's health check page — https://6ns95sgb.status.cron-job.org — existed and
was already referenced from CONTRIBUTING.md, so it was reachable to contributors but invisible to
anyone reading the README. The Grafana dashboard covering both environments is now linked too, tied
back to the /metrics section so a reader can see where its numbers come from.

Region corrected. The warning claimed the live version is hosted in the United States. Both
environments run in Singapore, which also understated the service: Singapore is far closer than
the US both to the users and to PESU Academy itself, which every authentication waits on.

Also drops a "seven days of history per check" line that the table makes redundant.

📋 And a correctness pass on the rest of the README

Auditing the whole file against the published schema — comparing documented endpoints, status codes
and model fields against app.openapi(), RequestModel, ProfileModel, ResponseModel and
MetricsModel — turned up three defects that predate this PR.

Only /metrics documented its response codes. /authenticate can answer with six (200, 400,
401, 422, 500, 502) and the README named none, so nothing told a caller that a 502 means PESU
Academy is unreachable or that a 422 means their profile page changed shape. It now has a table;
/health and /readme get a sentence each, since tabulating a success plus the universal 500
would be padding.

Both example timestamps were malformed2024-07-28 22:30:10.103368+05:30 with a space, where
the API serialises via datetime.isoformat() and always emits a T. Anyone parsing against the
documented shape would have failed on a real response, and the OpenAPI examples disagreed with the
README.

The cURL example's response heading was a level too shallow, so it rendered as a section of its
own rather than part of #### cURL, while Python's matching block was nested correctly.

What the audit confirmed was already right: all four endpoints have sections, every
RequestModel / ResponseModel / ProfileModel / MetricsModel field appears (campusCode and
friends by their camelCase wire names, not the Python attribute names), all 24 metric families and
all 20 JSON fields are covered, and the Python version claims match requires-python = ">=3.14".

ℹ️ Fixes / Related Issues
No issue. Follows #157#159, which built /metrics and the token the dashboard scrapes through.

🧱 Type of Change

  • 🐛 Bug fix – Non-breaking fix for a functional/logic error
  • ✨ New feature – Adds functionality without breaking existing APIs
  • ⚠️ Breaking change – Introduces backward-incompatible changes (API, schema, etc.)
  • 📝 Documentation update – README, docstrings, OpenAPI tags, etc.
  • 🧪 Test suite change – Adds/updates unit, functional, or integration tests
  • ⚙️ CI/CD pipeline update – Modifies GitHub Actions, pre-commit, or Docker build
  • 🧹 Code quality / Refactor – Improves structure, readability, or style (no functional changes)
  • 🐢 Performance improvement – Speeds up auth, scraping, or reduces I/O
  • 🕵️ Debug/logging enhancement – Adds or improves logging/debug support
  • 🔧 Developer tooling – Scripts, benchmarks, local testing improvements
  • 🔒 Security fix – Addresses auth/session/data validation vulnerabilities
  • 🧰 Dependency update – Updates libraries in requirements.txt, pyproject.toml

🧪 How Has This Been Tested?

  • Unit Tests (tests/unit/)
  • Functional Tests (tests/functional/)
  • Integration Tests (tests/integration/)
  • Manual Testing

276 tests, 100.00% coverage, unchanged — no code is touched. pre-commit run --all-files
passes 12/12 hooks.

Manual checks, since this PR is almost entirely URLs:

  • All eight status badges fetched, all 200 — and each was matched to its row by the job name
    embedded in its own SVG <title>, not by the order it was supplied in. That is what placed
    "Simple authentication" and "Profile data" against the right checks; production's existing four
    were re-verified the same way.
  • Both status pages and the Grafana dashboard return 200.
  • The Grafana shields badge renders as a real SVG titled Grafana: metrics & KPIs.
  • The README's internal links resolve against its actual headings — both of them, not just the new
    #metrics one.
  • The Grafana URL in the file was byte-compared against the intended one, and it is the only
    Grafana URL present.
  • Every command the README gives was actually run this session: the Docker build and both
    docker run forms, uv run python -m app.app, and the test runner.

⚙️ Test Configuration:

  • OS: Linux
  • Python: 3.14.4 via uv
  • Docker build tested

Unchecked: nothing in the image or its behaviour changes.

✅ Checklist

  • My code follows the CONTRIBUTING.md guidelines
  • I've performed a self-review of my changes
  • I've added/updated necessary comments and docstrings
  • I've updated relevant docs (README or endpoint docs)
  • No new warnings introduced
  • I've added tests to cover my changes
  • All tests pass locally (scripts/run_tests.py)
  • I've run linting and formatting (pre-commit run --all-files)
  • Docker image builds and runs correctly
  • Changes are backwards compatible (if applicable)
  • Feature flags or .env vars updated (if applicable)
  • I've tested across multiple environments (if applicable)
  • Benchmarks still meet expected performance (scripts/benchmark/benchmark_requests.py)

Unchecked items carry no work here: no code, so no docstrings and no tests; no image change; no new
variables; nothing on a request path a benchmark measures.

🛠️ Affected API Behaviour

  • app/app.py – Modified /authenticate route logic
  • app/pesu.py – Updated scraping or authentication handling

Only README.md.

🧩 Models

  • app/models/request.py – Input validation or request schema changes
  • app/models/response.py – Authentication response formatting
  • app/models/profile.py – Profile extraction logic

🐳 DevOps & Config

  • Dockerfile – Changes to base image or build process
  • .github/workflows/*.yaml – CI/CD pipeline or deployment updates
  • pyproject.toml / requirements.txt – Dependency version changes
  • .pre-commit-config.yaml – Linting or formatting hook changes

Project version only, 4.4.0 → 4.5.0, plus the matching uv.lock. No dependency changes.

📊 Benchmarks & Analysis

  • scripts/benchmark/benchmark_requests.py – Performance or latency measurement changes
  • scripts/benchmark/analyze_benchmark.py – Benchmark result analysis changes
  • scripts/run_tests.py – Custom test runner logic or behavior updates

🧠 Additional Notes

The staging badge URLs could not be derived and had to come from the maintainer. Recorded because
the next person will look: a cron-job.org badge is
api.cron-job.org/jobs/<id>/<token>/status-7.svg, where the token is a per-job secret. The status
page is a client-side app that serves the same HTML for every path, and its private API
(POST https://api.cron-job.org/ with X-API-Method: GetPublicStatusPage) returns the four
monitor titles with no identifiers attached. They exist only in the console.

The Grafana badge is static. A live one would need shields.io to read a value, and both routes
are closed: the public-dashboard query API is POST-only where shields issues GET, and /metrics now
requires a bearer token shields cannot send. /health is open and could drive a dynamic badge, at
the cost of shields polling the service on every README view.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VU7YUhP71KSsotWQ1H7CRH

aditeyabaral and others added 2 commits September 13, 2026 22:57
The deployment section listed only production's health check page, so staging's — which exists and
is already linked from CONTRIBUTING.md — was undiscoverable from the README. It is now beside
production's.

Adds the Grafana dashboard covering both environments, built on the counters `/metrics` exposes,
and links it back to that section so a reader can see where the numbers come from.

The existing status badges are labelled **Production**, since four unlabelled badges gave no
indication of which environment or which check each one was.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VU7YUhP71KSsotWQ1H7CRH
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VU7YUhP71KSsotWQ1H7CRH
@aditeyabaral
aditeyabaral requested a review from a team as a code owner September 14, 2026 03:57
aditeyabaral and others added 4 commits September 13, 2026 23:05
Both environments run in Singapore, not the United States. The claim predates this and was simply
wrong; it also understated the service, since Singapore is a great deal closer than the US both to
the users and to PESU Academy itself, which every authentication waits on.

Reworded to cover both environments rather than "the live version", now that the README links
staging as well.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VU7YUhP71KSsotWQ1H7CRH
Four unlabelled badges in a row said nothing about which check each one was, and left no room for a
second environment. A table names every check and gives staging a column to drop into.

The metrics dashboard gets a badge of its own beneath it, so all the monitoring surfaces are in one
place rather than split between prose and images.

The staging column is not filled in. A cron-job.org badge URL carries a per-job token that exists
only inside the owning account: the status page is a client-side app that returns the same HTML for
every path, and its API (`X-API-Method: GetPublicStatusPage`) returns the four monitor titles with
no identifiers attached. The URLs have to be copied out of the console.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VU7YUhP71KSsotWQ1H7CRH
Replaces the two-column layout with rows keyed by environment and check, and moves the metrics
dashboard into the table as a row of its own so every monitoring surface is in one place. Drops the
"seven days of history" line.

Staging's four cells link to its status page rather than carrying badges, and they are identical
because there is nothing yet to tell them apart: a cron-job.org badge URL carries a per-job token
that only exists inside the owning account. They become real badges as soon as those four URLs are
copied out of the console.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VU7YUhP71KSsotWQ1H7CRH
Fills the four staging cells, so the table now carries all eight checks plus the dashboard.

Each badge was fetched and matched by the job name embedded in its own SVG title rather than by the
order it arrived in, which is how "Simple authentication" and "Profile data" were placed against
the right rows. All eight return 200, and production's existing four were re-checked the same way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VU7YUhP71KSsotWQ1H7CRH
@aditeyabaral aditeyabaral changed the title docs: link the staging health checks and the metrics dashboard docs: link both environments' monitoring, and correct the deployment region Sep 15, 2026
Found auditing the README against the published schema rather than reading it.

**Only `/metrics` documented its response codes.** `/authenticate` can answer with six — 200, 400,
401, 422, 500 and 502 — and the README named none of them, so a caller integrating against it had
no way to learn that a `502` means PESU Academy is unreachable or that a `422` means their profile
page changed shape. It now has a table. `/health` and `/readme` get a sentence each instead, since
a table listing a success and the universal catch-all `500` would be padding.

**Both example timestamps were malformed.** They showed `2024-07-28 22:30:10.103368+05:30` with a
space, but the API serialises with `datetime.isoformat()`, which always separates with a `T`. A
reader parsing against the documented shape would have failed on real responses. The OpenAPI
examples had it right, so the two disagreed.

**The cURL example's response heading was a level too shallow**, making it a sibling of `#### cURL`
rather than part of it, so it read as a section of its own in the outline while Python's matching
block was nested correctly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VU7YUhP71KSsotWQ1H7CRH
@aditeyabaral aditeyabaral changed the title docs: link both environments' monitoring, and correct the deployment region docs: monitoring links for both environments, and a correctness pass on the README Sep 15, 2026
@aditeyabaral
aditeyabaral merged commit 59da9bc into pesu-dev:dev Sep 15, 2026
5 checks passed
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