Raw JSON report machine-readable
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 6386,
"has_wiki": true,
"homepage": null,
"languages": {
"R": 16988,
"Go": 6352748,
"CSS": 124693,
"HCL": 33291,
"HTML": 65728,
"Shell": 44396,
"Python": 30417,
"Makefile": 18009,
"Dockerfile": 1943,
"JavaScript": 592226
},
"pushed_at": "2026-07-22T22:05:06Z",
"created_at": "2026-04-15T13:07:02Z",
"owner_type": "User",
"updated_at": "2026-07-22T22:05:26Z",
"description": "ShinyHub — deploy and manage Shiny apps",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Go",
"significant_languages": [
"Go"
]
},
"owner": {
"blog": "https://am8.nl",
"name": "Ruben J. Jongejan",
"type": "User",
"login": "rvben",
"company": "AM8 B.V.",
"location": "Netherlands",
"followers": 79,
"avatar_url": "https://avatars.githubusercontent.com/u/5196381?v=4",
"created_at": "2013-08-09T09:44:22Z",
"is_verified": null,
"public_repos": 140,
"account_age_days": 4730
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.10.14",
"kind": "patch",
"published_at": "2026-07-22T22:13:57Z"
},
{
"tag": "v0.10.13",
"kind": "patch",
"published_at": "2026-07-22T21:21:01Z"
},
{
"tag": "v0.10.12",
"kind": "patch",
"published_at": "2026-07-22T17:04:01Z"
},
{
"tag": "v0.10.11",
"kind": "patch",
"published_at": "2026-07-22T13:15:08Z"
},
{
"tag": "v0.10.10",
"kind": "patch",
"published_at": "2026-07-22T11:54:37Z"
},
{
"tag": "v0.10.9",
"kind": "patch",
"published_at": "2026-07-22T09:33:34Z"
},
{
"tag": "v0.10.8",
"kind": "patch",
"published_at": "2026-07-10T18:19:15Z"
},
{
"tag": "v0.10.7",
"kind": "patch",
"published_at": "2026-07-10T13:05:39Z"
},
{
"tag": "v0.10.6",
"kind": "patch",
"published_at": "2026-07-09T20:58:30Z"
},
{
"tag": "v0.10.5",
"kind": "patch",
"published_at": "2026-07-09T16:57:56Z"
},
{
"tag": "v0.10.4",
"kind": "patch",
"published_at": "2026-07-09T15:05:16Z"
},
{
"tag": "v0.10.3",
"kind": "patch",
"published_at": "2026-07-09T14:06:16Z"
},
{
"tag": "v0.10.2",
"kind": "patch",
"published_at": "2026-07-09T11:18:48Z"
},
{
"tag": "v0.10.1",
"kind": "patch",
"published_at": "2026-07-08T19:11:41Z"
},
{
"tag": "v0.10.0",
"kind": "minor",
"published_at": "2026-07-08T14:50:58Z"
},
{
"tag": "v0.9.6",
"kind": "patch",
"published_at": "2026-07-08T08:09:38Z"
},
{
"tag": "v0.9.5",
"kind": "patch",
"published_at": "2026-07-04T10:04:30Z"
},
{
"tag": "v0.9.4",
"kind": "patch",
"published_at": "2026-07-03T00:31:16Z"
},
{
"tag": "v0.9.3",
"kind": "patch",
"published_at": "2026-07-02T17:56:42Z"
},
{
"tag": "v0.9.2",
"kind": "patch",
"published_at": "2026-07-02T14:05:09Z"
},
{
"tag": "v0.9.1",
"kind": "patch",
"published_at": "2026-07-01T19:54:58Z"
},
{
"tag": "v0.9.0",
"kind": "minor",
"published_at": "2026-06-30T20:12:57Z"
},
{
"tag": "v0.8.29",
"kind": "patch",
"published_at": "2026-06-22T17:55:50Z"
},
{
"tag": "v0.8.28",
"kind": "patch",
"published_at": "2026-06-22T16:32:15Z"
},
{
"tag": "v0.8.27",
"kind": "patch",
"published_at": "2026-06-22T13:47:20Z"
},
{
"tag": "v0.8.26",
"kind": "patch",
"published_at": "2026-06-20T21:10:01Z"
},
{
"tag": "v0.8.25",
"kind": "patch",
"published_at": "2026-06-20T10:42:55Z"
},
{
"tag": "v0.8.24",
"kind": "patch",
"published_at": "2026-06-18T21:57:42Z"
},
{
"tag": "v0.8.23",
"kind": "patch",
"published_at": "2026-06-18T21:24:37Z"
},
{
"tag": "v0.8.22",
"kind": "patch",
"published_at": "2026-06-18T20:30:54Z"
},
{
"tag": "v0.8.21",
"kind": "patch",
"published_at": "2026-06-18T12:20:02Z"
},
{
"tag": "v0.8.20",
"kind": "patch",
"published_at": "2026-06-18T09:35:50Z"
},
{
"tag": "v0.8.19",
"kind": "patch",
"published_at": "2026-06-17T21:36:33Z"
},
{
"tag": "v0.8.18",
"kind": "patch",
"published_at": "2026-06-17T20:31:29Z"
},
{
"tag": "v0.8.17",
"kind": "patch",
"published_at": "2026-06-17T19:15:44Z"
},
{
"tag": "v0.8.16",
"kind": "patch",
"published_at": "2026-06-17T17:10:47Z"
},
{
"tag": "v0.8.15",
"kind": "patch",
"published_at": "2026-06-17T09:49:26Z"
},
{
"tag": "v0.8.14",
"kind": "patch",
"published_at": "2026-06-17T07:46:22Z"
},
{
"tag": "v0.8.13",
"kind": "patch",
"published_at": "2026-06-16T22:05:36Z"
},
{
"tag": "v0.8.12",
"kind": "patch",
"published_at": "2026-06-16T13:36:41Z"
},
{
"tag": "v0.8.11",
"kind": "patch",
"published_at": "2026-06-14T21:38:19Z"
},
{
"tag": "v0.8.10",
"kind": "patch",
"published_at": "2026-06-14T19:02:00Z"
},
{
"tag": "v0.8.9",
"kind": "patch",
"published_at": "2026-06-14T17:09:35Z"
},
{
"tag": "v0.8.8",
"kind": "patch",
"published_at": "2026-06-13T20:39:34Z"
},
{
"tag": "v0.8.7",
"kind": "patch",
"published_at": "2026-06-13T15:29:58Z"
},
{
"tag": "v0.8.6",
"kind": "patch",
"published_at": "2026-06-13T09:30:16Z"
},
{
"tag": "v0.8.5",
"kind": "patch",
"published_at": "2026-06-10T11:42:05Z"
},
{
"tag": "v0.8.4",
"kind": "patch",
"published_at": "2026-06-10T08:28:33Z"
},
{
"tag": "v0.8.3",
"kind": "patch",
"published_at": "2026-06-10T05:50:19Z"
},
{
"tag": "v0.8.2",
"kind": "patch",
"published_at": "2026-06-09T20:46:45Z"
},
{
"tag": "v0.8.1",
"kind": "patch",
"published_at": "2026-06-09T07:35:51Z"
},
{
"tag": "v0.8.0",
"kind": "minor",
"published_at": "2026-06-08T10:21:13Z"
},
{
"tag": "v0.7.5",
"kind": "patch",
"published_at": "2026-06-05T20:58:15Z"
},
{
"tag": "v0.7.4",
"kind": "patch",
"published_at": "2026-06-05T20:26:49Z"
},
{
"tag": "v0.7.3",
"kind": "patch",
"published_at": "2026-06-04T06:27:47Z"
},
{
"tag": "v0.7.2",
"kind": "patch",
"published_at": "2026-06-03T13:56:58Z"
},
{
"tag": "v0.7.1",
"kind": "patch",
"published_at": "2026-06-02T20:58:29Z"
},
{
"tag": "v0.7.0",
"kind": "minor",
"published_at": "2026-06-02T20:04:59Z"
},
{
"tag": "v0.6.2",
"kind": "patch",
"published_at": "2026-05-27T20:39:55Z"
},
{
"tag": "v0.6.1",
"kind": "patch",
"published_at": "2026-05-27T06:51:26Z"
},
{
"tag": "v0.6.0",
"kind": "minor",
"published_at": "2026-05-23T17:18:14Z"
},
{
"tag": "v0.5.8",
"kind": "patch",
"published_at": "2026-05-23T15:22:13Z"
},
{
"tag": "v0.5.7",
"kind": "patch",
"published_at": "2026-05-23T12:16:15Z"
},
{
"tag": "v0.5.6",
"kind": "patch",
"published_at": "2026-05-22T17:38:46Z"
},
{
"tag": "v0.5.5",
"kind": "patch",
"published_at": "2026-05-18T12:57:59Z"
},
{
"tag": "v0.5.4",
"kind": "patch",
"published_at": "2026-05-18T11:57:12Z"
},
{
"tag": "v0.5.3",
"kind": "patch",
"published_at": "2026-05-18T08:10:15Z"
},
{
"tag": "v0.5.2",
"kind": "patch",
"published_at": "2026-05-16T18:36:21Z"
},
{
"tag": "v0.5.1",
"kind": "patch",
"published_at": "2026-05-16T13:44:16Z"
},
{
"tag": "v0.5.0",
"kind": "minor",
"published_at": "2026-05-14T07:36:47Z"
},
{
"tag": "v0.4.1",
"kind": "patch",
"published_at": "2026-05-13T12:18:18Z"
},
{
"tag": "v0.4.0",
"kind": "minor",
"published_at": "2026-05-13T11:10:51Z"
},
{
"tag": "v0.3.3",
"kind": "patch",
"published_at": "2026-05-13T08:17:36Z"
},
{
"tag": "v0.3.2",
"kind": "patch",
"published_at": "2026-05-12T19:37:55Z"
},
{
"tag": "v0.3.1",
"kind": "patch",
"published_at": "2026-05-12T16:17:57Z"
},
{
"tag": "v0.3.0",
"kind": "minor",
"published_at": "2026-04-27T14:07:44Z"
},
{
"tag": "v0.2.6",
"kind": "patch",
"published_at": "2026-04-25T19:58:37Z"
},
{
"tag": "v0.2.5",
"kind": "patch",
"published_at": "2026-04-24T20:32:35Z"
},
{
"tag": "v0.2.4",
"kind": "patch",
"published_at": "2026-04-22T13:51:24Z"
},
{
"tag": "v0.2.3",
"kind": "patch",
"published_at": "2026-04-22T12:08:24Z"
},
{
"tag": "v0.2.1",
"kind": "patch",
"published_at": "2026-04-21T17:08:37Z"
},
{
"tag": "v0.2.0",
"kind": "minor",
"published_at": "2026-04-20T19:39:19Z"
}
],
"recent_commits": [
{
"oid": "d10e4f6891b20e2662732450ad94b34c5df9673d",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.14",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T22:05:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3c4077094af25f9f9b828402c0b7eecf5cee9046",
"body": "cosign 3 (installed by cosign-installer v4) defaults to the bundle format and\nignores --output-signature / --output-certificate under it, so the old detached\npair could not survive the upgrade. Releases now publish one\nchecksums.txt.bundle carrying both the signature and the certificate.\n\nscripts/in\n[…]\nath still verifies the published v0.10.13 artifacts;\nand both negative controls fail correctly - a wrong identity regexp is rejected\nby subject mismatch, a tampered checksums.txt by invalid signature.",
"is_bot": false,
"headline": "feat(release): sign releases with the Sigstore bundle format",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T21:51:44Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "86863d86d71534d0aba60d108913e9422ffc6b51",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.13",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T21:12:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2fef00f4c9e200a3457aa03ad9cd435df1c86ed5",
"body": "… server\n\npg_dump refuses to dump a server newer than itself, so on a developer machine\nwith an older Homebrew client than the test container the round-trip failed with\na version-mismatch error that looks like a broken backup. A suite that goes red\nfor reasons unrelated to the code teaches people to\n[…]\ndefault\nlags, which is exactly what a green suite must never hide.\n\nBoth paths verified against a real postgres:16 container: skip and exit 0\nlocally, fail with the provisioning message under CI=true.",
"is_bot": false,
"headline": "test(backup): skip the Postgres round-trip on a client older than the…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T20:56:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a6034af92b18b4c30c40ad0104f3b37fac09da0c",
"body": "TestLoginRateLimit_BlocksAfterThreshold failed on the Postgres backend and\npassed on a rerun with no code change. The limiter is a FIXED window bucketed on\nfloor(now/window), not a sliding one, so a burst that crosses a boundary starts a\nfresh count and the over-limit attempt is legitimately allowed\n[…]\nook, so the hook cannot drift from what ships.\n\nDiagnosis cost a full cycle because the failure landed in the one backend a\nrecent schema change had touched, which made it look like a real regression.",
"is_bot": false,
"headline": "test(api): stop the login rate-limit tests straddling a window boundary",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T20:23:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3d305229493e0f3576fbeab18a0d85b21338a4bb",
"body": "An elastic worker launches with `uv run --frozen --no-sync`, which performs no\ndependency work, so it needs the environment the deploy built. The spawner\nassumed that environment persists: workers start on demand, potentially days\nlater, and a host reboot with an ephemeral apps dir, a cache wipe, or\n[…]\nctually run: promotion runs them, re-activating an\nalready-served bundle does not, so a restart is not a way to re-run one, and\ngenerated assets must live with the bundle rather than in scratch space.",
"is_bot": false,
"headline": "fix(lifecycle): refuse an elastic spawn whose built environment is gone",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T19:47:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "949b09d478b4a43f097251891138c368610c22c3",
"body": "Changing a worker dial, replica count, or resource limit on a running app\ntriggers a background redeploy of the deployment that is already live. It was\nrunning the full preparation phase, so applying a replica count re-executed the\nbundle's post-deploy hooks - app-controlled code with app-controlled\n[…]\n that env, so its\ninputs genuinely differ.\n\nAlso corrects the isolation docs, which claimed a dial change re-runs the build\nand hooks. It drops the current pool, which is the part worth budgeting for.",
"is_bot": false,
"headline": "fix(api): treat a scaling or resource change as an activation",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T19:28:06Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6198e8963a1e2b8acfa367850c868ea3afb73f7d",
"body": "It holds investigation notes that are never shipped and that carry customer\nnames, which must not reach a committed file. docs/superpowers is already\nignored; this closes the equivalent gap.",
"is_bot": false,
"headline": "chore: ignore the local research scratch directory",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T19:11:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a8ea449a7a4394cbec4196aa868dbf220a052a2e",
"body": "…ated\n\ncosign 4 defaults to the new bundle signature format, which ignores the\n--output-signature and --output-certificate flags .goreleaser.yaml passes and\nthen fails writing an empty --bundle path:\n\n Error: signing dist/checksums.txt: create bundle file: open : no such file\n\nMoving to v4 means mi\n[…]\nwith the reason.\n\nThe pin matters because this action runs only in the release job: an unpinned\nbump passes CI and fails at release time with the tag already pushed, which is\nexactly how it was found.",
"is_bot": false,
"headline": "fix(ci): hold cosign-installer at v3 until the signing config is migr…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T16:54:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5a7169a63c671aa0bbc65587230677745051eeb6",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.12",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T16:44:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2421e02ef48cfc23f18a8409b941cb4d5b6be379",
"body": "checkout, setup-go, setup-node, setup-python to v7, hashicorp/setup-terraform\nto v4, actions/attest-build-provenance to v4, and cosign-installer to v4.1.2.\n\ncosign-installer is pinned to a concrete version rather than the floating major\nthe updater proposed: it publishes v4.x tags but no `v4` ref, u\n[…]\nchecked against the GitHub API before committing.\n\nThese are only provable by running, so they are a separate commit: CI validates\nci.yml immediately, and release.yml is exercised by the next release.",
"is_bot": false,
"headline": "chore(deps): update GitHub Actions to latest majors",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T15:04:47Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bc87e8273f10574288142933632845d80057cfbe",
"body": "axe-core and jsdom for the UI tests, PyJWT and pytest for the identity helper\npackage, and the shiny/streamlit/dash floors in the example bundles.\n\nTwo majors, both checked rather than assumed. pytest 7 to 9: the identity\nhelper's 31 tests and the Go conformance suite pass. dash 2.16 to 4.4: the dem\n[…]\ntrand it.\n\npackage-lock.json regenerated so the declared ranges match package.json; the\ninstalled versions already satisfied them, but npm ci validates the ranges and\nwould have rejected the mismatch.",
"is_bot": false,
"headline": "chore(deps): update Node and Python manifests to latest",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T15:03:17Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b69c28bfa8795a35c96c0b7b1d6473962355307b",
"body": "All minor and patch: AWS SDK, OpenTelemetry, gopsutil, chi, and the rest.\ngrpc stays at v1.82.1, above the GHSA-hrxh-6v49-42gf floor.\n\nVerified: build, vet, full suite, -race, govulncheck, and the container image\nscan all clean.",
"is_bot": false,
"headline": "chore(deps): update Go modules to latest (52 updates, no majors)",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T15:01:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "92873ccaff432d4d8838f2894266b729c1a56668",
"body": "Reproducible 2-vCPU rig that establishes the baseline for render-aware\nadmission backpressure: a synthetic Shiny app with calibrated CPU-bound\nrender cost, a husker microVM lifecycle script, verdict helpers, a\nheadless-browser driver, and make targets.\n\nMeasured baseline: negative controls hold at N=1 and at 10 sessions on a\nsparse cadence, while 5 sessions on a 2s cadence disconnect 100 percent of\nthe time. The dose-response curve is monotonic and saturates by N=5.",
"is_bot": false,
"headline": "Merge: render-saturation verification rig",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T14:39:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "121f3f09d66dfb443a91549fadd910fe8ee7602f",
"body": "…49-42gf\n\nThe container image scan fails on a HIGH advisory in grpc v1.80.0 (xDS RBAC and\nHTTP/2). The pinned version has not changed since CI was last green on\n2026-07-10; the advisory was published in between, so identical code started\nfailing once trivy refreshed its database.\n\nThe release workfl\n[…]\nwhose affected symbols\nare unreachable. The image scan is version-based and flags the embedded module\nregardless. Reproduced locally with `make scan-image` before and after: HIGH: 1\nthen a clean exit.",
"is_bot": false,
"headline": "fix(deps): upgrade google.golang.org/grpc to v1.82.1 for GHSA-hrxh-6v…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T14:10:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "58699098f2c6b462106e5726a0829b185616bbde",
"body": "The environment-presence tests drove a fixed-replica boot, which execs the real\nlaunch command, so an inferred-command bundle needed uv (or Rscript) installed.\nThat is present on a dev machine and absent on the release runner, so the tests\npassed locally and failed the release workflow.\n\nThey assert\n[…]\nthe elastic path: it runs preparation and returns without booting a replica,\nexercising exactly the code under test and execing nothing. Verified by running\nthem with uv and Rscript removed from PATH.",
"is_bot": false,
"headline": "test(deploy): stop the preparation tests from needing uv on PATH",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T13:05:57Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "017d70a936dea8f4e15e675f162fdc6a90e5caa3",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.11",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T13:02:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a18c965e2e0c31d22105fa5398c36005447a3cb1",
"body": "…ation",
"is_bot": false,
"headline": "Merge: restart and rollback are activations, with environment verific…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T13:01:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "67bfc53889309513d080704069f21a557fb6bb25",
"body": "Checking that .venv is a directory proves it was created, not that it still\nworks. A venv's interpreter is a symlink to a system or managed Python, and\nupgrading or removing that Python leaves the directory in place with a dangling\nlink - the ordinary way a previously-good environment stops working \n[…]\n check is the\nbackstop.\n\nAlso covers the R half, which had no test: a bundle with a lockfile needs its\nrestored library and rebuilds without it, while a bundle managing its own\npackages is left alone.",
"is_bot": false,
"headline": "fix(deploy): treat a venv with an unresolvable interpreter as absent",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T13:00:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2bb2f223e6f29f7f5175fd021d86e6faa38116ec",
"body": "…nothing\n\nThe prepared record says preparation once succeeded, not that its output still\nexists, and skipping the build treated it as the latter. An inferred host launch\nis `uv run --frozen --no-sync`, which performs no repair, so anything that\nremoves the built environment turned a skip into a boot\n[…]\nt launch has\nno environment to miss and is left alone.\n\nAlso documents that restart and rollback are activations, and that a restart is\ntherefore not a rebuild - deploy again if that is what you want.",
"is_bot": false,
"headline": "fix(deploy): rebuild when a skipped preparation would launch against …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T12:55:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a3ac0ba68e37a7d4f4ea8c07153bf8129f69b70b",
"body": "…ey failed\n\nRestart re-activates the deployment that is already live, and rollback brings\nback one that already served. Both were running the full preparation phase, so\nevery restart re-executed the bundle's post-deploy hooks. Hooks are\napp-controlled code and nothing guarantees a second run is safe\n[…]\nind, which became more visible once these paths\ncould fail on a build or hook. They now use the same classified response as the\ndeploy path, so a failed hook reports hook_failed and names the command.",
"is_bot": false,
"headline": "fix(api): treat restart and rollback as activations and report why th…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T12:49:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a2041fde6bae8794fcea27a5d8bec660bde16233",
"body": "… harness",
"is_bot": false,
"headline": "docs(loadtest): re-confirm the single-session control under the fixed…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:58:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "679469c50728eaa55e90f6bbcee96aec44d9694b",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.10",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:45:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9887e0ef9689692f43f1eedfd8d13cfd275f4245",
"body": null,
"is_bot": false,
"headline": "Merge: restore a previous bundle as an activation, not a promotion",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:44:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "32363ba95f89202d323f857931a4017388dc8c42",
"body": "…backends\n\nprepared is INTEGER in both migrations, matching the existing ephemeral_data_ack\nprecedent, but the scans read it straight into a bool. database/sql does not\nconvert an integer column to bool, so this would fail on postgres. The sqlite\ndriver happens to accept it, which is exactly why the\n[…]\nrestore would then skip the build\nfor an environment that was never built. The previous test only covered the\nsuccess path, so it would still have passed had preparation been recorded\nunconditionally.",
"is_bot": false,
"headline": "fix(db): scan the prepared column through an int so it works on both …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:44:21Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8338ba8464b879c3e9ca6002831dd77d2ff6f33a",
"body": "Once elastic apps gained a deploy-time preparation phase, restorePreviousPool\ninherited it. That path is the unattended safety net that brings back the\nprevious good bundle after a failed deploy, and for elastic apps it had\npreviously been incapable of failing. It could now fail on a transient build\n[…]\n value of\nPreparationMode is the strict mode, so every existing caller keeps promotion\nsemantics; a test pins that, since a change there would silently stop deploys\nrunning their declared build steps.",
"is_bot": false,
"headline": "fix(deploy): restore a previous bundle as an activation, not a promotion",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:37:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2b923ddafd4a805df2fab630c380bc471f9442f4",
"body": "Documents what the render-saturation rig measures, why the existing\nk6 scenarios structurally cannot measure it, the exact commands to\nreproduce a run, and the control matrix with its gating rule (a\nfailing negative control voids the run).\n\nRecords the measured baseline: both negative controls pass,\n[…]\ntrol reproduces the production disconnect at 5/5 (100%),\nand the dose-response curve (N=3,5,8,12) is monotonic and saturates\nby N=5, consistent with CPU saturation on the 2-vCPU host as the\nmechanism.",
"is_bot": false,
"headline": "docs(loadtest): render-saturation rig baseline and control matrix",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:37:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7a4989093c0700ee5aea0c0d0e4320e238c344f5",
"body": "…rig guest\n\nCOST_MS was assigned from RENDER_COST_MS but never referenced anywhere\nin rig.sh; the app's render cost was never actually configurable\nthrough this script. up() starts ShinyHub before the app is deployed,\nso there is no app process yet whose environment it could set. Replace\nthe dead re\n[…]\n not uv, and ShinyHub's native build\nsandbox deploys Python apps exclusively through uv, so every deploy of\nthe synthetic app failed with \"Python runtime not found on the server\"\nuntil this was added.",
"is_bot": false,
"headline": "fix(loadtest): remove dead RENDER_COST_MS read and install uv in the …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:37:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b382d1e009008287f77d9a8d5ca3d34f11fb6862",
"body": "page.waitForFunction(fn, { timeout }) binds the options object to the\npredicate's arg parameter, not to Playwright's options, since the real\nsignature is (pageFunction, arg, options). The timeout was silently\ndiscarded and Playwright fell back to its 30s default, misreporting\nslower-but-healthy sessions queued behind ShinyHub's single multiplexed\nworker as failed to establish at N=10 concurrent sessions.",
"is_bot": false,
"headline": "fix(loadtest): pass waitForFunction options as the third argument",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:37:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a82fa274d2f0d04baa3db22e0eb673a67131f1f8",
"body": "The previous test proved writeErrorWithKind preserves a valid kind when called\ncorrectly, which is not the invariant that matters. What keeps the anchored hook\nmarker safe is that every deploy-failure RESPONSE carries a valid kind, since the\nwrapped human message classifies as runtime_missing on its\n[…]\noes not\nblame the server runtime.\n\nAlso sharpens the worker-dial docs: the background redeploy tears down and\nre-registers the pool, so it drops the current pool rather than merely costing\nbuild time.",
"is_bot": false,
"headline": "test(api): pin failure_kind at the handler, not just the helper",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T11:27:46Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5b8431b49f7ff94802b0bcd446da7d55e37a7d16",
"body": "Add render-rig-up, render-rig-down, load-test-render and test-render-rig,\ntying together rig.sh, drive.mjs and the two orphaned unit suites\n(burn_test.py, detect.test.js) so they run as CI actions rather than\nfiles someone has to remember to run by hand.\n\ntest-render-rig runs burn_test.py through uv\n[…]\nt\ninstalled; this matches the test-py-identity target's convention.\n\nAlso ignore loadtest/render/driver/package-lock.json, an npm install\nartifact of the driver test harness rather than a deliverable.",
"is_bot": false,
"headline": "ci: make targets for the render-saturation rig",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T10:44:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9531a5bcb23456d289ffdc8f40da960e5c8ce4c0",
"body": null,
"is_bot": false,
"headline": "fix(loadtest): count errored sessions and stop overwriting rig results",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T10:29:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f6444a78898346ee67febfc147dc862118c9f08a",
"body": null,
"is_bot": false,
"headline": "feat(loadtest): let the render rig drive an installed system browser",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T10:16:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8131632e8d32b16ccf4525f29b1198ace74c5004",
"body": "…_kind invariant\n\nChanging a worker dial on a running app triggers a background redeploy\n(apps.go workerChanged). Before elastic apps got a preparation phase that\nredeploy was a no-op for them, so the isolation docs described the dials as\nredeploy-free and instant. It is now a full dependency build \n[…]\nruntime_missing on its own, so the CLI's text fallback would resurrect the exact\nmisclassification hook_failed removes. It is unreachable only while every\ndeploy-failure response carries a valid kind.",
"is_bot": false,
"headline": "fix(docs): correct the worker-dial redeploy cost, and pin the failure…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T09:44:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c802d1fe05cb691201eecb89053299603a6bbfd9",
"body": null,
"is_bot": false,
"headline": "test(loadtest): headless chromium driver for the render-saturation rig",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T09:32:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "85fc7051b1cb31e126eb254952cbfea872662049",
"body": null,
"is_bot": false,
"headline": "chore: record the x/text security fix in the v0.10.9 changelog",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T09:24:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0ebd1a50c8aff1b80b0de2e3288c5df4d4c312c4",
"body": "govulncheck flags an infinite loop on invalid input in x/text v0.38.0, reachable\nfrom db.Store.Migrate via sql.DB.Conn. The release workflow's vulnerability scan\nfails on it, blocking publication.",
"is_bot": false,
"headline": "fix(deps): upgrade golang.org/x/text to v0.39.0 for GO-2026-5970",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T09:23:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "94e8851e0e35d95b7d92c19340b624e8cb0d3eb1",
"body": null,
"is_bot": false,
"headline": "test(loadtest): verdict helpers for the render-saturation rig",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T09:17:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5edc8738ee9191acece472bcd0073d1a31f32213",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.9",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-22T09:11:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "92483897ef5e003b4fe8f3f3ffe4d54d65285085",
"body": null,
"is_bot": false,
"headline": "Merge: classify post-deploy hook failures as hook_failed",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T16:56:28Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "75503b9b278f40ff2c355fc6eb244e424ae04eb1",
"body": "The marker search scanned the whole message, but everything after the marker in\na deploy error is app-controlled: the message echoes the hook's own argv, and\nother deploy errors echo an app-chosen [app] command. An app could therefore\nname its launch command \"hook[3] (x)\" and have its own failed lau\n[…]\nailureClassifiesAsHookFailed pins that propagation for both the\nelastic and multiplex paths, so a future wrap fails the build rather than\nsilently reverting the classifier to blaming the host runtime.",
"is_bot": false,
"headline": "fix(deploy): anchor the hook-failure marker to the start of the message",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T16:56:25Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9c51f4aaaabfa8c4ed337fff689907614f469d6a",
"body": "… missing runtime\n\nA hook echoes the app's own command into its error, so a hook invoking a binary\nthe host lacks produced the same `exec: \"python\": executable file not found`\ntext as a genuinely missing server runtime. The classifier matched on that text\nand reported runtime_missing, and the develo\n[…]\nin Valid() so clients trust it instead of falling\nback to substring matching.\n\nVerified against a running server: the 500 body reports\nfailure_kind \"hook_failed\" and no longer blames the host runtime.",
"is_bot": false,
"headline": "fix(deploy): classify a failed post-deploy hook as hook_failed, not a…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T16:39:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2aa49e052eae31bdc929d732b7240835fe7dabca",
"body": null,
"is_bot": false,
"headline": "Merge: run dependency build and post-deploy hooks for elastic apps",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T11:06:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8200dd5b1a62c84b54cbfb78be71d0188299fd4d",
"body": "hostPreparesDeps reports false when handed no tiers, which would silently skip\nthe build and downgrade the hooks to a reported skip. Params.assignments clamps\nto at least one replica, keeping that unreachable; this pins the property.",
"is_bot": false,
"headline": "test(deploy): pin elastic preparation when the replica count is zero",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T11:05:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "acdf329c01eba6e3449106124b020f23fc6b5612",
"body": "…ic apps\n\nElastic pools (grouped / per_session) returned from deploy.Run before the\npreparation phase, so a declared `[[hook]] on = \"post-deploy\"` silently never\nran and the app's environment was never built. The deploy reported success and\nthe app served requests without whatever the hook was meant\n[…]\nentrypoint, or an invalid [app] command, now fails the deploy\nrather than every future worker spawn. Under a container runtime hooks are\nstill skipped, and the skipped count now reaches the developer.",
"is_bot": false,
"headline": "fix(deploy): run the dependency build and post-deploy hooks for elast…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T11:00:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2be6e6059823d6f9c6cff0d7f3e745056e75fca9",
"body": "The up() EXIT trap previously discarded husker destroy's exit status with\n\"|| true\", so a destroy failure during cleanup (often caused by the same\ndaemon/connectivity fault that triggered the provisioning failure in the\nfirst place) was silently hidden. The operator saw only \"provisioning\nfailed, de\n[…]\nld never\nfire for the failure case it was meant to catch (the aborting command itself\nends the script first), and on any real failure the whole VM is destroyed\nanyway, taking stray /tmp files with it.",
"is_bot": false,
"headline": "fix(loadtest): report rig teardown failures instead of swallowing them",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T09:47:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "db981b03deb2ed662c4ded75cf73568927b527df",
"body": "…the binary transfer\n\nEvery failure after `husker run` (wait, chunked copy, pip install,\nport-forward, the reachability timeout) previously left the VM running on\nthe shared husker daemon with no trap to clean it up. copy_binary also had\nno integrity check on the ~98 MiB chunked binary transfer, so \n[…]\neports the no-op and exits 0, a full up/down cycle still prints\nthe base URL as the last line and tears down cleanly, and running up twice\nwithout an intervening down no longer dumps a raw JSON error.",
"is_bot": false,
"headline": "fix(loadtest): destroy the rig VM on provisioning failure and verify …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T09:25:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "53973a223098fec337501a4f8538c53a8341a525",
"body": null,
"is_bot": false,
"headline": "test(loadtest): husker VM lifecycle for the render-saturation rig",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T09:02:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b2891ab8753a46374230cb009c89f6312fb84ae2",
"body": "…cale errors",
"is_bot": false,
"headline": "test(loadtest): tighten the burn duration ceiling to catch moderate s…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T08:27:36Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2f276046828a7b6a0730ffdcb04bc7957bba03c5",
"body": "…errors",
"is_bot": false,
"headline": "test(loadtest): restore a loose duration ceiling to catch burn scale …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T08:17:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "eb8d3a43775767b5f272b0097c7f00abb7246ef1",
"body": null,
"is_bot": false,
"headline": "chore: ignore Python bytecode from the render-rig test suites",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T08:10:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2c1f0026792a7fad02ad61e3f790b44e0ee7237a",
"body": "…ed CPU ratio",
"is_bot": false,
"headline": "test(loadtest): compare burn against a sleep control instead of a fix…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T08:09:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "75b4829e0192d555f46ebe87b93728536fab96bd",
"body": "…cost",
"is_bot": false,
"headline": "test(loadtest): synthetic Shiny app with calibrated CPU-bound render …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-21T08:06:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "00509ebc3a1f7dbb97637395a2df25a9bd04acb1",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.8",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T18:10:02Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6c923b2ebdbb9d6e5670b176bc503b2eb59564ea",
"body": "The dashboard card badge and the detail-header pill flip to Deploying\nwhile a deployment or rollback executes (pending deployment row plus the\nheld per-slug deploy lock, so a stale row can never light the badge) and\nback on the next poll. The poll also carries last_deployment_status so a\nfirst deploy that fails while watched surfaces as Failed instead of\nreverting to Awaiting deploy.",
"is_bot": false,
"headline": "feat(ui): live Deploying badge on app cards and the detail status pill",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T17:39:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9bf3a676206c0c6efd4c3c87eb1e584cd7e0a7b1",
"body": "…y failures",
"is_bot": false,
"headline": "fix(ui): live-update the detail status pill and surface watched deplo…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T17:36:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4da28b155512cb2f6fd6ec67d3019818a9d7b512",
"body": "… executes",
"is_bot": false,
"headline": "feat(ui): show a live Deploying badge on app cards while a deployment…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T17:18:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0b5978b45f2a0ef302b132802b61f6106b7b0644",
"body": "While a deployment is in flight, visitors now see an auto-refreshing\n'Deploying app' page instead of the wrong 'This app is stopped' page\n(first deploys) or a false 'App did not start' give-up (long builds).\nDeploy and rollback validation now runs before the pending row is\nrecorded and the pool is torn down, so rejected requests leave no\ndeployment record and no state change.",
"is_bot": false,
"headline": "feat: deploy-aware wait pages for the proxy miss path",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T16:56:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6154b86a0acce600936e8c877758c140edc1fc4a",
"body": "…s deploying",
"is_bot": false,
"headline": "fix(db): allowlist the statuses a pending deployment row may report a…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T16:49:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ec25e0f3dc0a61b0e64384ec9ffd6b45661b21e9",
"body": "…nly while the deploy lock is held",
"is_bot": false,
"headline": "fix(db): trust a pending deployment row for stopped or crashed apps o…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T16:31:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "23c74a8cf287d6a5aa12feb9bbe09b1f5c40bef7",
"body": "…ed in flight",
"is_bot": false,
"headline": "fix(proxy): keep firing the wake trigger while a deployment is report…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T16:23:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ad37cd88091fb24e20a28a38019cd6fb014a82fd",
"body": null,
"is_bot": false,
"headline": "feat(server): report in-flight deployments to the proxy miss path",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T16:03:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "618d16eab901188df7a1f8d2cba9d457178bda9c",
"body": "…flight",
"is_bot": false,
"headline": "feat(proxy): serve a deploy-aware wait page while a deployment is in …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T16:02:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4447e469c6157fef145aca6b4db32e49a75fdfa7",
"body": null,
"is_bot": false,
"headline": "refactor(proxy): share the wait-page shell and add a deploying variant",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T16:00:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1b57b5ca63117a6a812879a76d96c07d8025107f",
"body": "… pending",
"is_bot": false,
"headline": "feat(db): report a synthesized deploying status while a deployment is…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T15:59:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ffcfb173786a0f90de4f232f6fd152ab1b62794f",
"body": "…ow or tearing down the pool",
"is_bot": false,
"headline": "fix(api): validate deploy and rollback before recording the pending r…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T15:58:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c2d122461c337d78cd28c53e27894bac9e7ed997",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.7",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T12:56:50Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3d4ac12e8a91da07f26d87965485eb855a4056df",
"body": "The rejected-token diagnostics and the SHINYHUB_IDENTITY_DEV_* dev\nidentity are new public surface, which a minor bump signals; 0.1.1\nundersold them as a fix. Publishes to PyPI with the next shinyhub\nrelease.",
"is_bot": false,
"headline": "chore(identity): version the SDK helpers 0.2.0",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T12:52:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d99f189320b9b204ae9922e4f6459be27c486627",
"body": "The helpers are versioned independently of the server, which raises the\nquestion lockstep versioning pretends to answer: which helper works with\nwhich server. Answer it explicitly: any helper release verifies tokens\nfrom any ShinyHub v0.8.6 or later (identity forwarding shipped in\nv0.8.6), the token contract is stable across releases, and claims a\nlater server added (email, name) are empty when an older server minted\nthe token.",
"is_bot": false,
"headline": "docs(identity): state SDK helper compatibility with server releases",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T12:52:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f8580fcfaaaa61722698d9779c8d3c03f04ab00d",
"body": "The level named \"shared\" reads like \"private plus granted members\" but\nmeans every signed-in user, which has left fleets sitting on public\nbecause the intended internal tier was not obviously named. The CLI now\nnormalizes internal to shared in `apps access set` and\n`deploy --visibility` before sending, so the server API stays canonical.\nHelp text and schema annotations document the alias and state what each\nlevel admits.",
"is_bot": false,
"headline": "feat(cli): accept internal as an alias for the shared access level",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T12:25:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e3ec122fd6d04cff13200237aefd0bb9798ee3d0",
"body": "A token that is present but fails verification now emits a warning once\nper distinct reason per process (Python: WARNING on the shinyhub_identity\nlogger; R: warning()). A present-but-rejected token almost always means a\nmisconfigured deployment (missing or wrong SHINYHUB_IDENTITY_KEY,\naudience/issue\n[…]\nDocs now list every Identity field (name was missing), state the\nfail-closed diagnostics contract, and recommend a startup self-check.\nBumps shinyhub-identity (PyPI) and shinyhubidentity (R) to 0.1.1.",
"is_bot": false,
"headline": "feat(identity): diagnose rejected tokens and add local-dev identities",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-10T12:24:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e16d0025502d20cd7e7c60b98d0f390cfe36f16a",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.6",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T20:49:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "83a66409e54b41b425505aeead0ffcbcd84a6bb6",
"body": "…ist decoders\n\nWebSocket upgrades pinned to a booting elastic worker are parked (bounded,\ncanceled on disconnect) and routed once the worker registers, instead of\nreceiving a non-101 loading page that hard-fails scripted WS clients. List\ncommands' decode failures now carry the same version-skew envelope hint as\nthe fleet commands.",
"is_bot": false,
"headline": "Merge: WS-upgrade parking during worker boot; version-skew hints on l…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T20:46:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c0b5ae44166054f8b36c793ad39a1c34cad801db",
"body": "A WS upgrade arriving while its pinned worker was still booting was answered\nwith the loading page - a non-101 that hard-fails scripted WebSocket clients,\nwhich connect straight after their first response and cannot follow the\nsplash's reload loop (browsers were unaffected). The upgrade is now parke\n[…]\nut or a vanished\nworker it falls back to the loading page. Parking is bounded to one wait per\nrequest and applies only to upgrades pinned to a booting worker; plain\nrequests keep the immediate splash.",
"is_bot": false,
"headline": "feat(proxy): park WebSocket upgrades while their pinned worker boots",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T20:39:47Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7ee3d255202c2b388e6ae2ad9fbd9e9f43a42362",
"body": "List commands decoded through getPaginatedListWithExtra classified an\nundecodable body as a plain internal error with no guidance. The decode\nfailure is now the same typed protocol error the fleet commands use, and a\nshared helper attaches the version-skew hint (client vs server version from\n/api/server-info) to the structured envelope.",
"is_bot": false,
"headline": "fix(cli): give undecodable list responses the version-skew hint",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T20:39:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bfc97bfc8a5a35dbde5133feb0867547a132b0df",
"body": "server.min_available_memory_mb now defaults to 256 MiB (explicit 0 still\ndisables; the field distinguishes unset from explicit zero), so grouped/\nper_session apps are protected from the kernel OOM killer out of the box.\nmake test-provisioning runs real sandboxed uv builds - managed-Python\nprovisioning plus a private index served hermetically in-process behind\nUV_EXTRA_INDEX_URL - and both ci.yml and release.yml now gate on it, closing\nthe class that shipped broken deploys twice.",
"is_bot": false,
"headline": "Merge: default-on elastic memory floor + build-provisioning release gate",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T20:17:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a998c8ed7602c1ad736f83785d978a2dd7306172",
"body": "The probe package now lives only behind UV_EXTRA_INDEX_URL - the exact\nvariable and topology of the original regression - while UV_INDEX_URL\npoints at a hermetic empty index so the happy path never leaves localhost.\nVerified: removing UV_EXTRA_INDEX_URL from the build env allowlist fails\nthe gate with the production symptom; current code passes.",
"is_bot": false,
"headline": "test(deploy): gate the private-index e2e on UV_EXTRA_INDEX_URL",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T20:17:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0d200911849322004aa96e33bc58ed36d3d75ad0",
"body": "The build-provisioning regression class (managed-Python interpreters could\nnot be written under the sandbox; private package-index env vars were\ndropped by the build env allowlist) shipped in releases twice because no\ngate exercised it: the failures were invisible on dev boxes with a matching\nsystem\n[…]\nker. Both ci.yml (own\njob) and release.yml (pre-goreleaser, after the vuln scan) run it.\nVerified non-vacuous: removing UV_INDEX_URL from the allowlist makes the\ngate fail with the production symptom.",
"is_bot": false,
"headline": "ci(release): gate releases on the sandboxed build-provisioning path",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T20:09:08Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f55633e9c83635fa1c8dceb8c10a9740fec1bda0",
"body": "server.min_available_memory_mb previously defaulted to off, leaving the\nkernel OOM killer as the only backstop for grouped/per_session apps unless\nthe operator opted in - and an elastic OOM takes out a whole worker plus\nevery session bound to it. The unset key now applies a 256 MiB floor: low\nenough\n[…]\ned-isolation warning now fires only in that explicitly-opted-out\nstate, and its text says how to re-enable. The floor is probed only on\nelastic worker allocation; multiplex deployments are unaffected.",
"is_bot": false,
"headline": "feat(config): enable the elastic memory floor by default (256 MiB)",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T20:02:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bda0ed67e9cf75ea32fab76d12466a1c3471bc75",
"body": "…worker_pool envelope)\n\nOperators tuning grouped_size/max_workers can now read the live worker\ntable (slot, routing status, bound sessions vs cap, pid, port, CPU/RSS)\nfrom apps show and apps metrics instead of counting processes in server\nlogs. The proxy exports a pool snapshot, the app envelope carries it as\nworker_pool, the metrics endpoints rebuild per-replica rows from it, and\nthe dashboard inherits real session counts from the metrics poll.",
"is_bot": false,
"headline": "Merge: per-worker capacity view for elastic apps (apps show/metrics, …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T18:44:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5eee09a1b73f345f5a1d75f382ec2b0ece83ab13",
"body": "The lost-status overlay indexes the replica rows positionally. The elastic\nrebuild compacts rows to live slots, so a stale multiplex-era DB replica\nmarked lost could overwrite a live worker's row (wrong worker shown lost,\nreal sessions hidden). Elastic workers are never persisted to the replicas\ntable, so for an elastic pool every DB replica row is a leftover: the\noverlay now applies to multiplex pools only.",
"is_bot": false,
"headline": "fix(api): keep the DB lost-replica overlay away from elastic metric rows",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T18:43:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "43cf320c8ad9e9b493ac94929e5ba897a36d4bad",
"body": "Operators tuning grouped_size/max_workers had to count workers from server\nlogs and ps: apps show rendered only the (stale, multiplex-era) replicas\ntable for elastic apps and apps metrics reported sessions as -1 with the\nmultiplex per-replica cap.\n\nThe proxy now exports ElasticWorkersSnapshot (slot,\n[…]\neiling, and a Workers\ntable (slot, status, sessions/cap, pid, port); apps metrics summarizes the\npool ceiling. The dashboard replica panel inherits real session counts from\nthe metrics poll unchanged.",
"is_bot": false,
"headline": "feat(observability): per-worker capacity view for elastic apps",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T18:38:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ad79c9a895800b1fb149c50f98d1a4f4875d17b6",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.5",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T16:48:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d88359d46817dae502071b67520813dcb5029760",
"body": "…size; CLI protocol-error classification\n\nA burst of simultaneous cold clients on a grouped-isolation app was shed with\n503s at max_workers arrivals (each reserving its own booting worker) instead\nof the configured max_workers x grouped_size ceiling. New clients now bind\nonto booting workers and wai\n[…]\nn. Separately, an undecodable API response (CLI/server version\nskew) is now classified internal with upgrade guidance in both prose and the\nerror envelope hint, instead of kind auth with a login hint.",
"is_bot": false,
"headline": "Merge: grouped cold-burst admission packs booting workers to grouped_…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T16:11:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1d794d7a2e30fbdca09337abb10c6c35e15deec7",
"body": "The upgrade guidance for an undecodable response was printed only as stderr\nprose; scripted and JSON consumers read the structured error envelope, which\ncarried just the raw unmarshal message. The guidance now also travels in the\nenvelope's hint field.",
"is_bot": false,
"headline": "fix(cli): carry version-skew guidance into the error envelope hint",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T16:09:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "832773198a95f7664d8f20241c04c15f31ef8bb3",
"body": "Re-placing a client away from a draining worker stops the old binding's\npending grace timer and decrements the worker's assignedClients. When that\ncount reaches zero the stopped timer was the only remaining reclaim path, so\nthe migration now dispatches the terminate callback itself; otherwise the\nemptied worker would run indefinitely.",
"is_bot": false,
"headline": "fix(proxy): dispatch terminate when client migration empties a worker",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T16:05:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a6009404f7559daa92e155ff4db0cc5ea2c3b49c",
"body": "…-skew guidance\n\nAn older CLI decoding a newer server's changed response shape failed with a\nraw unmarshal error classified as kind \"auth\" (exit 3) and a misleading\n\"run 'shinyhub login'\" hint. Decode failures are now a typed protocol error\nclassified as internal (exit 1, not retryable). The fleet commands diagnose\nthe failure against /api/server-info: when the server's version differs from\nthe CLI's, the message names both versions and advises upgrading the CLI.",
"is_bot": false,
"headline": "fix(cli): classify undecodable API responses as internal with version…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T16:00:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e997348d8425e1a91d91e8bd5962900dbe1fc919",
"body": "…d_size\n\nUnder a burst of simultaneous cold arrivals, every fresh client reserved its\nown worker slot because booting workers were excluded from placement: a\ngrouped pool shed 503s (and answered WebSocket upgrades with the loading\npage) once max_workers clients arrived, far below the configured\nmax_\n[…]\ne. Rebinding away from a draining or removed worker migrates the\nassignedClients accounting, and a grace-timer identity guard keeps a stale\nexpiry from tearing down a re-placed client's fresh binding.",
"is_bot": false,
"headline": "fix(proxy): pack cold-burst clients onto booting workers up to groupe…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T15:59:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c18b0edebb3ff46115d7954f7e247b0c101bdbd2",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.4",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T14:56:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "26cdd0807e870b9dd6493d1c50644f50e82e8f1d",
"body": "…tics (multi-tenant private-index support)",
"is_bot": false,
"headline": "Merge: per-app env vars reach builds and hooks; package-index diagnos…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T14:45:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a99fb658c8187e7fa342dcf2db4f1c4d705e1c38",
"body": "…index misses\n\nHost-side dependency builds (uv sync / renv restore) and post-deploy hooks\nran with only the sanitized server environment, so per-app env vars -\nincluding secrets such as private package-index credentials - reached the\napp process but never dependency resolution. On a multi-tenant ins\n[…]\nure is annotated with the index configuration the build actually saw,\nor with a docs pointer when none reached it - the v0.9.6 env-scrub\nregression class took a two-release bisect without this signal.",
"is_bot": false,
"headline": "feat(deploy): give builds and hooks the app's env vars, and diagnose …",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T14:42:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0ffe09b356671794f36edd5ef994f052c9807a40",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.3",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T13:56:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0c7e15e007e401aec217fe40ec4ffc4111c9606e",
"body": "…ilds (private-registry deploy fix)",
"is_bot": false,
"headline": "Merge: pass package-index env vars through to sandboxed and native bu…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T13:55:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e78bdfcf0c9286b735a423e3eeb92dfa5920de48",
"body": "The v0.9.6 switch of SanitizedEnv from a SHINYHUB_*-deny-list to an\nallow-list dropped uv's index configuration (UV_EXTRA_INDEX_URL,\nUV_INDEX_URL, UV_DEFAULT_INDEX, UV_INDEX, UV_FIND_LINKS, and the\nUV_INDEX_{NAME}_USERNAME/PASSWORD credential family) while keeping the\nproxy vars, so on a host whose \n[…]\nrver-wide and visible to every build that uses them; the docs\nnow state that visibility model, the full inherited-env allow-list, and\nthe SHINYHUB_APP_ENV_ALLOW escape hatch (previously undocumented).",
"is_bot": false,
"headline": "fix(process): pass package-index env vars through to app builds",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T13:55:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b7e1eeda08e0f0b35e91fabc1493bc703f9def8f",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.2",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T11:02:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5ebcd12205843279aaa94d011a9beca81ac1a40a",
"body": "…V_PYTHON_INSTALL_DIR)",
"is_bot": false,
"headline": "Merge: build sandbox allows uv managed-Python provisioning (per-app U…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T10:14:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c5b3c29b50b2a64d6f3f00b7916324988208a707",
"body": "…eters\n\nSandboxing the dependency-build and post-deploy-hook phases (SEC-A1,\nv0.9.6) redirected the uv/renv caches into the writable build dir but\nleft uv's managed-Python store at its default $HOME/.local/share/uv/python,\nwhich Landlock denies under the standard tier's read-only root. On a host\nwhe\n[…]\nive test and a\ngated end-to-end test (SHINYHUB_LIVE_UV=1, real uv downloading a managed\nCPython through sandboxedPythonSync) reproduce the exact reported failure\non pre-fix code and pass with the fix.",
"is_bot": false,
"headline": "fix(deploy): let sandboxed builds provision uv-managed Python interpr…",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-09T10:04:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9c97d392effa97d616899baf9c98e9a31c84663d",
"body": "The release vulnerability gate rejects the 1.26.4 toolchain: govulncheck\nflags the crypto/tls Encrypted Client Hello privacy leak, fixed in\n1.26.5. All workflows read the toolchain from go.mod.",
"is_bot": false,
"headline": "chore: require Go 1.26.5 (crypto/tls fix for GO-2026-5856)",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-08T19:02:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6fbba002ef15c860f1b7989cb7bcdda29448c03e",
"body": null,
"is_bot": false,
"headline": "chore: bump version to v0.10.1",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-08T18:55:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "01e7b1cc79b88213fe8e9aff0f994ab2ea3815ee",
"body": null,
"is_bot": false,
"headline": "chore: gitignore local investigation notes",
"author_name": "Ruben J. Jongejan",
"author_login": "rvben",
"committed_at": "2026-07-08T18:55:38Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 82,
"commits_last_year": 1935,
"latest_release_at": "2026-07-22T22:13:57Z",
"latest_release_tag": "v0.10.14",
"releases_from_tags": false,
"days_since_last_push": 0,
"active_weeks_last_year": 14,
"days_since_latest_release": 0,
"mean_days_between_releases": 1.5
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": true,
"health_percentage": 71,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "github.com/rvben/shinyhub",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": true,
"registry_url": "https://pkg.go.dev/github.com/rvben/shinyhub",
"is_deprecated": false,
"latest_version": "v0.10.14",
"repository_url": "https://github.com/rvben/shinyhub",
"versions_count": 84,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-22T22:05:04Z",
"latest_version_yanked": null,
"days_since_latest_publish": 0
}
]
},
"popularity": {
"forks": 0,
"stars": 1,
"watchers": 1,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": null,
"open_issues_and_prs": 1
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [
"examples",
"recipes"
],
"has_llms_txt": false,
"has_dockerfile": true,
"has_mcp_signal": false,
"bootstrap_files": [
"Makefile"
],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [
"go.mod"
],
"largest_source_bytes": 205375,
"source_files_sampled": 890,
"oversized_source_files": 16,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"go.mod",
"package.json"
],
"advisories": {
"error": null,
"scope": null,
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"go",
"npm"
],
"dependencies": [
{
"name": "github.com/BurntSushi/toml",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.0"
},
{
"name": "github.com/aws/aws-sdk-go-v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.43.0"
},
{
"name": "github.com/aws/aws-sdk-go-v2/config",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.32.31"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/ec2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.317.0"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/ecs",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.89.0"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/s3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.106.0"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/s3files",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.0"
},
{
"name": "github.com/aws/aws-sdk-go-v2/service/secretsmanager",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "github.com/cloudflare/tableflip",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.2.3"
},
{
"name": "github.com/coreos/go-oidc/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.20.0"
},
{
"name": "github.com/go-chi/chi/v5",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v5.3.1"
},
{
"name": "github.com/golang-jwt/jwt/v5",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v5.3.1"
},
{
"name": "github.com/google/uuid",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.0"
},
{
"name": "github.com/jackc/pgx/v5",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v5.10.0"
},
{
"name": "github.com/landlock-lsm/go-landlock",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.9.0"
},
{
"name": "github.com/mattn/go-shellwords",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.14"
},
{
"name": "github.com/prometheus/client_golang",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.24.0"
},
{
"name": "github.com/prometheus/client_model",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.6.2"
},
{
"name": "github.com/robfig/cron/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.0.1"
},
{
"name": "github.com/sabhiram/go-gitignore",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20210923224102-525f6e181f06"
},
{
"name": "github.com/santhosh-tekuri/jsonschema/v6",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v6.0.2"
},
{
"name": "github.com/shirou/gopsutil/v4",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v4.26.6"
},
{
"name": "github.com/spf13/cobra",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.10.2"
},
{
"name": "github.com/spf13/pflag",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.10"
},
{
"name": "go.opentelemetry.io/otel",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "go.opentelemetry.io/otel/sdk",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "go.opentelemetry.io/otel/trace",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.44.0"
},
{
"name": "golang.org/x/crypto",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.54.0"
},
{
"name": "golang.org/x/oauth2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.36.0"
},
{
"name": "golang.org/x/sys",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.47.0"
},
{
"name": "golang.org/x/term",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.45.0"
},
{
"name": "gopkg.in/yaml.v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.0.1"
},
{
"name": "modernc.org/sqlite",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.54.0"
}
],
"all_dependencies": {
"error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"source": null,
"packages": [],
"collected": false,
"truncated": false,
"total_count": null,
"direct_count": null,
"indirect_count": null
}
},
"maintainership": {
"issues": {
"open_prs": 1,
"merged_prs": 0,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 9
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "rvben",
"commits": 1935,
"avatar_url": "https://avatars.githubusercontent.com/u/5196381?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"release.yml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"go.sum",
"package-lock.json"
],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 0,
"reason": "branch protection not enabled on development/release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": null,
"reason": "no pull request found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 0/30 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 3,
"reason": "project has 1 contributing companies or organizations -- score normalized to 3",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 10,
"reason": "update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 10,
"reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "no SAST tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 10,
"reason": "security policy file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": 6,
"reason": "4 out of the last 5 releases have a total of 4 signed artifacts.",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 7,
"reason": "3 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "d10e4f6891b20e2662732450ad94b34c5df9673d",
"ran_at": "2026-07-23T00:04:32Z",
"aggregate_score": 5.4,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": true,
"has_dependabot_config": true
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-22T22:15:57Z",
"oldest_open_prs": [
{
"number": 1,
"created_at": "2026-06-20T19:33:29Z",
"last_comment_at": null,
"last_comment_author": null
}
],
"last_merged_pr_at": null,
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/rvben/shinyhub",
"host": "github.com",
"name": "shinyhub",
"owner": "rvben"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 55,
"inputs": {
"security": 54,
"vitality": 83,
"community": 33,
"governance": 39,
"engineering": 66
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 83,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 74,
"inputs": {
"commits_last_year": 1935,
"human_commit_share": 1,
"days_since_last_push": 0,
"active_weeks_last_year": 14
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "14/52 weeks with commits",
"points": 9.7,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 14
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "1935 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 1935
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": null,
"notes": [],
"value": 96,
"inputs": {
"releases_count": 82,
"latest_release_tag": "v0.10.14",
"releases_from_tags": false,
"days_since_latest_release": 0,
"mean_days_between_releases": 1.5
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "82 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 82
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~1.5 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 1.5
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "4 out of the last 5 releases have a total of 4 signed artifacts.",
"points": 6,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "at_risk",
"name": "Community & Adoption",
"value": 33,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 0,
"stars": 1,
"watchers": 1,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "1 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 1
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "1 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 1
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "good",
"name": "Community health",
"note": null,
"notes": [],
"value": 70,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": true,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 18,
"status": "met",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "at_risk",
"name": "Sustainability & Governance",
"value": 39,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 13,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 1,
"top_contributor_share": 1
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 100% of commits",
"points": 0,
"status": "missed",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 100
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "1 contributors",
"points": 1.4,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 1
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 3,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "critical",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"issue_resolution"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 1,
"inputs": {
"merged_prs": 0,
"open_issues": 0,
"closed_issues": 0,
"issue_closed_ratio": null,
"closed_unmerged_prs": 9
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "no issues or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_issues_or_data",
"params": {}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "0/9 decided PRs merged",
"points": 0,
"status": "missed",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 0,
"decided": 9
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "moderate",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 61,
"inputs": {
"followers": 79,
"owner_type": "User",
"is_verified": null,
"owner_login": "rvben",
"public_repos": 140,
"account_age_days": 4730
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "79 followers of rvben",
"points": 13.7,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 79,
"login": "rvben"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "140 public repos, account ~12 yr old",
"points": 25,
"status": "met",
"details": [
{
"code": "public_repos",
"params": {
"count": 140
}
},
{
"code": "account_age_years",
"params": {
"years": 12
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"github.com/rvben/shinyhub"
],
"ecosystems": "go",
"any_deprecated": false,
"min_days_since_publish": 0
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on go",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"ecosystems": "go"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 0 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 0
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "84 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 84
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "moderate",
"name": "Engineering Quality",
"value": 66,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 60,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "2 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 2
}
}
],
"max_points": 24
},
{
"key": "tests_present",
"name": "Tests present",
"detail": null,
"points": 24,
"status": "met",
"details": [],
"max_points": 24
},
{
"key": "linter_config",
"name": "Linter config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "good",
"name": "Documentation",
"note": null,
"notes": [],
"value": 75,
"inputs": {
"topics": [],
"has_wiki": true,
"homepage": null,
"has_readme": true,
"has_docs_dir": true,
"has_description": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 25,
"status": "met",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "moderate",
"name": "Security",
"value": 54,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "moderate",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 54,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 17,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 1,
"scorecard_aggregate": 5.4
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection not enabled on development/release branches",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 0.8,
"status": "partial",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "update tool detected",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "no SAST tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "4 out of the last 5 releases have a total of 4 signed artifacts.",
"points": 4.5,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "3 existing vulnerabilities detected",
"points": 5.2,
"status": "partial",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "excellent",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"review_only_matches": 0,
"assessed_self_published_locations": 2
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "moderate",
"name": "AI Readiness",
"value": 59,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "at_risk",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 0.93,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "no CLAUDE.md / AGENTS.md / editor rules",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_instructions",
"params": {}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "93 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 93,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "moderate",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 66,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"go.sum",
"package-lock.json"
],
"has_dockerfile": true,
"typed_language": true,
"bootstrap_files": [
"Makefile"
],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [],
"agent_commit_share": 0,
"toolchain_manifests": [
"go.mod"
],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "Makefile",
"points": 18,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Makefile"
}
}
],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "Go (statically typed)",
"points": 11,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "Dockerfile, lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Dockerfile, lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "no agent-authored commits among the last 100",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_agent_authored_commits",
"params": {
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "dependency automation configured, none observed in the sampled commits",
"points": 5,
"status": "partial",
"details": [
{
"code": "dependency_bot_config_only",
"params": {}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 99,
"inputs": {
"primary_language": "Go",
"largest_source_bytes": 205375,
"source_files_sampled": 890,
"oversized_source_files": 16
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Go (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "16/890 source files over 60KB",
"points": 54,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 890,
"oversized": 16
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "at_risk",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"example_dirs": [
"examples",
"recipes"
],
"has_mcp_signal": false,
"api_schema_files": []
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": "examples, recipes",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "examples, recipes"
}
}
],
"max_points": 40
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
],
"report_type": "repository",
"generated_at": "2026-07-23T00:04:45.530293Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/r/rvben/shinyhub.svg",
"full_name": "rvben/shinyhub",
"license_state": "standard",
"license_spdx": "MIT"
}