Skip to content

Changelog — Jarvis Helm Chart ​

All notable changes to the Jarvis Helm chart (oci://ghcr.io/kj187/charts/jarvis) are documented in this file. The format is based on Keep a Changelog, and the chart follows Semantic Versioning. The chart version is decoupled from the Jarvis app version; appVersion is the image tag the chart deploys by default. The app changelog lives in the repository root.

Every chart version lists a Breaking Changes section, even when there are none. A breaking change is anything that can make helm install/helm upgrade fail or change the behavior of an existing release without the user changing their values: removed or renamed values, changed defaults, new validations that reject previously accepted values, new resources that need extra permissions, or changed selector labels. A breaking change always bumps the chart's major version.

Entries up to and including 1.7.6 were reconstructed from the git history when this file was introduced; their breaking-change classification was assessed retroactively.

Unreleased ​

2.2.0 - 2026-10-10 ​

Breaking Changes ​

  • No breaking changes.

Changed ​

  • appVersion bumped to 2.1.0.
  • The readiness probe now sets timeoutSeconds: 3 (the Kubernetes default of 1 s is shorter than the app's 2 s database ping, so a slow ping could fail the probe and pull the pod out of the Service endpoints). Together with the app no longer caching a failed ping when a client aborts the request, a healthy pod stays ready. Values are unchanged — not breaking.
  • database.maxOpenConns: 1 with a PostgreSQL DSN is now raised to 2 by the app, with a warning in the log, instead of running a single-connection pool, which the app never supported. The default (10) and every value from 2 up are unchanged; SQLite ignores the value. Nothing has to change in existing values — not breaking.
  • Custom cluster headers (clusters[].auth.headers) are now stored in the chart's Secret (cluster-<n>-header-<name>) and read by the Deployment through secretKeyRef, instead of being rendered into the ConfigMap, so a header such as Authorization no longer sits in a readable ConfigMap. The environment the app sees is identical (JARVIS_CLUSTER_<n>_HEADER_<name>), and the chart Secret is rendered whenever a header is set, also when database.existingSecret is used. Values stay as they were; nothing has to change in existing values — not breaking.
  • The liveness probe now calls /health/live (process only) and the readiness probe /health/ready (database ping), instead of both calling /health. A database outage now takes the pod out of the Service endpoints, while an Alertmanager outage does not. The new paths exist from the app version that ships with this chart, so an image.tag override pointing at an older Jarvis release fails its probes — not breaking for a release that keeps the chart's default tag.

Added ​

  • image.digest value (sha256:<64 hex>): when set, the pod pulls <repository>:<tag>@<digest>. Empty by default, so an existing release renders unchanged; a malformed digest fails the render instead of failing at image-pull time — not breaking.

  • networkPolicy.* values: an optional NetworkPolicy that restricts ingress (port 8080, optionally from networkPolicy.ingress.from) and egress (DNS via networkPolicy.egress.allowDns plus networkPolicy.egress.rules). Off by default, so an existing release renders unchanged and no new resource appears — not breaking. Enabling it denies every connection that is not listed: add egress rules for Alertmanager, the database and the OIDC issuer (see docs/deploy-kubernetes.md).

  • config.wsMaxConnections value (JARVIS_WS_MAX_CONNECTIONS), empty by default and rendered into the ConfigMap only when set (0 is rendered and means no cap). The app itself now caps WebSocket connections per pod at 500 and answers 503 beyond that; the value tunes or lifts that cap. With the chart's default tag an existing release gets the app default without changing values — not breaking for any realistic deployment, since 500 simultaneous browser tabs per pod is far above the intended use.

  • metrics.token (stored in the chart Secret) or metrics.existingSecret / metrics.existingSecretKey (default metrics-token) value: sets JARVIS_METRICS_TOKEN, so /metrics requires Authorization: Bearer <token>. The ServiceMonitor then scrapes with an authorization block pointing at the same Secret key; annotation-based scraping and other scrapers have to send the header themselves. Empty by default, so an existing release renders unchanged and keeps /metrics open — not breaking.

  • config.allowedHosts (JARVIS_ALLOWED_HOSTS) and config.trustedProxies (JARVIS_TRUSTED_PROXIES) values, both empty by default and rendered into the ConfigMap only when set. allowedHosts makes the app answer 421 to a Host header outside the list (probe and metrics paths exempt); trustedProxies names the proxies whose X-Forwarded-For is believed when logging the client IP. Empty renders unchanged and keeps the checks off — not breaking. An invalid trustedProxies entry makes the app refuse to start, so it surfaces on rollout.

  • config.cookieSecure value (default empty), rendered as JARVIS_COOKIE_SECURE only when set. true makes the session cookie always Secure, for a TLS-terminating proxy that does not send X-Forwarded-Proto; empty keeps the automatic behavior, so an existing release renders unchanged — not breaking.

  • auth.setupToken value (and auth.existingSecretKeys.setupToken, default setup-token), rendered as JARVIS_SETUP_TOKEN from the chart's Secret when auth.provider is internal. When set, creating the first admin through /setup requires the token. Empty by default, so an existing release renders unchanged and keeps the open wizard; with auth.existingSecret the Secret key is optional (optional: true), so a Secret without it does not block the rollout — not breaking.

  • config.resolvedBufferTTL value, rendered as JARVIS_RESOLVED_BUFFER_TTL in the ConfigMap only when set. It sets how long a resolved alert stays in the live snapshot (Go duration, 1m–24h; an invalid value makes the app refuse to start, so it surfaces on rollout). Empty by default, so an existing release renders unchanged and keeps the 20-minute default — not breaking.

  • auth.oidc.adminValue now accepts several comma-separated groups (e.g. admin_a,admin_b); membership in any one grants the admin role. A single group behaves exactly as before and the value is passed through unchanged, so an existing release renders unchanged — not breaking.

2.1.0 - 2026-09-28 ​

Breaking Changes ​

  • No breaking changes.

Added ​

  • config.silenceDurations value, rendered as JARVIS_SILENCE_DURATIONS in the ConfigMap only when set. It defines the instance-wide default durations of the Fast-Silence and Extend-silence menus (comma-separated m/h/d/w/y durations, up to 12, each 1m–365d); an invalid value makes the app refuse to start, so it surfaces on rollout rather than silently. Empty by default, so an existing release renders unchanged and keeps the built-in durations — not breaking.
  • clusters[].auth.* values for per-cluster upstream Alertmanager authentication: OAuth2 client credentials, bearer token, basic auth, and custom headers — rendered as the existing JARVIS_CLUSTER_<n>_* variables the backend already reads. oauth2.clientSecret, bearerToken and basicAuth.password are stored in the chart's Secret, never the ConfigMap; clusters[].auth.existingSecret sources them from an externally managed Secret instead, consistent with database.existingSecret and auth.existingSecret. Setting oauth2.clientId without oauth2.tokenUrl fails the render, mirroring the backend's own startup validation instead of failing silently at runtime.
  • auth.oidc.groupsClaim and auth.oidc.adminValue values, rendered as JARVIS_OIDC_GROUPS_CLAIM and JARVIS_OIDC_ADMIN_VALUE in the ConfigMap, each only when set. They let SSO group membership (e.g. cognito:groups) grant the admin role without editing extraEnv. Empty by default, so an existing release renders unchanged.
  • config.retention.* values (days, eventsDays, claimsDays, silenceEventsDays, commentsDays, sweepInterval), rendered as the corresponding JARVIS_RETENTION_* variables, each only when set. Controls the data-retention sweep; empty by default, matching the backend's own opt-in default of keeping history forever, so an existing release renders unchanged.

Changed ​

  • appVersion bumped to 2.0.0.
  • The chart README now keeps only chart values and chart-specific examples; release verification, upgrade/rollback, and authentication procedures link to their canonical guides instead of duplicating them. Documentation only, no rendered change.
  • The Kubernetes section of docs/authentication-alertmanager.md and the chart README now document clusters[].auth.* directly instead of the extraEnv workaround; extraEnv is kept as a documented fallback for chart versions before this one.
  • The ingress section points at the new reverse-proxy guide and states that config.allowedOrigins must name the URL the browser uses — the WebSocket annotations alone are not enough. Documentation only, no rendered change.
  • artifacthub.io/links's Documentation entry now points at the published docs site (https://kj187.github.io/jarvis/) instead of the docs/ tree on GitHub, following the docs restructure into a reader-intent site. Metadata only, no rendered change.
  • Comments in values.yaml and the template files pointing at docs/persistence.md now point at docs/postgres-ha.md, following the same restructure. Comments and a test suite name only, no rendered change.

Fixed ​

  • The Deployment now rolls when the configuration changes. The pod template carries checksum/config (the rendered ConfigMap) and, when the chart creates a Secret, checksum/secret, so a helm upgrade that changes auth.mode, config.pollInterval, config.allowedOrigins, a cluster entry or a chart-managed secret replaces the pods instead of leaving them on the old environment until a manual kubectl rollout restart. A Secret referenced through an existingSecret value is not rendered by the chart and is not covered — restart the Deployment after rotating it (see docs/deploy-kubernetes.md). The two checksum/* keys belong to the chart: a podAnnotations entry with the same name is ignored instead of rendering a duplicate key. Not breaking: nothing has to change in existing values, and the upgrade rolls the pods just as every chart version upgrade already does, because the pod labels carry the chart version (helm.sh/chart); re-running the same chart version with unchanged values does not roll them. Refs #264.
  • The values table in the chart README documents six values that existed but were listed nowhere: podLabels, persistence.annotations, updateStrategy.type, autoscaling.minReplicas, autoscaling.maxReplicas and autoscaling.targetCPUUtilizationPercentage. updateStrategy.type matters most — its auto-selection (Recreate with a PVC, RollingUpdate otherwise) was explained only in a values.yaml comment and therefore reached neither the website nor Artifact Hub. Documentation only, no rendered change.

2.0.0 - 2026-09-15 ​

Breaking Changes ​

  • SQLite (database.dsn is a file path) combined with replicaCount > 1 or autoscaling.enabled now fails the render regardless of persistence.enabled. Previously the guard only fired with a PVC, so the default emptyDir setup rendered fine — while every pod polled Alertmanager independently and kept its own divergent history. Migration: set replicaCount: 1 or switch to PostgreSQL (database.dsn: postgres://..., see docs/persistence.md). (#194)
  • auth.provider other than none now fails the render unless auth.secretKey or auth.existingSecret is set, and auth.provider: oidc additionally requires auth.oidc.issuer, auth.oidc.clientId and auth.oidc.redirectUrl. Such releases previously rendered, but the pod never started (CreateContainerConfigError). Migration: set the missing values. (#193)

Changed ​

  • appVersion bumped to 1.12.0.
  • The chart now ships its own CHANGELOG.md; the Artifact Hub links point to both the chart and the app changelog.
  • The chart is published only after the image for its appVersion exists — as part of an app release, or on its own for chart-only releases. The README documents the versioning rules (breaking change → major).
  • Chart.yaml comments point to the release process at its new location (.agents/skills/release/SKILL.md); comment-only, no rendered change.

Fixed ​

  • The generated Secret renders dsn, secret-key and oidc-client-secret independently. Setting database.existingSecret no longer suppresses the auth secret key the Deployment references. (#192)

1.7.6 - 2026-09-09 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • appVersion bumped to 1.11.0.

1.7.5 - 2026-09-05 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • appVersion bumped to 1.10.1.

1.7.4 - 2026-09-05 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • appVersion bumped to 1.10.0.

1.7.3 - 2026-08-17 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • appVersion bumped to 1.9.3.

1.7.2 - 2026-07-17 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • appVersion bumped to 1.9.2.

1.7.1 - 2026-07-16 ​

Breaking Changes ​

No breaking changes.

Added ​

  • database.maxOpenConns (default 10) → JARVIS_DB_MAX_OPEN_CONNS, caps the PostgreSQL connection pool per pod. Ignored for SQLite. (#120)

Changed ​

  • appVersion bumped to 1.9.1.

1.7.0 - 2026-07-15 ​

Breaking Changes ​

  • leaderElection.podLabel.enabled defaults to true: the chart now renders a Role (pods: get, patch) and a RoleBinding, and the pod mounts its ServiceAccount token (automountServiceAccountToken: true at pod level) so the leader can label itself. Installations whose Helm user may not create RBAC resources, or that rely on the token not being mounted, must set leaderElection.podLabel.enabled: false. (#112)

Added ​

  • Leader pod label jarvis.kj187.de/role=leader (PostgreSQL multi-replica), with POD_NAME/POD_NAMESPACE injected via the Downward API. (#112)
  • podDisruptionBudget.enabled / podDisruptionBudget.minAvailable and a topologySpreadConstraints passthrough for HA deployments. (#113)
  • metrics.serviceMonitor.relabelings, metricRelabelings, annotations and honorLabels. (#117)

Changed ​

  • appVersion bumped to 1.9.0.

1.6.2 - 2026-07-13 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • appVersion bumped to 1.8.0.

1.6.1 - 2026-07-09 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • appVersion bumped to 1.7.0.

1.6.0 - 2026-07-04 ​

Breaking Changes ​

No breaking changes.

Added ​

  • Prometheus scraping for /metrics: an opt-in ServiceMonitor (metrics.serviceMonitor.enabled) and prometheus.io/* pod annotations (metrics.podAnnotations).
  • Artifact Hub annotations (category, license, links) in Chart.yaml.

Changed ​

  • Chart versioning is decoupled from the app version: the chart is published by its own workflow on changes under charts/ and signed keylessly with cosign. Previous chart versions were identical to the app version.
  • appVersion bumped to 1.6.0.

1.5.0 - 2026-06-26 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • Chart README recommends PostgreSQL for Kubernetes deployments.
  • appVersion bumped to 1.5.0. Chart versions 1.5.1–1.5.3 only bumped appVersion to the matching app release.

1.4.0 - 2026-06-22 ​

Breaking Changes ​

No breaking changes.

Changed ​

  • auth values point to the split user-authentication docs (docs/authentication-user.md).
  • appVersion bumped to 1.4.0.

1.3.1 - 2026-06-19 ​

Breaking Changes ​

  • SQLite with persistence.enabled: true combined with replicaCount > 1 or autoscaling.enabled now fails the render. This was released as a patch at the time.

Added ​

  • updateStrategy.type; when empty, the Deployment strategy is auto-selected: Recreate with persistence.enabled, RollingUpdate otherwise.

Fixed ​

  • Rolling updates with an RWO volume (e.g. EBS) no longer force a volume detach that caused SQLITE_IOERR_READ.

Changed ​

  • appVersion bumped to 1.3.1. Chart version 1.3.0 only bumped appVersion.

1.2.0 - 2026-06-18 ​

Breaking Changes ​

No breaking changes.

Added ​

  • extraEnv, extraVolumes, extraVolumeMounts and serviceAccountTokenProjection (projected, audience-scoped ServiceAccount token, e.g. for Vault/JWT). All disabled by default.

Changed ​

  • appVersion bumped to 1.2.0. Chart version 1.1.0 only bumped appVersion.

1.0.2 - 2026-06-16 ​

Breaking Changes ​

No breaking changes (first published chart version).

Added ​

  • Initial chart: Deployment, Service, ConfigMap, Secret, PVC, HPA, ServiceAccount and Ingress (nginx and Traefik WebSocket examples).
  • User authentication values: auth.provider (none/internal/oidc), auth.mode (write_protect/full_protect), auth.secretKey/auth.existingSecret, OIDC settings.
  • helm-unittest suite.

Chart versions 1.0.3–1.0.5 only bumped appVersion to the matching app release.

Released under the Apache 2.0 License. Jarvis is not affiliated with Prometheus or Alertmanager.