Metadata-Version: 2.4
Name: crowdcoding
Version: 0.1.1
Summary: A trusted contribution protocol: improve or audit a repo you don't own and hand the owner a portable, signed change credited to a verifiable GitHub identity. The owner re-verifies with their own tooling before merge. AI optional.
Author: Augusto Bastos
License: MIT
Project-URL: Homepage, https://crowdcoding.pages.dev
Project-URL: Repository, https://github.com/augbastos/crowdcoding
Project-URL: Documentation, https://github.com/augbastos/crowdcoding/blob/main/docs/format.md
Keywords: github,contributions,open-source,supply-chain,provenance,attestation,in-toto,dsse,code-signing,ssh,verification
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Version Control :: Git
Classifier: Topic :: Security
Classifier: Topic :: Security :: Cryptography
Classifier: Environment :: Console
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=42
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pyyaml>=6; extra == "dev"
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == "mcp"
Dynamic: license-file

<p align="center">
  <img src="docs/assets/hero.svg" alt="crowdcoding — trusted contributions to any repo" width="860">
</p>

<p align="center">
  <img alt="tests" src="https://img.shields.io/badge/tests-264_passing-41c257?style=flat-square&labelColor=0b0b0c">
  <img alt="python" src="https://img.shields.io/badge/python-3.11%2B-41c257?style=flat-square&labelColor=0b0b0c">
  <img alt="license" src="https://img.shields.io/badge/license-MIT-41c257?style=flat-square&labelColor=0b0b0c">
  <img alt="status" src="https://img.shields.io/badge/v0.1-early-d29922?style=flat-square&labelColor=0b0b0c">
</p>

**Improve or audit a public repo you don't own**, and hand the owner a **portable, signed
change whose credit is a cryptographically-verifiable GitHub identity** — not a typed-in name
anyone could fake. The owner re-proves it with *their own* tooling, at a scrutiny level they
choose, before anything merges. On accept the change merges with the contributor as the git
author, so they **appear natively in the repo's Contributors** — the identity *is* the credit.

> A contribution rides as a plain-text spec-label anyone can verify by eye — the same card, in
> your terminal, a PR comment, or a README:
>
> ```
> +--<+> crowdcoding --------------------------- CONTRIBUTION --+
> |  contributor  @you  (github.com/you)                       |
> |  signed by    an SSH key on that GitHub account            |
> |  changes      1 piece(s),  +14 / -3,  3 files              |
> |  risk         LOW  (recompute to confirm)                  |
> |  CLAIM - confirm it yourself:                               |
> |    uvx crowdcoding verify envelope.zip --repo .             |
> +----------------------------- cc/spec-01 - claim, not proof +
> ```

AI is optional, not the point. Bring your own model to draft the fix, or edit by hand — the
value is the **verifiable, owner-gated trust layer**, neutral to whatever tool either side
uses. It is not a bot opening unsolicited PRs; it is the inverse — opt-in and owner-gated,
where the *owner's own tooling* decides what enters.

**Verifiable identity.** A contribution (and an audit) is signed with an SSH key the
contributor's GitHub account publishes; the owner verifies that signature against
`github.com/<login>.keys`. Credit is spoof-resistant on both sides: nobody can attribute work
to an account they don't control. Requires a GitHub account, an SSH key registered on it, and
the `gh` CLI — see [docs/format.md](docs/format.md) for the exact scheme (any language can
verify it) and [docs/action.md](docs/action.md) for the maintainer-side GitHub Action that
posts a verified "seal" on each PR.

## Why not just Git's SSH commit signing?

Git can sign commits with an SSH key, and GitHub shows a green "Verified" — so why this?
Because they answer **different questions at different moments**. Commit signing proves *who
authored the final commit*; crowdcoding proves *who authored the **contribution**, against
which base, with what provenance*, **before** a commit even exists — and adds what commit
signing does not:

- **Provenance of how it was made** — hand-authored, or AI-assisted with which model,
  self-verified in a sandbox.
- **A signed audit** (in-toto/DSSE, `cosign`-verifiable) as a first-class deliverable —
  "found nothing" is a result you can publish, not just a merged diff.
- **A deterministic, reproducible risk band** over the diff (a published rule set, not a
  magic score — see [docs/format.md](docs/format.md)).
- **Owner re-verification** — the owner re-proves safety/tests/fit with *their own* tooling.

crowdcoding **complements** commit signing; it never replaces it. On merge, the commit is
authored with the contributor's GitHub identity, so native commit signing and the Verified
badge apply as usual.

## How it works

The contract between the two sides is the **Envelope** (a signed zip) plus the receiver's
**re-prove** — never a shared agent and never blind trust. The Ed25519 signature proves only
*"a real keyholder produced this, unaltered"*; it is anti-forgery, not a reason to trust.

```
contributor's model  ──analyze──▶  fix pieces  ──self-verify (sandbox)──▶  sign
                                                                            │
                                                                     envelope.zip
                                                                            │
owner's model  ◀──re-prove: provenance ▸ safety ▸ correctness ▸ fit──  unpack
        │
   accept ─▶ git apply + commit (author = contributor, Assisted-By: trailer)   /   reject
```

