{ "$schema": "node_modules/wrangler/config-schema.json", "name": "gitfor", "compatibility_date": "2026-10-08", "compatibility_flags": ["nodejs_compat"], // Sites: one wildcard route, first-level labels only, so Universal SSL covers every site and preview. "routes": [ { "pattern": "gitfor.dev", "custom_domain": true }, { "pattern": "editor.gitfor.dev", "custom_domain": true }, { "pattern": "gitforusers.dev", "custom_domain": true }, { "pattern": "*/*", "zone_name": "gitforstatic.dev" } ], "main": "src/server.ts", "observability": { "enabled": true }, // Optional Stripe billing (docs/billing.md). Leave unset to self-host without billing; nothing requires Stripe. // Set with `wrangler secret put` (or .dev.vars locally; see .dev.vars.example): // STRIPE_SECRET_KEY enables billing (sk_test_/sk_live_ or a restricted rk_ key) // STRIPE_PUBLISHABLE_KEY pk_ key shown to the browser // STRIPE_WEBHOOK_SECRET signing secret of the endpoint at /stripe/webhook // STRIPE_PRICE_PRO price id of the Pro monthly subscription // STRIPE_PRICE_CUSTOM_DOMAIN price id of the $5/month per-domain custom domain add-on (quantity = domains) // STRIPE_TOPUP_PRICES JSON {"": "price_..."} // STRIPE_DEV_REPLAY "true" enables the loopback-only /__dev/stripe/replay route (test keys only) // STRIPE_WEBHOOK_MODE "test" or "live", the webhook endpoint's mode; refused when it mismatches the keys // BILLING_CHECKOUT_DISABLED "true" blocks new checkouts and portal plan changes; webhooks keep working // PAST_DUE_GRACE_DAYS days past_due keeps Pro before usage drops to Free (default 14) // AI_DAILY_SPEND_CEILING_CENTS platform-wide daily AI cost ceiling in cents (default 10000 with Stripe, else off; "off" disables) // Operator contact secrets: ABUSE_FORWARD_TO (verified Email Routing destination that receives a copy of every // abuse@ message). Kept out of the repo. // Optional PostHog analytics (docs/analytics.md). Off unless POSTHOG_KEY is set: // POSTHOG_KEY project token (phc_...); VITE_POSTHOG_PROJECT_TOKEN is accepted as an alias // POSTHOG_HOST ingestion host, default https://us.i.posthog.com (VITE_POSTHOG_HOST alias) // POSTHOG_PERSON_EMAIL "true" attaches the signed-in user's email to their person (off: no PII) // This file is the PRODUCTION config (`bun run deploy`). `bun run dev` / `bun run preview` apply the dev // overrides in vite.config.ts on top of it: PUBLIC_URL=http://localhost:3000, GITFOR_LOCAL=true, and every // Artifacts namespace and trigger filter renamed to `-dev`. A deployed worker refuses to serve // (503) until PUBLIC_URL, USERCONTENT_ORIGIN and SECRETS_KEY are set correctly; see docs/self-hosting.md "Production setup". // Required secrets: SECRETS_KEY (>= 32 chars). First admin: set ADMIN_EMAIL (promoted once that address is // verified) or the one-time BOOTSTRAP_TOKEN secret. "vars": { "FORGE_NAME": "gitfor", "ARTIFACTS_NAMESPACE": "stig", "ARTIFACTS_SHARDS": "1", "ARTIFACTS_ORPHAN_SWEEP": "report", "ARTIFACTS_NAMESPACE_EXCLUSIVE": "false", "SIGNUPS_ENABLED": "true", "PUBLIC_URL": "https://gitfor.dev", "ADMIN_EMAIL": "", // first admin already exists; set only to bootstrap a fresh instance "CLOUD_JOBS_PER_OWNER": "2", "CLOUD_MINUTES_PER_DAY": "60", "LFS_STORAGE_BYTES_PER_OWNER": "2147483648", "LFS_BANDWIDTH_BYTES_PER_MONTH": "5368709120", "LFS_MAX_OBJECT_BYTES": "52428800", "RELEASE_ASSET_BYTES_PER_OWNER": "2147483648", "CUSTOM_DOMAINS_ZONE_ID": "8031ee3b7c34663c43cf8118b00130da", // Cloudflare for SaaS zone for Sites custom domains (fallback origin is this Worker); with CF_API_TOKEN "CUSTOM_DOMAINS_TARGET": "domains.gitforstatic.dev", // the SaaS fallback origin customers CNAME their domain to "SITES_ZONE_ID": "8031ee3b7c34663c43cf8118b00130da", // zone of SITES_DOMAIN; with CF_API_TOKEN (Cache Purge), suspensions purge site hosts "SITES_DOMAIN": "gitforstatic.dev", "SITES_ENABLED": "true", // "false" stops every dynamic site and scratch upload (operator kill switch) "SITES_DAILY_CPU_MS_LIMIT": "0", // platform-wide daily CPU ms for dynamic sites; past it they answer 503 (0 = unlimited) "SITES_DAILY_REQUEST_LIMIT": "0", // platform-wide daily site requests; past it dynamic sites answer 503 (0 = unlimited) "EDITOR_ORIGIN": "https://editor.gitfor.dev", "USERCONTENT_ORIGIN": "https://gitforusers.dev", "EDITOR_OPEN_VSX": "off", "EDITOR_CONTAINERS": "on", "EDITOR_CONTAINER_IDLE_MINUTES": "10", "EDITOR_CONTAINER_CAP_HOURS": "2", "EDITOR_CONTAINERS_PER_ACCOUNT": "1", "EMAIL_FROM": "gitfor ", "EMAIL_REPLY_DOMAIN": "mail.gitfor.dev", "TURNSTILE_SITEKEY": "0x4AAAAAAFUg9PmDIBH5nisz", "TURNSTILE_HOSTNAMES": "gitfor.dev", "EMAIL_DEV_SINK": "", "NOTIFY_DIGEST_DELAY_MS": "", "CACHE_BYTES_PER_REPO": "536870912", "MIN_SCHEDULE_INTERVAL_MINUTES": "15", "MERGEFIX_PROVIDER": "workers-ai", "MERGEFIX_GATEWAY_ID": "default", "MERGEFIX_MODEL": "@cf/zai-org/glm-5.3-flash", "MERGEFIX_CLEF_MODEL": "clef", "PR_DESCRIBE_MODEL": "@cf/meta/llama-3.1-8b-instruct-fast", "METERING_PLANS": "", "LEGAL_ENTITY": "Taigrr LLC", "LEGAL_CONTACT_EMAIL": "support@gitfor.dev", "LEGAL_ADDRESS": "", // optional; legal pages omit the postal address when empty "LEGAL_JURISDICTION": "California, United States", "DMCA_AGENT_EMAIL": "abuse@gitfor.dev", "SECURITY_CONTACT_EMAIL": "security@gitfor.dev", "SUPPORT_EMAIL": "support@gitfor.dev", "GITFOR_ENV": "production", "STRIPE_WEBHOOK_MODE": "live", // .dev.vars sets "test" for local runs "BILLING_CHECKOUT_DISABLED": "false", "PAST_DUE_GRACE_DAYS": "14", "AI_DAILY_SPEND_CEILING_CENTS": "10000" }, "analytics_engine_datasets": [{ "binding": "USAGE", "dataset": "gitfor_usage" }], "worker_loaders": [{ "binding": "LOADER" }], "ai": { "binding": "AI", "remote": true }, "send_email": [{ "name": "EMAIL", "remote": true }], "images": { "binding": "IMAGES" }, "artifacts": [ { "binding": "ARTIFACTS", "namespace": "stig", "remote": true } ], "ratelimits": [ { "name": "AUTH_LIMITER", "namespace_id": "1001", "simple": { "limit": 10, "period": 60 } }, { "name": "WRITE_LIMITER", "namespace_id": "1002", "simple": { "limit": 30, "period": 60 } }, { "name": "HEAVY_LIMITER", "namespace_id": "1003", "simple": { "limit": 30, "period": 60 } }, { "name": "GIT_LIMITER", "namespace_id": "1004", "simple": { "limit": 120, "period": 60 } }, { "name": "REPORT_LIMITER", "namespace_id": "1005", "simple": { "limit": 5, "period": 60 } } ], "d1_databases": [ { "binding": "DB", "database_name": "gitfor", "database_id": "2a42c6f8-2cd5-4c46-a850-02865b12369b", "migrations_dir": "migrations" }, { "binding": "ADVISORY_DB", "database_name": "gitfor-advisories", "database_id": "0f04839a-a1db-4c23-81dc-34e70444d1ef", "migrations_dir": "migrations-advisories" } ], "kv_namespaces": [ { "binding": "KV", "id": "173ad00e010b4d85981e98427feb1bc2" } ], "r2_buckets": [ { "binding": "BUCKET", "bucket_name": "gitfor" } ], "queues": { "producers": [ { "binding": "EVENTS", "queue": "gitfor-events" }, { "binding": "SECURITY_QUEUE", "queue": "gitfor-security" }, { "binding": "INTEGRATIONS", "queue": "gitfor-integrations" } ], "consumers": [ { "queue": "gitfor-events", "max_batch_size": 10, "max_batch_timeout": 2, "max_retries": 8, "dead_letter_queue": "gitfor-events-dlq" }, { "queue": "gitfor-security", "max_batch_size": 4, "max_batch_timeout": 5, "max_retries": 5, "dead_letter_queue": "gitfor-security-dlq" }, { "queue": "gitfor-integrations", "max_batch_size": 10, "max_batch_timeout": 2, "max_retries": 6, "dead_letter_queue": "gitfor-integrations-dlq" }, { "queue": "gitfor-integrations-dlq", "max_batch_size": 10, "max_batch_timeout": 5, "max_retries": 1 } ] }, "workflows": [ { "name": "gitfor-push", "binding": "PUSH_WORKFLOW", "class_name": "PushWorkflow" }, { "name": "gitfor-repo-provision", "binding": "REPO_PROVISION", "class_name": "RepoProvisionWorkflow" }, { "name": "gitfor-ci-run", "binding": "CI_WORKFLOW", "class_name": "CiRunWorkflow" }, { "name": "gitfor-sites-deploy", "binding": "SITES_WORKFLOW", "class_name": "SitesDeployWorkflow" }, { "name": "gitfor-mergefix", "binding": "MERGEFIX_WORKFLOW", "class_name": "MergeFixWorkflow" } ], "durable_objects": { "bindings": [ { "name": "RUNNER", "class_name": "Runner" }, { "name": "PROJECT_ROOM", "class_name": "ProjectRoom" }, { "name": "EDITOR_ROOM", "class_name": "EditorRoom" }, { "name": "EDITOR_CONTAINER", "class_name": "EditorContainer" }, { "name": "MERGE_QUEUE", "class_name": "MergeQueue" }, { "name": "GIT_RUNNER", "class_name": "GitTaskRunner" }, { "name": "RUNNER_LARGE", "class_name": "RunnerLarge" }, { "name": "RUNNER_XLARGE", "class_name": "RunnerXLarge" }, { "name": "MCP_HUB", "class_name": "McpHub" }, { "name": "REPO_INSIGHTS", "class_name": "RepoInsights" }, { "name": "REPO_SEARCH", "class_name": "RepoSearch" }, { "name": "REPO_STATE", "class_name": "RepoState" }, { "name": "ACCOUNT_STATE", "class_name": "AccountState" }, { "name": "COUNTERS", "class_name": "Counters" }, { "name": "RATE_LIMITER", "class_name": "RateLimiter" }, { "name": "USER_INBOX", "class_name": "UserInbox" }, { "name": "WEBHOOK_LOG", "class_name": "WebhookLog" }, { "name": "METER_BUFFER", "class_name": "MeterBuffer" }, { "name": "JOB_DOORBELL", "class_name": "JobDoorbell" } ] }, "containers": [ { "class_name": "Runner", "image": "./runner/Dockerfile", "instance_type": "standard-1", "max_instances": 20 }, { "class_name": "RunnerLarge", "image": "./runner/Dockerfile", "instance_type": "standard-2", "max_instances": 10 }, { "class_name": "RunnerXLarge", "image": "./runner/Dockerfile", "instance_type": "standard-4", "max_instances": 5 }, { "class_name": "GitTaskRunner", "image": "./runner/Dockerfile", "instance_type": "standard-1", "max_instances": 10 }, { "class_name": "EditorContainer", "image": "./editor-container/Dockerfile", "instance_type": "standard-1", "max_instances": 20 } ], "secrets_store_secrets": [ { "binding": "OIDC_SIGNING_KEY", "store_id": "80a4ef8e7bb84d6cb31b0f64f45371aa", // the account's default_secrets_store (one store per account) "secret_name": "gitfor-oidc-signing-key" } ], "migrations": [ { "tag": "v1", "new_sqlite_classes": ["Runner"] }, { "tag": "issues-v1", "new_sqlite_classes": ["ProjectRoom"] }, { "tag": "pulls-merge-queue", "new_sqlite_classes": ["MergeQueue"] }, { "tag": "v2", "new_sqlite_classes": ["RunnerLarge", "RunnerXLarge"] }, { "tag": "mcp-v1", "new_sqlite_classes": ["McpHub"] }, { "tag": "editor-v1", "new_sqlite_classes": ["EditorRoom", "EditorContainer"] }, { "tag": "insights-v1", "new_sqlite_classes": ["RepoInsights"] }, { "tag": "scale-v1", "new_sqlite_classes": ["Counters", "UserInbox", "WebhookLog", "MeterBuffer"] }, { "tag": "ci-doorbell-v1", "new_sqlite_classes": ["JobDoorbell"] }, { "tag": "git-runner-v1", "new_sqlite_classes": ["GitTaskRunner"] }, { "tag": "ratelimit-v1", "new_sqlite_classes": ["RateLimiter"] }, { "tag": "search-v1", "new_sqlite_classes": ["RepoSearch"] }, { "tag": "repo-state-v1", "new_sqlite_classes": ["RepoState"] }, { "tag": "account-state-v1", "new_sqlite_classes": ["AccountState"] } ], "triggers": { "crons": ["*/5 * * * *"], "events": [ { "type": "cf.artifacts.repo.pushed", "filter": { "namespace": "stig" }, "targets": [ { "type": "workflow", "workflow_name": "gitfor-push" } ] }, { "type": "cf.artifacts.repo.forked", "filter": { "namespace": "stig" }, "targets": [ { "type": "workflow", "workflow_name": "gitfor-repo-provision" } ] } ] } }