diff --git a/.pi-map.index.md b/.pi-map.index.md index 6325906..874982b 100644 --- a/.pi-map.index.md +++ b/.pi-map.index.md @@ -16,7 +16,7 @@ dir: . Trust boundary: index routes, map orients, source decides. ## role -A self-hosted web-based project management and git repository platform with OAuth2 authentication, containerized via Docker Compose. +Infrastructure and deployment configuration for a self-hosted project management platform with OAuth2 authentication, providing Docker Compose orchestration, environment templates, and development tooling. ## parent - ## children diff --git a/.pi-map.md b/.pi-map.md index 03088ba..5997626 100644 --- a/.pi-map.md +++ b/.pi-map.md @@ -18,7 +18,7 @@ index: ./.pi-map.index.md Trust boundary: index routes, map orients, source decides. ## role -A self-hosted web-based project management and git repository platform with OAuth2 authentication, containerized via Docker Compose. +Infrastructure and deployment configuration for a self-hosted project management platform with OAuth2 authentication, providing Docker Compose orchestration, environment templates, and development tooling. ## files - .env.example | Provides a template of environment variables for configuring a Headquarter application with PostgreSQL, Redis, Authentik SSO, and Docker/Traefik deployment - .gitignore | Specifies files and directories for Git to ignore across a multi-language project with Python, Node, and custom tooling | dep: Git @@ -31,7 +31,7 @@ A self-hosted web-based project management and git repository platform with OAut - progress.md | Tracks completed and remaining tasks for a backend-frontend code refactoring project organized in 7 phases - swap-pane | Empty file with no functionality ## arch -Multi-service containerized architecture with separate frontend (likely Node.js), API backend (likely Python), PostgreSQL database, Redis cache, and Traefik reverse proxy for TLS termination, configured through environment variables and supporting Authentik SSO integration. +Containerized microservices architecture using Docker Compose with PostgreSQL and Redis data layers, Traefik reverse proxy for TLS/ingress, multi-stage builds for Node.js frontend and Python backend, and environment-driven configuration management. ## tags docker, redis, git, application, postgresql, compose, traefik, project ## symbols diff --git a/apps/.pi-map.index.md b/apps/.pi-map.index.md index 9e45461..a46b146 100644 --- a/apps/.pi-map.index.md +++ b/apps/.pi-map.index.md @@ -2,7 +2,7 @@ dir: apps ## role -Contains the main deployable application modules and entry points for the project. +Container for deployable application entry points and top-level configurations in the project. ## parent index: ./.pi-map.index.md map: ./.pi-map.md diff --git a/apps/.pi-map.md b/apps/.pi-map.md index 5425fa8..bb64e5b 100644 --- a/apps/.pi-map.md +++ b/apps/.pi-map.md @@ -4,10 +4,10 @@ dir: apps index: apps/.pi-map.index.md ## role -Contains the main deployable application modules and entry points for the project. +Container for deployable application entry points and top-level configurations in the project. ## files ## arch -Follows a modular app structure where each subdirectory is an independent application with its own configuration, dependencies, and build setup, typically using a monorepo pattern with shared libraries. +Monorepo-style directory structure housing independently runnable applications that share common libraries or modules, typically with per-app configuration, dependencies, and build targets. ## tags - ## symbols diff --git a/apps/api/.pi-map.index.md b/apps/api/.pi-map.index.md index 0640d99..26fb718 100644 --- a/apps/api/.pi-map.index.md +++ b/apps/api/.pi-map.index.md @@ -2,7 +2,7 @@ dir: apps/api ## role -FastAPI backend API that manages projects, git repositories, and development tools through Docker-based instances with PostgreSQL persistence. +Self-hosted FastAPI backend API that manages projects, git repositories, and development tools by orchestrating Docker instances for remote development environments. ## parent index: apps/.pi-map.index.md map: apps/.pi-map.md diff --git a/apps/api/.pi-map.md b/apps/api/.pi-map.md index 154883f..012a7f2 100644 --- a/apps/api/.pi-map.md +++ b/apps/api/.pi-map.md @@ -4,7 +4,7 @@ dir: apps/api index: apps/api/.pi-map.index.md ## role -FastAPI backend API that manages projects, git repositories, and development tools through Docker-based instances with PostgreSQL persistence. +Self-hosted FastAPI backend API that manages projects, git repositories, and development tools by orchestrating Docker instances for remote development environments. ## files - .dockerignore | Specifies files and directories to exclude from Docker build context to reduce image size and avoid copying unnecessary files into containers. | dep: Docker - Dockerfile | Multi-stage Docker build for a Python application with Docker socket access, Cloudflare tunneling, and database dependency waiting | dep: python:3.11-slim, gcc, libpq-dev, docker-ce-cli, docker-compose-plugin, cloudflared, uvicorn, pyproject.toml dependencies @@ -14,7 +14,7 @@ FastAPI backend API that manages projects, git repositories, and development too - uv.lock | Lock file for the uv Python package manager that pins exact dependency versions and their artifact hashes for reproducible installations | dep: uv, Python 3.11+, aiosqlite, alembic, annotated-doc, annotated-types, anyio, ast-serialize, asyncpg, and many other PyPI packages - wait-for-db.sh | Wait for a PostgreSQL database to become available before executing a command, with configurable retry logic. | dep: nc (netcat), sh (POSIX shell), sleep ## arch -Async Python/FastAPI service using multi-stage Docker containers, Alembic migrations, uv package management, and external Docker socket access for container orchestration. +Async Python backend using FastAPI with PostgreSQL (asyncpg), Alembic migrations, uv package management, multi-stage Docker builds with Docker-in-Docker socket access, and Cloudflare tunneling for secure external connectivity. ## tags docker, alembic, python, database, fastapi, postgresql, asyncpg, uvicorn ## symbols diff --git a/apps/api/src/services/build/manifest_compiler.py b/apps/api/src/services/build/manifest_compiler.py index 3bcd47c..c1b3546 100644 --- a/apps/api/src/services/build/manifest_compiler.py +++ b/apps/api/src/services/build/manifest_compiler.py @@ -393,6 +393,13 @@ def compile_entrypoint(manifest: dict) -> str: if user: name = user["name"] lines.append("# Drop privileges to the container user") + # When the container command is a shell, force an interactive login + # shell. Detached containers may not have stdin connected, and a plain + # /bin/bash invocation exits immediately with code 0. -il keeps it + # alive so the container stays running for docker exec/web terminals. + lines.append('if [ "$1" = "/bin/bash" ] || [ "$1" = "bash" ]; then') + lines.append(f' exec runuser -u {name} -- /bin/bash -il') + lines.append('fi') lines.append(f'exec runuser -u {name} -- "$@"') else: lines.append('exec "$@"') @@ -582,7 +589,7 @@ def compute_image_tag(tool_name: str, manifest: dict) -> str: Returns: Docker image tag string. """ - compiler_version = "v3" # bump when compile_dockerfile/entrypoint/compose change + compiler_version = "v4" # bump when compile_dockerfile/entrypoint/compose change canonical = json.dumps(manifest, sort_keys=True, separators=(",", ":")) hash_suffix = hashlib.sha256( f"{compiler_version}:{canonical}".encode() diff --git a/apps/api/tests/.pi-map.index.md b/apps/api/tests/.pi-map.index.md index a1951b9..be886e4 100644 --- a/apps/api/tests/.pi-map.index.md +++ b/apps/api/tests/.pi-map.index.md @@ -2,7 +2,7 @@ dir: apps/api/tests ## role -Provides shared test infrastructure and fixtures for API integration testing +Provides shared test infrastructure and fixtures for the API application's test suite. ## parent index: apps/api/.pi-map.index.md map: apps/api/.pi-map.md diff --git a/apps/api/tests/.pi-map.md b/apps/api/tests/.pi-map.md index 68138d6..1f611e4 100644 --- a/apps/api/tests/.pi-map.md +++ b/apps/api/tests/.pi-map.md @@ -4,11 +4,11 @@ dir: apps/api/tests index: apps/api/tests/.pi-map.index.md ## role -Provides shared test infrastructure and fixtures for API integration testing +Provides shared test infrastructure and fixtures for the API application's test suite. ## files - conftest.py | Provides shared pytest fixtures for testing a FastAPI application with async SQLite database, authenticated clients, and test data setup. | exp: func:test_client() → Generator[TestClient, None, None], call:create_async_engine, call:engine.begin, call:conn.run_sync, call:asyncio.run, call:init_db, call:async_sessionmaker, call:patch, call:TestClient, call:app.dependency_overrides.pop, call:engine.dispose, func:init_db(), call:engine.begin, call:conn.run_sync, func:override_get_db_session() → AsyncGenerator[AsyncSession, None], call:async_sessionmaker, func:db_session(test_client) → AsyncGenerator[AsyncSession, None], call:app.dependency_overrides.get, call:override_fn, call:gen.asend, call:gen.aclose, call:create_async_engine, call:engine.begin, call:conn.run_sync, call:async_sessionmaker, call:engine.dispose, func:authenticated_client(test_client) → Generator[TestClient, None, None], call:str, call:uuid.uuid4, call:Settings, call:app.dependency_overrides.get, call:override_fn, call:gen.asend, call:User, call:uuid.UUID, call:session.add, call:session.commit, call:gen.aclose, call:asyncio.run, call:create_test_user, call:create_session_cookie, call:test_client.cookies.set, func:create_test_user(), call:app.dependency_overrides.get, call:override_fn, call:gen.asend, call:User, call:uuid.UUID, call:session.add, call:session.commit, call:gen.aclose, func:test_project_and_repo(authenticated_client) → tuple[str, str], call:uuid.uuid4, call:Settings, call:authenticated_client.cookies.get, call:decode_session_cookie, call:uuid.UUID, call:asyncio.run, call:get_user_id, call:app.dependency_overrides.get, call:override_fn, call:gen.asend, call:Project, call:session.add, call:GitRepository, call:session.commit, call:gen.aclose, call:create_project_and_repo, call:str, raise:RuntimeError, func:get_user_id(), call:Settings, call:authenticated_client.cookies.get, call:decode_session_cookie, call:uuid.UUID, func:create_project_and_repo(), call:app.dependency_overrides.get, call:override_fn, call:gen.asend, call:Project, call:session.add, call:GitRepository, call:session.commit, call:gen.aclose, func:admin_client(test_client) → Generator[TestClient, None, None], call:str, call:uuid.uuid4, call:Settings, call:app.dependency_overrides.get, call:override_fn, call:gen.asend, call:User, call:uuid.UUID, call:session.add, call:session.commit, call:gen.aclose, call:asyncio.run, call:create_admin_user, call:create_session_cookie, call:test_client.cookies.set, func:create_admin_user(), call:app.dependency_overrides.get, call:override_fn, call:gen.asend, call:User, call:uuid.UUID, call:session.add, call:session.commit, call:gen.aclose | dep: asyncio, os, typing, unittest.mock, pytest, pytest_asyncio, fastapi.testclient, sqlalchemy.ext.asyncio, src.config, src.models.base, src.main, src.auth.dependencies, uuid, src.auth.session, src.models.user.user, src.models.project.project, src.models.project.git_repository, fastapi, sqlalchemy, aiosqlite, src.models, src.auth ## arch -Pytest fixture-based architecture with async SQLite test database, dependency injection overrides, and authenticated client factories for FastAPI endpoint testing +Pytest fixture-based testing architecture with async SQLite test database, dependency injection overrides, and authenticated client factories using FastAPI's TestClient. ## tags call:app.dependency, call:create, overrides.get, call:override, fn, call:gen.asend, call:gen.aclose, user ## symbols diff --git a/apps/api/tests/unit/.pi-map.index.md b/apps/api/tests/unit/.pi-map.index.md index a7e7245..833c9b1 100644 --- a/apps/api/tests/unit/.pi-map.index.md +++ b/apps/api/tests/unit/.pi-map.index.md @@ -2,7 +2,7 @@ dir: apps/api/tests/unit ## role -Contains comprehensive unit tests for the API application's core services, utilities, and infrastructure components. +Contains unit tests for the API application's core services, utilities, and infrastructure components. ## parent index: apps/api/tests/.pi-map.index.md map: apps/api/tests/.pi-map.md diff --git a/apps/api/tests/unit/.pi-map.md b/apps/api/tests/unit/.pi-map.md index cb1592f..104e156 100644 --- a/apps/api/tests/unit/.pi-map.md +++ b/apps/api/tests/unit/.pi-map.md @@ -4,7 +4,7 @@ dir: apps/api/tests/unit index: apps/api/tests/unit/.pi-map.index.md ## role -Contains comprehensive unit tests for the API application's core services, utilities, and infrastructure components. +Contains unit tests for the API application's core services, utilities, and infrastructure components. ## files - __init__.py | Empty file with no functionality - test_alembic_migrations.py | Unit tests that verify Alembic database migrations are importable, have correct revision identifiers, and declare expected dependencies without requiring a live database. | exp: func:test_home_directory_migration_imports_and_rewrites() → None, call:Path, call:migration_path.exists, call:importlib.util.spec_from_file_location, call:importlib.util.module_from_spec, call:spec.loader.exec_module, call:callable, func:test_merge_migration_resolves_heads() → None, call:Path, call:migration_path.exists, call:importlib.util.spec_from_file_location, call:importlib.util.module_from_spec, call:spec.loader.exec_module, call:callable, func:test_remove_pi_agent_repo_mount_migration_imports() → None, call:Path, call:migration_path.exists, call:importlib.util.spec_from_file_location, call:importlib.util.module_from_spec, call:spec.loader.exec_module, call:callable | dep: importlib.util, pathlib, pytest, importlib @@ -30,7 +30,7 @@ Contains comprehensive unit tests for the API application's core services, utili - test_readiness_probe.py | Unit tests for a Docker container readiness probe service that executes commands via docker exec with retry logic. | exp: class:TestExecuteProbe, class:TestIntegrationScenarios | dep: unittest.mock, src.services.shared.readiness_probe, subprocess - test_ssh_keys.py | Unit tests for SSH key preparation functionality including file creation, permissions, ownership, and error handling | exp: class:TestPrepareSshKeyFiles | dep: os, pathlib, unittest.mock, pytest, src.services.shared.ssh_keys ## arch -Standard Python unittest/pytest pattern with heavy use of mocking (subprocess, filesystem, database) to isolate components; tests are organized by service/domain with each file targeting a single module/class; no internal dependencies between test files. +Comprehensive unit test suite using mocked dependencies to test business logic in isolation, covering database migrations, configuration, Docker operations, Git workflows, file services, event handling, health monitoring, and SSH/security utilities. ## tags test, url, call:notification, git, call:, home, merge, call:db ## symbols diff --git a/apps/api/tests/unit/test_manifest_compiler.py b/apps/api/tests/unit/test_manifest_compiler.py index 80857ad..4ffc21a 100644 --- a/apps/api/tests/unit/test_manifest_compiler.py +++ b/apps/api/tests/unit/test_manifest_compiler.py @@ -270,6 +270,7 @@ def test_compile_dockerfile_starts_as_root_and_drops_privileges() -> None: entrypoint = compile_entrypoint(manifest) assert "USER dev" not in dockerfile + assert 'exec runuser -u dev -- /bin/bash -il' in entrypoint assert 'exec runuser -u dev -- "$@"' in entrypoint