{
  "schema_version": 3,
  "app": "filebrowser-quantum",
  "display_name": "FileBrowser Quantum",
  "upstream_repo": "https://github.com/gtsteffaniak/filebrowser",
  "docs_url": "https://filebrowserquantum.com/en/docs/getting-started/docker/",
  "status": "ok",
  "summary": {
    "primary_service": "filebrowser",
    "app_version": "v2.0.1-stable",
    "app_version_pinned": true,
    "runs": 3,
    "publishable": true,
    "publishable_note": null,
    "idle_total_mem_mib": 29.29,
    "idle_total_cpu_pct": 0.45,
    "peak_total_mem_mib": 43.97,
    "peak_is_under_load": true,
    "startup_seconds": 5.4,
    "startup_peak_total_mem_mib": 39.65,
    "settled": true,
    "settle_seconds_used": 173.6,
    "peak_max_mib": 48.12,
    "sizing_peak_mib": 48.12,
    "idle_mem_mib": {
      "median": 29.29,
      "min": 27.41,
      "max": 31.4,
      "values": [
        31.4,
        27.41,
        29.29
      ]
    },
    "idle_cpu_pct": {
      "median": 0.45,
      "min": 0.45,
      "max": 0.46,
      "values": [
        0.45,
        0.45,
        0.46
      ]
    },
    "peak_mem_mib": {
      "median": 43.97,
      "min": 41.89,
      "max": 48.12,
      "values": [
        48.12,
        41.89,
        43.97
      ]
    },
    "startup_peak_mem_mib": {
      "median": 39.65,
      "min": 39.62,
      "max": 43.7,
      "values": [
        43.7,
        39.62,
        39.65
      ]
    },
    "startup_s": {
      "median": 5.4,
      "min": 5.4,
      "max": 5.5,
      "values": [
        5.5,
        5.4,
        5.4
      ]
    },
    "settled_after_healthy_s": {
      "median": 175.1,
      "min": 175.1,
      "max": 181.1,
      "values": [
        175.1,
        181.1,
        175.1
      ]
    },
    "settled_runs": 3,
    "per_service": {
      "filebrowser": {
        "idle_mem_mib": {
          "median": 29.29,
          "min": 27.41,
          "max": 31.4,
          "values": [
            31.4,
            27.41,
            29.29
          ]
        },
        "peak_mem_mib": {
          "median": 43.97,
          "min": 41.89,
          "max": 48.12,
          "values": [
            48.12,
            41.89,
            43.97
          ]
        }
      }
    },
    "variance_flag": null,
    "representative_run": 3,
    "cpu_models": [
      "INTEL(R) XEON(R) PLATINUM 8573C"
    ],
    "cpu_model_mismatch": false,
    "rule": "idle = median of the run idle means; peak = median of the run peaks (highest simultaneous total, under load when the app has a load step); peak_max_mib = highest run peak; sizing_peak_mib = highest over runs of max(run peak, run startup peak); variance_flag when max/min over runs is above 1.5 for idle or peak."
  },
  "run": {
    "started_at": "2026-10-18T04:10:41Z",
    "date": "2026-10-18",
    "harness_version": "3.0.0",
    "runs_requested": 3,
    "docker_host": null,
    "remote": false,
    "runs_completed": 3
  },
  "host": {
    "label": "github-actions ubuntu-latest (2 vCPU, 8 GB)",
    "ci": {
      "runs_on": "ubuntu-latest",
      "runner_environment": "github-hosted",
      "runner_os": "Linux",
      "runner_arch": "X64",
      "image_os": "ubuntu24",
      "image_version": "20261012.334.1"
    },
    "cpu_model": "INTEL(R) XEON(R) PLATINUM 8573C",
    "cpu_model_note": null,
    "cores": 2,
    "mem_total_mib": 7937,
    "kernel": "6.17.0-1022-azure",
    "os": "Ubuntu 24.04.5 LTS",
    "arch": "x86_64",
    "oci_arch": "amd64",
    "docker_server_version": "28.0.4",
    "docker_client_version": "28.0.4",
    "compose_client_version": "2.38.2",
    "storage_driver": "overlay2",
    "containerd_image_store": false,
    "source": "docker info + throwaway container reading /proc/cpuinfo on the daemon host",
    "compose_note": "Compose runs on the client machine; Docker server fields are from the daemon host"
  },
  "helper_images": {
    "curlimages/curl:latest": {
      "pulled_as": "curlimages/curl:latest",
      "digest": "curlimages/curl@sha256:a134550be58ab783810e613ae96fd253c38f7bdd16d9bf9be350700c7a29ac06"
    },
    "python:3.12-slim": {
      "pulled_as": "python:3.12-slim",
      "digest": "python@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1"
    }
  },
  "pull_seconds": 3.8,
  "finished_at": "2026-10-18T04:21:49Z",
  "elapsed_seconds": 668.2,
  "services": {
    "filebrowser": {
      "image_ref": "gtstef/filebrowser:2.0.1-stable",
      "image_repo": "gtstef/filebrowser",
      "image_tag": "2.0.1-stable",
      "digest": "sha256:2e3936caf7b12908f7d3ebb68ddfcea075cda5f732e4bd95beae6cfa529cbec7",
      "digest_note": null,
      "version": "v2.0.1-stable",
      "version_source": "label:org.opencontainers.image.version",
      "version_pinned": true,
      "version_note": null,
      "resolved_tag": "2.0.1-stable",
      "resolved_tag_note": null,
      "image_size": {
        "unpacked_mb": 137.0,
        "unpacked_source": "docker image ls Size: unpacked image on the daemon host, rounded by docker to 3 significant figures",
        "compressed_mb": 63.1,
        "compressed_source": "sum of compressed layer sizes in the registry manifest for linux/amd64",
        "compressed_null_reason": null,
        "unit_note": "MB = 10^6 bytes. unpacked = disk used on the host; compressed = what is downloaded"
      },
      "compose_image": "gtstef/filebrowser:2.0.1-stable",
      "compose_comment": "sha256:2e3936caf7b12908f7d3ebb68ddfcea075cda5f732e4bd95beae6cfa529cbec7  (version v2.0.1-stable, from label:org.opencontainers.image.version)",
      "restart_count": 0,
      "oom_killed": false
    }
  },
  "runs": [
    {
      "run": 1,
      "started_at": "2026-10-18T04:10:51Z",
      "host": {
        "label": "github-actions ubuntu-latest (2 vCPU, 8 GB)",
        "ci": {
          "runs_on": "ubuntu-latest",
          "runner_environment": "github-hosted",
          "runner_os": "Linux",
          "runner_arch": "X64",
          "image_os": "ubuntu24",
          "image_version": "20261012.334.1"
        },
        "cpu_model": "INTEL(R) XEON(R) PLATINUM 8573C",
        "cpu_model_note": null,
        "cores": 2,
        "mem_total_mib": 7937,
        "kernel": "6.17.0-1022-azure",
        "os": "Ubuntu 24.04.5 LTS",
        "arch": "x86_64",
        "oci_arch": "amd64",
        "docker_server_version": "28.0.4",
        "docker_client_version": "28.0.4",
        "compose_client_version": "2.38.2",
        "storage_driver": "overlay2",
        "containerd_image_store": false,
        "source": "docker info + throwaway container reading /proc/cpuinfo on the daemon host",
        "compose_note": "Compose runs on the client machine; Docker server fields are from the daemon host"
      },
      "date": "2026-10-18",
      "startup": {
        "seconds": 5.5,
        "ok": true,
        "checks": [
          {
            "type": "container",
            "ok": true,
            "ready_after_s": 5.5,
            "detail": "shb-filebrowser-quantum-filebrowser-1=running/healthy"
          }
        ],
        "up_command_seconds": 0.3,
        "definition": "wall clock from starting `docker compose up -d` until every health check passed; checks poll every 0.5 s from a throwaway container on the compose network, so resolution is about +/- 1 s"
      },
      "versions": {
        "filebrowser": "v2.0.1-stable"
      },
      "setup": [
        {
          "exit_code": 0,
          "duration_s": 0.5,
          "reported": {
            "login_ok": true,
            "root_files": 0,
            "root_folders": 0,
            "unauthenticated_api_status": 401
          },
          "output_tail": [
            "logged in as admin; source 'files' root has 0 files and 0 folders (0.00s); without a token the API answers HTTP 401"
          ],
          "description": "Check /health, check that the API refuses a request without a token, log in as the admin user (POST /api/auth/login) and list the empty root of the source (GET /api/resources), as the first visit of a user would."
        }
      ],
      "idle": {
        "per_service": {
          "filebrowser": {
            "samples": 16,
            "mem_mean_mib": 31.4,
            "mem_max_mib": 31.61,
            "cpu_mean_pct": 0.45,
            "cpu_max_pct": 2.39
          }
        },
        "total": {
          "samples": 16,
          "dropped_for_total": 0,
          "mem_mean_mib": 31.4,
          "mem_max_mib": 31.61,
          "cpu_mean_pct": 0.45,
          "cpu_max_pct": 2.39
        },
        "window_seconds": 30.3,
        "series": [
          {
            "t_offset_s": 0.0,
            "total_mem_mib": 31.23,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 2.0,
            "total_mem_mib": 31.5,
            "total_cpu_pct": 2.38
          },
          {
            "t_offset_s": 4.0,
            "total_mem_mib": 31.5,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 6.1,
            "total_mem_mib": 31.26,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 8.1,
            "total_mem_mib": 31.54,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 10.1,
            "total_mem_mib": 31.33,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 12.1,
            "total_mem_mib": 31.61,
            "total_cpu_pct": 2.39
          },
          {
            "t_offset_s": 14.1,
            "total_mem_mib": 31.61,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 16.1,
            "total_mem_mib": 31.43,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 18.2,
            "total_mem_mib": 31.45,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 20.2,
            "total_mem_mib": 31.34,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 22.2,
            "total_mem_mib": 31.45,
            "total_cpu_pct": 2.38
          },
          {
            "t_offset_s": 24.2,
            "total_mem_mib": 31.29,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 26.2,
            "total_mem_mib": 31.29,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 28.3,
            "total_mem_mib": 31.32,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 30.3,
            "total_mem_mib": 31.32,
            "total_cpu_pct": 0.0
          }
        ],
        "memory_stat": {
          "read_at": "2026-10-18T04:14:22Z",
          "per_service": {
            "filebrowser": {
              "cgroup": "v2",
              "anon_mib": 30.09,
              "file_mib": 0.61,
              "active_file_mib": 0.0,
              "inactive_file_mib": 0.61,
              "shmem_mib": 0.0
            }
          },
          "read_lag_s": 0.0,
          "method": "docker exec <container> cat /sys/fs/cgroup/memory.stat (cgroup v1: /sys/fs/cgroup/memory/memory.stat); MiB; splits what docker stats shows as one number into anon (heap) and file cache; a field that is absent was not printed by the kernel or not readable (see reason)",
          "taken": "right after the idle window"
        }
      },
      "settle": {
        "settled": true,
        "mode": "detected",
        "settle_seconds_used": 173.6,
        "settle_started_after_healthy_s": 1.5,
        "params": {
          "window_seconds": 60,
          "threshold_pct": 2.0,
          "threshold_min_mib": 10.0,
          "min_seconds": 120,
          "max_seconds": 600
        },
        "last_window": {
          "n": 30,
          "mean_mib": 31.47,
          "min_mib": 31.23,
          "max_mib": 31.68,
          "spread_mib": 0.45,
          "threshold_mib": 10.0
        },
        "rechecks": 0,
        "rule": "settled = over the last window_seconds the stack total varied (max - min) by less than max(threshold_pct of the window mean, threshold_min_mib); not before min_seconds, at the latest max_seconds, both counted from the end of the setup steps; the idle window must also be flat and agree with it. If max_seconds passes without settling, settled=false and the idle window is measured anyway."
      },
      "startup_peak": {
        "per_service_mem_mib": {
          "filebrowser": 43.7
        },
        "total_mem_mib": 43.7,
        "samples": 87,
        "note": "highest value across docker stats samples (about one every 2-3 s) from healthy until the stack settled; shorter spikes between samples are not seen"
      },
      "timeline": {
        "step_s": 10,
        "t0": "healthy",
        "offsets_s": [
          10,
          20,
          30,
          40,
          50,
          60,
          70,
          80,
          90,
          100,
          110,
          120,
          130,
          140,
          150,
          160,
          170,
          180,
          190,
          200,
          210
        ],
        "total_mem_mib": [
          43.4,
          43.4,
          43.3,
          43.5,
          43.5,
          43.4,
          43.4,
          43.5,
          43.4,
          43.4,
          43.6,
          38.6,
          31.5,
          31.5,
          31.5,
          31.4,
          31.5,
          31.4,
          31.5,
          31.4,
          31.3
        ],
        "per_service_mem_mib": {
          "filebrowser": [
            43.4,
            43.4,
            43.3,
            43.5,
            43.5,
            43.4,
            43.4,
            43.5,
            43.4,
            43.4,
            43.6,
            38.6,
            31.5,
            31.5,
            31.5,
            31.4,
            31.5,
            31.4,
            31.5,
            31.4,
            31.3
          ]
        }
      },
      "load": {
        "per_service": {
          "filebrowser": {
            "samples": 3,
            "mem_mean_mib": 47.91,
            "mem_max_mib": 48.12,
            "cpu_mean_pct": 15.68,
            "cpu_max_pct": 47.03
          }
        },
        "total": {
          "samples": 3,
          "dropped_for_total": 0,
          "mem_mean_mib": 47.91,
          "mem_max_mib": 48.12,
          "cpu_mean_pct": 15.68,
          "cpu_max_pct": 47.03
        },
        "description": "The same load as the Nextcloud, Seafile, ownCloud and File Browser tests, through FileBrowser Quantum's HTTP API. One user (the admin), over plain HTTP on the Compose network, one request at a time, each on a new connection. A Python script generates the same 103 random files (100 small ones of 1 KB to 1 MB, about 50 MB together, and three of 50 MB; same seed, same names, same order), creates a folder and uploads the files (POST /api/resources, the documented \"create or upload a resource\" call: one POST of the raw body per file, whole file, not chunked), lists the folder with one GET (GET /api/resources), and downloads five files (three small, two large; GET /api/resources/download) and checks their SHA-256. About 200 MB in total. The web interface cuts large uploads into chunks; this test sends each file whole, so it measures one request per file as the other apps do. No browser, no thumbnails or previews, no sharing, no search, no WebDAV.",
        "duration_s": 2.6,
        "window": "from LAB_MARK load_start (or step start) until 2 s after the step ended",
        "reported_by_script": {
          "api": "filebrowser quantum http api (POST /api/resources to create the folder and upload, GET /api/resources to list, GET /api/resources/download), whole-file upload (not chunked)",
          "files_uploaded": 103,
          "small_files": 100,
          "large_files": 3,
          "bytes_uploaded": 194456599,
          "upload_seconds": 0.4,
          "listing_entries": 103,
          "listing_seconds": 0.0,
          "listing_sizes_exact": false,
          "listing_bytes_reported": 194654208,
          "files_downloaded": 5,
          "bytes_downloaded": 101451451,
          "download_seconds": 0.1,
          "downloads_sha256_match": true,
          "requests": {
            "create_folder": {
              "sent": 1,
              "ok": 1,
              "statuses": {
                "200": 1
              }
            },
            "upload": {
              "sent": 103,
              "ok": 103,
              "statuses": {
                "200": 103
              }
            },
            "list": {
              "sent": 1,
              "ok": 1,
              "statuses": {
                "200": 1
              }
            },
            "download": {
              "sent": 5,
              "ok": 5,
              "statuses": {
                "200": 5
              }
            }
          },
          "requests_total": 110,
          "requests_failed": 0
        },
        "output_tail": [
          "generated 103 files (100 small, 3 large), 194.5 MB",
          "uploaded 103 of 103 files, 194.5 MB in 0.4s; statuses {'200': 103}",
          "GET dir HTTP 200: 103 files in 0.00s; names match the upload: True; sizes at least the file length: True; sizes identical: False",
          "downloaded 5 of 5 files, 101.5 MB in 0.1s"
        ],
        "series": [
          {
            "t_offset_s": 0.0,
            "total_mem_mib": 48.12,
            "total_cpu_pct": 47.03
          },
          {
            "t_offset_s": 2.0,
            "total_mem_mib": 47.8,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 4.0,
            "total_mem_mib": 47.8,
            "total_cpu_pct": 0.0
          }
        ],
        "series_start_offset_s": 1.0,
        "peak_note": "peak = highest value seen across docker stats samples (about one every 2-3 s); shorter spikes between samples are not seen",
        "peak_memory_stat": {
          "read_at": "2026-10-18T04:14:24Z",
          "per_service": {
            "filebrowser": {
              "cgroup": "v2",
              "anon_mib": 40.85,
              "file_mib": 186.27,
              "active_file_mib": 0.0,
              "inactive_file_mib": 186.27,
              "shmem_mib": 0.0
            }
          },
          "read_lag_s": 0.0,
          "series_index": 0,
          "sample_t_offset_s": 0.0,
          "total_mem_mib": 48.12
        }
      },
      "container_end_state": {
        "filebrowser": {
          "restart_count": 0,
          "oom_killed": false
        }
      },
      "teardown": {
        "done": true,
        "volumes_removed": true,
        "images_removed": false,
        "error": null
      },
      "warnings": [],
      "finished_at": "2026-10-18T04:14:28Z",
      "elapsed_seconds": 217.3
    },
    {
      "run": 2,
      "started_at": "2026-10-18T04:14:28Z",
      "host": {
        "label": "github-actions ubuntu-latest (2 vCPU, 8 GB)",
        "ci": {
          "runs_on": "ubuntu-latest",
          "runner_environment": "github-hosted",
          "runner_os": "Linux",
          "runner_arch": "X64",
          "image_os": "ubuntu24",
          "image_version": "20261012.334.1"
        },
        "cpu_model": "INTEL(R) XEON(R) PLATINUM 8573C",
        "cpu_model_note": null,
        "cores": 2,
        "mem_total_mib": 7937,
        "kernel": "6.17.0-1022-azure",
        "os": "Ubuntu 24.04.5 LTS",
        "arch": "x86_64",
        "oci_arch": "amd64",
        "docker_server_version": "28.0.4",
        "docker_client_version": "28.0.4",
        "compose_client_version": "2.38.2",
        "storage_driver": "overlay2",
        "containerd_image_store": false,
        "source": "docker info + throwaway container reading /proc/cpuinfo on the daemon host",
        "compose_note": "Compose runs on the client machine; Docker server fields are from the daemon host"
      },
      "date": "2026-10-18",
      "startup": {
        "seconds": 5.4,
        "ok": true,
        "checks": [
          {
            "type": "container",
            "ok": true,
            "ready_after_s": 5.4,
            "detail": "shb-filebrowser-quantum-filebrowser-1=running/healthy"
          }
        ],
        "up_command_seconds": 0.2,
        "definition": "wall clock from starting `docker compose up -d` until every health check passed; checks poll every 0.5 s from a throwaway container on the compose network, so resolution is about +/- 1 s"
      },
      "versions": {
        "filebrowser": "v2.0.1-stable"
      },
      "setup": [
        {
          "exit_code": 0,
          "duration_s": 0.5,
          "reported": {
            "login_ok": true,
            "root_files": 0,
            "root_folders": 0,
            "unauthenticated_api_status": 401
          },
          "output_tail": [
            "logged in as admin; source 'files' root has 0 files and 0 folders (0.00s); without a token the API answers HTTP 401"
          ],
          "description": "Check /health, check that the API refuses a request without a token, log in as the admin user (POST /api/auth/login) and list the empty root of the source (GET /api/resources), as the first visit of a user would."
        }
      ],
      "idle": {
        "per_service": {
          "filebrowser": {
            "samples": 16,
            "mem_mean_mib": 27.41,
            "mem_max_mib": 27.57,
            "cpu_mean_pct": 0.45,
            "cpu_max_pct": 2.4
          }
        },
        "total": {
          "samples": 16,
          "dropped_for_total": 0,
          "mem_mean_mib": 27.41,
          "mem_max_mib": 27.57,
          "cpu_mean_pct": 0.45,
          "cpu_max_pct": 2.4
        },
        "window_seconds": 30.3,
        "series": [
          {
            "t_offset_s": 0.0,
            "total_mem_mib": 27.32,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 2.0,
            "total_mem_mib": 27.24,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 4.0,
            "total_mem_mib": 27.24,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 6.1,
            "total_mem_mib": 27.55,
            "total_cpu_pct": 2.4
          },
          {
            "t_offset_s": 8.1,
            "total_mem_mib": 27.53,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 10.1,
            "total_mem_mib": 27.53,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 12.1,
            "total_mem_mib": 27.57,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 14.1,
            "total_mem_mib": 27.57,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 16.2,
            "total_mem_mib": 27.34,
            "total_cpu_pct": 2.4
          },
          {
            "t_offset_s": 18.2,
            "total_mem_mib": 27.34,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 20.2,
            "total_mem_mib": 27.34,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 22.2,
            "total_mem_mib": 27.39,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 24.2,
            "total_mem_mib": 27.39,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 26.2,
            "total_mem_mib": 27.42,
            "total_cpu_pct": 2.39
          },
          {
            "t_offset_s": 28.3,
            "total_mem_mib": 27.42,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 30.3,
            "total_mem_mib": 27.42,
            "total_cpu_pct": 0.0
          }
        ],
        "memory_stat": {
          "read_at": "2026-10-18T04:18:05Z",
          "per_service": {
            "filebrowser": {
              "cgroup": "v2",
              "anon_mib": 25.59,
              "file_mib": 0.57,
              "active_file_mib": 0.0,
              "inactive_file_mib": 0.57,
              "shmem_mib": 0.0
            }
          },
          "read_lag_s": 0.0,
          "method": "docker exec <container> cat /sys/fs/cgroup/memory.stat (cgroup v1: /sys/fs/cgroup/memory/memory.stat); MiB; splits what docker stats shows as one number into anon (heap) and file cache; a field that is absent was not printed by the kernel or not readable (see reason)",
          "taken": "right after the idle window"
        }
      },
      "settle": {
        "settled": true,
        "mode": "detected",
        "settle_seconds_used": 179.6,
        "settle_started_after_healthy_s": 1.5,
        "params": {
          "window_seconds": 60,
          "threshold_pct": 2.0,
          "threshold_min_mib": 10.0,
          "min_seconds": 120,
          "max_seconds": 600
        },
        "last_window": {
          "n": 30,
          "mean_mib": 27.35,
          "min_mib": 27.18,
          "max_mib": 27.57,
          "spread_mib": 0.39,
          "threshold_mib": 10.0
        },
        "rechecks": 0,
        "rule": "settled = over the last window_seconds the stack total varied (max - min) by less than max(threshold_pct of the window mean, threshold_min_mib); not before min_seconds, at the latest max_seconds, both counted from the end of the setup steps; the idle window must also be flat and agree with it. If max_seconds passes without settling, settled=false and the idle window is measured anyway."
      },
      "startup_peak": {
        "per_service_mem_mib": {
          "filebrowser": 39.62
        },
        "total_mem_mib": 39.62,
        "samples": 90,
        "note": "highest value across docker stats samples (about one every 2-3 s) from healthy until the stack settled; shorter spikes between samples are not seen"
      },
      "timeline": {
        "step_s": 10,
        "t0": "healthy",
        "offsets_s": [
          10,
          20,
          30,
          40,
          50,
          60,
          70,
          80,
          90,
          100,
          110,
          120,
          130,
          140,
          150,
          160,
          170,
          180,
          190,
          200,
          210,
          220
        ],
        "total_mem_mib": [
          39.3,
          39.4,
          39.2,
          39.4,
          39.4,
          39.4,
          39.4,
          39.4,
          39.3,
          39.3,
          39.3,
          39.5,
          29.8,
          27.3,
          27.4,
          27.4,
          27.4,
          27.3,
          27.4,
          27.5,
          27.4,
          27.4
        ],
        "per_service_mem_mib": {
          "filebrowser": [
            39.3,
            39.4,
            39.2,
            39.4,
            39.4,
            39.4,
            39.4,
            39.4,
            39.3,
            39.3,
            39.3,
            39.5,
            29.8,
            27.3,
            27.4,
            27.4,
            27.4,
            27.3,
            27.4,
            27.5,
            27.4,
            27.4
          ]
        }
      },
      "load": {
        "per_service": {
          "filebrowser": {
            "samples": 3,
            "mem_mean_mib": 41.69,
            "mem_max_mib": 41.89,
            "cpu_mean_pct": 15.39,
            "cpu_max_pct": 43.76
          }
        },
        "total": {
          "samples": 3,
          "dropped_for_total": 0,
          "mem_mean_mib": 41.69,
          "mem_max_mib": 41.89,
          "cpu_mean_pct": 15.39,
          "cpu_max_pct": 43.76
        },
        "description": "The same load as the Nextcloud, Seafile, ownCloud and File Browser tests, through FileBrowser Quantum's HTTP API. One user (the admin), over plain HTTP on the Compose network, one request at a time, each on a new connection. A Python script generates the same 103 random files (100 small ones of 1 KB to 1 MB, about 50 MB together, and three of 50 MB; same seed, same names, same order), creates a folder and uploads the files (POST /api/resources, the documented \"create or upload a resource\" call: one POST of the raw body per file, whole file, not chunked), lists the folder with one GET (GET /api/resources), and downloads five files (three small, two large; GET /api/resources/download) and checks their SHA-256. About 200 MB in total. The web interface cuts large uploads into chunks; this test sends each file whole, so it measures one request per file as the other apps do. No browser, no thumbnails or previews, no sharing, no search, no WebDAV.",
        "duration_s": 2.2,
        "window": "from LAB_MARK load_start (or step start) until 2 s after the step ended",
        "reported_by_script": {
          "api": "filebrowser quantum http api (POST /api/resources to create the folder and upload, GET /api/resources to list, GET /api/resources/download), whole-file upload (not chunked)",
          "files_uploaded": 103,
          "small_files": 100,
          "large_files": 3,
          "bytes_uploaded": 194456599,
          "upload_seconds": 0.4,
          "listing_entries": 103,
          "listing_seconds": 0.0,
          "listing_sizes_exact": false,
          "listing_bytes_reported": 194654208,
          "files_downloaded": 5,
          "bytes_downloaded": 101451451,
          "download_seconds": 0.1,
          "downloads_sha256_match": true,
          "requests": {
            "create_folder": {
              "sent": 1,
              "ok": 1,
              "statuses": {
                "200": 1
              }
            },
            "upload": {
              "sent": 103,
              "ok": 103,
              "statuses": {
                "200": 103
              }
            },
            "list": {
              "sent": 1,
              "ok": 1,
              "statuses": {
                "200": 1
              }
            },
            "download": {
              "sent": 5,
              "ok": 5,
              "statuses": {
                "200": 5
              }
            }
          },
          "requests_total": 110,
          "requests_failed": 0
        },
        "output_tail": [
          "generated 103 files (100 small, 3 large), 194.5 MB",
          "uploaded 103 of 103 files, 194.5 MB in 0.4s; statuses {'200': 103}",
          "GET dir HTTP 200: 103 files in 0.00s; names match the upload: True; sizes at least the file length: True; sizes identical: False",
          "downloaded 5 of 5 files, 101.5 MB in 0.1s"
        ],
        "series": [
          {
            "t_offset_s": 0.0,
            "total_mem_mib": 41.68,
            "total_cpu_pct": 43.76
          },
          {
            "t_offset_s": 2.0,
            "total_mem_mib": 41.51,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 4.0,
            "total_mem_mib": 41.89,
            "total_cpu_pct": 2.42
          }
        ],
        "series_start_offset_s": 1.1,
        "peak_note": "peak = highest value seen across docker stats samples (about one every 2-3 s); shorter spikes between samples are not seen",
        "peak_memory_stat": {
          "read_at": "2026-10-18T04:18:11Z",
          "per_service": {
            "filebrowser": {
              "cgroup": "v2",
              "anon_mib": 34.19,
              "file_mib": 186.29,
              "active_file_mib": 0.0,
              "inactive_file_mib": 186.29,
              "shmem_mib": 0.0
            }
          },
          "read_lag_s": 0.0,
          "series_index": 2,
          "sample_t_offset_s": 4.0,
          "total_mem_mib": 41.89
        }
      },
      "container_end_state": {
        "filebrowser": {
          "restart_count": 0,
          "oom_killed": false
        }
      },
      "teardown": {
        "done": true,
        "volumes_removed": true,
        "images_removed": false,
        "error": null
      },
      "warnings": [],
      "finished_at": "2026-10-18T04:18:12Z",
      "elapsed_seconds": 223.6
    },
    {
      "run": 3,
      "started_at": "2026-10-18T04:18:12Z",
      "host": {
        "label": "github-actions ubuntu-latest (2 vCPU, 8 GB)",
        "ci": {
          "runs_on": "ubuntu-latest",
          "runner_environment": "github-hosted",
          "runner_os": "Linux",
          "runner_arch": "X64",
          "image_os": "ubuntu24",
          "image_version": "20261012.334.1"
        },
        "cpu_model": "INTEL(R) XEON(R) PLATINUM 8573C",
        "cpu_model_note": null,
        "cores": 2,
        "mem_total_mib": 7937,
        "kernel": "6.17.0-1022-azure",
        "os": "Ubuntu 24.04.5 LTS",
        "arch": "x86_64",
        "oci_arch": "amd64",
        "docker_server_version": "28.0.4",
        "docker_client_version": "28.0.4",
        "compose_client_version": "2.38.2",
        "storage_driver": "overlay2",
        "containerd_image_store": false,
        "source": "docker info + throwaway container reading /proc/cpuinfo on the daemon host",
        "compose_note": "Compose runs on the client machine; Docker server fields are from the daemon host"
      },
      "date": "2026-10-18",
      "startup": {
        "seconds": 5.4,
        "ok": true,
        "checks": [
          {
            "type": "container",
            "ok": true,
            "ready_after_s": 5.4,
            "detail": "shb-filebrowser-quantum-filebrowser-1=running/healthy"
          }
        ],
        "up_command_seconds": 0.2,
        "definition": "wall clock from starting `docker compose up -d` until every health check passed; checks poll every 0.5 s from a throwaway container on the compose network, so resolution is about +/- 1 s"
      },
      "versions": {
        "filebrowser": "v2.0.1-stable"
      },
      "setup": [
        {
          "exit_code": 0,
          "duration_s": 0.5,
          "reported": {
            "login_ok": true,
            "root_files": 0,
            "root_folders": 0,
            "unauthenticated_api_status": 401
          },
          "output_tail": [
            "logged in as admin; source 'files' root has 0 files and 0 folders (0.00s); without a token the API answers HTTP 401"
          ],
          "description": "Check /health, check that the API refuses a request without a token, log in as the admin user (POST /api/auth/login) and list the empty root of the source (GET /api/resources), as the first visit of a user would."
        }
      ],
      "idle": {
        "per_service": {
          "filebrowser": {
            "samples": 16,
            "mem_mean_mib": 29.29,
            "mem_max_mib": 29.63,
            "cpu_mean_pct": 0.46,
            "cpu_max_pct": 2.46
          }
        },
        "total": {
          "samples": 16,
          "dropped_for_total": 0,
          "mem_mean_mib": 29.29,
          "mem_max_mib": 29.63,
          "cpu_mean_pct": 0.46,
          "cpu_max_pct": 2.46
        },
        "window_seconds": 30.3,
        "series": [
          {
            "t_offset_s": 0.0,
            "total_mem_mib": 29.41,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 2.0,
            "total_mem_mib": 29.21,
            "total_cpu_pct": 2.44
          },
          {
            "t_offset_s": 4.0,
            "total_mem_mib": 29.19,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 6.1,
            "total_mem_mib": 29.18,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 8.1,
            "total_mem_mib": 29.49,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 10.1,
            "total_mem_mib": 29.34,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 12.1,
            "total_mem_mib": 29.41,
            "total_cpu_pct": 2.43
          },
          {
            "t_offset_s": 14.1,
            "total_mem_mib": 29.21,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 16.1,
            "total_mem_mib": 29.21,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 18.2,
            "total_mem_mib": 29.23,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 20.2,
            "total_mem_mib": 29.23,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 22.2,
            "total_mem_mib": 29.63,
            "total_cpu_pct": 2.46
          },
          {
            "t_offset_s": 24.2,
            "total_mem_mib": 29.3,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 26.2,
            "total_mem_mib": 29.18,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 28.3,
            "total_mem_mib": 29.27,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 30.3,
            "total_mem_mib": 29.22,
            "total_cpu_pct": 0.0
          }
        ],
        "memory_stat": {
          "read_at": "2026-10-18T04:21:43Z",
          "per_service": {
            "filebrowser": {
              "cgroup": "v2",
              "anon_mib": 26.12,
              "file_mib": 0.57,
              "active_file_mib": 0.0,
              "inactive_file_mib": 0.57,
              "shmem_mib": 0.0
            }
          },
          "read_lag_s": 0.0,
          "method": "docker exec <container> cat /sys/fs/cgroup/memory.stat (cgroup v1: /sys/fs/cgroup/memory/memory.stat); MiB; splits what docker stats shows as one number into anon (heap) and file cache; a field that is absent was not printed by the kernel or not readable (see reason)",
          "taken": "right after the idle window"
        }
      },
      "settle": {
        "settled": true,
        "mode": "detected",
        "settle_seconds_used": 173.6,
        "settle_started_after_healthy_s": 1.5,
        "params": {
          "window_seconds": 60,
          "threshold_pct": 2.0,
          "threshold_min_mib": 10.0,
          "min_seconds": 120,
          "max_seconds": 600
        },
        "last_window": {
          "n": 30,
          "mean_mib": 29.34,
          "min_mib": 29.18,
          "max_mib": 29.55,
          "spread_mib": 0.37,
          "threshold_mib": 10.0
        },
        "rechecks": 0,
        "rule": "settled = over the last window_seconds the stack total varied (max - min) by less than max(threshold_pct of the window mean, threshold_min_mib); not before min_seconds, at the latest max_seconds, both counted from the end of the setup steps; the idle window must also be flat and agree with it. If max_seconds passes without settling, settled=false and the idle window is measured anyway."
      },
      "startup_peak": {
        "per_service_mem_mib": {
          "filebrowser": 39.65
        },
        "total_mem_mib": 39.65,
        "samples": 87,
        "note": "highest value across docker stats samples (about one every 2-3 s) from healthy until the stack settled; shorter spikes between samples are not seen"
      },
      "timeline": {
        "step_s": 10,
        "t0": "healthy",
        "offsets_s": [
          10,
          20,
          30,
          40,
          50,
          60,
          70,
          80,
          90,
          100,
          110,
          120,
          130,
          140,
          150,
          160,
          170,
          180,
          190,
          200,
          210
        ],
        "total_mem_mib": [
          39.3,
          39.5,
          39.5,
          39.3,
          39.3,
          39.4,
          39.5,
          39.5,
          39.4,
          39.5,
          39.3,
          35.3,
          29.4,
          29.3,
          29.3,
          29.3,
          29.3,
          29.3,
          29.3,
          29.3,
          29.2
        ],
        "per_service_mem_mib": {
          "filebrowser": [
            39.3,
            39.5,
            39.5,
            39.3,
            39.3,
            39.4,
            39.5,
            39.5,
            39.4,
            39.5,
            39.3,
            35.3,
            29.4,
            29.3,
            29.3,
            29.3,
            29.3,
            29.3,
            29.3,
            29.3,
            29.2
          ]
        }
      },
      "load": {
        "per_service": {
          "filebrowser": {
            "samples": 3,
            "mem_mean_mib": 43.7,
            "mem_max_mib": 43.97,
            "cpu_mean_pct": 15.64,
            "cpu_max_pct": 46.93
          }
        },
        "total": {
          "samples": 3,
          "dropped_for_total": 0,
          "mem_mean_mib": 43.7,
          "mem_max_mib": 43.97,
          "cpu_mean_pct": 15.64,
          "cpu_max_pct": 46.93
        },
        "description": "The same load as the Nextcloud, Seafile, ownCloud and File Browser tests, through FileBrowser Quantum's HTTP API. One user (the admin), over plain HTTP on the Compose network, one request at a time, each on a new connection. A Python script generates the same 103 random files (100 small ones of 1 KB to 1 MB, about 50 MB together, and three of 50 MB; same seed, same names, same order), creates a folder and uploads the files (POST /api/resources, the documented \"create or upload a resource\" call: one POST of the raw body per file, whole file, not chunked), lists the folder with one GET (GET /api/resources), and downloads five files (three small, two large; GET /api/resources/download) and checks their SHA-256. About 200 MB in total. The web interface cuts large uploads into chunks; this test sends each file whole, so it measures one request per file as the other apps do. No browser, no thumbnails or previews, no sharing, no search, no WebDAV.",
        "duration_s": 2.2,
        "window": "from LAB_MARK load_start (or step start) until 2 s after the step ended",
        "reported_by_script": {
          "api": "filebrowser quantum http api (POST /api/resources to create the folder and upload, GET /api/resources to list, GET /api/resources/download), whole-file upload (not chunked)",
          "files_uploaded": 103,
          "small_files": 100,
          "large_files": 3,
          "bytes_uploaded": 194456599,
          "upload_seconds": 0.4,
          "listing_entries": 103,
          "listing_seconds": 0.0,
          "listing_sizes_exact": false,
          "listing_bytes_reported": 194654208,
          "files_downloaded": 5,
          "bytes_downloaded": 101451451,
          "download_seconds": 0.1,
          "downloads_sha256_match": true,
          "requests": {
            "create_folder": {
              "sent": 1,
              "ok": 1,
              "statuses": {
                "200": 1
              }
            },
            "upload": {
              "sent": 103,
              "ok": 103,
              "statuses": {
                "200": 103
              }
            },
            "list": {
              "sent": 1,
              "ok": 1,
              "statuses": {
                "200": 1
              }
            },
            "download": {
              "sent": 5,
              "ok": 5,
              "statuses": {
                "200": 5
              }
            }
          },
          "requests_total": 110,
          "requests_failed": 0
        },
        "output_tail": [
          "generated 103 files (100 small, 3 large), 194.5 MB",
          "uploaded 103 of 103 files, 194.5 MB in 0.4s; statuses {'200': 103}",
          "GET dir HTTP 200: 103 files in 0.00s; names match the upload: True; sizes at least the file length: True; sizes identical: False",
          "downloaded 5 of 5 files, 101.5 MB in 0.1s"
        ],
        "series": [
          {
            "t_offset_s": 0.0,
            "total_mem_mib": 43.97,
            "total_cpu_pct": 46.93
          },
          {
            "t_offset_s": 2.0,
            "total_mem_mib": 43.65,
            "total_cpu_pct": 0.0
          },
          {
            "t_offset_s": 4.0,
            "total_mem_mib": 43.48,
            "total_cpu_pct": 0.0
          }
        ],
        "series_start_offset_s": 1.0,
        "peak_note": "peak = highest value seen across docker stats samples (about one every 2-3 s); shorter spikes between samples are not seen",
        "peak_memory_stat": {
          "read_at": "2026-10-18T04:21:45Z",
          "per_service": {
            "filebrowser": {
              "cgroup": "v2",
              "anon_mib": 34.71,
              "file_mib": 186.23,
              "active_file_mib": 0.0,
              "inactive_file_mib": 186.23,
              "shmem_mib": 0.0
            }
          },
          "read_lag_s": 0.0,
          "series_index": 0,
          "sample_t_offset_s": 0.0,
          "total_mem_mib": 43.97
        }
      },
      "container_end_state": {
        "filebrowser": {
          "restart_count": 0,
          "oom_killed": false
        }
      },
      "teardown": {
        "done": true,
        "volumes_removed": true,
        "images_removed": false,
        "error": null
      },
      "warnings": [],
      "finished_at": "2026-10-18T04:21:49Z",
      "elapsed_seconds": 217.6
    }
  ],
  "load_defined": true,
  "notes": [
    "Host: a GitHub Actions runner (ubuntu-latest, x86_64, 2 vCPU, 8 GB RAM; the CPU model varies between runners and each run records its own). Numbers are valid for that host only.",
    "Version and channel: FileBrowser Quantum 2.0.1, the STABLE channel (Docker Hub gtstef/filebrowser:2.0.1-stable, also `stable`, `latest`, `2-stable`, `2.0-stable`; GitHub release v2.0.1-stable of 13 Oct 2026, marked Latest; it is a security release for a path-escape bug with `..` in a user name and a session-token collision). The project's other channel is BETA (2.1.x, tags `beta`, `2.1-beta`; v2.1.2-beta of 13 Oct 2026), which gets features first and, in the project's words, may have unexpected issues; it is not tested here. The image is the default one, with ffmpeg and document preview (about 60 MB compressed per the docs); the `-slim` variant (about 15 MB) is not tested. See lab/notes/filebrowser-quantum-2026-10-18.md for the evidence.",
    "Not the same program as File Browser 2.63.23 (lab app `filebrowser`): Quantum is a fork that was rewritten. It has its own API (/api/resources with source and path parameters, a bearer token), a YAML config file and a SQLite database, and v2 cannot simply replace a v1 or File Browser install (a one-time migration reads the old database). Do not compare the two apps' numbers as one program.",
    "Config: one source, the directory /home/filebrowser/data/files, named `files`, written as `config.yaml` inline in the compose file (Compose `configs`). The admin password is the environment variable FILEBROWSER_ADMIN_PASSWORD (plain text, not a hash, unlike File Browser). One named volume holds config, SQLite database, cache and the served folder. The docs bind-mount a folder you own at /folder instead; a second named volume would belong to root and Quantum (UID 1000) could not write into it, and Quantum does not create a missing source folder, so the container's entrypoint runs `mkdir -p` first and then `exec ./filebrowser`. The binary, the user and the data layout are the image's own.",
    "Indexing: Quantum indexes every source into a SQLite index in the background (folder sizes, search, quotas). The first pass runs at start-up, in the first second, and costs nothing measurable on the empty source, so it is part of start-up and idle does not wait for it. Afterwards the app re-scans on a schedule the docs call adaptive (one full scan, then four quick scans, at intervals from 5 minutes to 12 hours that lengthen while nothing changes). In two sandbox probes on a fresh stack the first scheduled scan was 12 min 51 s and 17 min 40 s after the start (a round wall-clock time), longer than a lab run (about 3 minutes from start to the end of the load), so the idle window and the load window contain no scan and no `periodic:` rule is used. A probe that kept a stack for 15 minutes saw one scan, after the load, lift memory by about 4.5 MiB (21.7 to 26.4 MiB) with 103 files. The slot rule is not documented and only two samples were taken: if a run's `idle` or `peak` looks higher than the others, a scan is a suspect. Not tested: indexing a large tree (the docs' own figures are about 50 MB for 20,000 items, 150 MB for 100,000, 300 MB for 1,000,000), so a reader with a big folder should expect more RAM than the idle figure. See lab/notes/filebrowser-quantum-2026-10-18.md.",
    "Measured: idle RAM and CPU after the first start with one user and an empty source; RAM and CPU while the load of load.description runs (a few seconds); image size; start-up time. Not measured: the web interface or a browser, chunked uploads, thumbnails and previews (generated on demand when a folder is viewed in the web interface; the API load never asks for one), the search, sharing links, WebDAV, the other login methods (OIDC, LDAP, JWT, proxy, passkeys, TOTP), multiple users and access rules, OnlyOffice, a reverse proxy, desktop or mobile sync (Quantum has no sync client; it is a file manager, not a sync tool), the beta channel, migration from File Browser.",
    "Equivalence with the Nextcloud test: same 103 files (same generator and seed), same order, one request at a time, one user, plain HTTP, 5 downloads with a SHA-256 check. Differences that come from the product: no address requests, the login token is a header (Authorization: Bearer), and the folder listing returns files and folders apart, so `listing_entries` is 103. Quantum reports sizes in a listing as disk usage (4 KiB blocks) unless `useLogicalSize: true` is set, so the listing check needs the same names and a size at least the file length (`listing_sizes_exact` says whether they were identical, `listing_bytes_reported` is the total it reported).",
    "The load script reports every request kind with the HTTP statuses it got (`requests` in the load result); any failed request fails the run.",
    "The app checks for updates at start (server.disableUpdateCheck is false by default) and the default config was left as it is. The login route is rate limited by default; the load logs in once."
  ],
  "warnings": [],
  "files": {
    "compose": "filebrowser-quantum.compose.yaml",
    "env": "filebrowser-quantum.env"
  },
  "definitions": {
    "memory": "cgroup working set as reported by `docker stats` (usage minus inactive file cache), MiB = 2^20 bytes",
    "cpu": "percent of ONE core as reported by `docker stats` (4 busy cores = 400)",
    "total": "stats over the sum of all containers at the same instant",
    "sample_interval": "docker stats --no-stream takes about 1-2 s per call, so samples are 2-3 s apart",
    "runs": "each run is a full fresh cycle (up, health, setup, settle, idle, load, down -v); the published figure is the median over the runs, shown with the min-max range; see summary.rule"
  }
}