## The command set

| Command | What it does | Brain |
|---|---|---|
| `analyze <repo>` | Read-only scout: grade the repo and brief its top fixable issues. No fix, no envelope. | council |
| `contribute <repo>` | Analyze → fix → self-verify in a sandbox → emit a **signed Envelope**. | council |
| `pull <repo>` | Clone the repo into a local workspace so you can edit it **by hand**. | none |
| `pack` | Seal your workspace's manual edits into the **same signed Envelope** a council would produce. | none |
| `keygen` | Create or show your Ed25519 signing key — prints the **public** key only. | none |
| `inspect <envelope>` | Read an Envelope safely: parse + signature check, **runs nothing**. | none |
| `verify <envelope> --repo <clone>` | Owner handshake: re-prove provenance ▸ safety ▸ correctness ▸ fit. `--apply` merges with credit. | owner's |
| `submit <envelope>` | Open a native PR from your fork with the envelope attached, authored by your GitHub identity. | none |
| `seal <envelope> --repo <clone>` | Decision-first PR seal: identity, a deterministic risk band, tests, provenance. Powers the GitHub Action. | none/owner's |
| `attest <repo>` | Sign a standard in-toto/DSSE **audit** attestation — no diff, credits nobody, auditor bound to a GitHub identity. | your own |
| `verify-attest <file>` | Verify a DSSE attestation independently (works with `cosign` too). | none |
| `label <artifact>` | Print the plain-text confirmation card that rides with an envelope/attestation. | none |
| `extract <envelope>` | Explode an envelope into `envelope.json` + `contribution.patch` — the open form, no crowdcoding needed to read it. | none |
| `init` | Stamp the machine-detectable opt-in badge on a repo's README. | none |

`analyze` and `contribute` use the **council brain** (your own LLM); `pull` and `pack` are the
**AI-free "do it your way" path** — you author the diff by hand and crowdcoding just signs and
packages it into an Envelope the owner re-proves exactly the same way.

## Quickstart (offline, no key, zero cost)

Everything here runs with no network and no API key — the bundled `mock` backend is a
deterministic offline stub used by the test suite and CI.

```bash
python -m pip install -e .[dev]

crowdcoding --version          # crowdcoding 0.1.1
crowdcoding keygen             # prints your PUBLIC key; private stays in ~/.crowdcoding/key.pem
python -m pytest -q            # 264 passing — the full contribute → verify → credited-merge flow
```

`keygen`, `pull`, `pack`, `inspect`, and `init` need **no model and no API key** — the whole
do-it-your-way path (edit a clone, seal it, read the result) runs fully offline.

The test suite is the offline proof: it drives *two independent* mock councils end to end,
including tamper-rejection and booby-trap-rejection.

> The `mock` backend is a stub for tests/CI — it does **not** synthesize fixes or grades on its
> own, so `crowdcoding analyze <repo> --backend mock` and `crowdcoding contribute <repo> --backend
> mock` both report "no issues". To produce real analysis or contributions, bring your own model
> (below). The AI-free commands (`pull`/`pack`/`inspect`/`init`) do not need a backend at all.

## Bring your own model

One OpenAI-compatible backend covers every provider — OpenAI, Azure, Gemini/Anthropic compat
endpoints, OpenRouter, and local runtimes (Ollama, LM Studio, llama.cpp, vLLM). Configure it
with three environment variables:

```bash
export CROWDCODING_BACKEND=openai
export CROWDCODING_BASE_URL=http://localhost:11434/v1   # Ollama (fully local, free)
export CROWDCODING_MODEL=llama3
# export CROWDCODING_API_KEY=...   # only if the provider needs one; never logged, only its presence
```

OpenRouter instead:

```bash
export CROWDCODING_BASE_URL=https://openrouter.ai/api/v1
export CROWDCODING_MODEL=anthropic/claude-3.5-sonnet
export CROWDCODING_API_KEY=...
```

**Scout first (optional)** — read-only grade + briefing of the top fixable issues, no envelope:

```bash
crowdcoding analyze https://github.com/owner/repo          # add --json for the machine report
```

**Contributor side** — analyze, fix, self-verify, and emit a signed envelope credited to your
verifiable GitHub identity (resolved from the `gh` CLI + your registered SSH key):

```bash
crowdcoding contribute https://github.com/owner/repo --out envelope.zip
```

It drafts the fixes, then STOPS so you review every diff before anything is sent — nothing
leaves your machine until you act. Prefer to skip the AI? Use the `pull` → hand-edit → `pack`
path below; it produces the same signed, GitHub-credited envelope with no model at all.

**Owner side** — re-prove the envelope against your own clone, then merge with credit:

```bash
crowdcoding verify envelope.zip --repo /path/to/local/clone --trust strict
crowdcoding verify envelope.zip --repo /path/to/local/clone --apply
```

