JSON-Rohbericht maschinenlesbar
{
"data": {
"repo": {
"topics": [
"netlab",
"netns",
"netsim",
"network-simulation",
"networking",
"p2p",
"rust",
"hole-punching"
],
"is_fork": false,
"size_kb": 2523,
"has_wiki": true,
"homepage": "https://n0-computer.github.io/patchbay/",
"languages": {
"CSS": 16204,
"HTML": 293,
"Rust": 1207023,
"Shell": 179,
"TypeScript": 172355
},
"pushed_at": "2026-07-27T14:04:25Z",
"created_at": "2026-02-23T11:24:32Z",
"owner_type": "Organization",
"updated_at": "2026-07-27T13:59:41Z",
"description": "Rust library for realistic network simulation via Linux namespaces",
"is_archived": false,
"is_disabled": false,
"license_spdx": "Apache-2.0",
"default_branch": "main",
"license_spdx_raw": "Apache-2.0",
"primary_language": "Rust",
"significant_languages": [
"Rust",
"TypeScript"
]
},
"owner": {
"blog": "https://n0.computer",
"name": "number zero",
"type": "Organization",
"login": "n0-computer",
"company": null,
"location": null,
"followers": 1032,
"avatar_url": "https://avatars.githubusercontent.com/u/101023307?v=4",
"created_at": "2022-03-05T22:12:15Z",
"is_verified": null,
"public_repos": 120,
"account_age_days": 1604
},
"license": {
"state": "standard",
"spdx_id": "Apache-2.0",
"raw_spdx": "Apache-2.0",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "rolling",
"kind": "other",
"published_at": "2026-03-04T11:15:42Z"
},
{
"tag": "patchbay-v0.5.2",
"kind": "other",
"published_at": "2026-05-07T14:43:55Z"
},
{
"tag": "patchbay-v0.5.1",
"kind": "other",
"published_at": "2026-05-04T09:25:39Z"
}
],
"recent_commits": [
{
"oid": "5cc60db1eb190360dfcd64eaf2f829bce4072551",
"body": null,
"is_bot": false,
"headline": "chore: prepare 0.7.0 release",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-07-27T13:58:20Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8415da55db963fc03a9132475d9d6c1052c5d85a",
"body": "…g (#37)\n\n## Summary\n\nRework the `Nat` enum from deployment-flavored variants (`Home`,\n`Corporate`, `Cgnat`, `CloudNat`, `FullCone`) into a three-tier behavior\ngradient (`Open`, `Moderate`, `Strict`) ordered by hole-punching\ndifficulty. The tiers are named after the console NAT-type scale (Open /\nMo\n[…]\ntinction between EIM and EDM end-to-end.\n- A compile-only guard that `nat(None)` / `set_nat(None)` still infer\n`Option<NatConfig>` without a turbofish.\n- `cargo clippy --workspace --all-targets` clean",
"is_bot": false,
"headline": "feat!: rework NAT taxonomy with behavior-only variants + ADF filterin…",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-07-27T11:13:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7014aaa542b4aa61a8c212dcac85116a28d22767",
"body": "…obs) (#43)\n\n## Description\n\nWe use patchbay to emulate degraded links for the iroh relay throughput\nbenchmark. Two things were wrong with the old model. It described links\nwith raw `netem` knobs, so a realistic link was hard to set up unless\nyou already knew the numbers, and the presets modeled los\n[…]\n [x] Documentation updates: presets, setters, guide, and reference\ntables.\n- [x] Tests: derivation-rule unit tests and the existing impairment\nintegration tests.\n- [x] All breaking changes documented.",
"is_bot": false,
"headline": "feat!: realistic link emulation (congestion-buffer and bursty-loss kn…",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-07-27T10:51:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9f0d703fc821ba1957928b01cf7221470bba5450",
"body": "## Description\n\nThis adds additive helpers on the lab API to remove boilerplate that\nevery patchbay integration test repeats when it initializes a lab.\n\nToday, iroh's patchbay tests (both `iroh` and `iroh-dns-server`) do this\nto auto-label a lab with the test name:\n\n```rust\nlet mut builder = Lab::bu\n[…]\nts to keep control over the builder:\n\n```rust\nlet lab = Lab::builder()\n .outdir(OutDir::Exact(dir))\n .label_from_thread()\n .build()\n .await?;\n```\n\n## Breaking changes\n\nNone, only additions",
"is_bot": false,
"headline": "feat: add test setup helpers to Lab builder (#44)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-07-23T08:42:35Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fafb1378c610c34e50912267318cc3560e33b455",
"body": null,
"is_bot": false,
"headline": "chore: Release",
"author_name": "dignifiedquire",
"author_login": "dignifiedquire",
"committed_at": "2026-06-15T10:34:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4332285b8572df44bee3bdc46b538bd62e964c8d",
"body": null,
"is_bot": false,
"headline": "feat!: update deps and iroh-metrics@1.0 (#42)",
"author_name": "Friedel Ziegelmayer",
"author_login": "dignifiedquire",
"committed_at": "2026-06-15T10:34:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2c23f5e50612eac4bface3c98f6346e182f138d1",
"body": null,
"is_bot": false,
"headline": "chore: Release",
"author_name": "dignifiedquire",
"author_login": "dignifiedquire",
"committed_at": "2026-05-07T13:49:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "198bae0afcdd21ad569b55c321d915933e9cc7a6",
"body": null,
"is_bot": false,
"headline": "feat: update deps to latest (#40)",
"author_name": "Friedel Ziegelmayer",
"author_login": "dignifiedquire",
"committed_at": "2026-05-07T13:44:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6ba0c1ff287cfe2524c01f55f2f7e58843cf8955",
"body": null,
"is_bot": false,
"headline": "chore: Release",
"author_name": "dignifiedquire",
"author_login": "dignifiedquire",
"committed_at": "2026-05-04T09:25:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cecd3b22e23396874169fa12d4441a6bdcaa1de9",
"body": null,
"is_bot": false,
"headline": "feat: add cargo deny and fix issues (#39)",
"author_name": "Friedel Ziegelmayer",
"author_login": "dignifiedquire",
"committed_at": "2026-05-04T09:18:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f2582bab6bddada635ddb405b2c329992e2cefec",
"body": "Demotes noisy per-operation logs (nft rule text, sysctl writes,\nper-interface addresses, NAT application steps) from debug to trace.\nAdds one-line summary logs at debug level when routers and devices are\nfully configured.\n\nDebug output for a 3-router + 2-device lab now reads as a clean sequence\nof s\n[…]\nirs instead of dozens of individual netlink and sysctl\ncalls. Trace level retains all the detail for debugging patchbay\ninternals.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: refine tracing log levels for cleaner debug output (#35)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-14T13:28:37Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b3c9cf30c6535e19491cfdc78e0afac0112e6adf",
"body": "also fixes up `cliff.toml` and `CHANGELOG.md`",
"is_bot": false,
"headline": "chore: prepare 0.5.0 release (#32)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-14T08:00:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "09a33de051bf67ed7ac2bb785647d6da299de6f7",
"body": "Replaces LabOpts with a LabBuilder accessed via Lab::builder().\nLab::new() remains as sugar for Lab::builder().build(). TOML config\nloading moves to LabBuilder::config() which stores the config and\napplies it during build.\n\n```rust\n// Simple\nlet lab = Lab::new().await?;\n\n// With options\nlet lab = La\n[…]\n`.\n* Added: `LabBuilder` with all the methods from LabOpts plus `.config()`\nand `.build()`.\n* Added: `Lab::builder()` constructor.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat!: replace LabOpts with Lab::builder() pattern (#31)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-14T07:33:25Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e001d5c23d14e27169c00192ce58272aa18a35a7",
"body": "Replace the CancellationToken-based DNS server shutdown with\nArc<AbortOnDropHandle>. The serve task is aborted automatically when the\nlast DnsServer clone drops, eliminating the manual shutdown() call in\nLabInner::drop and making it impossible for the task to outlive its\nowner regardless of drop ord\n[…]\n20 lines, +15 lines. Removes DnsServer::shutdown(), the\nCancellationToken field, and the explicit shutdown call in\nLabInner::drop.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: use AbortOnDropHandle for DNS server task lifecycle (#28)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-14T07:09:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4973d1015db074dc8b9901b175530e2036a0a6f0",
"body": "…(#29)\n\nWrap Lab around Arc<LabDropGuard> which derefs to LabInner. When the\nlast Lab clone drops, the guard cancels all namespace workers (async\nruntimes + sync workers), flushes all buffered log files via a\nFlushRegistry, and writes the final state.json with the correct test\nstatus.\n\nDevice, Route\n[…]\nne but could not safely\nparticipate in the drop guard lifecycle. Never called externally.\n* Removed: `Router::lab()`. Same reason.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat!: LabDropGuard with FlushRegistry for guaranteed clean shutdown …",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-13T22:31:51Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "275ac1db745c5b9347326d362934f5ccd46df74d",
"body": "…on (#30)\n\nRunning patchbay as real root on CI runners overwrote the host's\n/etc/resolv.conf. Two issues caused this.\n\nThe main issue: init_userns skipped the user namespace bootstrap when\nrunning as root, leaving the process in the initial namespace where\nmount operations affect the real filesystem\n[…]\ng all mounts private with MS_REC | MS_PRIVATE on /\nimmediately after creating the mount namespace. The function also\nreturns early if unshare fails, preventing bind mounts in the real mount\nnamespace.",
"is_bot": false,
"headline": "fix: prevent mount namespace leaks and enforce user namespace isolati…",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-13T21:33:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f1ef699f1c0c43063382af41de0509c18dea6d0c",
"body": "## Summary\n\n- Remove the `iroh-integration/` directory, which contained legacy sim\nconfigs and topology files from when iroh integration tests lived in\nthis repo. Iroh patchbay tests now live in the iroh repo itself, so\nthese configs are unused.\n- Replace the CI container smoke test and the Rust ipe\n[…]\n/tests/fixtures/iperf-1to1-public.toml` (inlined topology,\nno `extends` or external references).\n- Update `.github/workflows/ci.yml` and `patchbay-cli/src/native.rs` to\nreference the new fixture path.",
"is_bot": false,
"headline": "chore: replace iroh-integration with self-contained fixture (#24)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-10T15:56:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "78edca33bc18502eb3124fcfe470a2eacb2a2714",
"body": "Updates all code examples, API references, and guide prose across\nREADME, docs/, and Rust doc comments to reflect the 0.4.0 API changes.\n\nThe main migration: all per-interface mutations now go through the Iface\nhandle (dev.iface(\"eth0\").unwrap().set_condition(), .link_down(),\n.replug(), etc.) instea\n[…]\ne by adding the\nmissing OutDir import.\n\n7 files updated across README, 4 guide pages, 2 reference pages, and one\nRust source file.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: update all documentation for DNS server and Iface API (#25)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-10T15:55:57Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "859adc6428603ba07eb5027f0d3e7f0db9152e2a",
"body": "Remove files that are no longer used:\n\n* AGENTS.md: outdated\n* HISTORY.md: the changelog now lives in CHANGELOG.md, generated by\ngit-cliff.\n* test-results/.last-run.json: build artifact that should not be\ntracked.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: remove stale files (#23)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-10T13:38:16Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c3b0f36418bec043f02db646f382123b107dac14",
"body": null,
"is_bot": false,
"headline": "chore: prepare 0.4.0 release (#22)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-10T13:23:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ccc77d944e01d194ec3ed1dacb0ec09185ba8e10",
"body": "…ated interfaces (#21)\n\nInterfaces get a proper configuration type and a mutable runtime handle,\nreplacing the old pattern of passing string names to Device methods.\n\nIfaceConfig is a Copy struct used identically at build time and runtime.\nIt supports routed interfaces (connected to a router's bridg\n[…]\nterface.\n* Explicit IP override on routed interfaces via `.addr()`.\n* Duplicate interface names rejected at build time.\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat!: unified interface API with IfaceConfig, Iface handle, and isol…",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-10T13:19:41Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4c2c0a2d5b8b0ea32deb7c67e81987d58c793155",
"body": "…(#18)\n\nLab::set_link_condition accepted a LinkDirection but silently ignored\nit. The Lab-level method resolves a single interface endpoint per call,\nso directional control was impossible at this abstraction level.\n\nThis removes the parameter and documents the correct pattern for\nbidirectional impai\n[…]\n latency.\n\nFor per-interface directional control, use Device::set_link_condition\nwhich handles LinkDirection correctly.\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix!: remove unused direction parameter from Lab::set_link_condition …",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-09T20:25:45Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "8983acd73938f251ab8cfe1fc43c9f5957701ace",
"body": "`break_region_link` and `restore_region_link` shelled out to `ip route\nreplace` via `std::process::Command`, while every other route operation\nin the crate uses rtnetlink. This replaces them with `nl_run` and a new\n`Netlink::replace_route_v4` method that uses the `NLM_F_REPLACE` flag.\nBoth functions\n[…]\nnc, matching their callers. Net reduction of\n~30 lines.\n\nAll 11 region tests pass including `break_restore_link`.\n\nDepends on #14.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: use rtnetlink for region link break/restore (#16)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-09T20:25:26Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "5c3cab93f007ad8707ac62cb9398e184760df80c",
"body": "Fixes two critical findings from the crate review.\n\nThe NAT64 TUN setup used `unsafe { OwnedFd::from_raw_fd }` followed by\n`mem::forget`, which risked a double-close if a panic occurred between\nthe two lines. Replaced with safe `OwnedFd::from(fd)` which atomically\nconsumes the File.\n\n`replug_iface` \n[…]\n`op.lock().await` guard used by all other mutation methods.\n\nAlso adds a pre-commit hook that runs `cargo make format`.\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: two safeguard issues from crate review (#15)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-09T20:23:19Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "359ef31dcd78428c391534f16ddef07030e2f827",
"body": "Plans and review notes are local working documents, not part of the\nshipped crate. This removes them from the repository.\n\nMost plans were implemented or nearly implemented. I created\nhttps://github.com/n0-computer/patchbay/issues/20 to keep the\nvirtual-time research available.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: remove plans/ and REVIEW.md from repo (#19)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-09T20:23:00Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "765e38bb00b9dc46eb59d097b4e8dcf01ecb54db",
"body": "The three largest source files (core.rs at 3191 lines, lab.rs at 2521,\nhandles.rs at 1726) made navigation difficult and mixed unrelated\nconcerns. This splits them into domain-focused modules where each file\nstays under 2000 lines.\n\nnft.rs (439 lines) takes nftables rule generation, NAT application,\n[…]\n, the Ix handle, presets, and config\nloading. handles.rs is deleted.\n\nAlso adds `Display` for `NodeId` and removes a redundant `Vec<&str>`\nintermediate in qdisc arg building.\n\nNo logic or API changes.",
"is_bot": false,
"headline": "refactor: split core.rs and handles.rs into focused modules (#14)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-09T19:07:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "699170f58efee64ffed010bf7e4c4cca8510e9d6",
"body": "The old DNS system wrote per-device `/etc/hosts` files and bind-mounted\nthem into every namespace thread. Lab-wide `dns_entry()` calls rewrote\nall files on every mutation, and hickory-resolver could miss late\nentries because it reads `/etc/hosts` at construction time.\n\nThis replaces it with an in-pr\n[…]\n` auto-sets\n`resolv.conf`.\n- `Device::dns_entry()` renamed to `Device::set_host()`.\n- `Device::resolve()` is now async.\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat!: replace DNS overlay with in-process DNS server (#13)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-04-09T12:13:54Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "6ad9f77e9051483050ba5b310e67b5d7d5c14d2e",
"body": null,
"is_bot": false,
"headline": "chore: prepare patchbay v0.3.0 release",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-31T12:32:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a26cf729be9a918f420b8bb49642c30874031521",
"body": "`set_link_condition` previously applied netem only on the device-side veth — egress from the device. Download traffic flowed through the unimpaired bridge-side veth in the router namespace. For protocols that rely on bidirectional timing (QUIC holepunching, congestion control), this produced mislead\n[…]\nIngress`) — exported from `patchbay`.\n* **Added** `direction` field to `LabEventKind::LinkConditionChanged`.\n* **Removed** impairment parameter from `DeviceBuilder::iface()` and `Device::add_iface()`.",
"is_bot": false,
"headline": "feat!: bidirectional per-device link impairment (#12)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-03-31T11:32:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "dff4873db89647354d401c70104cebbf971f4c5b",
"body": "curl sends Host without a scheme, so the push response's view_url was\nmissing the protocol prefix.\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: prepend https:// to view_url when Host header lacks scheme (#11)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-03-30T16:50:01Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "03ab97d86a8d79089fca28b038b779451efa4139",
"body": null,
"is_bot": false,
"headline": "chore: prepare patchbay v0.2.0 release",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-30T14:13:26Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4fb9f7355027d7827011ff96963be87a54bc48b1",
"body": "Overhauls run discovery, test result handling, and the compare UI to\nsupport the full CI-to-UI workflow without requiring a patchbay binary\nin CI.\n\nThe server now uses `events.jsonl` as the sole leaf-run indicator and\ntreats `run.json` without it as a group manifest. Test results are built\nfrom dire\n[…]\nor user namespace init is restored for\nnextest-spawned test processes. Legacy `batch`/`invocation` aliases are\nremoved.\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: improve run discovery and group pages (#10)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-03-30T13:29:08Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "52890e15fbf55bd462a7e1317df5a672e1c61059",
"body": null,
"is_bot": false,
"headline": "chore: fixup CI",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-27T13:33:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3e92f5f698e9ed7613a8bd1d34a66fdce3ff29f2",
"body": "Unified CLI\n\nWe consolidated `patchbay-runner` and `patchbay-vm` into libraries\nbehind a single `patchbay-cli` crate. The `patchbay` binary auto-detects\nnative vs VM backends, with VM commands nested under `patchbay vm`. All\npaths consolidate under `.patchbay/` — work output, VM state, and\nworktrees\n[…]\nes\nwhen missing. The CI template installs via `cargo binstall` with\n`--git-url` and falls back to building from source.\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: unified CLI, compare mode, metrics collection (#9)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-03-27T13:14:53Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "674b80b250ad4b63fdd586e5961849e8e6770f63",
"body": "Add an alternative VM backend using Apple's Containerization framework\n(macOS 26 + Apple Silicon). The container backend provides sub-second\nboot times and native VirtioFS mounts, replacing QEMU's SSH-based\ninteraction with `container exec`.\n\n- Split vm.rs into common.rs (shared types/helpers), qemu\n[…]\nemu|container flag with auto-detection\n- Default to all host CPUs and 8GB RAM for both backends\n- Update docs/guide/vm.md with setup guides for both backends\n- Add .container-vm and .tmp to .gitignore",
"is_bot": false,
"headline": "feat: add Apple container backend for patchbay-vm (#7)",
"author_name": "Asmir Avdicevic",
"author_login": "Arqu",
"committed_at": "2026-03-25T10:30:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9f41d41e3030e38eba405e7052c4566f8f7831f0",
"body": "The sync worker used to install its own tracing subscriber, creating a\nnew events.jsonl file that truncated the async worker's output. Now the\nasync worker's dispatch is captured and passed to the sync worker so\nboth share the same file handles.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: share tracing dispatch between async and sync namespace workers",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-24T13:28:51Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "94876c49879dc51c50dcf4503739c83013dad0f4",
"body": "When a step template has results like `down_bytes = \".size\"`, this gets\nexpanded to `\"fetcher.size\"` during template merge. But for counted\ndevices (fetcher-0, fetcher-1, ...), the capture is stored under\n`\"fetcher-0.size\"` while the results key remained `\"fetcher.size\"`.\n\nFix by also rewriting Step\n[…]\nize\"` for the expanded step.\n\nThis fixes missing results in combined-results for multi-device sims\n(1to3, 1to5, 1to10, 2to2, etc).\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: rewrite results capture keys during counted device expansion (#6)",
"author_name": "Franz Heinzmann",
"author_login": "Frando",
"committed_at": "2026-03-24T11:30:46Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "887f9ffd3bb077c5c1ae732503808c1a1e98c03f",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: reduce default capture timeout from 300s to 30s",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T15:06:02Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8fca4d02522c59f35ec1bcc5f82cc5c74b7d7055",
"body": "- Test round-robin rewriting of ${provider.capture} in cmd args\n- Test bare requires refs (provider.ready -> provider-0.ready)\n- Test that non-counted device refs are left untouched\n- Fix requires to use bare ref rewriter (no ${} wrapper)\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test: add tests for counted device ref rewriting",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T14:35:41Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "7544b19bcead4faa57b51b503cb4d02833c0a87e",
"body": "When a step is expanded for a counted device (e.g. fetcher-0, fetcher-1),\nalso rewrite ${other_counted_device.capture} references in cmd/args to\n${other_counted_device-{idx}.capture}. Uses modulo for round-robin when\ncounts differ (e.g. 4 fetchers across 2 providers).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: rewrite variable refs during counted device expansion",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T14:33:07Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9bdd7fc528117b0bb1ce949399b95d1bc75c0dda",
"body": "After setns(CLONE_NEWNET), /proc/net (a symlink to self/net) still\nresolves to the thread group leader's network namespace, not the calling\nthread's. Only /proc/thread-self/net reflects the new namespace.\n\nThis caused libraries like netwatch that read /proc/net/route to get the\nhost's default route \n[…]\nLONE_NEWNS) on every\nnamespace thread and bind-mount /proc/thread-self/net over /proc/net.\nAlso make the tokio blocking pool on_thread_start unconditional so\nspawned blocking threads get the same fix.",
"is_bot": false,
"headline": "fix: bind-mount /proc/thread-self/net over /proc/net in namespaces (#5)",
"author_name": "Friedel Ziegelmayer",
"author_login": "dignifiedquire",
"committed_at": "2026-03-23T12:04:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1637f144851b9f477c649d8784cd0988b6a3bbd2",
"body": null,
"is_bot": false,
"headline": "chore: run CI on all pull requests",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T12:02:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "11685cc975fa9c68990e2d89c0f5bf05f9fd4f40",
"body": null,
"is_bot": false,
"headline": "chore: fmt",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T12:01:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5ed18dc1f998debb97b4ad88fb9ff9da6afb0fb0",
"body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: extract AxisParams type alias to satisfy clippy type_complexity",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T11:49:12Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c3139aff509fd4bd55445fa77e1b35a5d3e49943",
"body": "The `prepare_sims` function was assembling (copying) binaries before\nrunning the prepare build step, so it failed when binaries didn't\nexist yet. Swap the order so builds run first.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: run prepare builds before binary assembly",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T11:40:03Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "3a60cd9d0539d01b0e03049e23c0a598c29b9e38",
"body": "Document [matrix] table, multi-axis Cartesian product, params,\nconditional steps with when, and string coercion for link condition\nfields. Add ${matrix.*} to variable interpolation table.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: add matrix expansion and when field to TOML reference",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T10:24:33Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "729bc67bbb9df8a95c0e690c4476eb32c3cd5203",
"body": "A `[matrix]` table in a sim TOML defines axes whose Cartesian product\ngenerates multiple simulation variants. Substitution replaces\n`${matrix.*}` placeholders in string values of the parsed toml::Value\ntree — files remain valid TOML at every stage.\n\nFeatures:\n- Single and multi-axis matrix with Cart\n[…]\nd\n string values like `latency_ms = \"200\"` work alongside native numbers\n- Backward compatible: files without `[matrix]` produce exactly 1 sim\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add [matrix] expansion for sim TOML files",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T10:21:04Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "57641d454a1c5bdab714d47ba0fe1f0f9f63e64a",
"body": "The `serve` feature (enabled by default) gates the Serve subcommand\nand the --open flag in Run. Without it, patchbay-server is not compiled\nas a dependency.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: put patchbay-server integration behind `serve` feature",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T09:30:51Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8efa1317b7a717b8311f01d5b431aadb15577e04",
"body": "- Merge / and /runs into a single RunsIndex component\n- Remove /api/pushed-runs; /api/runs now includes manifest from run.json\n- Remove PushedRunsIndex (merged into RunsIndex)\n- Rename RunManifest.status to test_outcome to distinguish from lab\n lifecycle status (state.json). The JSON field accepts both names\n via serde alias for backward compat with existing run.json files.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: merge runs index, unify /api/runs with manifest data",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T09:01:43Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "866aa8fd6603e3a33a1752d4355a6cb6c448e55d",
"body": "- Add /api/pushed-runs endpoint returning RunIndexEntry with manifests\n- Add status field to RunManifest for CI test outcome\n- Replace server-side HTML at /runs with React SPA + PushedRunsIndex\n- Show branch, commit, PR link, title, status in pushed runs listing\n- Add github-workflow-template.yml wi\n[…]\n in PR comments\n- Replace inlined YAML in README with link to template file\n- Backward compat: testdir mode (/) unchanged, pushed runs at /runs\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: move pushed-runs listing to React UI, add workflow template",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-23T09:01:43Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "0e388f96aa7547d1e2e7108ba8e8d76cb7db5cc0",
"body": "fix: apply proper fullcone NAT rules for CGNAT (EIM+EIF)",
"is_bot": false,
"headline": "Merge pull request #4 from n0-computer/fix/cgnat-fullcone-rules-v2",
"author_name": "Friedel Ziegelmayer",
"author_login": "dignifiedquire",
"committed_at": "2026-03-22T20:19:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "78540fb279ba897fc588b08b221b4147f09b6f33",
"body": "CGNAT was special-cased with plain `masquerade` which had no prerouting\nDNAT chain. Without a prerouting chain, inbound packets to mapped ports\nwere dropped instead of being forwarded — breaking the EIF (endpoint-\nindependent filtering) guarantee that CGNAT is documented to provide.\n\nThis removes th\n[…]\nles()`\nlike all other NAT types, getting the fullcone dynamic map for correct\nport-preserving SNAT and unconditional inbound DNAT.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: apply proper fullcone NAT rules for CGNAT (EIM+EIF)",
"author_name": "dignifiedquire",
"author_login": "dignifiedquire",
"committed_at": "2026-03-22T18:15:00Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "10e39e60b59e7f5fe4887ca574e060a8d721d6f7",
"body": null,
"is_bot": false,
"headline": "chore: fmt",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T14:12:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e905ff68254c70d25523715104d804cdf77c218d",
"body": "Replace the fragile thread-spawn + Handle::try_current approach with a\nshared Arc<Mutex<LabState>> between the writer task and LabInner. The\nwriter updates the shared state on every event. LabInner::drop reads\nit, sets the final status, and writes state.json synchronously — no\nasync runtime needed.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: sync final state.json write via shared LabState mutex",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T12:01:00Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "88f2344b7f148e517260e30ca2414a0045beda3d",
"body": "LabInner::drop now blocks on the writer task handle so it always gets\nto do its final flush (drain events, set status, write state.json).\nAs a fallback, if state.json still doesn't exist (test finished before\nthe first 1-second flush interval), drop creates a minimal state.json\nwith the correct status. Fixes fast tests showing \"running\" forever.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: block on writer completion in drop, create state.json if missing",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T11:49:36Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "38f2226a7f52e25d689c48e4e222e946d8ff4ec7",
"body": "TestGuard now emits a TestCompleted lab event (with passed: true/false)\nso the test result is visible in the timeline. The _lab node column is\nsorted before device nodes in the timeline grid.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: emit TestCompleted event, sort _lab first in timeline",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T10:28:16Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "d75987aed81ab8525d7e0cbac4a3e01970d9fc50",
"body": "Lab::test_guard() returns an RAII guard that records test outcome.\nCalling .ok() marks success; dropping without .ok() (panic or early\nerror return) marks failure. The writer reads the status on shutdown\nand LabInner::drop() synchronously patches state.json so the final\nstatus is always written, even during panic unwind.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add TestGuard for per-test pass/fail status in state.json",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T09:29:45Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "e69d5134e533397a341df57c13713b5b8ca5bea8",
"body": "Add GET /api/runs/{run}/events.json REST endpoint for fetching all\nevents as a JSON array. Client now loads initial data via REST and only\nopens SSE connections for runs with status \"running\". Runs list uses\npolling instead of SSE. Tabs showing completed runs use zero persistent\nconnections, fixing hangs when many tabs are open.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: replace SSE with REST for initial load, SSE only for live runs",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T09:23:57Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "ff8f0b67da49742de714ec59794bc6c52fe5334e",
"body": "TLS-ALPN-01 challenges require port 443; bail if --https-bind uses a\ndifferent port. Warn if --http-bind is not port 80 since browsers\nwon't follow the redirect.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: validate ACME port requirements at startup",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T08:24:08Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "bc821ac5394154f67deb2bf4e1a8cd2256b57bb0",
"body": "Replace --bind with --http-bind (default 0.0.0.0:8080) and\n--https-bind (default 0.0.0.0:4443). Service template uses\n80/443 with CAP_NET_BIND_SERVICE for privileged ports.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: split bind into --http-bind and --https-bind",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T08:06:19Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8f28d1f4d8cdeebfcb1685a61df11fb755167ba6",
"body": "IPv6-only bind doesn't work on hosts without IPv6 enabled.\nUse 0.0.0.0:80 and 0.0.0.0:443 for the ACME redirect and\nTLS listeners.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: bind ACME listeners on 0.0.0.0 instead of [::]",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T08:03:06Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6424cbbfe18d33b0a7e82ae2801e7df489e3e611",
"body": "Rustls requires an explicit CryptoProvider when no default is\nselected via crate features. Install ring as the default provider\nbefore any TLS operations.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: install rustls crypto provider at startup",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T07:56:40Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "705c0d4fb2d264821e9655886a1b0ead4e767d93",
"body": "Step-by-step systemd deployment (create user, install binary,\nconfigure unit, start) and GitHub Actions snippet for pushing\nresults and commenting on PRs.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: add patchbay-server README with deploy and CI docs",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T07:53:08Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b31372d1cc2fa129f5103559a22ff3cc0f097ddb",
"body": "Tests the full push flow: run a sim, start patchbay-serve with\n--accept-push, tar+gz the output and POST to /api/push/{project},\nverify the response, open the deep link /#/inv/{invocation}, verify\nthe sims tab lists the run, click through to topology view, and\ncheck auth rejection without API key. Also verifies the server-side\n/runs index page renders manifest fields (branch, PR link).\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "test: add e2e test for push API and deep linking",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-20T06:30:40Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "c3d79aac2cd21edf036d5d7465c4c6c0140b1c8f",
"body": "- Push creates {project}-{date}-{uuid} (flat, no nesting) so the dir\n name IS the invocation. CI link: /#/inv/{invocation}\n- Invocation view now has a \"sims\" tab listing all runs in the group,\n with links to each. Perf tab still available for combined results.\n- RunsIndex auto-redirects: single ru\n[…]\nst_run from push response (unnecessary)\n- Simplify retention (flat dir scan)\n- Fix multi-sim e2e test to click perf tab explicitly\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: flat run dirs, sims tab in invocation view, fix deep linking",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-19T23:27:16Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "f92295bb77074fb8ba1d37e760345f6d7e7a98d6",
"body": "Add react-router-dom with HashRouter for URL-based navigation:\n- /#/ — runs index page listing all runs with links to each\n- /#/run/{name} — deep link to a specific sim run\n- /#/inv/{name} — deep link to an invocation (combined view)\n\nThe dropdown in the topbar navigates via the router. The patchbay\n[…]\n sim name)\nso CI can build a direct deep link into the UI. CI snippet updated\nto use `/#/run/{first_run}` for the PR comment link.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add deep linking with react-router HashRouter",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-19T23:02:03Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1cfe67a4ef58edf5ff924207593d4404b26a1e60",
"body": "The UI doesn't support ?run= query params for deep linking. Fix CI\nsnippet to use /runs#path fragment (scrolls to run entry). Fix runs\nindex \"View\" link to point to / where the sidebar lists all runs.\nAdd :target CSS highlight so fragment-linked runs are visually marked.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: correct view URL in CI snippet and runs index page",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-19T22:54:24Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "94f77b0a971ceb837ee2f37c3daf6993b89ace50",
"body": "- Add patchbay-serve.service with hardening (ProtectSystem, NoNewPrivileges, etc.)\n- Restructure testing.md: local tests → CI integration → patchbay-serve deployment\n- Move server docs to end as its own section with install/systemd instructions\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add systemd unit file, restructure testing docs",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-19T22:49:57Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "aedf9c05eda0574e846650e875b28f649529182d",
"body": "Add a standalone `patchbay-serve` binary for hosting run results remotely.\nCI pipelines can push test results via `POST /api/push/{project}` (tar.gz)\nand get a link back for viewing in the devtools UI.\n\n- Push endpoint with Bearer token auth, stores runs as {project}/{date}-{uuid}\n- run.json manifes\n[…]\nckground retention watcher (--retention) deletes oldest runs over limit\n- GitHub Actions snippet and deployment docs in testing.md\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add patchbay-serve binary with push API, ACME TLS, and retention",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-19T22:47:02Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "2920b8c13ead82adaab5624c12a0b8c234ebd2e5",
"body": "…an rendering\n\nTimeline: skip text/ansi logs when structured jsonl exists for a node,\nstrip trailing colon from tracing event kinds, unquote field values.\nJump-to-log: try exact full-precision timestamp match before falling\nback to nearest-millisecond. Spans: bold names only, dim punctuation\nand field keys, white field values. Remove font-size variation in log lines.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: deduplicate timeline events, fix jump-to-log precision, style sp…",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-13T10:27:17Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "e0c48e094ae11442b1ea374b6d4d8fd55a498ac1",
"body": null,
"is_bot": false,
"headline": "chore: update .gitignore",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-12T12:27:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8b53233c3afcf570e94e49bcd40de3f8af6872a4",
"body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: bump GitHub Actions to v5 to fix Node.js 20 deprecation",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-12T12:26:01Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "67fe8f049e0b09789f7968c2e479ea03fe5f8982",
"body": null,
"is_bot": false,
"headline": "deps: cleanup and bump all deps",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-12T12:20:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c300b995f5d4a3410c78f09f64c98226032e315b",
"body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "chore: fmt patchbay-runner",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-12T12:13:28Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2770ff41cf95c3ba36d7b5c7755eae9e84c0e4d8",
"body": "Rewrite the patchbay crate-level documentation to focus on the builder\nAPI with concrete examples for topology building, running code in\nnamespaces, router presets, link conditions, multi-region routing, and\ndynamic operations.\n\nRemove the ObservedAddr type alias (was just SocketAddr) and replace\nal\n[…]\nused by external crates. Re-export\nReflectorGuard (returned by public spawn_reflector methods). Fix\nunnecessary core:: qualifications in tests.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: improve lib.rs docs, remove ObservedAddr, tighten visibility",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-12T12:13:12Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "203c6e966c7eff3f30a7a430ed58649afa3cbd4b",
"body": "Install iperf3 in the e2e CI job (was only in the ci job), scope\ntracing file locators to node groups to match the UI prefix stripping,\nand use .first() for timeline event locators to avoid strict mode\nviolations.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: fix e2e test failures in CI",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-12T11:53:39Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "af3801e9928ae52738c19f259d8be7a6dae27648",
"body": "- When no sims are specified on CLI, look for patchbay.toml or\n .patchbay.toml in project root with `simulations = \"path/to/sims\"`\n- Recursive directory scanning for *.toml sim files in subdirectories\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add patchbay.toml config and recursive sim directory scanning",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-06T08:09:12Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "bd53b9a86906694a59b15ab0ac15da2d7151ceaf",
"body": "Add content-based detection of tracing-subscriber JSON output\n(lines with timestamp, level, target keys) so command stderr\nlogs are correctly classified without needing TOML hints.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: detect tracing-jsonl logs by content in server",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T23:05:24Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "f21a94f8757da84a97abc4692c8ff36a257b648d",
"body": "…improvements\n\n- Write command stdout/stderr as flat files (device.{name}.{id}.stdout.log)\n so the server discovers them automatically\n- Emit CommandStarted/CommandCompleted events for timeline visibility\n- PerfTab: human-readable byte formatting, clickable sim links\n- LogsTab: strip device prefix from filenames, add download button\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: flat stdout/stderr log files, command lifecycle events, and UI …",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T23:04:47Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "efb0f734957e587d93a35d2d9f2599bc08edad9b",
"body": "…on edge cases\n\nAdd --project-root flag to run/prepare subcommands for specifying the\nproject root directory instead of defaulting to cwd.\n\nAdd --timeout flag for per-sim deadline enforcement. Uses Instant-based\ndeadlines threaded through SimState since tokio::time::timeout cannot\nfire on current_th\n[…]\n.direct_addresses.0 on empty array), preventing\ncaptures from blocking forever. Add filtering to drop --flag <empty> pairs\nafter interpolation.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add --project-root, --timeout flags and fix capture/interpolati…",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T22:13:05Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "66b7fc582f8625a707db8417b588e246a79263fe",
"body": "Add server-side invocation field to RunInfo (derived from directory\nstructure) and a /api/invocations/{name}/combined-results endpoint.\nThe UI now groups runs by invocation in the selector dropdown with\nan optgroup, offering a \"combined\" option that shows aggregated\nresults across all sims in the in\n[…]\n`mode` field,\nnormalize iroh-defaults.toml to use `action` (preserving `kind` in\nmatch fields), and add iperf e2e fixture + multi-sim e2e test.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add invocation grouping and combined results view to UI",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T16:44:04Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c7fb67af9cd17267dc3f9f2571534384fc00ea29",
"body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: move simple example from patchbay-runner to patchbay",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T12:44:49Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "2668e1f38c480cb11a1da9341edfbdf987c23924",
"body": "Write human-readable ANSI-formatted .tracing.log files alongside existing\n.tracing.jsonl files for each namespace. The ANSI formatter pipes JSON\nlog lines through format_json_as_ansi, producing output that matches\ntracing-subscriber's default fmt format bit-for-bit (verified by parity\ntest). This removes the need for the standalone fmt-log CLI command,\nwhich has been deleted.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add .tracing.log ANSI output per namespace",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T12:44:39Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "1c1cd13ce2fd1cd27acc6fe92becdd288fac3559",
"body": null,
"is_bot": false,
"headline": "chore: fmt",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T11:58:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9310b1dbdb107e2abd02941290e81b877a190e69",
"body": "Close all EventSource connections on beforeunload to prevent Firefox's\n6-connection-per-domain HTTP/1.1 limit from blocking fetch requests\nafter page refresh. Also stop JsonTree field name clicks from\ncollapsing the parent object.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: close SSE connections on page unload and fix JsonTree key click",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T11:34:41Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b882445fa3b412244d2eb4d0c5fd908cbd9f39aa",
"body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: add fmt-log command to testing guide",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T11:22:20Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9c8dde10be11eb175dac170414920067bd33f655",
"body": "…ilter\n\nReplace LevelFilter with tracing_subscriber::filter::Targets so that\ndirective strings like `myapp=debug,patchbay::netlink=trace` are parsed\ncorrectly instead of silently falling back to INFO.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: support full directive syntax in PATCHBAY_LOG / RUST_LOG file f…",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T11:20:36Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b4bc8db75d772f6668614cd77efc90a85a7b3369",
"body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "style: cargo fmt patchbay-vm",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T11:04:34Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "8c2c3334b839a52635b163655c16a239da3a4c94",
"body": "The writer now sets status=\"stopped\" when the broadcast channel closes\nor the cancel token fires, instead of relying on an explicit LabStopping\nevent. This fixes the e2e test where Device/Router handles kept the\nArc<LabInner> alive, preventing the event from being emitted before the\ntest assertion.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: write stopped status on channel close instead of LabStopping event",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T10:49:10Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9355fc4c8cfd5816d410ede0f7e8519411a41bf9",
"body": null,
"is_bot": false,
"headline": "chore: update gitignore",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T10:32:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2a35cca613b217e6d0bd46896f7349ba59eae750",
"body": "- Add short CLI aliases (-p, -j, -F, etc.) and positional test filter\n- Parallelize VM boot and cargo build with std::thread::scope\n- Stream cargo build output with [qemu]/[cargo]/[test] prefixes\n- Fix virtiofs uid mapping with --translate-uid squash-guest for\n writable mounts so testdir output is \n[…]\nnt stale key errors\n- Forward RUST_LOG, RUST_BACKTRACE, and other env vars to guest\n- Add testing guide docs page and vm_smoke integration test\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: improve patchbay-vm test command and fix virtiofs permissions",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T10:32:07Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "19358e6627bef6934221a8422c379b1059725e19",
"body": "Both `patchbay serve --testdir` and `patchbay-vm serve --testdir` now\nresolve the testdir-current directory automatically instead of\nrequiring a manual path.\n\nNative (patchbay): runs `cargo metadata` to find the target directory\nand serves `<target-dir>/testdir-current`.\n\nVM (patchbay-vm): serves `<work-dir>/binaries/tests/testdir-current`,\nwhere the testdir crate writes output next to the test executable.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat: add --testdir flag to serve commands",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T09:37:41Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "aeec33eee56f32d1cdc84345605b3802a63ea350",
"body": "JsonTree: clicking any key in an expanded object now collapses it back.\nCollapsed summaries use correct singular/plural (\"1 item\" vs \"3 items\").\n\nTimeline detail panel: remove the raw JSON dump below the KvPairs\nfields. KvPairs gains a `vertical` prop for multi-line rendering in the\ndetail pane whil\n[…]\no state.json ends with\nstatus \"stopped\" instead of staying stuck on \"running\". Add assertion\nin the devtools e2e Rust test and playwright test.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: json tree toggle, timeline detail cleanup, and lab stop status",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T09:31:10Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "49d26965dd6af3870c2fd49e6a39f7a16a016b56",
"body": "Merge Mobile/MobileV6 into IspCgnat/IspV6 since mobile carriers use\nthe same CGNAT and NAT64 configurations as wireline ISPs. Rewrite all\nRouterPreset doc comments to follow writing.md style and Rust doc\nconventions. Update simple.rs example to use presets and spawn_command.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: consolidate router presets and improve documentation",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T09:12:00Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "79e5ae26c82cf4b55b69abb30297e2479fe7aaab",
"body": "Move completed items (recursive scan, OutDir enum, dead qdisc code,\nIpv6Profile variants) to REVIEW.md completed section. Add doc comment\nto Ipv6Profile noting future divergence intent for variants that\ncurrently share the same mode tuple. Reclassify DeviceSetupData clone\nas structurally required.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "docs: update REVIEW.md and add Ipv6Profile divergence comment",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T08:25:12Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "b0dd032ab2c6bdfbe5f6dcb8dbe391dd88b47282",
"body": "Replace separate outdir/run_dir fields on LabOpts with a single OutDir\nenum (Nested creates timestamped subdir, Exact writes directly). Server\nnow scans up to 3 levels deep for run directories and supports\nsingle-run mode when base dir itself contains events.jsonl. Symlinks\nare skipped during scan t\n[…]\n\"latest\" link.\nRunner uses OutDir::Exact to write directly into its work dir, removing\nthe need for PATCHBAY_OUTDIR in the runner-sim e2e test.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: introduce OutDir enum and recursive server scan",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T08:20:30Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e87a72e5463b34e10d3a4aa330c1e7613efaad7e",
"body": "…endering\n\nRemove the dedicated events tab; events.jsonl now appears in the logs\nsidebar as a lab_events file kind with a shared JsonLinesTable component.\nAdd collapsible JsonTree for json files (state.json etc). Extract shared\ne2e helper using cargo-metadata to resolve the target directory. Add\nplaywright globalSetup to build UI and cargo workspace before e2e tests.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "refactor: replace events tab with lab_events file kind and DRY JSON r…",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T08:08:38Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "9134facc8886e8733876bb8122018991c70642d1",
"body": "- Fix compile error in patchbay-runner topology.rs (missing RA fields)\n- Unify replace_default_route_v6 and replace_default_route_v6_scoped\n into single method; add set_default_route_v6 convenience helper\n- Replace open-coded RA-enabled guard with ra_default_enabled()\n- Consolidate RS emit logic in\n[…]\nration functions\n- Remove unnecessary check_caps from preset_recommended_ipv6_profiles\n- Add Relaxed ordering rationale comment on RaRuntimeCfg\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix: deduplicate v6 route dispatch, RA guard, and RS emit logic",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T00:23:01Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "72a823551b3d3a06016dfd477796490caae49393",
"body": null,
"is_bot": false,
"headline": "docs: improve prose and writing style",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-05T00:05:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0058fe3f832e06c5bcf9e991c3b15c30e426bf25",
"body": null,
"is_bot": false,
"headline": "merge: bring main into ip6-link-local",
"author_name": "Frando",
"author_login": "Frando",
"committed_at": "2026-03-04T23:25:13Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 3,
"commits_last_year": 308,
"latest_release_at": "2026-03-04T11:15:42Z",
"latest_release_tag": "rolling",
"releases_from_tags": false,
"days_since_last_push": 0,
"active_weeks_last_year": 12,
"days_since_latest_release": 145,
"mean_days_between_releases": -30.5
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": false,
"health_percentage": 37,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "patchbay",
"exists": true,
"license": "MIT OR Apache-2.0",
"keywords": [
"namespace",
"nat",
"network",
"simulation",
"testing"
],
"ecosystem": "crates",
"matches_repo": true,
"registry_url": "https://crates.io/crates/patchbay",
"is_deprecated": false,
"latest_version": "0.7.0",
"repository_url": "https://github.com/n0-computer/patchbay",
"versions_count": 9,
"total_downloads": 16351,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": 4356,
"first_published_at": "2026-03-12T12:31:23.728809Z",
"latest_published_at": "2026-07-27T14:04:20.399257Z",
"latest_version_yanked": false,
"days_since_latest_publish": 0
}
]
},
"popularity": {
"forks": 1,
"stars": 33,
"watchers": 1,
"fork_history": {
"days": [
{
"date": "2026-03-03",
"count": 1
}
],
"complete": true,
"collected": 1,
"total_forks": 1
},
"star_history": null,
"open_issues_and_prs": 7
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [
"examples"
],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [
"ui/tsconfig.json"
],
"toolchain_manifests": [
"Cargo.toml",
"patchbay-cli/Cargo.toml",
"patchbay-cli/tests/fixtures/counter/Cargo.toml",
"patchbay-runner/Cargo.toml",
"patchbay-server/Cargo.toml",
"patchbay-utils/Cargo.toml",
"patchbay-vm/Cargo.toml",
"patchbay/Cargo.toml"
],
"largest_source_bytes": 78703,
"source_files_sampled": 107,
"oversized_source_files": 3,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"Cargo.toml",
"patchbay-cli/Cargo.toml",
"patchbay-runner/Cargo.toml",
"patchbay-server/Cargo.toml",
"patchbay-utils/Cargo.toml",
"patchbay-vm/Cargo.toml",
"patchbay/Cargo.toml",
"ui/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": [
"crates",
"npm"
],
"dependencies": [
{
"name": "anyhow",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "chrono",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "clap",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "4"
},
{
"name": "flate2",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "open",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "5"
},
{
"name": "patchbay-server",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": null
},
{
"name": "patchbay-utils",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": null
},
{
"name": "patchbay-vm",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": null
},
{
"name": "reqwest",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.13"
},
{
"name": "serde",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "serde_json",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "tar",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "tokio",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "toml",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1.0"
},
{
"name": "tracing",
"manifest": "patchbay-cli/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.1"
},
{
"name": "anyhow",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "chrono",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "clap",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "4"
},
{
"name": "comfy-table",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "7"
},
{
"name": "flate2",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "patchbay",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": null
},
{
"name": "patchbay-utils",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": null
},
{
"name": "nix",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.31"
},
{
"name": "rcgen",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.14"
},
{
"name": "regex",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "serde",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "serde_json",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "tar",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "tokio",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "toml",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1.0"
},
{
"name": "tracing",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.1"
},
{
"name": "tracing-subscriber",
"manifest": "patchbay-runner/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.3"
},
{
"name": "axum",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.8"
},
{
"name": "tokio",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "tokio-stream",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.1"
},
{
"name": "tokio-rustls-acme",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.9.1"
},
{
"name": "anyhow",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "async-stream",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.3"
},
{
"name": "clap",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "4"
},
{
"name": "dirs",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "6"
},
{
"name": "flate2",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "serde",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "serde_json",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "tar",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "tracing",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.1"
},
{
"name": "tracing-subscriber",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.3"
},
{
"name": "uuid",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "chrono",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "patchbay-utils",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": null
},
{
"name": "axum-server",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.8"
},
{
"name": "rustls",
"manifest": "patchbay-server/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.23"
},
{
"name": "anyhow",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "flate2",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "glob",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.3"
},
{
"name": "reqwest",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.13"
},
{
"name": "serde",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "serde_json",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "sha2",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.11"
},
{
"name": "tar",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "tracing",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.1"
},
{
"name": "chrono",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "tracing-subscriber",
"manifest": "patchbay-utils/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.3"
},
{
"name": "anyhow",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "clap",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "4"
},
{
"name": "dirs",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "6"
},
{
"name": "patchbay-utils",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": null
},
{
"name": "nix",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.31"
},
{
"name": "serde",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "serde_json",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "toml",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1.0"
},
{
"name": "tracing",
"manifest": "patchbay-vm/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.1"
},
{
"name": "iroh-metrics",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1.0.0"
},
{
"name": "anyhow",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "chrono",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.4"
},
{
"name": "derive_more",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "2.1.1"
},
{
"name": "futures",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.3"
},
{
"name": "ipnet",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "2.11"
},
{
"name": "libc",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.2"
},
{
"name": "nix",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.31"
},
{
"name": "rtnetlink",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.21"
},
{
"name": "serde",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "serde_json",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "strum",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.28"
},
{
"name": "tokio",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1"
},
{
"name": "hickory-proto",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.26"
},
{
"name": "tokio-util",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.7"
},
{
"name": "toml",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "1.0"
},
{
"name": "tracing",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.1"
},
{
"name": "tracing-core",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.1"
},
{
"name": "tracing-subscriber",
"manifest": "patchbay/Cargo.toml",
"ecosystem": "crates",
"version_constraint": "0.3"
},
{
"name": "@types/dagre",
"manifest": "ui/package.json",
"ecosystem": "npm",
"version_constraint": "^0.7.54"
},
{
"name": "@xyflow/react",
"manifest": "ui/package.json",
"ecosystem": "npm",
"version_constraint": "^12.10.1"
},
{
"name": "dagre",
"manifest": "ui/package.json",
"ecosystem": "npm",
"version_constraint": "^0.8.5"
},
{
"name": "react",
"manifest": "ui/package.json",
"ecosystem": "npm",
"version_constraint": "^18.2.0"
},
{
"name": "react-dom",
"manifest": "ui/package.json",
"ecosystem": "npm",
"version_constraint": "^18.2.0"
},
{
"name": "react-router-dom",
"manifest": "ui/package.json",
"ecosystem": "npm",
"version_constraint": "^7.13.1"
}
],
"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": 5,
"merged_prs": 34,
"open_issues": 2,
"closed_ratio": 0,
"closed_issues": 0,
"closed_unmerged_prs": 2
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "Frando",
"commits": 301,
"avatar_url": "https://avatars.githubusercontent.com/u/43627?v=4"
},
{
"type": "User",
"login": "dignifiedquire",
"commits": 9,
"avatar_url": "https://avatars.githubusercontent.com/u/790842?v=4"
},
{
"type": "User",
"login": "Arqu",
"commits": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/1760977?v=4"
}
],
"contributors_sampled": 3,
"top_contributor_share": 0.968
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"book.yml",
"ci.yml",
"release-rolling.yml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"Cargo.lock",
"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": null,
"reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 9,
"reason": "24 out of 25 merged PRs checked by a CI test -- score normalized to 9",
"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": 1,
"reason": "Found 3/30 approved changesets -- score normalized to 1",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 10,
"reason": "project has 28 contributing companies or organizations",
"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": 0,
"reason": "no 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": 8,
"reason": "10 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 8",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": null,
"reason": "packaging workflow not 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": "SAST tool is not run on all commits -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 0,
"reason": "security policy file not detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": 0,
"reason": "Project has not signed or included provenance with any releases.",
"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": 0,
"reason": "27 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "5cc60db1eb190360dfcd64eaf2f829bce4072551",
"ran_at": "2026-07-27T21:16:31Z",
"aggregate_score": 3.4,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": false,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-27T14:00:56Z",
"oldest_open_prs": [
{
"number": 26,
"created_at": "2026-04-11T13:54:13Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 33,
"created_at": "2026-04-14T08:02:21Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 34,
"created_at": "2026-04-14T13:00:19Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 36,
"created_at": "2026-04-15T08:11:18Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 38,
"created_at": "2026-04-23T21:34:38Z",
"last_comment_at": null,
"last_comment_author": null
}
],
"last_merged_pr_at": "2026-07-27T11:13:20Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": [
{
"number": 8,
"created_at": "2026-03-24T12:01:30Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 20,
"created_at": "2026-04-09T20:20:47Z",
"last_comment_at": null,
"last_comment_author": null
}
]
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/n0-computer/patchbay",
"host": "github.com",
"name": "patchbay",
"owner": "n0-computer"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": "The weighted overall 58 is calibrated to 62 on the published index scale (record calibration 2026-08-02).",
"notes": [
{
"code": "overall_calibration",
"params": {
"raw": 58,
"calibrated": 62,
"calibration": "2026-08-02"
}
}
],
"value": 62,
"inputs": {
"security": 34,
"vitality": 74,
"community": 42,
"governance": 54,
"calibration": "2026-08-02",
"engineering": 80,
"ai_readiness": 59,
"weighted_overall_raw": 58
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 74,
"weight": 0.21,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 70,
"inputs": {
"commits_last_year": 308,
"human_commit_share": 1,
"days_since_last_push": 0,
"active_weeks_last_year": 12
},
"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": "12/52 weeks with commits",
"points": 8.3,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 12
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "308 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 308
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "10 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 8",
"points": 8,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": null,
"notes": [],
"value": 81,
"inputs": {
"releases_count": 3,
"latest_release_tag": "rolling",
"releases_from_tags": false,
"days_since_latest_release": 145,
"mean_days_between_releases": -30.5
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "3 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 3
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 145 days ago",
"points": 27,
"status": "partial",
"details": [
{
"code": "release_recency",
"params": {
"days": 145
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~-30.5 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": -30.5
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "exceptional",
"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": "weak",
"name": "Community & Adoption",
"value": 42,
"weight": 0.17,
"metrics": [
{
"key": "popularity",
"band": "at_risk",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 24,
"inputs": {
"forks": 1,
"stars": 33,
"watchers": 1,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "33 stars",
"points": 24.4,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 33
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "1 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 1
}
}
],
"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": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"readme_badges": null,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"readme_badge_services": [],
"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 (Apache-2.0)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "Apache-2.0"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"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
}
]
},
{
"key": "ecosystem_adoption",
"band": "moderate",
"name": "Ecosystem adoption (downloads)",
"note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"registry_dependents"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 61,
"inputs": {
"packages": [
"patchbay"
],
"dependents": null,
"ecosystems": "crates",
"total_downloads": 16351,
"monthly_downloads": 4356
},
"components": [
{
"key": "monthly_downloads",
"name": "Monthly downloads",
"detail": "4,356 downloads/month across crates",
"points": 48.5,
"status": "partial",
"details": [
{
"code": "downloads_monthly",
"params": {
"count": 4356,
"ecosystems": "crates"
}
}
],
"max_points": 80
},
{
"key": "registry_dependents",
"name": "Registry dependents",
"detail": "not reported by this ecosystem",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_reported_by_this_ecosystem",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 54,
"weight": 0.23,
"metrics": [
{
"key": "maintainer_resilience",
"band": "at_risk",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 24,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 3,
"top_contributor_share": 0.968
},
"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 97% of commits",
"points": 0.7,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 97
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "3 contributors",
"points": 4.1,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 3
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 28 contributing companies or organizations",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "at_risk",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"newcomer_pr_acceptance"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 34,
"inputs": {
"merged_prs": 34,
"open_issues": 2,
"closed_issues": 0,
"prs_merged_7d": null,
"prs_decided_7d": null,
"prs_merged_30d": null,
"prs_decided_30d": null,
"issue_closed_ratio": 0,
"closed_unmerged_prs": 2,
"first_time_authors_30d": null,
"first_time_prs_merged_30d": null,
"first_time_prs_decided_30d": null
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "0% of issues closed",
"points": 0,
"status": "missed",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 0
}
}
],
"max_points": 42
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "34/36 decided PRs merged",
"points": 28.3,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 34,
"decided": 36
}
}
],
"max_points": 30
},
{
"key": "newcomer_pr_acceptance",
"name": "Newcomer PR acceptance",
"detail": "no first-time contributor's PR decided in 30d",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_newcomer_prs",
"params": {
"days": 30
}
}
],
"max_points": 13
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 3/30 approved changesets -- score normalized to 1",
"points": 1.5,
"status": "partial",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "good",
"name": "Ownership & stewardship",
"note": null,
"notes": [],
"value": 74,
"inputs": {
"followers": 1032,
"owner_type": "Organization",
"is_verified": null,
"owner_login": "n0-computer",
"public_repos": 120,
"account_age_days": 1604
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "organization-owned",
"points": 30,
"status": "met",
"details": [
{
"code": "owner_organization",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "1,032 followers of n0-computer",
"points": 21.7,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 1032,
"login": "n0-computer"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "120 public repos, account ~4 yr old",
"points": 21.8,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 120
}
},
{
"code": "account_age_years",
"params": {
"years": 4
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "exceptional",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"patchbay"
],
"ecosystems": "crates",
"any_deprecated": false,
"min_days_since_publish": 0
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on crates",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"ecosystems": "crates"
}
}
],
"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": "9 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 9
}
}
],
"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": "excellent",
"name": "Engineering Quality",
"value": 80,
"weight": 0.19,
"metrics": [
{
"key": "engineering_practices",
"band": "good",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 66,
"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": "3 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 3
}
}
],
"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": "24 out of 25 merged PRs checked by a CI test -- score normalized to 9",
"points": 18,
"status": "partial",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "exceptional",
"name": "Documentation",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"topics": [
"netlab",
"netns",
"netsim",
"network-simulation",
"networking",
"p2p",
"rust",
"hole-punching"
],
"has_wiki": true,
"homepage": "https://n0-computer.github.io/patchbay/",
"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": "https://n0-computer.github.io/patchbay/",
"points": 15,
"status": "met",
"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": "8 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 8
}
}
],
"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": "at_risk",
"name": "Security",
"value": 34,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): Branch-Protection, Packaging. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"branch_protection",
"packaging"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 34,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 16,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 2,
"scorecard_aggregate": 3.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": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "24 out of 25 merged PRs checked by a CI test -- score normalized to 9",
"points": 2.2,
"status": "partial",
"details": [],
"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 3/30 approved changesets -- score normalized to 1",
"points": 0.8,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 28 contributing companies or organizations",
"points": 2.5,
"status": "met",
"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": "no update tool detected",
"points": 0,
"status": "missed",
"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": "10 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 8",
"points": 6,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow not detected",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"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": "SAST tool is not run on all commits -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file not detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"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": "27 existing vulnerabilities detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "exceptional",
"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"
],
"commit_weight_rule": {
"min_commits": 50,
"min_commit_share": 0.1
},
"review_only_matches": 0,
"below_threshold_exposures": [],
"assessed_self_published_locations": 14
},
"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.04,
"metrics": [
{
"key": "ai_agent_context",
"band": "weak",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 1,
"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": "100 of 100 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 100,
"sampled": 100
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "good",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 66,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"Cargo.lock",
"package-lock.json"
],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [
"ui/tsconfig.json"
],
"agent_commit_share": 0.69,
"toolchain_manifests": [
"Cargo.toml",
"patchbay-cli/Cargo.toml",
"patchbay-cli/tests/fixtures/counter/Cargo.toml",
"patchbay-runner/Cargo.toml",
"patchbay-server/Cargo.toml",
"patchbay-utils/Cargo.toml",
"patchbay-vm/Cargo.toml",
"patchbay/Cargo.toml"
],
"dependency_bot_commit_share": 0
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "Cargo.toml, patchbay-cli/Cargo.toml, patchbay-cli/tests/fixtures/counter/Cargo.toml (toolchain convention, no task runner)",
"points": 12.6,
"status": "partial",
"details": [
{
"code": "toolchain_convention",
"params": {
"files": "Cargo.toml, patchbay-cli/Cargo.toml, patchbay-cli/tests/fixtures/counter/Cargo.toml"
}
}
],
"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": "ui/tsconfig.json",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "ui/tsconfig.json"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "69 of the last 100 commits agent-authored or agent-credited",
"points": 10,
"status": "met",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 69,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "no automated dependency updates observed",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_dependency_automation",
"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": "exceptional",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 98,
"inputs": {
"primary_language": "Rust",
"largest_source_bytes": 78703,
"source_files_sampled": 107,
"oversized_source_files": 3
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Rust (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Rust"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "3/107 source files over 60KB",
"points": 53.5,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 107,
"oversized": 3
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "weak",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"example_dirs": [
"examples"
],
"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",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "examples"
}
}
],
"max_points": 40
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
}
],
"classification": {
"top": [
"library",
"application"
],
"labels": [
"library",
"network-service",
"web-ui",
"cli"
],
"scores": {
"cli": 4,
"web-ui": 4,
"library": 8,
"network-service": 4
},
"primary": "library",
"evidence": [
{
"tier": "distribution",
"label": "library",
"source": "registry:crates",
"weight": 6
},
{
"tier": "dependencies",
"label": "cli",
"source": "dep:clap",
"weight": 4
},
{
"tier": "dependencies",
"label": "network-service",
"source": "dep:axum",
"weight": 4
},
{
"tier": "dependencies",
"label": "web-ui",
"source": "dep:react-dom",
"weight": 4
},
{
"tier": "description",
"label": "library",
"source": "description:library",
"weight": 2
}
],
"artifacts": [],
"confidence": "medium",
"host_extension": false,
"runs_as_process": true,
"consumed_by_code": true
},
"metrics_version": "2.5.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"Could not fetch crates package 'patchbay-vm' from its registry",
"Could not fetch crates package 'patchbay-cli' from its registry",
"Could not fetch crates package 'patchbay-utils' from its registry",
"Could not fetch crates package 'patchbay-runner' from its registry",
"Could not fetch crates package 'patchbay-server' from its registry",
"GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
"deps.dev does not index crates:patchbay@0.7.0; advisories assessed against the repository dependency graph instead"
],
"report_type": "repository",
"generated_at": "2026-07-27T21:16:46.193897Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/n/n0-computer/patchbay.svg",
"full_name": "n0-computer/patchbay",
"license_state": "standard",
"license_spdx": "Apache-2.0"
}