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.
59 lines
2.5 KiB
TypeScript
59 lines
2.5 KiB
TypeScript
import type { PluginManifest } from '@@/plugins/manifest';
|
|
|
|
/**
|
|
* Gitea — repositories, issues and pull requests, inside Officer.
|
|
*
|
|
* ── This one renders Gitea's own web interface ──
|
|
*
|
|
* Every other plugin is panels over a JSON API. Gitea already HAS a web interface, and a good one, so
|
|
* reimplementing it was seventeen files of screen that could only ever be a worse Gitea. The panel is an
|
|
* iframe, and the platform proxies the real thing into it.
|
|
*
|
|
* The proxy is not decoration, it is what makes the iframe possible at all. Officer and Gitea are
|
|
* different registrable domains, so an iframe pointed straight at gitea.officer.dev gets a login page
|
|
* whose session cookie the browser drops as third-party. Served through Officer's own origin the cookie
|
|
* is first-party and survives — and Gitea's `X-Frame-Options` is stripped on the way through, which is
|
|
* safe only because the frame is the same origin the browser already authenticated.
|
|
*
|
|
* ── Whose Gitea account ──
|
|
*
|
|
* The person's own. The web proxy injects NOTHING and forwards the browser's own cookies, so whoever is
|
|
* looking at the frame is signed in to Gitea as themselves. The stored API token is used only by
|
|
* `/_api/*`, which the panel uses for the small things around the frame.
|
|
*
|
|
* That distinction is the one thing not to get wrong here: injecting the stored token into the web proxy
|
|
* would show every user the owner's view of every repository.
|
|
*
|
|
* ── `unauthenticatedPaths` ──
|
|
*
|
|
* `/_web/*` is served above the platform's gate because an iframe's sub-resources carry no Authorization
|
|
* header. It authenticates with a minted, path-scoped cookie instead — see `api/router.ts`. Gitea
|
|
* authenticates the person itself regardless, so the worst an unauthenticated caller sees is a login
|
|
* page.
|
|
*
|
|
* ── `tea` ──
|
|
*
|
|
* The affordance in `affordances/` tells agents to use plain `git` for what git already does, and `tea`
|
|
* for pull requests, issues and comments. Provisioning `tea` per user is not built yet.
|
|
*/
|
|
export const manifest: PluginManifest = {
|
|
publisher: 'officerdev',
|
|
version: '1.0.0',
|
|
platform: '>=1.0.0',
|
|
|
|
label: 'Gitea',
|
|
summary: 'Repositories, issues and pull requests — your own Gitea, rendered in Officer',
|
|
icon: 'GitBranch',
|
|
color: '#609926',
|
|
|
|
unauthenticatedPaths: ['/_web/*'],
|
|
|
|
permissions: [
|
|
{
|
|
key: 'gitea',
|
|
label: 'Gitea',
|
|
description: 'Repositories, issues, pull requests and notifications from your own Gitea account',
|
|
},
|
|
],
|
|
};
|