-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathalkemio.yml
More file actions
730 lines (636 loc) · 33.8 KB
/
Copy pathalkemio.yml
File metadata and controls
730 lines (636 loc) · 33.8 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
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
# Configuration file for Alkemio.
#
# This is a YAML file: see [1] for a quick introduction. Note in particular
# that *indentation is important*: all the elements of a list or dictionary
# should have the same indentation.
#
# [1] https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
## endpoints ##
# External endpoint URLs surfaced into outbound payloads (e.g., the post-commit
# acknowledgement notification sent to a user's new login email — see spec 097
# §FR-016c). These are URLs targeted at end-user browsers, distinct from the
# internal `hosting.*` paths used by the platform itself.
endpoints:
# The base URL of the public client-web application. Used by post-commit
# email-change notifications to build a login deep link for the recipient.
client_web: ${ENDPOINTS_CLIENT_WEB}:http://localhost:3000
## hosting ##
# The hosting configuration for the Alkemio Server
hosting:
environment: ${ENVIRONMENT}:local
# The port that the Alkemio server will be listening on.
# For clusters (e.g. docker-compose, kubernetes) this should also be the port that is used in the ingress configuration (e.g. traefik).
# This is then used for routing the requests from the public-facing endpoint (e.g. https://dev.alkem.io/graphql)
# to the alkemio-server service, orchestrated with the orchestration engine of your choice, e.g. kubernetes or docker-compose.
# The graphql port is also used for internal communication between the services inside the e.g. kubernetes cluster.
#
port: ${GRAPHQL_PORT}:4000
# The entry point for the cluster
endpoint_cluster: ${ENDPOINT_CLUSTER}:http://localhost:3000
# The path from the end point for all public api rest requests.
# It is combined with the `endpoint` above to provide the full path for incoming requests targeting the public Rest api.
#
path_api_public_rest: ${PATH_API_PUBLIC_REST}:/api/public/rest
# The path from the end point for all private api rest requests.
# It is combined with the `endpoint` above to provide the full path for incoming requests targeting the public Rest api.
#
path_api_private_rest: ${PATH_API_PRIVATE_REST}:/api/private/rest
# Support for subscriptions enabled or not. These require a WebSocket connection
subscriptions:
enabled: ${SUBSCRIPTIONS_ENABLED}:true
# Support for subscriptions enabled or not. These require a WebSocket connection
whiteboard_rt:
port: ${WHITEBOARD_RT_PORT}:4001
max_json_payload_size: ${HOSTING_MAX_JSON_PAYLOAD_SIZE}:64mb
# Settings related to the authorization framework
authorization:
# amount of authorization policies saved in a single chunk
chunk: ${AUTHORIZATION_CHUNK_SIZE}:1000
## security ##
# The various means by which the security of the Alkemio platform can be configured.
security:
# cors settings for the application
cors:
# Need to be able to disable cors checks on the server when running behind another reverse proxy that is setting
# a cors origin header e.g. oathkeeper
enabled: ${CORS_ENABLED}:true
# Origin of the graphql requests to the Alkemio Server.
# Defaults to * (insecure, not recommended for production usage).
# Change to a value that whitelists your request origin.
origin: ${CORS_ORIGIN}:*
# Cors methods allowed in the Alkemio Server.
# Defaults to GET,HEAD,PUT,PATCH,POST,DELETE.
# Graphql uses mostly POST - the rest of the methods are left for utility REST endpoints.
# If no REST endpoints are used (they are kept for ease of development) the list of allowed methods can be reduced.
methods: ${CORS_METHODS}:GET,HEAD,PUT,PATCH,POST,DELETE
# Cors allowed headers.
allowed_headers: ${CORS_ALLOWED_HEADERS}:Origin,X-Requested-With,Content-Type,Accept,Authorization
encryption_key: ${ENCRYPTION_KEY}:ktO2wPinKwidG8cgjhfKTHGqU6D5lxP0NkCVAJglnfw=
innovation_hub:
header: ${INNOVATION_HUB_HEADER}:origin
# comma separated list of subdomains that are not an innovation hub (starting page)
whitelisted_subdomains: ${INNOVATION_HUB_WHITELISTED_SUBDOMAINS}:identity
search:
# max results per search
max_results: ${SEARCH_MAX_RESULTS}:40
# the index pattern used when ingesting data in Elasticsearch, e.g. alkemio-data-[organization];
# The dash at the end is MANDATORY
index_pattern: ${ELASTIC_SEARCH_INDEX_PATTERN}:alkemio-data-
# Pre-parse source-file-size cap (bytes) for in-process Collabora office-document
# text extraction (workspace#009-office-doc-search, FR-018). A document whose raw
# file exceeds this cap is skipped for content indexing (handled like a no-text
# document) to protect the in-process parser from OOM/hang. Default 15 MiB —
# matches the largest per-document storage cap (storage.file.max_file_size and
# StorageBucketService.DEFAULT_MAX_ALLOWED_FILE_SIZE), so a document that can be
# uploaded can always be parsed. Raising it above that has no effect.
collabora_document_max_source_size: ${SEARCH_COLLABORA_DOCUMENT_MAX_SOURCE_SIZE}:15728640
trustGateway:
# Local host-run default; deployments must set TRUST_GATEWAY_URL to the cluster Service.
url: ${TRUST_GATEWAY_URL}:http://localhost:8080
licensing:
wingback:
enabled: ${LICENSING_WINGBACK_ENABLED}:false
key: ${LICENSING_WINGBACK_API_KEY}
endpoint: ${LICENSING_WINGBACK_API_ENDPOINT}
retries: ${LICENSING_WINGBACK_RETRY}:3
timeout: ${LICENSING_WINGBACK_TIMEOUT}:30000
webhook_secret:
name: ${LICENSING_WINGBACK_WEBHOOK_SECRET_NAME}:wb-secret
value: ${LICENSING_WINGBACK_WEBHOOK_SECRET_VALUE}
## identity ##
# Defines all authentication and authorization configuration.
# Authentication is pluggable, using the notion of "Authentication Providers", which have the responsibility to authenticate users.
# Authorization is handled within the platform.
#
# Note: the term Authentication Provider is based on the more widely understood concept of Identity Providers (Servers, Services),
# but it is in Alkemio restricted to Authentication. Configuration is unique per provider.
#
# The only functionality used from an Authentication Provider is acquiring an access token (in other words, authentication) and
# extracting the users email .
# The email is used for matching the user account (provided from the Identity Server, e.g. Ory Kratos) to the user profile in Alkemio.
# Traditional Identity Provider functionality like federation, account management etc. are out-of-scope in Alkemio.
#
# Authorization is Credential-based, validating whether the user has valid credentials for the requested resource.
identity:
## authentication ##
# Defines both the configuration required for the server to process authentication requests (via passportJS strategies) and the
# client-side configuration required to authenticate to the Identity Servers (e.g. Ory Kratos) and generate
# valid Authorization Header (Bearer access token).
authentication:
# Time-to-live of the cache for user authentication info (credentials, verified credentials) in seconds. Defaults to 60.
cache_ttl: ${AUTH_CACHE_TTL}:60
# A list of Identity Providers that can be used for authenticating the user.
# The claims in the access token that are used in Alkemio are the user email and the token expiration time.
providers:
# Ory Kratos Next Gen Identity Provider (https://github.com/ory/kratos).
ory:
# Issuer of the kratos cookie. The cookie can be used as is or mutated by
# Ory Oathkeeper into an ID token. The session can be found at (default)
# http://localhost:4433/sessions/whoami
# A session looks like:
#
# {
# "id": "b237fd33-cb69-4670-a154-7c70f7d8db52",
# "active": true,
# "expires_at": "2021-05-20T13:29:55Z",
# "authenticated_at": "2021-05-19T13:29:55Z",
# "issued_at": "2021-05-19T13:29:55Z",
# "identity": {
# "id": "972164de-efdd-4a4c-bfcb-382a9ba9b6f4",
# "schema_id": "default",
# "schema_url": "http://localhost:4455/.ory/kratos/public/schemas/default",
# "traits": {
# "name": { "last": "Admin", "first": "Admin" },
# "email": "admin@alkem.io"
# },
# "verifiable_addresses": [
# {
# "id": "f271a114-ef14-4f07-9899-5c1dbfeebee1",
# "value": "admin@alkem.io",
# "verified": false,
# "via": "email",
# "status": "sent",
# "verified_at": null
# }
# ],
# "recovery_addresses": [
# {
# "id": "796b183e-49b0-493f-acbc-c821dd4eb177",
# "value": "admin@alkem.io",
# "via": "email"
# }
# ]
# }
# }
issuer: ${AUTH_ORY_KRATOS_ISSUER}:http://alkemio-server-dev/
# JSON Web Key Sets endpoint. Used for validating the JWT token signed
# by Ory Oathkeeper. A set of keys looks like:
# {
# "keys": [
# {
# "use": "sig",
# "kty": "RSA",
# "kid": "a2aa9739-d753-4a0d-87ee-61f101050277",
# "alg": "RS256",
# "n": "zpjSl0ySsdk_YC4ZJYYV-cSznWkzndTo0lyvkYmeBkW60YHuHzXaviHqonY_DjFBdnZC0Vs_QTWmBlZvPzTp4Oni-eOetP-Ce3-B8jkGWpKFOjTLw7uwR3b3jm_mFNiz1dV_utWiweqx62Se0SyYaAXrgStU8-3P2Us7_kz5NnBVL1E7aEP40aB7nytLvPhXau-YhFmUfgykAcov0QrnNY0DH0eTcwL19UysvlKx6Uiu6mnbaFE1qx8X2m2xuLpErfiqj6wLCdCYMWdRTHiVsQMtTzSwuPuXfH7J06GTo3I1cEWN8Mb-RJxlosJA_q7hEd43yYisCO-8szX0lgCasw",
# "e": "AQAB"
# }
# ]
# }
jwks_uri: ${AUTH_ORY_KRATOS_JWKS_URI}:http://localhost:3000/jwks/.well-known/jwks.json
# Ory Kratos Base Public URL. It is used as prefix for all Kratos flows.
# Locally, Kratos Public API works on http://localhost:3000/ory/kratos/public and by default in k8s it works on https://[HOST]/ory/kratos/public
# NB: The default kratos.yml config defines the selfservice endpoints with base address http://localhost:3000/identity.
# That is used as there is a reverse proxy in front of the Alkemio Web Client that forwards the calls to the Kratos Public URL.
# You can check the currently logged in user at http://localhost:3000/ory/kratos/public/sessions/whoami.
kratos_public_base_url: ${AUTH_ORY_KRATOS_PUBLIC_BASE_URL}:http://localhost:3000/ory/kratos/public
# Ory Kratos URL for usage by the Alkemio server when inside a cluster.
kratos_public_base_url_server: ${AUTH_ORY_KRATOS_PUBLIC_BASE_URL_SERVER}:http://localhost:3000/ory/kratos/public
kratos_admin_base_url_server: ${AUTH_ORY_KRATOS_ADMIN_BASE_URL_SERVER}:http://localhost:3000/ory/kratos
# credentials used for kratos related work flows
admin_service_account:
username: ${KRATOS_ADMIN_USERNAME}:kratos@alkem.io
password: ${KRATOS_ADMIN_PASSWORD}:kr@t0$!!
session_cookie_name: ${KRATOS_SESSION_COOKIE_NAME}:ory_kratos_session
# Hydra / OIDC Relying Party configuration (alkemio-server acts as BFF).
# Spec: specs/003-alkemio-oidc-idp/plan.md. Module: src/core/auth/oidc/.
oidc:
# Hydra OIDC issuer URL (used for discovery).
issuer_url: ${HYDRA_ISSUER_URL}:http://localhost:3000/
# Hydra JWKS endpoint used for Bearer JWT signature validation (jose).
jwks_url: ${HYDRA_JWKS_URL}:http://localhost:3000/.well-known/jwks.json
# Hydra client_id registered for alkemio-client-web (public client, PKCE-S256).
web_client_id: ${ALKEMIO_WEB_CLIENT_ID}:alkemio-web
# Redirect URI registered with Hydra for the alkemio-web client. MUST match the
# entry in the Hydra OAuth2Client CRD / local-dev seed exactly. Per-env overlays
# set the public hostname; local-dev defaults to the loopback callback path.
web_redirect_uri: ${OIDC_WEB_REDIRECT_URI}:http://localhost:3000/api/auth/oidc/callback
# Comma-separated allow-list of aud values accepted on Bearer JWTs (FR-024).
bearer_aud_allow_list: ${BEARER_AUD_ALLOW_LIST}:alkemio-web,synapse-client,element-client,ecosystem-analytics
# Refresh-token rotation leeway in seconds (FR-008 grace window overlap).
refresh_leeway_s: ${OIDC_REFRESH_LEEWAY_S}:30
# HS256 signing key for the alkemio_oidc_pre_auth cookie JWS (FR-017b).
# Base64url/hex of 32 random bytes. The defaults below are LOCAL-DEV ONLY —
# they live in this committed file and are NOT secret. Override per-env via
# the listed env var (sandbox/dev/test/prod overlays inject real secrets via
# the Alkemio-secrets operator); mint via:
# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
pre_auth_cookie_signing_key: ${PRE_AUTH_COOKIE_SIGNING_KEY}:placeholder-pre-auth-cookie-signing-key-change-me
# HS256 key for the authorization-request state parameter HMAC.
state_hmac_key: ${STATE_HMAC_KEY}:placeholder-state-hmac-key-change-me
# express-session secret for signing alkemio_session cookie.
session_signing_key: ${SESSION_SIGNING_KEY}:placeholder-session-signing-key-change-me
# alkemio_session cookie attributes. Per-env overlays set Secure + domain +
# per-env name suffix; the local-dev defaults below run over HTTP loopback.
cookie:
name: ${OIDC_SESSION_COOKIE_NAME}:alkemio_session
domain: ${OIDC_SESSION_COOKIE_DOMAIN}
secure: ${OIDC_SESSION_COOKIE_SECURE}:false
# Sliding idle window. Renewed lazily once past its half-life (see
# sessionRenewalMiddleware), so this is also the cookie maxAge and the
# Redis key TTL. Capped by the absolute ceiling below.
idle_ttl_s: ${OIDC_SESSION_COOKIE_IDLE_TTL_S}:1209600 # 14 days
# Absolute ceiling. Fixed at login (`absolute_expires_at = now + this`),
# never extended by activity or token refresh. Forces a full re-auth at
# this age regardless of activity. MUST be >= idle_ttl_s.
absolute_ttl_s: ${OIDC_SESSION_COOKIE_ABSOLUTE_TTL_S}:2592000 # 30 days
# Non-interactive credential→token endpoint for test harnesses and other
# clients that cannot perform the browser-based OIDC flow. Mounts
# POST /api/auth/non-interactive-login and a third Passport strategy
# (alongside cookie-session + hydra-bearer). The boot guard refuses to
# start when NODE_ENV=production AND enabled=true. Module:
# src/core/auth/non-interactive-login/.
non_interactive_login:
# Whether the endpoint is mounted and the strategy accepts tokens.
# MUST stay false in production environments.
enabled: ${ENABLE_NON_INTERACTIVE_LOGIN}:false
# HS256 signing key (hex or base64). Minimum 32 bytes when enabled.
# The default below is empty so a production boot with enabled=true
# would fail loudly. Mint via:
# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
signing_key: ${NON_INTERACTIVE_LOGIN_SIGNING_KEY}
# Minted JWT lifetime in seconds. 4 hours is enough for a full e2e
# suite without mid-run remint; tests cache and reuse.
token_ttl_s: ${NON_INTERACTIVE_LOGIN_TOKEN_TTL_S}:14400
## monitoring ##
# This section defines settings used for DevOps - monitoring providers, endpoints, logging configuration.
monitoring:
# logging & profiling section.
logging:
# A flag setting whether Winston Console transport will be enabled.
# If the flag is set to true logs of the appropriate level (see below) will be outputted to the console
# after the application has been bootstrapped.
# The NestJS bootstrap process is handled by the internal NestJS logging.
console_logging_enabled: ${LOGGING_CONSOLE_ENABLED}:true
# Logging level for outputs to console.
# Valid values are log|error|warn|debug|verbose.
level: ${LOGGING_LEVEL_CONSOLE}:verbose
# A flag enabling / disabling performance logging.
profiling_enabled: ${LOGGING_PROFILING_ENABLED}:true
# The logging format will be in json - useful for parsing
# if disabled - will be in a human readable form
json: ${LOGGING_FORMAT_JSON}:false
# Logging of the incoming requests to the server
requests:
# Log the full request object. NOT Recommended, because the object is huge.
full_logging_enabled: ${LOGGING_REQ_FULL_ENABLED}:false
# Log request headers. Requires Logging Level at least verbose.
headers_logging_enabled: ${LOGGING_REQ_HEADERS_ENABLED}:false
# Logging of the responses from the server
responses:
# Log response headers. Requires Logging Level at least verbose.
headers_logging_enabled: ${LOGGING_RES_HEADERS_ENABLED}:false
# To allow logging of a particular context to a file
context_to_file:
enabled: ${LOGGING_CONTEXT_ENABLED}:false
# The file name to use
filename: ${LOGGING_CONTEXT_FILENAME}:communication-events.log
# The context to actually log
context: ${LOGGING_CONTEXT_ID}:communication_events
# Sentry (client) logging configuration
sentry:
# A flag setting whether Sentry monitoring will be used on the client.
enabled: ${LOGGING_SENTRY_ENABLED}:false
# Logging end point for sentry
endpoint: ${LOGGING_SENTRY_ENDPOINT}
# Flag to control whether PII should be included on monitoring
submit_pii: ${LOGGING_SENTRY_PII_ENABLED}:false
# Set the Sentry environment variable to be used
environment: ${LOGGING_SENTRY_ENVIRONMENT}:development
# Elastic APM configuration
apm:
# Is real user monitoring enabled
rumEnabled: ${APM_RUM_ENABLED}:false
# Endpoint to the APM logging service where events are sent
endpoint: ${APM_ENDPOINT}
## communications ##
# Section defining all configuration parameters / endpoints required for communication between different actors (user-user, community-user etc) in Alkemio.
communications:
enabled: ${COMMUNICATIONS_ENABLED}:true
matrix:
connection_retries: ${COMMUNICATIONS_MATRIX_CONNECTION_RETRIES}:5
# Timeout in milliseconds for RPC calls to the Matrix adapter
connection_timeout: ${COMMUNICATIONS_MATRIX_CONNECTION_TIMEOUT}:30000
discussions:
enabled: ${COMMUNICATIONS_DISCUSSIONS_ENABLED}:true
## storage ##
# Alkemio uses multiple types of persistent storage, including SQL database, postgres database, file storage, redis.
storage:
#
enabled: ${STORAGE_ENABLED}:true
#
file:
# 15MB — the upload-middleware guard. Kept equal to
# StorageBucketService.DEFAULT_MAX_ALLOWED_FILE_SIZE, which every bucket is
# seeded with; a larger value here only defers rejection until after the
# whole file has been buffered. Raising it needs a storage_bucket migration.
max_file_size: ${STORAGE_MAX_FILE_SIZE}:15728640
# Timeout in milliseconds for reading file upload streams
stream_timeout_ms: ${STORAGE_STREAM_TIMEOUT_MS}:60000
# Database configuration for usage by the Alkemio Server.
# Uses PostgreSQL as the database backend.
# Note: both schema / database name are used for configuration and they need to have the same value.
database:
# Database host.
host: ${DATABASE_HOST}:localhost
# Database daemon port.
port: ${DATABASE_PORT}:5432
# Database username.
username: ${DATABASE_USERNAME}:synapse
# Database password.
password: ${DATABASE_PASSWORD}:synapse
# Database schema / database name.
schema: ${DATABASE_NAME}:alkemio
# Database schema / database name.
database: ${DATABASE_NAME}:alkemio
# Flag setting whether database operations should be logged to the console.
logging: ${ENABLE_ORM_LOGGING}:false
# Connection pool settings for PostgreSQL
pool:
# Maximum number of connections in the pool
max: ${DATABASE_POOL_MAX}:50
# Close idle connections after this many milliseconds
idle_timeout_ms: ${DATABASE_POOL_IDLE_TIMEOUT_MS}:30000
# Timeout for acquiring a connection in milliseconds
connection_timeout_ms: ${DATABASE_POOL_CONNECTION_TIMEOUT_MS}:10000
# PgBouncer compatibility settings
# Enable when connecting through PgBouncer in transaction pooling mode
pgbouncer:
# Set to true when using PgBouncer as connection pooler
enabled: ${PGBOUNCER_ENABLED}:false
# Statement timeout in milliseconds (prevents long-running queries from holding connections)
statement_timeout_ms: ${PGBOUNCER_STATEMENT_TIMEOUT_MS}:60000
local_storage:
# Absolute path
path: ${LOCAL_STORAGE_PATH}:.storage
# Go file-service HTTP API configuration
file_service:
# Base URL of the Go file-service internal API
url: ${FILE_SERVICE_URL}:http://localhost:3000
# HTTP request timeout in milliseconds (30s default for large file uploads)
timeout: ${FILE_SERVICE_TIMEOUT}:30000
# Number of retry attempts for transient errors
retries: ${FILE_SERVICE_RETRIES}:2
# Feature flag for gradual rollout
enabled: ${FILE_SERVICE_ENABLED}:true
# Collabora / WOPI service configuration
collabora:
# URL of the WOPI service (token issuance endpoint)
wopi_service_url: ${WOPI_SERVICE_URL}:http://localhost:3000
# Redis configuration
redis:
# Redis host
host: ${REDIS_HOST}:localhost
# Redis port
port: ${REDIS_PORT}:6379
# Redis timeout, in seconds
timeout: ${REDIS_TIMEOUT}:60
microservices:
rabbitmq:
# Connection in the form of 'amqp://[user]:[password]@[host]:[port]?heartbeat=30'
connection:
# RabbitMQ host
host: ${RABBITMQ_HOST}:localhost
# RabbitMQ AMQP port. Used by AMQP 0-9-1 and 1.0 clients without and with TLS
port: ${RABBITMQ_PORT}:5672
# RabbitMQ user
user: ${RABBITMQ_USER}:alkemio-admin
# RabbitMQ password
password: ${RABBITMQ_PASSWORD}:alkemio!
# Authorization / license reset queue. Consumed by the dedicated worker
# (src/main.worker.ts); the normal server publishes reset events here but
# never consumes them. Publisher and worker MUST agree on this name.
auth_reset:
queue: ${RABBITMQ_AUTH_RESET_QUEUE}:alkemio-auth-reset
# configuration for the event bus used by the AiServer
event_bus:
exchange: ${RABBITMQ_EVENT_BUS_EXCHANGE}:event-bus
ingest_body_of_knowledge_queue: ${RABBITMQ_INGEST_BODY_OF_KNOWLEDGE_QUEUE}:virtual-contributor-ingest-body-of-knowledge
ingest_body_of_knowledge_result_queue: ${RABBITMQ_INGEST_BODY_OF_KNOWLEDGE_RESULT_QUEUE}:virtual-contributor-ingest-body-of-knowledge-result
ingest_website_queue: ${RABBITMQ_INGEST_WEBSITE_QUEUE}:virtual-contributor-ingest-website
ingest_website_result_queue: ${RABBITMQ_INGEST_WEBSITE_RESULT_QUEUE}:virtual-contributor-ingest-website-result
invoke_engine_result: ${RABBITMQ_RESULT_QUEUE}:virtual-contributor-invoke-engine-result
invoke_engine_expert: ${RABBITMQ_INVOKE_ENGINE_EXPERT}:virtual-contributor-engine-expert
invoke_engine_libra_flow: ${RABBITMQ_INVOKE_ENGINE_LIBRA_FLOW}:virtual-contributor-engine-libra-flow
invoke_engine_guidance: ${RABBITMQ_INVOKE_ENGINE_GUIDANCE}:virtual-contributor-engine-guidance
invoke_engine_generic: ${RABBITMQ_INVOKE_ENGINE_GENERIC}:virtual-contributor-engine-generic
invoke_engine_openai_assistant: ${RABBITMQ_INVOKE_ENGINE_OPENAI_ASSISTANT}:virtual-contributor-engine-openai-assistant
# integrations with 3rd party services
integrations:
# Different types of geo information like lat, lan, city, country, etc...
geo:
enabled: ${GEO_ENABLED}:false
# Header used to get the user IP
header: ${GEO_HEADER}:x-forwarded-for
rest_endpoint: ${GEO_REST_ENDPOINT}:http://localhost:3000/api/public/rest/geo
# https://www.geoplugin.com/faq#i_stopped_getting_responses_from_geoplugin.net
service_endpoint: ${GEO_SERVICE_ENDPOINT}:http://www.geoplugin.net/json.gp?ip=
# How long (in seconds) the cache entry for a certain ip's geo will be held
cache_entry_ttl: ${GEO_CACHE_TTL}:14400
# Allowed amount of calls per time window
allowed_calls_to_service: ${GEO_SERVICE_CALL_LIMIT}:120
# Time window (in seconds) in which a certain amount of calls are allowed
allowed_calls_to_service_window: ${GEO_SERVICE_CALL_WINDOW}:60
geoapify:
enabled: ${GEOAPIFY_ENABLED}:false
geocode_rest_endpoint: ${GEOAPIFY_GEOCODE_REST_ENDPOINT}:https://api.geoapify.com/v1/geocode/search
api_key: ${GEOAPIFY_API_KEY}:'' # something like 4cfbe072a6904698aa21382c71a3a999
elasticsearch:
host: ${ELASTICSEARCH_URL}
api_key: ${ELASTICSEARCH_API_KEY}
retries: ${ELASTICSEARCH_RETRIES}:3
timeout: ${ELASTICSEARCH_TIMEOUT}:30000
indices:
contribution: ${ELASTIC_INDEX_ACTIVITY_NAME}:contribution-events
guidance_usage: ${ELASTIC_INDEX_GUIDANCE_USAGE_NAME}:guidance-usage
tls:
ca_cert_path: ${ELASTIC_TLS_CA_CERT_PATH}:none
rejectUnauthorized: ${ELASTIC_TLS_REJECT_UNAUTHORIZED}:false
notifications:
enabled: ${NOTIFICATIONS_ENABLED}:true
push:
enabled: ${PUSH_NOTIFICATIONS_ENABLED}:true
vapid:
public_key: ${VAPID_PUBLIC_KEY}:BKqdDhb3qBD7lNiqe-sxXQQqmxdMNfBjLPcj9kypfXfxv1LT_c4JS5gukL0Np3lhdd_jqqlZNR714gr2SGT-V44
private_key: ${VAPID_PRIVATE_KEY}:KGcZQvup8fMXYxkK1HZTfYJRqvnAOZ6x_F85dqiYcq8
subject: ${VAPID_SUBJECT}:mailto:notifications@alkem.io
max_subscriptions_per_user: ${PUSH_MAX_SUBSCRIPTIONS_PER_USER}:10
throttle:
max_per_minute: ${PUSH_THROTTLE_MAX_PER_MINUTE}:10
retry:
max_attempts: ${PUSH_RETRY_MAX_ATTEMPTS}:5
cleanup:
stale_days: ${PUSH_CLEANUP_STALE_DAYS}:30
in_app:
max_notifications_per_user: ${IN_APP_MAX_NOTIFICATIONS_PER_USER}:100
max_retention_period_days: ${IN_APP_MAX_RETENTION_PERIOD_DAYS}:90
# Callout-reaction notifications (041-callout-reaction-notifications).
# NOT declared on any deployment manifest this release — the in-code defaults
# below govern everywhere; flipping `enabled` requires a deploy (risk R-11).
callout_reactions:
enabled: ${CALLOUT_REACTION_NOTIFICATIONS_ENABLED}:true
email_suppression_window_seconds: ${CALLOUT_REACTION_EMAIL_SUPPRESSION_WINDOW_SECONDS}:300
# Chat/conversation message notifications (034-messaging-notifications).
# NOT declared on any deployment manifest this release (Operator Ruling 3b) —
# the in-code defaults below govern everywhere; flipping `enabled` in
# production requires a deploy (risk R-9).
messaging:
enabled: ${MESSAGING_NOTIFICATIONS_ENABLED}:true
# Operator Ruling R4 — messaging notifications are DEBOUNCED per recipient
# and then digested; nothing is sent on message arrival. Four independent
# tracks per recipient, each with its own quiet period and its own maximum
# delay cap. The cap is not optional: a pure reset-on-every-message
# debounce never fires in an active conversation, which would make the
# busiest conversations the quietest notifiers.
#
# Worst case dispatches per recipient per hour = 3600 / max_delay_seconds,
# INDEPENDENT of message volume. That bound is why the pre-R4 suppression
# window and both volume budgets were deleted (D-21).
#
# Every window is env-overridable because the live test stacks must run
# seconds-scale windows; the committed defaults are the production values.
# None of these vars are declared on any deployment manifest this release
# (Operator Ruling 3a/3b) — the literals below govern in production, and
# changing them requires a deploy (risk R-9).
#
# Validated at boot (fail fast): per track quiet <= max_delay, and
# sweep_interval <= the smallest quiet period.
digest:
# How often each replica sweeps the due queue. Lower = tighter adherence
# to the quiet periods below; cost is one ZRANGEBYSCORE per replica/tick.
sweep_interval_seconds: ${MESSAGING_DIGEST_SWEEP_INTERVAL_SECONDS}:10
max_dispatch_attempts: ${MESSAGING_DIGEST_MAX_DISPATCH_ATTEMPTS}:3
retry_backoff_seconds: ${MESSAGING_DIGEST_RETRY_BACKOFF_SECONDS}:60
# Push is the real-time channel, so it is faster than email; group is
# higher-volume and lower-salience per message, so it is slower than
# direct.
push:
direct:
quiet_period_seconds: ${MESSAGING_DIGEST_PUSH_DIRECT_QUIET_SECONDS}:60
max_delay_seconds: ${MESSAGING_DIGEST_PUSH_DIRECT_MAX_DELAY_SECONDS}:300
group:
quiet_period_seconds: ${MESSAGING_DIGEST_PUSH_GROUP_QUIET_SECONDS}:300
max_delay_seconds: ${MESSAGING_DIGEST_PUSH_GROUP_MAX_DELAY_SECONDS}:900
email:
direct:
quiet_period_seconds: ${MESSAGING_DIGEST_EMAIL_DIRECT_QUIET_SECONDS}:300
max_delay_seconds: ${MESSAGING_DIGEST_EMAIL_DIRECT_MAX_DELAY_SECONDS}:1800
group:
quiet_period_seconds: ${MESSAGING_DIGEST_EMAIL_GROUP_QUIET_SECONDS}:1200
max_delay_seconds: ${MESSAGING_DIGEST_EMAIL_GROUP_MAX_DELAY_SECONDS}:3600
collaboration:
# Server-side collaboration client: the unified collaboration-service the
# server joins as an ephemeral Yjs collaborator (MCP tools + content-replace
# paths). The url default is the host-run dev server; container deployments
# override COLLABORATION_SERVICE_URL to the in-cluster ws://collaboration-service:4006.
service:
# WebSocket base URL of the unified collaboration-service
url: ${COLLABORATION_SERVICE_URL}:ws://localhost:4006
# Actor-id header sent on the direct WS handshake; must match the
# collaboration-service AUTH_TOKEN_HEADER (the server connects directly, not
# through the gateway, so the header is not stripped/replaced by forwardAuth).
actor_id_header: ${COLLABORATION_SERVICE_ACTOR_ID_HEADER}:X-Alkemio-Actor-Id
# Connection handshake timeout in milliseconds
connect_timeout: ${COLLABORATION_SERVICE_CONNECT_TIMEOUT}:15000
# Correlated durability-barrier timeout in milliseconds
durability_timeout: ${COLLABORATION_SERVICE_DURABILITY_TIMEOUT}:20000
membership:
cache_ttl: ${MEMBERSHIP_TTL}:14400
whiteboards:
enabled: ${WHITEBOARDS_ENABLED}:true
max_collaborators_in_room: ${WHITEBOARD_MAX_COLLABORATORS_IN_ROOM}:20
memo:
enabled: ${MEMO_ENABLED}:true
max_collaborators_in_room: ${MEMO_MAX_COLLABORATORS_IN_ROOM}:20
## MCP Server ##
# Model Context Protocol server for AI client integrations.
# Exposes both read and write tools to AI assistants (platform content reads
# plus whiteboard create/edit), not read-only access.
mcp:
# Enable/disable the MCP server endpoint
enabled: ${MCP_ENABLED}:false
# Enable dedicated MCP API keys (in addition to Ory tokens)
api_key_enabled: ${MCP_API_KEY_ENABLED}:true
# Server-Sent Events configuration
sse:
# Heartbeat interval in milliseconds
heartbeat_interval_ms: ${MCP_SSE_HEARTBEAT_MS}:30000
# Connection timeout in milliseconds
connection_timeout_ms: ${MCP_SSE_TIMEOUT_MS}:300000
# Rate limiting configuration
rate_limit:
# Maximum requests per minute per client
requests_per_minute: ${MCP_RATE_LIMIT_RPM}:100
# Resource configuration
resources:
# Maximum items returned in list responses
max_response_items: ${MCP_MAX_RESPONSE_ITEMS}:100
## Language detection & offer configuration
# eligible: comma-separated list of language codes the platform proactively detects,
# offers via the banner, and accepts as invitation suggestions.
# Subset of the supported languages; an empty value disables all proactive offers.
# default: the platform-wide fallback language.
language:
eligible: ${LANGUAGE_ELIGIBLE}:nl
default: ${LANGUAGE_DEFAULT}:en
## Configuration of the legal / usability aspects of the platform
platform:
# Terms of usage that all users comply with
terms: ${PLATFORM_TERMS}:https://welcome.alkem.io/legal/terms/
# Privacy policy for the platform
privacy: ${PLATFORM_PRIVACY}:https://welcome.alkem.io/legal/privacy
# Security policy for the platform
security: ${PLATFORM_SECURITY}:https://welcome.alkem.io/legal/security
# Link for support requests
support: ${PLATFORM_SUPPORT}:https://welcome.alkem.io/contact/
# Link for latest platform release notification
forumreleases: ${PLATFORM_FORUM_RELEASES}:https://alkem.io/forum/releases/latest
# Feedback form for the platform
feedback: ${PLATFORM_FEEDBACK}:https://welcome.alkem.io/contact/
# About the platform
about: ${PLATFORM_ABOUT}:https://welcome.alkem.io
# landing
landing: ${PLATFORM_LANDING}:https://welcome.alkem.io/
# Blog
blog: ${PLATFORM_BLOG}:https://blog.alkem.io/
# Home page - Impact
impact: ${PLATFORM_IMPACT}:https://alkemio.org
# Collaboration tools
inspiration: ${PLATFORM_INSPIRATION}:https://welcome.alkem.io/resources/
# Innovation library
innovationLibrary: ${PLATFORM_INNOVATIONLIBRARY}:https://alkem.io/innovation-library
# Home page - Foundation
foundation: ${PLATFORM_FOUNDATION}:https://alkemio.org/
# Home page - Contact Support
contactsupport: ${PLATFORM_CONTACTSUPPORT}:https://welcome.alkem.io/contact/
# Home page - Switch Plan
switchplan: ${PLATFORM_SWITCHPLAN}:https://welcome.alkem.io/pricing/
# Home page - Opensource
opensource: ${PLATFORM_OPENSOURCE}:https://github.com/alkem-io/
# Home page - Opensource
releases: ${PLATFORM_RELEASES}:https://alkem.io/forum/releases/
# Help Dialog - Help
help: ${PLATFORM_HELP}:https://alkem.io/docs/
# Help Dialog - Community Forum
community: ${PLATFORM_COMMUNITY}:https://alkem.io/forum/
# Help Dialog - blog
newuser: ${PLATFORM_NEWUSER}:https://welcome.alkem.io/contact/
# Help Dialog - tips
tips: ${PLATFORM_TIPS}:https://welcome.alkem.io/contact/
# Acceptable Usage Policy
aup:
${PLATFORM_AUP}:https://welcome.alkem.io/legal/terms
# Documentation site path, endpoint is endpoint_cluster + documentation_path
documentation_path: ${PLATFORM_DOCUMENTATION_PATH}:/documentation
# Client can optionally work with a landing page, to give additional information
landing_page:
enabled: ${LANDING_PAGE_ENABLED}:false
# Configure usage of the guidance engine
guidance_engine:
enabled: ${GUIDANCE_ENGINE_ENABLED}:true
vector_db:
host: ${VECTOR_DB_HOST}:localhost
port: ${VECTOR_DB_PORT}:8765
credentials: ${VECTOR_DB_CREDENTIALS}:root\:toor
virtual_contributors:
history_length: ${VC_HISTORY_LENGTH}:30