mirror of
https://github.com/Dvorinka/Primora.git
synced 2026-10-28 15:51:23 +00:00
feat: phase 7 automation & realtime — scheduled jobs, domain events, SSE
Scheduled jobs (migration 00009): cron expressions + @every descriptors, in-process scheduler (15s scan, missed-run collapse), signed HTTP POST delivery (X-Primora-Signature), AES-256-GCM sealed secrets returned once, run history with status/duration/http-code, manual execution, retention pruning. Viewer reads, admin/developer writes. Domain events: publishEvent fans document/object/issue/deploy/job mutations to realtime subscribers and matching webhooks through one path. Webhook event filter extended to job.run, document.*, object.*. Realtime: GET /projects/:id/realtime/stream SSE with 25s keepalives and ?token=/?api_key= auth for EventSource clients. Automation dashboard page: Schedules tab (CRUD, run history, manual run, secret-once banner) + Live events tab (live badge, pause/clear). Demo mode parity. primora jobs:* CLI group, six primora_*_job* MCP tools, AutomationService in the generated client. Fixes folded in: gzip middleware buffered SSE flushes (broke EventSource on both streams — */stream now bypasses compression); event payloads double-marshaled json.RawMessage as base64; compose hardcoded localhost trusted origins so non-default ports broke sign-in; frontend auth base URL baked an absolute localhost instead of resolving /auth on origin. Verified live: stack up on :8085, signed delivery HMAC-checked at sink, @every 30s schedule firing, run history rendering, document.created landing in the live events feed. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
4b7fdf35ad
commit
9e9a3d5f98
49 files changed
+3555
-32
No files matched your search
@@ -39,6 +39,7 @@ import {
|
||||
import {
|
||||
AuditPage,
|
||||
AuthPage,
|
||||
AutomationPage,
|
||||
type AuthUser,
|
||||
CollectionsPage,
|
||||
DatabasesPage,
|
||||
@@ -58,6 +59,7 @@ import {
|
||||
IconStorage,
|
||||
IconDatabases,
|
||||
IconTelemetry,
|
||||
IconZap,
|
||||
IconCollections,
|
||||
IconAudit,
|
||||
IconAuth,
|
||||
@@ -1457,6 +1459,7 @@ export default function App() {
|
||||
{ id: "nav-members", label: "Go to Members", category: "Navigate", icon: <IconMembers class="w-4 h-4" />, keywords: ["team", "users", "invite"], action: () => setActiveView("members") },
|
||||
{ id: "nav-databases", label: "Go to Databases", category: "Navigate", icon: <IconDatabases class="w-4 h-4" />, keywords: ["db", "sql", "query", "tables", "redis"], action: () => setActiveView("databases") },
|
||||
{ id: "nav-telemetry", label: "Go to Telemetry", category: "Navigate", icon: <IconTelemetry class="w-4 h-4" />, keywords: ["errors", "metrics", "logs", "observability", "issues"], action: () => setActiveView("telemetry") },
|
||||
{ id: "nav-automation", label: "Go to Automation", category: "Navigate", icon: <IconZap class="w-4 h-4" />, keywords: ["cron", "jobs", "schedule", "events", "realtime"], action: () => setActiveView("automation") },
|
||||
{ id: "nav-storage", label: "Go to Storage", category: "Navigate", icon: <IconStorage class="w-4 h-4" />, keywords: ["files", "buckets", "upload"], action: () => setActiveView("storage") },
|
||||
{ id: "nav-collections", label: "Go to Collections", category: "Navigate", icon: <IconCollections class="w-4 h-4" />, keywords: ["documents", "database"], action: () => setActiveView("collections") },
|
||||
{ id: "nav-auth", label: "Go to Authentication", category: "Navigate", icon: <IconAuth class="w-4 h-4" />, keywords: ["users", "sign in", "ban"], action: () => setActiveView("auth") },
|
||||
@@ -1687,6 +1690,14 @@ export default function App() {
|
||||
/>
|
||||
</Show>
|
||||
|
||||
<Show when={activeView() === "automation"}>
|
||||
<AutomationPage
|
||||
projectID={activeProject()?.id}
|
||||
canManage={canUpdateProject()}
|
||||
demoMode={isDemo}
|
||||
/>
|
||||
</Show>
|
||||
|
||||
<Show when={activeView() === "storage"}>
|
||||
<StoragePage
|
||||
buckets={buckets()}
|
||||
|
||||
Reference in new issue
Block a user