~bigbes/sr-ht-ecore · memory

main · last commit 18 hours ago · 7bghjra2

Clear
1 entry sort: slug · age

ecore-architecture

written 3 days ago · 17qio80f

sourcecraft.dev/bigbes/sr-ht-ecore holds everything the six custom services of the self-hosted SourceHut instance share that is ours rather than upstream's, so the sr-ht-core fork stays a clean mirror of core-go.

Thirteen packages as of 2026-08-09: chrome (nav, brand, page partials, listing partials), grants, bearer (+ StatusFor/Challenge/IsRefusal), pages (page sets, buffered render, error page, FormValues), assets (hashed assets, DirFS), csrf, middleware (cache policy, panic recovery, 499), login (unified-login cookie decode), internalauth (both ends of Authorization: Internal), instconf (origin canonicalisation, Require), logging (slog policy without the handler), chimw (chi-shaped helpers), ecoretest.

This reverses the family convention still written in the services' Russian SPEC/DESIGN docs ("копируем, не выносим в общий модуль; единственная общая зависимость — sr-ht-core"). The user confirmed the reversal is deliberate and those documents are not to be corrected. There are two shared modules now: sr-ht-ecore and go.bigb.es/auxilia.

Boundaries settled by argument, not taste:

  • ecore does not depend on auxilia. logging ships the mask policy and a stdlib ReplaceAttr; the service picks the handler (scribe's tint on this instance).
  • middleware stays dependency-free (net/http only); anything chi-shaped goes in chimw.
  • A general logging adapter belongs in auxilia, not ecore — ecore is SourceHut-specific. That is why logrusbridge landed in auxilia.
  • middleware.RecoverPanics logs through slog.Default(), which is what gives ecore a stake in every service calling slog.SetDefault — hence logging existing at all.

chrome.BuildNav is only half of the instance's service switcher: the Python services render the same strip from core.sr.ht/srht/app/flask.py, which orders the non-canonical half by config-file order rather than alphabetically, and whose nav.html excludes hub from the loop exactly as navExcluded does. Changing the ordering or the exclusions here makes the two halves disagree — see srht-instance-deploy for why the config file is written alphabetically.

The alphabetical tiebreak is forced, not chosen: ini.File is a map[string]Section, so core-go's parser has already thrown the file order away by the time BuildNav sees it, and matching upstream exactly would mean re-scanning the config for [section] lines. Two more divergences from nav.html, neither of them ordering: BuildNav skips a section with no origin (upstream lists it, with a broken href), and it resolves every origin once at startup where upstream calls get_origin per render. Upstream is readable locally — the whole fleet is checked out under ~/data/home/sourcehut/ (core.sr.ht, git.sr.ht, …) — so answer "what does upstream actually do" from the source rather than from the comments in our copies.

chrome.Page embeds as the field name Page, so a view struct wanting Page for its own payload must rename it. Listing columns (Updated, Meta) are optional on purpose: bench and spec needed them, dolt has no timestamp in its schema, cover's table of sparklines fits no shared partial.