ops-copilot 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. ops_copilot-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +30 -0
  2. ops_copilot-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +23 -0
  3. ops_copilot-0.1.0/.github/dependabot.yml +10 -0
  4. ops_copilot-0.1.0/.github/pull_request_template.md +11 -0
  5. ops_copilot-0.1.0/.github/workflows/build.yml +27 -0
  6. ops_copilot-0.1.0/.github/workflows/ci.yml +25 -0
  7. ops_copilot-0.1.0/.github/workflows/publish.yml +22 -0
  8. ops_copilot-0.1.0/.github/workflows/smoke.yml +23 -0
  9. ops_copilot-0.1.0/.gitignore +13 -0
  10. ops_copilot-0.1.0/CHANGELOG.md +19 -0
  11. ops_copilot-0.1.0/CONTRIBUTING.md +36 -0
  12. ops_copilot-0.1.0/LICENSE +21 -0
  13. ops_copilot-0.1.0/MAINTAINERS.md +21 -0
  14. ops_copilot-0.1.0/PKG-INFO +192 -0
  15. ops_copilot-0.1.0/README.md +138 -0
  16. ops_copilot-0.1.0/SECURITY.md +15 -0
  17. ops_copilot-0.1.0/docs/maintenance-workflows.md +30 -0
  18. ops_copilot-0.1.0/docs/release-process.md +30 -0
  19. ops_copilot-0.1.0/docs/security-model.md +69 -0
  20. ops_copilot-0.1.0/docs/server.md +66 -0
  21. ops_copilot-0.1.0/docs/writing-tools.md +75 -0
  22. ops_copilot-0.1.0/examples/custom_tool.py +19 -0
  23. ops_copilot-0.1.0/examples/local_demo.py +39 -0
  24. ops_copilot-0.1.0/examples/run_agent.py +32 -0
  25. ops_copilot-0.1.0/examples/tools.yaml +33 -0
  26. ops_copilot-0.1.0/pyproject.toml +63 -0
  27. ops_copilot-0.1.0/scripts/smoke.py +30 -0
  28. ops_copilot-0.1.0/src/ops_copilot/__init__.py +17 -0
  29. ops_copilot-0.1.0/src/ops_copilot/graph.py +191 -0
  30. ops_copilot-0.1.0/src/ops_copilot/sanitizers.py +46 -0
  31. ops_copilot-0.1.0/src/ops_copilot/secrets.py +62 -0
  32. ops_copilot-0.1.0/src/ops_copilot/server.py +62 -0
  33. ops_copilot-0.1.0/src/ops_copilot/ssh.py +90 -0
  34. ops_copilot-0.1.0/src/ops_copilot/tools/__init__.py +6 -0
  35. ops_copilot-0.1.0/src/ops_copilot/tools/base.py +34 -0
  36. ops_copilot-0.1.0/src/ops_copilot/tools/executor.py +67 -0
  37. ops_copilot-0.1.0/src/ops_copilot/tools/registry.py +71 -0
  38. ops_copilot-0.1.0/src/ops_copilot/tools/shell.py +38 -0
  39. ops_copilot-0.1.0/tests/test_executor.py +54 -0
  40. ops_copilot-0.1.0/tests/test_graph.py +45 -0
  41. ops_copilot-0.1.0/tests/test_registry.py +67 -0
  42. ops_copilot-0.1.0/tests/test_sanitizers.py +32 -0
  43. ops_copilot-0.1.0/tests/test_secrets.py +43 -0
  44. ops_copilot-0.1.0/uv.lock +2581 -0