`--apply` requires `--repo` to be a local working copy, and refuses if the envelope claims a
GitHub identity that does NOT verify. For each accepted piece it runs `git apply` and one
`git commit` authored with the contributor's GitHub no-reply email — so once the owner pushes,
the contributor appears natively in the repo's Contributors — plus (per the target repo's AI
policy) an `Assisted-By: crowdcoding/<model>` trailer and the envelope's SHA-256. Add `--json`
to any `verify` for the full machine-readable report.

## Do-it-your-way — `pull` + `pack` (no AI required)

Prefer to fix things by hand? Skip the council entirely. `pull` clones the repo into a workspace
and records the exact base commit; you edit however you like; `pack` diffs your working tree
against that base and seals the change into the **same signed Envelope** — which the owner
re-proves with the identical handshake. No model, no API key.

```bash
crowdcoding pull https://github.com/owner/repo --dest ./repo   # clone + record the base commit
#   ... edit files in ./repo by hand ...
crowdcoding pack --workspace ./repo --out envelope.zip         # sign + package your manual diff
```

`pack` credits your **verifiable GitHub identity** (resolved from the `gh` CLI + your registered
SSH signing key — no typed-in name), the same as `contribute`. The base commit is stored in
`./repo/.crowdcoding/base.json` and kept out of your diff. `pack` refuses an empty change set, so
an accidental no-op never ships. Pass `--backend` **only** if you want a model to write the
owner-facing briefing — the diff itself is always yours.

## Read before you trust — `inspect`

`inspect` opens an Envelope and reports the sender, base commit, signature validity, and a
per-piece line count **without running anything** — no clone, no sandbox, no backend. It is safe
to point at an untrusted envelope: parsing plus a signature check is the whole attack surface.

```bash
crowdcoding inspect envelope.zip        # add --json for the full report
```

Exit code is `0` when the signature verifies and `2` when it does not (still listing the pieces),
so CI can gate on a tampered/unsigned envelope.

## Opt in — `init`

`init` stamps a machine-detectable badge on your repo's README so crawlers can find
"Crowdcoding contributions welcome" and humans can click through. It only edits `README.md` —
never commits, pushes, or reaches the network — and is idempotent (a second run is a no-op).

```bash
crowdcoding init --repo . --url https://github.com/you/your-repo   # --url defaults to origin
```

## Trust levels

The owner picks how hard to re-prove each envelope:

| `--trust`  | Provenance (signature) | Safety audit | Sandboxed correctness | Fit (style/license/AI policy) |
|------------|:----------------------:|:------------:|:---------------------:|:-----------------------------:|
| `strict`   | ✅                     | ✅           | ✅                    | ✅                            |
| `trusted`  | ✅                     | ✅           | —                     | —                             |
| `direct`   | ✅                     | —            | —                     | —                             |

A failed signature is fatal at every level: the envelope is rejected and nothing is applied.
`direct` accepts on a valid signature alone (confidence 0.5) — use it only for contributors you
already trust.

## What the handshake guarantees — and what it doesn't

- **Signature = authenticity, not trust.** It proves the bytes are unaltered and came from the
  holder of the stated key. It says nothing about whether the change is safe or good — that is
  what re-proving is for.
- **The sandbox is process isolation + a cleaned environment + a hard timeout, not a container.**
  It runs the untrusted diff in a throwaway copy of the repo, in a subprocess whose environment is
  stripped of `CROWDCODING_*`, `*_API_KEY`, `*_TOKEN`, `*_SECRET`, `*_PASSWORD` variables, and kills
  the run on timeout. That contains accidents and casual exfiltration — it is **not** a defense
  against a determined attacker. Container/VM hardening is the documented post-MVP step. Never run
  `verify` against a working tree you care about; the temp copy is always discarded.
- **The owner always has the final say.** Every stage produces evidence; the verdict
  (`accept` / `needs-changes` / `reject`) and confidence are the owner's to act on.
- **Secrets are scrubbed** from every prompt and from provenance excerpts, and are never logged —
  only their presence is.

## Anti-slop stance

Open-source maintainers are rightly wary of unsolicited AI contributions. Crowdcoding is built to
respect that:

- **Quality over volume** — pieces that don't apply cleanly or don't pass the target's own tests
  are dropped before they ever reach the owner.
- **Owner-gated by construction** — nothing merges unless the owner's own tooling re-proves it.
- **Always disclosed** — accepted merges carry an `Assisted-By:` trailer, in line with emerging
  maintainer AI policies.
- **Policy-aware** — the `fit` stage reads the repo's `AGENTS.md` / `CLAUDE.md` / `LICENSE` and
  judges the piece against them.

## Status

MVP, 264 tests passing. Working today: BYO-model `contribute`, the AI-free `pull`/`pack` path,
verifiable GitHub identity across contributions and audits, signed Envelopes, safe `inspect`, the
owner handshake with trust levels, credited `--apply` merges, the reproducible risk seal, the open
format + `extract`, native PR `submit`, the maintainer-side GitHub Action, and an MCP server for
envelope intake. On the roadmap (design-stage): a hosted verify App.

## License

MIT © 2026 Augusto Bastos.
