Skip to content

Production-readiness pass before the demo: stable Python, real lint/CI, plain failures, honest docs - #2

Merged
e-allora merged 4 commits into
mainfrom
claude/patchowner-production-ready-hj7ai7
Oct 2, 2026
Merged

e-allora merged 4 commits into
mainfrom
claude/patchowner-production-ready-hj7ai7

Conversation

@e-allora

@e-allora e-allora commented Oct 2, 2026

Copy link
Copy Markdown
Owner

What this fixes

An audit of the repo and the deployed site (site/index.html is what Vercel serves) ahead of the demo video. The site copy, disclaimers, and About tab were already accurate; the gaps were in the repo's own plumbing and in a few places where the repo said more than the code does.

Breaks on a fresh checkout

  • .python-version pinned 3.14 (a release candidate). FastAPI fails to import there with the locked pydantic, so patchowner serve crashes and tests/test_state.py::test_web_act_endpoint_records_and_rejects fails. Pinned to 3.12 (what CLAUDE.md and requires-python already assumed). CI runs 3.12 and 3.13.
  • The repo's edit hook and CLAUDE.md both call uv run ruff, but ruff was not a dependency, and the hook read an empty CLAUDE_FILE_PATHS variable. Ruff is now a dev dependency with explicit config, the codebase is formatted once, and the hook is a small script that reads the edited path from stdin.

Failures that were tracebacks

  • A failed or non-JSON KEV download raised a raw URLError (HTTP 500 in serve mode). It is now a FeedError with one sentence for the person running the tool. The CLI exits 3; the web form shows the sentence. A bad download never overwrites an existing cache.
  • /replay refuses uploads over 5 MB before parsing, validates the look-back range, and escapes every error message. /act bounds field lengths.
  • Policy.parse reports short rows and non-numeric row numbers as PolicyError.

One real escaping gap

  • The report embeds client data as JSON inside a <script> tag with |safe. An asset name or advisory text containing </script> could end the tag. The JSON now escapes <, > and &; a test renders a hostile inventory and asserts the page still has exactly its own three script tags.

Repo said more than the code does

  • db/models.py and db/sesion.py were SQLAlchemy models for a hosted multi-tenant version: unused, undeclared dependencies, and contradicting the README's "deliberately not here yet". Moved to docs/design/db/ with a README that says exactly what they are.
  • CLAUDE.md described PostgreSQL, Alembic, Row-Level Security, continuous KEV sync, and rules files that do not exist. Rewritten around the actual stack with the transparency and disclaimer rules made explicit; planned work is labelled planned.
  • README: test count corrected (it said 86; there are now 101, four of which skip without the cached feed), supported Python versions stated, site/ and the design sketch added to the layout, CI badge.

New

  • .github/workflows/ci.yml: ruff + pytest on 3.12 and 3.13, plus a CLI smoke test. The four tests that replay the live catalog skip in CI so results never depend on CISA's servers.
  • SECURITY.md.

Not changed, and why

  • site/index.html is untouched. It is a build artifact and the template logic did not change in a way that alters the rendered page. This sandbox cannot reach cisa.gov, so I could not refresh the demo report to today's catalog version. If you want the Health tab to show a current date on camera, run uv run patchowner replay examples/inventory.csv --refresh && cp out/report.html site/index.html locally and push; everything else on the page already states its snapshot date.

Verification

uv run ruff check . && uv run ruff format --check .   # clean
uv run pytest -q                                      # 97 passed, 4 skipped
uv run patchowner replay examples/inventory.csv       # offline here: one sentence, exit 3

🤖 Generated with Claude Code

https://claude.ai/code/session_012ZCSLekTvZQ7X3PsAUJuXk


Generated by Claude Code

claude added 4 commits October 2, 2026 13:51
.python-version pointed at 3.14 (a release candidate). With the locked
pydantic, FastAPI fails to import there, so `patchowner serve` crashes and
one test fails on a fresh checkout. Pin 3.12, which CLAUDE.md and
requires-python already assume; 3.13 passes too.

CLAUDE.md and the repo hook both call `uv run ruff`, but ruff was not a
dependency, so the hook failed on every edit. Add ruff to the dev group
with an explicit config in pyproject.toml, run check --fix and format
once across the codebase, and replace the hook command (which relied on
an empty CLAUDE_FILE_PATHS variable) with a small script that reads the
edited path from the hook's stdin JSON.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ZCSLekTvZQ7X3PsAUJuXk
…ape report data

- kev.load_feed raises FeedError with a sentence for the person running
  the tool instead of a raw URLError or JSONDecodeError. A failed or
  non-JSON download never overwrites an existing cache. The CLI prints
  it and exits 3; the web form shows it in place of a 500.
- /replay refuses uploads over 5 MB before parsing, checks the look-back
  range, and shows every error as escaped text. /act bounds field sizes.
- Policy.parse reports short rows and non-numeric row numbers as
  PolicyError rather than IndexError/ValueError.
- The client-data JSON embedded in the report's <script> tag now escapes
  <, > and &, so an asset name or advisory text containing "</script>"
  cannot end the tag. Tests cover each of these.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ZCSLekTvZQ7X3PsAUJuXk
…ibe the real stack

db/models.py and db/sesion.py are SQLAlchemy models for a hosted
multi-tenant version that does not exist yet. Nothing imports them and
their dependencies are not installed, while the README says multi-tenant
views are deliberately not here. Keep the sketch, but under
docs/design/db with a README that says exactly what it is and is not.

CLAUDE.md described PostgreSQL, Alembic, Row-Level Security and a
continuous KEV sync, and pointed at rules files that do not exist.
Rewrite it around what the code actually does, keep the transparency
and disclaimer rules explicit, and list planned work as planned. The
security-auditor subagent now reviews the surfaces that exist.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ZCSLekTvZQ7X3PsAUJuXk
GitHub Actions runs ruff and pytest on Python 3.12 and 3.13 for every
push and pull request; the four tests that need the live KEV feed skip
there so results do not depend on CISA's servers. README gets the badge,
the real test count (101, four skipped without the cached feed), the
supported Python versions, and layout entries for site/ and the design
sketch. SECURITY.md says what the tool does and does not do and how to
report a problem in it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ZCSLekTvZQ7X3PsAUJuXk
@vercel

vercel Bot commented Oct 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
patchowner Ready Ready Preview Oct 2, 2026 1:52pm UTC

Request Review

@e-allora
e-allora marked this pull request as ready for review October 2, 2026 14:28
@e-allora
e-allora merged commit a8d5b9e into main Oct 2, 2026
6 checks passed

This branch was successfully deployed

1 active deployment
Preview — b665bb67 Deployed Oct 2, 2026 by vercel[bot]
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.

2 participants