feat: harden plugin api for separate repos, signed updates and generic external login

This commit is contained in:
LukeGus committed 2026-09-29 18:11:59 -05:00
1 parent fb9c168b6b
commit 80944301dd
310 files changed
+6577 -4927

No files matched your search

+2 -1
View File
@@ -70,6 +70,7 @@
"descriptionKey": "permissions.execute.description",
"defaultRoles": ["user"]
}
]
],
"uses": ["snippets.extractInputs"]
}
}
+23 -2
View File
@@ -6,10 +6,31 @@
"scripts": {
"build": "termix-plugin build",
"test": "termix-plugin test",
"typecheck": "tsc -b ../../tsconfig.plugins.backend.json ../../tsconfig.plugins.frontend.json",
"typecheck": "tsc -p .",
"validate": "termix-plugin validate"
},
"dependencies": {
"clsx": "^2.1.1",
"jszip": "^3.10.2",
"lucide-react": "^1.33.0",
"tailwind-merge": "^3.5.0"
},
"devDependencies": {
"@termix/plugin-sdk": "*"
"@termix/plugin-sdk": "^1.0.0",
"@types/node": "^26.2.0",
"@types/react": "^19.2.18",
"@types/react-dom": "^19.2.4",
"better-sqlite3": "^13.0.3",
"jsdom": "^30.0.1",
"vitest": "^4.1.11"
},
"peerDependencies": {
"@termix/plugin-sdk": "^1.0.0",
"drizzle-orm": "^0.45.2",
"express": "^5.2.1",
"multer": "^2.3.0",
"react": "^19.2.8",
"sonner": "^2.0.8",
"ssh2": "^1.17.0"
}
}
@@ -20,7 +20,7 @@ afterEach(() => {
});
function fakeHosts(hosts: PluginHostSummary[]): PluginHosts {
return {
return <PluginHosts>(<unknown>{
list: async () => hosts,
get: async (hostId) => hosts.find((h) => h.id === hostId) ?? null,
checkAccess: async (hostId) => {
@@ -37,7 +37,7 @@ function fakeHosts(hosts: PluginHostSummary[]): PluginHosts {
share: async (hostId) => ({ hostId, shared: true }),
listUsers: async () => [],
listRoles: async () => [],
};
});
}
async function setup(hosts: PluginHostSummary[]) {
+2 -3
View File
@@ -19,15 +19,14 @@ describe("fleets.access", () => {
const service = server.mock.services.get("fleets.access") as FleetsService;
await expect(
server.mock.ctx.asUser("user-1", () => service.create({ name: "prod" })),
server.mock.actAs("user-1", () => service.create({ name: "prod" })),
).rejects.toThrow("fleets.manage");
});
it("adds only hosts the caller can see", async () => {
server = await startServer();
const service = server.mock.services.get("fleets.access") as FleetsService;
const run = <T>(fn: () => Promise<T>) =>
server!.mock.ctx.asUser("user-1", fn);
const run = <T>(fn: () => Promise<T>) => server!.mock.actAs("user-1", fn);
const fleet = await run(() => service.create({ name: "prod" }));
await run(() => service.addMember(fleet.id, 10));