diff --git a/packages/devqubit-braket/src/devqubit_braket/py.typed b/packages/devqubit-braket/src/devqubit_braket/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/packages/devqubit-cirq/src/devqubit_cirq/py.typed b/packages/devqubit-cirq/src/devqubit_cirq/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/packages/devqubit-engine/src/devqubit_engine/py.typed b/packages/devqubit-engine/src/devqubit_engine/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/packages/devqubit-engine/src/devqubit_engine/utils/env.py b/packages/devqubit-engine/src/devqubit_engine/utils/env.py index 63144f3..e70c3e4 100644 --- a/packages/devqubit-engine/src/devqubit_engine/utils/env.py +++ b/packages/devqubit-engine/src/devqubit_engine/utils/env.py @@ -133,6 +133,51 @@ def capture_environment(include_pip: bool | None = None) -> dict[str, Any]: return env +def _sanitize_git_url(url: str | None) -> str | None: + """ + Sanitize a git remote URL by removing embedded credentials. + + Removes userinfo (user:password@) from URLs to prevent accidental + token/credential leakage in run records. + + Parameters + ---------- + url : str or None + Git remote URL, possibly containing credentials. + + Returns + ------- + str or None + URL with credentials removed, or None if input was None. + + Examples + -------- + >>> _sanitize_git_url("https://token@github.com/org/repo.git") + 'https://github.com/org/repo.git' + >>> _sanitize_git_url("https://user:pass@github.com/org/repo.git") + 'https://github.com/org/repo.git' + >>> _sanitize_git_url("git@github.com:org/repo.git") + 'git@github.com:org/repo.git' + """ + if not url: + return url + + # Handle HTTPS URLs with credentials: https://user:pass@host/... + # Pattern matches: scheme://[userinfo@]host... + import re + + # Match URLs with credentials in userinfo section + pattern = r"^(https?://)([^@]+@)(.+)$" + match = re.match(pattern, url) + if match: + scheme, _, rest = match.groups() + sanitized = f"{scheme}{rest}" + logger.debug("Sanitized credentials from git remote URL") + return sanitized + + return url + + def capture_git_provenance(cwd: str | None = None) -> dict[str, Any] | None: """ Capture git repository provenance information. @@ -190,7 +235,8 @@ def _run_git(args: list[str]) -> str | None: branch = _run_git(["rev-parse", "--abbrev-ref", "HEAD"]) status_output = _run_git(["status", "--porcelain"]) dirty = bool(status_output) - remote = _run_git(["config", "--get", "remote.origin.url"]) + remote_raw = _run_git(["config", "--get", "remote.origin.url"]) + remote = _sanitize_git_url(remote_raw) describe = _run_git(["describe", "--tags", "--always", "--dirty"]) result = { diff --git a/packages/devqubit-pennylane/src/devqubit_pennylane/py.typed b/packages/devqubit-pennylane/src/devqubit_pennylane/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/packages/devqubit-qiskit-runtime/src/devqubit_qiskit_runtime/py.typed b/packages/devqubit-qiskit-runtime/src/devqubit_qiskit_runtime/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/packages/devqubit-qiskit/src/devqubit_qiskit/py.typed b/packages/devqubit-qiskit/src/devqubit_qiskit/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/packages/devqubit-ui/src/devqubit_ui/app.py b/packages/devqubit-ui/src/devqubit_ui/app.py index 59b5138..c10bd2f 100644 --- a/packages/devqubit-ui/src/devqubit_ui/app.py +++ b/packages/devqubit-ui/src/devqubit_ui/app.py @@ -28,6 +28,8 @@ import logging import os from contextlib import asynccontextmanager +from importlib.metadata import PackageNotFoundError +from importlib.metadata import version as get_version from pathlib import Path from typing import AsyncGenerator @@ -128,10 +130,15 @@ def create_app( - ``app.state.store`` - Object store - ``app.state.workspace`` - Workspace path string """ + try: + _version = get_version("devqubit-ui") + except PackageNotFoundError: + _version = "0.0.0" + app = FastAPI( title="devqubit UI", description="Web interface for devqubit experiment tracking", - version="0.1.4", + version=_version, lifespan=lifespan, ) diff --git a/packages/devqubit-ui/src/devqubit_ui/py.typed b/packages/devqubit-ui/src/devqubit_ui/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/src/devqubit/py.typed b/src/devqubit/py.typed new file mode 100644 index 0000000..e69de29