-
v0.9.4
Stablereleased this
2026-08-10 22:31:01 -05:00 | 84 commits to main since this releaseHardening and tidying — phase 4 of
docs/audit.md, which finishes it. No tool behaviour
changes; the only runtime difference is a default that production already overrides.Changed
-
ALLOWED_HOSTSdefaults to thePUBLIC_BASE_URLhost plus loopback, instead of
*.*disables the host check entirely. Production sets the var, so nothing was
actually open — but the safe default for a service reached through a named proxy is the
name, and a deployment that forgets the var should not silently lose DNS-rebinding
protection whenPUBLIC_BASE_URLis right there, already required and already
validated. An explicit value still wins, including an explicit*, which is a
deliberate local-development choice rather than something to second-guess. Loopback is
included because the container healthcheck has no proxy in front of it, and the port is
stripped because Starlette compares againstHostwithout one. -
line-length = 100is now a rule. It had been set under[tool.ruff]with nothing
selectingE501and the formatter never run, so it read as enforced while nine lines
exceeded it.E501is selected and those lines are wrapped. A setting that looks like a
rule and is not is worse than no setting. -
deploy/README.mdno longer contradicts the release procedure. It said "on a
release, bumpimage:there", which was true before the stack moved to:latestand
survived the change — sending anyone who followed it looking for a line that does not
exist, and past the re-pull step that actually decides whether a release takes.
Added
-
X-Frame-Options: DENYandReferrer-Policy: no-referreron the browser-facing OAuth
routes./consentis a button that grants a connector access to a personal calendar,
so it must not be frameable; and the consent URL carries a transaction id whose next hop
is Forgejo, which does not need it in aReferer.Deliberately not a full CSP: FastMCP already sends one for the consent page, and a
second complete policy is intersected with the first, so a stricter guess made at the
proxy would break the page it is protecting.The rate limit is documented rather than applied, and that is the honest outcome
rather than a shortfall:limit_reqrequires alimit_req_zonein nginx's http
context, and everything indeploy/nginx/calendar.confis pasted into NPM's Advanced
tab, which lands inside aserverblock. Addinglimit_reqthere alone makes
nginx -tfail and NPM refuse to save the proxy host — breaking the sign-in path the
change was meant to protect. The two-step fix, including the file to create on the NPM
host, is recorded in the config next to the block. -
The resource cache is bounded in principle, not only by its TTL. It is keyed by
collection and window, so a model sweeping many distinct ranges minted a key each
time; the 120-second TTL bounded that in practice while nothing bounded it in principle.
Now capped at 256 entries, evicting expired entries first and then oldest-first, with a
re-inserted key moved to the back so a hot key is not evicted on its original age.
Fixed
_addressed_eventdecoded the sameevent_idup to three times per candidate inside
its match loop. Decoded once — cosmetic on a handful of occurrences, but the condition
read as though the three calls could disagree.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-