Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
457 lines (445 loc) · 21.7 KB
/
Copy path.env.example
File metadata and controls
457 lines (445 loc) · 21.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# Shared runtime (optional defaults)
LOG_LEVEL=INFO
ENVIRONMENT=local
SENTRY_DSN=
SENTRY_SEND_DEFAULT_PII=false
SENTRY_DEBUG=false
# Queue transport (optional defaults for host-run app services)
REDIS_URL=redis://127.0.0.1:6379/0
REDIS_QUEUE_NAME=jobs.default
REDIS_KEY_PREFIX=jobs
REDIS_SOCKET_CONNECT_TIMEOUT=5.0
REDIS_SOCKET_TIMEOUT=5.0
REDIS_HOST_BIND=127.0.0.1
# Optional: expose Redis on a fixed host port for local debugging.
# `./scripts/dev.sh` computes a deterministic per-worktree port when unset.
# `./scripts/docker-compose.sh` computes a deterministic per-worktree port when unset.
# REDIS_HOST_PORT=6379
# Postgres (required in production; optional defaults for host-run app services)
POSTGRES_URL=postgresql://postgres:postgres@127.0.0.1:5432/workflows
POSTGRES_DB=workflows
POSTGRES_USER=postgres
# Change in production
POSTGRES_PASSWORD=postgres
POSTGRES_HOST_BIND=127.0.0.1
# Optional: expose postgres on a fixed host port for local debugging.
# `./scripts/dev.sh` computes a deterministic per-worktree port when unset.
# `./scripts/docker-compose.sh` computes a deterministic per-worktree port when unset.
# POSTGRES_HOST_PORT=5432
# Job retry behavior (optional)
JOB_MAX_ATTEMPTS=8
JOB_RETRY_BASE_SECONDS=5
JOB_RETRY_MAX_SECONDS=300
# Re-publish durable jobs whose initial or delayed Redis delivery was lost.
JOB_QUEUE_RECONCILIATION_INTERVAL_SECONDS=30
JOB_QUEUE_RECONCILIATION_BATCH_SIZE=100
JOB_TIMEOUT_SECONDS=600
JOB_RESULT_TTL_SECONDS=3600
GIG_RECRUITING_STALE_DAYS=7
GIG_CONTACTED_REMINDER_DAYS=5
GIG_RECRUITING_REMINDER_MAX_AGE_DAYS=90
ONBOARDING_REMINDERS_ENABLED=false
ONBOARDING_REMINDER_STALE_DAYS=7
ONBOARDING_REMINDER_REPEAT_DAYS=7
ONBOARDING_REMINDER_CHECK_SECONDS=3600
# Discord snowflake stored as text; use the #onboarding-volunteers channel ID.
DISCORD_ONBOARDING_VOLUNTEERS_CHANNEL_ID=
# Internal transfer storage (optional defaults for host-run app services)
MINIO_ENDPOINT=http://127.0.0.1:9000
MINIO_ROOT_USER=internal
# Change in production
MINIO_ROOT_PASSWORD=change-me
MINIO_INTERNAL_BUCKET=internal-transfers
MINIO_HOST_BIND=127.0.0.1
# Optional: expose MinIO on fixed host ports for local debugging.
# `./scripts/dev.sh` computes deterministic per-worktree ports when unset.
# `./scripts/docker-compose.sh` computes deterministic per-worktree ports when unset.
# MINIO_API_HOST_PORT=9000
# MINIO_CONSOLE_HOST_PORT=9001
# Web/API service (optional defaults; API_SHARED_SECRET required for protected API calls)
WEB_HOST=0.0.0.0
# Direct host-run web/API processes use WEB_PORT. Compose pins the container's
# internal listen port to 8090 and uses WEB_HOST_PORT for the published host port.
# `./scripts/dev.sh web` ignores this `.env` value and computes a deterministic
# per-worktree port unless you export WEB_PORT in your shell.
WEB_PORT=8090
WEB_HOST_BIND=127.0.0.1
# Optional: expose the web/API service on a fixed host port for Cloudflare Tunnel/local debugging.
# Leave unset to let ./scripts/docker-compose.sh compute a deterministic port.
# WEB_HOST_PORT=8090
# Host-run web/API processes launched through `./scripts/dev.sh web` override
# `WEB_PORT` with a deterministic per-worktree port automatically.
# Deprecated fallback names still work: WEBHOOK_INGEST_HOST, WEBHOOK_INGEST_PORT,
# WEBHOOK_INGEST_HOST_BIND, WEBHOOK_INGEST_HOST_PORT.
# Required for protected non-dashboard API routes, including /agent/*. Webhook
# routes use this only when WEBHOOK_SHARED_SECRET is unset.
API_SHARED_SECRET=
# Production agent RBAC uses the existing single DISCORD_SERVER_ID plus
# immutable Discord role IDs (not role names). Comma-separate role IDs if a
# bundle intentionally has more than one role. A combined Billing / ERP Dev
# role ID must appear in both applicable bundle variables. Never use the guild
# ID: Discord assigns it to the @everyone role, which would grant every member.
AGENT_DISCORD_ADMIN_ROLE_IDS=
AGENT_DISCORD_STEERING_COMMITTEE_ROLE_IDS=
AGENT_DISCORD_BILLING_ROLE_IDS=
AGENT_DISCORD_ERP_DEVELOPER_ROLE_IDS=
AGENT_DISCORD_PROJECT_MANAGER_ROLE_IDS=
AGENT_DISCORD_ENGINEER_ROLE_IDS=
# Local/test migration aid only. Never effective outside local/dev/test.
AGENT_ALLOW_ROLE_NAME_FALLBACK=false
# Env-only key used to encrypt admin-dashboard-managed secret config values.
CONFIG_SECRET_KEY=
# Optional: separate secret for external /webhooks/* callers. When unset or
# blank, webhook routes fall back to API_SHARED_SECRET for compatibility.
WEBHOOK_SHARED_SECRET=
# Authentik admin API (required for /create-sso-user and /create-user-accounts)
# Base URL can omit /api/v3; the client adds it automatically.
AUTHENTIK_API_BASE_URL=
AUTHENTIK_API_TIMEOUT_SECONDS=20.0
AUTHENTIK_API_TOKEN=
# Optional override. When unset, the bot resolves the Email Stage by name.
AUTHENTIK_RECOVERY_EMAIL_STAGE_ID=
# Optional Authentik Email Stage name used when the UUID override is unset.
AUTHENTIK_RECOVERY_EMAIL_STAGE_NAME=default-recovery-email
# Outline integrations
# Privileged API/worker-only key used for invitations (also requires Migadu +
# Authentik for /create-user-accounts) and explicitly approved wiki publishing.
# Do not reuse it for member-safe content reads or expose it to the Discord bot.
# OUTLINE_API_KEY is accepted as a legacy fallback.
# Required by the backend for /create-user-accounts and /invite-outline-user.
# For Outline Cloud, keep the default https://app.getoutline.com.
# For self-hosted Outline, use https://your-outline-host.
OUTLINE_BASE_URL=https://app.getoutline.com
OUTLINE_API_TIMEOUT_SECONDS=20.0
OUTLINE_ADMIN_API_KEY=
# Used by /wiki and project wiki matching. Create this key for a dedicated
# regular Outline Member with access only to member-safe collections; scope it
# to documents.search, documents.info, and stars.list. That account's starred
# documents are /wiki quick links.
OUTLINE_CONTENTS_API_KEY=
# Review-first Discord wiki authoring (disabled by default).
# The writer may only run in the configured Discord guild and requires the
# backend-only OUTLINE_ADMIN_API_KEY above plus a collection ID for new pages.
WIKI_EDITING_ENABLED=false
WIKI_OUTLINE_COLLECTION_ID=
# Required for updates on custom/self-hosted Outline after verifying version
# 1.10.0+ supports documents.update.lastRevision. New articles do not need it.
WIKI_OUTLINE_LAST_REVISION_CONFIRMED=false
# A separate high-entropy secret shared only by the Discord bot and API. It
# signs short-lived role/identity assertions for wiki actions and the fixed
# Outline membership proxy; each assertion binds its exact method, path, and
# JSON body. Do not reuse API_SHARED_SECRET. Inject it per service in
# production, not through a broadly inherited env_file.
WIKI_EDITING_ASSERTION_SECRET=
WIKI_EDITING_API_TIMEOUT_SECONDS=20.0
# Discord's authenticated wiki request can synchronously read then write
# Outline during a confirmed publish. A scalar provider timeout applies to
# connect and read separately; allow four default 20s windows plus overhead.
WIKI_EDITING_REQUEST_TIMEOUT_SECONDS=90.0
WIKI_EDITING_MAX_INSTRUCTION_CHARACTERS=4000
# Target articles above this limit are rejected rather than partially sent to
# an external model provider. Split large articles before requesting an edit.
WIKI_EDITING_MAX_DOCUMENT_CHARACTERS=16000
# OMP is never launched from the credentialed worker. Configure the separately
# credentialed sandbox endpoint instead. Host-run deployments require HTTPS;
# Compose injects http://wiki_omp_sandbox:8080 over its internal control network.
WIKI_OMP_SANDBOX_URL=
# Shared only by the worker and sandbox to authenticate the narrow draft RPC.
# Inject it per service in production, not through a broadly inherited env_file.
WIKI_OMP_SANDBOX_TOKEN=
WIKI_OMP_SANDBOX_PROTOCOL_VERSION=v1
WIKI_OMP_MODEL=openrouter/openai/gpt-5-mini
WIKI_OMP_THINKING=medium
WIKI_OMP_STARTUP_TIMEOUT_SECONDS=30.0
# Keep authoring at least 10 seconds longer than the sandbox run timeout.
WIKI_OMP_AUTHORING_TIMEOUT_SECONDS=300.0
WIKI_OMP_SANDBOX_RUN_TIMEOUT_SECONDS=270
# Do not set WIKI_OMP_COMMAND or WIKI_OMP_LAUNCHER_PATH: legacy local OMP
# launching is deliberately rejected. Supply the sandbox's OpenRouter key via
# a Docker secret or deployment secret manager, never this worker env file.
# ERPNext project tracking (required for project dashboard sync and /projects)
ERPNEXT_BASE_URL=https://erp.example.com/
ERPNEXT_API_TIMEOUT_SECONDS=20.0
ERPNEXT_API_KEY=
# Required before the agent exposes Billing/ERP read tools. Set this to the
# single Discord organization/guild ID that is authorized to use these ERPNext
# credentials; agent ERP reads fail closed when it is unset or does not match.
AGENT_ERP_ORGANIZATION_ID=
# Optional: Discord logs webhook for operator-visible logs from commands/jobs
DISCORD_LOGS_WEBHOOK_URL=
# Optional: wait for Discord server confirmation before returning from webhook call
DISCORD_LOGS_WEBHOOK_WAIT=true
# Dashboard/API auth (OIDC via Authentik; optional until enabled)
OIDC_ISSUER_URL=
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_SCOPE=openid profile email groups
OIDC_GROUPS_CLAIM=groups
OIDC_ADMIN_GROUPS=authentik Admins
OIDC_CALLBACK_PATH=/auth/callback
# Optional external base URL used to build redirect_uri (defaults to request base URL)
OIDC_REDIRECT_BASE_URL=
AUTH_SESSION_COOKIE_NAME=five08_session
# Dashboard session lifetime after a successful login link or OIDC login.
AUTH_SESSION_TTL_SECONDS=86400
DASHBOARD_DEFAULT_PATH=/dashboard
# Optional external base URL for generated deep links and dashboard CSRF origin checks
DASHBOARD_PUBLIC_BASE_URL=
# Configured Discord co-op server (required for /wiki and admin link checks)
DISCORD_SERVER_ID=
DISCORD_ADMIN_ROLES=Admin,Owner
DISCORD_API_TIMEOUT_SECONDS=8.0
DISCORD_LINK_TTL_SECONDS=600
# Discord dashboard links allow active CRM-linked Steering Committee+ users.
# DISCORD_ADMIN_ROLES marks which users can receive admin permissions; jobs,
# reruns, people sync, and audit still require SSO-validated dashboard sessions.
# Local/dev/test ENVIRONMENT values bypass that SSO requirement for development.
# Local-dev bootstrap switch: keep false unless OIDC is configured locally.
# Set true in production so Discord deep-link logins also require OIDC email
# identity checks against the linked CRM/Discord dashboard user.
DISCORD_LINK_REQUIRE_OIDC_IDENTITY_CHECKS=false
# Worker / consumer (optional defaults)
WORKER_NAME=worker
WORKER_API_BASE_URL=http://127.0.0.1:8090
DISCORD_BOT_INTERNAL_BASE_URL=http://127.0.0.1:3000
WORKER_QUEUE_NAMES=jobs.default
WORKER_BURST=false
MAX_ATTACHMENTS_PER_CONTACT=3
MAX_FILE_SIZE_MB=10
ALLOWED_FILE_TYPES=pdf,doc,docx,txt
OPENAI_API_KEY=
# Shared OpenAI-compatible endpoint. Bifrost can route multiple providers with one key.
# For same-host Docker-network routing, use http://bifrost:8080/openai instead.
OPENAI_BASE_URL=https://bifrost.508.dev/openai
OPENAI_MODEL=gpt-5-mini
# Optional direct OpenAI fallback when OPENAI_BASE_URL points at Bifrost.
OPENAI_DIRECT_API_KEY=
# Legacy direct OpenAI key name is also accepted: OPENAI_API_KEY_DIRECT.
OPENAI_DIRECT_BASE_URL=https://api.openai.com/v1
OPENAI_DIRECT_MODEL=
# Optional direct Fireworks fallback for planner routing.
FIREWORKS_API_KEY=
# Optional direct OpenRouter fallback when Bifrost is unavailable/misconfigured.
OPENROUTER_API_KEY=
# Optional Langfuse endpoint for LLM tracing/observability.
LANGFUSE_BASE_URL=
# Optional agent model tiers. Leave unset to fall back through
# reasoning -> strong -> fast -> AGENT_FALLBACK_MODEL -> gpt-4.1-mini.
# If OPENAI_BASE_URL points at Bifrost and OPENAI_API_KEY is set, the planner
# defaults to Kimi through Bifrost using the provider-prefixed model id
# fireworks/accounts/fireworks/models/kimi-k2p6.
# Explicit Bifrost provider-prefixed planner models, such as
# openrouter/openai/gpt-4.1-mini, are passed through unchanged.
# If Bifrost is not configured and FIREWORKS_API_KEY is set, the agent planner
# falls back to direct Fireworks using accounts/fireworks/models/kimi-k2p6.
# Base URLs should be OpenAI-compatible and use HTTPS, except the internal
# Docker-network Bifrost URL http://bifrost:8080/openai is allowed.
AGENT_PLANNER_MODEL=accounts/fireworks/models/kimi-k2p6
AGENT_FALLBACK_MODEL=gpt-4.1-mini
# Keep this below AGENT_API_TIMEOUT_SECONDS so deterministic fallback can respond.
AGENT_STRUCTURED_PLANNER_ENABLED=true
AGENT_STRUCTURED_PLANNER_TIMEOUT_SECONDS=6.0
AGENT_INTENT_NORMALIZER_ENABLED=true
AGENT_INTENT_NORMALIZER_TIMEOUT_SECONDS=3.0
# Maximum public-web tool/planner turns in one request. Writes never run in this loop.
AGENT_PLANNING_MAX_STEPS=3
# Caller-visible budget for synchronous agent planning/read requests. This is
# intentionally below AGENT_API_TIMEOUT_SECONDS; a timed-out sync worker may
# still be unwinding an upstream DNS or HTTP call in the background.
AGENT_REQUEST_RESPONSE_BUDGET_SECONDS=55.0
# Best-effort public-web operation budget. It must not exceed the response
# budget; the API response budget is the hard Discord-facing bound.
AGENT_PUBLIC_WEB_DEADLINE_SECONDS=50.0
# Sweep expired durable agent-memory facts even when no user sends a request.
# The cleanup worker only returns a deletion count and never exposes fact data.
AGENT_MEMORY_CLEANUP_ENABLED=true
AGENT_MEMORY_CLEANUP_INTERVAL_SECONDS=86400
# Durable recurring agent reports use five-field cron expressions and persist
# a fixed read-only capability catalog. The API dispatcher is safe to enable
# with no schedules configured. Five minutes is the minimum allowed cadence.
AGENT_SCHEDULE_ENABLED=true
AGENT_SCHEDULE_DISPATCH_INTERVAL_SECONDS=30
AGENT_SCHEDULE_DISPATCH_BATCH_SIZE=25
AGENT_SCHEDULE_MIN_INTERVAL_SECONDS=300
AGENT_SCHEDULE_EXECUTION_TIMEOUT_SECONDS=120.0
# Terminal outcomes are retained per schedule; full report bodies have a
# smaller cap so audit metadata remains available without unbounded text growth.
AGENT_SCHEDULE_RUN_RETENTION_PER_SCHEDULE=100
AGENT_SCHEDULE_RUN_OUTPUT_RETENTION_PER_SCHEDULE=20
AGENT_SCHEDULE_RUN_CLEANUP_INTERVAL_SECONDS=3600
AGENT_SCHEDULE_RUN_CLEANUP_BATCH_SIZE=10000
# Source-grounded Discord knowledge capture and Q&A.
KNOWLEDGE_ENABLED=true
KNOWLEDGE_API_TIMEOUT_SECONDS=15.0
KNOWLEDGE_MODEL_ENABLED=true
KNOWLEDGE_MODEL_TIMEOUT_SECONDS=6.0
KNOWLEDGE_SOURCE_TIMEOUT_SECONDS=6.0
KNOWLEDGE_CAPTURE_MAX_MESSAGES=50
KNOWLEDGE_CAPTURE_MAX_CHARACTERS=20000
KNOWLEDGE_CAPTURE_MAX_AGE_DAYS=7
KNOWLEDGE_CAPTURE_DRAFT_TTL_SECONDS=600
KNOWLEDGE_REVIEW_AFTER_DAYS=180
KNOWLEDGE_QUERY_MAX_EVIDENCE=8
KNOWLEDGE_SEMANTIC_CANDIDATE_LIMIT=24
# Prefer Dashboard > Configuration > Knowledge sources. Leave this empty for UI management.
# A nonempty environment override locks the picker. At most eight IDs; private threads excluded.
KNOWLEDGE_DISCORD_CHANNEL_IDS=
KNOWLEDGE_DISCORD_HISTORY_LIMIT=100
KNOWLEDGE_DISCORD_HISTORY_DAYS=30
# Suggest personal preferences in addressed conversations; saving requires confirmation.
AGENT_MEMORY_SUGGESTIONS_ENABLED=true
AGENT_FAST_MODEL=
AGENT_FAST_BASE_URL=
AGENT_FAST_API_KEY=
AGENT_STRONG_MODEL=
AGENT_STRONG_BASE_URL=
AGENT_STRONG_API_KEY=
AGENT_REASONING_MODEL=
AGENT_REASONING_BASE_URL=
AGENT_REASONING_API_KEY=
# HN job-lead scraping uses an LLM classifier when OpenAI-compatible credentials
# are configured, then falls back to keyword matching if the model is unavailable.
JOB_LEAD_CLASSIFIER_ENABLED=true
JOB_LEAD_CLASSIFIER_MODEL=
JOB_LEAD_CLASSIFIER_TIMEOUT_SECONDS=8.0
# Optional deterministic agent tool integrations.
# GitHub Issues are the canonical todo backend. Members receive no agent scopes;
# explicitly configured privileged roles can work in GitHub repositories selected
# for the GitHub App installation and the organization's Projects.
GITHUB_DEFAULT_REPO=508-dev/todos
GITHUB_ORGANIZATION=508-dev
# Keep true for Steering Committee/Admin/Owner access to every App-selected repo.
GITHUB_STEERING_ALL_INSTALLED_REPOS=true
# Used only when the preceding setting is false.
GITHUB_STEERING_EXTRA_REPOS=
# Preferred authentication: one 508.dev GitHub App installed on selected repos.
# These can instead be managed in Dashboard > Configuration > Operations. The
# private key is encrypted there when CONFIG_SECRET_KEY is configured. Any
# non-empty environment value takes precedence over the dashboard value.
GITHUB_APP_CLIENT_ID=
GITHUB_APP_INSTALLATION_ID=
# Preserve literal newlines when your deployment secret manager supports them;
# an escaped \n form is accepted too.
GITHUB_APP_PRIVATE_KEY=
# Legacy compatibility only: GITHUB_APP_ID is accepted as an alias for
# GITHUB_APP_CLIENT_ID. Prefer the Client ID shown in the GitHub App settings.
# Temporary legacy fallback while moving to the GitHub App.
GITHUB_API_TOKEN=
GITHUB_ALLOWED_REPOS=
# Optional public-web research. Providers are tried in this fallback order only
# when configured. Set one or more of SearXNG, Brave, and Firecrawl credentials.
AGENT_WEB_SEARCH_PROVIDER_ORDER=searxng,brave,firecrawl
AGENT_WEB_SEARCH_TIMEOUT_SECONDS=5.0
AGENT_WEB_DEFAULT_RESULT_LIMIT=5
# SearXNG may be a private in-cluster HTTP endpoint, for example http://searxng:8080.
# Its SearXNG settings must enable the JSON search response format.
SEARXNG_BASE_URL=
SEARXNG_SEARCH_LANGUAGE=
# Brave and Firecrawl endpoints must be HTTPS; their API keys remain backend-only.
BRAVE_SEARCH_API_KEY=
BRAVE_SEARCH_BASE_URL=https://api.search.brave.com
BRAVE_SEARCH_COUNTRY=
BRAVE_SEARCH_LANGUAGE=
FIRECRAWL_API_KEY=
FIRECRAWL_BASE_URL=https://api.firecrawl.dev
# Resume extraction can use a different provider from agent planning.
# Leave RESUME_AI_API_KEY/BASE_URL unset to use OPENAI_API_KEY/OPENAI_BASE_URL.
# Model names without provider prefix are OpenRouter-prefixed to openai/<model>.
# If the primary resume provider is Bifrost, runtime LLM calls retry matching
# direct providers from OPENROUTER_API_KEY, FIREWORKS_API_KEY, or OPENAI_DIRECT_API_KEY.
RESUME_AI_API_KEY=
RESUME_AI_BASE_URL=
RESUME_AI_MODEL=gpt-4.1-mini
RESUME_EXTRACTOR_MAX_TOKENS=2000
RESUME_EXTRACTOR_VERSION=v1
CRM_SYNC_ENABLED=true
CRM_SYNC_INTERVAL_SECONDS=900
CRM_SYNC_PAGE_SIZE=200
# Optional: restrict Docuseal agreements to this template id.
# If unset, Docuseal agreement processing is ignored.
DOCUSEAL_MEMBER_AGREEMENT_TEMPLATE_ID=
# Required for sending member agreement requests from Discord.
# For DocuSeal Cloud use https://api.docuseal.com
# For self-hosted DocuSeal, this is usually https://your-host/api
DOCUSEAL_BASE_URL=
DOCUSEAL_API_KEY=
# Discord bot (required for bot runtime)
DISCORD_BOT_TOKEN=your_bot_token_here
DISCORD_DEFAULT_JOB_FORUM_CHANNELS=gigs:part_time,fulltime-roles:full_time
DISCORD_UNQUALIFIED_LEADS_FORUM_CHANNEL=unqualified-leads
# Host-run bot processes launched through `./scripts/dev.sh discord-bot` ignore
# this `.env` value and compute a deterministic per-worktree port unless you
# export HEALTHCHECK_PORT in your shell.
HEALTHCHECK_PORT=3000
BACKEND_API_BASE_URL=http://127.0.0.1:8090
# The bot defers Discord interactions; allow the bounded web-research loop to
# complete provider fallback and planning turns.
AGENT_API_TIMEOUT_SECONDS=60.0
AUDIT_API_BASE_URL=
AUDIT_API_TIMEOUT_SECONDS=2.0
# Worker-to-API handoff for durable recurring agent runs. Host-run development
# uses the same backend address as the Discord bot; compose overrides this.
# This must cover schedule execution plus 60 seconds for role refresh, summary,
# and Discord delivery, and fit inside the durable worker job lease.
AGENT_SCHEDULE_API_BASE_URL=http://127.0.0.1:8090
AGENT_SCHEDULE_API_TIMEOUT_SECONDS=360.0
# Worker mailbox resume intake (required if email intake is enabled)
CHECK_EMAIL_WAIT=2
EMAIL_USERNAME=your_email@example.com
EMAIL_PASSWORD=your_app_password
IMAP_SERVER=imap.migadu.com
IMAP_TIMEOUT_SECONDS=10.0
# Onboarding email sending for reviewed /onboarding-email drafts
ONBOARDING_EMAIL_SMTP_SERVER=smtp.migadu.com
ONBOARDING_EMAIL_SMTP_PORT=465
ONBOARDING_EMAIL_SMTP_USE_SSL=true
ONBOARDING_EMAIL_SMTP_STARTTLS=false
ONBOARDING_EMAIL_SMTP_USERNAME=onboarding@508.dev
ONBOARDING_EMAIL_SMTP_PASSWORD=your_app_password
ONBOARDING_EMAIL_SMTP_TIMEOUT_SECONDS=20.0
ONBOARDING_EMAIL_SENDER_EMAIL=onboarding@508.dev
# Intake form resume URL fetch guardrails
INTAKE_RESUME_FETCH_TIMEOUT_SECONDS=20.0
INTAKE_RESUME_MAX_REDIRECTS=3
# Optional comma-separated host allowlist for intake resume URL fetches
INTAKE_RESUME_ALLOWED_HOSTS=
# Onboarding Tally intake webhooks. ONBOARDING_TALLY_API_KEY is optional for
# future API backfills; webhook submissions use the signing secret for auth.
# Legacy aliases still work: TALLY_API_KEY, TALLY_WEBHOOK_SIGNING_SECRET,
# TALLY_ALLOWED_FORM_IDS.
ONBOARDING_TALLY_API_KEY=
ONBOARDING_TALLY_WEBHOOK_SIGNING_SECRET=
# Required for Tally webhook intake; comma-separated accepted onboarding form IDs.
ONBOARDING_TALLY_ALLOWED_FORM_IDS=
# Resume files are untrusted. Keep scanning required in production and configure
# a scanner command; use "{path}" where the downloaded resume path should go.
# Compose deployments provide a ClamAV sidecar command by default. Uncomment
# and set this only when intentionally overriding or disabling that command.
INTAKE_RESUME_REQUIRE_VIRUS_SCAN=false
# INTAKE_RESUME_VIRUS_SCAN_COMMAND=
INTAKE_RESUME_VIRUS_SCAN_TIMEOUT_SECONDS=30.0
EMAIL_RESUME_INTAKE_ENABLED=false
EMAIL_RESUME_ALLOWED_EXTENSIONS=pdf,doc,docx
EMAIL_RESUME_MAX_FILE_SIZE_MB=10
EMAIL_REQUIRE_SENDER_AUTH_HEADERS=true
# Migadu mailbox automation settings are dashboard-managed in normal deployments.
# Set non-empty env values only when you intentionally want env to lock dashboard edits.
# MIGADU_API_USER=your_migadu_api_user
# MIGADU_API_KEY=your_migadu_api_key
# MIGADU_MAILBOX_DOMAIN=508.dev
# Newsletter sync settings are dashboard-managed in normal deployments.
# Set non-empty env values only when you intentionally want env to lock dashboard edits.
# BREVO_API_KEY=
# BREVO_API_BASE_URL=https://api.brevo.com/v3
# BREVO_API_TIMEOUT_SECONDS=20.0
# BREVO_508_MEMBERS_NEWSLETTER_LIST_ID=4
# BREVO_508_MEMBERS_NEWSLETTER_LIST_NAME="508 members"
# KEILA_API_KEY=
# KEILA_API_BASE_URL=https://app.keila.io
# KEILA_API_TIMEOUT_SECONDS=20.0
# NEWSLETTER_SYNC_ENABLED=false
# NEWSLETTER_SYNC_INTERVAL_SECONDS=604800
# NEWSLETTER_SYNC_EXCLUDED_MAILBOXES=system,service-account
# EspoCRM (required for worker integration)
ESPO_API_KEY=your_key_here
ESPO_BASE_URL=https://espo.url/