Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
Commit5e67f6b

fix(vapron): correct receiver URL — /api/hooks/gluecron/push (old path 404s)

fix(vapron): correct receiver URL — /api/hooks/gluecron/push (old path 404s)

Verified live 2026-07-14: Vapron's actual receiver is
POST https://vapron.ai/api/hooks/gluecron/push (401 on unsigned payloads =
route exists). Gluecron's default, wire-contract comment, panel helper text,
and test pins all referenced the pre-move /api/webhooks/gluecron-push, which
now 404s — so default-configured deploy webhooks died silently in retries.
Test pin inverted so a revert fails loudly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ccanty labs committed on July 14, 2026Parent: 16c3343
4 files changed+1275e67f6bf68c1f82edd36af4f2770b9f0d1f5b967
4 changed files+12−7
Modifiedsrc/__tests__/vapron-deploy.test.ts+5−4View fileUnifiedSplit
136136 expect(typeof triggerVapronDeploy).toBe("function");
137137 });
138138
139 it("POSTs to /api/webhooks/gluecron-push (matches Vapron receiver path)", async () => {
139 it("POSTs to /api/hooks/gluecron/push (matches Vapron receiver path, verified live 2026-07-14)", async () => {
140140 const { calls, fn } = captureFetch();
141141
142142 await triggerVapronDeploy(makeArgs(), { fetchImpl: fn, sleep: noSleep });
143143
144144 expect(calls.length).toBe(1);
145145 expect(calls[0]!.url).toBe(
146 "https://vapron.ai/api/webhooks/gluecron-push"
146 "https://vapron.ai/api/hooks/gluecron/push"
147147 );
148 expect(calls[0]!.url).not.toContain("/api/hooks/gluecron/push");
148 // The pre-move path 404s on Vapron now — pinned so a revert fails loudly.
149 expect(calls[0]!.url).not.toContain("/api/webhooks/gluecron-push");
149150 expect(calls[0]!.init.method).toBe("POST");
150151 });
151152
368369 });
369370
370371 it("defaults to the vapron.ai webhook URL and ccantynz-alt/vapron repo", () => {
371 expect(config.vapronDeployUrl).toBe("https://vapron.ai/api/webhooks/gluecron-push");
372 expect(config.vapronDeployUrl).toBe("https://vapron.ai/api/hooks/gluecron/push");
372373 expect(config.vapronRepo).toBe("ccantynz-alt/vapron");
373374 });
374375
Modifiedsrc/hooks/post-receive.ts+3−1View fileUnifiedSplit
406406 *
407407 * Wire contract (matches Vapron's `apps/api/src/webhooks/gluecron-push.ts`):
408408 *
409 * POST https://vapron.ai/api/webhooks/gluecron-push
409 * POST https://vapron.ai/api/hooks/gluecron/push
410 * (path verified live 2026-07-14 — the receiver returns 401 on unsigned
411 * payloads; the pre-move /api/webhooks/gluecron-push now 404s)
410412 * Content-Type: application/json
411413 * X-Gluecron-Signature: sha256=<hex(hmac-sha256(body, GLUECRON_WEBHOOK_SECRET))>
412414 *
Modifiedsrc/lib/config.ts+3−1View fileUnifiedSplit
2020 return (
2121 process.env.VAPRON_DEPLOY_URL ||
2222 process.env.CRONTECH_DEPLOY_URL || // legacy name (pre-rename)
23 "https://vapron.ai/api/webhooks/gluecron-push"
23 // Verified live 2026-07-14: Vapron's receiver is /api/hooks/gluecron/push
24 // (the old /api/webhooks/gluecron-push 404s — Vapron moved it).
25 "https://vapron.ai/api/hooks/gluecron/push"
2426 );
2527 },
2628 /**
Modifiedsrc/lib/system-config.ts+1−1View fileUnifiedSplit
255255 envFallback: "VAPRON_DEPLOY_URL",
256256 label: "Vapron webhook URL",
257257 helper:
258 "Optional: notify Vapron (formerly Crontech) on every push to the canonical repo. Default: https://vapron.ai/api/webhooks/gluecron-push",
258 "Optional: notify Vapron (formerly Crontech) on every push to the canonical repo. Default: https://vapron.ai/api/hooks/gluecron/push",
259259 isSecret: false,
260260 group: "webhook",
261261 },
262262