feat: pipeline templates, analytics opt-out, 83 conversion presets, positioning + e2e modernization

Lands five integrated branches: pipeline templates (#355), analytics opt-out (#354), 83 conversion presets bringing the catalog to 240 tools (#356), self-hosted positioning (#353), and e2e modernization (#351).

Integration fixes: aligned stale web analytics tests with the opt-out/allow-list model, closed 3 CodeQL incomplete-sanitization alerts in the i18n generator, resolved settings/index/docs/format-matrix conflicts, and corrected tool counts to 240.
This commit is contained in:
SnapOtter
2026-06-28 18:57:53 +08:00
committed by GitHub
parent 88af8d46fb
commit 63a03d26f2
421 changed files with 17308 additions and 2540 deletions
+12
View File
@@ -33,6 +33,7 @@ import {
ensureAnonymousUser,
ensureBuiltinRoles,
ensureDefaultAdmin,
ensureDefaultTeam,
getAuthUser,
} from "./plugins/auth.js";
import { registerMfa } from "./plugins/mfa.js";
@@ -54,6 +55,7 @@ import { filePreviewRoutes } from "./routes/file-preview.js";
import { fileRoutes } from "./routes/files.js";
import { registerMemeTemplates } from "./routes/meme-templates.js";
import { registerPipelineRoutes } from "./routes/pipeline.js";
import { preferencesRoutes } from "./routes/preferences.js";
import { registerProgressRoutes } from "./routes/progress.js";
import { rolesRoutes } from "./routes/roles.js";
import { settingsRoutes } from "./routes/settings.js";
@@ -123,6 +125,7 @@ if (env.SQLITE_MIGRATE_PATH) {
// inserted via data statements. The pg baseline is DDL-only, so roles are
// seeded here at boot time. onConflictDoNothing makes this idempotent.
await ensureBuiltinRoles();
await ensureDefaultTeam();
if (env.AUTH_ENABLED) {
await ensureDefaultAdmin();
@@ -173,6 +176,8 @@ if (!env.COOKIE_SECRET) {
}
await initAnalytics();
const { primeAnalyticsGate } = await import("./lib/analytics-gate.js");
await primeAnalyticsGate();
// Enterprise features (license-gated)
let enterpriseLicense: { org: string; plan: string } | null = null;
@@ -211,6 +216,8 @@ if (env.STORAGE_MODE === "s3") {
// Start the cooperative cancellation listener (Redis pub/sub)
await startCancelListener();
const { startAnalyticsGateListener } = await import("./lib/analytics-gate.js");
await startAnalyticsGateListener();
// Set up AI feature directories and recover from interrupted installs. Both are
// best-effort and must never block boot: ensureAiDirs swallows its own errors,
@@ -362,6 +369,9 @@ await registerIpAllowlist(app);
// Public config routes (no auth required)
await configRoutes(app);
// Per-user preferences (any authenticated user)
await preferencesRoutes(app);
// Auth middleware (must be registered before routes it protects)
await authMiddleware(app);
@@ -761,6 +771,8 @@ async function shutdown(signal: string) {
await closeQueueEvents();
await closeQueues();
await stopCancelListener();
const { stopAnalyticsGateListener } = await import("./lib/analytics-gate.js");
await stopAnalyticsGateListener();
await closeRedis();
console.log("Redis connections closed");
} catch (err) {