Gladex Agent Logs
Agent run logs & app logs · env: prod · LAN-only investor surface
Overview
| Run logs | 566 files, 19.4 MB |
| Latest run log | run-20260926-154050-164.log |
| Log directory | /data/agent-logs |
| App log directory | /opt/startup/prod/logs |
Run logs (newest first, last 50)
| File | Size | Modified (UTC) |
|---|---|---|
| run-20260926-154050-164.log | 108 KB | 2026-09-26 13:51:12 |
| run-20260926-153049-163.log | 153 B | 2026-09-26 13:30:50 |
| run-20260926-152049-162.log | 153 B | 2026-09-26 13:20:49 |
| run-20260926-151048-161.log | 153 B | 2026-09-26 13:10:49 |
| run-20260926-150047-160.log | 153 B | 2026-09-26 13:00:48 |
| run-20260926-145046-159.log | 153 B | 2026-09-26 12:50:47 |
| run-20260926-144046-158.log | 153 B | 2026-09-26 12:40:46 |
| run-20260926-143045-157.log | 153 B | 2026-09-26 12:30:46 |
| run-20260926-142044-156.log | 153 B | 2026-09-26 12:20:45 |
| run-20260926-141044-155.log | 153 B | 2026-09-26 12:10:44 |
| run-20260926-140043-154.log | 153 B | 2026-09-26 12:00:44 |
| run-20260926-135042-153.log | 190 B | 2026-09-26 11:50:43 |
| run-20260926-134042-152.log | 153 B | 2026-09-26 11:40:42 |
| run-20260926-133041-151.log | 153 B | 2026-09-26 11:30:42 |
| run-20260926-132040-150.log | 190 B | 2026-09-26 11:20:41 |
| run-20260926-131039-149.log | 153 B | 2026-09-26 11:10:40 |
| run-20260926-130039-148.log | 153 B | 2026-09-26 11:00:39 |
| run-20260926-125038-147.log | 190 B | 2026-09-26 10:50:39 |
| run-20260926-124037-146.log | 153 B | 2026-09-26 10:40:38 |
| run-20260926-123037-145.log | 153 B | 2026-09-26 10:30:37 |
| run-20260926-122036-144.log | 190 B | 2026-09-26 10:20:37 |
| run-20260926-121035-143.log | 190 B | 2026-09-26 10:10:36 |
| run-20260926-120035-142.log | 153 B | 2026-09-26 10:00:35 |
| run-20260926-115034-141.log | 153 B | 2026-09-26 09:50:34 |
| run-20260926-114033-140.log | 153 B | 2026-09-26 09:40:34 |
| run-20260926-113032-139.log | 153 B | 2026-09-26 09:30:33 |
| run-20260926-112032-138.log | 153 B | 2026-09-26 09:20:32 |
| run-20260926-111031-137.log | 153 B | 2026-09-26 09:10:32 |
| run-20260926-110026-136.log | 153 B | 2026-09-26 09:00:31 |
| run-20260926-105025-135.log | 153 B | 2026-09-26 08:50:26 |
| run-20260926-104024-134.log | 190 B | 2026-09-26 08:40:25 |
| run-20260926-103023-133.log | 153 B | 2026-09-26 08:30:24 |
| run-20260926-102023-132.log | 153 B | 2026-09-26 08:20:23 |
| run-20260926-101022-131.log | 190 B | 2026-09-26 08:10:23 |
| run-20260926-100021-130.log | 153 B | 2026-09-26 08:00:22 |
| run-20260926-095021-129.log | 153 B | 2026-09-26 07:50:21 |
| run-20260926-090029-128.log | 230 KB | 2026-09-26 07:40:21 |
| run-20260926-081623-127.log | 209 KB | 2026-09-26 06:50:29 |
| run-20260926-073109-126.log | 146 KB | 2026-09-26 06:06:23 |
| run-20260926-061035-125.log | 341 KB | 2026-09-26 05:21:09 |
| run-20260926-052113-124.log | 352 KB | 2026-09-26 04:00:35 |
| run-20260926-043030-123.log | 311 KB | 2026-09-26 03:11:13 |
| run-20260926-032802-122.log | 338 KB | 2026-09-26 02:20:30 |
| run-20260926-024118-121.log | 334 KB | 2026-09-26 01:18:02 |
| run-20260926-020038-120.log | 273 KB | 2026-09-26 00:31:18 |
| run-20260926-015037-119.log | 153 B | 2026-09-25 23:50:38 |
| run-20260926-014036-118.log | 153 B | 2026-09-25 23:40:37 |
| run-20260926-013035-117.log | 153 B | 2026-09-25 23:30:36 |
| run-20260926-012035-116.log | 153 B | 2026-09-25 23:20:35 |
| run-20260926-011034-115.log | 153 B | 2026-09-25 23:10:35 |
Tail — run-20260926-154050-164.log (last 200 lines)
[0m$ [0mcd /data/repo && grep -rn "33 checks\|32 checks\|34 checks\|checks, errors" tools/ tests/ *.md 2>/dev/null | head -20; echo "=== suite list pins ==="; grep -rn "test_system_status" tools/REGISTRY.md CHANGELOG.md agent-logs/PROGRESS.md | head -10
=== suite list pins ===
tools/REGISTRY.md:1280:- `bash tests/test_system_status_unread.sh` → **24 assertions**, hermetic and <1s
tools/REGISTRY.md:1301: case 11 + mutation M3 of `test_system_status_mx_soa.sh`.
tools/REGISTRY.md:1305:- `bash tests/test_system_status_mx_soa.sh` → **31 assertions**, hermetic and <1s
tools/REGISTRY.md:1317:- `bash tests/test_system_status_go_tests.sh` → **66 assertions, 6 mutations**,
tools/REGISTRY.md:1335: tests/test_system_status_go_tests.sh` → **15 passed / 39 failed / 1 skipped**.
tools/REGISTRY.md:1339:- `bash tests/test_system_status_go_compile.sh` → **82 assertions, 6 mutations**,
tools/REGISTRY.md:1357: 8894894f178db8ed97691f6b132855bd> bash tests/test_system_status_go_compile.sh`
tools/REGISTRY.md:1370:- `bash tests/test_system_status_promote_gates.sh` → **295 assertions, 39 mutations**,
tools/REGISTRY.md:1561: — `bash tests/test_system_status_promote_gates.sh`, logged at
tools/REGISTRY.md:1575: tests/test_system_status_promote_gates.sh`) → **234 passed / 9 failed / 0 skipped**:
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && grep -n "^## " tools/REGISTRY.md | sed -n '1,80p'
3:## domain-availability-check
60:## budget-show
110:## dns-verify
171:## healthcheck
217:## promote-dev-to-prod
693:## ip-drift-check
758:## pdns-api.py
817:## ip-drift-cron
926:## verify-landing
968:## system-status
1704:## version-check
1742:## tls-check
1780:## smtp-relay-probe
1820:## source-sync-check
1868:## queue-source-check
1963:## test_identity_wrapper.sh
1990:## test_app_contrast_meta.php
2015:## repo-lint
2071:## regression-run
2129:## test_regression_run.sh
2158:## test_queue_source.sh
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && sed -n '968,1060p' tools/REGISTRY.md
## system-status
**Purpose**: Quick overview of the entire Gladex system health — services, endpoints, DNS (incl. MX/SOA), messages, git, tests.
**Location**: `/data/repo/tools/system-status` (also via the `/data/tools` symlink —
`SCRIPT_DIR` resolves the script path with `realpath`, so through the link the repo
root is `/data/repo`, not the link's parent)
**Usage**:
```
system-status [--format human|json] [--help]
```
**Options**:
- `--format human|json` - Output format (default: human)
- `--help` - Show help message
**Exit codes**:
- `0` - All systems healthy
- `1` - One or more systems unhealthy
- `2` - Invalid arguments
**Checks performed (30 total)**:
- systemd services: investor-app-dev, investor-app-prod, git-daemon, apache2, certbot.timer, watchdog
- HTTP endpoints: /healthz (dev+prod), /download/gladex, /api/health, /api/uptime, /api/endpoints, /api/changelog, /api/stats
- DNS records: gladex.de, dev/git/info/stats/team/log subdomains → 77.90.15.49
- MX record: `MX:gladex.de` must be `10 gladex.de.` on **BOTH** 1.1.1.1 and 8.8.8.8
(propagation check; standing investor rule 2026-09-23 — adopted MX must stay
verified). Any other/missing answer on either resolver = **error, exit 1** —
a wrong MX on a public resolver is a mail outage, not a warning.
- SOA serial: `SOA:gladex.de` — serial must be numeric, >0 and **identical** on
1.1.1.1/8.8.8.8 (split = **warning** "propagation lag", transient by definition;
garbage/missing serial = **error**). The known `MNAME` placeholder
(`a.misconfigured.dns.server.invalid.`, provider-panel-only fix, open
NEEDS-INVESTOR) is surfaced as a **warning** in the detail and clears itself
once the panel value changes.
- TLS cert expiry: openssl check, warn <30d, error <7d
- Investor messages: unread `investor_to_agent` rows counted across **BOTH** DBs — detail `N unread dev=X prod=Y`
- Git tree: clean/dirty
- Next-candidate queue: `queue-source` carries `queue-source-check --format json
--repo`'s verdict — CHANGELOG's newest `### Queue` section must be a POINTER at
`agent-logs/PROGRESS.md` (the one authoritative list) and the 111 historical
item lines must be unchanged. child `0` → **ok**, `1` → **error + `ERRORS++`**
(a second list, a dropped pointer or an empty authoritative list turns the
dashboard red), `3` → **warning `cannot verify`** (no `CHANGELOG.md`, no
`### Queue` section, no `agent-logs/PROGRESS.md`) — never ok, never an error on
a tree that was not checked. `detail` is the child's own, already sanitised of
`"` and `\` so the hand-built row stays valid JSON.
- Go tests: verdict from the **exit code** of `go test ./...` over the whole
module (worktree) — see the verdict table below
- Go compile: `repo-lint --format json --sha HEAD`'s `go_compile` verdict
(the COMMIT) — see the verdict table below
- Promote gates: `promote-dev-to-prod --dry-run --force --format json` +
`GLADEX_GATE_PROBE=1` — "can we ship right now?" in one dashboard read —
see the verdict table below
**Unread-count contract (both DBs, since 2026-09-24)**: the investor primarily reads
the **prod** thread (public `https://gladex.de` → Apache `:443` → prod `:8001`), while
dev `:8000` carries a separate thread. The old read touched only
`/opt/startup/dev/data/messages.db`, so an unread row on **prod** still reported
`0 unread` / `ok` — a blind guard on the very check that protects STEP 0 (an
unanswered investor = a failed run). Counts are summed; an unreadable/missing DB
reports `?` and forces `warning`, so it can **never masquerade as `0`**.
`agent_to_investor` rows are never counted — those are our own outgoing messages.
**Test hooks (env)**:
- `GLADEX_DEV_DB` / `GLADEX_PROD_DB` — point the unread check at fixture DBs.
Defaults are the live `/opt/startup/{dev,prod}/data/messages.db`. Same pattern as
`IDENTITY_REPO`/`IDENTITY_LOG` on `identity-run.sh`.
- `GLADEX_REPO_DIR` — repo the git/Go checks report on (default: parent dir of the
script). Lets hermetic suites run **mutated copies** from a sandbox path; without
it a copy under `/tmp` computes a `REPO_DIR` with no `.git` and dies at the git
check under `set -e` (silent empty output → vacuous mutation checks).
- `GLADEX_GO_BIN` (default `go`) / `GLADEX_GO_TIMEOUT` (default `120`) /
`GLADEX_GO_GOPATH` (default `/tmp/gopath`) / `GLADEX_GO_GOCACHE` (default
`/tmp/gocache`) — the go-tests check only. `GOMODCACHE` is
`$GLADEX_GO_GOPATH/pkg/mod`. All four are documented in `--help`.
- `GLADEX_REPO_LINT_BIN` (default: the sibling `repo-lint`, resolved from this
script's own directory) / `GLADEX_GO_LINT_TIMEOUT` (default `120`) — the
go-compile check only. The first is what keeps a hermetic suite off the real
tree: every `system-status` run lints a real commit, so a suite that does not
test this row stubs the child (all three older suites do).
- `GLADEX_PROMOTE_BIN` (default: `<reported repo>/tools/promote-dev-to-prod`,
i.e. resolved through `GLADEX_REPO_DIR`, not through the script's own dir) /
`GLADEX_PROMOTE_TIMEOUT` (default `120`) — the promote-gates check only. The
default is what keeps a hermetic suite off the real tool: a suite that does
not test this row points it at a non-existent path and gets
`cannot verify` in well under a second (all four older suites do).
- `GLADEX_QUEUE_SOURCE_BIN` (default: the sibling `queue-source-check`, resolved
from this script's own directory) / `GLADEX_QUEUE_SOURCE_TIMEOUT` (default
`20`) — the queue-source check only. Same shape as the two above: a suite that
does not test this row leaves it on its default, and because the child answers
`cannot verify` (exit 3, `warning`) for any sandbox repo without a `### Queue`
[0m$ [0mcd /data/repo && grep -n -i "tls\|checks:\|33 \|32 checks" tools/REGISTRY.md | awk -F: '$1>968 && $1<1710' | head -40
1004:- TLS cert expiry: openssl check, warn <30d, error <7d
1548: M33 the hand-off dropped (`SS_SHIP_OUT=""` → our half of the comparison is blind)
1653:28 checks: the COMMIT is now a row too — `go-compile` carries `repo-lint`'s
1656:30 checks: the next-candidate queue is a row too — `queue-source` carries
1661:29 checks: the SHIP decision is a row too — `promote-gates` carries
> build · mimo-v2.6-flash-free
[0m$ [0mcd /data/repo && grep -rn "tls" tests/test_system_status_cloud.sh | head; echo "--- how cloud suite is structured (head) ---"; sed -n '1,60p' tests/test_system_status_cloud.sh
--- how cloud suite is structured (head) ---
#!/usr/bin/env bash
# Regression test for the `cloud` row in tools/system-status (Nextcloud + Immich).
#
# Motivated by queue item (10): system-status had 33 rows and not one of them knew
# either cloud stack existed, so Nextcloud (:8080) and Immich (:2283) — the two
# newest production surfaces — could BOTH be dead while the dashboard still printed
# ALL SYSTEMS HEALTHY. The row closes that with three independent witnesses (HTTP
# status.php, HTTP /api/server/ping, docker container state + RestartCount) and it
# is worth pinning every branch, because two of them are judgements rather than
# measurements:
# * a 200 whose BODY cannot be read must be `warning`, never `ok` (an unreadable
# body is not a healthy service) and never `error` (it is not a measured
# failure either) — the row must be willing to say it did not measure;
# * a docker binary that will not answer is `cannot verify`, not "the stacks are
# down" — a verdict about a host we could not ask is not a verdict.
#
# Hermetic by construction:
# * systemctl / curl / dig / openssl / go / repo-lint are stubbed on PATH — the
# curl stub is scenario-driven (it answers the cloud probes with a body AND a
# code, and the plain endpoint probes with a bare code), so no network is
# touched and the ~20s `go test` is skipped;
# * GLADEX_CLOUD_DOCKER_BIN points the container witness at a scenario stub, so
# this suite never reads (and can never be wrong about) the host's live
# containers;
# * GLADEX_DEV_DB / GLADEX_PROD_DB point at absent fixture DBs, so the LIVE
# message DBs (which guard STEP 0) are never read by this suite;
# * SYSTEM_STATUS_BIN points the mutation checks at a mutated copy, so the real
# tool is never edited by this test.
#
# Run: bash tests/test_system_status_cloud.sh
# Exit codes: 0 = all pass, 1 = at least one failure.
set -u
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
REAL_TOOL="${SYSTEM_STATUS_BIN:-$REPO/tools/system-status}"
TOOL="$REAL_TOOL"
PASS=0
FAIL=0
ok() { PASS=$((PASS+1)); echo " ok - $1"; }
bad() { FAIL=$((FAIL+1)); echo " FAIL - $1"; }
[ -f "$TOOL" ] || { echo "SKIP: tool not found: $TOOL"; exit 0; }
SANDBOX="$(mktemp -d /tmp/scd-test.XXXXXX)" || exit 1
trap 'rm -rf "$SANDBOX"' EXIT INT TERM
# ---------------------------------------------------------------- stubs -----
STUB="$SANDBOX/bin"
mkdir -p "$STUB"
printf '#!/bin/sh\necho active\n' > "$STUB/systemctl"
printf '#!/bin/sh\necho "notAfter=Dec 22 12:00:00 2026 GMT"\n' > "$STUB/openssl"
printf '#!/bin/sh\necho "ok github.com/gladex/gladex/cmd/gladex/commands 0.1s"\n' > "$STUB/go"
# Scenario curl: the tool asks the cloud probes for a BODY plus a code
# (`-w $'\n%{http_code}'`, no -o) and the plain endpoint probes for a bare code
# (`-o /dev/null -w %{http_code}`). Answering both from one stub is what lets a
# single PATH entry drive every HTTP witness in the tool.
cat > "$STUB/curl" <<'STUBCURL'
#!/bin/sh
Select another run log from the list above. Only files matching run-YYYYMMDD-HHMMSS-N.log are readable.
App log tail — prod-8001.log (last 60 lines)
[Sat Sep 26 15:08:45 2026] 127.0.0.1:47802 Accepted [Sat Sep 26 15:08:45 2026] 127.0.0.1:47802 Closing [Sat Sep 26 15:08:45 2026] 127.0.0.1:47812 Accepted [Sat Sep 26 15:08:45 2026] 127.0.0.1:47812 Closing [Sat Sep 26 15:10:54 2026] 127.0.0.1:34982 Accepted [Sat Sep 26 15:10:54 2026] 127.0.0.1:34982 Closing [Sat Sep 26 15:11:16 2026] 127.0.0.1:56780 Accepted [Sat Sep 26 15:11:16 2026] 127.0.0.1:56780 Closing [Sat Sep 26 15:25:07 2026] 127.0.0.1:44666 Accepted [Sat Sep 26 15:25:07 2026] 127.0.0.1:44666 Closing [Sat Sep 26 15:26:11 2026] 127.0.0.1:32954 Accepted [Sat Sep 26 15:26:11 2026] 127.0.0.1:32954 Closing [Sat Sep 26 15:26:11 2026] 127.0.0.1:32970 Accepted [Sat Sep 26 15:26:11 2026] 127.0.0.1:32970 Closing [Sat Sep 26 15:26:16 2026] 127.0.0.1:38468 Accepted [Sat Sep 26 15:26:16 2026] 127.0.0.1:38468 Closing [Sat Sep 26 15:38:46 2026] 127.0.0.1:39898 Accepted [Sat Sep 26 15:38:46 2026] 127.0.0.1:39898 Closing [Sat Sep 26 15:51:12 2026] 127.0.0.1:45468 Accepted [Sat Sep 26 15:51:12 2026] 127.0.0.1:45468 Closing [Sat Sep 26 15:51:12 2026] 127.0.0.1:45478 Accepted [Sat Sep 26 15:51:12 2026] 127.0.0.1:45478 Closing [Sat Sep 26 15:51:12 2026] 127.0.0.1:45492 Accepted [Sat Sep 26 15:51:12 2026] 127.0.0.1:45492 Closing [Sat Sep 26 15:51:12 2026] 127.0.0.1:45508 Accepted [Sat Sep 26 15:51:12 2026] 127.0.0.1:45508 Closing [Sat Sep 26 15:51:12 2026] 127.0.0.1:45524 Accepted [Sat Sep 26 15:51:12 2026] 127.0.0.1:45524 Closing [Sat Sep 26 15:51:12 2026] 127.0.0.1:45532 Accepted [Sat Sep 26 15:51:12 2026] 127.0.0.1:45532 Closing [Sat Sep 26 15:51:12 2026] 127.0.0.1:45548 Accepted [Sat Sep 26 15:51:13 2026] 127.0.0.1:45548 Closing [Sat Sep 26 15:51:13 2026] 127.0.0.1:45550 Accepted [Sat Sep 26 15:51:13 2026] 127.0.0.1:45550 Closing [Sat Sep 26 15:51:13 2026] 127.0.0.1:45556 Accepted [Sat Sep 26 15:51:13 2026] 127.0.0.1:45556 Closing [Sat Sep 26 15:51:13 2026] 127.0.0.1:45568 Accepted [Sat Sep 26 15:51:13 2026] 127.0.0.1:45568 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48584 Accepted [Sat Sep 26 15:51:46 2026] 127.0.0.1:48584 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48594 Accepted [Sat Sep 26 15:51:46 2026] 127.0.0.1:48594 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48604 Accepted [Sat Sep 26 15:51:46 2026] 127.0.0.1:48604 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48608 Accepted [Sat Sep 26 15:51:46 2026] 127.0.0.1:48608 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48612 Accepted [Sat Sep 26 15:51:46 2026] 127.0.0.1:48612 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48624 Accepted [Sat Sep 26 15:51:46 2026] 127.0.0.1:48624 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48628 Accepted [Sat Sep 26 15:51:46 2026] 127.0.0.1:48628 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48640 Accepted [Sat Sep 26 15:51:46 2026] 127.0.0.1:48640 Closing [Sat Sep 26 15:51:46 2026] 127.0.0.1:48644 Accepted [Sat Sep 26 15:51:47 2026] 127.0.0.1:48644 Closing [Sat Sep 26 15:51:47 2026] 127.0.0.1:48646 Accepted [Sat Sep 26 15:51:47 2026] 127.0.0.1:48646 Closing [Sat Sep 26 15:51:53 2026] 127.0.0.1:48660 Accepted
Generated 2026-09-26 13:51:53 UTC · Gladex.de