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/*'], // `tea` is not in any distribution, and Debian has an UNRELATED package of that name — a graphical // text editor. So this is a release binary with an identity check: `Bun.which('tea')` cannot tell the // two apart, and reporting the wrong one as satisfied is worse than reporting it missing. osDependencies: [ { binary: 'tea', reason: 'Pull requests, issues and comments. Plain git handles clones and pushes without it.', // Empty on purpose. Every entry here would install the text editor. packages: {}, release: { url: 'https://dl.gitea.com/tea/0.15.1/tea-0.15.1-{os}-{arch}', // Gitea's tea prints `Version: 0.9.2 golang: … go-sdk: …`. The text editor prints nothing of // the sort, and `go-sdk` is the least likely of those to appear in an unrelated tool. identify: { args: ['--version'], contains: 'go-sdk' }, }, }, ], permissions: [ { key: 'gitea', label: 'Gitea', description: 'Repositories, issues, pull requests and notifications from your own Gitea account', }, ], };