-
v1.19.2 — PR Review Hardening
StableAll checks were successfulPublish / detect-release (push) Successful in 7sPublish / tag (push) Successful in 8sCI / test-gravity-pm (push) Successful in 1m11sCI / test-event-engine (push) Successful in 1m29sPublish / publish-containers (push) Successful in 2m25sPublish / promote-release (push) Successful in 2sCI / lint (push) Successful in 2m52sCI / build (push) Successful in 55sreleased this
2026-02-23 14:58:45 +00:00 | 0 commits to main since this releaseWhat's Changed
v1.19.2 addresses all findings from two rounds of automated PR review on the v1.19.1 release. This is a hardening release — no new features, only security fixes, bug fixes, test improvements, and CI enhancements.
Security
- SSRF prevention: Validate OIDC issuer URL in all code paths including hot-reload via NATS; block IPv4-mapped IPv6 metadata addresses; reject exotic URL schemes (
javascript:,data:) - Secret redaction: Strip
oidc_client_secretfrom event log payloads before publishing to outbox - Prompt injection: Escape
</user_content>closing delimiter in Claude dispatch prompt sanitization - Cookie security: Propagate
SESSION_SECUREflag to OIDC state/nonce cookies - Session hardening: Improve session cookie security defaults (SameSite, HttpOnly, Secure)
- Request limits: Add 1 MB global request body size limit to event-engine job API
- Port binding: Bind all Docker services to 127.0.0.1 (was 0.0.0.0 for app/monitoring services)
- CI supply chain: Pin golangci-lint install script to release tag (was unpinned HEAD)
Bug Fixes
- Soft-delete invariant: Add
AND deleted_at IS NULLto 3UpdateXxxTxmethods that could update soft-deleted rows - Transaction isolation: Fix empty-update fallback reading from pool outside caller's transaction in all Tx methods
- Transactional reads: Move DeleteProject/PurgeProject project reads inside transaction with
FOR UPDATElocking - Domain events: PurgeProject now emits
ProjectDeletedevent withpurged: trueflag - SQL enum cast: Fix PostgreSQL implicit text→enum cast failure in
ReapStaleJobsCASE expression - Reaper logic:
ReapStaleJobsnow marks exhausted-retry jobs asdeadinstead of cycling throughfailed - Atomic retries: Use SQL
retries = retries + 1in processor to prevent race with reaper - TOCTOU fix: Construct
UpdateAuthSettingsresponse inline from saved settings - Graceful shutdown: Add signal-handling graceful shutdown to gravity-pm server
- Server timeouts: Add
ReadHeaderTimeout(10s) andIdleTimeout(120s) to both HTTP servers - Deterministic SQL: Sort parameter keys in
buildUpdateSetsfor reproducible query plans - Column allowlists: Add per-entity column allowlists to prevent arbitrary column updates
- Error leakage: Log full stderr from Claude CLI server-side; return generic error to clients
Refactoring
- Consolidate NATS JetStream API and connection lifecycle in event-engine
- Extract sub-functions from event-engine main and processor
- Standardize slog usage across both service entrypoints
- Transactional outbox for settings updates
Testing
- Coverage gate: Raised CI minimum from 22% to 40%
- Templ filtering: Exclude generated
*_templ.gofiles from gravity-pm coverage calculation - gravity-pm: 21.9% → 49.9% (filtered) — handler 69.1%, auth 46.1%, config 77.3%, event 62.8%
- event-engine: 27.7% → 62.1% (with DB) — handler 81.2%, store 68.1%, webhook 74.1%, engine 72.9%
- New tests: 65+ test cases across handler, auth, web, and store packages
- Flaky test fix: Namespace
actor_typeper test package to prevent concurrent cleanup collision - CI database: PostgreSQL service added to event-engine CI job for integration tests
- Auth wiring: Route-level middleware tests for all admin-protected endpoints
Infrastructure
- Add healthchecks to all Docker Compose services
- Complete
.env.examplewith all consumed environment variables (empty values with generation instructions) - Fix Grafana
histogram_quantilequeries with propersum by (le)aggregation
Work Packages
46 work packages across 2 epics (OP#1746, OP#1765, OP#1776) — all closed.
Full PR: #10
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- SSRF prevention: Validate OIDC issuer URL in all code paths including hot-reload via NATS; block IPv4-mapped IPv6 metadata addresses; reject exotic URL schemes (
-
v1.19.1 — Observability Foundation
StableSome checks failedCI / lint (push) Successful in 1m5sCI / test-gravity-pm (push) Successful in 1m7sCI / test-event-engine (push) Successful in 1m22sPublish / detect-release (push) Successful in 6sPublish / tag (push) Successful in 4sPublish / publish-containers (push) Failing after 38sCI / build (push) Successful in 5m1sPublish / promote-release (push) Failing after 0sreleased this
2026-02-23 04:03:20 +00:00 | 36 commits to main since this releaseFeatures
- Prometheus metrics: Added
prometheus/client_golangto event-engine with counters/histograms for events, jobs, and webhooks (OP#1492) - Structured logging: Standardized
slogacross both services with contextual error logging on all 5xx responses (OP#1493, OP#1528) - Health endpoints: Aggregated per-component health checks (database, NATS, Valkey) returning structured JSON (OP#1494)
- Grafana dashboard: Operational dashboard provisioning config with pre-built panels (OP#1495)
- Job queue & dispatch: Full async job submission, pull-based consumer, retry with dead-letter, timeout enforcement, stale job reaper, concurrency limiter (OP#1491 epic)
- CSRF protection: Origin/Referer validation middleware for session-authenticated state-changing requests (OP#1615)
- Graceful shutdown: Signal handling (SIGINT/SIGTERM) with 15s drain timeout for event-engine (OP#1613)
Bug Fixes
- TOCTOU race in UpdateJobStatus: Rewrote to atomic
WHERE status IN (...)guard (OP#1611) - Missing n++ in buildJobWhere: Fixed parameter counter skip causing query failures (OP#1629)
- Unconditional msg.Ack: Changed to conditional Ack/Nack based on SubmitJob success (OP#1626)
- Orphaned DB records: Mark job as "dead" when NATS publish fails after DB insert (OP#1612)
- Silently swallowed errors: Fixed across both services (OP#1528)
- crypto/rand.Read error: Now checked in event ID generation (OP#1527)
- NATS ack/term errors: Logged in job queue consumer (OP#1530)
Security
- Removed InsecureSkipVerify from OIDC HTTP client (OP#1524)
- Mandatory webhook secret: Validation now required, server refuses to start without it (OP#1525)
- Removed hardcoded credentials from source (OP#1526)
- DEV_AUTH production guard: Refuses to start with DEV_AUTH in non-development environments (OP#1614)
- Configurable session cookie Secure flag via SESSION_SECURE env var (OP#1610)
- SQL column whitelist in buildUpdateSets prevents injection (OP#1624)
- Webhook secret moved from package var to struct field (OP#1628)
- Transactional writes in webhook handlers with outbox events (OP#1617)
Refactoring
- Expanded
WPabbreviations toWorkPackagein model types/constants (OP#1514) - Renamed
WPFilter→WorkPackageFilter(OP#1515) - Renamed
PRURL→PullRequestURL(OP#1516) - Renamed
CSSVars→CSSVariables(OP#1517) - Removed unused Zitadel auth library (OP#1518)
- Removed dead code: unused store methods, no-op var (OP#1627)
- Bumped Go dependencies across both apps (OP#1519)
CI/CD
- Added golangci-lint with all violations fixed (OP#1531)
- Added test coverage reporting with minimum threshold (OP#1532)
- Split CI into parallel lint, test, and build jobs (OP#1599)
- Added
-raceflag to CI test runs (OP#1623)
Testing
- Auth middleware and CSRF protection unit tests (OP#1533)
- Work package CRUD handler tests with mock store (OP#1534)
- Comment and event handler tests (OP#1535)
- Auth flow integration tests (OP#1536)
- Comprehensive handler unit tests for coverage gate (OP#1598)
- Publisher error path tests (OP#1618)
- Transaction commit failure tests (OP#1619)
- Status-change event logic tests (OP#1620)
- UserSettings and ResetUserTheme tests (OP#1621)
- Mock call-count verification (OP#1622)
- Request context in eventlog writer (OP#1625)
- Compose depends_on for service ordering (OP#1616)
Tasks
- OP#1492, OP#1493, OP#1494, OP#1495, OP#1496, OP#1497
- OP#1514, OP#1515, OP#1516, OP#1517, OP#1518, OP#1519
- OP#1524, OP#1525, OP#1526, OP#1527, OP#1528, OP#1529, OP#1530
- OP#1531, OP#1532, OP#1533, OP#1534, OP#1535, OP#1536
- OP#1598, OP#1599
- OP#1610, OP#1611, OP#1612, OP#1613, OP#1614, OP#1615, OP#1616
- OP#1617, OP#1618, OP#1619, OP#1620, OP#1621, OP#1622, OP#1623
- OP#1624, OP#1625, OP#1626, OP#1627, OP#1628, OP#1629
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Prometheus metrics: Added
-
v1.19.0 — Agent Job Queue & Dispatch
StableAll checks were successfulreleased this
2026-02-22 18:06:05 +00:00 | 101 commits to main since this releaseFeatures
- Job Queue Infrastructure: NATS JetStream-backed work queue for agent dispatches with durable
AGENT_JOBSstream - Job Message Producer/Consumer: Publish job requests and pull-based consumption with configurable batch sizes
- Job Store: Full CRUD operations for job state persistence with PostgreSQL
engine_jobstable - Job State Machine: Typed state transitions (pending → running → completed/failed/dead) with audit tracking
- Retry & Backoff: Exponential backoff retry logic with configurable max attempts and dead-letter handling
- Timeout Enforcement: Per-job timeout with background reaper for stale/stuck jobs
- Concurrency Limiter: Semaphore-based per-agent-type concurrency control
- Job Metrics & Logging: Structured logging for queue depth, processing latency, and job lifecycle events
- REST API: Job submission endpoint (
POST /jobs) and job management handler - Async Dispatch: Event engine refactored from synchronous CLI dispatch to async job submission
- Result Events: Job completion results published back to NATS for downstream consumers
Refactoring
- Replaced synchronous Claude CLI dispatch with async job submission pipeline
Tests
- Unit tests for JetStream job queue (producer, consumer)
- Unit tests for job store and state machine
- Unit tests for retry, timeout, and reaper logic
- Unit tests for concurrency limiter
- Unit tests for job API handlers
- End-to-end integration tests for async dispatch pipeline
Tasks
- OP#1247: Configure JetStream stream for agent jobs
- OP#1248: Implement job message producer
- OP#1249: Implement job message consumer (pull-based)
- OP#1250: Unit tests for JetStream job queue
- OP#1251: Create jobs table migration
- OP#1252: Implement job store CRUD operations
- OP#1253: Implement job state machine transitions
- OP#1254: Unit tests for job store and state machine
- OP#1255: Implement retry logic with exponential backoff
- OP#1256: Implement job timeout enforcement
- OP#1257: Unit tests for retry and timeout logic
- OP#1258: Implement semaphore-based concurrency limiter
- OP#1259: Add job queue metrics and logging
- OP#1260: Unit tests for concurrency limiter
- OP#1261: Implement job REST API handler
- OP#1262: Add job submission endpoint
- OP#1263: Unit tests for job API endpoints
- OP#1264: Refactor engine to submit jobs instead of dispatching synchronously
- OP#1265: Write dispatch result back to job state
- OP#1266: End-to-end integration test for async dispatch
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Job Queue Infrastructure: NATS JetStream-backed work queue for agent dispatches with durable
-
released this
2026-02-21 18:37:09 +00:00 | 127 commits to main since this releaseWhat's New
Complete auth system overhaul and UI foundation for Gravity PM.
Auth System
- Replace Zitadel with Authelia as OIDC identity provider
- Replace hand-rolled sessions with scs + Valkey store
- Replace hand-rolled OIDC with goth provider
- Three auth modes: OIDC (external), built-in (local email+password), guest
- Sec-Fetch-Site CSRF middleware
- DEV_AUTH mode for local development
- First-run setup wizard for auth configuration
- Dual auth middleware (sessions + bearer tokens)
Theming
- Theme model with builtin seed data (Catppuccin Mocha, Catppuccin Latte, Nord, Dracula, etc.)
- Theme REST API (CRUD + resolve)
- CSS variable injection with Tailwind theme integration
- Live theme preview on user settings — instant preview on card selection
- Admin theme management (create/edit/delete custom themes)
Settings
- App settings singleton with migration
- Settings REST API (admin + user)
- Admin settings with theme card picker (replaces dropdown)
- User settings: appearance (theme picker + color mode) and profile
- Admin pages always render with server default theme
Navigation & Layout
- Auth-aware header with user menu dropdown
- Admin layout with sidebar navigation
Infrastructure
- Dual-mode edge proxy: Tailscale multi-node + custom domain via Caddy
- Tailscale stale node cleanup on boot (prevents hostname collisions)
- Caddyfile templates for tailscale and domain modes
setup.shinteractive wizard for stack configuration- Seed command for test data
- Makefile dev compose override
Bug Fixes
- Fix DevAuth logout route GET→POST (OP#1237)
- Fix header logout to use POST form (OP#1238)
- Fix EnsureAdminUser overwriting setup wizard admin (OP#1239)
- Fix OIDC issuer mismatch for Docker split URLs (OP#1240)
- Fix UpdateUserPreferences scan column mismatch (OP#1241)
Stats
- 33 commits | 43 work packages (5 epics, 29 tasks, 4 features, 5 bugs)
- All unit + integration tests passing (84 total)
- E2E tested: built-in auth, OIDC via Authelia, theme preview, admin pages
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v1.17.0
Stablereleased this
2026-02-20 17:00:04 +00:00 | 163 commits to main since this releaseWhat's Changed — Event Infrastructure
Infrastructure
- feat(infra): add NATS container with JetStream to docker-compose (
4fd6b23) - feat(infra): add Valkey container to docker-compose (
9dc76e0) - feat(infra): wire NATS and Valkey into service environment config (
20d1028)
Domain Event Publishing
- feat(event): define domain event types, payload model, and Publisher interface (
237581a) - feat(store): add pm_event_outbox migration, outbox store methods, and BeginTx (
44f2c62) - feat(event): add NATS JetStream publisher and outbox poller (
9d5e319) - feat(event): instrument all write handlers with transactional outbox (
0d0cf9d)
Event-Engine NATS Migration
- feat(event-engine): add NATS connection wrapper with reconnect logic (
5798469) - feat(event-engine): replace GoChannel with Watermill subscriber/publisher interfaces (
e072158) - feat(event-engine): wire NATS JetStream and remove Gravity PM webhook (
12e183d)
Event Log & History
- feat(gravity-pm): add pm_event_log migration for append-only audit trail (
d954dce) - feat(event-engine): add event log writer consuming JetStream events (
8d6a624) - feat(events): add event history API endpoint and MCP tool (
5f194ca)
Bug Fixes
- fix: consolidate chi work package routes to resolve 404 on GET/PATCH/DELETE (
3360579)
Tests
- test(event): add poller drain and handler event helper tests (
7883e2f) - test(event-engine): replace GoChannel with NATS JetStream in all tests (
c819c96) - test(events): add event log integration tests (
c2ae8c6)
Tasks
- OP#1178: Add NATS container with JetStream to docker-compose.yml
- OP#1179: Add Valkey container to docker-compose.yml
- OP#1180: Update .env.example and service environment configuration
- OP#1181: Test: Verify NATS and Valkey infrastructure
- OP#1182: Define domain event types and payload model
- OP#1183: Create pm_event_outbox migration and store methods
- OP#1184: NATS publisher client and outbox poller
- OP#1185: Inject event publisher into Handler and instrument all write handlers
- OP#1186: Test: Domain event publishing integration tests
- OP#1187: Create pm_event_log migration
- OP#1188: Event log writer in event-engine (JetStream consumer)
- OP#1189: Event history API endpoint and MCP tool
- OP#1190: Test: Event log integration tests
- OP#1191: Add watermill-nats/v2 dependency and NATS connection wrapper
- OP#1192: Replace GoChannel with NATS JetStream in engine.go
- OP#1193: Remove Gravity PM webhook handler and wire NATS in main.go
- OP#1194: Test: Event-engine NATS integration tests
Epics
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- feat(infra): add NATS container with JetStream to docker-compose (
-
v1.17.1
StableAll checks were successfulreleased this
2026-02-20 16:35:01 +00:00 | 161 commits to main since this releasev1.17.1 — CI Network Fix
Patch release: v1.17.0 CI failed because the
dockyard-sharedDocker network was missing on the runner host. All v1.17.0 code is already on main — this is a version-only bump to produce a clean CI artifact chain.Changes
Same as v1.17.0 (Event Infrastructure) plus:
- Runner compose network renamed from
dockyard-sharedtodocker-shared(neptune-forgejo repo)
Tasks
- OP#1198: Create release branch and publish v1.17.1
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Runner compose network renamed from
-
v1.15.0
Stablereleased this
2026-02-18 00:43:11 +00:00 | 183 commits to main since this releaseWhat's Changed
Service Stack Networking
This release restructures the Gravity compose stack networking. Services now expose their own ports directly with configurable host ports via environment variables, and adds Zitadel OIDC auto-provisioning for zero-config first boot.
Features
- Direct service port exposure — Removed Caddy reverse proxy in favor of direct port bindings. Each service gets a configurable host port via environment variables (GPM_PORT, ZITADEL_PORT, ENGINE_PORT). Service-to-service calls use Docker DNS.
- Zitadel OIDC auto-provisioning — A provisioner sidecar creates the Gravity project and OIDC app in Zitadel on first boot, writing client credentials to a shared volume (OP#908)
- Zitadel bootstrap with service account and PAT — Separate database, init container for machinekey permissions, FirstInstance bootstrap with service account (OP#913)
- OIDC credential loading — gravity-pm reads OIDC credentials with precedence: env vars > credential file > unconfigured (OP#915)
Tasks
- OP#906: Initialize version branch from develop
- OP#909: Add Caddy service with Caddyfile and path-based routing
- OP#910: Remove direct host port bindings from internal services
- OP#911: Add environment variable mechanism for optional port exposure
- OP#912: Test Caddy reverse proxy routing end-to-end
- OP#913: Configure Zitadel bootstrap with service account and PAT
- OP#914: Create provisioner sidecar container with OIDC app setup script
- OP#915: Update gravity-pm to read OIDC credentials from provisioner output
- OP#916: Test Zitadel auto-provisioning end-to-end
- OP#917: Create release branch and publish v1.15
Install
git clone ssh://git@git.bros.ninja:2222/mike/gravity.git cd gravity cp .env.example .env docker compose up -dContainer Images
Container images were not published for this release. The CI push failed with
413 Request Entity Too Large— nginx reverse proxy in front of Forgejo needsclient_max_body_sizeincreased. Build locally withdocker compose up --build.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
v1.13.1
StableAll checks were successfulreleased this
2026-02-17 15:01:05 +00:00 | 193 commits to main since this releaseWhat's Changed
Patch release to fix CI publish workflow deprecation warning.
Bug Fixes
- OP#875: Install
docker-cli-buildxin publish workflow sodocker builduses BuildKit instead of the deprecated legacy builder
Container Images
git.bros.ninja/mike/gravity/gravity-pm:1.13.1 git.bros.ninja/mike/gravity/event-engine:1.13.1Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- OP#875: Install
-
v1.13.0
StableAll checks were successfulreleased this
2026-02-17 14:46:17 +00:00 | 198 commits to main since this releaseWhat's Changed
First release of the consolidated Gravity monorepo — a unified PM + messaging + agent orchestration platform.
Features
- OP#830: Go project scaffold with docker-compose infrastructure
- OP#831: Extracted gravity-auth OIDC library from Gashy
- OP#832: Database schema for work packages, versions, comments, time entries, and news
- OP#833: REST API for work packages, versions, comments, and news
- OP#834: Web UI with templ + htmx (list, detail, and board views)
- OP#835: Stdio MCP server with 15 tools for agent integration
- OP#836: Forgejo webhook integration for commit keyword closing
- OP#837: Event engine scaffold with Forgejo webhook receiver and @agent dispatch
- OP#838: Gravity skill to replace openproject skill
- OP#839: Adapted release, journal, refinement, wiki, and testing skills for Gravity PM
- OP#840: Data migration script from OpenProject to Gravity PM
- OP#841: Unit and integration tests for Gravity PM and MCP server
- OP#872: Forgejo Actions publish workflow for container images
- OP#873: Docker-compose updated to pull from Forgejo container registry
Infrastructure
- Go workspace monorepo:
apps/gravity-pm,apps/event-engine,libs/auth,tools/gravity-migrate - CI workflow with Go vet + test
- Publish workflow with container image builds via DinD
- Docker Compose for production (registry images) and development (local builds)
Deploy
# Copy and configure environment cp .env.example .env # Edit .env with your values # Production (pulls from Forgejo registry) docker compose up -d # Development (builds locally) docker compose -f docker-compose.yml -f docker-compose.dev.yml up --buildContainer Images
git.bros.ninja/mike/gravity/gravity-pm:1.13.0 git.bros.ninja/mike/gravity/event-engine:1.13.0Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads