Files
zooqueen 252e1cb076 Generated clients call the API where it is mounted
`insights/mount.py` is explicit: `/v1/` is the mount and `/api/` is the older
spelling, kept on the wire for released CLI builds and personal-API-key
holders and rewritten once at the edge by `ApiRewriteMiddleware`. Our own
frontend was still on the older spelling: the orval clients were generated
two days before the mount moved and the move did not regenerate them, so 70
files and 2323 paths said `/api/`.

That is not only a spelling. `prepareUrl` in `lib/api.ts` rewrites `/v1/*` to
the selected region's host in OAuth mode and nothing else, because that is
what the cloud CORS allowlist covers — so every generated call quietly stayed
same-origin, and `getExportsContentRetrieveUrl` builds an `<img src>` that
never reaches `lib/api.ts` at all.

The clients are regenerated from a spec that needs postgres, the datastore and
Django, so this is the path strings only, which is the whole of what the mount
move changes in them: orval copies paths verbatim from the spec, and the spec
takes them from the URLconf. Doc comments carried the same stale prefix and
move with them; their Python docstrings already say `/v1/`. The two frozen
OAuth client-metadata paths are identifiers rather than API surface and appear
in none of these files.

The Slack task prompt told the agent to POST to
`$INSIGHTS_API_URL/api/projects/...`, which is a live request path, not prose.
2026-08-24 23:13:08 -07:00
..

Stamp

Approve-first PR review: an LLM reviewer that runs deterministic gates plus a scoped review over a pull request and, when the policy allows it, posts an actual GitHub approval — not just comments. Repos opt in per-repo; everything else stays untouched.

Two runtimes, one engine

The review engine lives in tools/pr-approval-agent/ and runs in two places:

  • GitHub Action — runs in the repo's own CI with the repo's own secrets (review_pr.py).
  • Hosted (this product) — a GitHub App delivers webhooks here; reviews run in an isolated Modal sandbox with per-run minted credentials (review_local.py consumes a pre-fetched context, no GitHub token inside the sandbox).

Hosted flow: webhook → Celery (backend/tasks/tasks.py) → Temporal (backend/temporal/workflow.py) → sandboxed engine → verdict posted back (post_verdict). The workflow dismisses stale approvals first, waits out other in-flight reviewer bots, then reviews.

There is one non-webhook entry: self-driving inbox PRs. When a self-driving Inbox implementation run opens its (bot-authored, draft) PR, review's inbox receiver calls the queue_inbox_pr_review facade — gated by the assigned reviewers' per-user stamp_review_inbox_prs toggles on Review's settings (any opted-in reviewer is enough) — and the initial review runs while the PR is still a draft so the verdict is ready at Inbox triage time. Later pushes re-review through the normal webhook path via a positively identified carve-out (task linkage through the tasks facade, toggle re-checked through facade/inbox_hooks.py); every other bot author stays refused at every layer. See AGENTS.md § the self-driving carve-out.

The digest

Independently of reviews, a repo can enable a daily Slack digest of its merged PRs (backend/tasks/digest.py): merges are stamped with an audience (author's GitHub team, or a channel the repo declares under digest: in .stamp/policy.yml), summarized with a small model, and posted per channel. Review-enabled repos digest only stamp-approved merges; digest-only repos (review off) digest every merge.

Configuration

Per-repo settings live on StampRepoConfig (synced via the GitHub App install flow, managed in the Stamp scene): review on/off, review mode (auto vs trigger label), digest on/off. Review policy (gates, deny-lists, tiers, ownership) is read from .stamp/policy.yml on the repo's default branch — never from the PR head — layered over hosted defaults in backend/logic/policy_defaults/.

Security model, in one paragraph

The sandbox runs an LLM over untrusted PR content, so it holds no long-lived secrets: it gets a per-run OAuth token (scoped to llm_gateway:read + the server-mint marker) that only works against the gateway's stamp route, egress is fenced to an explicit domain allowlist, posted bodies are scrubbed and markdown-image-neutralized, and approvals are governed by a strict supersession protocol so no approval survives events it shouldn't (pushes, re-reviews, repo disable). Details and invariants: AGENTS.md.