/architecture
How the agentactually works.
Five zones, twenty-six components, one rule: content from the outside world is data, never instruction. Every arrow below is a real call in the codebase, and every record it produces is persisted before anyone sees it.
01
System map
Hover any component to see its inputs, outputs and the trust boundary it enforces. Dashed zones hold untrusted data; the solid zone is the only place code runs.
02
One run, end to end
From a scheduler tick to a verified merge. Steps 01 to 09 happen inside a single run; 10 to 15 arrive later as signed webhooks.
03
Patch state machine
A patch's id is a fingerprint of repository, campaign and exact edits. Any fingerprint in a terminal state is skipped on later runs, which is what makes the worker idempotent.
04
Trust boundaries
Where each kind of input is allowed to go, and what stops it going further.
Repository content
Parsed by fixed regexes and a strict schema. Never executed, never sent to a model, never rendered as HTML. A README saying “ignore previous instructions” changes nothing (tested).
Advisory text
Control characters stripped, length capped, rendered as plain text. Raw hash stored so changes are detectable.
Webhooks
HMAC-SHA256 over the raw body with constant-time comparison before JSON is parsed. Only patch-agent/* branches are acted on.
Writes to GitHub
Only after installation + policy + validator. New branch only, never the default branch. One flag disables all writes.
05
Technology
Boring, inspectable choices. No WebGL, no model in the write path.
- Web
- Next.js 15 · React 19 · Tailwind 4
- Server-rendered pages so crawlers and AI evaluators can read everything without running JS.
- Realtime
- Server-Sent Events
- One in-process bus; every event is persisted before it is broadcast.
- Data
- Postgres (Neon) · Prisma 6
- 15 tables. Events, patches, source records with raw hashes, authorizations.
- Scheduling
- node-cron · external cron
- */15 in-process plus a bearer-protected backup trigger; single-flight runs.
- GitHub
- GitHub App · REST v3
- JWT → installation tokens. Serialised, spaced calls with rate-limit back-off.
- Advisories
- NVD 2.0 · GHSA · CISA KEV · php.net
- Merged into one schema, provenance kept per provider.
- Validation
- zod · yaml (aliases off)
- Strict .patchbot schema; unknown keys rejected; no command fields exist.
- Treasury
- Solana JSON-RPC (read-only)
- Public address only. No key material anywhere in the codebase.
06
Data model
Everything the public pages show is a query over these tables. See prisma/schema.prisma.
- AgentEventid · timestamp · eventType · dataMode · message · cveId · repositoryId · patchId · metadata · verificationUrl
- Patchid (fingerprint) · stage · repository · cveIds · changes · branch · prUrl · commitSha · ci · detected/matched/generated/prOpened/merged
- CVE / SourceRecordid · severity · cvss · firstSeenAt ⟶ provider · providerRecordId · sourceUrl · retrievedAt · rawHash
- Repository / Authorizationowner/repo · installationId ⟶ source (github-app | patchbot) · active · policy · granted/revoked
- TreasuryTransaction / ComputeExpensesignature · direction · lamports ⟶ category · amount · period · evidence
07
Every component, in text
The same information as the system map, for screen readers, crawlers and anyone who prefers a list.
NVD CVE API 2.0
Authoritative CVE records: description, CVSS, references. Untrusted text, stored and rendered as plain text only.
GitHub Advisories /advisories?cve_id
Ecosystem-level affected packages and version ranges. Untrusted; merged with provenance kept per provider.
CISA KEV known exploited feed
Flags whether a CVE is known to be exploited in the wild. Untrusted; hashed per entry.
php.net releases releases JSON
Latest release per branch. Confirms fixed versions exist. Never lowers a fixed version.
node-cron */15 * * * *
In-process scheduler started from instrumentation.ts. Single instance only.
Backup cron POST /api/internal/run
External cron with a bearer token, in case the in-process timer stalls. Constant-time token check; 503 if unset.
Install webhook installation_repositories.added
Runs immediately for newly added repositories. HMAC-verified before parsing.
Ingest + normalize providers.ts · lookupCve()
Queries every provider, merges into one schema, diffs raw hashes against stored SourceRecords. Provider failures become agent.error events; nothing is guessed.
Fixed-version table php-releases.ts
Branch → first fixed release (8.5.12, 8.4.27, 8.3.36, 8.2.35), cross-checked with php.net. Seed table labelled as SEED when php.net is unreachable.
Single-flight runner runAgent()
One run at a time. Overlapping triggers return immediately. Errors in one repo never stop the run.
Orchestrator agent.ts · processRepo()
Lists installations, mints installation tokens, walks each repo's git tree (≤ 40 files, ≤ 256 KB). Only repos inside an App installation are ever read.
Matcher / planner patcher.ts · planFile()
Finds explicit php:X.Y.Z pins in Dockerfile, compose, CI and composer config.platform.php. Floating tags are ignored. Fixed regexes only. Repository text never reaches a model.
Safety validator safety.ts · validateChange()
File allowlist, unchanged line count, ≤ 20 changed lines, secret and dangerous-content scan. Rejected changes become patch.rejected events.
Policy gate policy.ts · mayWrite()
App installed? .patchbot valid and enabled? Severity and patch type allowed? Invalid .patchbot fails closed. Schema has no command fields.
PR writer github.ts · openPullRequest()
Creates a patch-agent/* branch, one commit per file, opens a PR with the exact diff and sources. Never pushes to the default branch. Disabled unless GITHUB_WRITES_ENABLED=true.
CI + merge tracker webhooks/github · checkSummary()
Aggregates check runs for agent branches; records merges and closes. Only branches under patch-agent/* are considered.
Postgres (Neon) Prisma · 15 tables
Events, patches, source records, authorizations. Every record is written before it is broadcast. DEMO rows are rejected before reaching the database.
Event bus → SSE /api/v1/stream
In-process pub/sub fan-out to every open browser. Same events the ledger stores, nothing extra.
Health probes health.ts
Live probes of NVD, GitHub, App, RPC, plus SELECT 1 on Postgres and last worker run. Nothing is reported operational unless a probe passed.
App installations /app/installations
The opt-in list. Installation is the authorization. Least privilege: metadata r, contents rw, PRs rw, checks r.
Repo tree + blobs git/trees · git/blobs
Read-only fetch of candidate files and .patchbot. Content treated as data; prompt-injection text has no effect.
patch-agent/* PR branch · commit · pull
The only write the agent makes. Maintainers review and merge; the agent never merges.
Repository CI check runs
The repo's own tests run on the PR branch, in the repo's own CI. No repository code executes on the agent's server.
Signed webhooks X-Hub-Signature-256
Installation, PR, check_suite and check_run events back to the agent. Unsigned requests are rejected with 401.
/proof REAL-only ledger
Every action with an external link: PR, checks, NVD. DEMO can never appear here.
/status.json computed health
Machine-readable service state and capabilities. Computed per request (30 s cache).
/live SSE stream
Watch transitions as they happen. Read-only.
llms.txt for AI evaluators
Plain facts and evidence URLs for external agents. No marketing.
Next: methodology · security model · live status