~bigbes/sr-ht-compare

ref: f18653603d66734b583b52d2fe0da7c59a7b1f32 sr-ht-compare/web/handlers.go -rw-r--r-- 12.8 KiB
5719e51e — bigbes 10 days ago
login: ecore's cookie decoder, which validates the name ours did not

authz/identity.go was the fifth copy of a decode the instance has one of,
and it was one of the two that validated nothing: whatever name a sealed
payload carried went on to the GraphQL viewer field, the chrome's nav and
every log line the request produced. login.ValidName refuses it, and
there is no spelling of the API that turns the check off.

Gone with it: CookieName, UsernameFromRequest, Middleware, ForContext and
the ctxKey, plus identity_test.go, whose round-trip, tilde-stripping and
garbage-cookie cases are ecore's tests now. The Middleware becomes
login.Optional() — this service refuses nobody, git.sr.ht decides what an
anonymous viewer may see — and the default validator is kept rather than
core.ValidOwner, which is lowercase-only and would log a real account out
of compare alone.

The one behaviour change a viewer could notice: a cookie whose name
carries a '/', a control byte or a non-ASCII letter now reads as
anonymous instead of as that name.
65ffb96c — bigbes 10 days ago
log: slog through auxilia's scribe, not logrus

This was the last service on the instance still logging through logrus,
and the ecore bump made it a correctness question rather than a
consistency one: the recovery middleware reports a panic through slog's
DEFAULT logger, so without a SetDefault the one record carrying a stack
trace would have gone to Go's plain handler while every other line went
through logrus.

initLogging installs a scribe tint handler on stderr — source on, colour
only when stderr is a terminal, and the mask rules for token, cookie and
authorization. It reads -d out of the argument vector rather than
waiting for core-go's parse, because a daemon that only became verbose
after it had finished starting would be silent for exactly the part of
its life an operator passes -d to watch. Terminal detection is a stdlib
Stat rather than golang.org/x/term, which would be a new dependency for
one predicate.

The startup config check keeps its shape deliberately: it still
accumulates every missing key and reports them in ONE record before ONE
exit, so an operator fixes the config in a single pass. The keys go in
as a slice attribute rather than a joined string, so the structured
sinks keep them as a list.

culpa goes in at the one boundary where it pays: the errors web.New
returns, which are the only errors this package produces and all of
which arrive at that single startup record. Each carries a hint naming
the config key or the build step that fixes it, and scribe.Err unfolds
message, code, hint and stacktrace into fields of their own. The failing
request path logs the same way, with ErrorContext so a cancelled request
reads as cancelled rather than as an unexplained 500.

TestPanicIsAnErrorPage covers the wiring end to end through Register: a
panicking authorizer yields the chrome-wrapped 500, the panic value does
not reach the viewer, and the report reaches slog's default logger.
7ae492a4 — bigbes 10 days ago
web: draw assets, pages, csrf and the middleware from ecore

Deletes this package's copies of five things the instance now shares.

assets replaces hashedCSSRe, hashedBundleRe, resolveCSSHref,
resolveBundleHref and the bare StripPrefix(FileServer) route. That route
was a fix and not only a dedupe: an http.FileServer answers a directory
with a listing, so /static/ published the whole inventory of the binary
— every vendored artefact and the hashed names that fingerprint the
build — as a public, hour-cacheable page. It also wrote the cache
directives onto the header map before delegating, where a panic later
would have carried public, max-age=3600 onto a viewer's error page, and
left the Vary the private-cache policy sets, which is enough to stop any
shared cache from ever reusing an asset whose name was hashed for that
purpose. assets.Handler refuses the listing, stamps the policy on the
bytes rather than on the map, and drops the Vary per asset.

pages replaces pageNames, the package-level template map, render and
errorData. Pages are discovered from the embedded tree instead of listed
by hand, so templates/x.html is now the whole registration of a page,
and a page that defines no content block is refused at startup rather
than served as chrome around a hole with a 200 — neither of which this
service checked before. Render answers the response itself; the error it
returns is a log line and never reaches fail.

