feat(config): T-1259 — reach is a real command, and Typer vendors Click
`reach --help` runs from the console entrypoint in 80 ms. typer 0.27.1 and pydantic 2.13.4 join the dependencies, both CVE-checked against NVD, OSV and the GitHub Advisory Database. The design in the ticket did not survive contact. It specified a click.Group root, on the reasoning that it would keep typer off the --help path — but typer vendors Click as of 0.26.0, so there is no top-level click package to import and no supported way to extract typer's internal one. A click.Group root hosting Typer sub-apps would put two Click implementations in one process. The root is therefore a typer.Typer, and lazy registration will go through the supported typer.Typer(cls=...) surface with a TyperGroup subclass. T-1260 is corrected to match. The callback is not decoration: a Typer root with no commands AND no callback raises at build time, and lazy registration means no command is ever eager. The ticket claimed a zero-command root always raises — half right, and the half that matters is that a callback makes it legal. rich_markup_mode=None is load-bearing rather than cosmetic. It takes an empty --help from 168 ms to 74 ms, and keeps rich and pygments off the import path entirely rather than merely skipping the render. It also stops typer drawing box-art help, which it does even when stdout is a pipe — that would have put box-drawing characters into every hook log and agent capture. typer-slim was considered and rejected: deprecated since 0.22.0, now a shallow wrapper that installs all of typer. D-263 amended: the feels-instant ceiling goes from 250 ms to 500 ms. A ceiling is not a typical and most invocations sit far below it; the tighter number was buying discipline that the import-graph assertion enforces better. Stay smart about what loads, stop worrying about tightness. Security, checked 2026-08-23. typer has no advisories on record. pydantic 2.13.4 clears PYSEC-2026-1812 (email-regex ReDoS, fixed in 2.4.0) — and the 2026 SSRF advisories CVE-2026-25580 and CVE-2026-54249 are against pydantic-ai, a different package that is not a dependency here, recorded in pyproject so the next sweep does not re-panic. Transitively, pygments 2.21.0 clears CVE-2026-4539. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,8 +11,38 @@ dependencies = [
|
||||
# Pillow 12.2.0 — checked clean against NVD + OSV (2026-04-06)
|
||||
# CVE-2026-25990 fixed in 12.1.1, CVE-2025-48379 fixed in 11.3.0
|
||||
"Pillow==12.2.0",
|
||||
# typer 0.27.1 — the CLI transport (D-263). Checked clean against NVD, OSV
|
||||
# and the GitHub Advisory Database: no advisories on record for typer at all
|
||||
# (2026-08-20). Its transitive set was checked too, since typer pulls in
|
||||
# rich -> pygments: pygments 2.21.0 clears CVE-2026-4539 (archetype-lexer
|
||||
# ReDoS, fixed in 2.20.0); rich and click have no advisories on record.
|
||||
#
|
||||
# Plain `typer`, not `typer-slim`: slim is deprecated as of typer 0.22.0 and
|
||||
# is now a shallow wrapper that installs all of typer, so it buys nothing.
|
||||
# rich therefore ships as a transitive dependency — but `rich_markup_mode=None`
|
||||
# in tooling/main.py keeps it off the import path entirely (verified: `rich`
|
||||
# and `pygments` are absent from sys.modules after loading the CLI).
|
||||
"typer==0.27.1",
|
||||
# pydantic 2.13.4 — data shapes for domain schemas (D-263). Checked clean
|
||||
# against NVD + OSV (2026-08-20). PYSEC-2026-1812 / CVE-2024-3772 (email
|
||||
# regex ReDoS) is fixed in 2.4.0. NOTE the 2026 SSRF advisories
|
||||
# CVE-2026-25580 and CVE-2026-54249 are against *pydantic-ai*, a different
|
||||
# package that is not a dependency here — do not confuse the two on the
|
||||
# next sweep.
|
||||
"pydantic==2.13.4",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
# The whole point of D-263: one bare command, so one permission-rule entry
|
||||
# covers every tool.
|
||||
#
|
||||
# `cli` is a typer.Typer instance (callable), NOT the click.Group that T-1259
|
||||
# originally specified: typer vendors click as of 0.26.0, so there is no
|
||||
# top-level `click` to import and no supported way to extract typer's internal
|
||||
# one. Lazy domain registration therefore goes through `typer.Typer(cls=...)`
|
||||
# with a TyperGroup subclass (T-1260) rather than a click Group.
|
||||
reach = "tooling.main:cli"
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
# Explicit, not flat-layout auto-discovery. The repo root holds client/, server/,
|
||||
# docs/, wiki/, db/ and tests/ alongside tooling/, and auto-discovery either
|
||||
|
||||
Reference in New Issue
Block a user