2 Commits
Author SHA1 Message Date
officer bf27793b44 put the settings in the panel header
They were floating buttons over the top-right of the iframe, which was wrong
twice: they sit on top of Gitea's own controls, and an overlay on an
application that fills its whole panel is invisible until you already know it
is there. Reported as "I have no access to settings when the iframe is loaded",
which is exactly right.

The header is the platform's own furniture — always present, never competing
with the content underneath — and it is where photos and jellyfin put theirs.
It also names where you are, so /gitea/connection reads as "Gitea —
connection" rather than looking like the frame failed to load.
2026-08-19 10:11:47 +00:00
officer f680e25f82 gitea: the plugin, rendering Gitea's own interface
Eleventh plugin out, and the first that is not a move. The seventeen files that
reimplemented a fraction of Gitea's interface were deleted rather than carried
across — each one a promise to keep pace with a project that moves faster than
this plugin will.

That removed a platform change nobody now has to build. useGiteaLocation read
:owner/:name/:tab/:item from five route patterns and a plugin gets two, so
extracting as-is would have needed the plugin system to declare extra routes.
Nothing inside an iframe needs a route, so the requirement went with the screen.

No regression window: gitea's router had been commented out of hono.ts since
2026-08-13 with api: [], and officer-gitea was running nowhere. The screen
rendered and every request 404'd.

The proxy is what makes the iframe possible, not decoration. Officer and Gitea
are different registrable domains, so a frame pointed straight at the instance
gets a login page whose cookie the browser drops as third-party. Through
Officer's origin it is first-party and survives; X-Frame-Options and CSP are
stripped, safe only because the frame is the origin the browser already
authenticated.

/_web/* forwards the browser's own cookies and injects NOTHING. The sidecar
holds an API token and injecting it there would show every user the owner's
view of every repository. It is used only by /_api/*.

Two doors, because an iframe's sub-resources carry no Authorization header:
the ordinary routes go through the platform's gate, and /_web/* is declared
unauthenticated and authenticates itself with a minted, path-scoped cookie —
32 random bytes against the user who asked, not dev-proxy's constant =1 which
anyone knowing the cookie name can set. Verifying it also sets `user`, because
createSidecarProxy fills X-Officer-User from it and the sidecar refuses a
request without one.

Ships an affordance: git for what git does, tea for pull requests and issues.
Nothing copies it into capabilities/ yet — gitea is that mechanism's first
customer.
2026-08-19 07:58:55 +00:00