Merged
Conversation
b42a0e6 to
ff0544e
Compare
Ship the first host-side passive agent runtime for Graphēon with a lightweight one-shot collector, systemd service/timer units, installation helper, agent tests, and updated operator docs. The runtime keeps host impact low by collecting only local passive command output, storing a persistent random agent_uuid plus API key locally, using cached policy cadence and jitter, and sending gzip-compressed additive deltas over the existing outbound-only check-in API. Make the runtime a first-class manual CLI tool: improve --help output, add explicit register-only and check-in-only modes, document direct flag-driven execution from a repo checkout or installed host copy, and add unit tests for the help text and manual mode behavior. Add admin-driven per-agent API-key rotation/reissue so approved agents can recover from a lost local api_key file without re-enrollment. Update the backend schemas, router, tests, and docs accordingly. Add passive-agent release packaging and distribution: version the agent explicitly, add an agent changelog, build a release tarball, publish a GHCR agent container image, and extend the GitHub release workflow so master creates agent releases alongside backend and frontend releases. Bump the backend and agent versions and update release/deployment documentation. Finally, fix the Nix dev shell so the backend test suite can run under nix develop by exposing the missing libstdc++ runtime needed by greenlet/SQLAlchemy async imports.
ff0544e to
85dc514
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR delivers the first deployable passive-agent slice for Graphēon end to end.
It adds:
--helpsystemddeployment units and install helperCloses #48.
Related: #53.
What Changed
Host-side passive runtime
Added a new stdlib-only runtime under
agent/:agent/grapheon_agent.pyagent/tests/test_grapheon_agent.pyagent/README.mdagent/VERSIONagent/CHANGELOG.mdRuntime behavior:
agent_uuid/var/lib/grapheon-agentpendingstate until approvalPOST /api/agents/check-inagent/VERSIONinstead of a hardcoded stringPassive/local-only command set in this slice:
ip -json addr showip -json neigh showip -json route showss -tunapHnetstat -tunapas fallbackThis keeps the runtime aligned with the MVP constraints:
Manual CLI mode
The agent is now a first-class command-line tool, not just something hidden behind a
systemdoneshot unit.Added and documented:
--helpoutput with examples--register-only--check-in-onlyManual workflows now supported explicitly:
systemdThis makes the runtime easier to test, debug, and operate during rollout.
Deployment artifacts and container
Added:
deploy/grapheon-agent.servicedeploy/grapheon-agent.timerdeploy/grapheon-agent.env.examplescripts/install-passive-agent.shscripts/build-agent-artifact.shagent/DockerfileDeployment/distribution model:
systemdoneshot servicesystemdtimer every 15 minutes by default/opt/grapheon, seeds/etc/grapheon-agent.env, and creates/var/lib/grapheon-agentgrapheon-agent-vX.Y.Z.tar.gzghcr.io/badgerops/grapheon-agent:latestand:vX.Y.ZThe agent image is intended for per-host deployment and is documented with host network/PID namespace examples for containerized runs.
GitHub release automation
Extended
.github/workflows/release.ymlso merges tomasternow also release the passive agent.New behavior:
agent/VERSIONagent/CHANGELOG.mdagent-vX.Y.Zagent-vX.Y.Ztag and GitHub releasegrapheon-agent-vX.Y.Z.tar.gzto that releaseghcr.io/badgerops/grapheon-agent:latestghcr.io/badgerops/grapheon-agent:vX.Y.ZThe workflow name is updated from
Release ImagestoRelease Componentsto reflect the broader scope.Backend follow-up: API-key recovery
The runtime surfaced an operational gap: if an approved agent loses
/var/lib/grapheon-agent/api_key, there was no recovery path short of re-enrollment.This PR adds:
POST /api/agents/{id}/rotate-api-keyBehavior:
This keeps bootstrap and steady-state auth separate while giving operators a clean recovery path.
Version bumps and changelogs
Updated:
backend/VERSION→0.10.0backend/CHANGELOG.mdagent/VERSION→0.2.0agent/CHANGELOG.mdscripts/validate_versions.pynow validates agent version/changelog sync tooDocumentation
Updated:
README.mddocs/README.mddocs/agents.mddocs/agent_quickstart.mddocs/deployment.mddocs/release-process.mdbackend/README.mdagent/README.mdDocs now describe:
--helpregister-onlyandcheck-in-onlymodessystemdtimer modelDev shell fix
Updated
flake.nixto include:iproute2nettoolsutil-linuxstdenv.cc.cc.libAlso exports
LD_LIBRARY_PATHfor the C++ runtime library sogreenlet/ SQLAlchemy async imports work undernix develop.That change unblocked the previously failing backend test collection in this environment.
Key Decisions
One-shot runtime, not a long-running daemon
The agent runs as a short-lived process from a
systemdtimer by default, but the same runtime can now be executed directly with flags for manual workflows. That preserves the low-footprint design while making rollout and debugging practical.Random persisted
agent_uuidIdentity remains a locally persisted random UUID, not a MAC-derived identifier. MACs are still collected as metadata but are not treated as identity.
Additive delta reports
The runtime sends additive/update-only deltas based on the last successful snapshot. This keeps reports small and avoids needing delete semantics the backend does not yet model.
Current limitation:
Recovery via API-key rotation
Instead of overloading registration or requiring re-enrollment, recovery is handled by an explicit admin rotation endpoint. That keeps the agent auth model simple and operationally clear.
Agent-specific versioning and releases
The passive agent now has its own version and changelog. That keeps host-runtime release cadence independent from backend/frontend changes while still using the same GitHub/GHCR release flow.
Files Of Interest
agent/grapheon_agent.pyagent/Dockerfileagent/VERSIONagent/CHANGELOG.mdagent/tests/test_grapheon_agent.pyscripts/build-agent-artifact.shscripts/install-passive-agent.sh.github/workflows/release.ymlbackend/routers/agents.pybackend/schemas.pybackend/tests/test_agents.pybackend/VERSIONbackend/CHANGELOG.mddocs/agent_quickstart.mddocs/agents.mddocs/release-process.mddocs/deployment.mdflake.nixTesting
Ran:
python3 scripts/validate_versions.pybash -n scripts/build-agent-artifact.shbash scripts/build-agent-artifact.sh 0.2.0 /tmp/grapheon-agent-v0.2.0.tar.gztar -tzf /tmp/grapheon-agent-v0.2.0.tar.gzpython3 agent/grapheon_agent.py --helpnix develop -c .venv/bin/python -m pytestResult:
367 passed, 1 skippedFollow-Up Work
#53 Package and distribute the passive agent runtime
This PR adds the first release artifact and GHCR image, but broader packaging/distribution work is still tracked in #53.
Likely deliverables there:
.deb/.rpmpackagingRemaining broader agent work
Still out of scope here: