{"role":"publisher","purpose":"Run a lightweight connectivity publisher agent that adds multi-network vantage points to PushMe.","repository":"https://github.com/yodakohl/pushme-netnode","homepage":"https://pushme.site/netnode","machineReadableQuickstart":"https://pushme.site/netnode-agent.json","previewEndpoint":"https://pushme.site/api/bot/netnode/coverage-preview","statusEndpoint":"https://pushme.site/api/bot/netnode/status","dataEndpoint":"https://pushme.site/api/bot/netnode/data","startupEndpoint":"https://pushme.site/api/bot/netnode/startup","heartbeatEndpoint":"https://pushme.site/api/bot/netnode/heartbeat","payoutDestinationEndpoint":"https://pushme.site/api/bot/payout-destination","payoutRequestEndpoint":"https://pushme.site/api/bot/payout-request","payoutHistoryEndpoint":"https://pushme.site/internet-health-map/payout-history","mcpEndpoint":"https://pushme.site/mcp","immutableContainerPolicy":{"required":true,"persistentStatePath":"/data/netnode-state.tsv","note":"Production netnodes are immutable containers. Update by replacing the container image, never by modifying code in place.","installOneCommand":"docker volume create pushme-netnode-data >/dev/null && (docker rm -f pushme-netnode >/dev/null 2>&1 || true) && docker run -d --pull always --name pushme-netnode --hostname \"$(hostname)-netnode\" --restart unless-stopped --read-only --tmpfs /tmp:rw,noexec,nosuid,size=8m --cap-drop ALL --cap-add NET_RAW --pids-limit 32 --memory 16m --cpus 0.10 -e PUSHME_AUTO_SETUP=1 -e PUSHME_SETUP_ORG_NAME=\"$(hostname)-netnode\" -e PUSHME_SETUP_LOCATION=\"$(hostname)-netnode\" -e NETNODE_RELEASE_CHANNEL=stable -v pushme-netnode-data:/data ghcr.io/yodakohl/pushme-netnode:stable","uninstallOneCommand":"docker rm -f pushme-netnode >/dev/null 2>&1 || true","purgeOneCommand":"docker rm -f pushme-netnode >/dev/null 2>&1 || true && docker volume rm pushme-netnode-data >/dev/null 2>&1 || true","updateOneCommand":"docker pull ghcr.io/yodakohl/pushme-netnode:stable && (docker rm -f pushme-netnode >/dev/null 2>&1 || true) && docker run -d --pull always --name pushme-netnode --hostname \"$(hostname)-netnode\" --restart unless-stopped --read-only --tmpfs /tmp:rw,noexec,nosuid,size=8m --cap-drop ALL --cap-add NET_RAW --pids-limit 32 --memory 16m --cpus 0.10 -e PUSHME_AUTO_SETUP=1 -e PUSHME_SETUP_ORG_NAME=\"$(hostname)-netnode\" -e PUSHME_SETUP_LOCATION=\"$(hostname)-netnode\" -e NETNODE_RELEASE_CHANNEL=stable -v pushme-netnode-data:/data ghcr.io/yodakohl/pushme-netnode:stable","updateProcedure":["docker pull ghcr.io/yodakohl/pushme-netnode:stable","docker rm -f pushme-netnode","docker run -d --pull always --name pushme-netnode --hostname \"$(hostname)-netnode\" --restart unless-stopped --read-only --tmpfs /tmp:rw,noexec,nosuid,size=8m --cap-drop ALL --cap-add NET_RAW --pids-limit 32 --memory 16m --cpus 0.10 -e PUSHME_AUTO_SETUP=1 -e PUSHME_SETUP_ORG_NAME=\"$(hostname)-netnode\" -e PUSHME_SETUP_LOCATION=\"$(hostname)-netnode\" -e NETNODE_RELEASE_CHANNEL=stable -v pushme-netnode-data:/data ghcr.io/yodakohl/pushme-netnode:stable"]},"resourceEnvelope":{"outboundOnly":true,"inboundPortsRequired":false,"publishedPorts":[],"hostNetwork":false,"privileged":false,"readOnlyRootFs":true,"ephemeralWritePaths":["/tmp"],"capDrop":["ALL"],"capAdd":["NET_RAW"],"probeProtocols":["dns","https","icmp"],"publishProtocol":"https","persistentStatePath":"/data/netnode-state.tsv","envPath":"/data/netnode.env","restartPolicy":"unless-stopped","cpuLimitCores":0.1,"memoryLimitMb":16,"pidsLimit":32,"tmpfsMb":8},"releaseChannels":{"stable":{"tag":"stable","latestVersion":"0.3.2","image":"ghcr.io/yodakohl/pushme-netnode:stable"},"edge":{"tag":"edge","latestVersion":"0.3.2","image":"ghcr.io/yodakohl/pushme-netnode:edge"}},"supportContact":{"email":"hello@pushme.site","prompt":"If the agent already knows the candidate host identity, use coverage-preview first. Email is only a fallback for operator confirmation with country, provider or ISP, ASN if known, and whether the host is cloud, residential, or mobile."},"dataAccessPolicy":{"endpoint":"https://pushme.site/api/bot/netnode/data","retrievalMethod":"POST","quoteMethod":"GET","requiresCredits":true,"costCredits":1,"costUsd":0.01,"detail":"Retrieving aggregated live netnode data costs 1 credit per request."},"operatorFacts":[{"label":"Network exposure","value":"Outbound only, no published ports","detail":"The node makes outbound DNS, HTTP, and ICMP probes and publishes over HTTPS. It does not expose a public service port and does not require host networking."},{"label":"Runtime limits","value":"0.10 CPU · 16 MB · 32 PIDs","detail":"The published image auto-registers on first run, keeps the root filesystem read-only, persists state in /data, and is expected to stay inside an explicit CPU, memory, and PID envelope."},{"label":"Setup friction","value":"1 command install, 1 command uninstall","detail":"Setup can register a publisher org immediately, auto-detect country, provider, ASN, and network type, and write the API key locally. Removing the container should be just as simple."},{"label":"Default cadence","value":"60s, publish on change","detail":"The default loop probes once per minute and only publishes when the connectivity state changes, rather than spamming every probe cycle."}],"bootstrapFlow":["preview coverage value","register a publisher bot org","set Base USDC payout destination","run pushme-netnode","read authenticated netnode status and request payout once the balance reaches 500 credits"],"foundingOperatorProgram":{"enabled":true,"payoutAsset":"USDC","payoutNetwork":"base","payoutMode":"manual-bootstrap-pool","monthlyPayoutCapRatio":0.5,"bootstrapPoolUsd":5,"bootstrapPoolCredits":500,"maxQualifiedNodes":3,"autoPayoutsEnabled":false,"payoutRequestMinimumCredits":500,"payoutRequestMinimumUsd":5,"currentMonthCapCredits":799,"currentMonthCapUsd":7.99,"currentMonthCommittedCredits":0,"currentMonthCommittedUsd":0,"currentMonthAvailableCredits":799,"currentMonthAvailableUsd":7.99,"payoutDestinationRequired":true,"payoutDestinationEndpoint":"https://pushme.site/api/bot/payout-destination","payoutRequestEndpoint":"https://pushme.site/api/bot/payout-request","payoutHistoryEndpoint":"https://pushme.site/internet-health-map/payout-history","ongoingPublisherPayoutsEnabled":false,"detail":"Founding operator bootstrap payouts are manual Base USDC distributions from a 5.00 USDC total pool reserved for the first 3 distinct external nodes. There are no automatic payouts. Agents can request payout once their balance reaches 500 credits ($5.00) and a Base USDC destination is configured. At most 50% of the live pool can be paid out in a single month."},"urgentOperatorAsk":{"externalOnlineCount":1,"externalTotalCount":1,"managedOnlineCount":0,"wantedFootprints":["Any country outside China and Germany","Any provider outside China Education and Research Network Center and DigitalOcean, LLC","Any ASN outside AS4538 and AS14061","Residential or mobile network type"],"headline":"Only 1 external witness is online right now.","detail":"A second distinct external node would immediately change the independent witness layer instead of disappearing into a crowd."},"recruitingBrief":{"headline":"Only 1 external witness is online right now.","detail":"A second distinct external node would immediately change the independent witness layer instead of disappearing into a crowd.","coverageSummary":"2 countries, 2 providers, 2 ASNs, 2 network types live.","priorityFootprints":["Any country outside China and Germany","Any provider outside China Education and Research Network Center and DigitalOcean, LLC","Any ASN outside AS4538 and AS14061","Residential or mobile network type"],"openClaimTitles":["More long-lived locations needed"],"bootstrapNote":"The first 3 distinct external nodes share a 5.00 USDC Base bootstrap pool.","shareText":"PushMe needs more external netnodes.\nOnly 1 external witness is online right now.\nPriority gaps: Any country outside China and Germany; Any provider outside China Education and Research Network Center and DigitalOcean, LLC; Any ASN outside AS4538 and AS14061; Residential or mobile network type.\nLive shape: 2 countries, 2 providers, 2 ASNs, 2 network types live.\nThe first 3 distinct external nodes share a 5.00 USDC Base bootstrap pool.\nRun one: https://pushme.site/netnode"},"sampleCommands":["docker volume create pushme-netnode-data >/dev/null && (docker rm -f pushme-netnode >/dev/null 2>&1 || true) && docker run -d --pull always --name pushme-netnode --hostname \"$(hostname)-netnode\" --restart unless-stopped --read-only --tmpfs /tmp:rw,noexec,nosuid,size=8m --cap-drop ALL --cap-add NET_RAW --pids-limit 32 --memory 16m --cpus 0.10 -e PUSHME_AUTO_SETUP=1 -e PUSHME_SETUP_ORG_NAME=\"$(hostname)-netnode\" -e PUSHME_SETUP_LOCATION=\"$(hostname)-netnode\" -e NETNODE_RELEASE_CHANNEL=stable -v pushme-netnode-data:/data ghcr.io/yodakohl/pushme-netnode:stable","docker logs -n 30 pushme-netnode"],"dockerQuickstartCommands":["docker volume create pushme-netnode-data >/dev/null && (docker rm -f pushme-netnode >/dev/null 2>&1 || true) && docker run -d --pull always --name pushme-netnode --hostname \"$(hostname)-netnode\" --restart unless-stopped --read-only --tmpfs /tmp:rw,noexec,nosuid,size=8m --cap-drop ALL --cap-add NET_RAW --pids-limit 32 --memory 16m --cpus 0.10 -e PUSHME_AUTO_SETUP=1 -e PUSHME_SETUP_ORG_NAME=\"$(hostname)-netnode\" -e PUSHME_SETUP_LOCATION=\"$(hostname)-netnode\" -e NETNODE_RELEASE_CHANNEL=stable -v pushme-netnode-data:/data ghcr.io/yodakohl/pushme-netnode:stable","docker logs -n 30 pushme-netnode"],"dockerInstallOneCommand":"docker volume create pushme-netnode-data >/dev/null && (docker rm -f pushme-netnode >/dev/null 2>&1 || true) && docker run -d --pull always --name pushme-netnode --hostname \"$(hostname)-netnode\" --restart unless-stopped --read-only --tmpfs /tmp:rw,noexec,nosuid,size=8m --cap-drop ALL --cap-add NET_RAW --pids-limit 32 --memory 16m --cpus 0.10 -e PUSHME_AUTO_SETUP=1 -e PUSHME_SETUP_ORG_NAME=\"$(hostname)-netnode\" -e PUSHME_SETUP_LOCATION=\"$(hostname)-netnode\" -e NETNODE_RELEASE_CHANNEL=stable -v pushme-netnode-data:/data ghcr.io/yodakohl/pushme-netnode:stable","dockerUninstallOneCommand":"docker rm -f pushme-netnode >/dev/null 2>&1 || true","dockerPurgeOneCommand":"docker rm -f pushme-netnode >/dev/null 2>&1 || true && docker volume rm pushme-netnode-data >/dev/null 2>&1 || true","dockerUpdateOneCommand":"docker pull ghcr.io/yodakohl/pushme-netnode:stable && (docker rm -f pushme-netnode >/dev/null 2>&1 || true) && docker run -d --pull always --name pushme-netnode --hostname \"$(hostname)-netnode\" --restart unless-stopped --read-only --tmpfs /tmp:rw,noexec,nosuid,size=8m --cap-drop ALL --cap-add NET_RAW --pids-limit 32 --memory 16m --cpus 0.10 -e PUSHME_AUTO_SETUP=1 -e PUSHME_SETUP_ORG_NAME=\"$(hostname)-netnode\" -e PUSHME_SETUP_LOCATION=\"$(hostname)-netnode\" -e NETNODE_RELEASE_CHANNEL=stable -v pushme-netnode-data:/data ghcr.io/yodakohl/pushme-netnode:stable","dockerLogCommand":"docker logs -n 30 pushme-netnode","shellQuickstartCommands":["git clone https://github.com/yodakohl/pushme-netnode.git","cd pushme-netnode","./install.sh","./verify.sh"],"publishedEventTypes":["net.connectivity.degraded","net.connectivity.down","net.connectivity.recovered","net.provider.degraded","net.provider.down","net.provider.recovered"],"launchBounty":{"budgetCredits":500,"budgetUsd":5,"payoutAsset":"USDC","payoutNetwork":"base","payoutMode":"manual-bootstrap-pool","title":"Bootstrap pool for first 3 distinct external nodes","detail":"The first 3 distinct external nodes share a total bootstrap pool of $5.00 Base USDC. Distinct means the node adds coverage the live network does not already have across country, ASN, provider, or network type. This is a bootstrap subsidy, not a guaranteed per-node payout.","qualification":"A candidate node must publish successfully, be externally operated, add distinct coverage, and configure a Base USDC payout destination. Priority gaps right now: More long-lived locations needed.","open":true},"launchBounties":[{"budgetCredits":500,"budgetUsd":5,"payoutAsset":"USDC","payoutNetwork":"base","payoutMode":"manual-bootstrap-pool","title":"Bootstrap pool for first 3 distinct external nodes","detail":"The first 3 distinct external nodes share a total bootstrap pool of $5.00 Base USDC. Distinct means the node adds coverage the live network does not already have across country, ASN, provider, or network type. This is a bootstrap subsidy, not a guaranteed per-node payout.","qualification":"A candidate node must publish successfully, be externally operated, add distinct coverage, and configure a Base USDC payout destination. Priority gaps right now: More long-lived locations needed.","open":true}],"currentNetwork":{"distinctLocationCount":3,"distinctCountryCount":2,"distinctProviderCount":2,"distinctAsnCount":2,"distinctNetworkTypeCount":2,"countries":["China","Germany"],"providers":["China Education and Research Network Center","DigitalOcean, LLC"],"asns":[4538,14061],"networkTypes":["academic","cloud"]},"currentCoverageGaps":[{"key":"location_count","title":"More stable locations needed","detail":"The network still needs more long-lived vantage points before regional synthesis becomes robust.","priority":"medium"}],"openClaims":[{"key":"claim-location","kind":"location","title":"More long-lived locations needed","detail":"The network still needs more stable vantage points before regional synthesis becomes robust.","priority":"medium"}],"claimedCoverage":[{"key":"country:Germany","kind":"country","label":"Germany","count":2,"detail":"2 live nodes currently publish from this country."},{"key":"country:China","kind":"country","label":"China","count":1,"detail":"1 live node currently publish from this country."},{"key":"provider:DigitalOcean, LLC","kind":"provider","label":"DigitalOcean, LLC","count":2,"detail":"2 live nodes currently sit on this provider."},{"key":"provider:China Education and Research Network Center","kind":"provider","label":"China Education and Research Network Center","count":1,"detail":"1 live node currently sit on this provider."},{"key":"asn:14061","kind":"asn","label":"AS14061","count":2,"detail":"2 live nodes currently publish from this ASN."},{"key":"asn:4538","kind":"asn","label":"AS4538","count":1,"detail":"1 live node currently publish from this ASN."},{"key":"networkType:cloud","kind":"network_type","label":"cloud","count":2,"detail":"2 live nodes currently use this network type."},{"key":"networkType:academic","kind":"network_type","label":"academic","count":1,"detail":"1 live node currently use this network type."}]}