from __future__ import annotations import json import sys import tempfile import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / "scripts")) from check_boundaries import find_violations # noqa: E402 class BootstrapTests(unittest.TestCase): def test_workspace_metadata_and_roots_exist(self) -> None: package = json.loads((ROOT / "package.json").read_text(encoding="utf-8")) self.assertTrue(package["private"]) roots = ( "apps", "services", "connectors", "packages", "tests", "infrastructure", "evidence", "docs", ) for name in roots: self.assertTrue((ROOT / name).is_dir(), name) def test_forbidden_dependency_sample_is_detected(self) -> None: with tempfile.TemporaryDirectory() as directory: root = Path(directory) sample = root / "packages" / "hub-contracts" / "sample.py" sample.parent.mkdir(parents=True) sample.write_text("from connectors.gitea.client import Client\n", encoding="utf-8") violations = find_violations(root, [sample]) self.assertEqual(len(violations), 1) self.assertIn("forbidden dependency", violations[0].message) def test_runtime_composition_root_may_wire_services_and_connectors(self) -> None: with tempfile.TemporaryDirectory() as directory: root = Path(directory) sample = root / "services" / "runtime" / "sample.py" sample.parent.mkdir(parents=True) sample.write_text( "from services.control_api.auth import OIDCSettings\n" "from connectors.gitea import GiteaConnector\n", encoding="utf-8", ) violations = find_violations(root, [sample]) self.assertEqual(violations, []) def test_bootstrap_runtime_is_limited_to_declared_service_entrypoints(self) -> None: runtime_files = [ path.relative_to(ROOT).as_posix() for root_name in ("apps", "services", "connectors") for path in (ROOT / root_name).rglob("*") if path.is_file() and path.suffix in {".py", ".ts", ".tsx", ".js", ".jsx"} and not ( {"node_modules", "dist", "playwright-report", "test-results"} & set(path.parts) ) ] self.assertEqual( set(runtime_files), { "apps/web/src/bootstrap.ts", "apps/web/src/app.tsx", "apps/web/src/api.ts", "apps/web/src/contracts.ts", "apps/web/src/format.ts", "apps/web/src/hooks.ts", "apps/web/src/rbac.ts", "apps/web/src/rbac-context.tsx", "apps/web/src/navigation.ts", "apps/web/src/routing.ts", "apps/web/src/operator-data.ts", "apps/web/src/preferences.ts", "apps/web/src/schema-input.ts", "apps/web/src/status-refresh.ts", "apps/web/src/tool-history.ts", "apps/web/src/components/Brand.tsx", "apps/web/src/components/Breadcrumbs.tsx", "apps/web/src/components/CommandMenu.tsx", "apps/web/src/components/DataTable.tsx", "apps/web/src/components/ErrorPanel.tsx", "apps/web/src/components/Icon.tsx", "apps/web/src/components/LoadingPanel.tsx", "apps/web/src/components/McpTopology.tsx", "apps/web/src/components/MetricCard.tsx", "apps/web/src/components/Modal.tsx", "apps/web/src/components/SessionMenu.tsx", "apps/web/src/components/StatusPill.tsx", "apps/web/src/components/RecentToolRuns.tsx", "apps/web/src/components/SchemaInputFields.tsx", "apps/web/src/components/modal-focus.ts", "apps/web/src/pages/AuthGateway.tsx", "apps/web/src/pages/CatalogWorkflow.tsx", "apps/web/src/pages/ClientOnboarding.tsx", "apps/web/src/pages/ConnectorDetail.tsx", "apps/web/src/pages/Dashboard.tsx", "apps/web/src/pages/ForbiddenPanel.tsx", "apps/web/src/pages/Operations.tsx", "apps/web/src/pages/PolicySimulator.tsx", "apps/web/src/pages/ProjectDetail.tsx", "apps/web/src/pages/ResourcePage.tsx", "apps/web/src/pages/SettingsPage.tsx", "apps/web/src/pages/ToolReadinessModal.tsx", "apps/web/tests/contracts.test.ts", "apps/web/tests/api.test.ts", "apps/web/tests/rbac.test.ts", "apps/web/tests/operator-data.test.ts", "apps/web/tests/preferences.test.ts", "apps/web/tests/schema-input.test.ts", "apps/web/tests/tool-history.test.ts", "apps/web/tests/e2e/fixtures.ts", "apps/web/tests/e2e/auth.spec.ts", "apps/web/tests/e2e/rbac.spec.ts", "apps/web/tests/e2e/workflows.spec.ts", "apps/web/tests/e2e/theme.spec.ts", "apps/web/tests/e2e/navigation.spec.ts", "apps/web/tests/e2e/accessibility.spec.ts", "apps/web/tests/e2e/visual-quality.spec.ts", "apps/web/tests/e2e/operator-matrix.spec.ts", "apps/web/tests/e2e/operator-shell.spec.ts", "apps/web/tests/e2e/operator-review.spec.ts", "apps/web/tests/e2e/operator-workflows.spec.ts", "apps/web/src/main.ts", "apps/web/tests/bootstrap.test.ts", "apps/web/vite.config.ts", "apps/web/playwright.config.ts", "services/__init__.py", "services/observability/__init__.py", "services/observability/health.py", "services/control_api/__init__.py", "services/control_api/authz.py", "services/control_api/policy/__init__.py", "services/control_api/policy/router.py", "services/control_api/policy/service.py", "services/control_api/clients/__init__.py", "services/control_api/clients/router.py", "services/control_api/clients/service.py", "connectors/__init__.py", "connectors/knowledge/__init__.py", "connectors/knowledge/server.py", "connectors/gitea/__init__.py", "connectors/gitea/changesets.py", "connectors/gitea/fake.py", "connectors/gitea/lifecycle.py", "connectors/gitea/managed_validation.py", "connectors/gitea/server.py", "connectors/unraid/__init__.py", "connectors/unraid/client.py", "connectors/unraid/fake.py", "connectors/unraid/server.py", "connectors/mobilityops/__init__.py", "connectors/mobilityops/fake.py", "connectors/mobilityops/server.py", "services/dataplane_router/__init__.py", "services/dataplane_router/authz.py", "services/dataplane_router/errors.py", "services/dataplane_router/models.py", "services/dataplane_router/proxy.py", "services/dataplane_router/registry.py", "services/dataplane_router/router.py", "services/control_api/persistence/__init__.py", "services/control_api/persistence/dataplane_source.py", "services/control_api/persistence/demo_client.py", "services/control_api/persistence/machine_client.py", "services/control_api/knowledge/__init__.py", "services/control_api/knowledge/jobs.py", "services/control_api/knowledge/store.py", "services/control_api/gitea/__init__.py", "services/control_api/gitea/registry.py", "services/docker_read_broker/__init__.py", "services/docker_read_broker/broker.py", "services/docker_read_broker/server.py", "services/control_api/persistence/db.py", "services/control_api/persistence/models.py", "services/control_api/persistence/repositories.py", "services/control_api/persistence/seed.py", "services/control_api/catalog/__init__.py", "services/control_api/catalog/loader.py", "services/control_api/catalog/models.py", "services/control_api/catalog/planner.py", "services/control_api/catalog/reconciler.py", "services/control_api/catalog/router.py", "services/control_api/catalog/store.py", "services/control_api/auth/__init__.py", "services/control_api/auth/bff.py", "services/control_api/auth/config.py", "services/control_api/auth/errors.py", "services/control_api/auth/fake_provider.py", "services/control_api/auth/machine.py", "services/control_api/auth/models.py", "services/control_api/auth/provider.py", "services/control_api/auth/router.py", "services/control_api/contextforge/__init__.py", "services/control_api/contextforge/client.py", "services/control_api/contextforge/errors.py", "services/control_api/contextforge/fake.py", "services/control_api/contextforge/models.py", "services/control_api/persistence/services.py", "services/runtime/__init__.py", "services/runtime/__main__.py", "services/runtime/common.py", "services/runtime/connector_gitea.py", "services/runtime/gitea_operations_widget.py", "services/runtime/gitea_review_widget.py", "services/runtime/mcp_skills.py", "services/runtime/oauth_metadata.py", "services/runtime/synthetic_monitor.py", "services/runtime/connector_knowledge.py", "services/runtime/connector_ingestion.py", "services/runtime/ingestion_auth.py", "services/runtime/ingestion_files.py", "services/runtime/ingestion_hub_client.py", "services/runtime/ingestion_workflow.py", "services/runtime/connector_unraid.py", "services/runtime/connector_mobilityops.py", "services/runtime/connector_projectbrain.py", "services/runtime/connector_appops.py", "services/runtime/connector_stitch.py", "services/runtime/audit.py", "services/runtime/client_service.py", "services/runtime/control_api.py", "services/runtime/dataplane.py", "services/runtime/dispatch.py", "services/runtime/mcp_server.py", "services/runtime/migrate.py", "services/runtime/demo_token.py", "services/runtime/state_sync.py", "services/runtime/web.py", "services/runtime/worker.py", }, ) if __name__ == "__main__": unittest.main()