Commit Graph
66 Commits
Author SHA1 Message Date
Tomas DvorakandDevin 9707f307a1 fix: silence errcheck on test-response writes
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 23:08:15 +02:00
Tomas DvorakandDevin 3b90dae767 docs: roadmap ledger for release hardening, sandbox driver, client events
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 20:56:37 +02:00
Tomas DvorakandDevin 236357facb feat: Client-published events + realtime presence
- POST /projects/:id/events accepts client-authored events restricted to
  the custom.* namespace — system types can't be spoofed. They flow
  through the same publishEvent fan-out: realtime, webhooks, and
  event_pattern functions all fire.
- Presence: subscribe/unsubscribe bumps a per-project count and
  broadcasts presence.update {online} to the realtime stream only —
  deliberately not through publishEvent so webhooks and "*" functions
  don't fire on connect noise. GET …/realtime/presence reads the count.
- @primora/client gains publish() and presence(); CLI gains events:send.

Verified live: presence 0->1 on subscribe, presence.update frame
delivered, custom event delivered to SSE + fired a custom.* function,
spoofed document.created rejected 400.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 20:55:48 +02:00
Tomas DvorakandDevin 9ae1c22af0 feat: Sandboxed function execution via FUNCTIONS_DRIVER=docker
Each invoke runs in an ephemeral locked-down container — no network,
read-only rootfs, 128MiB/0.5CPU/64-pid caps, non-root, cap-drop ALL.
Source travels as base64 in the container env and materializes in the
tmpfs, so no bind mount is needed (Docker Desktop / remote daemons work).
Timeout force-removes the named container.

exec driver stays the default; the trust-model docs now describe both.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 20:45:33 +02:00
Tomas DvorakandDevin edef002beb feat: Desktop auto-updater + release SBOMs
- tauri-plugin-updater + process: pubkey embedded in tauri.conf.json,
  createUpdaterArtifacts, endpoint = GitHub latest.json manifest.
- Connect screen checks before auto-connect (bounded 5s) — a saved
  URL would otherwise navigate away before the check resolves.
  "Update & restart" downloads, verifies minisign, installs, relaunches.
- Release workflow signs updater artifacts with
  TAURI_SIGNING_PRIVATE_KEY secrets, ships the .sig files, and assembles
  latest.json from them. No key → no manifest → no update, never a
  silent unsigned install.
- anchore/sbom-action emits CycloneDX SBOMs per GHCR image plus the
  source tree, attached to every release.

Note: the signing keypair was generated locally
(~/.tauri/primora-updater.key); the private half must be added to repo
secrets before the next release for updates to activate.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 20:41:16 +02:00
Tomas DvorakandDevin fd36389328 feat: Presigned object URLs (s3 driver)
POST /buckets/:id/object-presigns mints SigV4 query-signed GET/PUT
URLs so clients move bytes directly against S3 — large transfers skip
the backend entirely.

- storage.Presigner optional interface; S3Store implements, local
  driver returns a clear error (no external surface to sign).
- TTL 60s–1h (default 15m); download requires read role + existing
  object row (no key probing); upload requires write role.
- S3_PUBLIC_ENDPOINT rewrites the client-facing host for internal
  S3_ENDPOINTs — signatures bind the host, URLs are valid only where
  minted.
- CLI: primora objects:presign <bucket> <key> [--upload] [--ttl].

Verified live against cloudserver: GET fetched the object with no
auth headers; PUT pushed 1 MB direct to S3; unsigned list → 403;
untracked-key download presign → 404.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 20:35:21 +02:00
Tomas DvorakandDevin a84049b8fc feat: Function triggers — schedule, inbound hook, domain events
Migration 00016: function_id on scheduled_jobs/inbound_hooks,
event_pattern on functions, 'event' in the run-trigger enum.

- Jobs deliver to a function instead of HTTP when function_id is set;
  the run's status_code mirrors the process exit code. Clearing the
  field returns the job to URL delivery.
