From 1d39af5b574f4d9b293ab160d8a3886c17914d1c Mon Sep 17 00:00:00 2001 From: Harish Seshadri Date: Wed, 7 Oct 2026 15:17:27 -0700 Subject: [PATCH] chore: rewrite owner to gainratio, drop default repository The repo moved from hseshadr to the gainratio org. Every Dagger gate now requires the run's own github.repository (no stale default owner), the allow-list names gainratio first and keeps hseshadr until the move finishes, and project URLs, CITATION, README and docs point at gainratio. Left alone on purpose: hseshadr/ci module pins (ci moves last), CHANGELOG, the 0.5.0 pypi-attestations command (signed under hseshadr), and the generated architecture evidence snapshot. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01UUhZtVsPJ1aFSZLD4X2cvD --- .dagger/src/edge_proc/main.py | 26 ++++++++--------- .dagger/tests/test_public_contracts.py | 39 ++++++++++++++++++-------- CITATION.cff | 4 +-- CONTRIBUTING.md | 2 +- README.md | 14 ++++----- docs/GETTING_STARTED.md | 2 +- docs/QUICKSTART.md | 2 +- pyproject.toml | 6 ++-- tests/test_dagger_release_pipeline.py | 2 +- tests/test_repin_locked_tools.py | 8 +++--- tests/test_workflow_security.py | 4 +-- 11 files changed, 60 insertions(+), 49 deletions(-) diff --git a/.dagger/src/edge_proc/main.py b/.dagger/src/edge_proc/main.py index 6c90553..45bdd78 100644 --- a/.dagger/src/edge_proc/main.py +++ b/.dagger/src/edge_proc/main.py @@ -16,10 +16,10 @@ "ghcr.io/astral-sh/uv:0.11.32@sha256:" "df4cae8f3a96d175e2e5f992e597550000edbe78fdc2594d5cd8de1a217f504c" ) -#: The repository as GitHub reports it today; the default keeps existing callers exact. -DEFAULT_REPOSITORY: Final = "hseshadr/edge-proc" -#: The only identities a run may claim: this repository today, and after the org transfer. -ALLOWED_REPOSITORIES: Final = ("hseshadr/edge-proc", "gainratio/edge-proc") +#: The only identities a run may claim: the canonical gainratio owner first, then the +#: pre-transfer identity until the org move finishes. There is deliberately no default: +#: every gate must be handed the run's own `github.repository`. +ALLOWED_REPOSITORIES: Final = ("gainratio/edge-proc", "hseshadr/edge-proc") PROJECT_NAME: Final = "edge-proc" CENTRAL_MODULE_SHA: Final = "a88866232e679b6353d2b75bceb01969be739f67" SOURCE_EXCLUDES: Final = [ @@ -99,21 +99,19 @@ def quality(self) -> dagger.Container: return self._quality(self.source) @function - async def security(self, commit_sha: str, repository: str = DEFAULT_REPOSITORY) -> str: + async def security(self, commit_sha: str, repository: str) -> str: """Run the shared exact-source, workflow, and history guard.""" await self._verified_source(self.source, _allowed_repository(repository), commit_sha) return "EdgeProc shared Dagger security gate passed" @function - def dependency_audit( - self, commit_sha: str, repository: str = DEFAULT_REPOSITORY - ) -> dagger.Container: + def dependency_audit(self, commit_sha: str, repository: str) -> dagger.Container: """Audit the locked graph through the shared Python-package Lego.""" return self._dependency_audit(self.source, _allowed_repository(repository), commit_sha) @function @check - async def ci(self, commit_sha: str, repository: str = DEFAULT_REPOSITORY) -> str: + async def ci(self, commit_sha: str, repository: str) -> str: """Run the canonical exact-source gate sequentially.""" await self._run_ci(self.source, commit_sha, _allowed_repository(repository)) return "EdgeProc canonical Dagger gate passed" @@ -122,7 +120,7 @@ async def ci(self, commit_sha: str, repository: str = DEFAULT_REPOSITORY) -> str @function(cache="never") # type: ignore[call-overload,untyped-decorator] # SDK stub gap async def release_candidate( self, tag: str, commit_sha: str, github_token: dagger.Secret, - repository: str = DEFAULT_REPOSITORY, + repository: str, ) -> dagger.Directory: """Create and reverify one exact attempt-bound Foundation envelope.""" repository = _allowed_repository(repository) @@ -136,7 +134,7 @@ async def release_candidate( @function(cache="never") # type: ignore[call-overload,untyped-decorator] # SDK stub gap async def repin_dependabot( - self, github_token: dagger.Secret, pr_number: int, repository: str = DEFAULT_REPOSITORY + self, github_token: dagger.Secret, pr_number: int, repository: str ) -> str: """Copy uv.lock tool versions into the literals of one Dependabot uv PR.""" repository = _allowed_repository(repository) @@ -155,7 +153,7 @@ async def verify_candidate( commit_sha: str, workflow_run_id: str, run_attempt: int, - repository: str = DEFAULT_REPOSITORY, + repository: str, ) -> dagger.Directory: """Revalidate a closed candidate without source or credentials.""" lineage = _Lineage( @@ -165,9 +163,7 @@ async def verify_candidate( await verified.tag() return verified.envelope() - async def _run_ci( - self, source: dagger.Directory, commit_sha: str, repository: str = DEFAULT_REPOSITORY - ) -> None: + async def _run_ci(self, source: dagger.Directory, commit_sha: str, repository: str) -> None: bound = await self._verified_source(source, repository, commit_sha) await self._product_gate(bound).sync() await self._dependency_audit(bound, repository, commit_sha).sync() diff --git a/.dagger/tests/test_public_contracts.py b/.dagger/tests/test_public_contracts.py index 004f44f..36e6a80 100644 --- a/.dagger/tests/test_public_contracts.py +++ b/.dagger/tests/test_public_contracts.py @@ -18,7 +18,7 @@ ROOT = Path(__file__).resolve().parents[2] CENTRAL_SHA = "a88866232e679b6353d2b75bceb01969be739f67" -REPOSITORY = "hseshadr/edge-proc" +REPOSITORY = "gainratio/edge-proc" PROJECT_NAME = "edge-proc" COMMIT_SHA = "a" * 40 MAX_FUNCTION_LINES = 15 @@ -260,7 +260,7 @@ def test_should_bind_guard_then_run_product_and_closed_audit_on_one_source( edge = _edge(source, events) # When - asyncio.run(edge._run_ci(source, COMMIT_SHA)) + asyncio.run(edge._run_ci(source, COMMIT_SHA, REPOSITORY)) # Then assert events == ["source", "guard", "product", "audit"] @@ -280,7 +280,7 @@ def test_should_query_osv_for_non_pypi_locked_versions( edge = _edge(cast(dagger.Directory, object()), []) # When - edge.dependency_audit(COMMIT_SHA) + edge.dependency_audit(COMMIT_SHA, REPOSITORY) # Then assert package.audit_commands == [list(dagger_module.OSV_AUDIT_COMMAND)] @@ -297,7 +297,7 @@ def test_should_stop_before_product_or_audit_when_shared_guard_rejects( # When / Then with pytest.raises(SharedGuardRejectedError, match="shared guard rejected source"): - asyncio.run(edge._run_ci(source, COMMIT_SHA)) + asyncio.run(edge._run_ci(source, COMMIT_SHA, REPOSITORY)) assert events == ["source"] assert edge.product_source is None assert package.audit_call is None @@ -313,7 +313,7 @@ def test_should_create_and_reverify_one_attempt_bound_closed_candidate( edge = _edge(source, events) # When - result = asyncio.run(edge.release_candidate("v0.4.1", COMMIT_SHA, token)) + result = asyncio.run(edge.release_candidate("v0.4.1", COMMIT_SHA, token, REPOSITORY)) # Then identity = (REPOSITORY, COMMIT_SHA, PROJECT_NAME, CENTRAL_SHA, "6100", 2) @@ -347,7 +347,9 @@ def test_should_reject_manual_tag_mismatch_before_candidate_handoff( # When / Then with pytest.raises(ValueError, match="manual tag differs"): - asyncio.run(edge.release_candidate("v0.4.1", COMMIT_SHA, cast(dagger.Secret, object()))) + asyncio.run( + edge.release_candidate("v0.4.1", COMMIT_SHA, cast(dagger.Secret, object()), REPOSITORY) + ) assert package.verify_call is None @@ -360,7 +362,7 @@ def test_should_verify_candidate_without_source_or_credentials( edge = _edge(cast(dagger.Directory, object()), events) # When - result = asyncio.run(edge.verify_candidate(envelope, COMMIT_SHA, "6100", 2)) + result = asyncio.run(edge.verify_candidate(envelope, COMMIT_SHA, "6100", 2, REPOSITORY)) # Then identity = (REPOSITORY, COMMIT_SHA, PROJECT_NAME, CENTRAL_SHA, "6100", 2) @@ -399,8 +401,8 @@ def test_should_keep_every_adapter_function_within_the_python_quality_contract() assert {name: span for name, span in spans.items() if span > MAX_FUNCTION_LINES} == {} -#: The repository as GitHub reports it today, and after the planned transfer to the org. -ALLOWED = ("hseshadr/edge-proc", "gainratio/edge-proc") +#: The canonical gainratio identity, then the pre-transfer one kept until the org move finishes. +ALLOWED = ("gainratio/edge-proc", "hseshadr/edge-proc") #: A fork, a sibling repository, a look-alike name, a look-alike owner, and nothing. REFUSED = ( @@ -412,12 +414,25 @@ def test_should_keep_every_adapter_function_within_the_python_quality_contract() ) -def test_should_default_to_the_repository_identity_used_today() -> None: +@pytest.mark.parametrize( + "gate", + [ + "ci", + "security", + "dependency_audit", + "release_candidate", + "repin_dependabot", + "verify_candidate", + "_run_ci", + ], +) +def test_should_require_the_runs_repository_with_no_stale_default_owner(gate: str) -> None: # Given / When - parameter = inspect.signature(EdgeProc.ci).parameters["repository"] + parameter = inspect.signature(getattr(EdgeProc, gate)).parameters["repository"] # Then - assert parameter.default == "hseshadr/edge-proc" + assert parameter.default is inspect.Parameter.empty + assert not hasattr(dagger_module, "DEFAULT_REPOSITORY") assert dagger_module.ALLOWED_REPOSITORIES == ALLOWED diff --git a/CITATION.cff b/CITATION.cff index d720e43..af7f2b3 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -12,8 +12,8 @@ authors: - family-names: Seshadri given-names: Harish email: harish.seshadri@gmail.com -repository-code: "https://github.com/hseshadr/edge-proc" -url: "https://github.com/hseshadr/edge-proc" +repository-code: "https://github.com/gainratio/edge-proc" +url: "https://github.com/gainratio/edge-proc" license: MIT version: 0.5.0 keywords: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ca72c4..118b103 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ New here? [Getting started for developers](docs/GETTING_STARTED.md) walks you fr clone to a green local build and your first change, with the time each step takes. ```bash -git clone https://github.com/hseshadr/edge-proc.git +git clone https://github.com/gainratio/edge-proc.git cd edge-proc uv sync --all-extras # core + extras + dev tooling uv run poe gate # lint + format-check + typecheck + complexity + test — what CI runs diff --git a/README.md b/README.md index af13361..fef1e7e 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ on the device, EdgeProc can also search it there, with no network. **Technical docs:** [Architecture](docs/ARCHITECTURE.md) · [Getting started for developers](docs/GETTING_STARTED.md) · [Full walkthrough with search](docs/QUICKSTART.md) · [Configuration](docs/CONFIGURATION.md) · [Operations and security](docs/OPERATIONS.md) -[![CI](https://github.com/hseshadr/edge-proc/actions/workflows/dagger.yml/badge.svg)](https://github.com/hseshadr/edge-proc/actions/workflows/dagger.yml) +[![CI](https://github.com/gainratio/edge-proc/actions/workflows/dagger.yml/badge.svg)](https://github.com/gainratio/edge-proc/actions/workflows/dagger.yml) [![PyPI](https://img.shields.io/pypi/v/edge-proc)](https://pypi.org/project/edge-proc/) -[![License](https://img.shields.io/github/license/hseshadr/edge-proc)](LICENSE) +[![License](https://img.shields.io/github/license/gainratio/edge-proc)](LICENSE) ## Try it @@ -135,7 +135,7 @@ rather than fetch one. ## How it fits with the related projects -- **[edgeproc-core](https://github.com/hseshadr/edgeproc-core)** (Python, on PyPI) is a +- **[edgeproc-core](https://github.com/gainratio/edgeproc-core)** (Python, on PyPI) is a smaller library underneath this one. EdgeProc uses two things from it: a common interface for vector search indexes, which EdgeProc's FAISS index implements, and the stable error codes, like `bundle.integrity_failed`. It installs automatically with EdgeProc. You would @@ -144,10 +144,10 @@ rather than fetch one. pages) does the checking half of EdgeProc inside a browser tab. It reads the same signed format that `edgeproc publish` writes, so you can publish with this library and load the data in a web page. -- **[edge-reco](https://github.com/hseshadr/edge-reco)** is a demo online store +- **[edge-reco](https://github.com/gainratio/edge-reco)** is a demo online store ([edge-reco.com](https://edge-reco.com)) that runs product search in the shopper's browser. It uses these libraries. -- **[privacy-core](https://github.com/hseshadr/privacy-core)** (published on npm as +- **[privacy-core](https://github.com/gainratio/privacy-core)** (published on npm as `@edgeproc/privacy-core`) is a separate project despite the shared name. It hides card numbers and similar IDs from AI prompts in the browser, and does not use EdgeProc. @@ -196,7 +196,7 @@ This README documents EdgeProc 0.5.0. It needs Python 3.13 or newer and installs ## Develop ```bash -git clone https://github.com/hseshadr/edge-proc.git +git clone https://github.com/gainratio/edge-proc.git cd edge-proc uv sync --all-extras uv run poe gate @@ -229,6 +229,6 @@ setup, a map of the code, a first change, and how to open a pull request. MIT. See [LICENSE](LICENSE). To cite EdgeProc, use [CITATION.cff](CITATION.cff). EdgeProc (also written `edge-proc` and `edgeproc`) lives at -[hseshadr/edge-proc](https://github.com/hseshadr/edge-proc), with a project page at +[gainratio/edge-proc](https://github.com/gainratio/edge-proc), with a project page at [edge-reco.com/edgeproc](https://edge-reco.com/edgeproc). It is not affiliated with any other product or company named "EdgeProc". diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index 81acded..1618150 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -21,7 +21,7 @@ builds on, installs from PyPI. ## Clone, install, and run it ```bash -git clone https://github.com/hseshadr/edge-proc.git +git clone https://github.com/gainratio/edge-proc.git cd edge-proc uv sync --all-extras ``` diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md index 1535dec..9f1e8c2 100644 --- a/docs/QUICKSTART.md +++ b/docs/QUICKSTART.md @@ -27,7 +27,7 @@ Budget more wall-clock on a slow link. The model download happens once; later ru ## 1. Clone and gate ```bash -git clone https://github.com/hseshadr/edge-proc.git +git clone https://github.com/gainratio/edge-proc.git cd edge-proc uv sync --all-extras # core + [localvec] + [bundles] + dev tooling diff --git a/pyproject.toml b/pyproject.toml index 7e4c1c0..154e7e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,9 +71,9 @@ dev = [ edgeproc = "edgeproc.cli:app" [project.urls] -Homepage = "https://github.com/hseshadr/edge-proc" -Repository = "https://github.com/hseshadr/edge-proc" -Issues = "https://github.com/hseshadr/edge-proc/issues" +Homepage = "https://github.com/gainratio/edge-proc" +Repository = "https://github.com/gainratio/edge-proc" +Issues = "https://github.com/gainratio/edge-proc/issues" # edgeproc-core installs from PyPI. Co-developing it locally? Clone it next to # this repo and add a path override (uncomment): diff --git a/tests/test_dagger_release_pipeline.py b/tests/test_dagger_release_pipeline.py index a9d077f..bd2b636 100644 --- a/tests/test_dagger_release_pipeline.py +++ b/tests/test_dagger_release_pipeline.py @@ -166,7 +166,7 @@ def test_should_fetch_only_hosted_identity_fields( monkeypatch.setattr(contract, "urlopen", lambda *_args, **_kwargs: next(responses)) # When - payload = contract.fetch_hosted_payload("hseshadr/edge-proc", SHA, "v1.2.3", "token") + payload = contract.fetch_hosted_payload("gainratio/edge-proc", SHA, "v1.2.3", "token") # Then contract.validate_hosted_eligibility(payload, SHA) diff --git a/tests/test_repin_locked_tools.py b/tests/test_repin_locked_tools.py index d92f629..dd2c2db 100644 --- a/tests/test_repin_locked_tools.py +++ b/tests/test_repin_locked_tools.py @@ -142,7 +142,7 @@ def test_should_build_a_head_bound_commit_request(tmp_path: Path) -> None: # When request = tool.commit_request( - root, "hseshadr/edge-proc", "dependabot/uv/x", "c" * 40, (TEST_SITE,) + root, "gainratio/edge-proc", "dependabot/uv/x", "c" * 40, (TEST_SITE,) ) # Then @@ -161,7 +161,7 @@ def test_should_refuse_a_head_that_is_not_a_full_commit_sha(tmp_path: Path) -> N # When / Then with pytest.raises(tool.RepinError, match="commit sha"): - tool.commit_request(root, "hseshadr/edge-proc", "b", "HEAD", (TEST_SITE,)) + tool.commit_request(root, "gainratio/edge-proc", "b", "HEAD", (TEST_SITE,)) def test_should_print_changed_sites_from_the_cli( @@ -211,7 +211,7 @@ def test_should_exit_one_with_the_refusal_on_stderr( HEAD = "e" * 40 -REPOSITORY = "hseshadr/edge-proc" +REPOSITORY = "gainratio/edge-proc" class FakeGitHub: @@ -293,7 +293,7 @@ def test_should_write_nothing_when_the_head_literals_match_its_lock(tmp_path: Pa ("pull", "reason"), [ (_pull(login="octocat"), "not opened by dependabot"), - (_pull(repo="fork/edge-proc"), "not in hseshadr/edge-proc"), + (_pull(repo="fork/edge-proc"), "not in gainratio/edge-proc"), (_pull(ref="dependabot/npm_and_yarn/x"), "not a Dependabot uv branch"), (_pull(ref=7), "malformed"), ], diff --git a/tests/test_workflow_security.py b/tests/test_workflow_security.py index dfc5ec4..39bbb7f 100644 --- a/tests/test_workflow_security.py +++ b/tests/test_workflow_security.py @@ -155,7 +155,7 @@ def _expand_action_args(args: str, tag: str, cwd: Path) -> list[str]: """Expand args exactly as dagger-for-github's final bash step does, but print them.""" bash = shutil.which("bash") assert bash is not None - env = {"TAG": tag, "GITHUB_SHA": "a" * 40, "GITHUB_REPOSITORY": "hseshadr/edge-proc"} + env = {"TAG": tag, "GITHUB_SHA": "a" * 40, "GITHUB_REPOSITORY": "gainratio/edge-proc"} env["PATH"] = "/usr/bin:/bin" result = subprocess.run( # noqa: S603 [bash, "-c", f"printf '%s\\0' {args}"], env=env, cwd=cwd, capture_output=True, check=True @@ -212,7 +212,7 @@ def test_should_pass_any_dispatched_tag_to_dagger_as_one_inert_argument( # Then Dagger receives the tag verbatim as one argument and no command ran assert words[:2] == ["release-candidate", f"--tag={tag}"] assert words[2] == "--commit-sha=" + "a" * 40 - assert words[4] == "--repository=hseshadr/edge-proc" + assert words[4] == "--repository=gainratio/edge-proc" assert list(tmp_path.iterdir()) == []