proximo-proxmox 0.1.1__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.
- proximo_proxmox-0.1.1/.github/workflows/ci.yml +24 -0
- proximo_proxmox-0.1.1/.gitignore +33 -0
- proximo_proxmox-0.1.1/CHANGELOG.md +180 -0
- proximo_proxmox-0.1.1/Dockerfile +16 -0
- proximo_proxmox-0.1.1/LANDSCAPE.md +173 -0
- proximo_proxmox-0.1.1/LICENSE +201 -0
- proximo_proxmox-0.1.1/PKG-INFO +159 -0
- proximo_proxmox-0.1.1/POSITIONING.md +159 -0
- proximo_proxmox-0.1.1/README.md +131 -0
- proximo_proxmox-0.1.1/ROADMAP.md +134 -0
- proximo_proxmox-0.1.1/debian/README.Debian +23 -0
- proximo_proxmox-0.1.1/debian/changelog +7 -0
- proximo_proxmox-0.1.1/debian/control +25 -0
- proximo_proxmox-0.1.1/debian/copyright +23 -0
- proximo_proxmox-0.1.1/debian/rules +5 -0
- proximo_proxmox-0.1.1/debian/source/format +1 -0
- proximo_proxmox-0.1.1/packaging/optional-daemon-mode.service.example +35 -0
- proximo_proxmox-0.1.1/packaging/proximo.env.example +26 -0
- proximo_proxmox-0.1.1/pyproject.toml +55 -0
- proximo_proxmox-0.1.1/scripts/live-smoke/README.md +144 -0
- proximo_proxmox-0.1.1/scripts/live-smoke/lib.sh +179 -0
- proximo_proxmox-0.1.1/scripts/live-smoke/netplane-smoke.py +147 -0
- proximo_proxmox-0.1.1/scripts/live-smoke/netplane-smoke.sh +51 -0
- proximo_proxmox-0.1.1/scripts/live-smoke/phase1-smoke.py +229 -0
- proximo_proxmox-0.1.1/scripts/live-smoke/phase1-smoke.sh +57 -0
- proximo_proxmox-0.1.1/scripts/live-smoke/readonly-smoke.py +88 -0
- proximo_proxmox-0.1.1/scripts/live-smoke/readonly-smoke.sh +41 -0
- proximo_proxmox-0.1.1/src/proximo/__init__.py +7 -0
- proximo_proxmox-0.1.1/src/proximo/__main__.py +9 -0
- proximo_proxmox-0.1.1/src/proximo/_a2a_entry.py +36 -0
- proximo_proxmox-0.1.1/src/proximo/_tls.py +27 -0
- proximo_proxmox-0.1.1/src/proximo/a2a/__init__.py +22 -0
- proximo_proxmox-0.1.1/src/proximo/a2a/__main__.py +6 -0
- proximo_proxmox-0.1.1/src/proximo/a2a/app.py +183 -0
- proximo_proxmox-0.1.1/src/proximo/a2a/card.py +92 -0
- proximo_proxmox-0.1.1/src/proximo/a2a/executor.py +144 -0
- proximo_proxmox-0.1.1/src/proximo/a2a/skills.py +282 -0
- proximo_proxmox-0.1.1/src/proximo/access.py +669 -0
- proximo_proxmox-0.1.1/src/proximo/access_governance.py +763 -0
- proximo_proxmox-0.1.1/src/proximo/access_users.py +810 -0
- proximo_proxmox-0.1.1/src/proximo/audit.py +234 -0
- proximo_proxmox-0.1.1/src/proximo/backends.py +224 -0
- proximo_proxmox-0.1.1/src/proximo/backup.py +351 -0
- proximo_proxmox-0.1.1/src/proximo/cloudinit.py +426 -0
- proximo_proxmox-0.1.1/src/proximo/cluster_ops.py +557 -0
- proximo_proxmox-0.1.1/src/proximo/config.py +102 -0
- proximo_proxmox-0.1.1/src/proximo/config_edit.py +474 -0
- proximo_proxmox-0.1.1/src/proximo/diagnose.py +139 -0
- proximo_proxmox-0.1.1/src/proximo/disk_ops.py +514 -0
- proximo_proxmox-0.1.1/src/proximo/firewall.py +716 -0
- proximo_proxmox-0.1.1/src/proximo/network.py +582 -0
- proximo_proxmox-0.1.1/src/proximo/observability.py +465 -0
- proximo_proxmox-0.1.1/src/proximo/pbs.py +938 -0
- proximo_proxmox-0.1.1/src/proximo/planning.py +373 -0
- proximo_proxmox-0.1.1/src/proximo/provisioning.py +357 -0
- proximo_proxmox-0.1.1/src/proximo/server.py +2081 -0
- proximo_proxmox-0.1.1/src/proximo/storage.py +236 -0
- proximo_proxmox-0.1.1/src/proximo/storage_admin.py +445 -0
- proximo_proxmox-0.1.1/src/proximo/tasks_pools.py +490 -0
- proximo_proxmox-0.1.1/tests/test_a2a_auth.py +112 -0
- proximo_proxmox-0.1.1/tests/test_a2a_card.py +87 -0
- proximo_proxmox-0.1.1/tests/test_a2a_e2e.py +61 -0
- proximo_proxmox-0.1.1/tests/test_a2a_entry.py +64 -0
- proximo_proxmox-0.1.1/tests/test_a2a_executor.py +249 -0
- proximo_proxmox-0.1.1/tests/test_a2a_integration.py +144 -0
- proximo_proxmox-0.1.1/tests/test_a2a_skills.py +268 -0
- proximo_proxmox-0.1.1/tests/test_access.py +849 -0
- proximo_proxmox-0.1.1/tests/test_access_governance.py +1061 -0
- proximo_proxmox-0.1.1/tests/test_access_users.py +1230 -0
- proximo_proxmox-0.1.1/tests/test_backends.py +294 -0
- proximo_proxmox-0.1.1/tests/test_backup.py +600 -0
- proximo_proxmox-0.1.1/tests/test_cloudinit.py +649 -0
- proximo_proxmox-0.1.1/tests/test_cluster_ops.py +740 -0
- proximo_proxmox-0.1.1/tests/test_config.py +57 -0
- proximo_proxmox-0.1.1/tests/test_config_edit.py +802 -0
- proximo_proxmox-0.1.1/tests/test_diagnose.py +173 -0
- proximo_proxmox-0.1.1/tests/test_disk_ops.py +678 -0
- proximo_proxmox-0.1.1/tests/test_firewall.py +935 -0
- proximo_proxmox-0.1.1/tests/test_ledger.py +233 -0
- proximo_proxmox-0.1.1/tests/test_main_module.py +11 -0
- proximo_proxmox-0.1.1/tests/test_mcp_stdio_e2e.py +49 -0
- proximo_proxmox-0.1.1/tests/test_network.py +850 -0
- proximo_proxmox-0.1.1/tests/test_observability.py +821 -0
- proximo_proxmox-0.1.1/tests/test_pbs.py +1178 -0
- proximo_proxmox-0.1.1/tests/test_planning.py +368 -0
- proximo_proxmox-0.1.1/tests/test_provisioning.py +641 -0
- proximo_proxmox-0.1.1/tests/test_server_new_wiring.py +257 -0
- proximo_proxmox-0.1.1/tests/test_server_plan.py +571 -0
- proximo_proxmox-0.1.1/tests/test_server_round3_wiring.py +158 -0
- proximo_proxmox-0.1.1/tests/test_storage.py +390 -0
- proximo_proxmox-0.1.1/tests/test_storage_admin.py +784 -0
- proximo_proxmox-0.1.1/tests/test_tasks_pools.py +905 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.12", "3.13"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: ${{ matrix.python-version }}
|
|
19
|
+
- name: Install
|
|
20
|
+
run: python -m pip install -e ".[dev]"
|
|
21
|
+
- name: Lint
|
|
22
|
+
run: ruff check .
|
|
23
|
+
- name: Test
|
|
24
|
+
run: pytest -q -ra
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Virtualenvs / caches
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
|
|
16
|
+
# Debian build artifacts
|
|
17
|
+
debian/proximo/
|
|
18
|
+
debian/.debhelper/
|
|
19
|
+
debian/files
|
|
20
|
+
debian/*.substvars
|
|
21
|
+
debian/*.log
|
|
22
|
+
*.deb
|
|
23
|
+
*.buildinfo
|
|
24
|
+
*.changes
|
|
25
|
+
|
|
26
|
+
# Proximo runtime — never commit audit logs or real config
|
|
27
|
+
*.log
|
|
28
|
+
audit.log
|
|
29
|
+
*.env
|
|
30
|
+
!*.env.example
|
|
31
|
+
|
|
32
|
+
# Lockfile (library — consumers resolve their own deps)
|
|
33
|
+
uv.lock
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Proximo. Format loosely follows Keep a Changelog; versions are SemVer.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
_Nothing yet._
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## [0.1.1] — 2026-06-10 — "Spaniard"
|
|
12
|
+
|
|
13
|
+
Hardening + release-readiness pass driven by an independent multi-team audit (3 cold reviewers,
|
|
14
|
+
40 doc claims source-verified, full-history leak audit, adversarial verification of every finding).
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **Realm options dict** (`8d2dac0`): `pve_realm_create` and `pve_realm_update` now accept a
|
|
18
|
+
type-specific `options` dict — LDAP (`server1`/`base_dn`/`user_attr`), AD (`domain`/`server1`),
|
|
19
|
+
OpenID (`issuer-url`/`client-id`). Previously, creating any LDAP/AD/OpenID realm was impossible
|
|
20
|
+
through the tool. Live-proven against a real PVE 9.2 API.
|
|
21
|
+
- **Governance/dangerous plane — live-proven to execute** (milestone): the governance and dangerous
|
|
22
|
+
plane (identity role/group/user/ACL; storage; SDN apply; network apply; realm create) that was
|
|
23
|
+
previously built+redteamed but MOCKED-only is now **proven to execute create→read→delete against
|
|
24
|
+
a real PVE 9.2 API on a nested test cluster**. Also proven on a nested 3-node test cluster:
|
|
25
|
+
offline guest migration (including local-disk) and HA-config operations (resource add/list/remove)
|
|
26
|
+
execute. PROVE ledger verified throughout. **Honest scope:** "nested test cluster" — not
|
|
27
|
+
production scale; HA **fencing** (hardware watchdog) and **online** live-migration (shared storage)
|
|
28
|
+
remain unproven.
|
|
29
|
+
- **CI**: GitHub Actions workflow — ruff + the full pytest suite on Python 3.12 and 3.13.
|
|
30
|
+
|
|
31
|
+
### Security
|
|
32
|
+
- **A2A perimeter hardening** (`a8ce10b`, `0d952a6`): fail-closed by design — non-localhost bind
|
|
33
|
+
is **refused** unless `PROXIMO_A2A_TOKEN_FILE` is set; bearer auth (constant-time comparison) on
|
|
34
|
+
the JSON-RPC control endpoint when a token is set; Host-header allowlist + DNS-rebind defense
|
|
35
|
+
(`PROXIMO_A2A_ALLOWED_HOSTS`); `'*'` in the allowlist warns rather than silently disabling. The
|
|
36
|
+
agent card declares the bearer scheme. localhost-default dev behavior unchanged; A2A stays opt-in.
|
|
37
|
+
- **Audit ledger file permissions:** the ledger is now created `0600` (owner-only) instead of the
|
|
38
|
+
umask default — entries can carry command/SQL detail and were world-readable on typical umasks.
|
|
39
|
+
Applies at creation; an existing file keeps the mode its operator set.
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
- Realm create/update no longer silently ignores type-specific options (LDAP/AD/OpenID realms
|
|
43
|
+
were uncreatable before this fix).
|
|
44
|
+
- **Audit-integrity:** `ct_logs` now enforces the CTID allowlist at the server layer like its
|
|
45
|
+
siblings — a forbidden CTID ledgers as `blocked:allowlist` instead of surfacing as a backend error,
|
|
46
|
+
so allowlist denials are uniformly traceable in the PROVE ledger. Blocked entries for read-only
|
|
47
|
+
tools (`ct_logs`, `ct_diagnose`) now ledger `mutation: false`, matching the tool's true class.
|
|
48
|
+
- **Packaging:** `proximo-a2a` without the `[a2a]` extra now prints a one-line
|
|
49
|
+
`pip install "proximo[a2a]"` hint (exit 2) instead of a raw `ModuleNotFoundError` traceback —
|
|
50
|
+
including when only `uvicorn` is missing; a missing *submodule* of an installed dependency still
|
|
51
|
+
tracebacks (that is a real environment bug, not a missing extra).
|
|
52
|
+
|
|
53
|
+
### Notes
|
|
54
|
+
- **117 MCP tools; 1964 tests passing (0 skipped); ruff clean.** Public on GitHub 2026-06-10; PyPI/GHCR pending.
|
|
55
|
+
- Docs: public-readiness scrub of ROADMAP/CHANGELOG/POSITIONING; README install command made
|
|
56
|
+
copy-pasteable; claim wording tightened to carry its own scope. Lint: 3 leftover warnings in the
|
|
57
|
+
live-smoke scripts cleaned.
|
|
58
|
+
|
|
59
|
+
## [0.1.0] — 2026-06-09 — "Spaniard"
|
|
60
|
+
|
|
61
|
+
First blood — the foundation of the ethical Proxmox MCP. _Tagged `v0.1.0`; not yet published to
|
|
62
|
+
PyPI/GHCR (local/private). Honest scope: 117 MCP tools, most exercised against mocks only; the trust
|
|
63
|
+
spine + core lifecycle are live-proven, the governance plane is built/redteamed but not yet live-fired._
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
- **MCP stdio transport, proven end-to-end:** `python -m proximo` entry point; the `initialize` handshake
|
|
67
|
+
advertises Proximo's own version (not the MCP SDK's); covered by a real-client integration test
|
|
68
|
+
(`test_mcp_stdio_e2e.py`: client → stdio → FastMCP dispatch → tool → back).
|
|
69
|
+
- Two backends: **REST API management** (scoped token) + **`ssh`→`pct` in-container exec** (local or remote).
|
|
70
|
+
- **MCP tool surface** (FastMCP): `pve_node_status`, `pve_list_guests`, `pve_guest_status`,
|
|
71
|
+
`pve_guest_power`, `ct_exec`, `ct_psql`, `ct_logs`.
|
|
72
|
+
- **Ethical spine:** append-only audit log (records real outcomes), confirm-gates on every mutating tool,
|
|
73
|
+
fail-closed CTID allowlist, input validation on API path components (vmid/kind/node).
|
|
74
|
+
- Tests (13) + ruff lint config. Clean run.
|
|
75
|
+
|
|
76
|
+
### Security
|
|
77
|
+
- Security redteam (2026-06-07): **5 findings, all fixed** —
|
|
78
|
+
`ct_exec`/`ct_psql` now confirm-gated; allowlist now fails **closed**; audit records real outcomes
|
|
79
|
+
(errors included); `vmid`/`kind`/`node` validated against injection; TLS-disabled now warns.
|
|
80
|
+
- Verified solid: command injection (shlex-correct on local + ssh + psql paths); the API token is never
|
|
81
|
+
logged, never enters the audit log, subprocess argv, or error messages.
|
|
82
|
+
|
|
83
|
+
### PROVE pillar — tamper-evident ledger (2026-06-07)
|
|
84
|
+
- The audit log is now a **hash-chained, tamper-evident ledger**: `entry_hash = sha256(prev_hash + body)`,
|
|
85
|
+
flock-guarded, fsync'd. `verify()` and the `audit_verify` MCP tool detect any altered / deleted /
|
|
86
|
+
inserted / reordered entry and pinpoint the break; `head()` is anchorable off-box. Tamper-**evident**,
|
|
87
|
+
not tamper-proof (honestly scoped). +6 tamper-detection tests. Redteam: 2 findings fixed.
|
|
88
|
+
- This is one of the four trust-layer pillars (PLAN · UNDO · **PROVE** · DIAGNOSE) — see POSITIONING.md.
|
|
89
|
+
|
|
90
|
+
### PLAN pillar — dry-run by default (2026-06-07)
|
|
91
|
+
- New `proximo.planning` module: **every mutating tool now previews before it acts.** Called without
|
|
92
|
+
`confirm=True`, `pve_guest_power` / `ct_exec` / `ct_psql` return a **plan** — the exact change, the
|
|
93
|
+
guest's live state (power), blast radius, and an **advisory, heuristic risk rating** — instead of
|
|
94
|
+
executing. `confirm=True` then executes. You structurally cannot mutate without a plan first existing.
|
|
95
|
+
- **PLAN ⊗ PROVE:** the previewed plan (including the live state it was based on) is written to the
|
|
96
|
+
tamper-evident ledger with `outcome="planned"`; a confirmed execution records `confirmed=true`. The
|
|
97
|
+
approval trail — *what preview was shown before the action* — is now verifiable, not just *that* it ran.
|
|
98
|
+
- **Honest by design (guard every path to LOW):** `LOW` means "does not change state," not "safe";
|
|
99
|
+
the absence of a `HIGH` flag is not a safety signal; destructive signatures are curated, not exhaustive.
|
|
100
|
+
- Adversarial review: confirmed bypasses fixed — whitelist audit (`find -delete`, `ip route add`,
|
|
101
|
+
`mount <dev>` no longer rate "read-only"); SQL `SELECT pg_terminate_backend()/lo_import()`,
|
|
102
|
+
`COPY ... PROGRAM` (RCE) now escalate; failed dry-runs are audited; `current` state recorded; latent
|
|
103
|
+
`_max_risk`/`_fmt_uptime` edge crashes fixed. Every confirmed bypass became a regression test.
|
|
104
|
+
- Tests: **81 total** (was 21), ruff clean.
|
|
105
|
+
- **Guarantee enforced:** the plan is recorded on BOTH paths — even a one-shot `confirm=True` records
|
|
106
|
+
its `planned` entry before mutating (no plan, no mutation). The PLAN→PROVE triplet
|
|
107
|
+
(`planned → ok/confirmed`) is uniform; a one-shot confirm can't bypass the recorded preview.
|
|
108
|
+
|
|
109
|
+
### UNDO pillar — auto-snapshot before mutating + one-call revert (2026-06-07)
|
|
110
|
+
- **Snapshot backend + tools:** `pve_snapshot_list` (read), `pve_snapshot_create`, `pve_rollback`
|
|
111
|
+
(DESTRUCTIVE — discards changes since the snapshot), `pve_snapshot_delete` (all PLAN-gated), and
|
|
112
|
+
`pve_task_status` to poll the async task UPIDs these return. Endpoints verified against PVE docs.
|
|
113
|
+
- **The headline — auto-undo before exec:** `ct_exec`/`ct_psql` gain `snapshot=True`. With `confirm=True`
|
|
114
|
+
it takes a `proximo_undo_<ts>` snapshot **and waits for the task to finish** before running the
|
|
115
|
+
mutation, records the undo point, and returns it. **Fail-closed:** if the snapshot can't be created
|
|
116
|
+
or doesn't finish OK (e.g. storage doesn't support snapshots), the command is **NOT run**.
|
|
117
|
+
- **Honest:** snapshots are storage-dependent (ZFS/BTRFS/LVM-thin; not directory/raw) — surfaced in the
|
|
118
|
+
plan, never assumed. Rollback's PLAN spells out the blast radius. Async ops record `outcome="submitted"`
|
|
119
|
+
(not "ok") so the ledger never claims an in-flight task is done.
|
|
120
|
+
- Adversarial review: confirmed fixes, each a regression test — regex anchors `$`→`\Z` (newline bypass),
|
|
121
|
+
UPID length cap + reserved-name (`current`) guard, microsecond-unique undo names, strict task-exit
|
|
122
|
+
(fail-closed on missing `exitstatus`), server-layer allowlist gate (no orphaned snapshot for a
|
|
123
|
+
forbidden CTID), non-contradictory rollback preview when the snapshot is missing.
|
|
124
|
+
- Tests: **116 total**, ruff clean.
|
|
125
|
+
|
|
126
|
+
### DIAGNOSE pillar — read-first "what's broken" (2026-06-07)
|
|
127
|
+
- New `proximo.diagnose` module + tools: `ct_diagnose` (API guest status + a FIXED read-only
|
|
128
|
+
in-container battery — failed units, disk, recent errors, memory, listening ports) and
|
|
129
|
+
`pve_diagnose` (node status + storage usage + recent failed tasks). Both strictly READ-ONLY
|
|
130
|
+
(no confirm, no mutation), audited. Backend reads: `node_storage`, `node_tasks`.
|
|
131
|
+
- **Honest by design:** advisory flags, never causation ("signal present", not "the cause is X").
|
|
132
|
+
Flags also surface **incompleteness** — partial mode (exec off → API-only + a skipped-probes flag),
|
|
133
|
+
a failed read, or a failed probe all flag, so an empty `flags` list can never read as a false clean
|
|
134
|
+
bill of health. Inactive/offline storage is reported as offline, not as "full" (no stale-data alarm).
|
|
135
|
+
- Adversarial review — read-only guarantee held (no injection, gates correct); the task-list `status`
|
|
136
|
+
field was **verified against the live PVE API**. Fixes, each a regression test: incompleteness flags,
|
|
137
|
+
inactive-storage handling, removed dead `--no-legend` guard, `_frac` inf/overflow guard, transient/
|
|
138
|
+
WARNINGS tasks no longer counted as failed, `node_tasks` limit clamp, `ExecBackend` vmid validation.
|
|
139
|
+
- Tests: **141 total**, ruff clean. **All four trust-layer pillars (PLAN · UNDO · PROVE · DIAGNOSE) now built.**
|
|
140
|
+
|
|
141
|
+
### Coverage expansion — phases 1–7 (2026-05 → 2026-06)
|
|
142
|
+
- Grew the MCP surface from the 7 foundation tools to **117** `@mcp.tool()` tools, every mutating one
|
|
143
|
+
wearing PLAN+UNDO+PROVE by construction: provisioning/backup/restore, config/disk/cloud-init mutation, the
|
|
144
|
+
four "dangerous plane" domains (**firewall · network/SDN · cluster HA/migration · ACL/users/roles/realms**),
|
|
145
|
+
observability, task/pool control, storage admin, and **PBS-native** deep tools (GC/verify/prune/snapshots/
|
|
146
|
+
namespaces; separate `:8007` backend, TLS fail-closed).
|
|
147
|
+
- **Live-proven** against a real PVE: the core provisioning/config mutate cycle (create→config→revert→
|
|
148
|
+
clone→backup→restore→delete, ledger verified) + read shapes across node/storage/observability + a
|
|
149
|
+
PBS datastore. **Honest scope:** the bulk of the 117-tool surface — *including the dangerous plane* —
|
|
150
|
+
is **MOCKED-only** (unit-tested against fakes, not fired against real Proxmox). A broad live smoke needs a
|
|
151
|
+
wider scoped token. See the `ROADMAP.md` reality-check and `LANDSCAPE.md`.
|
|
152
|
+
|
|
153
|
+
### A2A (Agent2Agent) face — experimental (2026-06-09)
|
|
154
|
+
- Optional second protocol head (`pip install 'proximo[a2a]'` → `proximo-a2a`): a curated **16-skill slice**
|
|
155
|
+
exposed over A2A, routing to the same server tools so PLAN/PROVE/UNDO/fail-closed are inherited. Serves an
|
|
156
|
+
agent card at `/.well-known/agent-card.json`; localhost by default (no built-in auth — warns on
|
|
157
|
+
non-localhost). Built + redteamed (PLAN-bypass + slice-boundary: **0 findings**); +47 tests. **Proven
|
|
158
|
+
end-to-end against a real a2a-sdk client** — agent-card resolve over HTTP + a real `message/send` invoking a
|
|
159
|
+
skill → completed task with a `result` artifact (real-socket proof + an in-process integration test,
|
|
160
|
+
`test_a2a_e2e.py`).
|
|
161
|
+
|
|
162
|
+
### PROVE — opt-in HMAC-keyed audit chain (2026-06-09)
|
|
163
|
+
- The audit ledger now supports an **opt-in keyed mode**: set `PROXIMO_AUDIT_KEY_PATH` to chain entries
|
|
164
|
+
with **HMAC-SHA256** instead of bare SHA-256 (key auto-generated at 0600 via an atomic temp+link, hex
|
|
165
|
+
stored, fail-closed on empty/non-hex/<32-byte). The **ledger's key is authoritative** — a downgrade
|
|
166
|
+
(strip the HMAC, recompute as SHA-256 without the key) is rejected; a keyed log must be all-keyed. Default
|
|
167
|
+
stays **unkeyed and byte-identical** (existing logs + tests unaffected); `audit_verify` reports `keyed`.
|
|
168
|
+
Adversarial review (forge / key-handling / verify lenses): no exploitable forgery; +12 tests incl. the downgrade
|
|
169
|
+
attack. **Honest scope:** keying resists forward-rewrite by an attacker *without* the key, but a same-user
|
|
170
|
+
attacker who can write the 0600 log can often read the 0600 key — the **off-box `head()` anchor remains
|
|
171
|
+
the strong guarantee.** Not a "cryptographic depth" moat.
|
|
172
|
+
|
|
173
|
+
### Honesty note (2026-06-09)
|
|
174
|
+
- The PBS cert fingerprint is stored but **not yet wire-enforced**.
|
|
175
|
+
|
|
176
|
+
### Notes
|
|
177
|
+
- Not yet released; **pre-alpha.** Apache-2.0 LICENSE: ✅ added. Pending: broad live smoke of the
|
|
178
|
+
mocked surface (needs a properly-scoped token), publish (PyPI/GHCR + CI) so the install commands work.
|
|
179
|
+
|
|
180
|
+
_Strength and honor._
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Proximo — self-contained, sovereign, on-demand.
|
|
2
|
+
# The MCP client launches it per session: `docker run -i --rm ... proximo` (stdio).
|
|
3
|
+
FROM python:3.13-slim
|
|
4
|
+
|
|
5
|
+
# openssh-client powers the in-container exec edge (ssh -> pct). Everything else is bundled by pip,
|
|
6
|
+
# so the image is self-contained and the host stays untouched.
|
|
7
|
+
RUN apt-get update \
|
|
8
|
+
&& apt-get install -y --no-install-recommends openssh-client \
|
|
9
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
10
|
+
|
|
11
|
+
WORKDIR /app
|
|
12
|
+
COPY . /app
|
|
13
|
+
RUN pip install --no-cache-dir .
|
|
14
|
+
|
|
15
|
+
# MCP stdio server — no daemon, no open port. Launched on demand by the client.
|
|
16
|
+
ENTRYPOINT ["proximo"]
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Proximo — The Proxmox Automation Landscape
|
|
2
|
+
|
|
3
|
+
> **Created** 2026-06-08 · **Refreshed** 2026-06-09 (method-corrected sweep; see Method).
|
|
4
|
+
> **Refreshed 2026-06-10** (competitor numbers re-verified; Proximo governance plane now live-proven to
|
|
5
|
+
> execute; A2A perimeter parity closed; official-Proxmox-MCP threat added).
|
|
6
|
+
> An honest, source-verified survey of the Proxmox automation field across four modalities
|
|
7
|
+
> (MCP / A2A / AI / API-IaC), with Proximo's own position stated plainly — including where it is late,
|
|
8
|
+
> unproven, or simply not first. No manufactured foils.
|
|
9
|
+
|
|
10
|
+
> **Method.** Competitors are ranked by real popularity (GitHub stars, registry presence). Tool counts
|
|
11
|
+
> and safety features were re-read from the repositories on 2026-06-09 — not inferred from READMEs or
|
|
12
|
+
> star counts, which miss feature drift. A keyword-only search (`proxmox` + `mcp`/`ai`) misses tools
|
|
13
|
+
> whose primary identity is something else — e.g. a multi-backend homelab cockpit that exposes Proxmox
|
|
14
|
+
> as one backend among many — so this survey adds an **off-keyword pass** for that class. A survey's
|
|
15
|
+
> silence means "not found," never "does not exist"; treat each finding as as-of its date.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## TL;DR — the Proxmox field, four lanes
|
|
20
|
+
|
|
21
|
+
1. **MCP (AI-native) — contested; Proximo is not first.** Two ~250★ leaders (**canvrno** ~261★, read-only
|
|
22
|
+
"safe inspector" with ~6 tools; **RekklesNA/ProxmoxMCP-Plus** ~241★, the active governance leader), a
|
|
23
|
+
long <50★ tail, and one real *trust* peer (**proxxx**). **Raw tool-count is not a moat:**
|
|
24
|
+
`chajus1/proxmox-mcp-enhanced` already claims **115 tools** — within a couple of Proximo's 117, and a
|
|
25
|
+
raw count says nothing about whether the tools are proven (a significant portion of Proximo's lifecycle
|
|
26
|
+
surface still runs against mocks — see *Where Proximo stands*).
|
|
27
|
+
2. **A2A (agent-to-agent) — greenfield for Proxmox.** No dedicated open A2A agent-card/server for Proxmox
|
|
28
|
+
found (off-keyword sweep included). Homelabbers run multi-agent systems *on* Proxmox; nobody exposes
|
|
29
|
+
Proxmox *as* an A2A participant. Demand is unverified — flagged, not claimed.
|
|
30
|
+
3. **AI (non-MCP automation) — hobby-tier, unconsolidated.** n8n templates, Prox-AI, OpenClaw, Clawdbot,
|
|
31
|
+
Paperclip — real activity, near-zero stars, no serious product. The serious builders are choosing MCP,
|
|
32
|
+
so this lane mostly feeds Lane 1.
|
|
33
|
+
4. **API / IaC — the mature base layer (different modality, not a rival).** Terraform (Telmate ~2.9k★, bpg
|
|
34
|
+
~2k★), Ansible `community.general.proxmox`, proxmoxer ~787★. Proximo doesn't compete here — but its
|
|
35
|
+
PLAN/UNDO maps onto the **plan/apply/destroy** idiom those users already trust.
|
|
36
|
+
|
|
37
|
+
**The honest summary:** Proximo is a late, unstarred entrant in the contested MCP lane. Its defensible
|
|
38
|
+
thesis is **not** "first," "most tools," or "the only one with trust." It is **trust *by construction***
|
|
39
|
+
(every mutation carries PLAN + UNDO + PROVE in-band, fail-closed) **× coverage of the dangerous/governance
|
|
40
|
+
plane** (firewall/SDN/ACL/roles/realms/PBS) that even the leaders keep off the MCP surface **× auto-UNDO**
|
|
41
|
+
(fail-closed snapshot-before-mutate). You can bolt a `--dry-run` flag onto one tool; you cannot retrofit
|
|
42
|
+
auto-snapshot + hash-chain + blast-radius across 100+ existing flat tools after the fact.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Lane 1 — MCP servers for Proxmox VE (ranked, stars re-pulled 2026-06-10)
|
|
47
|
+
|
|
48
|
+
| # | Repo | ★ | Tools | Lang | What it is / safety posture (source-verified 06-10) |
|
|
49
|
+
|---|---|---|---|---|---|
|
|
50
|
+
| 1 | **canvrno/ProxmoxMCP** | ~261 | ~6 | Py | Most-starred. Read-mostly "safe inspector," built for Cline. Popular *because* it doesn't hold the knives. |
|
|
51
|
+
| 2 | **RekklesNA/ProxmoxMCP-Plus** | ~241 | ~42 | Py | **Active governance leader** (v0.5.8, Jun 7 2026). VMs/CT/snap/backup/ISO/storage/cluster + SSH-exec + job-control (list/get/poll/cancel/retry). Gov = `command_policy` + `approval_token` + TLS + DNS-rebind. **NO dry-run / NO auto-rollback / NO blast-radius / NO firewall·SDN·ACL·HA.** Permissive by default. |
|
|
52
|
+
| 3 | **chajus1/proxmox-mcp-enhanced** | ~10 | **115** | Py | ⚠️ **The breadth rival.** Claims 115 tools "covering every aspect." Trust layer **unverified/absent** — but it rules out any "most complete by count" claim. Its dangerous-op coverage should be verified before anyone claims the completeness lane. |
|
|
53
|
+
| 4 | **fabriziosalmi/proxxx** | ~15 | **25 (MCP)** | Rust | **The real TRUST peer** (v0.8.4, May 30 2026, 43 releases). MCP = VM ops + cluster diag + PBS *browse/restore* + GitOps state export/diff/**`--dry-run`** + audit-verify. Has a pre-flight **risk gate (PLAN-ish)** + **HMAC-keyed offline-verifiable audit chain** (PROVE — arguably stronger than Proximo's default-unkeyed ledger) + Telegram **HITL**. **No auto-UNDO** (read-only rollback *preview* only). **Firewall/SDN/ACL/PBS-writes are NOT on the MCP surface** — they live in the human TUI. |
|
|
54
|
+
| 5 | gilby125/mcp-proxmox | ~41 | ~55 | JS | Configurable permissions. |
|
|
55
|
+
| 6 | Markermav/ProxmoxMCP-advance | ~24 | — | Py | Multi-client (Claude/Goose/Cline). |
|
|
56
|
+
| 7 | bsahane/mcp-proxmox | ~18 | — | Py | FastMCP, token auth, monitoring. |
|
|
57
|
+
| 8 | mdlmarkham/TailOpsMCP | ~13 | — | Py | Homelab ops over Tailscale (multi-host; see Cross-cut A). |
|
|
58
|
+
| 9 | tyxak/remotepower | ~12 | — | Py | Dashboard + CVE/patch + Proxmox MCP. |
|
|
59
|
+
| 10 | antonio-mello-ai/mcp-proxmox | ~11 | — | Py | Cluster mgmt via AI. |
|
|
60
|
+
| — | mjrestivo16 (35 tools), Samik081 (TS), jmerelnyc, GethosTheWalrus, agentify-sh, husniadil (PyPI), heybearc, ry-ops, plgonzalezrx8 (read-only+confirm), Zaptimist (ssh-exec), rodaddy (forks) | <10 | — | mix | The long tail. Registry-listed (PulseMCP/mcpmarket/Glama). |
|
|
61
|
+
|
|
62
|
+
**PBS-specific MCPs (PBS is not whitespace):** `szoran53/pbs-mcp-server` (TS), `ahmetem/pbs-mcp` (Py) —
|
|
63
|
+
datastore/snapshot/GC/verify/prune. proxxx covers PBS *browse/restore* inside its cockpit.
|
|
64
|
+
|
|
65
|
+
**Where Proximo differs (Lane 1):** the governance leader (RekklesNA) is permissive-by-default with no
|
|
66
|
+
PLAN/UNDO; the trust peer (proxxx) has PLAN+PROVE+HITL but keeps the dangerous plane out of MCP and has no
|
|
67
|
+
auto-UNDO; the breadth rival (chajus1) has count but no verified trust. The intersection none of them
|
|
68
|
+
holds — *the full firewall/SDN/ACL/roles/realms/PBS plane, exposed to the agent over MCP, every tool
|
|
69
|
+
PLAN+UNDO+PROVE by construction, fail-closed by default* — is where Proximo aims. That intersection is
|
|
70
|
+
currently empty.
|
|
71
|
+
|
|
72
|
+
## Lane 2 — A2A (agent-to-agent) for Proxmox — greenfield
|
|
73
|
+
|
|
74
|
+
- **No open A2A agent-card / server for Proxmox found** (incl. off-keyword sweep). A2A itself is large
|
|
75
|
+
(Google → Linux Foundation, 50+ partners; JSON-RPC/gRPC/REST + SSE + Agent Cards) — but nobody has
|
|
76
|
+
shipped "Proxmox as a first-class A2A participant."
|
|
77
|
+
- Closest: commercial **Mindflow** "Proxmox VE agent"; homelabbers running *multi-agent systems on*
|
|
78
|
+
Proxmox (Paperclip, Clawdbot) — agents-hosted-on-Proxmox, not Proxmox-as-agent.
|
|
79
|
+
- **Proximo's position:** an A2A Agent Card for Proxmox ("the Proxmox operator agent; here are its skills")
|
|
80
|
+
would be first in this lane. Demand is unverified — no signal yet that anyone is asking.
|
|
81
|
+
|
|
82
|
+
## Lane 3 — AI (non-MCP automation) for Proxmox — hobby-tier
|
|
83
|
+
|
|
84
|
+
| Project | Signal | What it is |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| **n8n "Proxmox AI agent" template** | popular no-code path | NL→Proxmox API via n8n + genAI; the most-reached-for non-coder route. |
|
|
87
|
+
| **folkvarlabs/Prox-AI** | ~5★, HCL | Terraform-config *generator* via Google Forms + cost-approval. Not an agent. |
|
|
88
|
+
| **OpenClaw** | — | Read-only LLM-backed Proxmox interface. |
|
|
89
|
+
| **Clawdbot / Paperclip** | — | LLM-with-tools runtimes deployed *in* Proxmox LXCs. |
|
|
90
|
+
|
|
91
|
+
No serious consolidated product here; the real builders pick MCP (Lane 1). This lane is a feeder, not a
|
|
92
|
+
separate front — though a one-command no-code on-ramp (e.g. an n8n node) would reach the non-coder crowd.
|
|
93
|
+
|
|
94
|
+
## Lane 4 — API / IaC clients — the mature base layer (different modality)
|
|
95
|
+
|
|
96
|
+
Terraform **bpg** ~2k★ (modern leader, plan/apply/destroy) & **Telmate** ~2.9k★ (legacy) · Ansible
|
|
97
|
+
`community.general.proxmox` (huge usage) · **proxmoxer** ~787★ (dominant Py wrapper) · Go (Telmate ~487,
|
|
98
|
+
luthermonson ~267) · **Corsinvest cv4pve** suite (admin/autosnap/diag/metrics/botgram) · **CAPMOX** ~447★
|
|
99
|
+
(K8s Cluster-API). Proximo doesn't rival these — but their users already trust **plan/apply** semantics, so
|
|
100
|
+
Proximo's PLAN/UNDO speaks a dialect they know. Leverage, not competition.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Cross-cut A — the multi-backend / homelab-fleet shape
|
|
105
|
+
|
|
106
|
+
These never surface under "proxmox mcp"; Proxmox is one backend among several. This is the class a
|
|
107
|
+
keyword search misses, and the one to keep watching:
|
|
108
|
+
- **bshandley/homelab-mcp** — MCP over Docker + OPNsense (firewall) + TrueNAS + **Proxmox** + Home Assistant;
|
|
109
|
+
read-only→write capability tiers. A unified-homelab play on the "AI runs my whole homelab" pitch.
|
|
110
|
+
- **AI-Engineering-at/homelab-mcp-bundle** (~4★) — 8-server homelab bundle incl. Proxmox.
|
|
111
|
+
- **mdlmarkham/TailOpsMCP** (~13★) — multi-host homelab ops over Tailscale.
|
|
112
|
+
- **shareed2k/Honey** — searches service instances across platforms incl. Proxmox.
|
|
113
|
+
|
|
114
|
+
**Implication:** Proximo's bet is *depth on one platform with trust*; this class's bet is *breadth across
|
|
115
|
+
the homelab*. Different bets — but if "AI runs my homelab" becomes the dominant framing, the breadth
|
|
116
|
+
players, not the Proxmox-MCP leaders, are the more direct competition.
|
|
117
|
+
|
|
118
|
+
## Cross-cut B — generic trust layers: can someone add PLAN/UNDO *for* Proxmox without building it?
|
|
119
|
+
|
|
120
|
+
The 2026 hot category is **MCP gateways / guardrails** — they sit in front of *any* MCP and add governance:
|
|
121
|
+
**IBM ContextForge** (3.8k★, Apache-2.0; proxies MCP **and A2A** and REST), **Docker MCP Gateway**,
|
|
122
|
+
**Lasso**, **Bifrost**, **TrueFoundry**, **Portkey**, **MintMCP**, **Obot**, **Traefik Hub**, **AWS Bedrock
|
|
123
|
+
AgentCore**. The adjacent AI-SRE market (Hyground, StackGen, NeuBird, Azure SRE Agent, SRE.ai) is
|
|
124
|
+
well-funded.
|
|
125
|
+
|
|
126
|
+
**Why this matters, source-verified:** every one of these gateways provides **auth + policy + audit +
|
|
127
|
+
(some) human-approval** — but **none provide dry-run, auto-rollback, or blast-radius**, because a gateway
|
|
128
|
+
is **resource-blind**: it can gate or log a tool call, but it can't snapshot a Proxmox VM or compute the
|
|
129
|
+
blast radius of an ACL change, because it doesn't understand the resource. **PLAN and UNDO are
|
|
130
|
+
domain-specific by necessity** — a generic layer can't do them *for* Proxmox.
|
|
131
|
+
|
|
132
|
+
**The honest threat (assemble-from-parts):** ContextForge (audit/policy/approval) + RekklesNA (coverage)
|
|
133
|
+
= a credible audit + policy + HITL story over Proxmox *today*, with no new code. That combo lacks
|
|
134
|
+
PLAN/UNDO/blast-radius — but if a buyer's bar is "audit + approval," it clears now. The defensible ground
|
|
135
|
+
is the part that can't be assembled: PLAN (live-state + blast-radius), UNDO (auto-snapshot/revert), and
|
|
136
|
+
coverage of the governance plane — not "has an audit log."
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Where Proximo honestly stands (no spin, no shrink)
|
|
141
|
+
|
|
142
|
+
- **Popularity:** zero (local, unpublished — v0.1.1, not on PyPI/GHCR, zero public stars). MCP leaders
|
|
143
|
+
~250★; IaC leaders ~2–3k★.
|
|
144
|
+
- **"First":** no. **"Most tools":** no (chajus1 ≈115). **"Only one with trust":** no (proxxx: risk-gate +
|
|
145
|
+
keyed audit chain + HITL; RekklesNA: command_policy + approval-token).
|
|
146
|
+
- **Genuinely differentiated, execution now confirmed on the key plane:**
|
|
147
|
+
1. **Trust by construction** — every mutation PLAN+UNDO+PROVE *in-band & fail-closed-by-default*, vs
|
|
148
|
+
proxxx's human-gates-each-act and RekklesNA's opt-in/audit-only.
|
|
149
|
+
2. **The dangerous/governance plane on the MCP surface** — firewall/SDN/ACL/roles/realms/PBS exposed *to
|
|
150
|
+
the agent*. RekklesNA doesn't cover it; proxxx keeps it in the TUI. This is the empty intersection.
|
|
151
|
+
The identity/storage/SDN/network/realm surface and offline migration + HA-config have been
|
|
152
|
+
**live-proven to execute** against a real PVE 9.2 API, including a nested 3-node test cluster, with
|
|
153
|
+
PROVE verified throughout. Still unproven: real HA fencing (hardware watchdog), online live-migration
|
|
154
|
+
(shared storage), and production scale.
|
|
155
|
+
3. **Auto-UNDO** — none of the above takes the snapshot for you; proxxx previews a rollback, it doesn't
|
|
156
|
+
perform one.
|
|
157
|
+
- **A2A face perimeter-parity closed:** fail-closed public bind, bearer auth on the control endpoint,
|
|
158
|
+
`PROXIMO_A2A_ALLOWED_HOSTS` Host/DNS-rebind allowlist — previously warn-only. Matches the leader's
|
|
159
|
+
perimeter posture.
|
|
160
|
+
- **Maturity, stated straight:** v0.1.1, unpublished; a significant portion of the broader ~117-tool
|
|
161
|
+
lifecycle surface still runs against mocks; MCP face is local stdio (no network bind); perimeter
|
|
162
|
+
hardening for MCP becomes required the day a remote transport is added. The differentiation above is now
|
|
163
|
+
execution-confirmed on the governance plane; lifecycle breadth and production scale remain to prove.
|
|
164
|
+
- **Emerging threat:** field chatter that Proxmox may ship an **official MCP server**. An official basic
|
|
165
|
+
server would commoditize the VM/LXC/snapshot/backup lifecycle layer. Proximo's durable answer is the
|
|
166
|
+
dangerous/governance plane and trust-by-construction — capabilities an official day-one server is
|
|
167
|
+
unlikely to ship. This risk is real; watch the Proxmox project for announcements.
|
|
168
|
+
|
|
169
|
+
## Sources
|
|
170
|
+
GitHub (stars + repo READMEs re-read 2026-06-10: canvrno, RekklesNA v0.5.8, proxxx v0.8.4, chajus1,
|
|
171
|
+
gilby125, bshandley/homelab-mcp); PulseMCP / mcpmarket / Glama registries; IBM/mcp-context-forge (3.8k★,
|
|
172
|
+
v1.0.2); Integrate.io & TrueFoundry MCP-gateway roundups; agamm/awesome-ai-sre; a2a-protocol.org;
|
|
173
|
+
Mindflow; n8n Proxmox-AI template.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2026 John Broadway
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|