Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

config.ts

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

config.tsBlame184 lines · 2 contributors
fc1817aClaude1import { join } from "path";
2
3export const config = {
4 get port() {
5 return Number(process.env.PORT || 3000);
6 },
7 get databaseUrl() {
8 return process.env.DATABASE_URL || "";
9 },
10 get gitReposPath() {
11 return process.env.GIT_REPOS_PATH || join(process.cwd(), "repos");
12 },
13 get gatetestUrl() {
a4e1564Claude14 return process.env.GATETEST_URL || "https://gatetest.ai/api/events/push";
fc1817aClaude15 },
e883329Claude16 get gatetestApiKey() {
17 return process.env.GATETEST_API_KEY || "";
18 },
9ecf5a4Claude19 get vapronDeployUrl() {
fc1817aClaude20 return (
9ecf5a4Claude21 process.env.VAPRON_DEPLOY_URL ||
22 process.env.CRONTECH_DEPLOY_URL || // legacy name (pre-rename)
5e67f6bccanty labs23 // 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"
fc1817aClaude26 );
27 },
43cf9b0Claude28 /**
9ecf5a4Claude29 * BLK-016 — only fire the Vapron deploy webhook for pushes to this
ba93444Claude30 * `<owner>/<name>`. Every other repo's push is ignored. Override per
9ecf5a4Claude31 * environment via `VAPRON_REPO` (legacy `CRONTECH_REPO` still honored).
ba93444Claude32 */
9ecf5a4Claude33 get vapronRepo() {
34 return (
35 process.env.VAPRON_REPO ||
36 process.env.CRONTECH_REPO || // legacy name (pre-rename)
37 "ccantynz-alt/vapron"
38 );
39 },
40 /**
41 * HMAC secret for signing the outbound Vapron deploy webhook
42 * (`X-Gluecron-Signature: sha256=<hex>`). Resolution order: the
43 * VAPRON_HMAC_SECRET set on /admin/integrations (or env), the legacy
44 * CRONTECH_HMAC_SECRET, then GLUECRON_WEBHOOK_SECRET (the original
45 * env-only name the signer used before the admin field existed).
46 */
47 get vapronHmacSecret() {
48 return (
49 process.env.VAPRON_HMAC_SECRET ||
50 process.env.CRONTECH_HMAC_SECRET ||
51 process.env.GLUECRON_WEBHOOK_SECRET ||
52 ""
53 );
ba93444Claude54 },
e61e6cdccanty labs55 /**
56 * Tenant API key issued by Vapron. When set, every outbound call to
57 * Vapron carries `Authorization: Bearer <key>` — Vapron's tenant model
58 * authenticates callers by API key (the HMAC signature above remains a
59 * payload-integrity check and is sent alongside when configured).
60 */
61 get vapronApiKey() {
62 return process.env.VAPRON_API_KEY || "";
63 },
ba93444Claude64 /**
9ecf5a4Claude65 * Shared HMAC secret for the outbound deploy webhook to Vapron's
ba93444Claude66 * `POST /api/webhooks/gluecron-push` endpoint. Used to compute the
67 * `X-Gluecron-Signature: sha256=<hex>` header on every fire. Default
9ecf5a4Claude68 * empty → header is omitted and Vapron will reject with 401 (treated
ba93444Claude69 * as a failed deploy).
43cf9b0Claude70 */
71 get gluecronWebhookSecret() {
72 return process.env.GLUECRON_WEBHOOK_SECRET || "";
73 },
e883329Claude74 get anthropicApiKey() {
75 return process.env.ANTHROPIC_API_KEY || "";
76 },
24cf2caClaude77 /** Email provider: "log" (dev, writes to stderr) or "resend" (HTTPS). */
78 get emailProvider() {
79 const v = (process.env.EMAIL_PROVIDER || "log").toLowerCase();
80 return v === "resend" ? "resend" : "log";
81 },
82 /** "From" address for outbound email. */
83 get emailFrom() {
84 return process.env.EMAIL_FROM || "gluecron <no-reply@gluecron.local>";
85 },
86 /** Resend API key (only used when EMAIL_PROVIDER=resend). */
87 get resendApiKey() {
88 return process.env.RESEND_API_KEY || "";
89 },
90 /** Canonical base URL for outbound links in emails + webhooks. */
60323c5Claude91 /** SSH server port. 0 disables SSH (default 2222 in dev, 22 in prod via SSH_PORT). */
92 get sshPort() {
93 const v = process.env.SSH_PORT;
94 if (v === "0") return 0;
95 return Number(v || 2222);
96 },
97 /**
98 * PEM-encoded Ed25519 (or RSA) private key for the SSH host.
99 * If unset, an ephemeral key is generated on startup (fine for dev,
100 * but clients will see "host key changed" warnings on restart —
101 * set SSH_HOST_KEY in production).
102 *
103 * Multi-line keys in env vars: use literal newlines or \\n escapes,
104 * both are normalised in ssh-server.ts.
105 */
106 get sshHostKey() {
107 return process.env.SSH_HOST_KEY || "";
108 },
24cf2caClaude109 get appBaseUrl() {
110 return (process.env.APP_BASE_URL || "http://localhost:3000").replace(
111 /\/+$/,
112 ""
113 );
114 },
845fd8aClaude115 /**
116 * Root directory for OCI container registry blob + manifest storage.
117 * Layout:
118 * ${ociStorePath}/blobs/sha256/<hex64> — finished layer/config blobs
119 * ${ociStorePath}/manifests/<name>/<ref> — image manifests by tag or digest
120 * ${ociStorePath}/uploads/<uuid> — in-progress chunked uploads
121 */
122 get ociStorePath() {
123 return process.env.OCI_STORE_PATH || join(process.cwd(), "oci-store");
124 },
1df50d5Claude125 /**
126 * Base URL used to construct preview URLs for PR builds.
127 * When set, the preview-builder will run and serve static files; when unset,
128 * previews are URL-only (no build runs).
129 *
130 * Production: set to e.g. "https://previews.gluecron.com"
131 */
132 get previewDomain() {
133 return process.env.PREVIEW_DOMAIN || "";
134 },
2df1f8cClaude135 /**
136 * WebAuthn relying-party ID (domain only, no scheme/port). Derived from
137 * appBaseUrl unless overridden. Passkeys issued for one RP ID can't be
138 * replayed against another, so this must be stable.
139 */
140 get webauthnRpId() {
141 if (process.env.WEBAUTHN_RP_ID) return process.env.WEBAUTHN_RP_ID;
142 try {
143 return new URL(this.appBaseUrl).hostname;
144 } catch {
145 return "localhost";
146 }
147 },
148 /** WebAuthn expected origin (must include scheme + port). */
149 get webauthnOrigin() {
150 return process.env.WEBAUTHN_ORIGIN || this.appBaseUrl;
151 },
152 /** Human-facing RP name shown by the browser. */
153 get webauthnRpName() {
154 return process.env.WEBAUTHN_RP_NAME || "gluecron";
155 },
13cbd17Claude156 /**
157 * Redis / Valkey connection URL for cross-instance SSE fan-out.
158 * When set, `src/lib/sse.ts` uses Redis pub/sub so SSE events reach all
159 * server instances behind the load balancer. Falls back to in-process
160 * delivery when unset.
161 */
162 get redisUrl() {
163 return process.env.REDIS_URL || process.env.VALKEY_URL || "";
164 },
6efae38Claude165 /**
166 * AI Auto-Issue Opener (src/lib/ai-auto-issues.ts). When set to "1",
167 * every git push is scanned for TODOs, hardcoded secrets, SQL injection
168 * patterns, and debug console.log calls; matching findings automatically
169 * open issues in the repository. Off by default.
170 */
171 get aiAutoIssues() {
172 return process.env.AI_AUTO_ISSUES === "1";
173 },
da3fc18Claude174 /**
175 * Dependency CVE scanner — when set to "1", the post-receive hook fires
176 * `scanDependencies()` on every push that touches a recognized manifest
177 * file (package.json, requirements.txt, Cargo.toml, go.mod, Gemfile).
178 * Results open security issues automatically. Fire-and-forget; never
179 * blocks a push.
180 */
181 get dependencyScanEnabled() {
182 return process.env.DEPENDENCY_SCAN_ENABLED === "1";
183 },
fc1817aClaude184};