[{"data":1,"prerenderedAt":1751},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Freleasing":143,"\u002Fdocs\u002Freleasing-surround":1747},[4],{"title":5,"path":6,"stem":7,"children":8,"page":32},"Docs","\u002Fdocs","docs",[9,33,58,79,112,117],{"title":10,"path":11,"stem":12,"children":13,"page":32},"Getting Started","\u002Fdocs\u002Fgetting-started","docs\u002Fgetting-started",[14,18,23,28],{"title":10,"path":15,"stem":16,"order":17},"\u002Fdocs\u002Fgetting-started\u002F_dir","docs\u002Fgetting-started\u002F_dir",1,{"title":19,"path":20,"stem":21,"order":22},"Configuration Reference","\u002Fdocs\u002Fgetting-started\u002Fconfiguration","docs\u002Fgetting-started\u002Fconfiguration",2,{"title":24,"path":25,"stem":26,"order":27},"Deployment Guide","\u002Fdocs\u002Fgetting-started\u002Fdeployment","docs\u002Fgetting-started\u002Fdeployment",3,{"title":29,"path":30,"stem":31,"order":17},"Quick Start","\u002Fdocs\u002Fgetting-started\u002Fquick-start","docs\u002Fgetting-started\u002Fquick-start",false,{"title":34,"path":35,"stem":36,"children":37,"page":32},"Guides","\u002Fdocs\u002Fguides","docs\u002Fguides",[38,41,45,49,54],{"title":34,"path":39,"stem":40,"order":22},"\u002Fdocs\u002Fguides\u002F_dir","docs\u002Fguides\u002F_dir",{"title":42,"path":43,"stem":44,"order":22},"Notifications","\u002Fdocs\u002Fguides\u002Fnotifications","docs\u002Fguides\u002Fnotifications",{"title":46,"path":47,"stem":48,"order":17},"Scoring Algorithm","\u002Fdocs\u002Fguides\u002Fscoring","docs\u002Fguides\u002Fscoring",{"title":50,"path":51,"stem":52,"order":53},"Sunset Mode","\u002Fdocs\u002Fguides\u002Fsunset-mode","docs\u002Fguides\u002Fsunset-mode",4,{"title":55,"path":56,"stem":57,"order":27},"Troubleshooting","\u002Fdocs\u002Fguides\u002Ftroubleshooting","docs\u002Fguides\u002Ftroubleshooting",{"title":59,"path":60,"stem":61,"children":62,"page":32},"Project","\u002Fdocs\u002Fproject","docs\u002Fproject",[63,67,71,75],{"title":59,"path":64,"stem":65,"order":66},"\u002Fdocs\u002Fproject\u002F_dir","docs\u002Fproject\u002F_dir",6,{"title":68,"path":69,"stem":70,"order":27},"Changelog","\u002Fdocs\u002Fproject\u002Fchangelog","docs\u002Fproject\u002Fchangelog",{"title":72,"path":73,"stem":74,"order":17},"Contributing","\u002Fdocs\u002Fproject\u002Fcontributing","docs\u002Fproject\u002Fcontributing",{"title":76,"path":77,"stem":78,"order":22},"Contributors","\u002Fdocs\u002Fproject\u002Fcontributors","docs\u002Fproject\u002Fcontributors",{"title":80,"path":81,"stem":82,"children":83,"page":32},"Reference","\u002Fdocs\u002Freference","docs\u002Freference",[84,87,108],{"title":80,"path":85,"stem":86,"order":27},"\u002Fdocs\u002Freference\u002F_dir","docs\u002Freference\u002F_dir",{"title":88,"path":89,"stem":90,"children":91,"page":32},"Api","\u002Fdocs\u002Freference\u002Fapi","docs\u002Freference\u002Fapi",[92,96,100,104],{"title":93,"path":94,"stem":95,"order":22},"API Reference","\u002Fdocs\u002Freference\u002Fapi\u002F_dir","docs\u002Freference\u002Fapi\u002F_dir",{"title":97,"path":98,"stem":99,"order":22},"API Examples","\u002Fdocs\u002Freference\u002Fapi\u002Fexamples","docs\u002Freference\u002Fapi\u002Fexamples",{"title":101,"path":102,"stem":103,"order":53},"API Versioning & Stability Guarantees","\u002Fdocs\u002Freference\u002Fapi\u002Fversioning","docs\u002Freference\u002Fapi\u002Fversioning",{"title":105,"path":106,"stem":107,"order":27},"Common Workflows","\u002Fdocs\u002Freference\u002Fapi\u002Fworkflows","docs\u002Freference\u002Fapi\u002Fworkflows",{"title":109,"path":110,"stem":111,"order":17},"Architecture","\u002Fdocs\u002Freference\u002Farchitecture","docs\u002Freference\u002Farchitecture",{"title":113,"path":114,"stem":115,"order":116},"Release Workflow","\u002Fdocs\u002Freleasing","docs\u002Freleasing",5,{"title":118,"path":119,"stem":120,"children":121,"order":17},"Security Policy","\u002Fdocs\u002Fsecurity","docs\u002Fsecurity\u002Findex",[122,123,127,131,134,137,140],{"title":118,"path":119,"stem":120,"order":17},{"title":124,"path":125,"stem":126,"order":53},"Security","\u002Fdocs\u002Fsecurity\u002F_dir","docs\u002Fsecurity\u002F_dir",{"title":128,"path":129,"stem":130,"order":22},"OWASP ZAP API Scan — Baseline Report","\u002Fdocs\u002Fsecurity\u002Fzap-baseline-20260310","docs\u002Fsecurity\u002Fzap-baseline-20260310",{"title":128,"path":132,"stem":133,"order":27},"\u002Fdocs\u002Fsecurity\u002Fzap-baseline-20260316","docs\u002Fsecurity\u002Fzap-baseline-20260316",{"title":128,"path":135,"stem":136,"order":53},"\u002Fdocs\u002Fsecurity\u002Fzap-baseline-20260323","docs\u002Fsecurity\u002Fzap-baseline-20260323",{"title":128,"path":138,"stem":139,"order":116},"\u002Fdocs\u002Fsecurity\u002Fzap-baseline-20260324","docs\u002Fsecurity\u002Fzap-baseline-20260324",{"title":128,"path":141,"stem":142},"\u002Fdocs\u002Fsecurity\u002Fzap-baseline-20260406","docs\u002Fsecurity\u002Fzap-baseline-20260406",{"id":144,"title":113,"body":145,"description":1740,"extension":1741,"links":1742,"meta":1743,"navigation":1744,"path":114,"seo":1745,"stem":115,"__hash__":1746},"docs\u002Fdocs\u002Freleasing.md",{"type":146,"value":147,"toc":1715},"minimark",[148,178,183,188,196,249,253,256,291,294,298,596,600,607,622,629,656,659,666,812,816,819,866,870,873,921,927,931,941,1015,1019,1022,1029,1236,1242,1247,1342,1346,1349,1401,1405,1408,1453,1467,1471,1489,1593,1603,1606,1614,1618,1621,1663,1706,1712],[149,150,151,152,159,160,165,166,171,172,177],"p",{},"Capacitarr uses a tag-triggered release pipeline powered by ",[153,154,158],"a",{"href":155,"rel":156},"https:\u002F\u002Fgit-cliff.org\u002F",[157],"nofollow","git-cliff",", ",[153,161,164],{"href":162,"rel":163},"https:\u002F\u002Fgoreleaser.com\u002F",[157],"GoReleaser",", and GitHub Actions. Releases follow ",[153,167,170],{"href":168,"rel":169},"https:\u002F\u002Fsemver.org\u002F",[157],"Semantic Versioning"," and are driven by ",[153,173,176],{"href":174,"rel":175},"https:\u002F\u002Fwww.conventionalcommits.org\u002F",[157],"Conventional Commits",".",[179,180,182],"h2",{"id":181},"how-it-works","How It Works",[184,185,187],"h3",{"id":186},"tag-triggered-releases","Tag-Triggered Releases",[149,189,190,191,195],{},"Releases are created when you push a ",[192,193,194],"code",{},"v*"," tag to the repository. The CI pipeline then:",[197,198,199,211,225,231,243],"ol",{},[200,201,202,206,207,210],"li",{},[203,204,205],"strong",{},"Extracts release notes"," — ",[192,208,209],{},"git cliff --latest --strip header"," generates notes for the tagged version",[200,212,213,216,217,220,221,224],{},[203,214,215],{},"Builds cross-compiled binaries"," — GoReleaser compiles ",[192,218,219],{},"linux\u002Famd64"," and ",[192,222,223],{},"linux\u002Farm64"," binaries with the frontend SPA embedded",[200,226,227,230],{},[203,228,229],{},"Creates a GitHub release"," — with binary archives and checksums attached as downloadable assets",[200,232,233,236,237,239,240,242],{},[203,234,235],{},"Pushes Docker images"," — multi-arch images (",[192,238,219],{}," + ",[192,241,223],{},") to GHCR and Docker Hub",[200,244,245,248],{},[203,246,247],{},"Sends release notification"," — posts to Discord via webhook",[184,250,252],{"id":251},"on-every-push-and-pr","On Every Push and PR",[149,254,255],{},"The standard CI pipeline runs on every push and pull request:",[257,258,259,268,274,285],"ul",{},[200,260,261,206,264,267],{},[203,262,263],{},"Lint",[192,265,266],{},"golangci-lint"," + ESLint",[200,269,270,273],{},[203,271,272],{},"Test"," — Go tests + frontend tests",[200,275,276,206,278,239,281,284],{},[203,277,124],{},[192,279,280],{},"govulncheck",[192,282,283],{},"pnpm audit"," + Trivy (filesystem + image) + Gitleaks + Semgrep",[200,286,287,290],{},[203,288,289],{},"Build"," — Docker multi-arch smoke test (build only, no push)",[179,292,113],{"id":293},"release-workflow",[184,295,297],{"id":296},"step-by-step","Step-by-Step",[299,300,305],"pre",{"className":301,"code":302,"language":303,"meta":304,"style":304},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# 1. Run the full CI pipeline locally (must pass before releasing)\nmake ci\n\n# 2. Determine the next version\ngit cliff --bumped-version                    # e.g., v0.2.0\n\n# 3. Generate the full changelog\ngit cliff --bump -o CHANGELOG.md\n\n# 4. Update package.json version (strip the 'v' prefix)\nVERSION=$(git cliff --bumped-version)\nSEMVER=${VERSION#v}\nnpm version \"$SEMVER\" --no-git-tag-version\ncd frontend && npm version \"$SEMVER\" --no-git-tag-version && cd ..\n\n# 5. Commit and tag\ngit add CHANGELOG.md package.json package-lock.json frontend\u002Fpackage.json\ngit commit -m \"chore(release): $VERSION\"\ngit tag \"$VERSION\"\n\n# 6. Push\ngit push origin main        # CI pipeline: lint\u002Ftest\u002Fbuild\u002Fsecurity\ngit push origin \"$VERSION\"  # Release pipeline: changelog + GoReleaser + Docker + Discord\n","bash","",[192,306,307,315,325,331,336,350,354,360,376,381,387,407,427,448,483,488,494,514,536,550,555,561,578],{"__ignoreMap":304},[308,309,311],"span",{"class":310,"line":17},"line",[308,312,314],{"class":313},"sHwdD","# 1. Run the full CI pipeline locally (must pass before releasing)\n",[308,316,317,321],{"class":310,"line":22},[308,318,320],{"class":319},"sBMFI","make",[308,322,324],{"class":323},"sfazB"," ci\n",[308,326,327],{"class":310,"line":27},[308,328,330],{"emptyLinePlaceholder":329},true,"\n",[308,332,333],{"class":310,"line":53},[308,334,335],{"class":313},"# 2. Determine the next version\n",[308,337,338,341,344,347],{"class":310,"line":116},[308,339,340],{"class":319},"git",[308,342,343],{"class":323}," cliff",[308,345,346],{"class":323}," --bumped-version",[308,348,349],{"class":313},"                    # e.g., v0.2.0\n",[308,351,352],{"class":310,"line":66},[308,353,330],{"emptyLinePlaceholder":329},[308,355,357],{"class":310,"line":356},7,[308,358,359],{"class":313},"# 3. Generate the full changelog\n",[308,361,363,365,367,370,373],{"class":310,"line":362},8,[308,364,340],{"class":319},[308,366,343],{"class":323},[308,368,369],{"class":323}," --bump",[308,371,372],{"class":323}," -o",[308,374,375],{"class":323}," CHANGELOG.md\n",[308,377,379],{"class":310,"line":378},9,[308,380,330],{"emptyLinePlaceholder":329},[308,382,384],{"class":310,"line":383},10,[308,385,386],{"class":313},"# 4. Update package.json version (strip the 'v' prefix)\n",[308,388,390,394,398,400,402,404],{"class":310,"line":389},11,[308,391,393],{"class":392},"sTEyZ","VERSION",[308,395,397],{"class":396},"sMK4o","=$(",[308,399,340],{"class":319},[308,401,343],{"class":323},[308,403,346],{"class":323},[308,405,406],{"class":396},")\n",[308,408,410,413,416,418,421,424],{"class":310,"line":409},12,[308,411,412],{"class":392},"SEMVER",[308,414,415],{"class":396},"=${",[308,417,393],{"class":392},[308,419,420],{"class":396},"#",[308,422,423],{"class":392},"v",[308,425,426],{"class":396},"}\n",[308,428,430,433,436,439,442,445],{"class":310,"line":429},13,[308,431,432],{"class":319},"npm",[308,434,435],{"class":323}," version",[308,437,438],{"class":396}," \"",[308,440,441],{"class":392},"$SEMVER",[308,443,444],{"class":396},"\"",[308,446,447],{"class":323}," --no-git-tag-version\n",[308,449,451,455,458,461,464,466,468,470,472,475,477,480],{"class":310,"line":450},14,[308,452,454],{"class":453},"s2Zo4","cd",[308,456,457],{"class":323}," frontend",[308,459,460],{"class":396}," &&",[308,462,463],{"class":319}," npm",[308,465,435],{"class":323},[308,467,438],{"class":396},[308,469,441],{"class":392},[308,471,444],{"class":396},[308,473,474],{"class":323}," --no-git-tag-version",[308,476,460],{"class":396},[308,478,479],{"class":453}," cd",[308,481,482],{"class":323}," ..\n",[308,484,486],{"class":310,"line":485},15,[308,487,330],{"emptyLinePlaceholder":329},[308,489,491],{"class":310,"line":490},16,[308,492,493],{"class":313},"# 5. Commit and tag\n",[308,495,497,499,502,505,508,511],{"class":310,"line":496},17,[308,498,340],{"class":319},[308,500,501],{"class":323}," add",[308,503,504],{"class":323}," CHANGELOG.md",[308,506,507],{"class":323}," package.json",[308,509,510],{"class":323}," package-lock.json",[308,512,513],{"class":323}," frontend\u002Fpackage.json\n",[308,515,517,519,522,525,527,530,533],{"class":310,"line":516},18,[308,518,340],{"class":319},[308,520,521],{"class":323}," commit",[308,523,524],{"class":323}," -m",[308,526,438],{"class":396},[308,528,529],{"class":323},"chore(release): ",[308,531,532],{"class":392},"$VERSION",[308,534,535],{"class":396},"\"\n",[308,537,539,541,544,546,548],{"class":310,"line":538},19,[308,540,340],{"class":319},[308,542,543],{"class":323}," tag",[308,545,438],{"class":396},[308,547,532],{"class":392},[308,549,535],{"class":396},[308,551,553],{"class":310,"line":552},20,[308,554,330],{"emptyLinePlaceholder":329},[308,556,558],{"class":310,"line":557},21,[308,559,560],{"class":313},"# 6. Push\n",[308,562,564,566,569,572,575],{"class":310,"line":563},22,[308,565,340],{"class":319},[308,567,568],{"class":323}," push",[308,570,571],{"class":323}," origin",[308,573,574],{"class":323}," main",[308,576,577],{"class":313},"        # CI pipeline: lint\u002Ftest\u002Fbuild\u002Fsecurity\n",[308,579,581,583,585,587,589,591,593],{"class":310,"line":580},23,[308,582,340],{"class":319},[308,584,568],{"class":323},[308,586,571],{"class":323},[308,588,438],{"class":396},[308,590,532],{"class":392},[308,592,444],{"class":396},[308,594,595],{"class":313},"  # Release pipeline: changelog + GoReleaser + Docker + Discord\n",[184,597,599],{"id":598},"convenience-script","Convenience Script",[149,601,602,603,606],{},"There is a convenience script in the root ",[192,604,605],{},"package.json",":",[299,608,610],{"className":301,"code":609,"language":303,"meta":304,"style":304},"npm run release\n",[192,611,612],{"__ignoreMap":304},[308,613,614,616,619],{"class":310,"line":17},[308,615,432],{"class":319},[308,617,618],{"class":323}," run",[308,620,621],{"class":323}," release\n",[149,623,624,625,628],{},"This runs the full CI pipeline (",[192,626,627],{},"make ci",") first, then performs the release flow (changelog generation, version bump, commit, and tag). If CI fails, the release is aborted. You still need to push afterward:",[299,630,632],{"className":301,"code":631,"language":303,"meta":304,"style":304},"git push origin main\ngit push origin vX.Y.Z\n",[192,633,634,645],{"__ignoreMap":304},[308,635,636,638,640,642],{"class":310,"line":17},[308,637,340],{"class":319},[308,639,568],{"class":323},[308,641,571],{"class":323},[308,643,644],{"class":323}," main\n",[308,646,647,649,651,653],{"class":310,"line":22},[308,648,340],{"class":319},[308,650,568],{"class":323},[308,652,571],{"class":323},[308,654,655],{"class":323}," vX.Y.Z\n",[179,657,170],{"id":658},"semantic-versioning",[149,660,661,662,665],{},"Version numbers follow the ",[192,663,664],{},"MAJOR.MINOR.PATCH"," format. The version bump is determined automatically from commit messages:",[667,668,669,685],"table",{},[670,671,672],"thead",{},[673,674,675,679,682],"tr",{},[676,677,678],"th",{},"Commit Type",[676,680,681],{},"Version Bump",[676,683,684],{},"Example",[686,687,688,707,725,741,757,773,789],"tbody",{},[673,689,690,696,702],{},[691,692,693],"td",{},[192,694,695],{},"feat:",[691,697,698,701],{},[203,699,700],{},"MINOR"," (0.1.0 → 0.2.0)",[691,703,704],{},[192,705,706],{},"feat: add disk group filtering",[673,708,709,714,720],{},[691,710,711],{},[192,712,713],{},"fix:",[691,715,716,719],{},[203,717,718],{},"PATCH"," (0.1.0 → 0.1.1)",[691,721,722],{},[192,723,724],{},"fix: correct capacity calculation",[673,726,727,732,736],{},[691,728,729],{},[192,730,731],{},"docs:",[691,733,734,719],{},[203,735,718],{},[691,737,738],{},[192,739,740],{},"docs: update deployment guide",[673,742,743,748,752],{},[691,744,745],{},[192,746,747],{},"refactor:",[691,749,750,719],{},[203,751,718],{},[691,753,754],{},[192,755,756],{},"refactor: simplify poller logic",[673,758,759,764,768],{},[691,760,761],{},[192,762,763],{},"perf:",[691,765,766,719],{},[203,767,718],{},[691,769,770],{},[192,771,772],{},"perf: optimize database queries",[673,774,775,780,784],{},[691,776,777],{},[192,778,779],{},"chore:",[691,781,782,719],{},[203,783,718],{},[691,785,786],{},[192,787,788],{},"chore: update dependencies",[673,790,791,801,807],{},[691,792,793,794,797,798],{},"Any type with ",[192,795,796],{},"BREAKING CHANGE:"," footer or ",[192,799,800],{},"!",[691,802,803,806],{},[203,804,805],{},"MAJOR"," (0.1.0 → 1.0.0)",[691,808,809],{},[192,810,811],{},"feat!: redesign API endpoints",[184,813,815],{"id":814},"skipped-types","Skipped Types",[149,817,818],{},"The following commit types are excluded from the changelog but still count toward version determination:",[257,820,821,826,832,842,848,854,860],{},[200,822,823,825],{},[192,824,7],{}," — documentation changes",[200,827,828,831],{},[192,829,830],{},"refactor"," — code refactoring",[200,833,834,837,838,841],{},[192,835,836],{},"chore"," — maintenance tasks (including ",[192,839,840],{},"chore(release)",")",[200,843,844,847],{},[192,845,846],{},"test"," — test additions\u002Fchanges",[200,849,850,853],{},[192,851,852],{},"ci"," — CI\u002FCD pipeline changes",[200,855,856,859],{},[192,857,858],{},"style"," — code style\u002Fformatting changes",[200,861,862,865],{},[192,863,864],{},"build"," — build system changes",[179,867,869],{"id":868},"version-display","Version Display",[149,871,872],{},"Version information flows to the UI through two paths:",[197,874,875,903],{},[200,876,877,880,881,884,885,888,889,159,892,159,895,898,899,902],{},[203,878,879],{},"Backend (API version)"," — injected via ",[192,882,883],{},"-ldflags"," at build time into ",[192,886,887],{},"main.go"," variables (",[192,890,891],{},"version",[192,893,894],{},"commit",[192,896,897],{},"buildDate","). Exposed at ",[192,900,901],{},"GET \u002Fapi\u002Fv1\u002Fversion",". Displayed in the navbar as \"API vX.Y.Z\" and on the help page.",[200,904,905,908,909,912,913,916,917,920],{},[203,906,907],{},"Frontend (UI version)"," — read from ",[192,910,911],{},"frontend\u002Fpackage.json"," at build time via ",[192,914,915],{},"nuxt.config.ts"," → ",[192,918,919],{},"runtimeConfig.public.appVersion",". Displayed in the navbar as \"UI vX.Y.Z\" and on the help page.",[149,922,923,924,926],{},"Both ",[192,925,605],{}," files must be updated during the release prep step for the UI to display the correct version.",[179,928,930],{"id":929},"git-cliff-configuration","git-cliff Configuration",[149,932,933,934,940],{},"The changelog is configured in ",[153,935,937],{"href":936},"..\u002Fcliff.toml",[192,938,939],{},"cliff.toml"," at the project root. Key settings:",[257,942,943,949,984,1003,1009],{},[200,944,945,948],{},[203,946,947],{},"Conventional commits parsing"," — only conventional commit messages are included",[200,950,951,954,955],{},[203,952,953],{},"Commit grouping"," — user-facing commits are organized by type with emoji prefixes:\n",[257,956,957,963,969,975,978],{},[200,958,959,960,841],{},"🚀 Features (",[192,961,962],{},"feat",[200,964,965,966,841],{},"🐛 Bug Fixes (",[192,967,968],{},"fix",[200,970,971,972,841],{},"⚡ Performance (",[192,973,974],{},"perf",[200,976,977],{},"🛡️ Security (commits with \"security\" in the body)",[200,979,980,981,841],{},"◀️ Revert (",[192,982,983],{},"revert",[200,985,986,206,989,159,991,159,993,159,995,159,997,159,999,159,1001],{},[203,987,988],{},"Skipped from changelog",[192,990,7],{},[192,992,830],{},[192,994,836],{},[192,996,846],{},[192,998,852],{},[192,1000,858],{},[192,1002,864],{},[200,1004,1005,1008],{},[203,1006,1007],{},"Commit links"," — each changelog entry links to the commit on GitHub",[200,1010,1011,1014],{},[203,1012,1013],{},"Sorted oldest-first"," — commits within each group appear in chronological order",[179,1016,1018],{"id":1017},"ci-pipeline-jobs","CI Pipeline Jobs",[184,1020,252],{"id":1021},"on-every-push-and-pr-1",[149,1023,1024,1025,1028],{},"These jobs are defined in ",[192,1026,1027],{},".github\u002Fworkflows\u002Fci.yml",". Lint and test jobs run in parallel; build and security jobs run after lint+test pass.",[667,1030,1031,1047],{},[670,1032,1033],{},[673,1034,1035,1038,1041,1044],{},[676,1036,1037],{},"Job",[676,1039,1040],{},"Group",[676,1042,1043],{},"Tool \u002F Action",[676,1045,1046],{},"Purpose",[686,1048,1049,1068,1083,1098,1113,1130,1147,1168,1186,1202,1219],{},[673,1050,1051,1056,1059,1065],{},[691,1052,1053],{},[192,1054,1055],{},"lint-go",[691,1057,1058],{},"lint",[691,1060,1061,1064],{},[192,1062,1063],{},"golangci\u002Fgolangci-lint:v2.11.4"," Docker image",[691,1066,1067],{},"Go linting",[673,1069,1070,1075,1077,1080],{},[691,1071,1072],{},[192,1073,1074],{},"lint-frontend",[691,1076,1058],{},[691,1078,1079],{},"pnpm + Node.js 24",[691,1081,1082],{},"ESLint + Prettier + TypeScript typecheck",[673,1084,1085,1090,1092,1095],{},[691,1086,1087],{},[192,1088,1089],{},"test-go",[691,1091,846],{},[691,1093,1094],{},"Go 1.26",[691,1096,1097],{},"Go unit tests",[673,1099,1100,1105,1107,1110],{},[691,1101,1102],{},[192,1103,1104],{},"test-frontend",[691,1106,846],{},[691,1108,1109],{},"pnpm + Vitest",[691,1111,1112],{},"Frontend unit tests",[673,1114,1115,1120,1122,1127],{},[691,1116,1117],{},[192,1118,1119],{},"build-docker",[691,1121,864],{},[691,1123,1124],{},[192,1125,1126],{},"docker\u002Fsetup-buildx-action",[691,1128,1129],{},"Multi-arch Docker smoke test (no push)",[673,1131,1132,1137,1140,1144],{},[691,1133,1134],{},[192,1135,1136],{},"security-govulncheck",[691,1138,1139],{},"security",[691,1141,1142],{},[192,1143,280],{},[691,1145,1146],{},"Go vulnerability check",[673,1148,1149,1154,1156,1161],{},[691,1150,1151],{},[192,1152,1153],{},"security-pnpm-audit",[691,1155,1139],{},[691,1157,1158],{},[192,1159,1160],{},"pnpm audit --ignore-registry-errors",[691,1162,1163,1164,1167],{},"npm dependency audit (see ",[192,1165,1166],{},"SECURITY.md"," for registry 410 workaround)",[673,1169,1170,1175,1177,1183],{},[691,1171,1172],{},[192,1173,1174],{},"security-trivy",[691,1176,1139],{},[691,1178,1179,1182],{},[192,1180,1181],{},"aquasecurity\u002Ftrivy-action@v0.35.0"," (Trivy v0.69.3)",[691,1184,1185],{},"Filesystem CVE scan (backend + frontend)",[673,1187,1188,1193,1195,1199],{},[691,1189,1190],{},[192,1191,1192],{},"security-trivy-image",[691,1194,1139],{},[691,1196,1197,1182],{},[192,1198,1181],{},[691,1200,1201],{},"Docker image CVE scan",[673,1203,1204,1209,1211,1216],{},[691,1205,1206],{},[192,1207,1208],{},"security-gitleaks",[691,1210,1139],{},[691,1212,1213],{},[192,1214,1215],{},"gitleaks\u002Fgitleaks-action",[691,1217,1218],{},"Git secrets detection",[673,1220,1221,1226,1228,1233],{},[691,1222,1223],{},[192,1224,1225],{},"security-semgrep",[691,1227,1139],{},[691,1229,1230],{},[192,1231,1232],{},"semgrep\u002Fsemgrep:1.155.0",[691,1234,1235],{},"Static analysis (SAST)",[184,1237,1239,1240,841],{"id":1238},"on-tag-push-v","On Tag Push (",[192,1241,194],{},[149,1243,1024,1244,177],{},[192,1245,1246],{},".github\u002Fworkflows\u002Frelease.yml",[667,1248,1249,1259],{},[670,1250,1251],{},[673,1252,1253,1255,1257],{},[676,1254,1037],{},[676,1256,1043],{},[676,1258,1046],{},[686,1260,1261,1276,1292,1307,1325],{},[673,1262,1263,1268,1273],{},[691,1264,1265],{},[192,1266,1267],{},"changelog",[691,1269,1270],{},[192,1271,1272],{},"orhunp\u002Fgit-cliff:2.12.0",[691,1274,1275],{},"Extract release notes for the tagged version",[673,1277,1278,1283,1289],{},[691,1279,1280],{},[192,1281,1282],{},"goreleaser",[691,1284,1285,1288],{},[192,1286,1287],{},"goreleaser\u002Fgoreleaser-action@v6"," (GoReleaser v2.14.1)",[691,1290,1291],{},"Cross-compile binaries, create GitHub Release with assets",[673,1293,1294,1299,1304],{},[691,1295,1296],{},[192,1297,1298],{},"docker-build",[691,1300,1301,1303],{},[192,1302,1126],{}," + GHCR login",[691,1305,1306],{},"Build and push multi-arch Docker images to GHCR",[673,1308,1309,1314,1319],{},[691,1310,1311],{},[192,1312,1313],{},"docker-mirror-dockerhub",[691,1315,1316],{},[192,1317,1318],{},"crane copy",[691,1320,1321,1322,841],{},"Mirror from GHCR to Docker Hub (",[192,1323,1324],{},"continue-on-error",[673,1326,1327,1332,1337],{},[691,1328,1329],{},[192,1330,1331],{},"discord-notify",[691,1333,1334],{},[192,1335,1336],{},"scripts\u002Fdiscord-release-notify.sh",[691,1338,1339,1340,841],{},"Send release notification to Discord (",[192,1341,1324],{},[179,1343,1345],{"id":1344},"release-artifacts","Release Artifacts",[149,1347,1348],{},"Each release produces:",[667,1350,1351,1361],{},[670,1352,1353],{},[673,1354,1355,1358],{},[676,1356,1357],{},"Artifact",[676,1359,1360],{},"Description",[686,1362,1363,1373,1383,1393],{},[673,1364,1365,1370],{},[691,1366,1367],{},[192,1368,1369],{},"capacitarr_X.Y.Z_linux_amd64.tar.gz",[691,1371,1372],{},"Linux x86_64 binary + README + LICENSE + CHANGELOG",[673,1374,1375,1380],{},[691,1376,1377],{},[192,1378,1379],{},"capacitarr_X.Y.Z_linux_arm64.tar.gz",[691,1381,1382],{},"Linux ARM64 binary + README + LICENSE + CHANGELOG",[673,1384,1385,1390],{},[691,1386,1387],{},[192,1388,1389],{},"checksums.txt",[691,1391,1392],{},"SHA-256 checksums for all archives",[673,1394,1395,1398],{},[691,1396,1397],{},"Docker image (multi-arch)",[691,1399,1400],{},"Published to GHCR and Docker Hub (see below)",[184,1402,1404],{"id":1403},"docker-registries","Docker Registries",[149,1406,1407],{},"Docker images are published to two registries using a build-then-mirror pipeline:",[667,1409,1410,1423],{},[670,1411,1412],{},[673,1413,1414,1417,1420],{},[676,1415,1416],{},"Registry",[676,1418,1419],{},"Image Path",[676,1421,1422],{},"Role",[686,1424,1425,1438],{},[673,1426,1427,1430,1435],{},[691,1428,1429],{},"GHCR",[691,1431,1432],{},[192,1433,1434],{},"ghcr.io\u002Fghent\u002Fcapacitarr",[691,1436,1437],{},"Source of truth (built + pushed first)",[673,1439,1440,1443,1448],{},[691,1441,1442],{},"Docker Hub",[691,1444,1445],{},[192,1446,1447],{},"ghentstarshadow\u002Fcapacitarr",[691,1449,1450,1451],{},"Mirrored via ",[192,1452,1318],{},[149,1454,1455,1456,1462,1463,1466],{},"The build job pushes to GHCR. A mirror job then uses ",[153,1457,1460],{"href":1458,"rel":1459},"https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgo-containerregistry\u002Ftree\u002Fmain\u002Fcmd\u002Fcrane",[157],[192,1461,1318],{}," to replicate the multi-arch manifest to Docker Hub. The mirror job has ",[192,1464,1465],{},"continue-on-error: true"," — if Docker Hub is down, the workflow shows a warning but does not fail.",[184,1468,1470],{"id":1469},"docker-image-tags","Docker Image Tags",[149,1472,1473,1474,1477,1478,159,1481,1484,1485,1488],{},"Every release is tagged with the exact version and ",[192,1475,1476],{},":latest",". Pre-release channels (alpha, beta) get a rolling channel tag. Stable releases get ",[192,1479,1480],{},":stable",[192,1482,1483],{},":MAJOR",", and ",[192,1486,1487],{},":MINOR"," convenience tags:",[667,1490,1491,1504],{},[670,1492,1493],{},[673,1494,1495,1498,1501],{},[676,1496,1497],{},"Tag",[676,1499,1500],{},"Applied When",[676,1502,1503],{},"Meaning",[686,1505,1506,1523,1534,1550,1566,1578],{},[673,1507,1508,1517,1520],{},[691,1509,1510,1513,1514],{},[192,1511,1512],{},":1.0.0"," or ",[192,1515,1516],{},":1.0.0-beta",[691,1518,1519],{},"Every release",[691,1521,1522],{},"Immutable, pinned to exact version",[673,1524,1525,1529,1531],{},[691,1526,1527],{},[192,1528,1476],{},[691,1530,1519],{},[691,1532,1533],{},"Most recently built image, may include pre-releases",[673,1535,1536,1541,1547],{},[691,1537,1538],{},[192,1539,1540],{},":alpha",[691,1542,1543,1544,841],{},"Alpha releases (",[192,1545,1546],{},"*-alpha*",[691,1548,1549],{},"Rolling tag — always the latest alpha build",[673,1551,1552,1557,1563],{},[691,1553,1554],{},[192,1555,1556],{},":beta",[691,1558,1559,1560,841],{},"Beta releases (",[192,1561,1562],{},"*-beta*",[691,1564,1565],{},"Rolling tag — always the latest beta build",[673,1567,1568,1572,1575],{},[691,1569,1570],{},[192,1571,1480],{},[691,1573,1574],{},"Stable releases only",[691,1576,1577],{},"Most recent non-pre-release version (recommended for production)",[673,1579,1580,1588,1590],{},[691,1581,1582,159,1585],{},[192,1583,1584],{},":1",[192,1586,1587],{},":1.0",[691,1589,1574],{},[691,1591,1592],{},"Floating within stable release line",[149,1594,1595,1596,1599,1600,1602],{},"Other pre-release suffixes (e.g., ",[192,1597,1598],{},"-rc.1",") receive only the exact version and ",[192,1601,1476],{}," tags.",[149,1604,1605],{},"All tags are available on both registries:",[299,1607,1612],{"className":1608,"code":1610,"language":1611},[1609],"language-text","# GHCR (recommended)\ndocker pull ghcr.io\u002Fghent\u002Fcapacitarr:stable\ndocker pull ghcr.io\u002Fghent\u002Fcapacitarr:beta\n\n# Docker Hub (no registry prefix needed)\ndocker pull ghentstarshadow\u002Fcapacitarr:stable\ndocker pull ghentstarshadow\u002Fcapacitarr:beta\n","text",[192,1613,1610],{"__ignoreMap":304},[179,1615,1617],{"id":1616},"prerequisites","Prerequisites",[149,1619,1620],{},"For the release pipeline to work correctly:",[197,1622,1623,1637,1651,1657],{},[200,1624,1625,1628,1629,1632,1633,1636],{},[203,1626,1627],{},"Use Conventional Commits"," — all commits on ",[192,1630,1631],{},"main"," must follow the ",[153,1634,176],{"href":174,"rel":1635},[157]," format. Non-conventional commits are filtered out.",[200,1638,1639,1644,1645,1647,1648,1650],{},[203,1640,1641,1642],{},"Tag from ",[192,1643,1631],{}," — releases are triggered by ",[192,1646,194],{}," tags. Create tags only from the ",[192,1649,1631],{}," branch.",[200,1652,1653,1656],{},[203,1654,1655],{},"Commit changelog and version before tagging"," — the release prep step (see workflow above) must be committed before creating the tag. The CI pipeline reads from the committed files.",[200,1658,1659,1662],{},[203,1660,1661],{},"Repository secrets"," — the following secrets must be configured in GitHub (Settings → Secrets and variables → Actions):",[667,1664,1665,1674],{},[670,1666,1667],{},[673,1668,1669,1672],{},[676,1670,1671],{},"Secret",[676,1673,1046],{},[686,1675,1676,1686,1696],{},[673,1677,1678,1683],{},[691,1679,1680],{},[192,1681,1682],{},"DOCKERHUB_USERNAME",[691,1684,1685],{},"Docker Hub login username (for mirroring)",[673,1687,1688,1693],{},[691,1689,1690],{},[192,1691,1692],{},"DOCKERHUB_TOKEN",[691,1694,1695],{},"Docker Hub access token (Read & Write)",[673,1697,1698,1703],{},[691,1699,1700],{},[192,1701,1702],{},"DISCORD_WEBHOOK_URL",[691,1704,1705],{},"Discord webhook URL for release notifications",[149,1707,1708,1711],{},[192,1709,1710],{},"GITHUB_TOKEN"," is automatically provided by GitHub Actions — it handles GHCR authentication and GoReleaser GitHub Releases. No separate GHCR token is needed.",[858,1713,1714],{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":304,"searchDepth":17,"depth":22,"links":1716},[1717,1721,1725,1728,1729,1730,1735,1739],{"id":181,"depth":22,"text":182,"children":1718},[1719,1720],{"id":186,"depth":27,"text":187},{"id":251,"depth":27,"text":252},{"id":293,"depth":22,"text":113,"children":1722},[1723,1724],{"id":296,"depth":27,"text":297},{"id":598,"depth":27,"text":599},{"id":658,"depth":22,"text":170,"children":1726},[1727],{"id":814,"depth":27,"text":815},{"id":868,"depth":22,"text":869},{"id":929,"depth":22,"text":930},{"id":1017,"depth":22,"text":1018,"children":1731},[1732,1733],{"id":1021,"depth":27,"text":252},{"id":1238,"depth":27,"text":1734},"On Tag Push (v*)",{"id":1344,"depth":22,"text":1345,"children":1736},[1737,1738],{"id":1403,"depth":27,"text":1404},{"id":1469,"depth":27,"text":1470},{"id":1616,"depth":22,"text":1617},"Capacitarr uses a tag-triggered release pipeline powered by git-cliff, GoReleaser, and GitHub Actions. Releases follow Semantic Versioning and are driven by Conventional Commits.","md",null,{},{"order":116},{"title":113,"description":1740},"zHCA_cyW6ugo8TDi9VOjBTDzJ7r_DDHEm3pxFgSWEFI",[1748,1750],{"title":109,"path":110,"stem":111,"description":1749,"order":17,"children":-1},"Capacitarr is a single-container application that bundles a Go backend, a Nuxt 4 (Vue 3) frontend, and a SQLite database. The frontend is statically generated at build time and embedded into the Go binary via go:embed, producing a single self-contained executable.",{"title":118,"path":119,"stem":120,"description":304,"order":17,"children":-1},1776649613242]