Files

188 lines
8.9 KiB
Bash

# Listen address for the Go server inside its container — override only if
# you know why (e.g. a non-standard port mapping); the docker-compose.yml
# port binding already assumes the default.
LISTEN_ADDR=:3000
# Postgres (own database — separate from core's)
POSTGRES_PASSWORD=change-me
DATABASE_URL=postgres://production:change-me@postgres:5432/production?sslmode=disable
# JWT — MUST equal core's JWT_SECRET exactly. Production has no login of its
# own, it only verifies staff tokens core issued.
JWT_SECRET=change-me-must-match-core-JWT_SECRET
# MinIO (own instance — separate from core's)
MINIO_ENDPOINT=minio:9000
MINIO_ACCESS_KEY=change-me
MINIO_SECRET_KEY=change-me
MINIO_BUCKET=production
MINIO_USE_SSL=false
# CORS (comma-separated origins the web frontend will be served from)
CORS_ORIGINS=http://localhost:5173
# Core module registration — get both tokens via core's `POST /api/modules`
# (owner-only, returned once). CORE_URL must be reachable from this
# container (internal core address, not the public domain).
CORE_URL=http://core-backend:3000
MODULE_NAME=production
MODULE_TOKEN=change-me-token-from-core-POST-/api/modules
# Lets core restart this process or flip it into maintenance mode
# (internal/modulecontrol) — the "control_token" core's POST /api/modules
# response returns alongside MODULE_TOKEN above. Unset disables both
# actions entirely (authOK never succeeds against an empty stored secret).
CORE_CONTROL_TOKEN=change-me-control-token-from-core-POST-/api/modules
# Inbound webhook auth (internal/sale.Webhook) — online-store calls
# POST /api/webhooks/online-store/sales with X-Module-Token set to its OWN
# core module token, so this must equal the token core issued online-store
# (not production's own MODULE_TOKEN above). Unset disables the endpoint
# (fails closed, returns 503) rather than accepting unauthenticated writes.
ONLINE_STORE_WEBHOOK_TOKEN=change-me-must-match-online-store-MODULE_TOKEN
# Web build args (compile-time, baked into the JS bundle by Vite) — these are
# what the *browser* calls, so loopback/public URLs, not the container-network
# addresses above. Read by docker-compose.yml's web.build.args.
WEB_CORE_URL=http://127.0.0.1:18090
WEB_PRODUCTION_URL=http://127.0.0.1:18091
# Business requisites for Счёт/Акт PDFs (internal/document, internal/pdfgen).
# All optional — the business isn't legally registered yet, unset fields
# render as clean placeholder blanks rather than breaking generation. Fill
# these in once real registration details exist.
BUSINESS_NAME=
BUSINESS_INN=
BUSINESS_KPP=
BUSINESS_ADDRESS=
BUSINESS_PHONE=
BUSINESS_BANK_NAME=
BUSINESS_BANK_ACCOUNT=
BUSINESS_BANK_BIK=
BUSINESS_BANK_CORR_ACCOUNT=
# AI-приёмка (internal/aiintake, Phase 6) — free-text -> order-form field
# extraction via Gemini's structured-output API (a Google AI Studio key,
# free tier available, no card required as of this writing). Unset disables
# the endpoint (fails closed, returns 503) rather than accepting requests it
# can't fulfill. GEMINI_MODEL is overridable because Google's free-tier
# flash-model lineup has moved fast (2.0 -> 2.5 -> 3.x observed within a
# year) — bump this instead of the code default when the current one is
# deprecated.
GEMINI_API_KEY=
GEMINI_MODEL=gemini-2.0-flash
# IMEI-автозаполнение (internal/imei) — brand/model lookup by IMEI when
# creating an order, HiCellTek's free-tier TAC API. Unset disables the
# lookup silently (button stays but returns "not found").
IMEI_API_KEY=
# Staff Telegram notifications (internal/notify, Phase 8) — new order/batch
# created, status changes. Fire-and-forget: unset disables it silently
# (no 503, nothing to fail — it's a convenience layer on top of the Kanban
# board, not a delivery guarantee). TG_CHAT_ID is a single shared chat/group
# for all staff, same pattern as site's lead bot.
#
# TG_API_BASE_URL points at a self-hosted Telegram Bot API server
# (docker-compose.yml's telegram-bot-api service) instead of
# api.telegram.org directly — by design, not a placeholder (see project
# wiki). That server needs TELEGRAM_API_ID/TELEGRAM_API_HASH from
# my.telegram.org (one-time manual registration, requires a phone number —
# not something this codebase can automate) before it will even start; until
# that's done, leave the telegram-bot-api service stopped and TG_BOT_TOKEN
# as a placeholder — Send() fails soft exactly like it would against a real
# but invalid token.
TG_BOT_TOKEN=
TG_CHAT_ID=
TG_API_BASE_URL=http://telegram-bot-api:8081
# Credentials for docker-compose.yml's telegram-bot-api service itself (the
# self-hosted server, not this Go app) — register an application at
# https://my.telegram.org/apps to get these. Leave unset and the container
# just exits on start; TG_BOT_TOKEN above stays a no-op placeholder either
# way until both this and a real bot token from @BotFather are in place.
TELEGRAM_API_ID=
TELEGRAM_API_HASH=
# Client-facing notifications (internal/clientnotify, internal/tgbot,
# internal/smsgw — Phase 11). Reuses the same bot token/API base URL above
# (TG_BOT_TOKEN/TG_API_BASE_URL), just a different recipient (the client's
# own chat_id instead of the fixed staff chat). Everything below is also
# editable live from the Settings page (internal/settings) — these are only
# the first-boot fallback values.
#
# CLIENT_TG_BOT_USERNAME (no @) is used to build the t.me/<bot>?start=<token>
# deep link a client opens to link their chat.
#
# TG_WEBHOOK_SECRET is checked against Telegram's
# X-Telegram-Bot-Api-Secret-Token header on every inbound webhook call —
# unset means the webhook endpoint 401s everything, closed by default.
#
# TG_WEBHOOK_URL (infra-level, NOT owner-editable via Settings — it's how
# THIS process's own public address gets registered with Telegram, same
# category as CORE_URL) is the full public HTTPS URL Telegram should POST
# updates to, e.g. https://your-domain/api/webhooks/telegram — requires a
# reverse-proxy route into this container's /api/webhooks/telegram. Unset
# skips webhook registration silently (see internal/tgbot.EnsureWebhook).
#
# PUBLIC_TRACKING_URL is the base URL for the client-facing tracking page
# (site's /track route) — appended with "/<tracking_token>" in the "ready"
# notification.
#
# MAX_WEBHOOK_URL is MAX's (max.ru) equivalent of TG_WEBHOOK_URL above —
# infra-level, NOT owner-editable via Settings, the full public HTTPS URL
# MAX should POST updates to, e.g. https://your-domain/api/webhooks/max.
# Bot token / webhook secret / client bot username ARE owner-editable in
# Settings (see internal/maxbot.EnsureWebhook — unset skips registration
# silently, same as Telegram).
#
# VK_WEBHOOK_URL is VK's (vk.com community Callback API) equivalent —
# infra-level, NOT owner-editable via Settings, the full public HTTPS URL
# VK should POST events to, e.g. https://your-domain/api/webhooks/vk. Group
# token / group ID / secret key / confirmation code / community short name
# ARE owner-editable in Settings (see internal/vkbot.EnsureWebhook — unset
# skips registration silently, same as MAX/Telegram). Unlike MAX/Telegram,
# VK's confirmation code is VK-generated and only ever shown in the
# community's own admin panel — an owner still has to open that page once
# regardless of whether EnsureWebhook auto-registered the server URL.
#
# SMS.ru (internal/smsgw) is the SMS fallback for clients without a linked
# Telegram/MAX chat — get SMS_API_ID from https://sms.ru/?panel=api. SMS
# costs money per message; sms_enabled stays off by default even with
# credentials configured (owner must explicitly enable it in Settings).
CLIENT_TG_BOT_USERNAME=
TG_WEBHOOK_SECRET=
TG_WEBHOOK_URL=
MAX_WEBHOOK_URL=
VK_WEBHOOK_URL=
PUBLIC_TRACKING_URL=
SMS_PROVIDER=smsru
SMS_API_ID=
SMS_FROM=
# internal/scraper's technosuccess.ru source — a wholesale account's own
# login (unlike Regard, which needs no auth). Unset skips registering this
# source entirely, same pattern as the Telegram/MAX bot tokens above.
TECHNOSUCCESS_EMAIL=
TECHNOSUCCESS_PASSWORD=
# internal/scraper's i-t-p.pro (b2b.i-t-p.pro) source — a wholesale
# account's own login/password for their documented JSON-RPC B2B API
# (https://b2b.i-t-p.pro/download/docs/api/api.html), not a site scrape.
# Unset skips registering this source entirely, same pattern as
# TECHNOSUCCESS_* above.
ITPARTNER_LOGIN=
ITPARTNER_PASSWORD=
# internal/selfupdate — "Обновить" button in Settings → Обновления, proxies
# to deploy-agent/ (see that directory's README.md for what it does and the
# install steps). DEPLOY_AGENT_SOCKET_PATH is the path *inside this
# container* (docker-compose.yml bind-mounts deploy-agent/ to
# /run/deploy-agent), not a host path. DEPLOY_AGENT_TOKEN must exactly
# match deploy-agent/agent.env's value. Unset either and every
# /api/selfupdate/* route 503s — same fail-closed pattern as
# TECHNOSUCCESS_*/ITPARTNER_* above, and matches that most deployments of
# this repo won't have deploy-agent installed at all.
DEPLOY_AGENT_SOCKET_PATH=/run/deploy-agent/agent.sock
DEPLOY_AGENT_TOKEN=