Commit Graph
14682 Commits
Author SHA1 Message Date
kevinveenbirkenbach 8755146a0e chore(claude): allow docs.github.com for WebFetch 2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Fable 5 17cd53609a feat(readme): merge the Production deploy into one docker command
The role README Production section now runs provision and deploy in a
single docker call: APP and HOST are shell variables passed via -e,
INVENTORY is the in-container SPOT for the duplicated paths, and the
redundant --vars-file (optional, default None) and --id (the inventory
is already narrowed by --include) flags are gone. All 153 role READMEs
regenerated from the template; test-run.yml executes exactly this block.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Fable 5 9bce39009c feat(ci): derive deploy-matrix slots from the workflow chain
cli.meta.ci.slots statically and conservatively counts every job the
CI run spawns outside the deploy matrices (reusable workflows opened
recursively, static matrices multiplied out, dynamic ones estimated,
worst entry-*.yml overhead included) and splits the remaining
256-job run budget between compose/swarm/host by the _SHARES weights,
with a per-mode floor and _SLOT_OVERRIDES pins. INFINITO_MAX_JOBS
defaults to 'auto', resolved per mode in apps.sh; the host workflow
drops its hardcoded cap. --matrix renders the budget as a table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Fable 5 0821a16dc1 feat(ci): star the priority line and gate the pipeline on test-run
Priority deploy callers and their discover jobs now carry a star
(marker input threaded through single-node into the leaf workflows);
regular callers are labelled distinctly. New test-run.yml extracts the
Production command from a role README and executes it against the
runner (localhost => local connection, Docker socket instead of TTY),
runs parallel to test-environment and gates the final done job.
Lint Mermaid gets the broom emoji like every other lint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Fable 5 d8ec933232 fix(ci): aggregate variant shards worst-first in role statuses
parse_role_statuses collapsed a role's variant shards per mode with
last-write-wins, so one green shard could mask a failed sibling and
--failed retriggers silently skipped the role (gitlab, run 29599179461).
Aggregate worst-first (failure > cancelled > running > success) and let
parse_role_urls link the worst shard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Opus 4.8 2b3fcb6592 docs(matrix): add the swarm deploy chain schema
Mermaid flowchart of the flavors' swarm chain: handler flush before the registration wait, synapse reaching the issuer through the runner-bridge node gateway, and the node-local verifier skip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Opus 4.8 fa59b29b2a test(filters): whitelist the ansible.builtin urlsplit filter
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Opus 4.8 ca139756e0 style(cln-bkps): shorten the backups-root task names to the length limit
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Opus 4.8 62e9f5efb0 test(akaunting): assert the app is installed after the OIDC login
The OIDC spec only checked the return URL and a visible body, both of which the installer wizard of a never-installed app satisfies (oauth2-proxy authenticates in front of it), so the crashed one-shot install still went green. After the Keycloak round-trip the URL must now avoid /install/ and land on /login or a /{company_id} dashboard, the two states an installed 3.1.21 serves per its route sources.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:24 +02:00
kevinveenbirkenbachandClaude Opus 4.8 7c8a9bb352 fix(dashboard): quote every free-text scalar in the rendered config
The applications menu and the platform/company header interpolated operator and role free text as plain YAML scalars, so any description containing a colon-space broke the rendered config at the from_yaml parse in the branding-asset task; moodle variant 0 hit it as the only deploy combining an active dashboard with web-app-lam, whose description carries 'directories: managing'. All name, description, icon, url and title fields now render through to_json, which yields quoted scalars for arbitrary text, matching what to_nice_yaml already did for the cards block.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:24 +02:00
kevinveenbirkenbachandClaude Opus 4.8 36d50d604c fix(cln-bkps): run the backup cleanups on every backup-holding host
The inventory gating removed the manager's unconditional volume and secrets backup groups, which had been the only include paths that ever executed the cleanup roles; svc-bkp-nfs-2-local declares both cleanups itself but their IS_STACK_HOST gate silently skipped them on the nfs host, so the required_by validator failed the deploy. The gate becomes the group_vars constant IS_BACKUP_HOST (any svc-bkp-* group membership), which covers every include site since only the five backup roles include the cleanups, and both roles now ensure the backups root exists before installing their timer: cleanback refuses a missing root by design and the size-cleanup script walks it with os.listdir.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:24 +02:00
kevinveenbirkenbachandClaude Opus 4.8 5628408b11 fix(swarm): gate one-shot jobs on Complete and retry transient crashes
The install and realm-import waits accepted Shutdown as success, so a crashed job passed silently: akaunting went green without ever installing, and a keycloak import crash left synapse against a realm-less provider, surfacing as matrix Playwright OIDC timeouts. The state probe moves to a shared sys-svc-compose script where only Complete passes, Shutdown fails loudly with the task error, and Failed/Rejected count as pending because the jobs now restart on-failure with three bounded attempts, turning the observed import race from a coin flip into self-healing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:24 +02:00
kevinveenbirkenbachandClaude Opus 4.8 2c6c8b7633 fix(matrix): make the swarm deploy of both flavors converge and authenticate
Three layers of one chain. The CI verifier polled the service matrix_matrix, which no variant creates (the ansible flavor deploys a node-local MDAD runner, the compose flavor names its services matrix_synapse and friends); workload: node-local routes it to the established skip like bigbluebutton. Under swarm the stack deploy is a notified handler, so the registration wait started before any bridge existed and killed the play with the handler still pending; a flush before the wait deploys the stack first, and is a no-op in compose mode. Synapse resolves the OIDC issuer through two docker layers where both 127.0.0.1 and host-gateway point at the wrong loopback; the issuer now maps to the runner bridge's node gateway (local subnet .1), emitted only when OIDC is enabled so a no-auth setup keeps its previous arguments, proven by the full Playwright suite against the live cluster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:24 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6a72aeba33 refactor(skills): rename the iteration skills to the i8- prefix and add i8-cheatsheet
The six iteration skill wrappers move from infinito-iteration-* to i8-iteration-* (frontmatter, consistency lint prefix, alias and cheatsheet references follow). The new i8-cheatsheet skill routes to the operator cheatsheet and prints its prompt blocks verbatim, or just the block matching a named situation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:03:24 +02:00
kevinveenbirkenbachandClaude Opus 4.8 5936d3ba18 fix(csp): CSP token and injected asset agree on the aligned provider scheme
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 02:12:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0fb5eb8609 fix(logout): sweep only same-family domains of enabled entities
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 02:12:11 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6e20b94f14 chore: apply autoformat and settings churn from the quality run
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6050fadd21 docs(readme): regenerate openresty and registry READMEs
Follows the backup-free declarations and the registry swarm-mode removal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 dbb1a9bd38 chore(seaweedfs): drop the dollar-escape branch and pin the launcher invariants
The sidecar script contains no shell dollars anymore, so the swarm-only replace escape is dead; tests pin the exec-as-PID1 shape and the dollar-free invariant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 3585ad3be7 fix(seaweedfs): keep the embedded sidecar launcher free of shell dollars
The compose and swarm render paths launder dollars differently; the launched argv arrived with $pid collapsed to an empty string and $! doubled, and the sidecar crash-looped on a sh syntax error, so opentalk's wait for the embedded object store exhausted its retries. The bucket bootstrap now polls /status from a backgrounded subshell and exec makes the server PID 1, which needs no pid bookkeeping and receives docker stop's TERM directly; the poll loop dies with the container and readiness stays gated by the consumer's bounded wait.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 d51130bfbe chore(bkp): pin backup-docker-to-local 3.1.2
Picks up the postgres --empty pre-clean covering text search dictionaries and configurations, which unblocks taiga's restore drill. CI needs the 3.1.2 release on PyPI before this pin can deploy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 931b393c99 style(tests): wrap the closure literal in the extend-inventory test
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 17fa64e4e6 chore(claude): pause for confirmation before CHANGELOG or pyproject edits
Release metadata stays a manual operator step, mirroring the same ask-gate in backup-docker-to-local.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0b57337032 fix(proxy): reach node-local force_bridge apps via the host gateway under swarm
A force_bridge app (matrix's MDAD flavor) deploys as a node-local compose stack and publishes its local port on its host, while openresty runs as an overlay task whose 127.0.0.1 is its own loopback; the readiness probe died on 502. The proxy_pass lookup now resolves networks.local.force_bridge (trust-tagged for the 2.19 templar, hard-failing on an unrendered template instead of silently falling back to loopback) and keys the decision on the real DEPLOYMENT_MODE, since such apps rewrite the effective mode to compose via compose_mode_force. The upstream becomes host.docker.internal:<local_port> rendered as a literal directive, because the request-time resolver cannot see /etc/hosts entries, and the swarm openresty service maps host.docker.internal to the host gateway like prometheus already does. Non-force_bridge renders stay byte-identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0864a2e813 fix(akaunting): run the one-shot install through the image entrypoint
The setup passed --no-start as the container command, which the ca-trust wrapper exec'd as a binary (exit 127); the flag does not exist in the image's entrypoint at all. Invoking /usr/local/bin/akaunting.sh with no arguments is the real one-shot contract: with AKAUNTING_SETUP=true it runs artisan install and exits without starting Apache. The swarm wait gate also accepted Shutdown as success and let the crashed job pass without ever installing; the state probe now lives in install_job_state.sh and only Complete passes, while terminal states fail loudly with the task error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Fable 5 194671d90f feat(readme): uniform description schema and clearer role titles
Rewrite all 254 role descriptions to a uniform noun-phrase schema
(function-first, no leading verb, no trailing period, <=120 chars) and
enforce it via the extended description lint. Rename 12 role README H1
titles for clarity (e.g. Backup Container to Local -> Backup Docker
Volumes, CSS Service -> Corporate Design, NGINX Legal -> Imprint) and
regenerate their Cosmos and Quick Setup sections. Overview table
regenerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 029ce2bd74 fix(swarm-test): gate every backup leg on its inducer's include closure
extend_inventory appended the volume, secrets and nfs backup groups to the test inventory unconditionally, so the DR-drill ran on hosts whose roles declare no backup. For roles whose only volume is backup-disabled (registries, unbound, redis, openresty) the volume drill produced a payload-less generation and failed its non-empty assertion. Each leg now follows the closure of the role that induces it: volume and (transitively, via volume-2-local's secrets_backup consumer) secrets on the app closure, nfs on svc-storage-nfs-server's closure via its nfs_backup consumer. Enumeration confirms no consumer-active role loses its leg; a README documents the group derivation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 e7be00aa60 fix(gitlab): slow the CNG dependency-check loop to stop draining postgres
WAIT_FOR_TIMEOUT is an iteration count, not seconds, and CNG wait-for-deps leaks one postgres connection per iteration (establish_connection, never disconnected). At 1800 iterations of the 1s default the dedicated instance's non-superuser slots filled with idle gitlab connections before migrations could claim one, deadlocking the deploy. 60 iterations of 30s keeps the 30-minute budget at a thirtieth of the leak rate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Fable 5 3a9e9997f7 feat(readme): rename Lifecycle to Status, merge links into a More column
The overview table now shows Name, Status, Description, More, Integrated
with. The Homepage, Video and Install links collapse into one 'More'
column of emoji links (🌐 homepage, 🎬 video, 🛠️ install).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 88a64e469a fix(openresty): declare the proxy role permanently backup-free
The two named volumes carry no mounts and stay empty; every piece of proxy state (configs, certs, webroot) arrives through deploy-rendered read-only binds, so the volume-backup drill produced a payload-less generation and failed. Same pattern as the registry, unbound and redis roles: backup.disabled on the service, the container_backup consumer statically off, and the volumes.yml opt-out documenting the exemption.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 edb5692bfe fix(registry): drop the standalone swarm test mode for both registry roles
A registry serving the swarm its locally built images cannot be exercised as a swarm stack of its own (chicken-and-egg with the pulls it backs), so both roles disable the swarm mode and the svc.registry category default follows. This only removes the standalone swarm variants from test-deploy discovery; the constructor bootstrap still deploys both registries manager-pinned inside every swarm job via application_allowed, which does not read modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:47 +02:00
kevinveenbirkenbachandClaude Fable 5 103972b996 feat(ci): label priority and regular deploy jobs distinctly
Name the four deploy caller jobs so the Actions UI separates the two
lines: '⭐ Priority · single-node/swarm' and '🔁 Regular · single-node/swarm'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 01:11:47 +02:00
kevinveenbirkenbachandClaude Opus 4.8 bce2df6225 fix(tests): use valid application_ids in family-alignment fixtures; autoformat
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:44:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 7d6267c3a6 feat(rdr-domains): redirect the bare onion apex to the homepage on onion nodes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:44:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 f6174655b1 fix(hlth-webserver): expect the apex only when web-opt-rdr-domains serves it
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:44:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 e0867fb44d feat(lookup): family-align peer refs to the consuming app (cross-family substrate)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:44:11 +02:00
kevinveenbirkenbachandClaude Opus 4.8 88af0b883b fix(e2e): scale the Playwright global timeout for onion; hoist onion gate/proxy/timeout to vars constants
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:08:28 +02:00
kevinveenbirkenbachandClaude Opus 4.8 33631ad152 fix(fediwall): rewrite the SPA's hardcoded https API scheme for onion
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:08:28 +02:00
kevinveenbirkenbachandClaude Opus 4.8 deb3a35292 fix(bluesky): broker reaches the PDS over the internal network on onion nodes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:08:28 +02:00
kevinveenbirkenbachandClaude Opus 4.8 1b9d6cc862 fix(e2e): retry onion navigation on Firefox/WebKit transient network errors
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:08:28 +02:00
kevinveenbirkenbachandClaude Opus 4.8 1404455410 fix(zammad): OIDC discovery over the plaintext onion issuer
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:08:28 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6ebdb4bbf9 fix(svc-runner): retry apt on transient Ubuntu-mirror 404s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:08:27 +02:00
kevinveenbirkenbachandClaude Opus 4.8 d5cf6b0c69 fix(matrix): rename bridge vars to matrix_bridge_* for upstream MDAD
Upstream matrix-docker-ansible-deploy (pinned ref: master) renamed all
bridge variables to the matrix_bridge_<name>_ prefix; its config sanity
check now hard-fails on the old matrix_<name>_ names, killing the
mdad-bootstrap service so Synapse never starts and the loopback probe
exhausts its retries.

Rename all 10 emitted bridge _enabled vars to matrix_bridge_* (verified
1:1 against the upstream CHANGELOG rename map), drop the redundant
default(false) (services.matrix.plugins always defines every key), and
drop the dead matrix_mautrix_gitter_enabled (no such role upstream).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:08:27 +02:00
kevinveenbirkenbachandClaude Opus 4.8 33fa48bcad fix(proxy): strip upstream HSTS unconditionally (never leak over plaintext onion)
The Strict-Transport-Security strip in the shared per-location partial
was gated on 'lookup(tls, app, enabled)', so on plaintext transports
(onion, and pure-http clearnet) it never rendered and the upstream
app's own HSTS header (kix: max-age=31536000; openproject/Rails
force_ssl: same) leaked to the http client. That violates RFC 6797 and
the onion e2e TLS/HSTS specs caught it.

Make the strip unconditional. No behaviour change on TLS nodes: the
proxy still adds its own HSTS in the tls-gated ssl block of
nginx_ssl_header.j2. On http-only/onion vhosts nothing re-adds it (the
add is in the same tls-gated block), so the leaked upstream header is
simply removed — which is correct, since HSTS over plaintext is invalid.

Verified live: kix onion emits no HSTS header and its tls-hsts spec
passes; openproject rides the same shared partial.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 21:08:27 +02:00
kevinveenbirkenbach 4e46ec5af6 chore(claude): allow consent.youtube.com and framatube.org for WebFetch 2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Fable 5 a3a8bc92ac feat(readme): filter overview to tested envelope, place under Use it online
The roles overview now lists only tested-envelope roles (lifecycle
alpha/beta/rc/stable/maintenance) and renders below the renamed
'Use it online' section with an introductory sentence. Rename the
former 'Get Started' heading and drop the redundant subsection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0fc18a8a8b fix(diagnostics): stop the local-dump copy from recursing into its own snapshot
The snapshot directory lives under the dump base (both derive from INFINITO_RESCUE_DIAGNOSTICS_DIR), so copytree copied its growing destination into itself until ENAMETOOLONG; the suppressed error left a local-dumps/<stamp>/local-dumps chain that failed the artifact upload of otherwise green jobs (swapfile, wireguard-plain). The copy now ignores the snapshot's own subtree and every ancestor holding it, which also excludes stale sibling snapshots of the same app; a regression test drives real copytree over the production topology.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Fable 5 da598a2d67 feat(readme): roles overview table with homepage/video backfill
Add cli.build.readme.overview (make readme-index / make docs) rendering a
roles overview in the root README: Name, Lifecycle, Homepage, Video,
Description, Integrated with, Install. New info-media lint requires
homepage + video in every invokable role's meta/info.yml (opt out via
'# nocheck: info-media' in meta/main.yml); backfilled 147 roles with
researched, adversarially-verified homepages and official videos.

Retire the 'unsupported' lifecycle value: fold it into 'eol' as a valid
live end-of-life status (shipped but untested/unmaintained) across the
stage lists, symbol glossary, allow-list lint and docs. Retag confluence,
jira, minio, phpldapadmin to eol and magento to pre-alpha.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Opus 4.8 4900f55d20 fix(unbound,redis): declare the cache-state roles permanently backup-free
Both roles already mark their only volume backup.disabled (resolver state and redis cache are rebuildable), so the volume-backup drill produced a generation without payload and failed its non-empty assertion. The container_backup consumer is now statically off with the volumes.yml opt-out documenting the exemption, matching the registry roles; derive_includes proves the backup legs leave both closures.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Opus 4.8 86bb184bfa feat(diagnostics): capture pg_stat_activity for postgres containers in the rescue snapshot
The gitlab dedicated-postgres failure exhausted all 167 non-superuser slots, but the rescue artifact could not show which clients held them. The collector now dumps pg_stat_activity (per-backend rows, query truncated to 120 chars) and a usename/datname/state connection histogram for every container with postgres in its name, via psql over the container's peer-authenticated socket. Runs only in the failure path and capture() never raises, so a non-postgres name match just records the exec error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00