Standard terms, under counsel review; effective as posted. Counsel's edits replace this draft when they arrive; this line comes off then.

Legal — Privacy

Privacy Policy

Effective as posted. Contact: legal@corund.dev

Scope, and how to read this page

This policy covers the Corund GitHub App at app.corund.dev, the marketing site at corund.dev and its waitlist, and what Corund posts back to GitHub. Corund is operated by Grade-Inc. [FLAGGED: the legal entity's name and place of organisation are an attorney item — the Corund / Grade-Inc structure]

Every sentence on this page that says what Corund does with data was written against the code that does it, at a named commit, and the repository's test suite holds the page and that record to the same set of statements. A sentence carrying a [FLAGGED ...] mark describes something the code does not yet settle; it is a draft, not a fact.

The open-source Corund Action runs inside your own CI and publishes its results as a GitHub check run; the App reads those results from GitHub, so the Action has no reason to call Corund's servers. [FLAGGED: the Action is a separate codebase; this sentence was not verified against it]

1. When you install the App

Installation record. When the App is installed, GitHub sends Corund a signed webhook and Corund stores the installation's id, the account's numeric id, login and type (user or organisation), the time, and — if GitHub later suspends the installation — the suspension time.

Repository record. For each repository you grant, Corund stores GitHub's repository id, its full name, whether it is private, and its default branch; for a private repository it also mints a random badge token so that only someone holding the token can load its README badge.

Settings you enter. Corund stores what you type into a repository's settings: the loud-skip allowlist, the required-path map, which of the four checks are enabled, and which rules may block. On plans with org auto-enable, a newly added repository inherits the installation's most recent settings.

Membership. The person who installs the App becomes its owner; roles are owner, admin and member, one per person per installation, with a record of who granted each.

Webhook ledger. Corund verifies GitHub's signature over the raw body before it parses anything, then records each delivery once: its delivery id, event, action, installation id, the time, and a SHA-256 hash of the payload. The payload itself is never stored.

What the App may read on GitHub. The App is registered with the permissions checks: write, pull_requests: read, contents: read and metadata: read. It has no write access to your code. [FLAGGED: the App asks the owner for pull_requests: write (to post its receipt as a PR comment) and administration: read (to read classic branch protection for C3); until that word is given the comment is recorded as permission_missing and C3 reads rulesets only]

2. When you sign in

Sign-in is GitHub OAuth with the read:user scope. Corund keys your account on GitHub's immutable numeric user id and caches your login and display name for the screen only; neither is used to decide what you may see. Corund does not store your email address.

Audit log. Sign-ins, membership changes and internal failures are appended to an audit log: the time, the acting account's internal id, the installation, the action name, a target, and a short detail (for example the reason a webhook handler crashed).

3. When a pull request is opened or updated

Run record. Each pull-request event creates a run row: the PR number, the PR author's numeric id, account type and login (login for display only), whether the repository was private at run time, head and base commit SHAs and the base branch name, the triggering event, the run's state, the ids of the check runs Corund created on GitHub, a snapshot of the branch's required status checks (for C3), whether the receipt comment could be posted, any error text, the receipt's content hash, the Corund build that produced it, and timestamps.

What Corund reads during a run. Using a short-lived installation token, the App reads from GitHub: the repository's metadata; the pull request; the pull request's diff (C2); its reviews — reviewer id, state and the commit each approval was given for (C4); the check runs on the head commit, to find the red-on-revert results the Corund Action published (C1); branch rulesets or classic branch protection and the workflow files under .github/workflows at base and head (C3); the policy file .github/corund.yml at the base branch; and the pull request's existing comments, to update Corund's own comment in place.

Transient means this. Those inputs live in the process's memory for the length of that one run, are handed to the check core, and are discarded when the run ends. The diff, the workflow files, the per-test pass/fail maps and the policy text are not written to Corund's database or to any file store; Corund has no object storage. What persists from a run is the run record above and the receipt rows below.

Corund's servers never execute your tests. The red-on-revert results C1 needs are produced by the Corund Action inside your own CI and read back from its check-run output on GitHub; if the Action has not run for a commit, C1 reports NOT_RUN and says why.

Receipt rows. For each of the four checks, Corund stores the check id, its verdict, the UNPROVEN reason where one applies, the base, head and approval SHAs, the time, and a free-text detail: the evidence lines the check produced, or the text of the exception if it crashed. Those lines can name file paths, test identifiers and skip sites. [FLAGGED: the evidence lines are written by the check core, a separate codebase; the receipt has no field for file contents, but the lines are free text and were not verified line by line]

Receipt integrity. When a run finishes, Corund stamps it with a SHA-256 over the receipt's canonical rows, the Corund build id and a fingerprint of the code that produced it, so a reader can later check that a receipt has not been altered.

What Corund posts to GitHub. The receipt goes back to GitHub as four check runs (each with a title, summary and the check's detail text) and as one pull-request comment that later runs update in place. Every posting carries a link to the receipt's permalink.

Receipt permalinks. A receipt at /r/<id> is public, with no sign-in, when the repository was public at run time; a private repository's receipt is visible only to signed-in members of that installation. Any other request gets the same not-found answer, so ids cannot be probed.

When something breaks. If a run crashes, the exception's text is stored on the run and on a CRASHED receipt for each check that has none, and one structured failure line is logged. Corund never turns a crash into a passing result.

4. Replay

On install, and whenever an owner or admin asks, Corund replays a repository's most recent merged pull requests (50 by default) through the four checks, read-only, building the same inputs as a live run and posting nothing to GitHub. It stores one row per pull request and check: the PR number, merge SHA, check id, verdict, reason, whether a block rule would have fired, the evidence lines with the SHAs, and any true- or false-positive mark an operator sets, with that operator's account id and the time. The replay export you can download is built from those stored rows only.

5. The README badge

A badge request returns one word derived from the latest finished run on the default branch. Each time a badge is served Corund records an event with the word, the installation and the repository; nothing about the viewer is recorded. A private repository's badge needs its token.

6. Product events and metrics

Corund keeps an append-only events ledger — install, uninstall, run started, run finished, fake green caught, badge served, replay started and finished, and operator overrides — with the installation id, repository id, time and a small payload of kinds, states and numeric ids. The writer refuses any payload key that looks like a login, name, email, token or secret. Corund's own metrics page is derived from this ledger and is visible only to Corund's administrators, identified by numeric GitHub id.

Seat counts and the product-qualified-lead signal are derived from the same records: the distinct people who authored pull requests on the installation's private repositories in the trailing 90 days, counted by numeric id, with bot accounts excluded and a 48-hour grace period for a newly seen author. Reaching the lead threshold is recorded once per installation.

Corund also keeps a global list of citations — URLs of articles, repositories and posts that link to Corund, entered by an administrator or imported from a CSV. It names no customer and holds no customer data.

7. Cookies and sessions

The App sets two cookies and no others: corund_session (HttpOnly; Secure when served over HTTPS; SameSite=Lax; path /; expires after 30 days) carrying a random session token, and corund_gh_oauth_state (same flags; path /auth/github; expires after 10 minutes) carrying the sign-in flow's anti-forgery state. The marketing site at corund.dev sets no cookies at all. There are no advertising or analytics cookies anywhere, which is why there is no cookie banner.

Only a SHA-256 hash of the session token is stored, never the token. A session ends after 30 days at most, sooner when idle — 12 hours for an owner, 24 hours for an admin, 7 days for a member — the moment any of your roles changes, or when you sign out.

8. Logs

Each request is logged with its method, path, status and duration and an 8-character prefix of a salted SHA-256 hash of the client IP address (the salt is a server secret); never the raw IP address, headers, cookies, request bodies or query strings. A failure is logged as one structured line with a request id, the method, the matched route pattern, the path, the status, the installation id if the route named one, and the exception's class name; the logger refuses fields whose names look like a token, secret, cookie, password, header or body. Every response carries an X-Request-ID header so you can quote a request to us.

Application logs are held by our hosting provider. [FLAGGED: the log-retention window is set on the hosting side and is not in Corund's code; the owner has not yet named a period]

9. The marketing site and the waitlist

The pages at corund.dev are static files. They are built for and served by Cloudflare Pages, which sees the requests for them. [FLAGGED: the Cloudflare deployment is a step the owner performs; until then the same files are served by the Railway web host]

The waitlist endpoint on the Railway web host (POST /api/waitlist) stores the email address you submit (normalised to lower case), a short source tag, the salted IP hash described above, up to 256 characters of your browser's User-Agent string, and the time. A duplicate address is silently ignored; a submission that fills the hidden honeypot field is answered but stores nothing; the endpoint is rate-limited per IP address in memory.

On the published marketing site the waitlist button is a mail link to hello@corund.dev. [FLAGGED: mail sent there is handled by the owner's mail provider, which is outside Corund's code]

Today, both the marketing pages and the App's pages load their typefaces from Google Fonts, so your browser requests fonts.googleapis.com and fonts.gstatic.com directly and Google receives those requests, including your IP address. If those hosts are unreachable the pages fall back to system fonts. [FLAGGED: RULED — the App will self-host these fonts on app.corund.dev instead of loading them from Google; that work is pending lane B and has not shipped yet, so this page still describes what the App does today]

10. Billing

Paid plans are billed through Stripe. Checkout happens on Stripe's hosted page. To start it, Corund creates a Stripe customer named after the installation's GitHub account login, tagged with the installation id and the GitHub account id, and opens a checkout session that carries the installation id, the plan's prices and seat quantity, and the return addresses. Corund sends Stripe no email address and never sees, asks for or stores a card number; whatever you type on Stripe's page goes to Stripe.

Billing is not switched on yet. [FLAGGED: the billing code exists and is tested, but it is not yet mounted in the App; this section describes what it does when it is]

What Corund keeps from Stripe. The Stripe customer id; for each subscription its id, item id, price id, plan, billing interval, seat quantity, Stripe's own status word, current period start and end, whether it is set to cancel at period end, when it entered past-due, any add-ons, and the status and time of the last invoice; a billing-events ledger of checkout completed, subscription created or cancelled, seats added or removed, and lead reached, each with the ids, plan, quantity and status involved; and a trial record with its start and end dates.

Stripe's webhooks. Corund verifies Stripe's signature over the raw body before parsing, processes each event once, and records only the event's id, type, the installation it resolved to, a SHA-256 hash of the payload, and the outcome. The payload itself is never stored.

Seats are measured at billing time from the private-repository authorship described in section 6; Corund never lowers a subscription's quantity on its own, and by default reports rather than changes it.

Stripe's handling of your payment details is governed by Stripe's own privacy policy at stripe.com/privacy and its data processing agreement at stripe.com/legal/dpa.

11. No training on your code

Corund does not use your code, diffs, test results or receipts to train, fine-tune or evaluate any machine-learning model, its own or anyone else's, and nothing in the App sends customer content to a model provider. No model takes part in a verdict: each of the four checks is a deterministic comparison, and a check that could not run says so.

12. Subprocessors and other third parties

Three companies process data on Corund's behalf. Each is wired into the code or the deployment configuration named below, and the repository's tests refuse a change that adds one to this list without the other, or to the other without this list.

ProviderWhat it does for CorundWhat it receivesWhere it is wiredIts terms
RailwayHosts the App and the web host and provides their Postgres databaseEverything this policy says Corund stores or logsscripts/deploy_lib.sh, railway.tomlrailway.com/legal/privacy, railway.com/legal/dpa
StripePayments, subscriptions, the customer portalWhat section 10 lists; the payment details you enter on Stripe's pageapp/corund_app/billingstripe.com/privacy, stripe.com/legal/dpa
GitHubThe platform Corund runs on: installation and pull-request webhooks, the API reads in section 3, OAuth sign-in, and the check runs and comments Corund postsThe receipt (check runs and one PR comment) and the API requests the App makes with its installation tokenapp/corund_app/webhooks_github.pyGitHub privacy statement

Your browser also contacts two hosts on its own when it loads a Corund page: Google Fonts (section 9) and, for the marketing site, Cloudflare Pages (section 9). Neither receives customer content from Corund.

13. Retention and deletion

Corund keeps the records above for the life of the account. We commit to purging them within 30 days of account deletion; the automated purge is being built and this page will say when it is live. [FLAGGED: no automatic purge is implemented yet for runs, receipts, replay rows, events, audit rows or sessions; 30 days is the target the code will honor once built, not a measurement of what it does today]

Deletion. Uninstalling the App on GitHub, or an installation owner pressing delete in the App's settings, deletes the installation's data in one pass and in this order: billing events, billing webhook ledger, subscriptions, trials and billing customer; check receipts; jobs; replay items and replay runs; runs; repository settings; repositories; the webhook ledger; audit rows carrying the installation id; memberships; and finally the installation record itself.

What survives a deletion. Rows in the events ledger are anonymised rather than deleted — the installation id, repository id and payload are set to null and only the event kind and time remain, so install counts never shrink because a tenant left. Your own account record (GitHub numeric id, login, display name) and your sessions survive, because they may belong to other installations; audit rows that name no installation, such as sign-ins, survive too. Stripe keeps its own records under its own retention. [FLAGGED: there is no code path that deletes an account record; a request to delete one is handled by hand]

Billing records on uninstall. [FLAGGED: the billing design says billing rows are retained on uninstall and the Stripe subscription is set to cancel at period end; the App's uninstall handler as written deletes the billing rows with everything else and does not yet call the cancel step. Which behaviour ships is the owner's decision; until then nothing here is promised]

An expired or revoked session is refused but its row is not purged.

14. Security

GitHub and Stripe webhooks are authenticated over the raw body before anything is parsed. Session tokens are stored hashed. A request for an installation you do not belong to gets the same not-found answer as one that does not exist. The App holds the least GitHub permission its checks need. Every response carries strict transport security, a content-security policy with no third-party script hosts, and frame denial. Report a suspected vulnerability privately to security@corund.dev; the repository's SECURITY.md has the details.

15. Your choices

Write to the contact address above to access, correct or delete information Corund holds about you, or with any privacy question. Corund serves business customers; where regional privacy rights apply to you, they are honoured as the law requires. [FLAGGED: regional-rights language is counsel's to write]

Corund is not directed at children and does not knowingly collect information from them. [FLAGGED: counsel to confirm the age threshold and wording]

16. Changes

Changes to this policy take effect when posted here; the version served is the one in force. [FLAGGED: Corund stores no email addresses for App users, so notice of a material change would have to be given inside the App or on GitHub; the owner has not yet chosen the mechanism]