ACL-deny sites now write a JSON body naming the missing verb so the
client-side toast can render "you need <verb> here" and offer
elevation (the path-scoped /.profile/access?path= reports whether
elevation would unlock the verb).
Body shape:
{"error": "Forbidden", "missing_verb": "w"}
New helper writeForbidden(w, action) in errors.go, applied at the
four primary ACL-deny gates:
- directory.go (list, action=read)
- fileapi.go (file CRUD; action varies per request)
- tablehandler.go (table read)
- archivehandler.go (existence-leak guard, treated as read)
Other 403 sites (no authenticated principal, planreview detail
errors) keep their plain-text bodies — "missing_verb" doesn't apply
there. Existing clients that read the body as text see the JSON
string instead of "Forbidden\n"; no client in this repo parses the
body for content, so it's a non-breaking change in practice.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>