Service Environment Variables¶
This document provides a comprehensive reference for all environment variables used by SyRF services.
Note: Environment variables are now managed via the Schema-Driven Code Generation system. See Env-Mapping Code Generation for the architecture and How-To: Extend Env-Mapping Schema for adding new variables.
Source of Truth¶
All environment variables are defined in a single schema file:
This schema generates:
- Helm templates (
_env-blocks.tpl) for .NET services - TypeScript interfaces for the web service
- JSON configuration files for NGINX envsubst
Overview¶
| Service | Total Env Vars | Prefix | Deployment Type |
|---|---|---|---|
| API | ~70 | SYRF__ |
.NET |
| project-management | ~70 | SYRF__ |
.NET |
| Quartz | ~75 | SYRF__ |
.NET |
| Web | ~48 | SYRF__ |
Angular/NGINX |
.NET Services (API, project-management, Quartz)¶
Common Environment Variables¶
These environment variables are shared across all .NET services.
GitVersion (Required)¶
Injected by CI/CD pipeline for version tracking.
| Variable | Values Path | Secret | Description |
|---|---|---|---|
VERSION |
.gitVersion.version |
No | SemVer version |
SYRF__GitVersion__SemVer |
.gitVersion.version |
No | SemVer version |
SYRF__GitVersion__FullSemVer |
.gitVersion.fullSemVer |
No | Full semantic version |
SYRF__GitVersion__InformationalVersion |
.gitVersion.informationalVersion |
No | Informational version |
SYRF__GitVersion__Sha |
.gitVersion.sha |
No | Git commit SHA |
SYRF__AppSettingsConfig__BuildNumber |
.gitVersion.version |
No | Build number |
Runtime Environment (Required)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__RuntimeEnvironment |
.environment.name |
No | production/staging/preview (local for local development). No default |
SYRF__ActiveEnvironment |
.environment.name |
No | Same value as SYRF__RuntimeEnvironment. No default |
ASPNETCORE_URLS |
.service.internalPort |
No | HTTP listener URL |
The api, project-management, quartz, identity and web charts no longer fall back to local
(issue #4231): local is on the runtime feature-flag mutable allow-lists, so a deployment whose
environment values went missing would have run as a mutable-flag environment. They read
environment.name only: environmentName is not a fallback, because cluster-gitops
global.values.yaml sets environmentName: local for every service. When environment.name is
unset, empty, whitespace-only or the literal "", the render fails with syrf-common: environment.name must be set by the environment values; refusing to default the runtime environment to "local". An explicit local is accepted.
Helper: syrf-common.runtimeEnvironment (src/charts/syrf-common/templates/_runtime-environment.tpl).
The pdf-agent chart (not syrf-common) likewise has no default environment.name; it already
required one of production, staging or preview.
The helper is the single source of truth for the runtime environment in these charts (PR #4249).
Every other environment-dependent expression reads it through
include "syrf-common.runtimeEnvironment" ., never environment.name | default .Values.environmentName.
So none of them can fall back to environmentName, local or Production:
| Consumer | Where | Effect of the environment |
|---|---|---|
SYRF__BulkPdfStorage__EnvironmentRoot conditions |
env-mapping.yaml (bulkPdfStorage) |
preview derives previews/pr-<n> from syrf.prNumber; other environments use bulkPdfStorage.environmentRoot |
Identity host environment (DOTNET_ENVIRONMENT/ASPNETCORE_ENVIRONMENT) |
identity/.chart/templates/deployment.yaml |
env.DOTNET_ENVIRONMENT, then env.ASPNETCORE_ENVIRONMENT, then environment.name |
| OpenIddict client secrets and signing/encryption key env vars; DataProtection block | env-mapping.yaml (identityOpenIddict, identityDataProtection) |
Rendered unless that host environment is Development (the useInDevelopment switches opt previews back in) |
| Preview OpenIddict key-material guards | identity/.chart/templates/deployment.yaml |
preview rejects PKCS12 material and overlap rotation |
| Identity campaign Job host environment and label | identity/.chart/templates/campaign-job.yaml |
development skips the DataProtection certificate mount |
auth.syrf.org/environment pod label |
syrf-common/templates/_deployment-dotnet.tpl |
Label value |
SYRF__ThemeCookie__Name |
syrf-common/templates/_theme-cookie.tpl |
syrf-theme in production, otherwise suffixed |
SYRF__EmailTransport__Provider (SMTP) |
syrf-common/templates/_email-transport.tpl |
Refused in production |
| Preview RabbitMQ vhost PreSync Job | api/.chart/templates/presync-rabbitmq-vhost.yaml |
Rendered only for preview with rabbitMq.previewPrincipal.enabled false (it used to nil-pointer without an environment map) |
Preview broker principal (SYRF__MessageBusConfig__RabbitMqConfig__Username / __Password) |
syrf-common/templates/_rabbitmq-preview-principal.tpl |
preview uses syrf-<namespace> and Secret rabbitmq-preview-principal unless rabbitMq.previewPrincipal.enabled is false |
Every chart that renders these expressions also renders SYRF__RuntimeEnvironment. So a render
that succeeds always has a non-empty environment.name, and the removed fallbacks could only be
reached by renders that already failed. Real production, staging and preview renders were
byte-identical before and after the change. Out of scope:
- The
preview-infrastructurechart keepsenvironment.name | default "preview". It is deployed only for previews, itsvalues.yamldefaultsenvironment.name: preview, and thesyrf-previewsApplicationSet always passesenvironment.name=preview. - The
s3-notifierchart's ownenvironmentNameisrequiredand names the bucket and Lambda.
Logging (Optional)¶
| Variable | Values Path | Secret | Default | Description |
|---|---|---|---|---|
SYRF__Logging__Console__LogLevel__Default |
.logging.level |
No | Information | Console log level |
SYRF__Logging__Debug__LogLevel__System |
.logging.level |
No | Information | System debug level |
SYRF__Logging__Debug__LogLevel__Default |
.logging.level |
No | Information | Default debug level |
SYRF__Logging__Debug__LogLevel__Microsoft |
.logging.level |
No | Information | Microsoft namespace level |
SYRF__Logging__IncludeScopes |
.logging.includeScopes |
No | false | Include log scopes |
SYRF__Serilog__MinimumLevel |
.logging.level |
No | Information | Serilog minimum level |
SYRF__Logging__Console__FormatterName |
.logging.format |
No | simple | Console log format: json emits one JSON object per event; any other value, including unset, renders plain text |
Credential hygiene. Hosts that share AddSyrfInstrumentationAndHealthChecks (and the
bootstrap logger) hold the Amazon log category at Warning or above regardless of
SYRF__Serilog__MinimumLevel or any Serilog:MinimumLevel:Override:Amazon value
(ConsoleLogFormat.ApplyAwsLoggingFloor), because the AWS SDK's diagnostics can carry the access key
ID. Code that logs a URL which may be presigned must pass it through AwsSignedUrlRedactor.Redact,
which masks X-Amz-Credential, X-Amz-Signature, X-Amz-Security-Token, AWSAccessKeyId and
Signature. Production code under src/libs and src/services must not write to System.Console
(direct writes bypass this redaction, and S3PostSigner once printed SigV4 requests, signatures and the
access key ID that way); NoConsoleOutputInProductionCodeTests enforces it, with an explicit allow-list for CLI
and start-up entry points.
SYRF__Logging__Console__FormatterName is honoured by the hosts that share
AddSyrfInstrumentationAndHealthChecks — API, project-management and Quartz. Identity pins
Serilog.Formatting.Json.JsonFormatter in its own appsettings.json, always emits JSON and does not
read this variable; its chart values declare format: json so the rendered variable describes what
the pod logs — with one exception: Identity's bootstrap logger (Program.cs, before the host is
built) writes plain text, so its first few startup lines are not JSON. The JSON shape is Serilog's
JsonFormatter with renderMessage: true:
{"Timestamp":…,"Level":…,"MessageTemplate":…,"RenderedMessage":…,"Properties":{…}}, so a
structured property is queried as Properties.<Name> while RenderedMessage carries the same
sentence the plain-text formatter would have printed — every substring an operator greps for today
still matches, inside that field. See the
Phase 2C staging-proof runbook
for worked queries.
Database Connections¶
MongoDB (Required for API, PM, Quartz)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__ConnectionStrings__MongoConnection__Username |
- | Yes | MongoDB username |
SYRF__ConnectionStrings__MongoConnection__Password |
- | Yes | MongoDB password |
SYRF__ConnectionStrings__MongoConnection__ClusterAddress |
.mongoDb.clusterAddress |
No | Cluster hostname. Required, no default: the render fails unless the environment sets it (or mongoDb.configMapName) |
SYRF__ConnectionStrings__MongoConnection__DatabaseName |
.mongoDb.databaseName |
No | Database name. Required, no default: the render fails unless the environment sets it (or mongoDb.configMapName) |
SYRF__ConnectionStrings__MongoConnection__AuthDb |
.mongoDb.authDb |
No | Auth database |
SYRF__ConnectionStrings__MongoConnection__UseSSL |
.mongoDb.ssl |
No | Enable SSL (default: true) |
Secret Reference: mongoDb.authSecretName with keys: username, password
There is no default cluster: an unset, empty, whitespace-only or literal "" cluster address or
database name fails the render with, for example, syrf-common: mongoDb.clusterAddress must be set by the environment values (or set mongoDb.configMapName); refusing to fall back to a default.
See MongoDB reference.
PostgreSQL (Required for API, PM)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__DatabaseConfig__PSqlConfig__Hostname |
.postgres.hostname |
No | PostgreSQL host |
SYRF__DatabaseConfig__PSqlConfig__Port |
.postgres.port |
No | PostgreSQL port |
SYRF__DatabaseConfig__PSqlConfig__Username |
.postgres.username |
No | Database username |
SYRF__DatabaseConfig__PSqlConfig__Database |
.postgres.database |
No | Database name |
SYRF__DatabaseConfig__PSqlConfig__Password |
- | Yes | Database password |
Secret Reference: postgres.authSecretName with key: postgresql-password
Elasticsearch (Optional)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__ConnectionStrings__ElasticConnection__ServerUrl |
.elastic.serverUrl |
No | Elasticsearch URL |
SYRF__ConnectionStrings__ElasticConnection__Username |
- | Yes | ES username |
SYRF__ConnectionStrings__ElasticConnection__Password |
- | Yes | ES password |
Secret Reference: elastic.authSecretName with keys: username, password
Quartz-Specific Databases¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__ConnectionStrings__quartz |
- | Yes | Quartz scheduler DB |
SYRF__ConnectionStrings__SqlConnection |
- | Yes | SQL Server connection |
Secret References: quartzSql.secretName, sqlServer.secretName with key: connectionString
Message Queue¶
RabbitMQ (Required)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__MessageBusConfig__RabbitMqConfig__Username |
.rabbitMq.username |
No | RabbitMQ user |
SYRF__MessageBusConfig__RabbitMqConfig__Password |
- | Yes | RabbitMQ password |
SYRF__MessageBusConfig__RabbitMqConfig__SchemeName |
.rabbitMq.schemeName |
No | Protocol (amqp/amqps) |
SYRF__MessageBusConfig__RabbitMqConfig__Hostname |
.rabbitMq.hostname |
No | RabbitMQ host |
SYRF__MessageBusConfig__RabbitMqConfig__Port |
.rabbitMq.port |
No | RabbitMQ port |
SYRF__MessageBusConfig__RabbitMqConfig__VirtualHost |
.rabbitMq.virtualHost |
No | Virtual host (default: namespace) |
SYRF__MessageBusConfig__RabbitMqConfig__*QueueName |
.rabbitMq.queueNames.* |
No | Dynamic queue names |
Secret Reference: rabbitMq.authSecretName with key: rabbitmq-password
Previews: with rabbitMq.previewPrincipal.enabled true (the default) a preview's API, PM and Quartz
use username syrf-<namespace> and Secret rabbitmq-preview-principal (key rabbitmq-password)
instead of rabbitMq.username, the ConfigMap's username and rabbitMq.authSecretName; setting it
false restores those values. No effect outside a preview
(src/charts/syrf-common/templates/_rabbitmq-preview-principal.tpl).
ConfigMap Support: All non-secret values can come from rabbitMq.configMapName
Cloud Services¶
AWS S3 (Required for API, PM)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__S3Settings__KeyId |
- | Yes | AWS Key ID |
SYRF__S3Settings__AccessKey |
- | Yes | AWS Access Key |
SYRF__S3Settings__BucketName |
.s3.bucketName |
No | S3 bucket name |
SYRF__S3Settings__Region |
.s3.region |
No | AWS region |
SYRF__S3Settings__MaxUploadPartSizeInMb |
.s3.upload.maxPartSizeMb |
No | Upload part size |
SYRF__S3Settings__MaxUploadConnections |
.s3.upload.maxConnections |
No | Max connections |
SYRF__S3Settings__UploadStreamBufferSize |
.s3.upload.streamBufferSize |
No | Buffer size |
Secret Reference: s3.authSecretName with keys: keyId, accessKey
AWS SES (Required for API, PM)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__SESSettings__KeyId |
- | Yes | AWS Key ID |
SYRF__SESSettings__AccessKey |
- | Yes | AWS Access Key |
SYRF__SESSettings__Region |
.ses.region |
No | AWS region |
SYRF__SESSettings__ConfigurationSetName |
.ses.configurationSetName |
No | SES config set |
SYRF__SESSettings__DevEmail |
.ses.devEmail |
No | Dev email address |
SYRF__SESSettings__RestrictEmailToDev |
.ses.restrictEmailToDev |
No | Restrict to dev only |
Secret Reference: ses.authSecretName with keys: keyId, accessKey
Authentication¶
Auth0 (Required)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__Auth0__ClientSecret |
- | Yes | Auth0 client secret |
SYRF__Auth0__ClientId |
.auth0.clientId |
No | Auth0 client ID |
SYRF__Auth0__CustomDomain |
.auth0.customDomain |
No | Custom domain |
SYRF__Auth0__Region |
.auth0.region |
No | Auth0 region |
SYRF__Auth0__Tenant |
.auth0.tenant |
No | Auth0 tenant |
SYRF__Auth0__ApiAudience |
.auth0.apiAudience |
No | API audience |
Secret Reference: auth0.clientSecretName with key: clientSecret
Swagger Auth (API Only)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__SwaggerAuthConfig__ClientId |
.swaggerAuthConfig.clientId |
No | Swagger client ID |
Swagger uses a public PKCE client; no client secret is mapped or rendered.
Observability¶
Sentry (Optional)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__CustomSentryConfig__Enabled |
.sentry.enabled |
No | Enable Sentry |
SYRF__CustomSentryConfig__TracingSampleRate |
.sentry.tracingSampleRate |
No | Tracing sample rate |
SYRF__CustomSentryConfig__OpenTelemetryTracing |
.sentry.openTelemetryTracing |
No | OTel integration |
SYRF__Sentry__Dsn |
- | Yes | Sentry DSN |
Secret Reference: sentry.authSecretName with key: {chart-name} (e.g., api, project-management)
Elastic APM (Optional)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__ElasticApm__Enabled |
.elasticApm.enabled |
No | Enable APM |
SYRF__ElasticApm__ServiceName |
Chart annotation | No | Service display name |
SYRF__ElasticApm__ServerUrl |
- | Yes | APM server URL |
SYRF__ElasticApm__LogLevel |
.elasticApm.logLevel |
No | APM log level |
SYRF__ElasticApm__SecretToken |
- | Yes | APM secret token |
Secret Reference: elasticApm.authSecretName with keys: serverUrl, secretToken
External Integrations¶
Google Sheets (API, PM)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__GoogleSheetsConfig__ServiceAccountEmail |
- | Yes | Service account email |
SYRF__GoogleSheetsConfig__CertificationPassword |
- | Yes | Cert password |
SYRF__GoogleSheetsConfig__ProtocolSheetId |
.googleSheets.protocolSheetId |
No | Protocol sheet ID |
SYRF__GoogleSheetsConfig__FaqSheetId |
.googleSheets.faqSheetId |
No | FAQ sheet ID |
SYRF__GoogleSheetsConfig__LibrarySheetId |
.googleSheets.librarySheetId |
No | Library sheet ID |
SYRF__GoogleSheetsConfig__KeyFileLocation |
.googleSheets.keyFileMount |
No | Key file path |
Secret Reference: googleSheets.authSecretName with keys: serviceAccountEmail, password, key-cert
Volume Mount: Mounts key cert as /credentials/google-sheet-key.p12
Mothballed AI risk-of-bias prototype¶
The external MapsGroup integration and its RobApiSettings environment mapping were
removed. See the retirement boundary. Existing
external secrets are left untouched and are no longer consumed by these services.
Public API (API Only)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__PublicApiConfig__ApiKey |
- | Yes | Public API key |
Secret Reference: publicApiConfig.secretName with key: apiKey
Application Settings¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SYRF__AppSettingsConfig__UiUrl |
.frontend |
No | Frontend URL |
SYRF__AppSettingsConfig__MinUiVersion |
.appSettings.minUiVersion |
No | Minimum UI version |
Web Service (Angular)¶
The web service uses environment variables with the standardised SYRF__ prefix. These are injected at container startup via NGINX envsubst.
Note: The web service previously used
SPA__prefix. This has been standardised toSYRF__for consistency across all services. See env-mapping.yaml for the current schema.
Version Information¶
| Variable | Values Path | Description |
|---|---|---|
VERSION |
.gitVersion.version |
SemVer version |
SPA__GitVersion |
.gitVersion.version |
SemVer version |
SPA__GitInformationalVersion |
.gitVersion.informationalVersion |
Informational version |
SPA__GitFullSemVer |
.gitVersion.fullSemVer |
Full semantic version |
SPA__GitVersion__Sha |
.gitVersion.sha |
Git commit SHA |
API Configuration¶
| Variable | Values Path | Description |
|---|---|---|
SPA__ApiOrigin |
.api.origin |
API base URL |
SPA__ProtectedUrls |
.api.protectedUrls |
Semicolon-separated URLs |
SPA__StsUrl |
Hardcoded | Auth endpoint URL |
SPA__UserGuideUrl |
.syrf.userGuideUrl |
User guide link |
Authentication (Auth0)¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SPA__Auth0Tenant |
.auth0.tenant |
No | Auth0 tenant |
SPA__Auth0Domain |
.auth0.domain |
No | Auth0 domain |
SPA__Auth0ClientId |
.auth0.clientId |
No | Auth0 client ID |
SPA__Auth0Region |
.auth0.region |
No | Auth0 region |
SPA__ApiAudience |
.auth0.apiAudience |
No | API audience |
SPA__Auth0ApiAudience |
.auth0.apiAudience |
No | API audience (duplicate) |
Observability¶
| Variable | Values Path | Secret | Description |
|---|---|---|---|
SPA__ErrorTracking |
.sentry.enabled |
No | Enable error tracking |
SPA__SentryDsn |
- | Yes | Sentry DSN |
SPA__GoogleAnalyticsToken |
Hardcoded | No | GA tracking ID |
SPA__LogRocketEnabled |
.featureFlags.logRocket |
No | Enable LogRocket |
Secret References:
sentry.authSecretNamewith key:web
Feature Flags¶
All feature flags are non-secret configuration values:
| Variable | Values Path | Default | Description |
|---|---|---|---|
SYRF__RuntimeEnvironment |
.environment.name (syrf-common.runtimeEnvironment) |
none: the render fails when unset | Environment name |
SPA__RobToolEnabled |
.featureFlags.robToolEnabled |
false | ROB tool feature |
SPA__StudyFiltersConfigurable |
.featureFlags.studyFilters |
false | Study filters |
SPA__ShowContactUsForm |
.featureFlags.contactUsForm |
false | Contact form |
SPA__MockHttp |
.featureFlags.mockHttp |
false | Mock HTTP |
SPA__MockAuth |
.featureFlags.mockAuth |
false | Mock auth |
SPA__Graph2DataEnabled |
.featureFlags.graph2Data |
false | Graph2Data |
SPA__SignalRActive |
.featureFlags.signalRActive |
false | SignalR |
SPA__NewQuestionManagement |
.featureFlags.newQuestionManagement |
false | Question mgmt |
SPA__NewProgressIndicators |
.featureFlags.newProgressIndicators |
false | Progress UI |
SPA__VersionMismatchCheck |
.featureFlags.versionMismatchCheck |
false | Version check |
SPA__MockStats |
.featureFlags.mockStats |
false | Mock stats |
SPA__ShowStageOverviewAreaCharts |
.featureFlags.showStageOverviewAreaCharts |
false | Area charts |
SPA__NewStageOverview |
.featureFlags.newStageOverview |
false | Stage overview |
SPA__NewScreeningOverview |
.featureFlags.newScreeningOverview |
false | Screening UI |
SPA__ShowUpdateInclusionInfo |
.featureFlags.showUpdateInclusionInfo |
false | Inclusion info |
Secret Summary¶
All Kubernetes secrets required by the services:
| Secret Name | Used By | Keys |
|---|---|---|
mongoDb.authSecretName |
API, PM | username, password |
postgres.authSecretName |
API, PM | postgresql-password |
elastic.authSecretName |
API, PM | username, password |
rabbitMq.authSecretName |
ALL .NET | rabbitmq-password |
s3.authSecretName |
API, PM | keyId, accessKey |
ses.authSecretName |
API, PM | keyId, accessKey |
auth0.clientSecretName |
ALL .NET | clientSecret |
sentry.authSecretName |
ALL | {chart-name}, web |
elasticApm.authSecretName |
ALL .NET | serverUrl, secretToken |
googleSheets.authSecretName |
API, PM | serviceAccountEmail, password, key-cert |
publicApiConfig.secretName |
API | apiKey |
quartzSql.secretName |
Quartz | connectionString |
sqlServer.secretName |
Quartz | connectionString |
ConfigMap Support¶
Most non-secret values can be read from ConfigMaps instead of direct values. The pattern is:
# In values.yaml
mongoDb:
configMapName: syrf-mongodb-config # If set, reads from ConfigMap
clusterAddress: "fallback-value" # Used if configMapName not set
Supported ConfigMaps:
mongoDb.configMapNamepostgres.configMapNameelastic.configMapNamerabbitMq.configMapNames3.configMapNameses.configMapNameauth0.configMapNameelasticApm.configMapNamegoogleSheets.configMapNameappSettings.configMapNameswaggerAuthConfig.configMapName
Service Comparison Matrix¶
| Feature Block | API | PM | Quartz | Web |
|---|---|---|---|---|
| GitVersion | ✅ | ✅ | ✅ | ✅ |
| Logging | ✅ | ✅ | ✅ | ❌ |
| MongoDB | ✅ | ✅ | ✅ | ❌ |
| PostgreSQL | ✅ | ✅ | ✅ | ❌ |
| Elasticsearch | ✅ | ✅ | ✅ | ❌ |
| RabbitMQ | ✅ | ✅ | ✅ | ❌ |
| S3 | ✅ | ✅ | ✅ | ❌ |
| SES | ✅ | ✅ | ✅ | ❌ |
| Auth0 | ✅ | ✅ | ✅ | ✅ |
| Sentry | ✅ | ✅ | ✅ | ✅ |
| Elastic APM | ✅ | ✅ | ✅ | ❌ |
| Google Sheets | ✅ | ✅ | ✅ | ❌ |
| Swagger Auth | ✅ | ❌ | ❌ | ❌ |
| Public API | ✅ | ❌ | ❌ | ❌ |
| Quartz SQL | ❌ | ❌ | ✅ | ❌ |
| SQL Server | ❌ | ❌ | ✅ | ❌ |
| Feature Flags | ✅ | ✅ | ✅ | ✅ (30+) |
Template Duplication Analysis¶
This analysis supports the Helm library chart refactoring.
Identical Blocks (can be shared 100%)¶
| Block | Lines | Services |
|---|---|---|
| GitVersion | 12 | API, PM, Quartz |
| Logging | 12 | API, PM, Quartz |
| MongoDB | 47 | API, PM, Quartz |
| PostgreSQL | 43 | API, PM, Quartz |
| RabbitMQ | 60 | API, PM, Quartz |
| S3 | 57 | API, PM, Quartz |
| SES | 48 | API, PM, Quartz |
| Auth0 | 51 | API, PM, Quartz |
| Sentry | 13 | API, PM, Quartz |
| Elastic APM | 25 | API, PM, Quartz |
| Google Sheets | 40 | API, PM, Quartz |
| Elasticsearch | 21 | API, PM, Quartz |
Service-Specific Blocks¶
| Block | Service | Lines | Notes |
|---|---|---|---|
| Swagger Auth | API only | 15 | API-specific |
| Public API | API only | 7 | API-specific |
| Quartz SQL | Quartz only | 7 | Scheduler DB |
| SQL Server | Quartz only | 7 | SQL connection |
| Debug ports | Quartz only | 6 | Remote debugging |
| Feature Flags | ALL | Varies | Different per service |
Web-Specific (Not Shared)¶
The web service uses SPA__ prefix and envsubst pattern, making it fundamentally different from .NET services. Web deployment should remain separate.
References¶
- Helm charts:
src/services/{api,project-management,quartz,web}/.chart/ - Values files:
cluster-gitops/syrf/environments/{staging,production}/services/ - Secrets management: External Secrets Operator in cluster-gitops