- Inbound hooks gain mode "function" — received body becomes stdin
  payload, acked immediately, run recorded async.
- event_pattern (document.*, *, exact type) fires the function detached
  on matching publishEvent — never blocks realtime/webhook fan-out.
- One executeFunction path serves manual/schedule/hook/event; run rows
  record the trigger source.
- Backend image now ships bun 1.3.14 so Functions work under compose.

Dashboard: job target picker, hook function mode, event-pattern field.

Verified live: job run → success (status_code 0), hook POST → run,
document.created → event run with correct payload.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 20:28:04 +02:00
Tomas DvorakandDevin c094afad65 docs: README/QUICK_START coverage for S3 driver and Functions
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 19:48:57 +02:00
Tomas DvorakandDevin 0a4ff1e6ae fix: compose healthchecks use 127.0.0.1, not localhost
Inside the frontend and nginx containers, localhost resolves to ::1
only while their nginx binds IPv4 — the wget healthcheck was refused
and both containers reported unhealthy despite serving fine.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 19:47:47 +02:00
Tomas DvorakandDevin 32587c8063 feat: Functions — JS/TS execution with run log
core.functions + core.function_runs: project-scoped code executed by a
runtime binary on the backend host (bun or deno per function). Payload
arrives on stdin + PRIMORA_PAYLOAD env; stdout/stderr captured per run
(capped), with status/exit code/duration. Invoke returns 502 + the
recorded run on failure so errors stay observable.

Dashboard gains a Functions page: code editor, JSON payload invoke,
live result, run history. Runner config via FUNCTIONS_RUNTIME /
FUNCTIONS_TIMEOUT_SECONDS / FUNCTIONS_MAX_OUTPUT_BYTES.

Verified live: bun ran code, stdin payload delivered, error path returns
502 with captured stderr; timeout kills at deadline.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 19:46:32 +02:00
Tomas DvorakandDevin 3aca5bd1e0 feat: S3-compatible object storage backend
BACKEND_STORAGE_DRIVER=s3 swaps LocalStore for a stdlib-only SigV4
implementation — PutObject/GetObject/DeleteObject/CopyObject/ListObjectsV2
against any S3-compatible API (AWS, MinIO, Garage, R2). Storage becomes a
Store interface; storage_path records s3://bucket/key. Content-Length is
resolved by seeking or temp-file spooling — chunked uploads are rejected
by real S3 servers. Bucket auto-created on startup.

Verified live against zenko/cloudserver: bucket, put, get, copy, delete.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 19:38:50 +02:00
Tomas DvorakandDevin f747b33b46 feat: HA scheduler leadership + templated email log
HA scheduler: the job scheduler and alert evaluator hold session-scoped
PostgreSQL advisory locks on pinned pool connections — replicas scan for
due work exactly once, failover verified live with two replicas. Manual
and hook-triggered runs stay available on any replica.

