From fb1a0b0b8ef62d9ec9af65d3feeece5e1019f44d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Fri, 17 Jul 2026 13:30:23 +0200 Subject: [PATCH 1/7] landing: kGOA units, full money stats, rootless resource display Public bank/exchange/merchant landing stats and performance UI only. Secret goa-ui overlay stays on local/merchant-secret-ui (never push). --- configs/bank-landing/goa-amount.js | 152 +++++++++---- configs/bank-landing/index.html | 211 +++++++++++++----- configs/exchange-landing/goa-amount.js | 152 +++++++++---- configs/exchange-landing/index.html | 142 +++++++++--- configs/merchant-landing/goa-amount.js | 152 +++++++++---- configs/merchant-landing/index.html | 103 ++++++--- configs/shared/goa-amount.js | 152 +++++++++---- .../collect_container_resources.sh | 133 ++++++++++- scripts/taler-landing/goa_amounts.py | 126 ++++++++--- scripts/taler-landing/merge_resources.py | 40 +++- scripts/taler-landing/test-landing-stats.sh | 14 +- .../taler-merchant/landing-stats-merchant.sh | 2 +- 12 files changed, 1046 insertions(+), 333 deletions(-) diff --git a/configs/bank-landing/goa-amount.js b/configs/bank-landing/goa-amount.js index 67c3859..cfaaad3 100644 --- a/configs/bank-landing/goa-amount.js +++ b/configs/bank-landing/goa-amount.js @@ -1,29 +1,63 @@ -/* Compact GOA / CUR:amount display using currency alt_unit_names. - * Large values → "1.23 Mega-GOA" (title = full GOA:n) so landing tiles fit. +/* Compact GOA / CUR:amount display using SI-style alt units (kGOA, MGOA, …). + * Large values → "1.23 MGOA" (title = full GOA:n) so landing tiles fit. */ (function (global) { "use strict"; var DEFAULT_ALT = { - "24": "Yotta-GOA", - "21": "Zetta-GOA", - "18": "Exa-GOA", - "15": "Peta-GOA", - "12": "Tera-GOA", - "9": "Giga-GOA", - "6": "Mega-GOA", - "3": "Kilo-GOA", + "24": "YGOA", + "21": "ZGOA", + "18": "EGOA", + "15": "PGOA", + "12": "TGOA", + "9": "GGOA", + "6": "MGOA", + "3": "kGOA", "0": "GOA", - "-1": "Deci-GOA", - "-2": "Centi-GOA", - "-3": "Milli-GOA", - "-6": "Micro-GOA", - "-7": "Deci-Micro-GOA", - "-8": "Atomic-GOA" + "-1": "dGOA", + "-2": "cGOA", + "-3": "mGOA", + "-6": "µGOA", + "-7": "dµGOA", + "-8": "aGOA" + }; + + var LONG_TO_COMPACT = { + "yotta-goa": "YGOA", + "zetta-goa": "ZGOA", + "exa-goa": "EGOA", + "peta-goa": "PGOA", + "tera-goa": "TGOA", + "giga-goa": "GGOA", + "mega-goa": "MGOA", + "kilo-goa": "kGOA", + "goa": "GOA", + "deci-goa": "dGOA", + "centi-goa": "cGOA", + "milli-goa": "mGOA", + "micro-goa": "µGOA", + "deci-micro-goa": "dµGOA", + "atomic-goa": "aGOA" }; var THRESHOLD = 1000; + function compactAlt(altMap) { + var out = {}; + var src = altMap || DEFAULT_ALT; + Object.keys(DEFAULT_ALT).forEach(function (k) { + out[k] = DEFAULT_ALT[k]; + }); + Object.keys(src).forEach(function (k) { + var name = String(src[k] || "").trim(); + var low = name.toLowerCase().replace(/\s+/g, ""); + if (LONG_TO_COMPACT[low]) out[k] = LONG_TO_COMPACT[low]; + else if (DEFAULT_ALT[k] && /goa/i.test(name)) out[k] = DEFAULT_ALT[k]; + else out[k] = name || DEFAULT_ALT[k] || name; + }); + return out; + } + function parseAmount(s) { if (s == null || s === "") return { cur: "GOA", val: 0 }; if (typeof s === "number") return { cur: "GOA", val: s }; @@ -51,7 +85,7 @@ } /** - * @param {string|number} amount + * @param {string|number|object} amount * @param {object} [altMap] * @returns {{ display: string, title: string, raw: string, usedAlt: boolean }} */ @@ -59,24 +93,17 @@ if (amount == null || amount === "") { return { display: "—", title: "", raw: "", usedAlt: false }; } - // Prefer server-provided alt if caller passes object {amount, amount_alt} + // Prefer re-format from canonical amount (keeps kGOA even if server sent Kilo-GOA) if (typeof amount === "object" && amount) { - if (amount.amount_alt) { - var rawO = amount.amount || amount.amount_full || String(amount.amount_alt); - return { - display: String(amount.amount_alt), - title: amount.amount_full || rawO, - raw: String(rawO), - usedAlt: true - }; + if (amount.amount) { + return format(amount.amount, altMap); } - amount = amount.amount || amount.amount_full || ""; + amount = amount.amount_full || amount.amount_alt || ""; } - var alt = altMap || global.__GOA_ALT_UNITS || DEFAULT_ALT; + var alt = compactAlt(altMap || global.__GOA_ALT_UNITS || DEFAULT_ALT); var p = parseAmount(amount); var raw = baseStr(p.cur, p.val); - // Foreign currencies must not pick up Kilo-GOA / Mega-GOA labels var baseName = (alt && alt["0"]) || p.cur; var curU = String(p.cur || "").toUpperCase(); var baseU = String(baseName || "").toUpperCase(); @@ -95,7 +122,9 @@ var n = parseInt(k, 10); if (!isNaN(n)) scales.push({ sc: n, name: String(alt[k]) }); }); - scales.sort(function (a, b) { return b.sc - a.sc; }); + scales.sort(function (a, b) { + return b.sc - a.sc; + }); var abs = Math.abs(p.val); var chosen = null; @@ -136,33 +165,80 @@ setText(document.getElementById(id), amount, altMap); } - /** Prefer amount_alt from stats row, else format amount. */ + /** Prefer formatting from amount field; fall back to amount_alt string. */ function pick(rowOrAmount, altMap) { if (rowOrAmount && typeof rowOrAmount === "object") { + var a = + rowOrAmount.amount || + rowOrAmount.total_amount || + rowOrAmount.amount_paid_sum || + rowOrAmount.amount_sum; + if (a) return format(a, altMap); if (rowOrAmount.amount_alt) { - return format({ - amount: rowOrAmount.amount, - amount_alt: rowOrAmount.amount_alt, - amount_full: rowOrAmount.amount_full - }, altMap); + return { + display: String(rowOrAmount.amount_alt), + title: String(rowOrAmount.amount_full || rowOrAmount.amount_alt), + raw: String(rowOrAmount.amount_full || rowOrAmount.amount_alt), + usedAlt: true + }; } - return format(rowOrAmount.amount || rowOrAmount.total_amount, altMap); + return format("", altMap); } return format(rowOrAmount, altMap); } function rememberAlt(stats) { if (stats && stats.alt_unit_names && typeof stats.alt_unit_names === "object") { - global.__GOA_ALT_UNITS = stats.alt_unit_names; + global.__GOA_ALT_UNITS = compactAlt(stats.alt_unit_names); } } + /** Small legend HTML (positive scales). */ + function legendHtml(stats) { + var alt = compactAlt((stats && stats.alt_unit_names) || global.__GOA_ALT_UNITS || DEFAULT_ALT); + var rows = []; + Object.keys(alt) + .map(function (k) { + return parseInt(k, 10); + }) + .filter(function (n) { + return !isNaN(n) && n > 0; + }) + .sort(function (a, b) { + return a - b; + }) + .forEach(function (sc) { + rows.push( + "10" + + sc + + "" + + alt[String(sc)] + + "" + ); + }); + if (!rows.length) return ""; + return ( + '' + + rows.join("") + + "
×basename
" + ); + } + + function fillLegend(elOrId, stats) { + var el = typeof elOrId === "string" ? document.getElementById(elOrId) : elOrId; + if (!el) return; + el.innerHTML = legendHtml(stats); + } + global.GoaAmount = { format: format, setText: setText, setById: setById, pick: pick, rememberAlt: rememberAlt, + compactAlt: compactAlt, + legendHtml: legendHtml, + fillLegend: fillLegend, DEFAULT_ALT: DEFAULT_ALT, THRESHOLD: THRESHOLD }; diff --git a/configs/bank-landing/index.html b/configs/bank-landing/index.html index bd47143..b9ab241 100644 --- a/configs/bank-landing/index.html +++ b/configs/bank-landing/index.html @@ -995,6 +995,27 @@ color: #f0a090; text-align: center; } + .unit-legend { + margin: 0.65rem auto 0; + border-collapse: collapse; + font-size: 0.68rem; + color: var(--muted); + width: auto; + max-width: 100%; + } + .unit-legend th, .unit-legend td { + padding: 0.12rem 0.45rem; + border-bottom: 1px solid rgba(201, 184, 160, 0.12); + text-align: left; + } + .unit-legend th { font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; font-size: 0.62rem; } + .unit-legend strong { color: #5eead4; font-weight: 750; } + .unit-legend-note { + margin: 0.35rem 0 0; + font-size: 0.68rem; + color: var(--muted); + text-align: center; + } footer { margin-top: 2rem; color: var(--muted); @@ -1392,39 +1413,67 @@ tw run-until-done && tw balance @@ -1448,11 +1497,19 @@ tw run-until-done && tw balance
- Loadavg + CPU (container) + +
+
+ Loadavg (host)
- Container + PIDs + +
+
+ Container RSS
@@ -1469,10 +1526,10 @@ tw run-until-done && tw balance
-

Top processes (RSS)

+

Top processes (RSS inside container)

-

Memory from /proc + cgroup inside podman container.

+

RSS from /proc inside container (no memory cgroup in rootless podman). CPU from podman stats.

+ @@ -1545,6 +1555,13 @@ tw run-until-done && tw balance Privacy: processing under Swiss FADP (revDSG). What is retained is listed on /privacy.

+ +

+ Landing v42 + · content + · aa3c23b +

+ diff --git a/configs/exchange-landing/index.html b/configs/exchange-landing/index.html index cf671ad..a79a3e9 100644 --- a/configs/exchange-landing/index.html +++ b/configs/exchange-landing/index.html @@ -274,7 +274,17 @@ footer { margin-top: 1.75rem; text-align: center; color: var(--muted); font-size: 0.85rem; } footer a { color: #e8c878; } code { font-family: ui-monospace, Menlo, monospace; font-size: 0.86em; background: rgba(0,0,0,0.35); padding: 0.1em 0.35em; border-radius: 4px; color: #f0d090; } - + .landing-rev { + margin: 0.75rem 0 0; + font-size: 0.72rem; + color: var(--muted, #9a8fb0); + line-height: 1.45; + text-align: center; + } + .landing-rev a { color: inherit; text-decoration: underline; text-underline-offset: 2px; opacity: 0.95; } + .landing-rev strong { font-weight: 750; } + +

@@ -479,6 +489,13 @@ sudo apt-get install -y taler-wallet-cli Privacy: processing under Swiss FADP (revDSG). What is retained is listed on /privacy.

+ +

+ Landing v42 + · content + · aa3c23b +

+ diff --git a/configs/merchant-landing/index.html b/configs/merchant-landing/index.html index 1a14014..ae66805 100644 --- a/configs/merchant-landing/index.html +++ b/configs/merchant-landing/index.html @@ -517,7 +517,17 @@ .sym-gold path[data-ring], .sym-gold circle[data-ring] { fill: none; stroke: #f0c86a; } .sym-blue path, .sym-blue circle { fill: #3ecfbf; stroke: #3ecfbf; } .sym-blue path[data-ring], .sym-blue circle[data-ring] { fill: none; stroke: #3ecfbf; } - + .landing-rev { + margin: 0.75rem 0 0; + font-size: 0.72rem; + color: var(--muted, #9a8fb0); + line-height: 1.45; + text-align: center; + } + .landing-rev a { color: inherit; text-decoration: underline; text-underline-offset: 2px; opacity: 0.95; } + .landing-rev strong { font-weight: 750; } + +

@@ -822,6 +832,13 @@ sudo apt-get install -y taler-wallet-cli Privacy: processing under Swiss FADP (revDSG). What is retained is listed on /privacy.

+ +

+ Landing v42 + · content + · aa3c23b +

+ diff --git a/configs/shared/landing-version.json b/configs/shared/landing-version.json new file mode 100644 index 0000000..ee06829 --- /dev/null +++ b/configs/shared/landing-version.json @@ -0,0 +1,9 @@ +{ + "version": 42, + "updated_iso": "2026-07-17T13:31:56+02:00", + "updated_human": "2026-07-17 13:31 CEST", + "commit": "aa3c23be49236ba5c20cd095bb02790f84aeb1e5", + "commit_short": "aa3c23b", + "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/aa3c23be49236ba5c20cd095bb02790f84aeb1e5", + "note": "Bump with scripts/taler-landing/stamp-landing-version.sh --bump after each landing content change." +} diff --git a/scripts/taler-landing/stamp-landing-version.sh b/scripts/taler-landing/stamp-landing-version.sh new file mode 100755 index 0000000..570636c --- /dev/null +++ b/scripts/taler-landing/stamp-landing-version.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +# Stamp landing footers with version + last content change + linkified commit. +# +# Usage (from koopa-admin-log root): +# ./scripts/taler-landing/stamp-landing-version.sh # re-stamp with HEAD + current version +# ./scripts/taler-landing/stamp-landing-version.sh --bump # version += 1, then stamp HEAD +# ./scripts/taler-landing/stamp-landing-version.sh --set 42 # force version +# +# Typical flow after editing landing HTML/CSS/JS: +# 1) edit landings +# 2) ./scripts/taler-landing/stamp-landing-version.sh --bump +# 3) git add configs/ && git commit +# 4) ./scripts/taler-landing/stamp-landing-version.sh && git add configs/ && git commit --amend --no-edit +# +# Or one-shot (commits for you if GIT_STAMP_COMMIT=1). +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +VER_FILE="$ROOT/configs/shared/landing-version.json" +REPO_WEB="${LANDING_REPO_WEB:-https://git.hacktivism.ch/hernani/koopa-admin-log}" +LANDINGS=( + "$ROOT/configs/bank-landing/index.html" + "$ROOT/configs/exchange-landing/index.html" + "$ROOT/configs/merchant-landing/index.html" +) + +export TZ="${TZ:-Europe/Zurich}" + +bump=0 +set_ver="" +while [ $# -gt 0 ]; do + case "$1" in + --bump) bump=1; shift ;; + --set) set_ver="${2:-}"; shift 2 ;; + -h|--help) + sed -n '2,20p' "$0" + exit 0 + ;; + *) echo "unknown arg: $1" >&2; exit 2 ;; + esac +done + +if [ ! -f "$VER_FILE" ]; then + echo '{"version":42,"updated_iso":"","updated_human":"","commit":"","commit_short":""}' >"$VER_FILE" +fi + +version=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("version",42))' "$VER_FILE") +if [ -n "$set_ver" ]; then + version="$set_ver" +elif [ "$bump" = 1 ]; then + version=$((version + 1)) +fi + +# Prefer staged/index commit identity after commit; allow OVERRIDE_COMMIT +if [ -n "${OVERRIDE_COMMIT:-}" ]; then + full="$OVERRIDE_COMMIT" +else + full=$(git -C "$ROOT" rev-parse HEAD 2>/dev/null || echo "unknown") +fi +short=$(git -C "$ROOT" rev-parse --short=7 "$full" 2>/dev/null || echo "${full:0:7}") +iso=$(date +%Y-%m-%dT%H:%M:%S%z | sed -E 's/([+-][0-9]{2})([0-9]{2})$/\1:\2/') +human=$(date +"%Y-%m-%d %H:%M %Z") +url="${REPO_WEB}/commit/${full}" + +python3 - "$VER_FILE" "$version" "$iso" "$human" "$full" "$short" "$url" <<'PY' +import json, sys +path, version, iso, human, full, short, url = sys.argv[1:] +data = { + "version": int(version), + "updated_iso": iso, + "updated_human": human, + "commit": full, + "commit_short": short, + "repo_commit_url": url, + "note": "Bump with scripts/taler-landing/stamp-landing-version.sh --bump after each landing content change.", +} +open(path, "w", encoding="utf-8").write(json.dumps(data, indent=2, ensure_ascii=False) + "\n") +print(f"version={version} commit={short} at={human}") +PY + +# HTML block injected into each footer (idempotent via markers) +block=$(cat < +

+ Landing v${version} + · content + · ${short} +

+ +EOF +) + +css_snip=' .landing-rev { + margin: 0.75rem 0 0; + font-size: 0.72rem; + color: var(--muted, #9a8fb0); + line-height: 1.45; + text-align: center; + } + .landing-rev a { color: inherit; text-decoration: underline; text-underline-offset: 2px; opacity: 0.95; } + .landing-rev strong { font-weight: 750; } +' + +for f in "${LANDINGS[@]}"; do + [ -f "$f" ] || { echo "missing $f" >&2; exit 1; } + # ensure CSS once + if ! grep -q '\.landing-rev' "$f"; then + # insert before of first style block + python3 - "$f" "$css_snip" <<'PY' +import sys +path, snip = sys.argv[1], sys.argv[2] +t = open(path, encoding="utf-8").read() +if ".landing-rev" in t: + sys.exit(0) +idx = t.find("") +if idx < 0: + raise SystemExit(f"no in {path}") +t = t[:idx] + snip + "\n" + t[idx:] +open(path, "w", encoding="utf-8").write(t) +print(f"css → {path}") +PY + fi + # replace or insert rev block before + python3 - "$f" "$block" <<'PY' +import sys, re +path, block = sys.argv[1], sys.argv[2] +t = open(path, encoding="utf-8").read() +block = block.rstrip() + "\n" +pat = re.compile(r"[ \t]*.*?\n?", re.S) +if pat.search(t): + t = pat.sub(block, t, count=1) +else: + # before closing footer + t2, n = re.subn(r"(\n)([ \t]*)", r"\1" + block + r"\2", t, count=1) + if n != 1: + raise SystemExit(f"could not insert landing-rev in {path}") + t = t2 +open(path, "w", encoding="utf-8").write(t) +print(f"stamp → {path}") +PY +done + +echo "OK landing v${version} → ${short} (${human})" From d5eba029453b9055267ddabb17a437f4cacefdb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Fri, 17 Jul 2026 13:31:57 +0200 Subject: [PATCH 3/7] landing: point v42 footer at content commit 1c9978e --- configs/bank-landing/index.html | 6 +++--- configs/exchange-landing/index.html | 6 +++--- configs/merchant-landing/index.html | 6 +++--- configs/shared/landing-version.json | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/configs/bank-landing/index.html b/configs/bank-landing/index.html index 8efca46..52c3955 100644 --- a/configs/bank-landing/index.html +++ b/configs/bank-landing/index.html @@ -1556,10 +1556,10 @@ tw run-until-done && tw balance /privacy.

-

+

Landing v42 - · content - · aa3c23b + · content + · b01058c

diff --git a/configs/exchange-landing/index.html b/configs/exchange-landing/index.html index a79a3e9..44991b0 100644 --- a/configs/exchange-landing/index.html +++ b/configs/exchange-landing/index.html @@ -490,10 +490,10 @@ sudo apt-get install -y taler-wallet-cli /privacy.

-

+

Landing v42 - · content - · aa3c23b + · content + · b01058c

diff --git a/configs/merchant-landing/index.html b/configs/merchant-landing/index.html index ae66805..6797c55 100644 --- a/configs/merchant-landing/index.html +++ b/configs/merchant-landing/index.html @@ -833,10 +833,10 @@ sudo apt-get install -y taler-wallet-cli /privacy.

-

+

Landing v42 - · content - · aa3c23b + · content + · b01058c

diff --git a/configs/shared/landing-version.json b/configs/shared/landing-version.json index ee06829..f3ccae7 100644 --- a/configs/shared/landing-version.json +++ b/configs/shared/landing-version.json @@ -1,9 +1,9 @@ { "version": 42, - "updated_iso": "2026-07-17T13:31:56+02:00", + "updated_iso": "2026-07-17T13:31:57+02:00", "updated_human": "2026-07-17 13:31 CEST", - "commit": "aa3c23be49236ba5c20cd095bb02790f84aeb1e5", - "commit_short": "aa3c23b", - "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/aa3c23be49236ba5c20cd095bb02790f84aeb1e5", + "commit": "b01058c6c1f8bf25fa1ddcd1224c65fb12a1debd", + "commit_short": "b01058c", + "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/b01058c6c1f8bf25fa1ddcd1224c65fb12a1debd", "note": "Bump with scripts/taler-landing/stamp-landing-version.sh --bump after each landing content change." } From 1bbdc2d1ae00d331d78258d7fc18e4ee5e79dd3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Fri, 17 Jul 2026 13:32:12 +0200 Subject: [PATCH 4/7] doc/landing: version stamp workflow (v42+) --- scripts/taler-landing/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/taler-landing/README.md b/scripts/taler-landing/README.md index 4b79f7b..8e70120 100644 --- a/scripts/taler-landing/README.md +++ b/scripts/taler-landing/README.md @@ -146,3 +146,16 @@ podman exec taler-hacktivism-bank crontab -l # inspect curl -sS https://bank.hacktivism.ch/intro/stats.json | python3 -m json.tool | head ``` + +## Landing content version + +Footers show **Landing vN** + last content change + linkified git commit. + +- State: `configs/shared/landing-version.json` (start **v42**) +- After editing any `configs/*-landing/` content: + ```bash + ./scripts/taler-landing/stamp-landing-version.sh --bump + git add configs/ && git commit -m "landing: …" + ./scripts/taler-landing/stamp-landing-version.sh + git add configs/ && git commit --amend --no-edit # optional pin + ``` From bdfdbfe7c87ca870e4ca819f6f4b2a6291b3252c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Fri, 17 Jul 2026 13:32:58 +0200 Subject: [PATCH 5/7] landing: per-site content versions (bank/exchange/merchant v42) Independent version counters per landing footer with last-change time and linkified commit; stamp script takes bank|exchange|merchant|--all. --- configs/bank-landing/index.html | 8 +- configs/exchange-landing/index.html | 8 +- configs/merchant-landing/index.html | 8 +- configs/shared/landing-version.json | 40 +++- scripts/taler-landing/README.md | 16 +- .../taler-landing/stamp-landing-version.sh | 182 +++++++++++------- 6 files changed, 170 insertions(+), 92 deletions(-) diff --git a/configs/bank-landing/index.html b/configs/bank-landing/index.html index 52c3955..ba5857d 100644 --- a/configs/bank-landing/index.html +++ b/configs/bank-landing/index.html @@ -1556,10 +1556,10 @@ tw run-until-done && tw balance /privacy.

-

- Landing v42 - · content - · b01058c +

+ Bank landing v42 + · content + · 2504315

diff --git a/configs/exchange-landing/index.html b/configs/exchange-landing/index.html index 44991b0..6b498ad 100644 --- a/configs/exchange-landing/index.html +++ b/configs/exchange-landing/index.html @@ -490,10 +490,10 @@ sudo apt-get install -y taler-wallet-cli /privacy.

-

- Landing v42 - · content - · b01058c +

+ Exchange landing v42 + · content + · 2504315

diff --git a/configs/merchant-landing/index.html b/configs/merchant-landing/index.html index 6797c55..21dc6f5 100644 --- a/configs/merchant-landing/index.html +++ b/configs/merchant-landing/index.html @@ -833,10 +833,10 @@ sudo apt-get install -y taler-wallet-cli /privacy.

-

- Landing v42 - · content - · b01058c +

+ Merchant landing v42 + · content + · 2504315

diff --git a/configs/shared/landing-version.json b/configs/shared/landing-version.json index f3ccae7..4aec0ff 100644 --- a/configs/shared/landing-version.json +++ b/configs/shared/landing-version.json @@ -1,9 +1,35 @@ { - "version": 42, - "updated_iso": "2026-07-17T13:31:57+02:00", - "updated_human": "2026-07-17 13:31 CEST", - "commit": "b01058c6c1f8bf25fa1ddcd1224c65fb12a1debd", - "commit_short": "b01058c", - "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/b01058c6c1f8bf25fa1ddcd1224c65fb12a1debd", - "note": "Bump with scripts/taler-landing/stamp-landing-version.sh --bump after each landing content change." + "note": "Per-site landing content versions (start 42). Bump: scripts/taler-landing/stamp-landing-version.sh --bump bank|exchange|merchant", + "sites": { + "bank": { + "version": 42, + "label": "Bank landing", + "path": "configs/bank-landing", + "updated_iso": "2026-07-17T13:32:58+02:00", + "updated_human": "2026-07-17 13:32 CEST", + "commit": "250431590ede905cddf79f7390d2267578a5e758", + "commit_short": "2504315", + "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/250431590ede905cddf79f7390d2267578a5e758" + }, + "exchange": { + "version": 42, + "label": "Exchange landing", + "path": "configs/exchange-landing", + "updated_iso": "2026-07-17T13:32:58+02:00", + "updated_human": "2026-07-17 13:32 CEST", + "commit": "250431590ede905cddf79f7390d2267578a5e758", + "commit_short": "2504315", + "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/250431590ede905cddf79f7390d2267578a5e758" + }, + "merchant": { + "version": 42, + "label": "Merchant landing", + "path": "configs/merchant-landing", + "updated_iso": "2026-07-17T13:32:58+02:00", + "updated_human": "2026-07-17 13:32 CEST", + "commit": "250431590ede905cddf79f7390d2267578a5e758", + "commit_short": "2504315", + "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/250431590ede905cddf79f7390d2267578a5e758" + } + } } diff --git a/scripts/taler-landing/README.md b/scripts/taler-landing/README.md index 8e70120..f9e9d62 100644 --- a/scripts/taler-landing/README.md +++ b/scripts/taler-landing/README.md @@ -147,15 +147,17 @@ podman exec taler-hacktivism-bank crontab -l # inspect curl -sS https://bank.hacktivism.ch/intro/stats.json | python3 -m json.tool | head ``` -## Landing content version +## Landing content version (per site) -Footers show **Landing vN** + last content change + linkified git commit. +Each landing footer shows **Bank|Exchange|Merchant landing vN** + last content +change + linkified git commit. Versions are **independent** (start **v42** each). -- State: `configs/shared/landing-version.json` (start **v42**) -- After editing any `configs/*-landing/` content: +- State: `configs/shared/landing-version.json` → `sites.bank|exchange|merchant` +- After editing one site (example bank): ```bash - ./scripts/taler-landing/stamp-landing-version.sh --bump - git add configs/ && git commit -m "landing: …" - ./scripts/taler-landing/stamp-landing-version.sh + ./scripts/taler-landing/stamp-landing-version.sh --bump bank + git add configs/ && git commit -m "landing(bank): …" + ./scripts/taler-landing/stamp-landing-version.sh bank git add configs/ && git commit --amend --no-edit # optional pin ``` +- Re-stamp all without bump: `./scripts/taler-landing/stamp-landing-version.sh --all` diff --git a/scripts/taler-landing/stamp-landing-version.sh b/scripts/taler-landing/stamp-landing-version.sh index 570636c..9616dec 100755 --- a/scripts/taler-landing/stamp-landing-version.sh +++ b/scripts/taler-landing/stamp-landing-version.sh @@ -1,57 +1,83 @@ #!/usr/bin/env bash -# Stamp landing footers with version + last content change + linkified commit. +# Stamp landing footers per site: version + last content change + linkified commit. +# +# Sites: bank | exchange | merchant # # Usage (from koopa-admin-log root): -# ./scripts/taler-landing/stamp-landing-version.sh # re-stamp with HEAD + current version -# ./scripts/taler-landing/stamp-landing-version.sh --bump # version += 1, then stamp HEAD -# ./scripts/taler-landing/stamp-landing-version.sh --set 42 # force version +# ./scripts/taler-landing/stamp-landing-version.sh bank +# re-stamp bank with current version + HEAD +# ./scripts/taler-landing/stamp-landing-version.sh --bump bank +# bank version += 1, then stamp HEAD +# ./scripts/taler-landing/stamp-landing-version.sh --set 42 exchange +# force exchange version to 42 +# ./scripts/taler-landing/stamp-landing-version.sh --all +# re-stamp all sites (no bump) +# ./scripts/taler-landing/stamp-landing-version.sh --bump --all +# bump every site by 1 (rare) # -# Typical flow after editing landing HTML/CSS/JS: -# 1) edit landings -# 2) ./scripts/taler-landing/stamp-landing-version.sh --bump -# 3) git add configs/ && git commit -# 4) ./scripts/taler-landing/stamp-landing-version.sh && git add configs/ && git commit --amend --no-edit -# -# Or one-shot (commits for you if GIT_STAMP_COMMIT=1). +# Typical flow after editing one site: +# 1) edit configs/bank-landing/… +# 2) ./scripts/taler-landing/stamp-landing-version.sh --bump bank +# 3) git add configs/ && git commit -m "landing(bank): …" +# 4) ./scripts/taler-landing/stamp-landing-version.sh bank +# git add configs/ && git commit --amend --no-edit # optional pin set -euo pipefail ROOT="$(cd "$(dirname "$0")/../.." && pwd)" VER_FILE="$ROOT/configs/shared/landing-version.json" REPO_WEB="${LANDING_REPO_WEB:-https://git.hacktivism.ch/hernani/koopa-admin-log}" -LANDINGS=( - "$ROOT/configs/bank-landing/index.html" - "$ROOT/configs/exchange-landing/index.html" - "$ROOT/configs/merchant-landing/index.html" + +declare -A SITE_HTML=( + [bank]="$ROOT/configs/bank-landing/index.html" + [exchange]="$ROOT/configs/exchange-landing/index.html" + [merchant]="$ROOT/configs/merchant-landing/index.html" +) +declare -A SITE_LABEL=( + [bank]="Bank landing" + [exchange]="Exchange landing" + [merchant]="Merchant landing" +) +declare -A SITE_PATH=( + [bank]="configs/bank-landing" + [exchange]="configs/exchange-landing" + [merchant]="configs/merchant-landing" ) export TZ="${TZ:-Europe/Zurich}" bump=0 set_ver="" +do_all=0 +sites=() + while [ $# -gt 0 ]; do case "$1" in --bump) bump=1; shift ;; --set) set_ver="${2:-}"; shift 2 ;; + --all) do_all=1; shift ;; + bank|exchange|merchant) sites+=("$1"); shift ;; -h|--help) - sed -n '2,20p' "$0" + sed -n '2,28p' "$0" exit 0 ;; - *) echo "unknown arg: $1" >&2; exit 2 ;; + *) echo "unknown arg: $1 (sites: bank exchange merchant)" >&2; exit 2 ;; esac done +if [ "$do_all" = 1 ]; then + sites=(bank exchange merchant) +fi +if [ "${#sites[@]}" -eq 0 ]; then + echo "usage: $0 [--bump|--set N] bank|exchange|merchant|--all" >&2 + exit 2 +fi + if [ ! -f "$VER_FILE" ]; then - echo '{"version":42,"updated_iso":"","updated_human":"","commit":"","commit_short":""}' >"$VER_FILE" + cat >"$VER_FILE" <<'EOF' +{"note":"per-site","sites":{"bank":{"version":42},"exchange":{"version":42},"merchant":{"version":42}}} +EOF fi -version=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("version",42))' "$VER_FILE") -if [ -n "$set_ver" ]; then - version="$set_ver" -elif [ "$bump" = 1 ]; then - version=$((version + 1)) -fi - -# Prefer staged/index commit identity after commit; allow OVERRIDE_COMMIT if [ -n "${OVERRIDE_COMMIT:-}" ]; then full="$OVERRIDE_COMMIT" else @@ -62,34 +88,6 @@ iso=$(date +%Y-%m-%dT%H:%M:%S%z | sed -E 's/([+-][0-9]{2})([0-9]{2})$/\1:\2/') human=$(date +"%Y-%m-%d %H:%M %Z") url="${REPO_WEB}/commit/${full}" -python3 - "$VER_FILE" "$version" "$iso" "$human" "$full" "$short" "$url" <<'PY' -import json, sys -path, version, iso, human, full, short, url = sys.argv[1:] -data = { - "version": int(version), - "updated_iso": iso, - "updated_human": human, - "commit": full, - "commit_short": short, - "repo_commit_url": url, - "note": "Bump with scripts/taler-landing/stamp-landing-version.sh --bump after each landing content change.", -} -open(path, "w", encoding="utf-8").write(json.dumps(data, indent=2, ensure_ascii=False) + "\n") -print(f"version={version} commit={short} at={human}") -PY - -# HTML block injected into each footer (idempotent via markers) -block=$(cat < -

- Landing v${version} - · content - · ${short} -

- -EOF -) - css_snip=' .landing-rev { margin: 0.75rem 0 0; font-size: 0.72rem; @@ -101,27 +99,80 @@ css_snip=' .landing-rev { .landing-rev strong { font-weight: 750; } ' -for f in "${LANDINGS[@]}"; do - [ -f "$f" ] || { echo "missing $f" >&2; exit 1; } +for site in "${sites[@]}"; do + html="${SITE_HTML[$site]:-}" + label="${SITE_LABEL[$site]:-}" + relpath="${SITE_PATH[$site]:-}" + [ -n "$html" ] && [ -f "$html" ] || { echo "missing site/html: $site" >&2; exit 1; } + + # resolve version for this site + version=$(python3 - "$VER_FILE" "$site" "$bump" "$set_ver" <<'PY' +import json, sys +path, site, bump, set_ver = sys.argv[1:5] +data = json.load(open(path, encoding="utf-8")) +sites = data.setdefault("sites", {}) +entry = sites.setdefault(site, {"version": 42}) +v = int(entry.get("version", 42)) +if set_ver: + v = int(set_ver) +elif bump == "1": + v += 1 +print(v) +PY +) + + # update JSON entry for this site (preserve others) + python3 - "$VER_FILE" "$site" "$version" "$label" "$relpath" "$iso" "$human" "$full" "$short" "$url" <<'PY' +import json, sys +path, site, version, label, relpath, iso, human, full, short, url = sys.argv[1:] +data = json.load(open(path, encoding="utf-8")) +data["note"] = ( + "Per-site landing content versions (start 42). " + "Bump: scripts/taler-landing/stamp-landing-version.sh --bump bank|exchange|merchant" +) +sites = data.setdefault("sites", {}) +sites[site] = { + "version": int(version), + "label": label, + "path": relpath, + "updated_iso": iso, + "updated_human": human, + "commit": full, + "commit_short": short, + "repo_commit_url": url, +} +open(path, "w", encoding="utf-8").write(json.dumps(data, indent=2, ensure_ascii=False) + "\n") +print(f"{site}: v{version} commit={short} at={human}") +PY + + block=$(cat < +

+ ${label} v${version} + · content + · ${short} +

+ +EOF +) + # ensure CSS once - if ! grep -q '\.landing-rev' "$f"; then - # insert before of first style block - python3 - "$f" "$css_snip" <<'PY' + if ! grep -q '\.landing-rev' "$html"; then + python3 - "$html" "$css_snip" <<'PY' import sys path, snip = sys.argv[1], sys.argv[2] t = open(path, encoding="utf-8").read() if ".landing-rev" in t: - sys.exit(0) + raise SystemExit(0) idx = t.find("") if idx < 0: raise SystemExit(f"no in {path}") -t = t[:idx] + snip + "\n" + t[idx:] -open(path, "w", encoding="utf-8").write(t) +open(path, "w", encoding="utf-8").write(t[:idx] + snip + "\n" + t[idx:]) print(f"css → {path}") PY fi - # replace or insert rev block before - python3 - "$f" "$block" <<'PY' + + python3 - "$html" "$block" <<'PY' import sys, re path, block = sys.argv[1], sys.argv[2] t = open(path, encoding="utf-8").read() @@ -130,7 +181,6 @@ pat = re.compile(r"[ \t]*.*?\n?", re.S) if pat.search(t): t = pat.sub(block, t, count=1) else: - # before closing footer t2, n = re.subn(r"(\n)([ \t]*)", r"\1" + block + r"\2", t, count=1) if n != 1: raise SystemExit(f"could not insert landing-rev in {path}") @@ -140,4 +190,4 @@ print(f"stamp → {path}") PY done -echo "OK landing v${version} → ${short} (${human})" +echo "OK stamped: ${sites[*]}" From 186fdc255c2ff61c07647e5cfa1ff701f1776d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Fri, 17 Jul 2026 13:32:59 +0200 Subject: [PATCH 6/7] landing: pin per-site v42 footers to commit --- configs/bank-landing/index.html | 6 +++--- configs/exchange-landing/index.html | 6 +++--- configs/merchant-landing/index.html | 6 +++--- configs/shared/landing-version.json | 24 ++++++++++++------------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/configs/bank-landing/index.html b/configs/bank-landing/index.html index ba5857d..3f31226 100644 --- a/configs/bank-landing/index.html +++ b/configs/bank-landing/index.html @@ -1556,10 +1556,10 @@ tw run-until-done && tw balance /privacy.

-

+

Bank landing v42 - · content - · 2504315 + · content + · 921a4f1

diff --git a/configs/exchange-landing/index.html b/configs/exchange-landing/index.html index 6b498ad..0101601 100644 --- a/configs/exchange-landing/index.html +++ b/configs/exchange-landing/index.html @@ -490,10 +490,10 @@ sudo apt-get install -y taler-wallet-cli /privacy.

-

+

Exchange landing v42 - · content - · 2504315 + · content + · 921a4f1

diff --git a/configs/merchant-landing/index.html b/configs/merchant-landing/index.html index 21dc6f5..96ab5eb 100644 --- a/configs/merchant-landing/index.html +++ b/configs/merchant-landing/index.html @@ -833,10 +833,10 @@ sudo apt-get install -y taler-wallet-cli /privacy.

-

+

Merchant landing v42 - · content - · 2504315 + · content + · 921a4f1

diff --git a/configs/shared/landing-version.json b/configs/shared/landing-version.json index 4aec0ff..7d1de54 100644 --- a/configs/shared/landing-version.json +++ b/configs/shared/landing-version.json @@ -5,31 +5,31 @@ "version": 42, "label": "Bank landing", "path": "configs/bank-landing", - "updated_iso": "2026-07-17T13:32:58+02:00", + "updated_iso": "2026-07-17T13:32:59+02:00", "updated_human": "2026-07-17 13:32 CEST", - "commit": "250431590ede905cddf79f7390d2267578a5e758", - "commit_short": "2504315", - "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/250431590ede905cddf79f7390d2267578a5e758" + "commit": "921a4f1572dbf4391b69899287b4c0280bb0e271", + "commit_short": "921a4f1", + "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/921a4f1572dbf4391b69899287b4c0280bb0e271" }, "exchange": { "version": 42, "label": "Exchange landing", "path": "configs/exchange-landing", - "updated_iso": "2026-07-17T13:32:58+02:00", + "updated_iso": "2026-07-17T13:32:59+02:00", "updated_human": "2026-07-17 13:32 CEST", - "commit": "250431590ede905cddf79f7390d2267578a5e758", - "commit_short": "2504315", - "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/250431590ede905cddf79f7390d2267578a5e758" + "commit": "921a4f1572dbf4391b69899287b4c0280bb0e271", + "commit_short": "921a4f1", + "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/921a4f1572dbf4391b69899287b4c0280bb0e271" }, "merchant": { "version": 42, "label": "Merchant landing", "path": "configs/merchant-landing", - "updated_iso": "2026-07-17T13:32:58+02:00", + "updated_iso": "2026-07-17T13:32:59+02:00", "updated_human": "2026-07-17 13:32 CEST", - "commit": "250431590ede905cddf79f7390d2267578a5e758", - "commit_short": "2504315", - "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/250431590ede905cddf79f7390d2267578a5e758" + "commit": "921a4f1572dbf4391b69899287b4c0280bb0e271", + "commit_short": "921a4f1", + "repo_commit_url": "https://git.hacktivism.ch/hernani/koopa-admin-log/commit/921a4f1572dbf4391b69899287b4c0280bb0e271" } } } From 4685e370ac662138f3c9a425af6ba54396bb7830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A2ni=20Marques?= Date: Fri, 17 Jul 2026 18:13:39 +0200 Subject: [PATCH 7/7] docs: I-08 landing-stats standalone migration note --- ISSUES.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/ISSUES.md b/ISSUES.md index 33f4f2a..4e89ea6 100644 --- a/ISSUES.md +++ b/ISSUES.md @@ -1,6 +1,6 @@ # Open issues -Stand **2026-07-16** (koopa, live). Keine Secrets. +Stand **2026-07-17** (koopa, live). Keine Secrets. ## Index @@ -13,6 +13,7 @@ Stand **2026-07-16** (koopa, live). Keine Secrets. | [I-05](#i-2026-07-16-05) | low | open | Alte exited Podman-Container | | [I-06](#i-2026-07-16-06) | low–medium | open | Nym HTTP API `*:9080` | | [I-07](#i-2026-07-16-07) | medium | **fixed** | Tor host vs `koopa-tor-relay` | +| [I-08](#i-2026-07-17-08) | medium | open | Landing-stats → standalone `taler-landing-stats` | --- @@ -131,6 +132,24 @@ podman ps --filter name=koopa-tor-relay --- +### I-2026-07-17-08 + +**Landing-stats / Resource-Monitoring: auf standalone `taler-landing-stats` umstellen** +Severity: medium · Host: koopa · Status: open · **TODO (noch nicht umsetzen auf koopa)** + +**Ist:** Collector + Timer leben unter `scripts/taler-landing/` in **diesem** admin-log, installiert nach `~/.local/bin` / user-systemd, Defaults stark **hacktivism.ch**-lastig (Container-Namen, URLs, `ADMIN_LOG`-Pfade). + +**Soll:** Dieselbe **moderne, host-dynamische** Lösung wie geplant/gebaut für andere Stacks: + +- Eigenes Repo **`taler-landing-stats`** auf **git.hacktivism.ch** (`hernani/taler-landing-stats`) +- Profile/env pro Host (bank/exchange/merchant Container, Landing-Pfade, optional bank full-scan) +- User-systemd timer (`taler-landing-stats.service` / `.timer`), Linger +- Resource-Merge (RSS/loadavg via in-container mem-snapshot + podman stats) host-agnostisch + +**Nicht jetzt auf koopa umbauen** — nur merken. Wenn das Repo steht und auf stage/etc. erprobt ist: koopa von `scripts/taler-landing/` auf Checkout+Install aus `taler-landing-stats` migrieren; hier ggf. nur noch Pointer/README. + +--- + ## Kein Issue (Scan) - Prod-Container mit Boot-Autostart: Up