feat(plugins): TREK-side registry — browse + one-click install (M5)

Connects TREK to the static GitHub registry (mauriceboe/TREK-Plugins). The
registry repo + CI gates were already live; this is the server side.

- registry.service: fetches the single aggregated dist/index.json (never
  per-plugin GitHub API calls — the HACS rate-limit lesson), caches it 30 min,
  soft-fails to a stale/empty registry, and installs a pinned version through
  the M4 pipeline: safe download -> sha256 verify -> slip-safe extract ->
  manifest re-validate -> native re-scan -> atomic move -> discover (inactive),
  recording repo/commit/sha provenance. Handles the codeload {repo}-{sha}/
  wrapper directory.
- Admin endpoints: GET /api/admin/plugins/registry (browse metadata) and
  POST /api/admin/plugins/install { id, version }. Install never executes code;
  activation stays a separate, deliberate step.
This commit is contained in:
mauriceboe
2026-07-03 17:38:10 +02:00
parent be07f29acd
commit c98bf7977d
8 changed files with 376 additions and 18 deletions
+2 -1
View File
@@ -5,6 +5,7 @@ import { PluginsProxyController } from './plugins-proxy.controller';
import { PluginFrameController } from './plugin-frame.controller';
import { PluginsService } from './plugins.service';
import { PluginRuntimeService } from './plugin-runtime.service';
import { PluginRegistryService } from './registry/registry.service';
/**
* Plugin system (#plugins). M0 read side + M2 isolated runtime + M3 frontend:
@@ -15,6 +16,6 @@ import { PluginRuntimeService } from './plugin-runtime.service';
*/
@Module({
controllers: [PluginsController, PluginsFeedController, PluginsProxyController, PluginFrameController],
providers: [PluginsService, PluginRuntimeService],
providers: [PluginsService, PluginRuntimeService, PluginRegistryService],
})
export class PluginsModule {}