Email surface: mailer renders registered templates (invitation); every
send is logged to core.email_log with status and error text. New
GET /projects/:id/emails endpoint; Members page shows an Email log card.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 19:27:06 +02:00
Tomas DvorakandDevin 45a1621909 feat: inbound webhooks — public ingest endpoints
core.inbound_hooks (migration 00013): POST /api/v1/hooks/<token> accepts
external events. event mode republishes as inbound.received through the
signed dispatcher + realtime; job mode triggers a scheduled-job run with
the received body as payload. Optional X-Primora-Signature HMAC verify.
Dashboard card on the Integrations page.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 19:15:12 +02:00
Tomas DvorakandDevin 2f4de543a9 feat: telemetry alert rules with webhook delivery
core.alert_rules (migration 00012) — heartbeat_silence and error_spike
rules evaluated by a 60s backend ticker. Transition-based firing:
alert.fired on breach, alert.resolved on recovery, both first-class
webhook event types riding the signed dispatcher + realtime stream.
Dashboard manages rules on the Integrations page.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 19:09:19 +02:00
Tomas DvorakandDevin 345cf7918b feat: realtime channel subscriptions in @primora/client
createRealtimeClient opens the project SSE stream via fetch +
ReadableStream (EventSource cannot send X-API-Key), with capped
exponential-backoff reconnect and state callbacks. channel() filters by
event namespace — channel("documents").on("created", cb). Presence and
client-broadcast deliberately deferred.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 18:58:58 +02:00
Tomas DvorakandDevin 8892c6dc43 feat: PostgREST-style document filtering and ordering
GET /collections/:id/documents accepts filter (field.op.value terms; eq neq
gt gte lt lte like in is; dotted paths index into document data) and order
(field.asc|desc). Whitelisted field/operator parsing with parameterized
values; plain lists keep the sqlc path. CLI gains `documents list
--collection --filter --order`; OpenAPI + generated client updated.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 18:55:56 +02:00
Tomas DvorakandDevin f9e7002048 fix(mcp): resolve pre-existing tsc drift in server.ts
zod v4 requires z.record(keySchema, valueSchema); the integration tool
passed a string literal where the generated client wants the enum.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 18:49:03 +02:00
Tomas DvorakandDevin 585bb04ab2 feat: encrypted secrets vault across CLI, desktop, dashboard, and backend
Local vault (apps/cli): clean-room PRMVLT01 format — Argon2id →
XChaCha20-Poly1305, AEAD-bound header, atomic writes. vault:* / secrets:*
/ inject (primora:// refs) / agent credential broker (dummy tokens in the
child, real secret on the wire) / TTL sessions / stack:* operator group.

Project vault (backend): core.project_secrets, AES-256-GCM via the
platform encryptor. Metadata-only list, audit-logged reveal, and
secret://NAME refs resolved at job delivery — refs stored, values never.

Surfaces: dashboard Vault page (+ local-vault card under the Tauri
shell), desktop vault window via IPC to the primora binary,
secrets:* --remote CLI mode, metadata/write-only MCP tools so agents
consume secrets via secret:// refs without holding plaintext.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-24 18:46:37 +02:00
Tomáš Dvořák 31bc23386b Merge pull request #15 from Dvorinka/release/v0.7.1
CI / Backend Tests (push) Canceled after 0s
CI / Frontend Tests (push) Canceled after 0s
CI / Build All Services (push) Canceled after 0s
CI / Docker Build (auth) (push) Canceled after 0s
CI / Docker Build (backend) (push) Canceled after 0s
CI / Docker Build (frontend) (push) Canceled after 0s
CI / Migration Up/Down (push) Canceled after 0s
CI / Compose E2E Smoke (push) Canceled after 0s
CI / Lint (push) Canceled after 0s
CI / Publish edge images (auth) (push) Canceled after 0s
CI / Publish edge images (backend) (push) Canceled after 0s
CI / Publish edge images (frontend) (push) Canceled after 0s
chore: release v0.7.1 + auto-release on merge to master
v0.7.1
2026-09-23 11:13:20 +02:00
Tomas DvorakandDevin 112cf84362 chore: release v0.7.1, auto-release on merge
Release workflow now also fires on workflow_run when CI succeeds on
master; verify job skips unless package.json version lacks a matching
tag, so merges only release on a version bump. Tag pushes unchanged.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-23 11:12:24 +02:00
Tomáš Dvořák 61ede5ee99 Merge pull request #13 from Dvorinka/fix/selfhosted-email-optional
CI / Backend Tests (push) Canceled after 0s
CI / Frontend Tests (push) Canceled after 0s
CI / Build All Services (push) Canceled after 0s
CI / Docker Build (auth) (push) Canceled after 0s
CI / Docker Build (backend) (push) Canceled after 0s
CI / Docker Build (frontend) (push) Canceled after 0s
CI / Migration Up/Down (push) Canceled after 0s
CI / Compose E2E Smoke (push) Canceled after 0s
CI / Lint (push) Canceled after 0s
CI / Publish edge images (auth) (push) Canceled after 0s
CI / Publish edge images (backend) (push) Canceled after 0s
CI / Publish edge images (frontend) (push) Canceled after 0s
fix: self-hosted auth without mail transport, password-manager-friendly login
2026-09-22 19:50:30 +02:00
Tomas DvorakandDevin 2fbde04563 fix: don't require email infra on self-hosted, improve login form detection
- sendTransactionalEmail no-ops (with a warning) when no mail transport is
  configured instead of throwing — sign-up 500'd on SMTP-less instances
