portacode 1.4.13.dev0__tar.gz → 1.4.13.dev2__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.
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/PKG-INFO +1 -1
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/_version.py +2 -2
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md +6 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/proxmox_infra.py +161 -112
- portacode-1.4.13.dev2/portacode/connection/handlers/test_proxmox_infra.py +13 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode.egg-info/PKG-INFO +1 -1
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode.egg-info/SOURCES.txt +1 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/.claude/agents/communication-manager.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/.claude/settings.local.json +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/.gitignore +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/.gitmodules +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/LICENSE +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/MANIFEST.in +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/Makefile +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/backup.sh +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/connect.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/connect.sh +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/docker-compose.yaml +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/docs/images/device-transfer-button.png +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/docs/images/device-transfer-modal.png +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/docs/images/pair-device-button.png +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/docs/images/pairing-request.png +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/docs/images/student-workspace.png +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/simple_device/Dockerfile +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/simple_device/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/simple_device/data/device-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/simple_device/docker-compose.yaml +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/Dockerfile +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/.local/share/portacode/run/gateway.pid +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/.gitignore +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/db.sqlite3 +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/settings.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/__pycache__/wsgi.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/admin.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/apps.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/menu.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/models.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/urls.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/__pycache__/views.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-01/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-02/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-03/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-04/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-05/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-06/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-07/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-08/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-09/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/.local/share/portacode/keys/id_portacode.pub +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/data/student-10/workspace/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/docker-compose.yaml +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/galactic_bakeshop/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/galactic_bakeshop/asgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/galactic_bakeshop/settings.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/galactic_bakeshop/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/galactic_bakeshop/wsgi.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/manage.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/templates/treats/home.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/admin.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/apps.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/menu.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/migrations/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/urls.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/initial_content/treats/views.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/examples/workshop_fleet/instructions/WELCOME.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/__main__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/cli.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/client.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/base.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/chunked_content.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/diff_handlers.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/file_handlers.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_aware_file_handlers.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state/file_system_watcher.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state/git_manager.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state/handlers.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state/manager.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state/models.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state/utils.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/project_state_handlers.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/registry.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/session.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/system_handlers.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/tab_factory.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/terminal_handlers.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/update_handler.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/multiplex.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/terminal.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/data.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/keypair.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/__pycache__/__init__.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/__pycache__/link_capture_wrapper.cpython-311.pyc +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/elinks +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/gio-open +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/gnome-open +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/gvfs-open +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/kde-open +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/kfmclient +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/link_capture_exec.sh +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/link_capture_wrapper.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/links +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/links2 +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/lynx +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/mate-open +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/netsurf +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/sensible-browser +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/w3m +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/x-www-browser +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/link_capture/bin/xdg-open +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/logging_categories.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/pairing.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/service.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/static/js/test-ntp-clock.html +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/static/js/utils/ntp-clock.js +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/utils/NTP_ARCHITECTURE.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/utils/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/utils/diff_apply.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/utils/diff_renderer.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/utils/ntp_clock.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode.egg-info/dependency_links.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode.egg-info/entry_points.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode.egg-info/requires.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode.egg-info/top_level.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/pyproject.toml +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/restore.sh +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/run_tests.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/setup.cfg +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/setup.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test.sh +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_device_online.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_file_operations.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_git_status_ui.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_login_flow.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_navigate_testing_folder.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_play_store_screenshots.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_terminal_buffer_performance.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_terminal_interaction.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_terminal_loading_race_condition.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_modules/test_terminal_start.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/test_request_id.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/.env.example +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/README.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/cli.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/core/__init__.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/core/base_test.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/core/cli_manager.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/core/hierarchical_runner.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/core/playwright_manager.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/core/runner.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/core/shared_cli_manager.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/core/test_discovery.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/testing_framework/requirements.txt +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/UI_UX/opening_a_file_on_desktop_results_in_nothing.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/agent_context_management.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/django_server_time_sync.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/issues/device_performance_degradation.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/issues/git_data_not_captured_in_proxmox.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/issues/indefinite_resource_loading.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/issues/portacode_service_silently_down.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/issues/premature_terminal_exit.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/issues/project_cpu_hotspots.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/issues/terminals_exit_upon_starting.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/issues/wrong_item_classification_on_client_side.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/todo/smartphone_terminal_input_frustrations.md +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/tools/generate_play_store_assets.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/tools/pairing_tester.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/tools/run_screenshot_suite.sh +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/tools/test_python_ntp_clock.py +0 -0
- {portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/validate.sh +0 -0
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.4.13.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 4, 13, '
|
|
31
|
+
__version__ = version = '1.4.13.dev2'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 4, 13, 'dev2')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
{portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/WEBSOCKET_PROTOCOL.md
RENAMED
|
@@ -361,6 +361,9 @@ Creates a Portacode-managed LXC container, starts it, and bootstraps the Portaco
|
|
|
361
361
|
* `username` (string, optional): OS user to provision (defaults to `svcuser`).
|
|
362
362
|
* `password` (string, optional): Password for the user (used only during provisioning).
|
|
363
363
|
* `ssh_key` (string, optional): SSH public key to add to the user.
|
|
364
|
+
* `device_id` (string, optional): ID of the Device record that already exists on the dashboard.
|
|
365
|
+
* `device_public_key` (string, optional): PEM-encoded Portacode public key. When supplied together with `device_private_key` the handler injects the keypair, records the device metadata, and runs `portacode service install` automatically.
|
|
366
|
+
* `device_private_key` (string, optional): PEM-encoded private key that pairs with `device_public_key`. Both key fields must be present for the automatic service-install mode.
|
|
364
367
|
|
|
365
368
|
**Responses:**
|
|
366
369
|
|
|
@@ -418,6 +421,8 @@ Emitted after a successful `create_proxmox_container` action. Contains the new c
|
|
|
418
421
|
* `public_key` (string): Portacode public auth key created inside the new container.
|
|
419
422
|
* `container` (object): Metadata such as `vmid`, `hostname`, `template`, `storage`, `disk_gib`, `ram_mib`, and `cpus`.
|
|
420
423
|
* `setup_steps` (array[object]): Detailed bootstrap step results (name, stdout/stderr, elapsed time, and status).
|
|
424
|
+
* `device_id` (string, optional): Mirrors the `device_id` supplied with `create_proxmox_container`, if any.
|
|
425
|
+
* `service_installed` (boolean): True when the handler already ran `portacode service install` (with a provided keypair); otherwise it remains False and the dashboard can call `start_portacode_service`.
|
|
421
426
|
|
|
422
427
|
### `proxmox_container_progress`
|
|
423
428
|
|
|
@@ -450,6 +455,7 @@ Runs `sudo portacode service install` inside the container after the dashboard h
|
|
|
450
455
|
* Emits additional [`proxmox_container_progress`](#proxmox_container_progress-event) events to report the authentication and service-install steps.
|
|
451
456
|
* On success, emits a [`proxmox_service_started`](#proxmox_service_started-event).
|
|
452
457
|
* On failure, emits a generic [`error`](#error) event.
|
|
458
|
+
* When `create_proxmox_container` already provided a dashboard-generated keypair, the handler may have installed the service already, so this call is optional unless you need to re-run the install.
|
|
453
459
|
|
|
454
460
|
### `proxmox_service_started`
|
|
455
461
|
|
{portacode-1.4.13.dev0 → portacode-1.4.13.dev2}/portacode/connection/handlers/proxmox_infra.py
RENAMED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
+
import base64
|
|
6
7
|
import json
|
|
7
8
|
import logging
|
|
8
9
|
import os
|
|
@@ -11,7 +12,6 @@ import shutil
|
|
|
11
12
|
import stat
|
|
12
13
|
import subprocess
|
|
13
14
|
import sys
|
|
14
|
-
import time
|
|
15
15
|
import threading
|
|
16
16
|
from datetime import datetime
|
|
17
17
|
from pathlib import Path
|
|
@@ -59,7 +59,6 @@ def _emit_progress_event(
|
|
|
59
59
|
message: str,
|
|
60
60
|
phase: str,
|
|
61
61
|
request_id: Optional[str],
|
|
62
|
-
client_sessions: Optional[List[str]] = None,
|
|
63
62
|
details: Optional[Dict[str, Any]] = None,
|
|
64
63
|
) -> None:
|
|
65
64
|
loop = handler.context.get("event_loop")
|
|
@@ -85,8 +84,6 @@ def _emit_progress_event(
|
|
|
85
84
|
payload["request_id"] = request_id
|
|
86
85
|
if details:
|
|
87
86
|
payload["details"] = details
|
|
88
|
-
if client_sessions:
|
|
89
|
-
payload["client_sessions"] = client_sessions
|
|
90
87
|
|
|
91
88
|
future = asyncio.run_coroutine_threadsafe(handler.send_response(payload), loop)
|
|
92
89
|
future.add_done_callback(
|
|
@@ -431,7 +428,12 @@ def _friendly_step_label(step_name: str) -> str:
|
|
|
431
428
|
return normalized.capitalize()
|
|
432
429
|
|
|
433
430
|
|
|
434
|
-
def _build_bootstrap_steps(
|
|
431
|
+
def _build_bootstrap_steps(
|
|
432
|
+
user: str,
|
|
433
|
+
password: str,
|
|
434
|
+
ssh_key: str,
|
|
435
|
+
include_portacode_connect: bool = True,
|
|
436
|
+
) -> List[Dict[str, Any]]:
|
|
435
437
|
steps = [
|
|
436
438
|
{
|
|
437
439
|
"name": "apt_update",
|
|
@@ -468,11 +470,14 @@ def _build_bootstrap_steps(user: str, password: str, ssh_key: str) -> List[Dict[
|
|
|
468
470
|
"cmd": f"install -d -m 700 /home/{user}/.ssh && echo '{ssh_key}' >> /home/{user}/.ssh/authorized_keys && chown -R {user}:{user} /home/{user}/.ssh",
|
|
469
471
|
"retries": 0,
|
|
470
472
|
})
|
|
471
|
-
steps.extend(
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
473
|
+
steps.extend(
|
|
474
|
+
[
|
|
475
|
+
{"name": "pip_upgrade", "cmd": "python3 -m pip install --upgrade pip", "retries": 0},
|
|
476
|
+
{"name": "install_portacode", "cmd": "python3 -m pip install --upgrade portacode", "retries": 0},
|
|
477
|
+
]
|
|
478
|
+
)
|
|
479
|
+
if include_portacode_connect:
|
|
480
|
+
steps.append({"name": "portacode_connect", "type": "portacode_connect", "timeout_s": 30})
|
|
476
481
|
return steps
|
|
477
482
|
|
|
478
483
|
|
|
@@ -682,6 +687,36 @@ def _run_pct_check(vmid: int, cmd: str) -> Dict[str, Any]:
|
|
|
682
687
|
return res
|
|
683
688
|
|
|
684
689
|
|
|
690
|
+
def _resolve_portacode_key_dir(vmid: int, user: str) -> str:
|
|
691
|
+
data_dir_cmd = f"su - {user} -c 'echo -n ${{XDG_DATA_HOME:-$HOME/.local/share}}'"
|
|
692
|
+
data_home = _run_pct_check(vmid, data_dir_cmd)["stdout"].strip()
|
|
693
|
+
return f"{data_home}/portacode/keys"
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
def _write_bytes_as_user(vmid: int, user: str, path: str, data: bytes, mode: int = 0o600) -> None:
|
|
697
|
+
encoded = base64.b64encode(data).decode()
|
|
698
|
+
path_literal = json.dumps(path)
|
|
699
|
+
script = (
|
|
700
|
+
f"su - {user} -c 'python3 - <<\"PY\"\n"
|
|
701
|
+
"import base64\n"
|
|
702
|
+
"from pathlib import Path\n"
|
|
703
|
+
f"path = Path({path_literal})\n"
|
|
704
|
+
"path.parent.mkdir(parents=True, exist_ok=True)\n"
|
|
705
|
+
f"path.write_bytes(base64.b64decode(\"{encoded}\"))\n"
|
|
706
|
+
f"path.chmod({mode})\n"
|
|
707
|
+
"PY'"
|
|
708
|
+
)
|
|
709
|
+
_run_pct_check(vmid, script)
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
def _deploy_device_keypair(vmid: int, user: str, private_key: str, public_key: str) -> None:
|
|
713
|
+
key_dir = _resolve_portacode_key_dir(vmid, user)
|
|
714
|
+
priv_path = f"{key_dir}/id_portacode"
|
|
715
|
+
pub_path = f"{key_dir}/id_portacode.pub"
|
|
716
|
+
_write_bytes_as_user(vmid, user, priv_path, private_key.encode(), mode=0o600)
|
|
717
|
+
_write_bytes_as_user(vmid, user, pub_path, public_key.encode(), mode=0o644)
|
|
718
|
+
|
|
719
|
+
|
|
685
720
|
def _portacode_connect_and_read_key(vmid: int, user: str, timeout_s: int = 10) -> Dict[str, Any]:
|
|
686
721
|
cmd = ["pct", "exec", str(vmid), "--", "bash", "-lc", f"su - {user} -c 'portacode connect'"]
|
|
687
722
|
proc = subprocess.Popen(cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
@@ -883,6 +918,7 @@ def _bootstrap_portacode(
|
|
|
883
918
|
progress_callback: Optional[ProgressCallback] = None,
|
|
884
919
|
start_index: int = 1,
|
|
885
920
|
total_steps: Optional[int] = None,
|
|
921
|
+
default_public_key: Optional[str] = None,
|
|
886
922
|
) -> Tuple[str, List[Dict[str, Any]]]:
|
|
887
923
|
actual_steps = steps if steps is not None else _build_bootstrap_steps(user, password, ssh_key)
|
|
888
924
|
results, ok = _run_setup_steps(
|
|
@@ -909,7 +945,7 @@ def _bootstrap_portacode(
|
|
|
909
945
|
raise RuntimeError(f"Portacode bootstrap steps failed: {summary}{history_snippet}")
|
|
910
946
|
raise RuntimeError("Portacode bootstrap steps failed.")
|
|
911
947
|
key_step = next((entry for entry in results if entry.get("name") == "portacode_connect"), None)
|
|
912
|
-
public_key = key_step.get("public_key") if key_step else
|
|
948
|
+
public_key = key_step.get("public_key") if key_step else default_public_key
|
|
913
949
|
if not public_key:
|
|
914
950
|
raise RuntimeError("Portacode connect did not return a public key.")
|
|
915
951
|
return public_key, results
|
|
@@ -1053,16 +1089,19 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1053
1089
|
return "create_proxmox_container"
|
|
1054
1090
|
|
|
1055
1091
|
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
1092
|
+
logger.info("create_proxmox_container command received")
|
|
1056
1093
|
request_id = message.get("request_id")
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
source_client_session,
|
|
1062
|
-
)
|
|
1063
|
-
client_sessions = [source_client_session] if source_client_session else None
|
|
1094
|
+
device_id = message.get("device_id")
|
|
1095
|
+
device_public_key = (message.get("device_public_key") or "").strip()
|
|
1096
|
+
device_private_key = (message.get("device_private_key") or "").strip()
|
|
1097
|
+
has_device_keypair = bool(device_public_key and device_private_key)
|
|
1064
1098
|
bootstrap_user, bootstrap_password, bootstrap_ssh_key = _get_provisioning_user_info(message)
|
|
1065
|
-
bootstrap_steps = _build_bootstrap_steps(
|
|
1099
|
+
bootstrap_steps = _build_bootstrap_steps(
|
|
1100
|
+
bootstrap_user,
|
|
1101
|
+
bootstrap_password,
|
|
1102
|
+
bootstrap_ssh_key,
|
|
1103
|
+
include_portacode_connect=not has_device_keypair,
|
|
1104
|
+
)
|
|
1066
1105
|
total_steps = 3 + len(bootstrap_steps) + 2
|
|
1067
1106
|
current_step_index = 1
|
|
1068
1107
|
|
|
@@ -1084,7 +1123,6 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1084
1123
|
message=start_message,
|
|
1085
1124
|
phase="lifecycle",
|
|
1086
1125
|
request_id=request_id,
|
|
1087
|
-
client_sessions=client_sessions,
|
|
1088
1126
|
)
|
|
1089
1127
|
try:
|
|
1090
1128
|
result = action()
|
|
@@ -1099,7 +1137,6 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1099
1137
|
message=f"{step_label} failed: {exc}",
|
|
1100
1138
|
phase="lifecycle",
|
|
1101
1139
|
request_id=request_id,
|
|
1102
|
-
client_sessions=client_sessions,
|
|
1103
1140
|
details={"error": str(exc)},
|
|
1104
1141
|
)
|
|
1105
1142
|
raise
|
|
@@ -1113,7 +1150,6 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1113
1150
|
message=success_message,
|
|
1114
1151
|
phase="lifecycle",
|
|
1115
1152
|
request_id=request_id,
|
|
1116
|
-
client_sessions=client_sessions,
|
|
1117
1153
|
)
|
|
1118
1154
|
current_step_index += 1
|
|
1119
1155
|
return result
|
|
@@ -1143,7 +1179,7 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1143
1179
|
payload["cpuunits"] = max(int(payload["cpus"] * 1024), 10)
|
|
1144
1180
|
payload["memory"] = int(payload["ram_mib"])
|
|
1145
1181
|
payload["node"] = node
|
|
1146
|
-
logger.
|
|
1182
|
+
logger.debug(
|
|
1147
1183
|
"Provisioning container node=%s template=%s ram=%s cpu=%s storage=%s",
|
|
1148
1184
|
node,
|
|
1149
1185
|
payload["template"],
|
|
@@ -1156,12 +1192,6 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1156
1192
|
payload["created_at"] = datetime.utcnow().isoformat() + "Z"
|
|
1157
1193
|
payload["status"] = "creating"
|
|
1158
1194
|
_write_container_record(vmid, payload)
|
|
1159
|
-
logger.info(
|
|
1160
|
-
"Container record written vmid=%s hostname=%s client_session=%s",
|
|
1161
|
-
vmid,
|
|
1162
|
-
payload["hostname"],
|
|
1163
|
-
source_client_session,
|
|
1164
|
-
)
|
|
1165
1195
|
return proxmox, node, vmid, payload
|
|
1166
1196
|
|
|
1167
1197
|
proxmox, node, vmid, payload = _run_lifecycle_step(
|
|
@@ -1220,16 +1250,9 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1220
1250
|
message=message_text,
|
|
1221
1251
|
phase="bootstrap",
|
|
1222
1252
|
request_id=request_id,
|
|
1223
|
-
client_sessions=client_sessions,
|
|
1224
1253
|
details=details or None,
|
|
1225
1254
|
)
|
|
1226
1255
|
|
|
1227
|
-
logger.info(
|
|
1228
|
-
"Bootstrapping Portacode in container vmid=%s user=%s client_session=%s",
|
|
1229
|
-
vmid,
|
|
1230
|
-
payload["username"],
|
|
1231
|
-
source_client_session,
|
|
1232
|
-
)
|
|
1233
1256
|
public_key, steps = _bootstrap_portacode(
|
|
1234
1257
|
vmid,
|
|
1235
1258
|
payload["username"],
|
|
@@ -1239,10 +1262,103 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1239
1262
|
progress_callback=_bootstrap_progress_callback,
|
|
1240
1263
|
start_index=current_step_index,
|
|
1241
1264
|
total_steps=total_steps,
|
|
1265
|
+
default_public_key=device_public_key if has_device_keypair else None,
|
|
1242
1266
|
)
|
|
1243
1267
|
current_step_index += len(bootstrap_steps)
|
|
1244
1268
|
|
|
1245
|
-
|
|
1269
|
+
service_installed = False
|
|
1270
|
+
if has_device_keypair:
|
|
1271
|
+
logger.info(
|
|
1272
|
+
"deploying dashboard-provided Portacode keypair (device_id=%s) into container %s",
|
|
1273
|
+
device_id,
|
|
1274
|
+
vmid,
|
|
1275
|
+
)
|
|
1276
|
+
_deploy_device_keypair(
|
|
1277
|
+
vmid,
|
|
1278
|
+
payload["username"],
|
|
1279
|
+
device_private_key,
|
|
1280
|
+
device_public_key,
|
|
1281
|
+
)
|
|
1282
|
+
service_installed = True
|
|
1283
|
+
service_start_index = current_step_index
|
|
1284
|
+
|
|
1285
|
+
auth_step_name = "setup_device_authentication"
|
|
1286
|
+
auth_label = "Setting up device authentication"
|
|
1287
|
+
_emit_progress_event(
|
|
1288
|
+
self,
|
|
1289
|
+
step_index=service_start_index,
|
|
1290
|
+
total_steps=total_steps,
|
|
1291
|
+
step_name=auth_step_name,
|
|
1292
|
+
step_label=auth_label,
|
|
1293
|
+
status="in_progress",
|
|
1294
|
+
message="Notifying the server of the new device…",
|
|
1295
|
+
phase="service",
|
|
1296
|
+
request_id=request_id,
|
|
1297
|
+
)
|
|
1298
|
+
_emit_progress_event(
|
|
1299
|
+
self,
|
|
1300
|
+
step_index=service_start_index,
|
|
1301
|
+
total_steps=total_steps,
|
|
1302
|
+
step_name=auth_step_name,
|
|
1303
|
+
step_label=auth_label,
|
|
1304
|
+
status="completed",
|
|
1305
|
+
message="Authentication metadata recorded.",
|
|
1306
|
+
phase="service",
|
|
1307
|
+
request_id=request_id,
|
|
1308
|
+
)
|
|
1309
|
+
|
|
1310
|
+
install_step = service_start_index + 1
|
|
1311
|
+
install_label = "Launching Portacode service"
|
|
1312
|
+
_emit_progress_event(
|
|
1313
|
+
self,
|
|
1314
|
+
step_index=install_step,
|
|
1315
|
+
total_steps=total_steps,
|
|
1316
|
+
step_name="launch_portacode_service",
|
|
1317
|
+
step_label=install_label,
|
|
1318
|
+
status="in_progress",
|
|
1319
|
+
message="Running sudo portacode service install…",
|
|
1320
|
+
phase="service",
|
|
1321
|
+
request_id=request_id,
|
|
1322
|
+
)
|
|
1323
|
+
|
|
1324
|
+
cmd = f"su - {payload['username']} -c 'sudo -S portacode service install'"
|
|
1325
|
+
res = _run_pct(vmid, cmd, input_text=payload["password"] + "\n")
|
|
1326
|
+
|
|
1327
|
+
if res["returncode"] != 0:
|
|
1328
|
+
_emit_progress_event(
|
|
1329
|
+
self,
|
|
1330
|
+
step_index=install_step,
|
|
1331
|
+
total_steps=total_steps,
|
|
1332
|
+
step_name="launch_portacode_service",
|
|
1333
|
+
step_label=install_label,
|
|
1334
|
+
status="failed",
|
|
1335
|
+
message=f"{install_label} failed: {res.get('stderr') or res.get('stdout')}",
|
|
1336
|
+
phase="service",
|
|
1337
|
+
request_id=request_id,
|
|
1338
|
+
details={
|
|
1339
|
+
"stderr": res.get("stderr"),
|
|
1340
|
+
"stdout": res.get("stdout"),
|
|
1341
|
+
},
|
|
1342
|
+
)
|
|
1343
|
+
raise RuntimeError(res.get("stderr") or res.get("stdout") or "Service install failed")
|
|
1344
|
+
|
|
1345
|
+
_emit_progress_event(
|
|
1346
|
+
self,
|
|
1347
|
+
step_index=install_step,
|
|
1348
|
+
total_steps=total_steps,
|
|
1349
|
+
step_name="launch_portacode_service",
|
|
1350
|
+
step_label=install_label,
|
|
1351
|
+
status="completed",
|
|
1352
|
+
message="Portacode service install finished.",
|
|
1353
|
+
phase="service",
|
|
1354
|
+
request_id=request_id,
|
|
1355
|
+
)
|
|
1356
|
+
|
|
1357
|
+
logger.info("create_proxmox_container: portacode service install completed inside ct %s", vmid)
|
|
1358
|
+
|
|
1359
|
+
current_step_index += 2
|
|
1360
|
+
|
|
1361
|
+
return {
|
|
1246
1362
|
"event": "proxmox_container_created",
|
|
1247
1363
|
"success": True,
|
|
1248
1364
|
"message": f"Container {vmid} is ready and Portacode key captured.",
|
|
@@ -1258,10 +1374,9 @@ class CreateProxmoxContainerHandler(SyncHandler):
|
|
|
1258
1374
|
"cpus": payload["cpus"],
|
|
1259
1375
|
},
|
|
1260
1376
|
"setup_steps": steps,
|
|
1377
|
+
"device_id": device_id,
|
|
1378
|
+
"service_installed": service_installed,
|
|
1261
1379
|
}
|
|
1262
|
-
if client_sessions:
|
|
1263
|
-
response["client_sessions"] = client_sessions
|
|
1264
|
-
return response
|
|
1265
1380
|
|
|
1266
1381
|
|
|
1267
1382
|
class StartPortacodeServiceHandler(SyncHandler):
|
|
@@ -1289,15 +1404,6 @@ class StartPortacodeServiceHandler(SyncHandler):
|
|
|
1289
1404
|
start_index = int(message.get("step_index", 1))
|
|
1290
1405
|
total_steps = int(message.get("total_steps", start_index + 2))
|
|
1291
1406
|
request_id = message.get("request_id")
|
|
1292
|
-
source_client_session = message.get("source_client_session")
|
|
1293
|
-
client_sessions = [source_client_session] if source_client_session else None
|
|
1294
|
-
|
|
1295
|
-
logger.info(
|
|
1296
|
-
"start_portacode_service invoked vmid=%s user=%s client_session=%s",
|
|
1297
|
-
vmid,
|
|
1298
|
-
user,
|
|
1299
|
-
source_client_session,
|
|
1300
|
-
)
|
|
1301
1407
|
|
|
1302
1408
|
auth_step_name = "setup_device_authentication"
|
|
1303
1409
|
auth_label = "Setting up device authentication"
|
|
@@ -1311,7 +1417,6 @@ class StartPortacodeServiceHandler(SyncHandler):
|
|
|
1311
1417
|
message="Notifying the server of the new device…",
|
|
1312
1418
|
phase="service",
|
|
1313
1419
|
request_id=request_id,
|
|
1314
|
-
client_sessions=client_sessions,
|
|
1315
1420
|
)
|
|
1316
1421
|
_emit_progress_event(
|
|
1317
1422
|
self,
|
|
@@ -1323,7 +1428,6 @@ class StartPortacodeServiceHandler(SyncHandler):
|
|
|
1323
1428
|
message="Authentication metadata recorded.",
|
|
1324
1429
|
phase="service",
|
|
1325
1430
|
request_id=request_id,
|
|
1326
|
-
client_sessions=client_sessions,
|
|
1327
1431
|
)
|
|
1328
1432
|
|
|
1329
1433
|
install_step = start_index + 1
|
|
@@ -1338,7 +1442,6 @@ class StartPortacodeServiceHandler(SyncHandler):
|
|
|
1338
1442
|
message="Running sudo portacode service install…",
|
|
1339
1443
|
phase="service",
|
|
1340
1444
|
request_id=request_id,
|
|
1341
|
-
client_sessions=client_sessions,
|
|
1342
1445
|
)
|
|
1343
1446
|
|
|
1344
1447
|
cmd = f"su - {user} -c 'sudo -S portacode service install'"
|
|
@@ -1355,7 +1458,6 @@ class StartPortacodeServiceHandler(SyncHandler):
|
|
|
1355
1458
|
message=f"{install_label} failed: {res.get('stderr') or res.get('stdout')}",
|
|
1356
1459
|
phase="service",
|
|
1357
1460
|
request_id=request_id,
|
|
1358
|
-
client_sessions=client_sessions,
|
|
1359
1461
|
details={
|
|
1360
1462
|
"stderr": res.get("stderr"),
|
|
1361
1463
|
"stdout": res.get("stdout"),
|
|
@@ -1363,12 +1465,6 @@ class StartPortacodeServiceHandler(SyncHandler):
|
|
|
1363
1465
|
)
|
|
1364
1466
|
raise RuntimeError(res.get("stderr") or res.get("stdout") or "Service install failed")
|
|
1365
1467
|
|
|
1366
|
-
logger.info(
|
|
1367
|
-
"portacode service install command completed vmid=%s returncode=%s",
|
|
1368
|
-
vmid,
|
|
1369
|
-
res["returncode"],
|
|
1370
|
-
)
|
|
1371
|
-
|
|
1372
1468
|
_emit_progress_event(
|
|
1373
1469
|
self,
|
|
1374
1470
|
step_index=install_step,
|
|
@@ -1379,18 +1475,14 @@ class StartPortacodeServiceHandler(SyncHandler):
|
|
|
1379
1475
|
message="Portacode service install finished.",
|
|
1380
1476
|
phase="service",
|
|
1381
1477
|
request_id=request_id,
|
|
1382
|
-
client_sessions=client_sessions,
|
|
1383
1478
|
)
|
|
1384
1479
|
|
|
1385
|
-
|
|
1480
|
+
return {
|
|
1386
1481
|
"event": "proxmox_service_started",
|
|
1387
1482
|
"success": True,
|
|
1388
1483
|
"message": "Portacode service install completed",
|
|
1389
1484
|
"ctid": str(vmid),
|
|
1390
1485
|
}
|
|
1391
|
-
if client_sessions:
|
|
1392
|
-
response["client_sessions"] = client_sessions
|
|
1393
|
-
return response
|
|
1394
1486
|
|
|
1395
1487
|
|
|
1396
1488
|
class StartProxmoxContainerHandler(SyncHandler):
|
|
@@ -1406,20 +1498,12 @@ class StartProxmoxContainerHandler(SyncHandler):
|
|
|
1406
1498
|
proxmox = _connect_proxmox(config)
|
|
1407
1499
|
node = _get_node_from_config(config)
|
|
1408
1500
|
_ensure_container_managed(proxmox, node, vmid)
|
|
1409
|
-
source_client_session = message.get("source_client_session")
|
|
1410
|
-
client_sessions = [source_client_session] if source_client_session else None
|
|
1411
|
-
|
|
1412
|
-
logger.info(
|
|
1413
|
-
"start_proxmox_container invoked vmid=%s client_session=%s",
|
|
1414
|
-
vmid,
|
|
1415
|
-
source_client_session,
|
|
1416
|
-
)
|
|
1417
1501
|
|
|
1418
1502
|
status, elapsed = _start_container(proxmox, node, vmid)
|
|
1419
1503
|
_update_container_record(vmid, {"status": "running"})
|
|
1420
1504
|
|
|
1421
1505
|
infra = get_infra_snapshot()
|
|
1422
|
-
|
|
1506
|
+
return {
|
|
1423
1507
|
"event": "proxmox_container_action",
|
|
1424
1508
|
"action": "start",
|
|
1425
1509
|
"success": True,
|
|
@@ -1429,9 +1513,6 @@ class StartProxmoxContainerHandler(SyncHandler):
|
|
|
1429
1513
|
"status": status.get("status"),
|
|
1430
1514
|
"infra": infra,
|
|
1431
1515
|
}
|
|
1432
|
-
if client_sessions:
|
|
1433
|
-
response["client_sessions"] = client_sessions
|
|
1434
|
-
return response
|
|
1435
1516
|
|
|
1436
1517
|
|
|
1437
1518
|
class StopProxmoxContainerHandler(SyncHandler):
|
|
@@ -1447,14 +1528,6 @@ class StopProxmoxContainerHandler(SyncHandler):
|
|
|
1447
1528
|
proxmox = _connect_proxmox(config)
|
|
1448
1529
|
node = _get_node_from_config(config)
|
|
1449
1530
|
_ensure_container_managed(proxmox, node, vmid)
|
|
1450
|
-
source_client_session = message.get("source_client_session")
|
|
1451
|
-
client_sessions = [source_client_session] if source_client_session else None
|
|
1452
|
-
|
|
1453
|
-
logger.info(
|
|
1454
|
-
"stop_proxmox_container invoked vmid=%s client_session=%s",
|
|
1455
|
-
vmid,
|
|
1456
|
-
source_client_session,
|
|
1457
|
-
)
|
|
1458
1531
|
|
|
1459
1532
|
status, elapsed = _stop_container(proxmox, node, vmid)
|
|
1460
1533
|
final_status = status.get("status") or "stopped"
|
|
@@ -1466,7 +1539,7 @@ class StopProxmoxContainerHandler(SyncHandler):
|
|
|
1466
1539
|
if final_status != "running" and elapsed == 0.0
|
|
1467
1540
|
else f"Stopped container {vmid} in {elapsed:.1f}s."
|
|
1468
1541
|
)
|
|
1469
|
-
|
|
1542
|
+
return {
|
|
1470
1543
|
"event": "proxmox_container_action",
|
|
1471
1544
|
"action": "stop",
|
|
1472
1545
|
"success": True,
|
|
@@ -1476,9 +1549,6 @@ class StopProxmoxContainerHandler(SyncHandler):
|
|
|
1476
1549
|
"status": final_status,
|
|
1477
1550
|
"infra": infra,
|
|
1478
1551
|
}
|
|
1479
|
-
if client_sessions:
|
|
1480
|
-
response["client_sessions"] = client_sessions
|
|
1481
|
-
return response
|
|
1482
1552
|
|
|
1483
1553
|
|
|
1484
1554
|
class RemoveProxmoxContainerHandler(SyncHandler):
|
|
@@ -1494,21 +1564,13 @@ class RemoveProxmoxContainerHandler(SyncHandler):
|
|
|
1494
1564
|
proxmox = _connect_proxmox(config)
|
|
1495
1565
|
node = _get_node_from_config(config)
|
|
1496
1566
|
_ensure_container_managed(proxmox, node, vmid)
|
|
1497
|
-
source_client_session = message.get("source_client_session")
|
|
1498
|
-
client_sessions = [source_client_session] if source_client_session else None
|
|
1499
|
-
|
|
1500
|
-
logger.info(
|
|
1501
|
-
"remove_proxmox_container invoked vmid=%s client_session=%s",
|
|
1502
|
-
vmid,
|
|
1503
|
-
source_client_session,
|
|
1504
|
-
)
|
|
1505
1567
|
|
|
1506
1568
|
stop_status, stop_elapsed = _stop_container(proxmox, node, vmid)
|
|
1507
1569
|
delete_status, delete_elapsed = _delete_container(proxmox, node, vmid)
|
|
1508
1570
|
_remove_container_record(vmid)
|
|
1509
1571
|
|
|
1510
1572
|
infra = get_infra_snapshot()
|
|
1511
|
-
|
|
1573
|
+
return {
|
|
1512
1574
|
"event": "proxmox_container_action",
|
|
1513
1575
|
"action": "remove",
|
|
1514
1576
|
"success": True,
|
|
@@ -1521,9 +1583,6 @@ class RemoveProxmoxContainerHandler(SyncHandler):
|
|
|
1521
1583
|
"status": "deleted",
|
|
1522
1584
|
"infra": infra,
|
|
1523
1585
|
}
|
|
1524
|
-
if client_sessions:
|
|
1525
|
-
response["client_sessions"] = client_sessions
|
|
1526
|
-
return response
|
|
1527
1586
|
|
|
1528
1587
|
|
|
1529
1588
|
class ConfigureProxmoxInfraHandler(SyncHandler):
|
|
@@ -1537,18 +1596,13 @@ class ConfigureProxmoxInfraHandler(SyncHandler):
|
|
|
1537
1596
|
verify_ssl = bool(message.get("verify_ssl"))
|
|
1538
1597
|
if not token_identifier or not token_value:
|
|
1539
1598
|
raise ValueError("token_identifier and token_value are required")
|
|
1540
|
-
source_client_session = message.get("source_client_session")
|
|
1541
|
-
client_sessions = [source_client_session] if source_client_session else None
|
|
1542
1599
|
snapshot = configure_infrastructure(token_identifier, token_value, verify_ssl=verify_ssl)
|
|
1543
|
-
|
|
1600
|
+
return {
|
|
1544
1601
|
"event": "proxmox_infra_configured",
|
|
1545
1602
|
"success": True,
|
|
1546
1603
|
"message": "Proxmox infrastructure configured",
|
|
1547
1604
|
"infra": snapshot,
|
|
1548
1605
|
}
|
|
1549
|
-
if client_sessions:
|
|
1550
|
-
response["client_sessions"] = client_sessions
|
|
1551
|
-
return response
|
|
1552
1606
|
|
|
1553
1607
|
|
|
1554
1608
|
class RevertProxmoxInfraHandler(SyncHandler):
|
|
@@ -1557,15 +1611,10 @@ class RevertProxmoxInfraHandler(SyncHandler):
|
|
|
1557
1611
|
return "revert_proxmox_infra"
|
|
1558
1612
|
|
|
1559
1613
|
def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
|
|
1560
|
-
source_client_session = message.get("source_client_session")
|
|
1561
|
-
client_sessions = [source_client_session] if source_client_session else None
|
|
1562
1614
|
snapshot = revert_infrastructure()
|
|
1563
|
-
|
|
1615
|
+
return {
|
|
1564
1616
|
"event": "proxmox_infra_reverted",
|
|
1565
1617
|
"success": True,
|
|
1566
1618
|
"message": "Proxmox infrastructure configuration reverted",
|
|
1567
1619
|
"infra": snapshot,
|
|
1568
1620
|
}
|
|
1569
|
-
if client_sessions:
|
|
1570
|
-
response["client_sessions"] = client_sessions
|
|
1571
|
-
return response
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from unittest import TestCase
|
|
2
|
+
|
|
3
|
+
from portacode.connection.handlers.proxmox_infra import _build_bootstrap_steps
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ProxmoxInfraHandlerTests(TestCase):
|
|
7
|
+
def test_build_bootstrap_steps_includes_portacode_connect_by_default(self):
|
|
8
|
+
steps = _build_bootstrap_steps("svcuser", "pass", "", include_portacode_connect=True)
|
|
9
|
+
self.assertTrue(any(step.get("name") == "portacode_connect" for step in steps))
|
|
10
|
+
|
|
11
|
+
def test_build_bootstrap_steps_skips_portacode_connect_when_requested(self):
|
|
12
|
+
steps = _build_bootstrap_steps("svcuser", "pass", "", include_portacode_connect=False)
|
|
13
|
+
self.assertFalse(any(step.get("name") == "portacode_connect" for step in steps))
|
|
@@ -301,6 +301,7 @@ portacode/connection/handlers/session.py
|
|
|
301
301
|
portacode/connection/handlers/system_handlers.py
|
|
302
302
|
portacode/connection/handlers/tab_factory.py
|
|
303
303
|
portacode/connection/handlers/terminal_handlers.py
|
|
304
|
+
portacode/connection/handlers/test_proxmox_infra.py
|
|
304
305
|
portacode/connection/handlers/update_handler.py
|
|
305
306
|
portacode/connection/handlers/project_state/README.md
|
|
306
307
|
portacode/connection/handlers/project_state/__init__.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|