gitea, extracted into plugins/gitea — the platform half
Eleventh extraction, and the only one that deleted its UI instead of moving it. Seventeen files under apps/Gitea/ reimplemented a fraction of an interface Gitea already has; the plugin renders the real one in an iframe over a same-origin proxy. Deleting rather than moving removed a platform change nobody now has to build: useGiteaLocation read :owner/:name/:tab/:item from five route patterns where a plugin gets two, so an as-is extraction would have required teaching the plugin system to declare extra route patterns. Nothing inside an iframe needs a route. Nothing working was lost. The 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, like soulseek, jellyfin and invoices before it. Gitea also stops being a CORE DOCK ITEM. It was hardcoded in CORE_DOCK_ITEMS, the only installable feature that was, on the reasoning that it fronts a remote instance and installs nothing locally. As a plugin its tile arrives from assets/icon.png like every other — which is also why the icon added to public/icons/ this morning was reverted rather than kept. 'gitea' stays in the ServiceName union: the connection lives in core service_connections, and gitea is the reason that table has its "member rows carry only a token and inherit the owner's URL" shape at all. registry.test.ts's grantable-permission test named gitea as "the case this was built for"; a plugin's permissions are registered at install and are never in that compile-time list, so it now names a core one. catalogue.test.ts re-anchored to vnc/notify. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -73,9 +73,9 @@ describe('totality', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('signin is exempt and gitea is not', () => {
|
||||
test('signin is exempt and an ordinary route is not', () => {
|
||||
expect(isExemptApiPath('/api/auth/signin')).toBe(true);
|
||||
expect(isExemptApiPath('/api/gitea')).toBe(false);
|
||||
expect(isExemptApiPath('/api/chat')).toBe(false);
|
||||
expect(isExemptApiPath('/api/dashboards/4')).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -254,8 +254,11 @@ describe('kinds', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('gitea is grantable — the case this was built for', () => {
|
||||
expect(GRANTABLE_PERMISSIONS.some((c) => c.key === 'gitea')).toBe(true);
|
||||
// `gitea` was this test's subject until 2026-08-19, when it became `plugins/gitea/`. A plugin's
|
||||
// permissions are registered at INSTALL from its manifest and are always `app`, so they are never in
|
||||
// this compile-time list — which is why the assertion has to name a core one to mean anything.
|
||||
test('an app permission is grantable — the case this was built for', () => {
|
||||
expect(GRANTABLE_PERMISSIONS.some((c) => c.key === 'chat')).toBe(true);
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
@@ -143,24 +143,6 @@ const CORE_REGISTRY: Permission[] = [
|
||||
},
|
||||
|
||||
// ── app: the grantable surface ──────────────────────────────────────────────────────────────────
|
||||
{
|
||||
key: 'gitea',
|
||||
label: 'Gitea',
|
||||
description: 'Repositories, issues, pull requests and notifications from your own Gitea account',
|
||||
kind: 'app',
|
||||
// api: ['/gitea'], // plugin — switched off 2026-08-13
|
||||
api: [],
|
||||
routes: ['/gitea'],
|
||||
// Every Gitea call is already scoped to the caller's own personal access token — the sidecar resolves
|
||||
// the token from the caller's row and the instance from the owner's, so a member holding `read` still
|
||||
// acts only as themselves upstream. Gitea's own permissions are the second gate and the real one:
|
||||
// a token cannot reach a repository its account cannot reach, whatever this platform thinks.
|
||||
//
|
||||
// Which is why the whole permission is `personal` rather than a list of sub-paths. Nothing under
|
||||
// /api/gitea can affect another Officer user, so withholding write here would only stop someone
|
||||
// commenting on their own issues — security theatre with a real cost and no benefit.
|
||||
personal: ['/'],
|
||||
},
|
||||
{
|
||||
key: 'memos',
|
||||
label: 'Memos',
|
||||
|
||||
Reference in New Issue
Block a user