{
  "generated_at": "2026-10-17T18:38:16Z",
  "generated_by": "tools/audit-report.rb (site build)",
  "what_this_is": "Verification record for the published no-log audit. Every signature listed here was checked with stock ssh-keygen against the key pinned in _data/audit-pins.json at build time. If this file says verified:false, or a host's own checks did not all pass, the build fails and nothing is published; if it says available:false, the artifact could not be retrieved and the page renders that instead.",
  "namespace": "logging-audit",
  "verify_recipe": "curl -O <base>/logging-audit/logging-audit.allowed_signers && curl -O <base>/logging-audit/logging-audit.json && curl -O <base>/logging-audit/logging-audit.json.sig && ssh-keygen -Y verify -f logging-audit.allowed_signers -I logging-audit@<host> -n logging-audit -s logging-audit.json.sig < logging-audit.json",
  "pins": {
    "vpn": {
      "role": "VPN edge",
      "principal": "logging-audit@vpn",
      "fingerprint": "SHA256:nLZOwc5NYNz4dWnTI6ZDOYi3IGsiFj9yhKEs/VzCpzY"
    },
    "public": {
      "role": "Public web / API",
      "principal": "logging-audit@public",
      "fingerprint": "SHA256:NkQoFKJH/tiH+K+8fICk3nCukwo35G+P4BdZDVnA/vU"
    },
    "vpn-mx": {
      "role": "Client VPN door (MX)",
      "principal": "logging-audit@vpn-mx",
      "fingerprint": "SHA256:6Cdnl9DxqCrnMqUFriROdySv9Vcm9bhNSZTszxNeXj4"
    }
  },
  "hosts": [
    {
      "host": "vpn",
      "role": "VPN edge",
      "base_url": "https://vpn.ymrtech.com",
      "principal": "logging-audit@vpn",
      "pinned_fingerprint": "SHA256:nLZOwc5NYNz4dWnTI6ZDOYi3IGsiFj9yhKEs/VzCpzY",
      "available": true,
      "allowed_signers_http": 200,
      "verified": true,
      "verify_output": "Good \"logging-audit\" signature for logging-audit@vpn with ED25519 key SHA256:nLZOwc5NYNz4dWnTI6ZDOYi3IGsiFj9yhKEs/VzCpzY",
      "report_sha256": "623c7f9f4df9ad20f5e1eb42cf11b3a41cd1099ffff2a45d9ad233f3418ff47b",
      "report_bytes": 4884,
      "generated_at": "2026-10-17T09:33:42Z",
      "generated_age": "9.1 h ago",
      "report_host_field": "vpn",
      "all_ok": true,
      "report_version": 1,
      "system_generation": "/nix/store/2bfwqygfkb99cim5cx4rwl7zmp8vapn1-nixos-system-vpn-26.11.20260909.7b66dac",
      "signer_type": "ssh-ed25519",
      "signer_fingerprint": "SHA256:nLZOwc5NYNz4dWnTI6ZDOYi3IGsiFj9yhKEs/VzCpzY",
      "retention": {
        "adguard-querylog": "no AdGuard instance serves on this host any more (the fleet resolver on 11.0.0.1 and the wg2 tier resolver on 172.16.41.1 are both blocky)",
        "blocky-querylog": "disabled on every blocky instance on this host: queryLog.type is forced to \"none\" by nix-config-private modules/resolver-blocky.nix (a host cannot override it; the module fails evaluation instead)",
        "hermes-lcm": "90d (enforced daily by systemd.timers.hermes-lcm-retention)",
        "journald": "30d local ceiling (a maximum, not an achieved window: size-bounded to 512M by NCFG-754, vpn's worst-case full-replay bound, where the ACHIEVED window is ~1-2 d and volume-dependent - 24.3 h at ~0.46 GB/day on 2026-10-07, 48.2 h at ~242 MiB/day on 2026-10-09 - so plan on ~1 d (NCFG-788); the >=3 d surface is VictoriaLogs, 14 d, whole journal shipped off-host)",
        "victorialogs": "14d",
        "victoriametrics": "30d (per-device byte counters are attributable to a customer's device)"
      },
      "checks": [
        {
          "id": "blocky:wg2:querylog-off",
          "ok": true,
          "status": "ok",
          "detail": "the effective config /nix/store/11dxqnddfr8kamn61gm8c0w5ll8jcgrg-blocky-wg2.yaml (path read from blocky-wg2, not declared here) has queryLog.type=none; no query logging is the fleet posture"
        },
        {
          "id": "blocky:wg2:no-querylog-file",
          "ok": true,
          "status": "ok",
          "detail": "queryLog.type=none target=None; 0 artifact(s) at the declared target; 0 query-log-shaped name(s) under state dir /var/lib/blocky-wg2; unit blocky-wg2 ActiveState=active"
        },
        {
          "id": "blocky:fleet:querylog-off",
          "ok": true,
          "status": "ok",
          "detail": "the effective config /nix/store/5yx6c7z5mmmn0jamzvgsnhc40s6wm41c-blocky-fleet.yaml (path read from blocky-fleet, not declared here) has queryLog.type=none; no query logging is the fleet posture"
        },
        {
          "id": "blocky:fleet:no-querylog-file",
          "ok": true,
          "status": "ok",
          "detail": "queryLog.type=none target=None; 0 artifact(s) at the declared target; 0 query-log-shaped name(s) under state dir /var/lib/blocky-fleet; unit blocky-fleet ActiveState=active"
        },
        {
          "id": "unbound:/etc/unbound/unbound.conf",
          "ok": true,
          "status": "ok",
          "detail": "log-queries lines=none"
        },
        {
          "id": "unbound:/etc/unbound-client/unbound.conf",
          "ok": true,
          "status": "ok",
          "detail": "log-queries lines=none"
        },
        {
          "id": "journal:no-client-tier-address",
          "ok": true,
          "status": "ok",
          "detail": "0 client match(es) in 1475 line(s) of units blocky-wg2,blocky-fleet,unbound,unbound-client since 14 days ago; 38 non-client line(s) ignored (sudo audit trail, or a fleet address: this host's own gateway, its peer's tier resolver, or the tier VIP)"
        }
      ],
      "notes": [
        "adguard:* checks ENFORCE the setting (idempotent POST), purge any persisted querylog, then require that a real query wrote nothing: the API has no read endpoint for this setting and its querylog GET serves stale memory.",
        "blocky:<instance> checks read the EFFECTIVE config the running unit loaded (the path comes from the unit's own ExecStart, not from this module's configuration) and require queryLog.type: none plus no query-log artifact under the unit's state dir, with the unit ACTIVE. There is no canary query on this engine: with query logging off blocky's /api/query answers 405, so a pass here is a claim about configuration and disk, not an observation that a sent query left no log entry.",
        "nolog:<unit> checks RE-RUN the unit's own behavioural assertion (restart, then require a fresh success plus its NO-LOG OK line) rather than re-reading the line a past deploy wrote: the local journal is size-capped and vacuums that line long before any declared retention.",
        "journal:no-client-tier-address scans only the resolver units named in queryUnits, and counts only lines naming a CLIENT tier address. Every address the fleet owns inside the scanned ranges — this host's own gateways, its peer's tier resolvers, and the tier VIP that moves between the halves, declared once in nix-config-private/modules/fleet-tier-addresses.nix — is counted and reported as non-client rather than dropped.",
        "retention values are DECLARED claims from the configuration, recorded here so a change to them is visible as a diff."
      ],
      "checks_total": 7,
      "checks_failed": 0,
      "monthly_index_verified": true,
      "monthly_index_sha256": "a2ed79574a9de43ea6a3c4b97ba4efb4550ab4c7414e0d54e9d6fa2a652b3c49",
      "monthly_index_verify_output": "Good \"logging-audit\" signature for logging-audit@vpn with ED25519 key SHA256:nLZOwc5NYNz4dWnTI6ZDOYi3IGsiFj9yhKEs/VzCpzY",
      "monthly_index_generated_at": "2026-10-17T09:33:42Z",
      "months": [
        {
          "month": "2026-09",
          "state": "month-to-date",
          "status": "incomplete",
          "all_ok": false,
          "days_with_report": 13,
          "days_expected": 30,
          "violations": 0,
          "sha256": "c60b353c5462388976b9bf8bd74c03150b2a077e8c28f767c4d7ad89ff19f2cc",
          "urls": null,
          "signature_verified": true,
          "actual_sha256": "c60b353c5462388976b9bf8bd74c03150b2a077e8c28f767c4d7ad89ff19f2cc",
          "sha256_matches": true,
          "archive_starts": "2026-09-18",
          "days_missing": [
            "2026-09-01",
            "2026-09-02",
            "2026-09-03",
            "2026-09-04",
            "2026-09-05",
            "2026-09-06",
            "2026-09-07",
            "2026-09-08",
            "2026-09-09",
            "2026-09-10",
            "2026-09-11",
            "2026-09-12",
            "2026-09-13",
            "2026-09-14",
            "2026-09-15",
            "2026-09-16",
            "2026-09-17"
          ]
        },
        {
          "month": "2026-10",
          "state": "month-to-date",
          "status": "clean",
          "all_ok": true,
          "days_with_report": 17,
          "days_expected": 17,
          "violations": 0,
          "sha256": "00cc7de5cfc1d1576fff0cd6af61ca5ed27235c29a93edf3f502b934654ff71e",
          "urls": null,
          "signature_verified": true,
          "actual_sha256": "00cc7de5cfc1d1576fff0cd6af61ca5ed27235c29a93edf3f502b934654ff71e",
          "sha256_matches": true,
          "archive_starts": "2026-09-18",
          "days_missing": []
        }
      ]
    },
    {
      "host": "public",
      "role": "Public web / API",
      "base_url": "https://ymrtech.com",
      "principal": "logging-audit@public",
      "pinned_fingerprint": "SHA256:NkQoFKJH/tiH+K+8fICk3nCukwo35G+P4BdZDVnA/vU",
      "available": true,
      "allowed_signers_http": 200,
      "verified": true,
      "verify_output": "Good \"logging-audit\" signature for logging-audit@public with ED25519 key SHA256:NkQoFKJH/tiH+K+8fICk3nCukwo35G+P4BdZDVnA/vU",
      "report_sha256": "edf0a7d8530298271363fdc1aad2c396d511b548a21edd7780da6c796ca30f4a",
      "report_bytes": 3543,
      "generated_at": "2026-10-17T09:47:06Z",
      "generated_age": "8.9 h ago",
      "report_host_field": "public",
      "all_ok": true,
      "report_version": 1,
      "system_generation": "/nix/store/2xsy2j8jslp3xn0i6rvvf72q7c35f1gi-nixos-system-public-26.11.20260909.7b66dac",
      "signer_type": "ssh-ed25519",
      "signer_fingerprint": "SHA256:NkQoFKJH/tiH+K+8fICk3nCukwo35G+P4BdZDVnA/vU",
      "retention": {
        "adguard-querylog": "disabled (no querylog.json, no retrievable tier entries)",
        "journald": "30d local ceiling (a maximum, not an achieved window: size-bounded, ~18d at the measured rate), AND 14d in VictoriaLogs on mail (shipped off-host since 2026-09-22, WP4)"
      },
      "checks": [
        {
          "id": "blocky:wg2-standby:querylog-off",
          "ok": true,
          "status": "ok",
          "detail": "the effective config /nix/store/isjqcsv3wfzavz2y5pw3b2hxxrymyxhn-blocky-wg2-standby.yaml (path read from blocky-wg2-standby, not declared here) has queryLog.type=none; no query logging is the fleet posture"
        },
        {
          "id": "blocky:wg2-standby:no-querylog-file",
          "ok": true,
          "status": "ok",
          "detail": "queryLog.type=none target=None; 0 artifact(s) at the declared target; 0 query-log-shaped name(s) under state dir /var/lib/blocky-wg2-standby; unit blocky-wg2-standby ActiveState=active"
        },
        {
          "id": "unbound:/etc/unbound/unbound.conf",
          "ok": true,
          "status": "ok",
          "detail": "log-queries lines=none"
        },
        {
          "id": "journal:no-client-tier-address",
          "ok": true,
          "status": "ok",
          "detail": "0 client match(es) in 248 line(s) of units blocky-wg2-standby,unbound since 14 days ago; 10 non-client line(s) ignored (sudo audit trail, or a fleet address: this host's own gateway, its peer's tier resolver, or the tier VIP)"
        }
      ],
      "notes": [
        "adguard:* checks ENFORCE the setting (idempotent POST), purge any persisted querylog, then require that a real query wrote nothing: the API has no read endpoint for this setting and its querylog GET serves stale memory.",
        "blocky:<instance> checks read the EFFECTIVE config the running unit loaded (the path comes from the unit's own ExecStart, not from this module's configuration) and require queryLog.type: none plus no query-log artifact under the unit's state dir, with the unit ACTIVE. There is no canary query on this engine: with query logging off blocky's /api/query answers 405, so a pass here is a claim about configuration and disk, not an observation that a sent query left no log entry.",
        "nolog:<unit> checks RE-RUN the unit's own behavioural assertion (restart, then require a fresh success plus its NO-LOG OK line) rather than re-reading the line a past deploy wrote: the local journal is size-capped and vacuums that line long before any declared retention.",
        "journal:no-client-tier-address scans only the resolver units named in queryUnits, and counts only lines naming a CLIENT tier address. Every address the fleet owns inside the scanned ranges — this host's own gateways, its peer's tier resolvers, and the tier VIP that moves between the halves, declared once in nix-config-private/modules/fleet-tier-addresses.nix — is counted and reported as non-client rather than dropped.",
        "retention values are DECLARED claims from the configuration, recorded here so a change to them is visible as a diff."
      ],
      "checks_total": 4,
      "checks_failed": 0,
      "monthly_index_verified": true,
      "monthly_index_sha256": "2e61d872a64e51654002fcafa76baae86f55e93f3a0fc35c6fce791a3e6468b1",
      "monthly_index_verify_output": "Good \"logging-audit\" signature for logging-audit@public with ED25519 key SHA256:NkQoFKJH/tiH+K+8fICk3nCukwo35G+P4BdZDVnA/vU",
      "monthly_index_generated_at": "2026-10-17T09:47:07Z",
      "months": [
        {
          "month": "2026-09",
          "state": "month-to-date",
          "status": "incomplete",
          "all_ok": false,
          "days_with_report": 13,
          "days_expected": 30,
          "violations": 0,
          "sha256": "d3e4d6d6a789d7c6da76ba91d7f56ab66048cdc98fa42982109d8618571833ec",
          "urls": null,
          "signature_verified": true,
          "actual_sha256": "d3e4d6d6a789d7c6da76ba91d7f56ab66048cdc98fa42982109d8618571833ec",
          "sha256_matches": true,
          "archive_starts": "2026-09-18",
          "days_missing": [
            "2026-09-01",
            "2026-09-02",
            "2026-09-03",
            "2026-09-04",
            "2026-09-05",
            "2026-09-06",
            "2026-09-07",
            "2026-09-08",
            "2026-09-09",
            "2026-09-10",
            "2026-09-11",
            "2026-09-12",
            "2026-09-13",
            "2026-09-14",
            "2026-09-15",
            "2026-09-16",
            "2026-09-17"
          ]
        },
        {
          "month": "2026-10",
          "state": "month-to-date",
          "status": "clean",
          "all_ok": true,
          "days_with_report": 17,
          "days_expected": 17,
          "violations": 0,
          "sha256": "67d7d48d7fc178d6fa7ae7faef0dc4b90927edffc1b54306a4f7601d01f396d5",
          "urls": null,
          "signature_verified": true,
          "actual_sha256": "67d7d48d7fc178d6fa7ae7faef0dc4b90927edffc1b54306a4f7601d01f396d5",
          "sha256_matches": true,
          "archive_starts": "2026-09-18",
          "days_missing": []
        }
      ]
    },
    {
      "host": "vpn-mx",
      "role": "Client VPN door (MX)",
      "base_url": "http://11.0.0.8:8082",
      "principal": "logging-audit@vpn-mx",
      "pinned_fingerprint": "SHA256:6Cdnl9DxqCrnMqUFriROdySv9Vcm9bhNSZTszxNeXj4",
      "available": true,
      "mesh_only": true,
      "mesh_host": "audit.vpn-mx.ymr:8082",
      "allowed_signers_http": 200,
      "verified": true,
      "verify_output": "Good \"logging-audit\" signature for logging-audit@vpn-mx with ED25519 key SHA256:6Cdnl9DxqCrnMqUFriROdySv9Vcm9bhNSZTszxNeXj4",
      "report_sha256": "f3a4a6e1a1a913f345ac99e91b88e342f285fb19c01cb010332261596e32bd57",
      "report_bytes": 3792,
      "generated_at": "2026-10-17T09:39:36Z",
      "generated_age": "9.0 h ago",
      "report_host_field": "vpn-mx",
      "all_ok": true,
      "report_version": 1,
      "system_generation": "/nix/store/c0a59hmbm4m97sl3n3wwpf8y7dgrvis2-nixos-system-vpn-mx-26.11.20260909.7b66dac",
      "signer_type": "ssh-ed25519",
      "signer_fingerprint": "SHA256:6Cdnl9DxqCrnMqUFriROdySv9Vcm9bhNSZTszxNeXj4",
      "retention": {},
      "checks": [
        {
          "id": "blocky:wg2:querylog-off",
          "ok": true,
          "status": "ok",
          "detail": "the effective config /nix/store/88dbgiax4gmrliqi7c1rsvr53rh5zbqc-blocky-wg2.yaml (path read from blocky-wg2, not declared here) has queryLog.type=none; no query logging is the fleet posture"
        },
        {
          "id": "blocky:wg2:no-querylog-file",
          "ok": true,
          "status": "ok",
          "detail": "queryLog.type=none target=None; 0 artifact(s) at the declared target; 0 query-log-shaped name(s) under state dir /var/lib/blocky-wg2; unit blocky-wg2 ActiveState=active"
        },
        {
          "id": "blocky:fleet:querylog-off",
          "ok": true,
          "status": "ok",
          "detail": "the effective config /nix/store/s8gn5chz9ydc8jm0mh7lisibm9baq4sp-blocky-fleet.yaml (path read from blocky-fleet, not declared here) has queryLog.type=none; no query logging is the fleet posture"
        },
        {
          "id": "blocky:fleet:no-querylog-file",
          "ok": true,
          "status": "ok",
          "detail": "queryLog.type=none target=None; 0 artifact(s) at the declared target; 0 query-log-shaped name(s) under state dir /var/lib/blocky-fleet; unit blocky-fleet ActiveState=active"
        },
        {
          "id": "unbound:/etc/unbound-client/unbound.conf",
          "ok": true,
          "status": "ok",
          "detail": "log-queries lines=none"
        },
        {
          "id": "journal:no-client-tier-address",
          "ok": true,
          "status": "ok",
          "detail": "0 client match(es) in 1842 line(s) of units blocky-wg2,blocky-fleet,unbound-client since 14 days ago; 84 non-client line(s) ignored (sudo audit trail, or a fleet address: this host's own gateway, its peer's tier resolver, or the tier VIP)"
        }
      ],
      "notes": [
        "adguard:* checks ENFORCE the setting (idempotent POST), purge any persisted querylog, then require that a real query wrote nothing: the API has no read endpoint for this setting and its querylog GET serves stale memory.",
        "blocky:<instance> checks read the EFFECTIVE config the running unit loaded (the path comes from the unit's own ExecStart, not from this module's configuration) and require queryLog.type: none plus no query-log artifact under the unit's state dir, with the unit ACTIVE. There is no canary query on this engine: with query logging off blocky's /api/query answers 405, so a pass here is a claim about configuration and disk, not an observation that a sent query left no log entry.",
        "nolog:<unit> checks RE-RUN the unit's own behavioural assertion (restart, then require a fresh success plus its NO-LOG OK line) rather than re-reading the line a past deploy wrote: the local journal is size-capped and vacuums that line long before any declared retention.",
        "journal:no-client-tier-address scans only the resolver units named in queryUnits, and counts only lines naming a CLIENT tier address. Every address the fleet owns inside the scanned ranges — this host's own gateways, its peer's tier resolvers, and the tier VIP that moves between the halves, declared once in nix-config-private/modules/fleet-tier-addresses.nix — is counted and reported as non-client rather than dropped.",
        "retention values are DECLARED claims from the configuration, recorded here so a change to them is visible as a diff."
      ],
      "checks_total": 6,
      "checks_failed": 0,
      "monthly_index_verified": true,
      "monthly_index_sha256": "6b297a6ae819d735dbfe1a349546c634c33c90f4173fbc26c370a8da51270750",
      "monthly_index_verify_output": "Good \"logging-audit\" signature for logging-audit@vpn-mx with ED25519 key SHA256:6Cdnl9DxqCrnMqUFriROdySv9Vcm9bhNSZTszxNeXj4",
      "monthly_index_generated_at": "2026-10-17T09:39:36Z",
      "months": [
        {
          "month": "2026-10",
          "state": "month-to-date",
          "status": "incomplete",
          "all_ok": false,
          "days_with_report": 9,
          "days_expected": 17,
          "violations": 0,
          "sha256": "4dc41db50f7e905d236a13b17e8daff605f2676147dc46b308f967489752084a",
          "urls": null,
          "signature_verified": true,
          "actual_sha256": "4dc41db50f7e905d236a13b17e8daff605f2676147dc46b308f967489752084a",
          "sha256_matches": true,
          "archive_starts": "2026-10-09",
          "days_missing": [
            "2026-10-01",
            "2026-10-02",
            "2026-10-03",
            "2026-10-04",
            "2026-10-05",
            "2026-10-06",
            "2026-10-07",
            "2026-10-08"
          ]
        }
      ]
    }
  ]
}