@@ -0,0 +1,30 @@
1
+ name: Bug report
2
+ description: Report an investigation, tool execution, SSH, or streaming issue.
3
+ title: "[Bug]: "
4
+ labels: [bug]
5
+ body:
6
+ - type: textarea
7
+ id: scenario
8
+ attributes:
9
+ label: Scenario
10
+ description: What were you trying to investigate?
11
+ validations:
12
+ required: true
13
+ - type: textarea
14
+ id: tool_config
15
+ attributes:
16
+ label: Tool configuration
17
+ description: Paste a minimal redacted YAML snippet if relevant.
18
+ render: yaml
19
+ - type: textarea
20
+ id: expected
21
+ attributes:
22
+ label: Expected behavior
23
+ validations:
24
+ required: true
25
+ - type: textarea
26
+ id: actual
27
+ attributes:
28
+ label: Actual behavior
29
+ validations:
30
+ required: true
@@ -0,0 +1,23 @@
1
+ name: Feature request
2
+ description: Suggest a new SRE workflow, tool type, or safety control.
3
+ title: "[Feature]: "
4
+ labels: [enhancement]
5
+ body:
6
+ - type: textarea
7
+ id: workflow
8
+ attributes:
9
+ label: Workflow
10
+ description: Which maintenance or incident workflow would this improve?
11
+ validations:
12
+ required: true
13
+ - type: textarea
14
+ id: proposal
15
+ attributes:
16
+ label: Proposal
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: safety
21
+ attributes:
22
+ label: Safety considerations
23
+ description: Any command, SSH, secret, or permission risks?
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "monthly"
7
+ - package-ecosystem: "uv"
8
+ directory: "/"
9
+ schedule:
10
+ interval: "monthly"
@@ -0,0 +1,11 @@
1
+ ## Summary
2
+
3
+ ## Safety checklist
4
+
5
+ - [ ] Added or updated tests.
6
+ - [ ] `uv run ruff check .` passes.
7
+ - [ ] `uv run pytest` passes.
8
+ - [ ] No real hostnames, private IPs, credentials, tokens, or internal service names were added.
9
+ - [ ] Tool output is redacted before it reaches the LLM or SSE stream.
10
+ - [ ] New shell commands are narrow, documented, and non-destructive.
11
+ - [ ] Security assumptions are documented when behavior changes.
@@ -0,0 +1,27 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ tags: ["v*"]
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v5
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.11"
21
+ - name: Build package
22
+ run: uv build
23
+ - name: Upload distributions
24
+ uses: actions/upload-artifact@v4
25
+ with:
26
+ name: dist
27
+ path: dist/*
@@ -0,0 +1,25 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@v5
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.11"
20
+ - name: Install dependencies
21
+ run: uv sync --dev
22
+ - name: Lint
23
+ run: uv run ruff check .
24
+ - name: Test
25
+ run: uv run pytest
@@ -0,0 +1,22 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ release:
6
+ types: [published]
7
+
8
+ jobs:
9
+ publish:
10
+ runs-on: ubuntu-latest
11
+ environment: pypi
12
+ permissions:
13
+ id-token: write
14
+ contents: read
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v5
19
+ - name: Build package
20
+ run: uv build
21
+ - name: Publish package
22
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,23 @@
1
+ name: Smoke
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ smoke:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@v5
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.11"
20
+ - name: Install dependencies
21
+ run: uv sync --dev
22
+ - name: Run smoke test
23
+ run: uv run python scripts/smoke.py
@@ -0,0 +1,13 @@
1
+ .venv/
2
+ __pycache__/
3
+ .pytest_cache/
4
+ .ruff_cache/
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .coverage
9
+ htmlcov/
10
+ .env
11
+ .env.*
12
+ !.env.example
13
+ .DS_Store
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ - Added maintainer documentation, security policy, release process, and issue/PR templates.
6
+ - Added security model, tool-writing, server, and maintenance-workflow documentation.
7
+ - Added local demo and custom tool examples.
8
+ - Added build and manual publish workflows.
9
+
10
+ ## 0.1.0
11
+
12
+ Initial public release.
13
+
14
+ - Added SSH client with lazy reconnect and command timeout handling.
15
+ - Added YAML-driven shell tools and injectable custom tool registry.
16
+ - Added LangGraph investigation loop with streaming events.
17
+ - Added FastAPI SSE integration helper.
18
+ - Added input/output sanitization and secret redaction.
19
+ - Added examples, tests, and CI.
@@ -0,0 +1,36 @@
1
+ # Contributing
2
+
3
+ Thanks for helping improve `ops-copilot`.
4
+
5
+ ## Development setup
6
+
7
+ `ops-copilot` depends on `langchain-content-normalizer`. Before that package is published to a package index, use the sibling checkout during local development:
8
+
9
+ ```bash
10
+ PYTHONPATH="../langchain-content-normalizer/src" uv run --no-sync ruff check .
11
+ PYTHONPATH="../langchain-content-normalizer/src" uv run --no-sync pytest
12
+ ```
13
+
14
+ Once the dependency is available through the configured Git URL, the normal workflow is:
15
+
16
+ ```bash
17
+ uv sync --dev
18
+ uv run ruff check .
19
+ uv run pytest
20
+ ```
21
+
22
+ ## Contribution guidelines
23
+
24
+ - Treat YAML tool definitions as privileged code.
25
+ - Add tests for every new command renderer, sanitizer, or graph event behavior.
26
+ - Never add real hostnames, credentials, private IPs, or internal service names.
27
+ - Keep tool outputs redacted before they reach the LLM or SSE stream.
28
+ - Prefer narrow, explicit parameters over free-form shell fragments.
29
+ - Document security assumptions in `docs/security-model.md`.
30
+
31
+ ## Useful PRs
32
+
33
+ - Safer command policy and allowlist validation.
34
+ - Built-in systemd and Docker tool packs.
35
+ - More fake incident fixtures for tests.
36
+ - Better documentation for custom tools and server deployment.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Benjamin Jornet
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ # Maintainers
2
+
3
+ ## Primary maintainer
4
+
5
+ - Benjamin Jornet (`@BenjaminJornet`)
6
+
7
+ ## Maintainer responsibilities
8
+
9
+ - Review pull requests that add tools, command templates, graph behavior, or server endpoints.
10
+ - Triage issues with redacted YAML snippets and reproduction steps.
11
+ - Maintain the security model for SSH and LLM-driven tool execution.
12
+ - Keep examples runnable without private infrastructure.
13
+ - Publish releases and maintain `CHANGELOG.md`.
14
+
15
+ ## Review priorities
16
+
17
+ 1. No real hostnames, private IPs, credentials, tokens, or internal service names.
18
+ 2. Tool output must be redacted before it reaches the LLM or SSE stream.
19
+ 3. Shell commands should be narrow, documented, and non-destructive.
20
+ 4. New graph/server behaviors need tests.
21
+ 5. Security assumptions must be documented.
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: ops-copilot
3
+ Version: 0.1.0
4
+ Summary: Self-hosted SRE investigation copilot with YAML tools, SSH execution, SSE streaming, and secret redaction.
5
+ Project-URL: Homepage, https://github.com/benjaminjornet/ops-copilot
6
+ Project-URL: Issues, https://github.com/benjaminjornet/ops-copilot/issues
7
+ Author-email: Benjamin Jornet <benjamin.jornet@gmail.com>
8
+ License: MIT License
9
+
10
+ Copyright (c) 2026 Benjamin Jornet
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ License-File: LICENSE
30
+ Keywords: incident-response,langgraph,llm,ops,sre,ssh
31
+ Classifier: Development Status :: 3 - Alpha
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Programming Language :: Python :: 3
35
+ Classifier: Programming Language :: Python :: 3.11
36
+ Classifier: Programming Language :: Python :: 3.12
37
+ Classifier: Programming Language :: Python :: 3.13
38
+ Requires-Python: >=3.11
39
+ Requires-Dist: asyncssh>=2.14
40
+ Requires-Dist: langchain-content-normalizer>=0.1.0
41
+ Requires-Dist: langchain-core>=0.3
42
+ Requires-Dist: langgraph>=0.2
43
+ Requires-Dist: pydantic>=2
44
+ Requires-Dist: pyyaml>=6
45
+ Provides-Extra: ollama
46
+ Requires-Dist: langchain-community>=0.3; extra == 'ollama'
47
+ Provides-Extra: openai
48
+ Requires-Dist: langchain-openai>=0.2; extra == 'openai'
49
+ Provides-Extra: server
50
+ Requires-Dist: fastapi>=0.115; extra == 'server'
51
+ Requires-Dist: sse-starlette>=2; extra == 'server'
52
+ Requires-Dist: uvicorn>=0.32; extra == 'server'
53
+ Description-Content-Type: text/markdown
54
+
55
+ # ops-copilot
56
+
57
+ [![CI](https://github.com/BenjaminJornet/ops-copilot/actions/workflows/ci.yml/badge.svg)](https://github.com/BenjaminJornet/ops-copilot/actions/workflows/ci.yml)
58
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
59
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](pyproject.toml)
60
+
61
+ Self-hosted SRE investigation copilot for production systems.
62
+
63
+ `ops-copilot` lets an LLM call tools defined in YAML, execute safe remote commands over SSH, redact secrets from outputs, and stream investigation events through LangGraph or an optional FastAPI SSE server.
64
+
65
+ ## Architecture
66
+
67
+ ```text
68
+ User question -> InvestigationGraph -> LLM -> YAML tools -> SSH host
69
+ <- redacted tool output <- command result
70
+ ```
71
+
72
+ The package is intentionally generic. You can start with shell tools from YAML, then inject custom Python `RemoteTool` classes for richer workflows.
73
+
74
+ ## Install
75
+
76
+ ```bash
77
+ uv add ops-copilot
78
+ ```
79
+
80
+ Optional extras:
81
+
82
+ ```bash
83
+ uv add 'ops-copilot[server]'
84
+ uv add 'ops-copilot[openai]'
85
+ uv add 'ops-copilot[ollama]'
86
+ ```
87
+
88
+ ## YAML tools
89
+
90
+ ```yaml
91
+ tools:
92
+ - name: disk_usage
93
+ type: shell
94
+ description: Show filesystem usage.
95
+ command: df -h
96
+
97
+ - name: journalctl_service
98
+ type: shell
99
+ description: Show recent logs for a systemd service.
100
+ command: journalctl -u {service} --since '{since}' --no-pager
101
+ parameters:
102
+ service:
103
+ type: string
104
+ since:
105
+ type: string
106
+ required: false
107
+ default: "30 minutes ago"
108
+ ```
109
+
110
+ ## Minimal usage
111
+
112
+ ```python
113
+ from ops_copilot import InvestigationGraph, SSHClient, ToolRegistry
114
+
115
+ ssh = SSHClient(host="server.example.com", user="deploy", key_path="~/.ssh/id_ed25519")
116
+ tools = ToolRegistry(ssh, config_path="tools.yaml").load()
117
+
118
+ graph = InvestigationGraph(
119
+ llm=your_langchain_chat_model,
120
+ tools=tools,
121
+ system_prompt="You are an SRE copilot. Investigate safely and report evidence.",
122
+ )
123
+
124
+ async for event in graph.stream("The API is slow. What should I check?"):
125
+ print(event)
126
+ ```
127
+
128
+ ## Streaming events
129
+
130
+ `InvestigationGraph.stream()` yields dictionaries with these event names:
131
+
132
+ | Event | Meaning |
133
+ | --- | --- |
134
+ | `token` | streamed model text |
135
+ | `tool_start` | tool call started with input and step id |
136
+ | `tool_end` | tool call finished with redacted output |
137
+ | `error` | graph or stream error |
138
+ | `done` | investigation complete |
139
+
140
+ ## Optional FastAPI server
141
+
142
+ The `ops_copilot.server.create_app()` helper exposes:
143
+
144
+ - `POST /investigate`
145
+ - `POST /investigate/stream`
146
+
147
+ If `OPS_COPILOT_API_KEY` is set, clients must send `X-API-Key`.
148
+
149
+ ## Security notes
150
+
151
+ This project executes commands on servers you control. Treat `tools.yaml` as privileged code.
152
+
153
+ Recommendations:
154
+
155
+ - Use SSH key auth with least-privilege users.
156
+ - Review every command template before exposing it to an LLM.
157
+ - Avoid destructive commands in YAML.
158
+ - Keep parameterized commands narrow.
159
+ - Store no secrets in YAML or prompts.
160
+ - Rely on built-in redaction as a safety net, not as your only control.
161
+
162
+ Built-in redaction covers env-style secret lines, Bearer tokens, OpenAI-style keys, JWTs, long hex runs, and inline image data URLs.
163
+
164
+ ## Documentation and examples
165
+
166
+ - `docs/security-model.md` documents threat boundaries and deployment controls.
167
+ - `docs/writing-tools.md` explains YAML and custom Python tools.
168
+ - `docs/server.md` covers the optional FastAPI/SSE integration.
169
+ - `docs/maintenance-workflows.md` describes maintainer workflows and review checklists.
170
+ - `examples/local_demo.py` runs without a real SSH host using fake outputs.
171
+ - `examples/custom_tool.py` shows how to inject a custom `RemoteTool` class.
172
+
173
+ ## Roadmap
174
+
175
+ - Command allowlist validation for shell tools.
176
+ - Built-in Docker and systemd tool packs.
177
+ - Persistent investigation sessions.
178
+ - Audit log export.
179
+ - More fake incident fixtures for regression tests.
180
+
181
+ ## Development
182
+
183
+ ```bash
184
+ uv sync --dev
185
+ uv run ruff check .
186
+ uv run pytest
187
+ uv run python scripts/smoke.py
188
+ ```
189
+
190
+ ## License
191
+
192
+ MIT
@@ -0,0 +1,138 @@
1
+ # ops-copilot
2
+
3
+ [![CI](https://github.com/BenjaminJornet/ops-copilot/actions/workflows/ci.yml/badge.svg)](https://github.com/BenjaminJornet/ops-copilot/actions/workflows/ci.yml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+ [![Python](https://img.shields.io/badge/python-3.11%2B-blue.svg)](pyproject.toml)
6
+
7
+ Self-hosted SRE investigation copilot for production systems.
8
+
9
+ `ops-copilot` lets an LLM call tools defined in YAML, execute safe remote commands over SSH, redact secrets from outputs, and stream investigation events through LangGraph or an optional FastAPI SSE server.
10
+
11
+ ## Architecture
12
+
13
+ ```text
14
+ User question -> InvestigationGraph -> LLM -> YAML tools -> SSH host
15
+ <- redacted tool output <- command result
16
+ ```
17
+
18
+ The package is intentionally generic. You can start with shell tools from YAML, then inject custom Python `RemoteTool` classes for richer workflows.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ uv add ops-copilot
24
+ ```
25
+
26
+ Optional extras:
27
+
28
+ ```bash
29
+ uv add 'ops-copilot[server]'
30
+ uv add 'ops-copilot[openai]'
31
+ uv add 'ops-copilot[ollama]'
32
+ ```
33
+
34
+ ## YAML tools
35
+
36
+ ```yaml
37
+ tools:
38
+ - name: disk_usage
39
+ type: shell
40
+ description: Show filesystem usage.
41
+ command: df -h
42
+
43
+ - name: journalctl_service
44
+ type: shell
45
+ description: Show recent logs for a systemd service.
46
+ command: journalctl -u {service} --since '{since}' --no-pager
47
+ parameters:
48
+ service:
49
+ type: string
50
+ since:
51
+ type: string
52
+ required: false
53
+ default: "30 minutes ago"
54
+ ```
55
+
56
+ ## Minimal usage
57
+
58
+ ```python
59
+ from ops_copilot import InvestigationGraph, SSHClient, ToolRegistry
60
+
61
+ ssh = SSHClient(host="server.example.com", user="deploy", key_path="~/.ssh/id_ed25519")
62
+ tools = ToolRegistry(ssh, config_path="tools.yaml").load()
63
+
64
+ graph = InvestigationGraph(
65
+ llm=your_langchain_chat_model,
66
+ tools=tools,
67
+ system_prompt="You are an SRE copilot. Investigate safely and report evidence.",
68
+ )
69
+
70
+ async for event in graph.stream("The API is slow. What should I check?"):
71
+ print(event)
72
+ ```
73
+
74
+ ## Streaming events
75
+
76
+ `InvestigationGraph.stream()` yields dictionaries with these event names:
77
+
78
+ | Event | Meaning |
79
+ | --- | --- |
80
+ | `token` | streamed model text |
81
+ | `tool_start` | tool call started with input and step id |
82
+ | `tool_end` | tool call finished with redacted output |
83
+ | `error` | graph or stream error |
84
+ | `done` | investigation complete |
85
+
86
+ ## Optional FastAPI server
87
+
88
+ The `ops_copilot.server.create_app()` helper exposes:
89
+
90
+ - `POST /investigate`
91
+ - `POST /investigate/stream`
92
+
93
+ If `OPS_COPILOT_API_KEY` is set, clients must send `X-API-Key`.
94
+
95
+ ## Security notes
96
+
97
+ This project executes commands on servers you control. Treat `tools.yaml` as privileged code.
98
+
99
+ Recommendations:
100
+
101
+ - Use SSH key auth with least-privilege users.
102
+ - Review every command template before exposing it to an LLM.
103
+ - Avoid destructive commands in YAML.
104
+ - Keep parameterized commands narrow.
105
+ - Store no secrets in YAML or prompts.
106
+ - Rely on built-in redaction as a safety net, not as your only control.
107
+
108
+ Built-in redaction covers env-style secret lines, Bearer tokens, OpenAI-style keys, JWTs, long hex runs, and inline image data URLs.
109
+
110
+ ## Documentation and examples
111
+
112
+ - `docs/security-model.md` documents threat boundaries and deployment controls.
113
+ - `docs/writing-tools.md` explains YAML and custom Python tools.
114
+ - `docs/server.md` covers the optional FastAPI/SSE integration.
115
+ - `docs/maintenance-workflows.md` describes maintainer workflows and review checklists.
116
+ - `examples/local_demo.py` runs without a real SSH host using fake outputs.
117
+ - `examples/custom_tool.py` shows how to inject a custom `RemoteTool` class.
118
+
119
+ ## Roadmap
120
+
121
+ - Command allowlist validation for shell tools.
122
+ - Built-in Docker and systemd tool packs.
123
+ - Persistent investigation sessions.
124
+ - Audit log export.
125
+ - More fake incident fixtures for regression tests.
126
+
127
+ ## Development
128
+
129
+ ```bash
130
+ uv sync --dev
131
+ uv run ruff check .
132
+ uv run pytest
133
+ uv run python scripts/smoke.py
134
+ ```
135
+
136
+ ## License
137
+
138
+ MIT
@@ -0,0 +1,15 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ Only the latest minor release receives security fixes while the project is pre-1.0.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Please open a private GitHub security advisory if available, or contact the maintainer through GitHub.
10
+
11
+ ## Security model summary
12
+
13
+ `ops-copilot` executes commands over SSH on systems you control. The project reduces accidental exposure with secret redaction, input/output sanitizers, and explicit tool definitions, but it does not make arbitrary shell commands safe.
14
+
15
+ Review `docs/security-model.md` before deploying the server or exposing tools to an LLM.
@@ -0,0 +1,30 @@
1
+ # Maintenance Workflows
2
+
3
+ `ops-copilot` is designed to be maintained with the same workflows it supports: structured investigation, explicit tools, safety review, and repeatable releases.
4
+
5
+ ## Codex-assisted maintenance use cases
6
+
7
+ - Review pull requests that add YAML tools or custom `RemoteTool` classes.
8
+ - Generate edge-case tests for command rendering and redaction.
9
+ - Review SSH and command-execution safety boundaries.
10
+ - Draft release notes from merged changes.
11
+ - Triage issues by reproducing reported tool configurations against fake SSH clients.
12
+ - Improve documentation for operational workflows.
13
+
14
+ ## Review checklist for tool PRs
15
+
16
+ - Is the command read-only or clearly documented?
17
+ - Are parameters narrow and typed?
18
+ - Could a parameter inject arbitrary shell syntax?
19
+ - Is output redacted before it reaches the graph or stream?
20
+ - Is there a test for the command template?
21
+ - Does the README or docs explain the workflow?
22
+
23
+ ## Release checklist
24
+
25
+ - Run `uv run ruff check .`.
26
+ - Run `uv run pytest`.
27
+ - Scan source files for hostnames, private IPs, credentials, and client-specific names.
28
+ - Update `CHANGELOG.md`.
29
+ - Tag the release.
30
+ - Publish release notes.