Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

21 files changed+47−0
Files (21)
modifiedapps/diffinery/package.json+1−0View file
@@ -46,6 +46,7 @@
4646 "react": "19.2.0",
4747 "react-dom": "19.2.0",
4848 "typescript": "^5.9.3",
49+ "undici": "6.23.0",
4950 "vitest": "^4.1.0",
5051 "wrangler": "^4.149.0"
5152 }
modifiedapps/diffinery/test/e2e/accounts.test.mjs+1−0View file
@@ -7,6 +7,7 @@
77 // username waits 90 days), a site administrator deleting someone's account, exporting an account (a tar
88 // archive with a clonable Git bundle and the issues you wrote), and granting and revoking site
99 // administration (signed in recently, audited, never the last site administrator).
10+import "./fresh-connections.mjs";
1011 import { spawn, execFileSync } from "node:child_process";
1112 import { createHash, randomBytes } from "node:crypto";
1213 import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
modifiedapps/diffinery/test/e2e/agent-setup.test.mjs+1−0View file
@@ -12,6 +12,7 @@
1212 // only what a person approved and never a workflow change, turning merging off, and revoke, regenerate
1313 // and renew. gh only talks HTTPS, so a stand-in gh (below) does what gh does with GH_ENTERPRISE_TOKEN and
1414 // GH_HOST; the real gh runs against diffinery.com in the live check.
15+import "./fresh-connections.mjs";
1516 import { spawn, execFileSync } from "node:child_process";
1617 import { createHash, randomBytes } from "node:crypto";
1718 import { chmodSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
modifiedapps/diffinery/test/e2e/agentic.test.mjs+1−0View file
@@ -6,6 +6,7 @@
66 // request waiting for a person, an agent's failing pull request, approvals and
77 // merges moving items between sections, the REST API, the MCP tool, an agent's
88 // own view and the dashboard page.
9+import "./fresh-connections.mjs";
910 import { spawn, execFileSync } from "node:child_process";
1011 import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from "node:fs";
1112 import { tmpdir } from "node:os";
modifiedapps/diffinery/test/e2e/e2e.test.mjs+1−0View file
@@ -8,6 +8,7 @@
88 // check runs, branch protection with required checks and human review for
99 // agent-authored PRs, merging, the REST contents API, the MCP server and
1010 // profile pictures (WASM image processing in the Worker).
11+import "./fresh-connections.mjs";
1112 import { spawn, spawnSync, execFileSync } from "node:child_process";
1213 import { mkdtempSync, writeFileSync, mkdirSync, readFileSync, existsSync, rmSync, openSync } from "node:fs";
1314 import { tmpdir } from "node:os";
modifiedapps/diffinery/test/e2e/early-access.test.mjs+1−0View file
@@ -10,6 +10,7 @@
1010 // identity only applies to requests addressed to this machine.
1111 //
1212 // pnpm --filter @diffinery/app exec node --test test/e2e/early-access.test.mjs
13+import "./fresh-connections.mjs";
1314 import { spawn, execFileSync } from "node:child_process";
1415 import { createHash, randomBytes } from "node:crypto";
1516 import { mkdtempSync, rmSync } from "node:fs";
modifiedapps/diffinery/test/e2e/email.test.mjs+1−0View file
@@ -11,6 +11,7 @@
1111 // through, failed workflow run emails, and the suppression list: signed bounce
1212 // and complaint intake, no email to a suppressed address, lifting it again; the
1313 // morning digest on its schedule (phase 5c) and Today at phone width.
14+import "./fresh-connections.mjs";
1415 import { spawn, execFileSync } from "node:child_process";
1516 import { mkdtempSync, writeFileSync, mkdirSync, existsSync, rmSync } from "node:fs";
1617 import { tmpdir } from "node:os";
addedapps/diffinery/test/e2e/fresh-connections.mjs+19−0View file
@@ -1,0 +1,19 @@
1+// Every fetch in an end-to-end test process gets a connection of its own (imported for that alone).
2+//
3+// wrangler dev closes a keep-alive connection that sits idle for a few seconds, and tests block the
4+// event loop for seconds at a time (execFileSync: `wrangler d1 execute`, git, tar). The close then
5+// waits unread, the next fetch reuses the dead connection and fails with "fetch failed" (other side
6+// closed, UND_ERR_SOCKET), and so does the test. A new localhost connection per request costs well under
7+// a millisecond; Node's fetch and WebSocket use this dispatcher.
8+//
9+// Node's fetch is its own bundled undici, which only works with a dispatcher from the same major
10+// version (undici 7's Agent under Node 22's fetch fails request bodies), so the undici dev dependency
11+// follows Node's: Node 22 bundles undici 6.
12+import { Agent, setGlobalDispatcher } from "undici";
13+import { createRequire } from "node:module";
14+
15+const ours = createRequire(import.meta.url)("undici/package.json").version;
16+if (ours.split(".")[0] !== process.versions.undici.split(".")[0]) {
17+ throw new Error(`apps/diffinery's undici dev dependency (${ours}) must have the major version of the undici in Node ${process.version} (${process.versions.undici})`);
18+}
19+setGlobalDispatcher(new Agent({ pipelining: 0 }));
modifiedapps/diffinery/test/e2e/graphql.test.mjs+1−0View file
@@ -6,6 +6,7 @@
66 // GitHub's error shape.
77 //
88 // pnpm --filter @diffinery/app exec node --test test/e2e/graphql.test.mjs
9+import "./fresh-connections.mjs";
910 import { spawn, execFileSync } from "node:child_process";
1011 import { createHash, randomBytes } from "node:crypto";
1112 import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
modifiedapps/diffinery/test/e2e/moderation.test.mjs+1−0View file
@@ -8,6 +8,7 @@
88 // (or the blocking organization's) repositories but still can everywhere else; a suspended person's
99 // token and session stop at once, their repositories, profile and comments disappear for everyone
1010 // but site administrators, and unsuspending restores it all; a minimized comment shows collapsed.
11+import "./fresh-connections.mjs";
1112 import { spawn, execFileSync } from "node:child_process";
1213 import { createHash, generateKeyPairSync, randomBytes } from "node:crypto";
1314 import { mkdtempSync, rmSync } from "node:fs";
modifiedapps/diffinery/test/e2e/oauth.test.mjs+1−0View file
@@ -7,6 +7,7 @@
77 // client metadata document as the client_id, the consent page (signed out, unknown app, wrong redirect,
88 // cancel, acting as yourself or an agent, admin never preselected), PKCE, codes working once, MCP calls
99 // with the token, refresh rotation and reuse, confidential clients, revocation, and Connected apps.
10+import "./fresh-connections.mjs";
1011 import { spawn, execFileSync } from "node:child_process";
1112 import { createHash, randomBytes } from "node:crypto";
1213 import { mkdtempSync, rmSync } from "node:fs";
modifiedapps/diffinery/test/e2e/passkeys.test.mjs+1−0View file
@@ -11,6 +11,7 @@
1111 // single-use invites and links, and refusing cross-site and token-driven calls.
1212 // Open sign-up (SIGNUP=open) runs on a second Worker: an emailed code, then a
1313 // passkey, and the sign-up pages answering 404 while it is off.
14+import "./fresh-connections.mjs";
1415 import { spawn, execFileSync } from "node:child_process";
1516 import { createHash, createHmac, randomBytes } from "node:crypto";
1617 import { mkdtempSync, readFileSync, rmSync } from "node:fs";
modifiedapps/diffinery/test/e2e/registry.test.mjs+1−0View file
@@ -8,6 +8,7 @@
88 // manifests by tag and digest, indexes, referrers, tag listing, cross-repository mounts,
99 // token scopes, the packages REST API, the job token's `packages` permission, linking
1010 // packages to repositories, and docker login/push/pull.
11+import "./fresh-connections.mjs";
1112 import { spawn, spawnSync, execFileSync } from "node:child_process";
1213 import { createHash, randomBytes } from "node:crypto";
1314 import { mkdtempSync, writeFileSync, mkdirSync, rmSync, existsSync, readFileSync } from "node:fs";
modifiedapps/diffinery/test/e2e/review.test.mjs+1−0View file
@@ -9,6 +9,7 @@
99 // read-only sandbox, autofix pushing to the pull request's branch, the
1010 // re-review marking the finding fixed, Fix it, asking for a review, and the
1111 // spend limits (model requests per review, the repository's daily limit).
12+import "./fresh-connections.mjs";
1213 import { spawn, execFileSync } from "node:child_process";
1314 import { mkdtempSync, writeFileSync, mkdirSync, rmSync, readdirSync, statSync, readFileSync, existsSync } from "node:fs";
1415 import { tmpdir } from "node:os";
modifiedapps/diffinery/test/e2e/security-limits.test.mjs+1−0View file
@@ -3,6 +3,7 @@
33 // invitations by username, per-account quotas, kill switches and the Markdown image proxy.
44 //
55 // pnpm --filter @diffinery/app e2e
6+import "./fresh-connections.mjs";
67 import { spawnSync, execFileSync } from "node:child_process";
78 import { createHash, randomBytes } from "node:crypto";
89 import { writeFileSync } from "node:fs";
modifiedapps/diffinery/test/e2e/security-txt.test.mjs+1−0View file
@@ -5,6 +5,7 @@
55 // audited triage; the other has SECURITY_CONTACT set (every field, the form first).
66 //
77 // pnpm --filter @diffinery/app exec node --test test/e2e/security-txt.test.mjs
8+import "./fresh-connections.mjs";
89 import { spawn, execFileSync } from "node:child_process";
910 import { createHash, randomBytes } from "node:crypto";
1011 import { mkdtempSync, rmSync } from "node:fs";
modifiedapps/diffinery/test/e2e/security.test.mjs+1−0View file
@@ -22,6 +22,7 @@
2222 // merge queue) where a person allowed it and a required check gates it, never by bypass.
2323 // Continued in security-limits.test.mjs (environment reviewers, quotas, kill switches, the image
2424 // proxy), which runs beside this file on a server of its own; the setup is in security-harness.mjs.
25+import "./fresh-connections.mjs";
2526 import { spawnSync, execFileSync } from "node:child_process";
2627 import { createHash, randomBytes } from "node:crypto";
2728 import { mkdtempSync, writeFileSync } from "node:fs";
modifiedapps/diffinery/test/e2e/status.test.mjs+1−0View file
@@ -4,6 +4,7 @@
44 // 404 for everyone else, the audit log, and the hosted compute pause showing as maintenance.
55 //
66 // pnpm --filter @diffinery/app exec node --test test/e2e/status.test.mjs
7+import "./fresh-connections.mjs";
78 import { spawn, execFileSync } from "node:child_process";
89 import { createHash, randomBytes } from "node:crypto";
910 import { mkdtempSync, rmSync } from "node:fs";
modifiedapps/diffinery/test/e2e/tasks.test.mjs+1−0View file
@@ -10,6 +10,7 @@
1010 // security rules: no token, agent or sandbox can start or steer a task, task
1111 // sandboxes are closed to the sandbox API, and a run's model token stops
1212 // working when the run ends.
13+import "./fresh-connections.mjs";
1314 import { spawn, execFileSync } from "node:child_process";
1415 import { mkdtempSync, writeFileSync, mkdirSync, rmSync, readdirSync, statSync, readFileSync, existsSync } from "node:fs";
1516 import { tmpdir } from "node:os";
modifiedapps/diffinery/test/e2e/terminals.test.mjs+1−0View file
@@ -2,6 +2,7 @@
22 // (agents-harness.mjs). In a file of their own so each file stays well under the test runner's per-file limit.
33 //
44 // pnpm --filter @diffinery/app e2e
5+import "./fresh-connections.mjs";
56 import { spawn, execFileSync } from "node:child_process";
67 import { mkdtempSync, writeFileSync, mkdirSync, rmSync, readdirSync, statSync, readFileSync, existsSync } from "node:fs";
78 import { tmpdir } from "node:os";
modifiedpnpm-lock.yaml+9−0View file
@@ -121,6 +121,9 @@
121121 typescript:
122122 specifier: ^5.9.3
123123 version: 5.9.3
124+ undici:
125+ specifier: 6.23.0
126+ version: 6.23.0
124127 vitest:
125128 specifier: ^4.1.0
126129 version: 4.1.11(@types/node@22.20.5)(vite@8.3.4(@types/node@22.20.5)(esbuild@0.25.11)(yaml@2.9.1))
@@ -2184,6 +2187,10 @@
21842187 undici-types@6.21.0:
21852188 resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
21862189
2190+ undici@6.23.0:
2191+ resolution: {integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==}
2192+ engines: {node: '>=18.17'}
2193+
21872194 undici@7.29.0:
21882195 resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==}
21892196 engines: {node: '>=20.18.1'}
@@ -4091,6 +4098,8 @@
40914098
40924099 undici-types@6.21.0: {}
40934100
4101+ undici@6.23.0: {}
4102+
40944103 undici@7.29.0: {}
40954104
40964105 undici@7.29.1: {}