- sendVerificationEmail catches transport failures so a broken SMTP can't
  block account creation; verification stays optional (requireEmailVerification
  was never set)
- login form gains id/name attributes and label for/id pairing so password
  managers (Proton Pass et al.) detect the fields; email input uses
  autocomplete=username

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-22 19:46:14 +02:00
Tomáš Dvořák 9c118d41c2 Merge pull request #12 from Dvorinka/feat/landing-page
feat: add static landing page
2026-09-22 19:38:16 +02:00
Tomas DvorakandDevin c0c5e1cfcb chore: gitignore vercel link metadata in landing/
Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-22 18:19:40 +02:00
Tomas DvorakandDevin 28b10eee2b feat: add static landing page
Self-contained index.html under landing/ — no build step, deploys as a
plain static site (Vercel output dir = landing/). Uses the app's design
tokens (zinc dark, vermilion accent, Geist/Geist Mono vendored as woff2),
real screenshots from docs/, and the README feature/architecture facts.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-22 18:14:28 +02:00
Tomáš Dvořák 23868ef7c9 Merge pull request #11 from Dvorinka/fix/installer-strip-build-blocks
CI / Backend Tests (push) Canceled after 0s
CI / Frontend Tests (push) Canceled after 0s
CI / Build All Services (push) Canceled after 0s
CI / Docker Build (auth) (push) Canceled after 0s
CI / Docker Build (backend) (push) Canceled after 0s
CI / Docker Build (frontend) (push) Canceled after 0s
CI / Migration Up/Down (push) Canceled after 0s
CI / Compose E2E Smoke (push) Canceled after 0s
CI / Lint (push) Canceled after 0s
CI / Publish edge images (auth) (push) Canceled after 0s
CI / Publish edge images (backend) (push) Canceled after 0s
CI / Publish edge images (frontend) (push) Canceled after 0s
fix: strip build blocks in installer prebuilt path
2026-09-21 22:31:36 +02:00
Tomas DvorakandDevin 10c667dffd fix: strip build blocks in installer prebuilt path
The installer's GHCR path ships a compose file that still declares
build: contexts pointing at apps/*/Dockerfile, which it never
downloads. Any later `compose build` or `up --build` fails with
"lstat apps: no such file or directory". Delete the build blocks
after a successful prebuilt pull so the shipped file matches what
is actually runnable.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 22:25:32 +02:00
Tomáš Dvořák 11aa82b459 Merge pull request #10 from Dvorinka/release/v0.7.0
CI / Backend Tests (push) Canceled after 0s
CI / Frontend Tests (push) Canceled after 0s
CI / Build All Services (push) Canceled after 0s
CI / Docker Build (auth) (push) Canceled after 0s
CI / Docker Build (backend) (push) Canceled after 0s
CI / Docker Build (frontend) (push) Canceled after 0s
CI / Migration Up/Down (push) Canceled after 0s
CI / Compose E2E Smoke (push) Canceled after 0s
CI / Lint (push) Canceled after 0s
CI / Publish edge images (auth) (push) Canceled after 0s
CI / Publish edge images (backend) (push) Canceled after 0s
CI / Publish edge images (frontend) (push) Canceled after 0s
chore: release v0.7.0
v0.7.0
2026-09-21 17:58:18 +02:00
Tomas DvorakandDevin 9658e167ba chore: release v0.7.0
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 17:53:47 +02:00
Tomáš Dvořák e71db32885 Merge pull request #9 from Dvorinka/feat/instance-admin
feat: instance administration, bootstrap admin, managed-tier OAuth gate
2026-09-21 17:53:03 +02:00
Tomas DvorakandDevin c6166de886 feat: instance administration, bootstrap admin, and managed-tier OAuth gate
Self-hosted instances are now email/password only — OAuth providers
(GitHub/Google/Discord/Microsoft) activate solely when PRIMORA_MANAGED=true,
reserved for the future hosted tier.

Sign-up lifecycle: the first public sign-up becomes the instance admin; after
bootstrap, sign-up closes by default. A better-auth databaseHook gates only
/sign-up/email, so admin-created users and OAuth flows bypass it. The login
page reads GET /instance/public to hide the sign-up tab, show the bootstrap
notice, and render only the providers the instance offers.

Instance settings live in core.settings (migration 00010) and resolve
in-app > env > built-in default, cached 15s. Platform admins (better-auth
user.role) manage sign-up, mail transport, and rate limits via
GET/PUT/DELETE /instance/settings or the new Settings → Instance tab. Secret
values are AES-256-GCM encrypted at rest with PRIMORA_ENCRYPTION_KEY, never
returned by the API, and decrypted by the auth service at send time.

Auth service reads the same settings table for the sign-up gate and mail
config, so in-app changes take effect without a restart.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 17:46:47 +02:00
Tomáš Dvořák 1214108d6b Merge pull request #8 from Dvorinka/docs/readme-cleanup
docs: slim README, move detail to per-app and contributor docs
2026-09-21 16:49:00 +02:00
Tomas DvorakandDevin 4f66c72121 docs: slim README, move detail into per-app and contributor docs
README down to the Containr skeleton: header, three-screenshot row
(rest behind <details>), features, architecture, quick start, links.
Dropped tables and sections already covered by QUICK_START.md.
Native dev commands and repo layout moved to CONTRIBUTING.md;
CLI/MCP usage moved to new per-app READMEs.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 16:46:32 +02:00
Tomáš Dvořák d3dc84028d Merge pull request #7 from Dvorinka/docs/readme-screenshots
docs: README refresh with logo and app screenshots
2026-09-21 16:19:12 +02:00
Tomas DvorakandDevin 591dedab2f docs: restructure README, add logo and app screenshots
Containr-style layout: centered mark, tagline, nav, CI/release/license
badges. New screenshots section with six captures from demo mode
(overview, storage, telemetry, collections, automation, audit).
Configuration and port tables added; existing install/dev/CLI content
preserved.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 16:16:38 +02:00
Tomáš Dvořák 5af23fbdc8 Merge pull request #6 from Dvorinka/fix/release-upload-files
ci: upload release assets by file, not glob
v0.6.0
2026-09-21 14:41:58 +02:00
Tomas DvorakandDevin bac8f08782 ci: upload release assets by file, not glob
Desktop artifacts extract to nested dirs (appimage/, deb/, rpm/);
dist-release/* expanded to directories and gh release create died on
"is a directory" mid-upload. find -type f builds the file list.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 14:36:48 +02:00
Tomáš Dvořák f9cd641164 Merge pull request #5 from Dvorinka/fix/release-artifact-download
ci: exclude .dockerbuild artifacts from release download
2026-09-21 14:25:06 +02:00
Tomas DvorakandDevin c3321b86ae release: align desktop versions, harden tag check
tauri.conf.json and apps/desktop/package.json lagged at 0.5.0, so
v0.6.0 desktop bundles were labeled 0.5.0. Verify job now checks all
three version sources match the tag.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 14:20:02 +02:00
Tomas DvorakandDevin 00bf725ba7 ci: exclude .dockerbuild artifacts from release download
build-push-action uploads <repo>~<branch>~<sha>.dockerbuild metadata
blobs as artifacts. pattern:"*" pulled them into the release job and
extraction failed after 5 retries, killing the v0.6.0 release run.
Match only binaries-*, desktop-*, and npm-tarballs.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 14:06:18 +02:00
Tomáš Dvořák ec91deed46 Merge pull request #4 from Dvorinka/release/v0.6.0
release: v0.6.0
2026-09-21 13:49:49 +02:00
Tomas DvorakandDevin fede14b24f release: v0.6.0
Bump version to 0.6.0 and cut the changelog — phase 7 automation
(scheduled jobs, realtime SSE, automation UI, jobs CLI/MCP), security
hardening, and the new CI image pipeline + install.sh.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 13:45:17 +02:00
Tomáš Dvořák d39fc22594 Merge pull request #3 from Dvorinka/ci/docker-enhancements
ci: Docker image caching, Trivy scans, edge publishing, standalone installer
2026-09-21 13:44:16 +02:00
Tomas DvorakandDevin fc79c57f7e ci: run Trivy via container image, not the action
The trivy-action setup step downloads its binary through the
unauthenticated GitHub API and dies to rate limits on shared runners.
Running aquasec/trivy against the docker socket has no API dependency
and is one line shorter.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 13:35:25 +02:00
Tomas DvorakandDevin fe28902c4a ci: image caching, Trivy scans, edge publishing, standalone installer
- docker-build job is now a per-app matrix with GHA layer cache, a
  container contents smoke check, and a non-blocking Trivy scan.
- New docker-publish job pushes edge + sha tags to GHCR on master.
- Fixed release.yml tagging ghcr.io/<Owner>/... with a mixed-case
  owner — GHCR requires lowercase, so tagged releases would have
  failed at push time.
- compose files: image: keys name local builds after the GHCR repos.
- install.sh: curl|bash installer — fetches compose files, generates
  secrets, pulls prebuilt images (docker pull + up --no-build, since
  compose pull skips buildable services), falls back to a source
  tarball build when packages aren't public.
- README: install section covering the one-liner, clone, and prebuilt
  paths plus common compose commands.

Verified locally: all three images build, full dev-overlay stack
passes scripts/smoke-e2e.sh, and install.sh produces a healthy
stack in a standalone directory.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-21 13:22:25 +02:00
Tomáš Dvořák 438ee46016 Merge pull request #2 from Dvorinka/feat/phase-7-automation-realtime
CI / Backend Tests (push) Successful in 10m6s
CI / Frontend Tests (push) Failing after 4m54s
CI / Build All Services (push) Successful in 19m38s
CI / Docker Build Test (push) Successful in 1m45s
CI / Migration Up/Down (push) Failing after 5m46s
CI / Compose E2E Smoke (push) Failing after 3s
CI / Lint (push) Successful in 30m8s
feat: phase 7 automation & realtime — scheduled jobs, domain events, SSE
2026-09-18 15:37:34 +02:00
Tomas DvorakandDevin 1494bedbd5 lint: satisfy errcheck + ineffassign — masked while the linter couldn't run
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 15:23:49 +02:00
Tomas DvorakandDevin a215da452a ci: build golangci-lint with repo toolchain — prebuilt v1 binary can't parse go 1.26
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-18 15:19:35 +02:00
Tomas DvorakandDevin 9e9a3d5f98 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>
2026-09-18 15:15:01 +02:00
Tomáš Dvořák 4b7fdf35ad Merge pull request #1 from Dvorinka/feat/phase-6-production-hardening
CI / Backend Tests (push) Successful in 10m22s
CI / Frontend Tests (push) Failing after 4m53s
CI / Build All Services (push) Successful in 19m40s
CI / Docker Build Test (push) Successful in 1m41s
CI / Migration Up/Down (push) Failing after 5m33s
CI / Compose E2E Smoke (push) Failing after 2s
CI / Lint (push) Failing after 14m38s
feat: phase 6 production hardening + DB-to-DB transfer
2026-09-17 20:39:42 +02:00