Files
Ruslan KonviserandClaude Opus 5 3a62724c23 fix(security): Social-login audience verification + purpose-bound tokens (GHSA-58x4, GHSA-28wv) (#10241)
* fix(security): verify social-login token audience and bind every purpose token

GHSA-58x4-7mw9-gmqg (critical): POST /auth/signin.email.social accepted any
provider access token that resolved to a victim's email — another app's token or
a GitHub PAT — and signed the caller in as that user. Each provider is now
introspected against an allow-list of OAuth client ids (Google tokeninfo aud/azp
plus email_verified, GitHub /applications/{client_id}/token, Facebook
debug_token app_id) and fails closed when no client is configured. Twitter/X is
refused, since it exposes no verified email. One normaliser rejects an empty id
or email, so an undefined value can no longer reach a find() and be dropped by
TypeORM's undefined:'ignore' behaviour, which returned every user in every
tenant.

GHSA-28wv-vrxj-rp4q (medium): tokens signed with JWT_SECRET were interchangeable.
New signPurposeToken/verifyPurposeToken pin a purpose claim, required non-empty
claims and HS256. Workspace sign-in, invoice share, estimate, invite, team-join,
appointment and password-reset tokens are typed; public invoice and estimate
links are bound to the stored row and the URL id; access-token consumers
(JwtStrategy, RegisterAuthorizationGuard, Zapier, Plane) reject a token whose
purpose says it is something else. Untyped legacy tokens are accepted only where
they are also bound to a stored row, and never on signin.workspace.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(cspell): add the new vocabulary and use US spellings

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* refactor(auth): review follow-ups on the purpose-token hardening

Addresses the bot review round on PR #10241. No security behaviour is relaxed;
every change either tightens a check or is a readability fix with the same
runtime semantics, and the affected suites were re-run (9 suites / 155 tests).

- Password reset now goes through `verifyPurposeToken(TokenPurposeEnum.PASSWORD_RESET)`
  instead of a bare `verify()` plus a string-literal purpose comparison
  (CodeRabbit). It additionally requires a non-empty `id` claim: an `undefined`
  id reaching `findOneByIdString` widens the lookup instead of failing closed,
  which is exactly the class of bug this PR exists to remove. The stored
  password_reset row still binds the token, so this is defence in depth.
  `verify` and `JWT_ALGORITHMS` are no longer imported there.
- `JwtStrategy.validate` moves the employeeId/organizationId claim checks into
  `attachEmployeeAndOrganizationContext` (SonarCloud: cognitive complexity 16 >
  15). The helper RETURNS the UnauthorizedException instead of throwing, so the
  exact exceptions and messages the callback received before are unchanged, and
  three specs now cover the organization branch (member missing, employee in
  another organization, happy path). Control: inverting the rejection makes 12
  of the 30 tests in that suite fail.
- `normalizeSocialIdentity` extracts its nested ternary into
  `normalizeProviderAccountId` (SonarCloud), same accepted values as before:
  trimmed string, or a positive safe integer stringified for GitHub.
- `Number.NaN` over `NaN` in the reschedule-token lifetime (SonarCloud), and the
  two unused `catch (error)` bindings in PublicInvoiceService are now bare
  `catch`.

Not changed, deliberately: Greptile's P1 "mixed-case emails fail lookup". The
social lookup already queries BOTH the normalised (lowercased) address and the
provider's exact spelling, which is a strict superset of what this code did
before the PR, so nothing regressed. Matching stored emails case-insensitively
would let the holder of `a@x.com` sign into an account stored as `A@x.com` —
a widening of an authentication lookup that password login does not perform —
and belongs in a repo-wide email-normalisation change, not in this advisory fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 16:20:57 +02:00

611 lines
18 KiB
Bash

# The name of the application.
APP_NAME="Gauzy"
# The URL for the application logo.
APP_LOGO="http://localhost:4200/assets/images/logos/logo_Gauzy.png"
# The signature or tagline for the application.
APP_SIGNATURE="Gauzy"
# The link to the application.
APP_LINK="http://localhost:4200"
# The URL for an email confirmation in the application.
APP_EMAIL_CONFIRMATION_URL="http://localhost:4200/#/auth/confirm-email"
# The URL for magic sign-in in the application.
APP_MAGIC_SIGN_URL="http://localhost:4200/#/auth/magic-sign-in"
# set true if running inside the Docker container
IS_DOCKER=false
HOST=localhost
PORT=4200
# API Host
API_HOST=localhost
# API Port
API_PORT=3000
# WEB UI Host
WEB_HOST=localhost
# WEB UI Port
WEB_PORT=4200
# set true if running as a Demo
DEMO=true
# DO (DIGITALOCEAN), AWS, AZURE, CIVO, CW (COREWEAVE), HEROKU, LINODE, LOCAL, OVH, SCALEWAY, VULTR, etc
CLOUD_PROVIDER=
ALLOW_SUPER_ADMIN_ROLE=true
# set to Gauzy API base URL
API_BASE_URL=http://localhost:3000
# set to Gauzy UI base URL
CLIENT_BASE_URL=http://localhost:4200
#set to Website Platform
PLATFORM_WEBSITE_URL=https://gauzy.co
PLATFORM_WEBSITE_DOWNLOAD_URL=https://gauzy.co/downloads
# DB_ORM: typeorm | mikro-orm
DB_ORM=typeorm
# DB_TYPE: sqlite | postgres | better-sqlite3 | mysql
DB_TYPE=better-sqlite3
DB_SYNCHRONIZE=false
# DB Connection Parameters
DB_HOST=localhost
## DB Port. The default for PostgreSQL - 5432, for MySQL - 3306
DB_PORT=5432
DB_NAME=gauzy
## DB Username. The default for PostgreSQL is 'postgres', for MySQL it's 'root'
DB_USER=postgres
DB_PASS=root
# Keep full ORM query logging opt-in; use "all" only for focused diagnostics.
DB_LOGGING=error
DB_POOL_SIZE=40
DB_POOL_SIZE_KNEX=10
DB_CONNECTION_TIMEOUT=5000
DB_IDLE_TIMEOUT=10000
DB_SLOW_QUERY_LOGGING_TIMEOUT=10000
DB_SSL_MODE=false
# If you want to use SSL and set DB_SSL_MODE=true, set the following environment variable
# with base64 encoded SSL certificate for DB
DB_CA_CERT=
# Configuration for Worker Queue and Scheduler
WORKER_QUEUE_ENABLED=false
WORKER_SCHEDULER_ENABLED=false
WORKER_DEFAULT_QUEUE=gauzy_worker_default_queue
WORKER_TIMEZONE=UTC
# Redis Connection Parameters
REDIS_ENABLED=false
REDIS_HOST=
REDIS_PASSWORD=
REDIS_PORT=
REDIS_USER=
REDIS_TLS=false
# redis[s]://[[username][:password]@][host][:port][/db-number]
REDIS_URL=redis://localhost:6379
EXPRESS_SESSION_SECRET=gauzy
# JWT Configuration
JWT_SECRET=secretKey
JWT_TOKEN_EXPIRATION_TIME=86400
# JWT Refresh Token Configuration
JWT_REFRESH_TOKEN_SECRET=refreshSecretKey
JWT_REFRESH_TOKEN_EXPIRATION_TIME=86400
# Email Verification Config
JWT_VERIFICATION_TOKEN_SECRET=verificationSecretKey
JWT_VERIFICATION_TOKEN_EXPIRATION_TIME=86400
# Password Less Authentication Configuration
MAGIC_CODE_EXPIRATION_TIME=600
# Join Request Organization Team Configuration
TEAM_JOIN_REQUEST_EXPIRATION_TIME=86400
# Rate Limiting
THROTTLE_ENABLED=false
THROTTLE_TTL=60000 # 1 minute
THROTTLE_LIMIT=60000
# CORS Allowed Origins (comma-separated list of trusted origins)
# If not set, all origins (*) are allowed. In production, set this to your trusted domains.
# ALLOWED_ORIGINS=http://localhost:4200,http://localhost:3000
# Twitter OAuth Configuration
TWITTER_CLIENT_ID=
TWITTER_CLIENT_SECRET=
TWITTER_CALLBACK_URL=http://localhost:3000/api/auth/twitter/callback
# Google OAuth Configuration
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_CALLBACK_URL=http://localhost:3000/api/auth/google/callback
# Facebook OAuth Configuration
FACEBOOK_CLIENT_ID=
FACEBOOK_CLIENT_SECRET=
FACEBOOK_CALLBACK_URL=http://localhost:3000/api/auth/facebook/callback
FACEBOOK_GRAPH_VERSION=v3.0
# Github OAuth App Integration
GAUZY_GITHUB_OAUTH_CLIENT_ID=
GAUZY_GITHUB_OAUTH_CLIENT_SECRET=
GAUZY_GITHUB_OAUTH_CALLBACK_URL="http://localhost:3000/api/auth/github/callback"
# Social sign-in by provider access token (POST /api/auth/signin.email.social, /api/auth/signup.link.account).
# Tokens are only accepted when issued to an allowed OAuth client. Gauzy's own apps above (GOOGLE_CLIENT_ID,
# GAUZY_GITHUB_OAUTH_CLIENT_ID/SECRET, FACEBOOK_CLIENT_ID/SECRET) are always allowed; list OTHER first-party
# clients (e.g. Ever Teams) here. Google: comma-separated client ids. GitHub/Facebook: comma-separated
# clientId:clientSecret pairs (the secret is needed to introspect the token). A provider with no client rejects all tokens.
GAUZY_SOCIAL_AUTH_GOOGLE_CLIENT_IDS=
GAUZY_SOCIAL_AUTH_GITHUB_APPS=
GAUZY_SOCIAL_AUTH_FACEBOOK_APPS=
# LinkedIn OAuth Configuration
LINKEDIN_CLIENT_ID=
LINKEDIN_CLIENT_SECRET=
LINKEDIN_CALLBACK_URL=http://localhost:3000/api/auth/linkedin/callback
# Microsoft OAuth Configuration
MICROSOFT_GRAPH_API_URL=https://graph.microsoft.com/v1.0
MICROSOFT_AUTHORIZATION_URL=https://login.microsoftonline.com/common/oauth2/v2.0/authorize
MICROSOFT_TOKEN_URL=https://login.microsoftonline.com/common/oauth2/v2.0/token
MICROSOFT_CLIENT_ID=
MICROSOFT_CLIENT_SECRET=
MICROSOFT_CALLBACK_URL=http://localhost:3000/api/auth/microsoft/callback
# Keycloak OAuth
KEYCLOAK_CLIENT_ID=
KEYCLOAK_CLIENT_SECRET=
KEYCLOAK_REALM=
KEYCLOAK_COOKIE_KEY=
KEYCLOAK_AUTH_SERVER_URL=https://keycloak.example.com/auth
KEYCLOAK_CALLBACK_URL=http://localhost:3000/api/auth/keycloak/callback
# Github Apps Integration
GAUZY_GITHUB_CLIENT_ID=XXXXXXX
GAUZY_GITHUB_CLIENT_SECRET=XXXXXXX
# Github App Install Integration
GAUZY_GITHUB_APP_NAME=
GAUZY_GITHUB_APP_ID=XXXXXXX
GAUZY_GITHUB_APP_PRIVATE_KEY=
# Github Webhook Configuration
GAUZY_GITHUB_WEBHOOK_URL=http://localhost:3000/api/auth/github/webhook
GAUZY_GITHUB_WEBHOOK_SECRET=XXXXXXX
# Github Redirect URL
GAUZY_GITHUB_REDIRECT_URL=http://localhost:3000/api/integration/github/callback
GAUZY_GITHUB_POST_INSTALL_URL="http://localhost:4200/#/pages/integrations/github/setup/installation"
GAUZY_GITHUB_API_VERSION="2022-11-28"
# Zapier Apps Integration
GAUZY_ZAPIER_CLIENT_ID=
GAUZY_ZAPIER_CLIENT_SECRET=
GAUZY_ZAPIER_REDIRECT_URL=http://localhost:3000/api/integration/zapier/oauth/callback
GAUZY_ZAPIER_POST_INSTALL_URL="http://localhost:4200/#/pages/integrations/zapier"
# Comma-separated list of domains allowed for OAuth redirects (security feature)
GAUZY_ZAPIER_ALLOWED_DOMAINS=gauzy.co,*.gauzy.co,ever.co,*.ever.co,zapier.com,*.zapier.com,localhost
# Maximum number of OAuth authorization codes to store in memory
GAUZY_ZAPIER_MAX_AUTH_CODES=1000
# Number of server instances (affects auth code cleanup behavior)
GAUZY_ZAPIER_INSTANCE_COUNT=1
# Third Party Integration Config
INTEGRATED_USER_DEFAULT_PASS=
# Upwork Integration Config
UPWORK_API_KEY=XXXXXXX
UPWORK_API_SECRET=XXXXXXX
UPWORK_REDIRECT_URL="http://localhost:3000/api/integrations/upwork/callback"
UPWORK_POST_INSTALL_URL="http://localhost:4200/#/pages/integrations/upwork"
# Hubstaff Integration Configuration
HUBSTAFF_CLIENT_ID=XXXXXXX
HUBSTAFF_CLIENT_SECRET=XXXXXXX
HUBSTAFF_REDIRECT_URL="http://localhost:3000/api/integration/hubstaff/callback"
HUBSTAFF_POST_INSTALL_URL="http://localhost:4200/#/pages/integrations/hubstaff"
# Format: https://hook.{region}.make.com/{webhook-id}
GAUZY_MAKE_WEBHOOK_URL=
# Make.com Platforms integration
GAUZY_MAKE_API_URL="https://hook.us2.make.com/api/v2"
GAUZY_MAKE_BASE_URL="https://www.make.com"
GAUZY_MAKE_CLIENT_ID=
GAUZY_MAKE_CLIENT_SECRET=
GAUZY_MAKE_REDIRECT_URL="${API_BASE_URL}/api/integration/make-com/oauth/callback"
GAUZY_MAKE_POST_INSTALL_URL="${CLIENT_BASE_URL}/#/pages/integrations/make"
GAUZY_MAKE_DEFAULT_SCOPES="offline_access"
# ActivePieces platforms integration
ACTIVEPIECES_BASE_URL="https://cloud.activepieces.com"
GAUZY_ACTIVEPIECES_API_KEY=
# Gauzy OAuth2 App (Activepieces -> Gauzy)
GAUZY_OAUTH_APP_CLIENT_ID=
GAUZY_OAUTH_APP_CLIENT_SECRET=
GAUZY_OAUTH_APP_CODE_SECRET=
GAUZY_OAUTH_APP_REDIRECT_URIS="http://localhost:4200/redirect,https://cloud.activepieces.com/redirect"
#SIM platform integration
SIM_DEFAULT_BASE_URL="https://www.sim.ai"
GAUZY_SIM_API_KEY=
# File System: LOCAL | S3 | WASABI | CLOUDINARY
FILE_PROVIDER=LOCAL
# AWS Config
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=us-east-1
AWS_S3_BUCKET=gauzy
# WASABI Config (optional)
WASABI_ACCESS_KEY_ID=
WASABI_SECRET_ACCESS_KEY=
WASABI_REGION=us-east-1
WASABI_SERVICE_URL=https://s3.wasabisys.com
WASABI_S3_BUCKET=gauzy
WASABI_S3_FORCE_PATH_STYLE=true
# DIGITALOCEAN Spaces Config (optional)
DIGITALOCEAN_ACCESS_KEY_ID=
DIGITALOCEAN_SECRET_ACCESS_KEY=
DIGITALOCEAN_REGION=us-east-1
DIGITALOCEAN_SERVICE_URL=
DIGITALOCEAN_CDN_URL=
DIGITALOCEAN_S3_BUCKET=gauzy
DIGITALOCEAN_S3_FORCE_PATH_STYLE=false
# Cloudinary Config (optional)
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
CLOUDINARY_API_SECURE=true
CLOUDINARY_CDN_URL=https://res.cloudinary.com
# Gauzy AI Endpoints (optional, do not set unless you subscribed to Gauzy AI)
GAUZY_AI_GRAPHQL_ENDPOINT=http://localhost:3005/graphql
GAUZY_AI_REST_ENDPOINT=http://localhost:3005/api
# Gauzy AI Key/Secret pair authentication
GAUZY_AI_API_KEY=
GAUZY_AI_API_SECRET=
# SMTP Mail Config
MAIL_FROM_ADDRESS=Gauzy@Ever.co
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=
MAIL_PASSWORD=
# Sentry Client Key
SENTRY_DSN=
SENTRY_HTTP_TRACING_ENABLED=false
SENTRY_POSTGRES_TRACKING_ENABLED=false
SENTRY_PROFILING_ENABLED=false
SENTRY_TRACES_SAMPLE_RATE=0.01
SENTRY_PROFILE_SAMPLE_RATE=0.01
# PostHog Configuration
POSTHOG_KEY=
POSTHOG_HOST=https://us.i.posthog.com
POSTHOG_ENABLED=false
POSTHOG_FLUSH_INTERVAL=10000
# Default Currency
DEFAULT_CURRENCY=USD
# Google Maps API Key
GOOGLE_MAPS_API_KEY=
# Chatwoot SDK Token
CHATWOOT_SDK_TOKEN=
# Restrict Access to Google Place Autocomplete
GOOGLE_PLACE_AUTOCOMPLETE=false
# Default Latitude and Longitude
DEFAULT_LATITUDE=
DEFAULT_LONGITUDE=
# Defines feature flags and settings related to user authentication methods.
FEATURE_EMAIL_PASSWORD_LOGIN=true
FEATURE_MAGIC_LOGIN=true
FEATURE_GITHUB_LOGIN=true
FEATURE_FACEBOOK_LOGIN=true
FEATURE_GOOGLE_LOGIN=true
FEATURE_TWITTER_LOGIN=true
FEATURE_MICROSOFT_LOGIN=true
FEATURE_LINKEDIN_LOGIN=true
#Features Toggles
FEATURE_DASHBOARD=true
FEATURE_TIME_TRACKING=true
FEATURE_ESTIMATE=true
FEATURE_ESTIMATE_RECEIVED=true
FEATURE_INVOICE=true
FEATURE_INVOICE_RECURRING=true
FEATURE_INVOICE_RECEIVED=true
FEATURE_INCOME=true
FEATURE_EXPENSE=true
FEATURE_PAYMENT=true
FEATURE_PROPOSAL=true
FEATURE_PROPOSAL_TEMPLATE=true
FEATURE_PIPELINE=true
FEATURE_PIPELINE_DEAL=true
FEATURE_DASHBOARD_TASK=true
FEATURE_TEAM_TASK=true
FEATURE_MY_TASK=true
FEATURE_JOB=true
FEATURE_EMPLOYEES=true
FEATURE_EMPLOYEE_TIME_ACTIVITY=true
FEATURE_EMPLOYEE_TIMESHEETS=true
FEATURE_EMPLOYEE_APPOINTMENT=true
FEATURE_EMPLOYEE_APPROVAL=true
FEATURE_EMPLOYEE_APPROVAL_POLICY=true
FEATURE_EMPLOYEE_LEVEL=true
FEATURE_EMPLOYEE_POSITION=true
FEATURE_EMPLOYEE_TIMEOFF=true
FEATURE_EMPLOYEE_RECURRING_EXPENSE=true
FEATURE_EMPLOYEE_CANDIDATE=true
FEATURE_MANAGE_INTERVIEW=true
FEATURE_MANAGE_INVITE=true
FEATURE_ORGANIZATION=true
FEATURE_ORGANIZATION_EQUIPMENT=true
FEATURE_ORGANIZATION_INVENTORY=true
FEATURE_ORGANIZATION_TAG=true
FEATURE_ORGANIZATION_VENDOR=true
FEATURE_ORGANIZATION_PROJECT=true
FEATURE_ORGANIZATION_DEPARTMENT=true
FEATURE_ORGANIZATION_TEAM=true
FEATURE_ORGANIZATION_DOCUMENT=true
FEATURE_ORGANIZATION_EMPLOYMENT_TYPE=true
FEATURE_ORGANIZATION_RECURRING_EXPENSE=true
FEATURE_ORGANIZATION_HELP_CENTER=true
FEATURE_CONTACT=true
FEATURE_GOAL=true
FEATURE_GOAL_REPORT=true
FEATURE_GOAL_SETTING=true
FEATURE_REPORT=true
FEATURE_USER=true
FEATURE_ORGANIZATIONS=true
FEATURE_APP_INTEGRATION=true
FEATURE_SETTING=true
FEATURE_EMAIL_HISTORY=true
FEATURE_EMAIL_TEMPLATE=true
FEATURE_IMPORT_EXPORT=true
FEATURE_FILE_STORAGE=true
FEATURE_PAYMENT_GATEWAY=true
FEATURE_SMS_GATEWAY=true
FEATURE_SMTP=true
FEATURE_ROLES_PERMISSION=true
# Email Verification
FEATURE_EMAIL_VERIFICATION=false
# Set the environment variable to enable/disable the global stats endpoint
FEATURE_OPEN_STATS=false
# Unleash Configuration
UNLEASH_APP_NAME=Gauzy
UNLEASH_API_URL=
UNLEASH_INSTANCE_ID=
UNLEASH_REFRESH_INTERVAL=15000
UNLEASH_METRICS_INTERVAL=60000
UNLEASH_API_KEY=
# GitHub App Integration
GITHUB_INTEGRATION_APP_ID=
GITHUB_INTEGRATION_CLIENT_ID=
GITHUB_INTEGRATION_CLIENT_SECRET=
GITHUB_INTEGRATION_PRIVATE_KEY=
GITHUB_INTEGRATION_WEBHOOK_SECRET=
# HubStaff Integration
HUBSTAFF_CLIENT_ID=
HUBSTAFF_CLIENT_SECRET=
HUBSTAFF_PERSONAL_ACCESS_TOKEN=
# Jitsu Browser Configuration
JITSU_BROWSER_URL=
JITSU_BROWSER_WRITE_KEY=
# Jitsu Server Configuration
JITSU_SERVER_URL=
JITSU_SERVER_WRITE_KEY=
JITSU_SERVER_DEBUG=
JITSU_SERVER_ECHO_EVENTS=
# Tracing Configuration
OTEL_ENABLED=false
OTEL_PROVIDER=zipkin
OTEL_SERVICE_NAME=
OTEL_EXPORTER_OTLP_PROTOCOL=
OTEL_EXPORTER_OTLP_HEADERS=
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=
OTEL_EXPORTER_OTLP_ENDPOINT=
ASPECTO_API_KEY=
HONEYCOMB_API_KEY=
HONEYCOMB_ENABLE_LOCAL_VISUALIZATIONS=
# Platform Logo resource URL (SVG is Recommended)
PLATFORM_LOGO='assets/images/logos/logo_Gauzy.svg'
# Desktop App 512x512 icon
GAUZY_DESKTOP_LOGO_512X512='assets/icons/icon_512x512.png'
# Platform Privacy URL
PLATFORM_PRIVACY_URL='https://gauzy.co/privacy'
# Platform terms of Services URL
PLATFORM_TOS_URL='https://gauzy.co/tos'
# Platform no internet logo
NO_INTERNET_LOGO='assets/images/logos/logo_Gauzy.svg'
# Company Information
COMPANY_NAME='Ever Co. LTD'
COMPANY_LINK='https://ever.co'
COMPANY_SITE_NAME='Gauzy'
COMPANY_SITE_LINK='https://gauzy.co'
COMPANY_GITHUB_LINK='https://github.com/ever-co'
COMPANY_GITLAB_LINK='https://gitlab.com/ever-co'
COMPANY_FACEBOOK_LINK='https://www.facebook.com/gauzyplatform'
COMPANY_TWITTER_LINK='https://twitter.com/gauzyplatform'
COMPANY_IN_LINK='https://www.linkedin.com/company/everhq'
# Desktop download links
DESKTOP_APP_DOWNLOAD_LINK_APPLE='https://gauzy.co/downloads#desktop/apple'
DESKTOP_APP_DOWNLOAD_LINK_WINDOWS='https://gauzy.co/downloads#desktop/windows'
DESKTOP_APP_DOWNLOAD_LINK_LINUX='https://gauzy.co/downloads#desktop/linux'
MOBILE_APP_DOWNLOAD_LINK='https://gauzy.co/downloads#mobile'
EXTENSION_DOWNLOAD_LINK='https://gauzy.co/downloads#extensions'
# Desktop Timer Application Configuration
PROJECT_REPO='https://github.com/ever-co/ever-gauzy.git'
DESKTOP_TIMER_APP_NAME='gauzy-desktop-timer'
DESKTOP_TIMER_APP_DESCRIPTION='Gauzy Desktop Timer'
DESKTOP_TIMER_APP_ID='com.ever.gauzydesktoptimer'
DESKTOP_TIMER_APP_REPO_NAME='ever-gauzy-desktop-timer'
DESKTOP_TIMER_APP_REPO_OWNER='ever-co'
DESKTOP_TIMER_APP_WELCOME_TITLE=
DESKTOP_TIMER_APP_WELCOME_CONTENT=
DESKTOP_TIMER_APP_PROTOCOL='gauzy-timer'
# Desktop Application Configuration
DESKTOP_APP_NAME='gauzy-desktop'
DESKTOP_APP_DESCRIPTION='Gauzy Desktop'
DESKTOP_APP_ID='com.ever.gauzydesktop'
DESKTOP_APP_REPO_NAME='ever-gauzy-desktop'
DESKTOP_APP_REPO_OWNER='ever-co'
DESKTOP_APP_WELCOME_TITLE=
DESKTOP_APP_WELCOME_CONTENT=
DESKTOP_APP_PROTOCOL='gauzy-desktop'
# Desktop Server Application Configuration
DESKTOP_SERVER_APP_NAME='gauzy-server'
DESKTOP_SERVER_APP_DESCRIPTION='Gauzy Server'
DESKTOP_SERVER_APP_ID='com.ever.gauzyserver'
DESKTOP_SERVER_APP_REPO_NAME='ever-gauzy-server'
DESKTOP_SERVER_APP_REPO_OWNER='ever-co'
DESKTOP_SERVER_APP_WELCOME_TITLE=
DESKTOP_SERVER_APP_WELCOME_CONTENT=
DESKTOP_SERVER_APP_PROTOCOL='gauzy-server'
# Desktop API Server Application Configuration
DESKTOP_API_SERVER_APP_NAME='gauzy-api-server'
DESKTOP_API_SERVER_APP_DESCRIPTION='Gauzy API Server'
DESKTOP_API_SERVER_APP_ID='com.ever.gauzyapiserver'
DESKTOP_API_SERVER_APP_REPO_NAME='ever-gauzy-api-server'
DESKTOP_API_SERVER_APP_REPO_OWNER='ever-co'
DESKTOP_API_SERVER_APP_WELCOME_TITLE=
DESKTOP_API_SERVER_APP_WELCOME_CONTENT=
DESKTOP_API_SERVER_APP_PROTOCOL='gauzy-api-server'
#AGENT
AGENT_APP_PROTOCOL='gauzy-agent'
REGISTER_URL='https://app.gauzy.co/#/auth/register'
FORGOT_PASSWORD_URL='https://app.gauzy.co/#/auth/request-password'
# I18N Translation Files URL
I18N_FILES_URL=
# MCP Server Configuration
API_TIMEOUT=30000
GAUZY_AUTH_EMAIL=your-email@example.com
GAUZY_AUTH_PASSWORD=your-secure-password
GAUZY_AUTO_LOGIN=false
GAUZY_MCP_DEBUG=false
MCP_APP_ID=co.gauzy.mcp-server
MCP_APP_NAME="Gauzy MCP Server"
NODE_ENV=development
# MCP Transport Configuration
# Options: stdio | http | websocket
MCP_SERVER_MODE="stdio" # Internal server runtime mode
MCP_TRANSPORT="stdio" # Exposed transport (used by TransportFactory)
# HTTP Transport Settings
MCP_AUTH_BASE_URL=http://localhost:3003
MCP_AUTH_PORT=3003
MCP_CORS_CREDENTIALS=true
MCP_CORS_ORIGIN=http://localhost:3000,http://localhost:4200,http://127.0.0.1:3000,http://127.0.0.1:4200
MCP_HTTP_HOST=localhost
MCP_HTTP_PORT=3001
# Session Management
MCP_AUTH_SESSION_SECRET=your-secure-session-secret
MCP_SESSION_COOKIE_NAME=mcp-session-id
MCP_SESSION_ENABLED=true
MCP_SESSION_TTL=1800000
MCP_TRUSTED_PROXIES=
# WebSocket Transport Settings
# DEV ONLY; set specific origins in production
MCP_WS_ALLOWED_ORIGINS="*"
MCP_WS_CERT_PATH=path/to/your/certs/cert.pem
MCP_WS_COMPRESSION=true
MCP_WS_HOST=localhost
MCP_WS_KEY_PATH=path/to/your/certs/key.pem
# Default 1MB is safer; increase only if you must handle large messages
MCP_WS_MAX_PAYLOAD=1048576
MCP_WS_PATH="/sse" # Realtime endpoint path (WS server behind /sse by default)
MCP_WS_PER_MESSAGE_DEFLATE=true
MCP_WS_PORT=3002
MCP_WS_SESSION_COOKIE_NAME=mcp-ws-session-id
MCP_WS_SESSION_ENABLED=true
MCP_WS_TLS=false
MCP_WS_TRUSTED_PROXIES=
# OAuth 2.0 Authorization Configuration (Development)
MCP_AUTH_ENABLED=true
MCP_AUTH_REQUIRED_SCOPES=mcp.read,mcp.write
MCP_AUTH_RESOURCE_URI=http://localhost:3001/sse
# JWT validation - RS256 for OAuth server tokens
MCP_AUTH_JWT_ALGORITHMS=RS256
MCP_AUTH_JWT_AUDIENCE=http://localhost:3001/sse
MCP_AUTH_JWT_ISSUER=http://localhost:3003
MCP_AUTH_JWT_JWKS_URI=http://localhost:3003/.well-known/jwks.json
# Cache settings
MCP_AUTH_METADATA_CACHE_TTL=3600
MCP_AUTH_TOKEN_CACHE_TTL=300
# Authorization server configuration (mock for development)
MCP_AUTH_SERVERS='[{"issuer":"http://localhost:3003","authorizationEndpoint":"http://localhost:3003/oauth2/authorize","tokenEndpoint":"http://localhost:3003/oauth2/token","grantTypesSupported":["authorization_code","client_credentials","refresh_token"],"responseTypesSupported":["code"],"scopesSupported":["mcp.read","mcp.write","mcp.admin"],"codeChallengeMethodsSupported":["S256"]}]'