From 23769e6ad4841a14ab664f511a2ba25ae04fc9d2 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Fri, 29 May 2026 15:39:30 +0200 Subject: [PATCH] fix: remove redundant ssh_keys mount from pi-agent manifest via data migration The ssh_keys mount was already removed from the Alembic seed migration, but that migration had already been applied to the DB. This data migration removes the mount from the actual tool_definition_manifests row so that instance-level SSH key mounting handles keys exclusively. Quality gates: pytest (18 passed) --- ..._29_remove_ssh_keys_mount_from_manifest.py | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 apps/api/alembic/versions/2026_05_29_remove_ssh_keys_mount_from_manifest.py diff --git a/apps/api/alembic/versions/2026_05_29_remove_ssh_keys_mount_from_manifest.py b/apps/api/alembic/versions/2026_05_29_remove_ssh_keys_mount_from_manifest.py new file mode 100644 index 0000000..a5903bd --- /dev/null +++ b/apps/api/alembic/versions/2026_05_29_remove_ssh_keys_mount_from_manifest.py @@ -0,0 +1,95 @@ +"""remove ssh_keys mount from pi-agent manifest + +Revision ID: 2026_05_29_remove_ssh_keys_mount_from_manifest +Revises: 2026_05_29_add_ssh_key_ids_to_tool_instances +Create Date: 2026-05-29 14:00:00.000000 + +""" + +import json +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision: str = "2026_05_29_remove_ssh_keys_mount_from_manifest" +down_revision: Union[str, None] = "2026_05_29_add_ssh_key_ids_to_tool_instances" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Remove the ssh_keys mount from the pi-agent manifest.""" + conn = op.get_bind() + + # Get the pi-agent manifest + result = conn.execute( + sa.text("SELECT id, manifest FROM tool_definition_manifests WHERE name = 'pi-agent'") + ) + row = result.fetchone() + if not row: + return + + manifest_id, manifest_json = row + manifest = manifest_json if isinstance(manifest_json, dict) else json.loads(manifest_json) + + mounts = manifest.get("mounts", []) + original_count = len(mounts) + + # Remove any mount named "ssh_keys" + filtered_mounts = [m for m in mounts if m.get("name") != "ssh_keys"] + + if len(filtered_mounts) < original_count: + manifest["mounts"] = filtered_mounts + conn.execute( + sa.text( + "UPDATE tool_definition_manifests SET manifest = :manifest WHERE id = :id" + ), + { + "manifest": json.dumps(manifest), + "id": manifest_id, + }, + ) + + +def downgrade() -> None: + """Restore the ssh_keys mount to the pi-agent manifest.""" + conn = op.get_bind() + + result = conn.execute( + sa.text("SELECT id, manifest FROM tool_definition_manifests WHERE name = 'pi-agent'") + ) + row = result.fetchone() + if not row: + return + + manifest_id, manifest_json = row + manifest = manifest_json if isinstance(manifest_json, dict) else json.loads(manifest_json) + + mounts = manifest.get("mounts", []) + + # Check if ssh_keys mount already exists + if any(m.get("name") == "ssh_keys" for m in mounts): + return + + # Add the ssh_keys mount back + mounts.append({ + "name": "ssh_keys", + "target": "/home/user/.ssh", + "source_type": "ssh_key", + "mode": "0700", + "file_mode": "0600", + "readonly": True, + }) + manifest["mounts"] = mounts + + conn.execute( + sa.text( + "UPDATE tool_definition_manifests SET manifest = :manifest WHERE id = :id" + ), + { + "manifest": json.dumps(manifest), + "id": manifest_id, + }, + )