> Call POST /v1/check before a tool that writes. DENY means do not invoke the tool. For clean Markdown of any page, append .md to the page URL. For the complete index, fetch https://docs.withwrit.com/llms.txt.

# GitHub App

> Install the Writ scanner on selected GitHub repositories. Every push and pull request is scanned for ungated write-sites; results appear in GitHub as a neutral check run and in the Writ portal.

# GitHub App

The Writ GitHub App is the scanner's one-click install path. After a tenant
admin installs it on selected repositories, every push to the default branch
and every pull request triggers a Writ scan of the exact commit.

## What the app does

* Scans the repository at the exact commit SHA using the same `pywrit`
  scanner that powers `writ scan`.
* Classifies write-sites as gated or ungated.
* Stores a scan manifest in the same scan manifest store as CI scans.
* Computes drift against the previous scan of that repo.
* Posts a GitHub check run named **Writ** on pull requests and on the head
  commit of a push.
* Surfaces findings in the Writ portal under **Integrations / GitHub**.

The check run is **informational only** in this build: it does not block or fail
a pull request. It reports the findings count, ungated count, Writ Score, and
drift headline.

## Permissions

The app requests exactly these repository permissions:

| Permission    | Level     | Why                                                                                            |
| ------------- | --------- | ---------------------------------------------------------------------------------------------- |
| Contents      | Read-only | Fetch code at an exact commit for the scan job.                                                |
| Metadata      | Read-only | Repo list, default branch, and language stats.                                                 |
| Checks        | Write     | Post the Writ check run on PRs and head commits.                                               |
| Pull requests | Write     | Only for the optional PR comment feature (default off). It can comment; it cannot change code. |

Subscribe to these webhook events: `installation`, `installation_repositories`,
`push`, `pull_request`, and `marketplace_purchase`.

## Consent and data handling

Installing the app is a consent moment. The installation record captures the
accepted Terms version, the installer, the GitHub account, and the selected
repositories. The app honors the tiered data strategy in the Terms:

* **Tier (i): Outcomes.** Receipts and decision metadata contain no customer code.
* **Tier (ii): Free and self-serve (this app).** Scan findings, extracted
  features, and de-identified snippets around write-sites are usable by Writ
  under the Terms' product-improvement license. The trade is explicit: free
  tooling, and the findings improve the model for everyone.
* **Tier (iii): Raw code.** Never stored, never trained on without a separate
  explicit opt-in. The scan reads code into ephemeral storage and discards it.
  Findings travel; code does not.
* **Tier (iv): Enterprise.** The DPA carries the carve-out; opt-in only,
  enforced by a tenant flag.

Consent rules the implementation honors:

* **Consent precedes scanning.** No scan runs before an installation record
  exists with the accepted Terms version on file. If the Terms version is
  stale, scanning pauses for that installation until the new version is
  accepted: fail-closed on consent.
* **Deletion is honored forward.** On customer request, that customer's tier
  (ii) artifacts are excluded from future dataset versions and blocked from
  re-ingestion. The portal disconnect screen offers this in one click.
* **Scrub before persistence.** Everything entering storage is secret-scrubbed
  and de-identified before a row exists.
* **No silent tier movement.** Nothing in this build moves data to a more
  permissive tier.

## Optional PR comment

An installation-level setting controls whether the app also posts a summary
comment on pull requests. It defaults to **OFF**. When enabled, the app posts
one comment per PR and updates it in place on `synchronize` events.

## Marketplace readiness

The app is designed to work end-to-end before the Marketplace listing exists.
The required legal/support URLs are already live:

* Privacy policy: [https://withwrit.com/privacy](https://withwrit.com/privacy)
* Terms: [https://withwrit.com/terms](https://withwrit.com/terms)
* Support: [hello@withwrit.com](mailto:hello@withwrit.com)

Marketplace `marketplace_purchase` events are acknowledged and recorded but
never crash the handler or trigger scans. Billing and plan handling are
managed on the operator side; the app treats free-plan purchases as normal
active installations.