The local error.html goes with them: ecore ships the page and the
srht-error partial. renderError stays here, because building this
service's view struct is this service's business, and it now passes
for every status but 400 so a repository the viewer may not see and one
that never existed produce the same sentence.

csrf.Require and the middleware group are new rather than replacements:
compare has no POST today, so the guard covers the day somebody adds
one, and PrivateCache states the policy every per-viewer page here was
serving without.

BundleHref leaves viewData for chrome.Service.Assets, keyed bundle.js
and read through an emptiness guard, next to StyleHref where the other
hashed artefact already lived. The date helper goes to chrome's reltime
and abstime: listings show 3 days ago and hover to the exact stamp.
3e79c6de — bigbes 10 days ago
web: draw the chrome from sr-ht-ecore

The nav/service-switcher, the brand, the login block and the environment
banner were a copy of code every custom service on this instance carries.
The copies drifted, so they now come from one place:
sourcecraft.dev/bigbes/sr-ht-ecore/chrome.

web/chrome.go is gone. New builds one chrome.Service from the shared
config.ini and hands it the discovered stylesheet; view() asks it for a
chrome.Page per request, which viewData embeds rather than copies, so a
field ecore adds later arrives here without an edit. The layout invokes
"srht-env-banner" and "srht-nav" instead of the markup it used to spell
out, the landing's repository listing goes through "srht-repo-list", and
the FuncMap starts from chrome.Funcs() with the local shortsha deleted.

Two ecore policies differ from what this service did and are adopted as
the instance's: the brand label is the config section's short name rather
than a literal "compare", and the origins are trimmed of a trailing
slash. What stays local is what is compare's alone: the bundle href, the
diff-status colours, and the container-fluid the two diff views ask for.

Tests move to testify; the nav ordering/exclusion test goes with the code
it tested, and a test that the layout invokes the chrome at all replaces
it.
4e7c6329 — bigbes a month ago
web: full-width split diff view with a rendered file tree

Make the commit and compare pages full-bleed and default to the side-by-side
(split) diff, so the layout matches a conventional diff viewer: file tree on
the left, split diff on the right.

- layout.html renders the content wrapper with a per-page ContainerClass;
  chrome() defaults it to "container" and the commit/compare handlers set
  "container-fluid" for the diff views (the nav stays centered).
- app.ts defaults DEFAULT_LAYOUT to "split".
- Fix the @pierre/trees sidebar rendering blank: its virtualized container
  collapses to zero height unless the mount has a definite height, so
  sizeTreeRoot() gives #tree-root a viewport-height panel (re-applied on
  resize). Rebuilt the vendored bundle.
a4853d05 — Eugene Blikh a month ago
rename module to sourcecraft.dev/bigbes/sr-ht-compare; depend on sourcecraft sr-ht-core
71475299 — bigbes a month ago
web: http server, sourcehut chrome, compare/commit pages

Implement the compare.sr.ht HTTP layer over the committed core/gitx/authz
packages:

- Server assembly (New) from shared SourceHut config: [git.sr.ht] repos,
  [meta.sr.ht]/[compare.sr.ht] origins, [sr.ht] site-name/environment, and
  the hashed stylesheet resolved by globbing the embedded static FS.
- Routes: landing, repo page, compare (base..base...head, .patch escape
  hatch), single-commit (+.patch), embedded static assets, healthz. Compare
  form GET canonicalizes to a clean URL via 302.
- SourceHut chrome port to html/template: nav service switcher (canonical
  order, paste/pages/hub excluded, compare active), login/logout with
  return_to, environment banner.
- Embedded compare-data JSON (template.JS so html/template's script-context
  escaper leaves it verbatim; json.Marshal's HTML escaping blocks a
  </script> breakout) plus the vendored bundle.js scaffold.
- httptest coverage with a stub Authorizer and a real git-CLI fixture repo.

The cmd layer must wire, in order: RealIP, Recoverer, Logger,
config.Middleware(conf,"compare.sr.ht"), authz.Middleware.