~bigbes/sr-ht-spec

ref: cd1b8b014d4f88d3a972259e5bb7aee42d14013b sr-ht-spec/web/templates/index.html -rw-r--r-- 1.6 KiB
53e56db2 — Eugene Blikh 10 days ago
web: draw the chrome from sr-ht-ecore

The nav/service-switcher, the login block, the environment banner and the
brand were this service's own copy of code compare.sr.ht had already copied
from somewhere else. They come from sourcecraft.dev/bigbes/sr-ht-ecore/chrome
now: one chrome.Service built at startup from the shared config.ini, one
chrome.Page per request, embedded in viewData so the shared partials find
their fields on the dot.

web/chrome.go is gone — buildNav, navItem, canonIndex, the login/logout/
profile URL building and the chrome half of viewData with it. The layout
renders srht-env-banner and srht-nav instead of the local markup, the landing
page's space list renders through srht-repo-list, and the template FuncMap
starts from chrome.Funcs() (the local shortsha was a duplicate of the shared
one). sameOrigin and the login redirect ask the chrome for our origin rather
than keeping a second copy that could disagree with the links on the page.

Three of ecore's policies differ from what this service did, and win, per that
package's own doc: [sr.ht]site-name defaults to "sr.ht" rather than
"sourcehut" and [sr.ht]environment to "development" rather than "production"
when the key is absent, and the brand carries a fixed 15rem min-width so the
switcher starts at the same x on every service. The instance's config.ini sets
both keys, so on it only the brand width is visible.

The nav tests that only restated ecore's rules — switcher order, the
paste/pages/hub exclusion, the shape of a login URL — are dropped; ecore tests
those. What is left covers this service's seam: that the identity authn
resolved is the one the chrome is handed.
a4d8cc52 — Eugene Blikh 10 days ago
authn: remove the local agent-token plane

The agent_token table and everything that minted, verified, listed or revoked
it. Agent credentials are tokens.sr.ht working tokens now: signed, expiring,
owned by a meta.sr.ht account and carrying grants, verified locally by
sr-ht-ecore's bearer package. One door, and nothing behind it — a credential the
instance plane refuses is refused, where it used to be offered to a second store
that might say yes.

DEPLOY GATE: do not deploy this until every agent configured with the shared
secret holds a tokens.sr.ht token with spec:propose (spec:read to read).
Migration 0005 drops the table, migrate-on-upgrade runs it on deploy, and
deploying early locks out every agent at once — including the SSH push path.

hooks/ no longer reads agent_token directly. The push path goes through the same
authn.Resolver the HTTP surfaces use and demands spec:propose, because a push by
an agent is a proposal by another transport. The refs rule and the provenance
requirement are untouched on both counts: a universal grant is still only an
agent to the receive path, and X-Agent / X-Agent-Session are still mandatory on
every agent write.

bearer.ErrNotOurs is now a permanent refusal. A meta.sr.ht PAT used to fall
through to the local store and miss there; with no store to fall through to it
earns a 401 rather than the 503 an unclassified error would.

[tokens.sr.ht] origin becomes a required config key: with no issuer there is no
credential to check, so the daemon fails startup instead of serving reads and
refusing every agent write one request at a time.

/tokens redirects to the daemon that issues (tokens SPEC ch. 7).
bb3d22db — Eugene Blikh 11 days ago
web: git.sr.ht-style dashboard and unified nav brand

Adopt the family look the dolt service already has. The nav brand
becomes circle icon + site name + red service label (dropping the
hub-origin variant), matching every other service on the instance. The
logged-in index turns into the two-column dashboard: a sidebar with the
service blurb, review-queue/agent-tokens block buttons and the search
form, and the spaces as shared-theme event-list cards. The big in-page
h2 lives on only for anonymous visitors, where the nav has no user
context yet.
8219ede1 — Eugene Blikh 13 days ago
feat(web,service): the owner mints and revokes agent tokens in a browser

Issuing a credential required SSH to the host, which made the remote
agent write plane unusable from anywhere else: to hand an agent a token
the owner had to be at the machine. /tokens is that page — list, mint,
revoke — behind the same owner-only gate and same-origin guard as
approve/reject.

The mint is owner-only, and that rule is what revocation depends on: an
agent allowed to mint would survive having its own credential revoked by
issuing itself another, and "revoke the token" is the entire incident
response this design has. An agent asking for the page gets 403 rather
than the read plane's login redirect — it is authenticated already, so
bouncing it to meta would answer a question it did not ask.

The plaintext is rendered in the response to the POST rather than after a
redirect. A redirect would either drop the secret or carry it in a URL,
where it lands in history and in every proxy log on the way; the cost is
that a reload re-submits and mints a second token, which is one click to
revoke on that same page, whereas a lost token is not recoverable.

service.IssueAgentToken/ListAgentTokens/RevokeAgentToken hold the ACL and
the mint, and `specsrht token` now goes through them too, so the CLI and
the page cannot drift into two ideas of what issuing a token is.

spec-ejq.3
7f779fef — Eugene Blikh 26 days ago
feat(web): review queue — inbox + policy-merged digest (Phase 4)

The backstop for work no link reached. /inbox lists every open proposal
on the instance ("waiting on you") and, below it, the digest of recently
policy-merged content — the firehose a human sees after the fact, which
is the whole reason approval=policy is kept distinct from human.

- service.InboxProposals / DigestProposals list instance-wide (one
  reviewer, so a per-space inbox would make them hunt), mapping each
  stored proposal's space_id back to a reference once from the space list.
- web/inbox.go + inbox.html render the two sections; the landing page
  links the queue for a logged-in owner.

Follow-up: the digest currently shows recent policy-merges rather than
"since you last looked" — the digest_mark table exists to track that, but
advancing it is a write and GET stays pure. Filed separately.
2a7569f4 — Eugene Blikh 27 days ago
feat: web — the Phase 2 read plane UI and its SCSS entry

SourceHut chrome (nav service-switcher, login block, environment banner,
error page, embedded hashed static assets) ported from compare.sr.ht, plus
the read-plane pages: landing, space document tree, rendered document with
frontmatter/backlinks, and search.

The URL grammar is the design's pinned one: a document's address carries no
extension, ".md" is raw source, ".json" is metadata plus body, and ?rev=
pins any of the three to an immutable revision. Links rendered inside a
pinned page keep the pin, so following one does not silently land on the
approved head.

One human and no visibility levels, so the read ACL is one line: the owner
and its agents read, everyone else is redirected to meta's login (a browser)
or refused with 401 (a client asking for .md/.json).