PR Annotator Service
File: src/main/services/pr-annotator.ts
Posts Latch attestation session receipts as structured Markdown comments on GitHub pull requests. Uses the GitHub REST API directly (no SDK dependency).
API
parsePrUrl(url: string): PrUrlParts | null
Extracts owner, repo, and prNumber from a GitHub PR URL of the form https://github.com/{owner}/{repo}/pull/{number}. Returns null for non-GitHub URLs or malformed paths.
formatReceiptComment(receipt: SessionReceipt): string
Formats a SessionReceipt as a Markdown PR comment body containing:
- Header with policy ID and data tier
- Markdown table with activity metrics (network requests, blocked requests, redactions, tokenizations, tool calls, tool denials, sandbox type, duration, exit reason)
- Collapsible
<details>section with cryptographic proof (Merkle root, audit event count, truncated signature and public key) - Footer linking to Latch Desktop
annotatePR(receipt: SessionReceipt, prUrl: string, githubToken: string): Promise<{ ok, commentUrl?, error? }>
Posts the formatted receipt comment on a GitHub PR. Steps:
- Parses the PR URL with
parsePrUrl - Formats the receipt with
formatReceiptComment - POSTs to
https://api.github.com/repos/{owner}/{repo}/issues/{prNumber}/comments - Returns the
html_urlof the created comment on success
Headers sent: Authorization: Bearer {token}, Accept: application/vnd.github+json, X-GitHub-Api-Version: 2022-11-28.
GitHub Token Resolution
The IPC handler (latch:attestation-annotate-pr in src/main/index.ts) resolves the GitHub token from the secrets store under the key service:github. It attempts to parse the stored value as JSON (extracting .token or .apiKey) and falls back to the raw string value.
Comment Format
The generated Markdown comment has this structure:
## Latch Attestation
Policy and tier summary line.
| Metric | Value |
|--------|-------|
| Network requests | ... |
| Blocked requests | ... |
| ... | ... |
<details>
<summary>Cryptographic proof</summary>
- Merkle root, audit event count, signature, public key
</details>
---
*Generated by Latch Desktop*
Testing
- Test file:
src/main/services/pr-annotator.test.ts - Test count: 6 tests
- Run:
npx vitest run src/main/services/pr-annotator.test.ts
Tests cover: URL parsing (valid and invalid), policy ID inclusion, activity metrics inclusion, Merkle root inclusion, and sandbox type inclusion in the formatted comment.