From aee050d274133570b08a181abcc3c81fdf63176d Mon Sep 17 00:00:00 2001 From: m2papierz Date: Mon, 12 Jan 2026 19:37:47 +0100 Subject: [PATCH 1/3] chore: add py.typed (PEP 561) --- packages/devqubit-braket/src/devqubit_braket/py.typed | 0 packages/devqubit-cirq/src/devqubit_cirq/py.typed | 0 packages/devqubit-engine/src/devqubit_engine/py.typed | 0 packages/devqubit-pennylane/src/devqubit_pennylane/py.typed | 0 .../devqubit-qiskit-runtime/src/devqubit_qiskit_runtime/py.typed | 0 packages/devqubit-qiskit/src/devqubit_qiskit/py.typed | 0 packages/devqubit-ui/src/devqubit_ui/py.typed | 0 src/devqubit/py.typed | 0 8 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/devqubit-braket/src/devqubit_braket/py.typed create mode 100644 packages/devqubit-cirq/src/devqubit_cirq/py.typed create mode 100644 packages/devqubit-engine/src/devqubit_engine/py.typed create mode 100644 packages/devqubit-pennylane/src/devqubit_pennylane/py.typed create mode 100644 packages/devqubit-qiskit-runtime/src/devqubit_qiskit_runtime/py.typed create mode 100644 packages/devqubit-qiskit/src/devqubit_qiskit/py.typed create mode 100644 packages/devqubit-ui/src/devqubit_ui/py.typed create mode 100644 src/devqubit/py.typed 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-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/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 From c4b8dc50275a006dc04f0422f18c0362563e1650 Mon Sep 17 00:00:00 2001 From: m2papierz Date: Mon, 12 Jan 2026 19:41:00 +0100 Subject: [PATCH 2/3] security: sanitize git remote URLs in provenance capture --- .../src/devqubit_engine/utils/env.py | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) 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 = { From 88aaa7a4e7b58f4d54acd94d91e433c899a8edd3 Mon Sep 17 00:00:00 2001 From: m2papierz Date: Mon, 12 Jan 2026 19:43:22 +0100 Subject: [PATCH 3/3] chore: use importlib.metadata for UI version instead of hardcoded string --- packages/devqubit-ui/src/devqubit_ui/app.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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, )