외부 리뷰("현재 상태를 유지하기 위한 검증이 너무 많고, 그 검증 자체를
다시 검증하는 구조까지 생겼다")를 설계 문서로 정리하고 코드로 반영한다.
설계·판단 근거는 docs/superpowers/specs/2026-09-16-verification-surface-reduction-design.md.
삭제
- .github/ci-gate-matrix.yml(1,025줄) + verify-gate-matrix.sh(568줄):
Gradle task graph와 workflow graph에 이미 있는 정보의 3중 복제
- verify-gradle-wrapper.sh(799줄): workflow 바이트 해시 잠금.
wrapper 검증은 gradle/actions/wrapper-validation(full SHA 핀)에 위임
- DeveloperExperienceContractTest 등의 CI YAML mutation 테스트:
애플리케이션 test suite가 GitHub Actions YAML 파서를 검증하던 계층 역전
- 문서 drift 파서: verifyReadmeCommands, verifyRunbookReferences,
verifyDocumentedLeafCount, verifyTestSourceSetRegistry
- 빈 레지스트리를 지키던 커스텀 YAML 파서: verifyTrivyignore,
verifyQuarantineSunset, flaky-quarantine.yaml
- verifyConfigurationPropertiesProcessor, verifyOneTypePerFile:
각각 ca.spring-config convention과 Checkstyle OneTopLevelClass가 대체
- 정상 입력으로도 성공할 수 없던 messaging always-fail task
- ModuleRegistry의 JSON 필드 집합 정확 일치, sample-portfolio negative guard
이동
- java/quality/spring 공통 설정을 configure(subprojects) 블록에서
ca.java-conventions / ca.quality-conventions / ca.java-library /
ca.spring-library convention plugin으로
- 아키텍처 검증을 ca.architecture로, JPA·messaging qualification을
gradle/qualification/ 아래로, verifyEnvKeys를 :app-bootstrap 소유로
완화
- Git revision은 releaseCheck·아카이브 생성에서만 요구. 일반 빌드는 SNAPSHOT
- SpotBugs/FindSecBugs는 로컬 check에서 빼고 qualityCheck 레인으로
task 계층
- leaf check는 그 leaf만. architectureCheck / qualityCheck /
configContractCheck / integrationCheck / ci / releaseCheck로 이름 분리
CI
- _reusable-gradle.yml 신규. checkout + wrapper validation + JDK/캐시 공통화
- fileserver-release.yml -> fileserver-certification.yml (CD가 아니라 certification)
- GitHub Actions = CI + artifact, Argo CD = CD 경계를 docs/ci-cd/boundary.md로 고정
순증감 +3,274 / -7,483.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5003 lines
193 KiB
YAML
5003 lines
193 KiB
YAML
# Registry: Env Keys
|
|
# SSOT: wiki/projects/ca-tmpl/registries/env-keys.yaml
|
|
# Schema owner: feature-contract-registry-governance
|
|
# Owner branch: feature-env-driven-runtime-configuration
|
|
# Last updated: 2026-07-28
|
|
#
|
|
# Conventions:
|
|
# - Application-owned env uses `APP_` prefix, fully unified (D2, 2026-06-05):
|
|
# datasource/server/etc. keys that map onto Spring properties are renamed APP_*
|
|
# as well (e.g. SERVER_PORT -> APP_SERVER_PORT).
|
|
# - Only env the Spring runtime reads natively stays native: SPRING_* and
|
|
# SPRING_PROFILES_ACTIVE (D6 — profile selector is Spring-native, not APP_).
|
|
# - `classification: secret` rows only reference secrets-classification.yaml; full row owned there.
|
|
# - reload_policy default = `restart-only` (env-driven branch "config reload: no runtime reload").
|
|
# - boolean encoding = true/false only (env-driven branch 2026-05-22).
|
|
# - Duration encoding = Spring shorthand (`30s`); ISO-8601 (`PT30S`) forbidden (env-driven branch 2026-05-22).
|
|
# - DataSize encoding = `10MB` (env-driven branch 2026-05-22).
|
|
|
|
env_keys:
|
|
# === Profile / Identity (feature-env-driven-runtime-configuration) ===
|
|
|
|
- name: SPRING_PROFILES_ACTIVE
|
|
# source: feature-env-driven-runtime-configuration D6 (2026-06-06), amended by
|
|
# five-adapter-runtime-remediation §7.1. Profile selector is Spring-native and sole
|
|
# (APP_PROFILE was dropped). Exactly one value, not a CSV list: two environments cannot both
|
|
# have their safety rules apply, and whichever lost did so silently.
|
|
type: enum
|
|
# No default. A profile that is guessed is a deployment nobody chose: a jar started
|
|
# with none used to become local, which before persistence was gated also meant an
|
|
# in-memory database that loses every write on restart.
|
|
allowed_values: [local, dev, prod]
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:profile-active
|
|
|
|
# APP_PROFILE intentionally removed (D6, 2026-06-06): profile = SPRING_PROFILES_ACTIVE
|
|
# alone. A duplicate APP_PROFILE would only add information doubling + mismatch-fail
|
|
# cost. See branch note feature-env-driven-runtime-configuration Claims (wont-fix).
|
|
|
|
- name: APP_NAME
|
|
# source: feature-env-driven-runtime-configuration 2026-05-22
|
|
# "Required config: APP_NAME, APP_PROFILE..."
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: non_empty_string
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:app-name-present
|
|
|
|
# === HTTP server (APP_ unified per D2) ===
|
|
|
|
- name: APP_SERVER_PORT
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — full APP_
|
|
# unification; server.port maps from APP_SERVER_PORT.
|
|
# + feature-management-actuator-security-contract 2026-05-22 "management port default = 9001 (separate from app 8080)"
|
|
type: int
|
|
default: 8080
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: port_range_1_65535
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:server-port-bound
|
|
|
|
- name: MANAGEMENT_SERVER_PORT
|
|
# source: feature-management-actuator-security-contract 2026-05-22
|
|
# "management port default = 9001 (separate from app 8080). single-port는 platform ingress 보호 + 문서화 시만 허용."
|
|
type: int
|
|
default: 9001
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-management-actuator-security-contract
|
|
validation: port_range_1_65535
|
|
compatibility_impact: behavior-change
|
|
required_test: actuator-contract:management-port-separated
|
|
|
|
- name: APP_SERVER_SHUTDOWN
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (server.shutdown mode; graceful drains in-flight requests)
|
|
type: enum
|
|
default: graceful
|
|
allowed_values: [graceful, immediate]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:server-shutdown-mode
|
|
|
|
- name: APP_SERVER_SHUTDOWN_TIMEOUT
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification.
|
|
# Supersedes the old APP_SHUTDOWN_TIMEOUT row. Must stay <= k8s
|
|
# terminationGracePeriod (cross-ref feature-container-runtime-contract).
|
|
type: duration
|
|
default: 30s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: spring_duration_shorthand_le_termination_grace
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:server-shutdown-timeout-aligned
|
|
|
|
- name: APP_SERVER_FORWARD_HEADERS_STRATEGY
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (trust X-Forwarded-* when behind LB/proxy)
|
|
type: enum
|
|
default: framework
|
|
allowed_values: [none, native, framework]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:server-forward-headers-strategy
|
|
|
|
- name: APP_SERVER_TOMCAT_MAX_THREADS
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (ceiling on concurrent request workers)
|
|
type: int
|
|
default: 200
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:tomcat-max-threads-bounded
|
|
|
|
- name: APP_SERVER_TOMCAT_MIN_SPARE_THREADS
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (idle worker pool floor)
|
|
type: int
|
|
default: 10
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: non_negative_int
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:tomcat-min-spare-threads-valid
|
|
|
|
- name: APP_SERVER_TOMCAT_ACCEPT_COUNT
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (OS-level backlog queue depth for incoming TCP connections)
|
|
type: int
|
|
default: 100
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: non_negative_int
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:tomcat-accept-count-valid
|
|
|
|
- name: APP_SERVER_TOMCAT_MAX_CONNECTIONS
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (hard cap on simultaneously open connections)
|
|
type: int
|
|
default: 8192
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:tomcat-max-connections-bounded
|
|
|
|
- name: APP_SERVER_TOMCAT_CONNECTION_TIMEOUT
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (connection timeout for the Tomcat connector)
|
|
type: duration
|
|
default: 20s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: spring_duration_shorthand
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:tomcat-connection-timeout-set
|
|
|
|
- name: APP_SERVER_COMPRESSION_ENABLED
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (server.compression toggle)
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:server-compression-toggle
|
|
|
|
- name: APP_SERVER_COMPRESSION_MIN_RESPONSE_SIZE
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (payloads below this threshold are not compressed)
|
|
type: data_size
|
|
default: 1KB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: spring_data_size
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:server-compression-min-size
|
|
|
|
- name: APP_SERVER_ERROR_INCLUDE_STACKTRACE
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (spring.web.error.include-stacktrace policy)
|
|
type: enum
|
|
default: never
|
|
allowed_values: [always, never, on_param]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:server-error-stacktrace-policy
|
|
|
|
- name: APP_SERVER_ERROR_INCLUDE_MESSAGE
|
|
# source: feature-env-driven-runtime-configuration D2 (2026-06-05) — APP_ unification
|
|
# (spring.web.error.include-message policy)
|
|
type: enum
|
|
default: never
|
|
allowed_values: [always, never, on_param]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:server-error-message-policy
|
|
|
|
# === Error exposure / body logging (env-driven branch "Required config: error exposure, log") ===
|
|
|
|
- name: APP_ERROR_DETAIL_EXPOSURE_ENABLED
|
|
# source: feature-env-driven-runtime-configuration 2026-05-22
|
|
# "prod profile에서 body logging과 internal error detail exposure는 기본 금지"
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: prod_profile_must_be_false
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:error-exposure-prod-safe
|
|
|
|
- name: APP_LOG_BODY_CAPTURE_ENABLED
|
|
# source: feature-env-driven-runtime-configuration 2026-05-22 "prod profile에서 body logging ... 기본 금지"
|
|
# + feature-log-management-contract "request body capture filter — allowlist 없이는 capture 자체 금지"
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: prod_profile_must_be_false
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:body-logging-prod-safe
|
|
|
|
- name: APP_MULTI_INSTANCE_ENABLED
|
|
# source: feature-env-driven-runtime-configuration D8 (2026-06-06)
|
|
# When true, StartupSafetyValidator (SmartInitializingSingleton) requires the 5
|
|
# instance-coordination beans (distributed lock / cache-stampede / outbox leader
|
|
# / rate-limiter / migration runner) to be present, else startup fails. Consumed
|
|
# by feature-runtime-health-lifecycle-contract, feature-background-job-async-contract,
|
|
# feature-cache-consistency-contract, feature-domain-event-outbox-contract,
|
|
# feature-rate-limit-idempotency-contract, feature-migration-startup-contract.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: requires_coordination_beans_when_true
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:multi-instance-beans-present
|
|
|
|
- name: APP_MIGRATION_ON_STARTUP
|
|
# source: feature-migration-startup-contract
|
|
# When true, Flyway migrations are executed automatically during application startup.
|
|
# When false, migrations are bypassed (delegated to out-of-app container/pipeline jobs).
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-migration-startup-contract
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:migration-on-startup-toggle
|
|
|
|
# === Datasource / pool (env-driven branch "Required config: datasource") ===
|
|
|
|
- name: APP_DATASOURCE_URL
|
|
# source: feature-env-driven-runtime-configuration "Required config: datasource"
|
|
# + feature-persistence-failure-baseline "datasource/pool/timeout/connection exhaustion log field"
|
|
type: url
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: jdbc_url_pattern
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:datasource-url-resolvable
|
|
|
|
- name: APP_DATASOURCE_USERNAME
|
|
# source: feature-env-driven-runtime-configuration "Required config: datasource"
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: non_empty_string
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:datasource-credential-present
|
|
|
|
- name: APP_DATASOURCE_PASSWORD
|
|
# source: feature-env-driven-runtime-configuration "Required config: datasource"
|
|
# + feature-secrets-config-source-contract — secret 분류로 secrets-classification.yaml에서 owns
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-secrets-config-source-contract
|
|
validation: must_not_be_local_dev_sentinel_in_prod
|
|
compatibility_impact: breaking
|
|
required_test: secrets-contract:db-password-not-leaked
|
|
|
|
- name: APP_DATASOURCE_POOL_MAX_SIZE
|
|
# source: feature-env-driven-runtime-configuration "datasource/pool env"
|
|
# + feature-persistence-failure-baseline "Hikari metric 노출 기준"
|
|
type: int
|
|
default: 10
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:pool-bounded
|
|
|
|
- name: APP_DATASOURCE_POOL_MIN_IDLE
|
|
# source: feature-env-driven-runtime-configuration "datasource/pool env"
|
|
type: int
|
|
default: 2
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: non_negative_int
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:pool-min-idle-valid
|
|
|
|
- name: APP_DATASOURCE_CONNECTION_TIMEOUT
|
|
# source: feature-env-driven-runtime-configuration "datasource/pool env"
|
|
# + feature-persistence-failure-baseline "Hikari Alert Threshold: pool wait p99 > 100ms"
|
|
# unit: milliseconds. It feeds spring.datasource.hikari.connection-timeout, which binds onto
|
|
# HikariConfig#setConnectionTimeout(long) — a duration shorthand such as "5s" does not bind and
|
|
# fails the boot. This row said `duration` / `5s`, application.yml copied that default, and
|
|
# every prod and dev deployment refused to start; five-adapter-runtime-remediation Wave 2 found
|
|
# it in the prod-smoke lane. Corrected to what the property actually accepts.
|
|
type: integer
|
|
default: 5000
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: positive_integer_milliseconds
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:connection-timeout-set
|
|
|
|
- name: APP_DATASOURCE_DRIVER
|
|
# source: feature-env-driven-runtime-configuration "Required config: datasource"
|
|
# (JDBC driver class for the configured datasource URL)
|
|
type: string
|
|
default: org.postgresql.Driver
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: non_empty_string
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:datasource-driver-set
|
|
|
|
- name: APP_DATASOURCE_DDL_AUTO
|
|
# source: feature-env-driven-runtime-configuration "Required config: datasource"
|
|
# (Hibernate ddl-auto; prod must be validate|none, local update convenient)
|
|
type: enum
|
|
default: validate
|
|
allowed_values: [none, validate, update, create, create-drop]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:datasource-ddl-auto-safe
|
|
|
|
- name: APP_DATASOURCE_SHOW_SQL
|
|
# source: feature-env-driven-runtime-configuration "Required config: datasource"
|
|
# (echo SQL to logs)
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:datasource-show-sql-toggle
|
|
|
|
- name: APP_DATASOURCE_FORMAT_SQL
|
|
# source: feature-env-driven-runtime-configuration "Required config: datasource"
|
|
# (pretty-print SQL — only useful when SHOW_SQL=true)
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:datasource-format-sql-toggle
|
|
|
|
- name: APP_DATASOURCE_OPEN_IN_VIEW
|
|
# source: feature-env-driven-runtime-configuration "Required config: datasource"
|
|
# (Hibernate OSIV — don't enable in prod)
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:datasource-open-in-view-toggle
|
|
|
|
- name: APP_DATASOURCE_POOL_IDLE_TIMEOUT
|
|
# source: feature-env-driven-runtime-configuration "datasource/pool env"
|
|
# (Hikari milliseconds; idle connection eviction threshold)
|
|
type: int
|
|
default: 600000
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: non_negative_int
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:pool-idle-timeout-valid
|
|
|
|
- name: APP_DATASOURCE_POOL_MAX_LIFETIME
|
|
# source: feature-env-driven-runtime-configuration "datasource/pool env"
|
|
# (Hikari milliseconds; max lifetime — rotate before broker timeout)
|
|
type: int
|
|
default: 1800000
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-env-driven-runtime-configuration
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:pool-max-lifetime-valid
|
|
|
|
# === Tracing / Observability (feature-distributed-tracing-contract) ===
|
|
|
|
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
|
# source: feature-distributed-tracing-contract 2026-05-22
|
|
# "Micrometer Tracing + OpenTelemetry exporter를 기본 기준으로 둠"
|
|
type: url
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-distributed-tracing-contract
|
|
validation: url_or_empty
|
|
compatibility_impact: additive
|
|
required_test: tracing-contract:exporter-endpoint-resolvable
|
|
|
|
- name: APP_TRACING_ENABLED
|
|
# source: feature-distributed-tracing-contract 2026-05-22
|
|
# "tracing disabled profile에서도 envelope meta.traceId와 log traceId는 유지"
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-distributed-tracing-contract
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: tracing-contract:meta-traceid-when-disabled
|
|
|
|
- name: APP_TRACING_SAMPLE_RATE
|
|
# source: feature-distributed-tracing-contract 2026-05-22
|
|
# "trace sampling rate default = prod 1%, staging 10%, dev/local 100%"
|
|
# D-1 ISSUE-1 fix (2026-06-16): blank = per-profile resolver 기본값 사용.
|
|
# TracingSampleRateResolver SSOT (prod=0.01/staging=0.10/dev·local=1.0).
|
|
# TracingSamplingEnvironmentPostProcessor bridges resolved rate to
|
|
# management.tracing.sampling.probability.
|
|
type: string
|
|
default: ""
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-distributed-tracing-contract
|
|
validation: float_between_0_and_1_or_blank
|
|
compatibility_impact: behavior-change
|
|
required_test: tracing-contract:sample-rate-per-profile
|
|
|
|
# === Log management (feature-log-management-contract) ===
|
|
|
|
# APP_LOG_LEVEL (single key) replaced by the 5 granular APP_LOG_LEVEL_* rows below
|
|
# (root / app / spring / web / sql) — as built by feature-log-management-contract.
|
|
|
|
- name: APP_LOG_LEVEL_ROOT
|
|
# source: feature-log-management-contract — root logger level
|
|
type: enum
|
|
default: INFO
|
|
allowed_values: [TRACE, DEBUG, INFO, WARN, ERROR, OFF]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:root-level
|
|
|
|
- name: APP_LOG_LEVEL_APP
|
|
# source: feature-log-management-contract — application package level
|
|
type: enum
|
|
default: INFO
|
|
allowed_values: [TRACE, DEBUG, INFO, WARN, ERROR, OFF]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:app-level
|
|
|
|
- name: APP_LOG_LEVEL_SPRING
|
|
# source: feature-log-management-contract — Spring framework package level
|
|
type: enum
|
|
default: INFO
|
|
allowed_values: [TRACE, DEBUG, INFO, WARN, ERROR, OFF]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:spring-level
|
|
|
|
- name: APP_LOG_LEVEL_WEB
|
|
# source: feature-log-management-contract — web/MVC package level
|
|
type: enum
|
|
default: INFO
|
|
allowed_values: [TRACE, DEBUG, INFO, WARN, ERROR, OFF]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:web-level
|
|
|
|
- name: APP_LOG_LEVEL_SQL
|
|
# source: feature-log-management-contract — JPA/JDBC SQL package level (DEBUG prints SQL)
|
|
type: enum
|
|
default: WARN
|
|
allowed_values: [TRACE, DEBUG, INFO, WARN, ERROR, OFF]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:sql-level
|
|
|
|
- name: APP_LOG_FILE_ENABLED
|
|
# source: feature-log-management-contract — rolling JSON file appender toggle
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:file-appender-toggle
|
|
|
|
- name: APP_LOG_FILE_PATH
|
|
# source: feature-log-management-contract — file path (relative to bootRun cwd or absolute)
|
|
type: string
|
|
default: logs/ca-skeleton.json
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: non_empty_string
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:file-path-set
|
|
|
|
- name: APP_LOG_FILE_MAX_SIZE
|
|
# source: feature-log-management-contract — per-file rolling size cap
|
|
type: data_size
|
|
default: 100MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: spring_data_size
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:file-max-size
|
|
|
|
- name: APP_LOG_FILE_MAX_HISTORY
|
|
# source: feature-log-management-contract — number of rolled archives to retain
|
|
type: int
|
|
default: 14
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:file-max-history
|
|
|
|
- name: APP_LOG_FILE_TOTAL_SIZE_CAP
|
|
# source: feature-log-management-contract — total size cap across rolled files
|
|
type: data_size
|
|
default: 3GB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: spring_data_size
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:file-total-size-cap
|
|
|
|
- name: APP_LOG_ASYNC_ENABLED
|
|
# source: feature-log-management-contract — AsyncAppender wrap for non-blocking I/O
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:async-appender-toggle
|
|
|
|
- name: APP_LOG_ASYNC_QUEUE_SIZE
|
|
# source: feature-log-management-contract — in-memory queue depth before back-pressure
|
|
type: int
|
|
default: 512
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:async-queue-size
|
|
|
|
- name: APP_LOG_ASYNC_DISCARDING_THRESHOLD
|
|
# source: feature-log-management-contract — remaining-capacity floor below which
|
|
# TRACE/DEBUG/INFO events drop (WARN/ERROR always kept). 0 = never drop.
|
|
type: int
|
|
default: 20
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: non_negative_int
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:async-discarding-threshold
|
|
|
|
- name: APP_LOG_JSON_TIMEZONE
|
|
# source: feature-log-management-contract — IANA timezone for JSON encoder timestamps
|
|
type: string
|
|
default: UTC
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: non_empty_string
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:json-timezone
|
|
|
|
- name: APP_LOG_JSON_TIMESTAMP_PATTERN
|
|
# source: feature-log-management-contract — JSON encoder timestamp pattern (ISO 8601 default)
|
|
type: string
|
|
default: "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: non_empty_string
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:json-timestamp-pattern
|
|
|
|
- name: APP_LOG_JSON_INCLUDE_CALLER_DATA
|
|
# source: feature-log-management-contract — include file/method/line (significant perf cost)
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:json-include-caller-data
|
|
|
|
- name: APP_LOG_JSON_LOGGER_NAME_LENGTH
|
|
# source: feature-log-management-contract — logger name abbreviation (0 = full name)
|
|
type: int
|
|
default: 0
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: non_negative_int
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:json-logger-name-length
|
|
|
|
- name: APP_LOG_SAMPLING_RATE
|
|
# source: feature-log-management-contract 2026-05-22
|
|
# "log sampling(prod 10%) > trace sampling(prod 1%)" + Sampling Policy 표 (prod 10%, staging/dev/local 100%)
|
|
type: string
|
|
default: "1.0"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-log-management-contract
|
|
validation: float_between_0_and_1
|
|
compatibility_impact: behavior-change
|
|
required_test: log-contract:sample-rate-per-profile
|
|
|
|
# === Privacy: user_principal pseudonymization (feature-data-retention-privacy-contract) ===
|
|
|
|
- name: APP_PRIVACY_PSEUDONYMIZATION_SALT
|
|
# source: feature-data-retention-privacy-contract — "pseudonymization key = HMAC-SHA-256
|
|
# with rotating salt (90d)". Consumed by feature-log-management-contract (DRIFT-6)
|
|
# to record user_principal in pseudonymized form. secret 분류로 secrets-classification.yaml에서 owns.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-data-retention-privacy-contract
|
|
validation: must_not_be_local_dev_sentinel_in_prod
|
|
compatibility_impact: breaking
|
|
required_test: secrets-contract:pseudonymization-salt-rotation
|
|
|
|
# === Security / CORS / JWT (feature-security-operational-baseline) ===
|
|
|
|
- name: APP_SECURITY_CORS_ORIGINS
|
|
# source: feature-security-operational-baseline 2026-05-22
|
|
# "allowlist origin은 env-driven runtime configuration의 APP_SECURITY_CORS_ORIGINS로 주입"
|
|
type: csv_list
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: csv_of_origins_no_wildcard_with_credentials
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:cors-allowlist
|
|
|
|
- name: APP_SECURITY_CORS_ENABLED
|
|
# source: feature-security-operational-baseline — CORS filter master toggle
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:cors-enabled-toggle
|
|
|
|
- name: APP_SECURITY_CORS_ALLOWED_METHODS
|
|
# source: feature-security-operational-baseline — allowed methods
|
|
# (empty -> sensible method defaults in CorsSettings)
|
|
type: csv_list
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: csv_of_http_methods_or_empty
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:cors-allowed-methods
|
|
|
|
- name: APP_SECURITY_CORS_ALLOWED_HEADERS
|
|
# source: feature-security-operational-baseline — allowed request headers ("*" = any)
|
|
type: csv_list
|
|
default: "*"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: csv_non_empty
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:cors-allowed-headers
|
|
|
|
- name: APP_SECURITY_CORS_ALLOW_CREDENTIALS
|
|
# source: feature-security-operational-baseline 2026-05-22
|
|
# "CORS는 allowlist default, credentials false default" / "wildcard with credentials forbidden"
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: forbid_true_with_wildcard_origin
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:cors-credentials-policy
|
|
|
|
- name: APP_SECURITY_CORS_MAX_AGE
|
|
# source: feature-security-operational-baseline 2026-05-22
|
|
# "preflight max-age 600s default"
|
|
type: duration
|
|
default: 600s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: spring_duration_shorthand
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:cors-preflight-max-age
|
|
|
|
- name: APP_SECURITY_AUTH_MODE
|
|
type: enum
|
|
default: jwt
|
|
allowed_values: [jwt, redis-session]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:auth-mode-exclusive
|
|
|
|
- name: APP_SESSION_COOKIE_NAME
|
|
type: string
|
|
default: CA_SESSION
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: bounded_cookie_name
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:cookie-hardened
|
|
|
|
- name: APP_SESSION_COOKIE_SECURE
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: must_be_true
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:cookie-hardened
|
|
|
|
- name: APP_SESSION_COOKIE_HTTP_ONLY
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: must_be_true
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:cookie-hardened
|
|
|
|
- name: APP_SESSION_COOKIE_SAME_SITE
|
|
type: enum
|
|
default: Lax
|
|
allowed_values: [Lax, Strict, None]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:cookie-hardened
|
|
|
|
- name: APP_SESSION_COOKIE_PATH
|
|
type: string
|
|
default: /
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: bounded_absolute_path
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:cookie-hardened
|
|
|
|
- name: APP_SESSION_CSRF_COOKIE_NAME
|
|
type: string
|
|
default: XSRF-TOKEN
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: bounded_cookie_name
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:csrf-enabled
|
|
|
|
- name: APP_SESSION_CSRF_HEADER_NAME
|
|
type: string
|
|
default: X-XSRF-TOKEN
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: bounded_header_name
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:csrf-enabled
|
|
|
|
- name: APP_SESSION_REDIS_NAMESPACE_ENVIRONMENT
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: local
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: lowercase_slug
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:key-namespace
|
|
|
|
- name: APP_SESSION_IDLE_TIMEOUT
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 30m
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: positive_duration_le_30d
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:idle-expiry
|
|
|
|
- name: APP_SESSION_ABSOLUTE_LIFETIME
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 8h
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: positive_duration_le_30d
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:absolute-expiry
|
|
|
|
- name: APP_SESSION_TOUCH_INTERVAL
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 1m
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: positive_duration_lt_idle
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:bounded-touch
|
|
|
|
- name: APP_SESSION_TOMBSTONE_TTL
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 5m
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: positive_duration_gt_route_drain
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:logout-tombstone
|
|
|
|
- name: APP_SESSION_MAXIMUM_ENVELOPE_BYTES
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 32768
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: int_range_64_1048576
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:serializer-bounded
|
|
|
|
- name: APP_SESSION_MAXIMUM_ATTRIBUTES
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 64
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: int_range_1_256
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:serializer-bounded
|
|
|
|
- name: APP_SESSION_MAXIMUM_SCALAR_BYTES
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 8192
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: positive_int_le_envelope
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:serializer-bounded
|
|
|
|
- name: APP_SECURITY_JWT_ISSUER
|
|
# source: feature-security-operational-baseline 2026-05-22
|
|
# "issuer mismatch | 401 | AUTH_ISSUER_MISMATCH"
|
|
type: url
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: url_required
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:jwt-issuer-set
|
|
|
|
- name: APP_SECURITY_JWT_AUDIENCE
|
|
# source: feature-security-operational-baseline 2026-05-22
|
|
# "audience mismatch | 401 | AUTH_AUDIENCE_MISMATCH"
|
|
type: csv_list
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: csv_non_empty
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:jwt-audience-set
|
|
|
|
- name: APP_SECURITY_JWT_JWKS_URI
|
|
# source: feature-security-operational-baseline 2026-05-22
|
|
# "JWKS refresh interval = 10분, on-demand refresh on unknown kid"
|
|
type: url
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: true
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: url_required
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:jwks-uri-resolvable
|
|
|
|
- name: APP_SECURITY_JWT_CLOCK_SKEW
|
|
# source: feature-security-operational-baseline 2026-05-22
|
|
# "JWT clock skew tolerance = 60s (Spring Security JwtTimestampValidator leeway)"
|
|
type: duration
|
|
default: 60s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-security-operational-baseline
|
|
validation: spring_duration_shorthand
|
|
compatibility_impact: behavior-change
|
|
required_test: security-contract:jwt-clock-skew-applied
|
|
|
|
- name: APP_SECURITY_JWT_SIGNING_KEY
|
|
# source: feature-security-operational-baseline 2026-05-22
|
|
# "JWT signing key rotation의 운영 관측 (JWKS refresh, kid mismatch 분류)"
|
|
# secret 분류 — owner: secrets-classification.yaml
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-secrets-config-source-contract
|
|
validation: must_not_be_local_dev_sentinel_in_prod
|
|
compatibility_impact: breaking
|
|
required_test: secrets-contract:jwt-signing-key-rotation-overlap
|
|
|
|
# === Tenant context (feature-tenant-context-policy) ===
|
|
|
|
- name: APP_TENANT_ENABLED
|
|
# source: feature-tenant-context-policy 2026-05-22
|
|
# "skeleton core는 multi-tenancy 미지원이 기본이며 tenant header는 기본 거부"
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-tenant-context-policy
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: tenant-contract:disabled-rejects-header
|
|
|
|
# === Rate limit / Idempotency (feature-rate-limit-idempotency-contract) ===
|
|
|
|
- name: APP_RATE_LIMIT_ENABLED
|
|
# Inbound enforcement stays disabled until an exact provider is selected.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-rate-limit-contract:transport-provider-default-pair
|
|
|
|
- name: APP_RATE_LIMIT_CLIENT_IP_MODE
|
|
# source: feature-rate-limit-idempotency-contract — rate-limit client IP source policy.
|
|
# Use forwarded-headers-trusted only behind an ingress/LB that overwrites X-Forwarded-For.
|
|
type: enum
|
|
default: remote-addr-only
|
|
allowed_values: [remote-addr-only, forwarded-headers-trusted]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-rate-limit-idempotency-contract
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: rate-limit-contract:client-ip-mode
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_ENABLED
|
|
# DEPRECATED 2026-08-10: the rate limiter no longer owns a Redis client of its own. One client, built by RedisSdkAutoConfiguration, serves every capability, so a second endpoint and a second set of ceilings could only ever disagree with it.
|
|
# Replaced by: app.redis.enabled (APP_REDIS_ENABLED).
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-disabled-zero-side-effect
|
|
|
|
- name: APP_RATE_LIMIT_PROVIDER
|
|
type: enum
|
|
default: disabled
|
|
allowed_values: [disabled, redis]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:provider-explicit
|
|
|
|
- name: APP_RATE_LIMIT_ROLE
|
|
type: enum
|
|
default: coordination
|
|
allowed_values: [coordination]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:coordination-role-only
|
|
|
|
- name: APP_RATE_LIMIT_FAILURE_POLICY
|
|
type: enum
|
|
default: fail-closed
|
|
allowed_values: [fail-closed]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:fail-closed-only
|
|
|
|
- name: APP_RATE_LIMIT_DEFAULT_POLICY_ID
|
|
type: string
|
|
default: api-default
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: lowercase_slug
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:default-policy-resolves
|
|
|
|
- name: APP_RATE_LIMIT_FAILURE_RETRY_AFTER
|
|
type: duration
|
|
default: 100ms
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: spring_duration_shorthand_non_zero_le_30d
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:failure-retry-bounded
|
|
|
|
- name: APP_RATE_LIMIT_HASH_KEY_VERSION
|
|
type: int
|
|
default: 1
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: int_1_to_9999
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:hash-version-bounded
|
|
|
|
- name: APP_RATE_LIMIT_KEY_VERSION
|
|
type: int
|
|
default: 1
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: int_1_to_9999
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:key-version-bounded
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_HOST
|
|
# DEPRECATED 2026-08-10: the rate limiter no longer owns a Redis client of its own. One client, built by RedisSdkAutoConfiguration, serves every capability, so a second endpoint and a second set of ceilings could only ever disagree with it.
|
|
# Replaced by: app.redis.nodes (APP_REDIS_NODES).
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: non_empty_string_when_rate_limit_redis_enabled
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-host-required
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_PORT
|
|
# DEPRECATED 2026-08-10: the rate limiter no longer owns a Redis client of its own. One client, built by RedisSdkAutoConfiguration, serves every capability, so a second endpoint and a second set of ceilings could only ever disagree with it.
|
|
# Replaced by: app.redis.nodes (APP_REDIS_NODES).
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 6379
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: port_range_1_65535
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-port-bounded
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_PASSWORD
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: must_not_be_local_dev_sentinel_in_prod
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-password-no-leak
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_TRUST_PEM
|
|
# DEPRECATED 2026-08-10: the rate limiter no longer owns a Redis client of its own. One client, built by RedisSdkAutoConfiguration, serves every capability, so a second endpoint and a second set of ceilings could only ever disagree with it.
|
|
# Replaced by: app.redis.tls.trust-material-resource.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: non_blank_pem_when_coordination_role_is_bound
|
|
compatibility_impact: additive
|
|
required_test: redis-contract:coordination-trust-material-no-leak
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_KEY_HMAC_SECRET
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: base64_min_32_bytes_when_rate_limit_redis_enabled
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-hmac-required
|
|
|
|
- name: APP_SESSION_REDIS_PASSWORD
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: non_blank_when_session_role_is_bound
|
|
compatibility_impact: additive
|
|
required_test: redis-contract:session-password-no-leak
|
|
|
|
- name: APP_SESSION_REDIS_TRUST_PEM
|
|
# DEPRECATED 2026-08-10: the session generation that bound this was removed, and the replacement does not own a Redis client of its own either.
|
|
# Replaced by: app.redis.tls.trust-material-resource.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: non_blank_pem_when_session_role_is_bound
|
|
compatibility_impact: additive
|
|
required_test: redis-contract:session-trust-material-no-leak
|
|
|
|
- name: APP_SESSION_REDIS_KEY_HMAC_SECRET
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: base64_min_32_bytes_when_redis_session_enabled
|
|
compatibility_impact: additive
|
|
required_test: redis-session-contract:key-hmac-no-leak
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_COMMAND_TIMEOUT
|
|
type: duration
|
|
default: 1s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: spring_duration_shorthand_non_zero_le_30s
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-timeout-bounded
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_MAXIMUM_COMMAND_BYTES
|
|
# DEPRECATED 2026-08-10: the rate limiter no longer owns a Redis client of its own. One client, built by RedisSdkAutoConfiguration, serves every capability, so a second endpoint and a second set of ceilings could only ever disagree with it.
|
|
# Replaced by: app.redis.limits.max-batch-request-bytes.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 16384
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: int_16384_to_65536
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-command-bytes-bounded
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_MAXIMUM_QUEUED_COMMANDS
|
|
# DEPRECATED 2026-08-10: the rate limiter no longer owns a Redis client of its own. One client, built by RedisSdkAutoConfiguration, serves every capability, so a second endpoint and a second set of ceilings could only ever disagree with it.
|
|
# Replaced by: app.redis.capacity.maximum-in-flight-commands.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 32
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: int_1_to_4096
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-queue-bounded
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_MAXIMUM_IN_FLIGHT_BYTES
|
|
# DEPRECATED 2026-08-10: the rate limiter no longer owns a Redis client of its own. One client, built by RedisSdkAutoConfiguration, serves every capability, so a second endpoint and a second set of ceilings could only ever disagree with it.
|
|
# Replaced by: app.redis.capacity.maximum-in-flight-bytes.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 1048576
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: covers_rate_limit_command_and_le_268435456
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-byte-admission-bounded
|
|
|
|
- name: APP_RATE_LIMIT_REDIS_NAMESPACE_ENVIRONMENT
|
|
# DEPRECATED 2026-08-10: the rate limiter no longer renders its own key prefix. Four capabilities each joining two free-form tokens produced four prefixes, and the ACL pattern matched none of them.
|
|
# Replaced by: app.redis.namespace.environment (APP_REDIS_NAMESPACE_ENVIRONMENT), shared by every capability.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: local
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: lowercase_slug
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:redis-namespace-bounded
|
|
|
|
- name: APP_RATE_LIMIT_POLICY_REVISION
|
|
type: string
|
|
default: v1
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: lowercase_slug
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:policy-revision-bounded
|
|
|
|
- name: APP_RATE_LIMIT_ALGORITHM
|
|
type: enum
|
|
default: sliding-counter
|
|
allowed_values: [fixed-window, sliding-counter, token-bucket]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:algorithm-selectable
|
|
|
|
- name: APP_RATE_LIMIT_LIMIT
|
|
type: int
|
|
default: 100
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: positive_lua_exact_integer
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:limit-bounded
|
|
|
|
- name: APP_RATE_LIMIT_WINDOW
|
|
type: duration
|
|
default: 1s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: spring_duration_shorthand_non_zero_le_1d
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:window-bounded
|
|
|
|
- name: APP_RATE_LIMIT_CAPACITY
|
|
type: int
|
|
default: 100
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: positive_lua_exact_integer
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:capacity-bounded
|
|
|
|
- name: APP_RATE_LIMIT_REFILL_TOKENS
|
|
type: int
|
|
default: 100
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: positive_lua_exact_integer
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:refill-tokens-bounded
|
|
|
|
- name: APP_RATE_LIMIT_REFILL_PERIOD
|
|
type: duration
|
|
default: 1s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: spring_duration_shorthand_non_zero_le_1d
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:refill-period-bounded
|
|
|
|
- name: APP_RATE_LIMIT_MAXIMUM_COST
|
|
type: int
|
|
default: 10
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: positive_lua_exact_integer
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:maximum-cost-bounded
|
|
|
|
- name: APP_RATE_LIMIT_CLEANUP_GRACE
|
|
type: duration
|
|
default: 5s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: spring_duration_shorthand_non_zero_le_1d
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:cleanup-grace-bounded
|
|
|
|
- name: APP_RATE_LIMIT_MAXIMUM_CLOCK_REGRESSION
|
|
type: duration
|
|
default: 250ms
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-distributed-rate-limit
|
|
validation: spring_duration_shorthand_non_negative_le_1h
|
|
compatibility_impact: additive
|
|
required_test: rate-limit-contract:clock-regression-bounded
|
|
|
|
- name: APP_IDEMPOTENCY_TTL
|
|
# source: feature-rate-limit-idempotency-contract 2026-05-22
|
|
# "idempotency TTL default = 24h. long-running use case는 use case 선언으로 72h까지 override 가능"
|
|
type: duration
|
|
default: 24h
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-rate-limit-idempotency-contract
|
|
validation: spring_duration_shorthand_le_72h
|
|
compatibility_impact: behavior-change
|
|
required_test: idempotency-contract:ttl-applied
|
|
|
|
- name: APP_IDEMPOTENCY_PROVIDER
|
|
# postgresql selects the owner-safe V2 store on the primary data source. It had no value here
|
|
# while the store, its schema stream and its integration suite all existed, so the capability
|
|
# could only be reached by constructing it in a test.
|
|
type: enum
|
|
default: jdbc
|
|
allowed_values: [disabled, jdbc, redis, postgresql]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-idempotency-contract:provider-exclusive
|
|
|
|
- name: APP_IDEMPOTENCY_REDIS_KEY_HMAC_SECRET
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: base64_min_32_bytes_when_redis_idempotency_enabled
|
|
compatibility_impact: additive
|
|
required_test: redis-idempotency-contract:key-hmac-no-leak
|
|
|
|
- name: APP_IDEMPOTENCY_REDIS_NAMESPACE_ENVIRONMENT
|
|
# DEPRECATED 2026-08-10: the idempotency store no longer renders its own key prefix. Four capabilities each joining two free-form tokens produced four prefixes, and the ACL pattern matched none of them.
|
|
# Replaced by: app.redis.namespace.environment (APP_REDIS_NAMESPACE_ENVIRONMENT), shared by every capability.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: local
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: lowercase_slug
|
|
compatibility_impact: additive
|
|
required_test: redis-idempotency-contract:key-namespace
|
|
|
|
- name: APP_IDEMPOTENCY_PROCESSING_LEASE
|
|
type: duration
|
|
default: 30s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: positive_duration_le_1h
|
|
compatibility_impact: additive
|
|
required_test: redis-idempotency-contract:processing-lease-bounded
|
|
|
|
- name: APP_IDEMPOTENCY_FAILURE_RETENTION
|
|
type: duration
|
|
default: 24h
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: positive_duration_le_30d
|
|
compatibility_impact: additive
|
|
required_test: redis-idempotency-contract:failure-retention-bounded
|
|
|
|
- name: APP_LEASE_PROVIDER
|
|
type: enum
|
|
default: disabled
|
|
allowed_values: [disabled, redis]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-lease-contract:provider-exclusive
|
|
|
|
- name: APP_LEASE_REDIS_KEY_HMAC_SECRET
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: base64_min_32_bytes_when_redis_lease_enabled
|
|
compatibility_impact: additive
|
|
required_test: redis-lease-contract:key-hmac-no-leak
|
|
|
|
- name: APP_LEASE_REDIS_NAMESPACE_ENVIRONMENT
|
|
# DEPRECATED 2026-08-10: the lease no longer renders its own key prefix. Four capabilities each joining two free-form tokens produced four prefixes, and the ACL pattern matched none of them.
|
|
# Replaced by: app.redis.namespace.environment (APP_REDIS_NAMESPACE_ENVIRONMENT), shared by every capability.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: local
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: lowercase_slug
|
|
compatibility_impact: additive
|
|
required_test: redis-lease-contract:key-namespace
|
|
|
|
- name: APP_LEASE_REDIS_DRIFT_BUDGET
|
|
type: duration
|
|
default: 10ms
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: non_negative_duration_lt_minimum_lease
|
|
compatibility_impact: additive
|
|
required_test: redis-lease-contract:drift-budget-bounded
|
|
|
|
# === Cache / Redis (feature-cache-consistency-contract + integration-adapter-templates) ===
|
|
|
|
- name: APP_CACHE_CANONICAL_DEFAULT_PROVIDER
|
|
# Canonical default semantic region provider selection; legacy enable is a separate migration path.
|
|
type: enum
|
|
default: disabled
|
|
allowed_values: [disabled, redis]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-cache:canonical-cache-role-composition
|
|
|
|
- name: APP_REDIS_ENABLED
|
|
# The single global Redis activation switch (property app.redis.enabled).
|
|
# False loads no Redis settings, requires no Redis secret, and creates no client, connection,
|
|
# thread or health contributor. Role selectors choose which capabilities compose once Redis is
|
|
# on; none of them is a second master switch.
|
|
property: app.redis.enabled
|
|
owner_module: app-bootstrap
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: always-optional
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: redis-optionality:global-switch-off-creates-nothing
|
|
|
|
|
|
- name: APP_CACHE_REDIS_POSITIVE_HARD_TTL
|
|
# How long a cache entry stays usable. The physical Redis TTL equals this and nothing else, so
|
|
# an entry can never outlive the deployment's own notion of usability or be discarded early.
|
|
type: duration
|
|
default: 5m
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: spring_duration_shorthand_ge_minimum_hard_ttl
|
|
compatibility_impact: additive
|
|
required_test: redis-capability:cache-region-composition
|
|
|
|
- name: APP_CACHE_REDIS_NEGATIVE_TTL
|
|
# How long an authoritative absence is cached. Separate from the positive TTL because "the
|
|
# source says this does not exist" is a fact with a different shelf life from a value.
|
|
type: duration
|
|
default: 10s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: spring_duration_shorthand_non_zero
|
|
compatibility_impact: additive
|
|
required_test: redis-capability:cache-region-composition
|
|
|
|
- name: APP_IDEMPOTENCY_REDIS_COMMAND_TIMEOUT
|
|
# The ceiling on one owner-safe transition.
|
|
type: duration
|
|
default: 200ms
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: spring_duration_shorthand_non_zero
|
|
compatibility_impact: additive
|
|
required_test: redis-capability:idempotency-store-composition
|
|
|
|
- name: APP_LEASE_REDIS_COMMAND_TIMEOUT
|
|
# The ceiling on one lease operation.
|
|
type: duration
|
|
default: 200ms
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: spring_duration_shorthand_non_zero
|
|
compatibility_impact: additive
|
|
required_test: redis-capability:lease-composition
|
|
|
|
- name: APP_LEASE_REDIS_CONTENTION_RETRY_AFTER
|
|
# What a contended acquire tells the caller to wait. Distinct from the drift budget: one is
|
|
# advice to a caller that lost, the other is how much of its own lease a winner does not trust.
|
|
type: duration
|
|
default: 50ms
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: spring_duration_shorthand_non_zero
|
|
compatibility_impact: additive
|
|
required_test: redis-capability:lease-composition
|
|
|
|
# --- Redis SDK typed settings (app.redis.*) -------------------------------
|
|
# Bound only by RedisSdkAutoConfiguration, which exists only while APP_REDIS_ENABLED
|
|
# is true. They are deliberately absent from application.yml and src/.env: putting
|
|
# them there would make a Redis-free deployment carry Redis configuration, which is
|
|
# the defect the conditional composition root removes. :app-bootstrap:verifyEnvKeys checks them
|
|
# against spring-configuration-metadata.json instead.
|
|
|
|
- name: APP_REDIS_ACKNOWLEDGED_WRITE_LOSS_ACCEPTED
|
|
# Declares that losing acknowledged writes is a deliberate trade. Leave false.
|
|
property: app.redis.acknowledged-write-loss-accepted
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_ADMIN_CREDENTIAL_REFERENCE
|
|
property: app.redis.admin.credential-reference
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
required_when: app.redis.admin.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_ADMIN_ENABLED
|
|
property: app.redis.admin.enabled
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_ADVANCED_ENABLED
|
|
property: app.redis.advanced.enabled
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_ADVANCED_POLICIES
|
|
property: app.redis.advanced.policies
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: csv
|
|
default: ""
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: csv_nonempty
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_BLOCKING_MAX_BLOCK
|
|
# Hard ceiling on a server-side block; zero would be unbounded.
|
|
property: app.redis.blocking.max-block
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "30s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_BLOCKING_MAX_CONNECTIONS
|
|
property: app.redis.blocking.max-connections
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 32
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_DATABASE
|
|
# Cluster supports database 0 only; a non-zero value fails startup there.
|
|
property: app.redis.database
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 0
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_BATCH_COMMANDS
|
|
property: app.redis.limits.max-batch-commands
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 500
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_BATCH_REPLY_BYTES
|
|
property: app.redis.limits.max-batch-reply-bytes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 16777216
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_BATCH_REQUEST_BYTES
|
|
property: app.redis.limits.max-batch-request-bytes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 4194304
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_BITMAP_OFFSET
|
|
property: app.redis.limits.max-bitmap-offset
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 10000000
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_COLLECTION_ELEMENTS
|
|
property: app.redis.limits.max-collection-elements
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 1000
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_HASH_FIELD_VALUE_BYTES
|
|
property: app.redis.limits.max-hash-field-value-bytes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 524288
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_KEY_BYTES
|
|
property: app.redis.limits.max-key-bytes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 512
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_SCAN_COUNT
|
|
property: app.redis.limits.max-scan-count
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 500
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_STREAM_PAYLOAD_BYTES
|
|
property: app.redis.limits.max-stream-payload-bytes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 262144
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_MAX_VALUE_BYTES
|
|
property: app.redis.limits.max-value-bytes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 1048576
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_LIMITS_OFFLINE_QUEUE_COMMANDS
|
|
property: app.redis.limits.offline-queue-commands
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 1000
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_MODE
|
|
# standalone | sentinel | cluster.
|
|
property: app.redis.mode
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: enum
|
|
default: "standalone"
|
|
allowed_values: [standalone, sentinel, cluster]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_NAMESPACE_DOMAIN
|
|
property: app.redis.namespace.domain
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: "shared"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_NAMESPACE_ENVIRONMENT
|
|
property: app.redis.namespace.environment
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: "local"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_NAMESPACE_SERVICE
|
|
property: app.redis.namespace.service
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: "sample-service"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_NODES
|
|
# CSV of host:port. Cluster and Sentinel take every seed node.
|
|
property: app.redis.nodes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: csv
|
|
default: "localhost:6379"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: csv_nonempty
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_RAW_CREDENTIAL_REFERENCE
|
|
property: app.redis.raw.credential-reference
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
required_when: app.redis.raw.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_RAW_ENABLED
|
|
property: app.redis.raw.enabled
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_RAW_POLICY_RESOURCE
|
|
# Classpath resource listing every approved raw command. Absent resource fails startup.
|
|
property: app.redis.raw.policy-resource
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: "classpath:redis-sdk/raw-command-allowlist.yml"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.raw.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_TIMEOUT_ADMIN
|
|
property: app.redis.timeout.admin
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "3s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_TIMEOUT_BATCH
|
|
property: app.redis.timeout.batch
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "2s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_TIMEOUT_COLLECTION
|
|
property: app.redis.timeout.collection
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "2s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_TIMEOUT_FAST
|
|
# Single-key command profile; above 5s produces a startup warning.
|
|
property: app.redis.timeout.fast
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "500ms"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_TIMEOUT_SCRIPT
|
|
property: app.redis.timeout.script
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "1s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
- name: APP_REDIS_TRANSACTION_MAX_CONNECTIONS
|
|
property: app.redis.transaction.max-connections
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 16
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:typed-settings-bound-and-validated
|
|
|
|
# --- Redis runtime composition settings (app.redis.*) ----------------------
|
|
# Authentication, Sentinel discovery, TLS, lifecycle, Cluster routing, capacity and
|
|
# subscription delivery. Same rule as the rest of app.redis.*: bound only while
|
|
# APP_REDIS_ENABLED is true, and deliberately absent from application.yml and .env.
|
|
|
|
- name: APP_REDIS_AUTHENTICATION_ADVANCED_CREDENTIAL_REFERENCE
|
|
property: app.redis.authentication.advanced-credential-reference
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_AUTHENTICATION_ANONYMOUS_ACCESS_ACCEPTED
|
|
property: app.redis.authentication.anonymous-access-accepted
|
|
owner_module: adapter-outbound-cache-redis
|
|
# Explicit acknowledgement that Redis runs with no credential. Startup fails without it when
|
|
# no credential reference is set, because booting anyway builds an unauthenticated client that
|
|
# cannot run a single command on any deployment which disabled the `default` ACL user — the
|
|
# failure moves from startup to the first request, where it reads as an outage rather than a
|
|
# missing setting. Setting this to true keeps the deployment running and logs the trade.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true and no credential reference is configured
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:authentication-required-unless-anonymous-accepted
|
|
|
|
- name: APP_REDIS_AUTHENTICATION_CREDENTIAL_REFERENCE
|
|
# Pointer to the application ACL account credential. The value lives in the secret manager.
|
|
property: app.redis.authentication.credential-reference
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_AUTHENTICATION_PUBSUB_CREDENTIAL_REFERENCE
|
|
property: app.redis.authentication.pubsub-credential-reference
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_CAPACITY_MAXIMUM_IN_FLIGHT_BYTES
|
|
property: app.redis.capacity.maximum-in-flight-bytes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_CAPACITY_MAXIMUM_IN_FLIGHT_COMMANDS
|
|
property: app.redis.capacity.maximum-in-flight-commands
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 64
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_CAPACITY_MAXIMUM_REPLY_BYTES
|
|
property: app.redis.capacity.maximum-reply-bytes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_CAPACITY_REJECT_WHEN_DISCONNECTED
|
|
# True refuses commands while disconnected. False restores the driver offline queue, which replays a burst of writes on reconnect in arbitrary order relative to the outage.
|
|
property: app.redis.capacity.reject-when-disconnected
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_CLUSTER_MAXIMUM_REDIRECTS
|
|
property: app.redis.cluster.maximum-redirects
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 5
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_CLUSTER_TOPOLOGY_REFRESH_PERIOD
|
|
property: app.redis.cluster.topology-refresh-period
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "30s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_LIFECYCLE_ACQUIRE_TIMEOUT
|
|
property: app.redis.lifecycle.acquire-timeout
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "2s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_LIFECYCLE_CLIENT_NAME
|
|
property: app.redis.lifecycle.client-name
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: "ca-skeleton"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_LIFECYCLE_CONNECT_TIMEOUT
|
|
property: app.redis.lifecycle.connect-timeout
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "2s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_LIFECYCLE_DRAIN_TIMEOUT
|
|
# How long shutdown waits for in-flight commands before closing connections.
|
|
property: app.redis.lifecycle.drain-timeout
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "6s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_LIFECYCLE_SHUTDOWN_QUIET_PERIOD
|
|
property: app.redis.lifecycle.shutdown-quiet-period
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "100ms"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_LIFECYCLE_SHUTDOWN_TIMEOUT
|
|
property: app.redis.lifecycle.shutdown-timeout
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "3s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_LIFECYCLE_TLS_HANDSHAKE_TIMEOUT
|
|
property: app.redis.lifecycle.tls-handshake-timeout
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: duration
|
|
default: "3s"
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: duration_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_PUBSUB_BUFFER_CAPACITY
|
|
property: app.redis.pubsub.buffer-capacity
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: integer
|
|
default: 1024
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_PUBSUB_OVERFLOW_POLICY
|
|
# error | drop-oldest | drop-latest.
|
|
property: app.redis.pubsub.overflow-policy
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: "error"
|
|
allowed_values: [error, drop-oldest, drop-latest]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_SENTINEL_CREDENTIAL_REFERENCE
|
|
property: app.redis.sentinel.credential-reference
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
# Applied only when present: RedisTopologyClientFactory sets the sentinel credentials provider
|
|
# through ifPresent, so a Sentinel deployment whose sentinels accept unauthenticated discovery
|
|
# starts without it. The unconditional "app.redis.mode=sentinel" this used to declare was a
|
|
# requirement the runtime never enforced.
|
|
required_when: app.redis.mode=sentinel and the sentinels require authentication
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_SENTINEL_MASTER_NAME
|
|
property: app.redis.sentinel.master-name
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.mode=sentinel
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_SENTINEL_NODES
|
|
property: app.redis.sentinel.nodes
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: csv
|
|
default: app.redis.nodes
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
# Falls back to app.redis.nodes by design, so a deployment that points nodes at its sentinels
|
|
# and says nothing else is the common case rather than a misconfiguration.
|
|
required_when: app.redis.mode=sentinel and app.redis.nodes does not list the sentinels
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: csv_nonempty
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_TLS_CLIENT_CERTIFICATE_RESOURCE
|
|
property: app.redis.tls.client-certificate-resource
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
# A key manager is configured only when this is present. Ordinary one-way TLS needs no client
|
|
# certificate, so requiring one whenever TLS is on was a claim the runtime never made.
|
|
required_when: app.redis.tls.enabled=true and the server requires mutual TLS
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_TLS_CLIENT_KEY_REFERENCE
|
|
property: app.redis.tls.client-key-reference
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
# A relationship between two settings rather than a switch: a client certificate without its
|
|
# key cannot build a key manager. Enforced in RedisSdkSettings.validate and covered by
|
|
# RedisSdkSettingsTest, which is where the registry's prose conditions are proven.
|
|
required_when: app.redis.tls.client-certificate-resource is configured
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_TLS_ENABLED
|
|
property: app.redis.tls.enabled
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_TLS_HOSTNAME_VERIFICATION
|
|
# Disabling this accepts any certificate the trust material signs, for any host.
|
|
property: app.redis.tls.hostname-verification
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
required_when: app.redis.enabled=true
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
|
|
- name: APP_REDIS_TLS_TRUST_MATERIAL_RESOURCE
|
|
property: app.redis.tls.trust-material-resource
|
|
owner_module: adapter-outbound-cache-redis
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
# A trust manager is installed only when this is present; otherwise the JDK default trust
|
|
# anchors apply, which is enough for a server certificate from a public CA.
|
|
required_when: app.redis.tls.enabled=true and the server certificate is not publicly trusted
|
|
reload_policy: restart-only
|
|
owner_branch: redis-optionality-and-composition
|
|
validation: nonblank_when_required
|
|
compatibility_impact: additive
|
|
required_test: redis-sdk:runtime-composition-binds-and-validates
|
|
- name: APP_CACHE_REDIS_ENABLED
|
|
# source: feature-integration-adapter-templates 2026-05-22
|
|
# "Redis | disabled optional module | cache consistency" + Adapter Template Defaults 표
|
|
# DEPRECATED 2026-08-10: this was a second Redis master switch, and the settings class that
|
|
# bound it was removed with the previous Redis generation, so the key reached nothing.
|
|
# APP_REDIS_ENABLED is the sole global activation authority; the cache role is selected by
|
|
# ca-skeleton.capabilities.cache.bindings.default. The row is kept rather than deleted so a
|
|
# deployment still setting this key can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
deprecated_alias_for: APP_REDIS_ENABLED
|
|
removal_deadline: 2026-11-30
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-integration-adapter-templates
|
|
validation: boolean_strict
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:redis-disabled-default
|
|
|
|
- name: APP_CACHE_REDIS_CLIENT_MODE
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: enum
|
|
default: managed
|
|
allowed_values: [managed, external]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: enum_strict
|
|
compatibility_impact: additive
|
|
required_test: adapter-contract:redis-client-mode-explicit
|
|
|
|
- name: APP_CACHE_REDIS_HOST
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
# source: feature-cache-consistency-contract — Redis adapter (활성화 시 endpoint 필요)
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-cache-consistency-contract
|
|
validation: non_empty_string_when_redis_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: cache-contract:redis-host-when-enabled
|
|
|
|
- name: APP_CACHE_REDIS_PORT
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
# source: feature-cache-consistency-contract — Redis adapter endpoint
|
|
type: int
|
|
default: 6379
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-cache-consistency-contract
|
|
validation: port_range_1_65535
|
|
compatibility_impact: behavior-change
|
|
required_test: cache-contract:redis-port-bound
|
|
|
|
- name: APP_CACHE_REDIS_PASSWORD
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: codex-phase-a-ci-recovery
|
|
validation: must_not_be_local_dev_sentinel_in_prod
|
|
compatibility_impact: additive
|
|
required_test: secrets-contract:redis-password-no-leak
|
|
|
|
- name: APP_CACHE_REDIS_TRUST_PEM
|
|
# DEPRECATED 2026-08-10: the cache no longer owns a Redis client of its own, so no code reads this.
|
|
# Replaced by: app.redis.tls.trust-material-resource (APP_REDIS_TLS_TRUST_MATERIAL_RESOURCE), which the one Redis client uses for every capability.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: sensitive-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: non_blank_pem_when_cache_role_is_bound
|
|
compatibility_impact: additive
|
|
required_test: redis-contract:cache-trust-material-no-leak
|
|
|
|
- name: APP_REDIS_SEMANTIC_PROBE_MINIMUM_INTERVAL
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 5s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: spring_duration_1s_to_60s
|
|
compatibility_impact: additive
|
|
required_test: redis-contract:semantic-probe-cadence-bounded
|
|
|
|
- name: APP_REDIS_SENTINEL_DISCOVERY_REFRESH_PERIOD
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 30s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: spring_duration_5s_to_5m_inclusive
|
|
compatibility_impact: additive
|
|
required_test: redis-contract:sentinel-discovery-refresh-period-bounded
|
|
|
|
- name: APP_REDIS_SEMANTIC_PROBE_MAXIMUM_STALENESS
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 15s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability-completion
|
|
validation: spring_duration_gte_probe_minimum_and_lte_5m
|
|
compatibility_impact: additive
|
|
required_test: redis-contract:semantic-probe-staleness-bounded
|
|
|
|
- name: APP_CACHE_REDIS_KEY_HMAC_SECRET
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: codex-phase-a-ci-recovery
|
|
validation: base64_min_32_bytes_when_redis_enabled
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-hmac-secret-bounded
|
|
|
|
- name: APP_CACHE_REDIS_COMMAND_TIMEOUT
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 2s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: codex-phase-a-ci-recovery
|
|
validation: spring_duration_shorthand_non_zero_le_30s
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-command-timeout-bounded
|
|
|
|
- name: APP_CACHE_REDIS_MAXIMUM_QUEUED_COMMANDS
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 8
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: codex-phase-a-ci-recovery
|
|
validation: int_1_to_4096
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-command-queue-bounded
|
|
|
|
- name: APP_CACHE_REDIS_MAXIMUM_IN_FLIGHT_BYTES
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 16777216
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: codex-phase-a-ci-recovery
|
|
validation: covers_maximum_value_and_le_268435456
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-command-byte-admission-bounded
|
|
|
|
- name: APP_CACHE_REDIS_POSITIVE_SOFT_TTL
|
|
type: duration
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-cache-resilience
|
|
validation: optional_spring_duration_non_zero_le_positive_hard_ttl
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-soft-hard-ttl-order
|
|
|
|
- name: APP_CACHE_REDIS_TTL_JITTER
|
|
type: float
|
|
default: 0.10
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-cache-resilience
|
|
validation: decimal_0_to_0_5
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-ttl-jitter-bounded
|
|
|
|
- name: APP_CACHE_REDIS_MINIMUM_HARD_TTL
|
|
type: duration
|
|
default: 1s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-cache-resilience
|
|
validation: spring_duration_shorthand_non_zero_le_configured_hard_ttls
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-hard-ttl-minimum
|
|
|
|
- name: APP_CACHE_REDIS_NAMESPACE_ENVIRONMENT
|
|
# DEPRECATED 2026-08-10: the cache no longer renders its own key prefix. Four capabilities
|
|
# each joining two free-form tokens produced four prefixes, and the ACL pattern that was meant
|
|
# to fence the deployment in matched none of them. The row is kept (not deleted) so a
|
|
# deployment still setting it can be told what replaced it.
|
|
# Replaced by: app.redis.namespace.environment (APP_REDIS_NAMESPACE_ENVIRONMENT), shared by
|
|
# every capability.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: local
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: codex-phase-a-ci-recovery
|
|
validation: lowercase_slug
|
|
compatibility_impact: behavior-change
|
|
required_test: cache-contract:redis-namespace-environment-bound
|
|
|
|
- name: APP_CACHE_REDIS_SEMANTIC_REGION
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: string
|
|
default: default
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: codex-phase-a-ci-recovery
|
|
validation: lowercase_slug
|
|
compatibility_impact: behavior-change
|
|
required_test: cache-contract:redis-semantic-region-bound
|
|
|
|
- name: APP_CACHE_REDIS_MAXIMUM_VALUE_BYTES
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 1048576
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: codex-phase-a-ci-recovery
|
|
validation: int_1_to_16777216
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-value-size-bounded
|
|
|
|
- name: APP_CACHE_REDIS_L1_ENABLED
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: boolean_strict_cache_only
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-l1-disabled-default
|
|
|
|
- name: APP_CACHE_REDIS_L1_MAXIMUM_ENTRIES
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 10000
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: int_1_to_1000000
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-l1-cardinality-bounded
|
|
|
|
- name: APP_CACHE_REDIS_L1_MAXIMUM_WEIGHT_BYTES
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 67108864
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: int_1_to_1073741824_accounting_proxy
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-l1-weight-bounded
|
|
|
|
- name: APP_CACHE_REDIS_L1_MAXIMUM_ENTRY_WEIGHT_BYTES
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 1048576
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: positive_not_above_l1_maximum_weight
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-l1-entry-weight-bounded
|
|
|
|
- name: APP_CACHE_REDIS_L1_TTL
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 30s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: spring_duration_shorthand_non_zero_le_1h
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-l1-ttl-bounded
|
|
|
|
- name: APP_CACHE_REDIS_L1_GENERATION_RECHECK_INTERVAL
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: duration
|
|
default: 5s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: spring_duration_shorthand_non_zero_le_l1_ttl
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-l1-generation-recheck-bounded
|
|
|
|
- name: APP_CACHE_REDIS_L1_INVALIDATION_QUEUE_CAPACITY
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
type: int
|
|
default: 1024
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: redis-production-capability
|
|
validation: int_1_to_65536
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:redis-l1-invalidation-queue-bounded
|
|
|
|
- name: APP_CACHE_DEFAULT_TTL
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
# source: feature-cache-consistency-contract 2026-05-22
|
|
# "TTL | explicit per key family | no-cache for sensitive data | immortal cache forbidden"
|
|
type: duration
|
|
default: 300s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-cache-consistency-contract
|
|
validation: spring_duration_shorthand_non_zero
|
|
compatibility_impact: behavior-change
|
|
required_test: cache-contract:default-ttl-bounded
|
|
|
|
- name: APP_CACHE_NEGATIVE_TTL
|
|
# DEPRECATED 2026-08-10: the settings class that bound this property was removed
|
|
# with the previous Redis generation, so the key reached nothing. The row is kept
|
|
# (not deleted) so a deployment still setting it can be told what replaced it.
|
|
deprecated_orphaned: true
|
|
removal_deadline: 2026-11-30
|
|
# source: feature-cache-consistency-contract 2026-05-22
|
|
# "negative cache 정책 = 존재하지 않는 row는 짧은 TTL(60s) 캐싱 허용"
|
|
type: duration
|
|
default: 60s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-cache-consistency-contract
|
|
validation: spring_duration_shorthand
|
|
compatibility_impact: additive
|
|
required_test: cache-contract:negative-ttl-bounded
|
|
|
|
# === Messaging / Kafka (feature-domain-event-outbox-contract + integration-adapter-templates) ===
|
|
|
|
- name: APP_MESSAGING_BROKER
|
|
# source: messaging multi-broker redesign 2026-06-16 — single active broker selection
|
|
# (app.messaging.broker=<brokerId>); blank = messaging disabled. Replaces the former
|
|
# Kafka-binary APP_MESSAGING_KAFKA_ENABLED. Adding a broker is new files only.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-integration-adapter-templates
|
|
validation: none
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:messaging-broker-selection
|
|
|
|
- name: APP_MESSAGING_KAFKA_BROKERS
|
|
# source: feature-domain-event-outbox-contract — "Kafka는 optional integration adapter"
|
|
# (broker 활성화 시 endpoint 필요)
|
|
type: csv_list
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-integration-adapter-templates
|
|
validation: csv_of_host_port_when_kafka_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:kafka-brokers-when-enabled
|
|
|
|
# === Notification adapters (feature-integration-adapter-templates) ===
|
|
|
|
- name: APP_NOTIFICATION_SLACK_PROVIDER
|
|
# source: notification provider-SPI redesign 2026-06-16 — single active Slack provider
|
|
# selection (app.notification.slack.provider=<id>, e.g. webhook); blank = Slack disabled.
|
|
# Replaces the former provider-binary APP_NOTIFICATION_SLACK_ENABLED.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-integration-adapter-templates
|
|
validation: none
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-slack-provider-selection
|
|
|
|
- name: APP_NOTIFICATION_EMAIL_PROVIDER
|
|
# source: notification provider-SPI redesign 2026-06-16 — single active email provider
|
|
# selection (app.notification.email.provider=<id>, e.g. google-email); blank = email disabled.
|
|
# Replaces the former provider-binary APP_NOTIFICATION_GOOGLE_EMAIL_ENABLED.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-integration-adapter-templates
|
|
validation: none
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-email-provider-selection
|
|
|
|
# === Fileserver R2 local-persistent provider ===
|
|
|
|
- name: APP_FILESERVER_ENABLED
|
|
# source: Fileserver R2 control-plane/provider-selection design 2026-07-28.
|
|
# Disabled is the shipped safe default. Enabling requires every local attestation
|
|
# value below and an exact app.fileserver destination/provider graph.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-r2-control-plane-provider-selection
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-r2:disabled-default-and-enabled-attestation
|
|
|
|
- name: APP_FILESERVER_LOCAL_ROOT
|
|
# Pre-provisioned local-persistent root. The runtime additionally attests real
|
|
# path, ancestor/root symlinks, owner/mode, FileStore, sentinel, and capabilities.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-r2-control-plane-provider-selection
|
|
validation: absolute_existing_directory_when_app_fileserver_enabled
|
|
compatibility_impact: additive
|
|
required_test: fileserver-r2:disabled-default-and-enabled-attestation
|
|
|
|
- name: APP_FILESERVER_LOCAL_EXPECTED_FILE_STORE_NAME
|
|
# Exact FileStore.name() expected for the pre-provisioned root.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-r2-control-plane-provider-selection
|
|
validation: non_empty_string_when_app_fileserver_enabled
|
|
compatibility_impact: additive
|
|
required_test: fileserver-r2:disabled-default-and-enabled-attestation
|
|
|
|
- name: APP_FILESERVER_LOCAL_EXPECTED_FILE_STORE_TYPE
|
|
# Exact FileStore.type() expected for the pre-provisioned root.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-r2-control-plane-provider-selection
|
|
validation: non_empty_string_when_app_fileserver_enabled
|
|
compatibility_impact: additive
|
|
required_test: fileserver-r2:disabled-default-and-enabled-attestation
|
|
|
|
- name: APP_FILESERVER_LOCAL_MOUNT_SENTINEL_SHA256
|
|
# Lowercase SHA-256 of the operator-created .ca-fileserver-volume sentinel.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-r2-control-plane-provider-selection
|
|
validation: lowercase_sha256_when_app_fileserver_enabled
|
|
compatibility_impact: additive
|
|
required_test: fileserver-r2:disabled-default-and-enabled-attestation
|
|
|
|
- name: APP_FILESERVER_LOCAL_EXPECTED_OWNER
|
|
# Exact filesystem owner expected for the attested root and private namespace.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-r2-control-plane-provider-selection
|
|
validation: non_empty_string_when_app_fileserver_enabled
|
|
compatibility_impact: additive
|
|
required_test: fileserver-r2:disabled-default-and-enabled-attestation
|
|
|
|
# === HTTP Client platform (app.httpclient.*) ===
|
|
#
|
|
# Only the master switch is registered here. The per-client surface is an indexed list whose
|
|
# element cannot be templated in application.yml without materialising a nameless client in every
|
|
# deployment, so it has no deployment-independent value for this registry to hold and is
|
|
# registered in docs/httpclient/env-fields.yaml instead. That manifest is derived from
|
|
# HttpClientPlatformSettings and enforced in both directions: a field with no entry fails
|
|
# HttpClientPlatformEnvManifestTest, and an APP_HTTPCLIENT_ variable with no field fails startup.
|
|
|
|
- name: APP_HTTPCLIENT_ENABLED
|
|
# Master switch. While false the platform block is not bound at all: the auto-configuration that
|
|
# binds it is not processed, so no bean, connection pool, TLS context, credential, thread or
|
|
# gateway exists, and a malformed HTTP client setting cannot fail this deployment's startup.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: httpclient-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: httpclient-platform:off-state-zero-side-effects-and-env-manifest-parity
|
|
|
|
# === Fileserver HTTP platform (app.fileserver-platform.*) ===
|
|
#
|
|
# A different capability from the app.fileserver R2 publication block above. Separate
|
|
# namespaces so the two cannot be switched on together by accident, and so a change to one
|
|
# cannot silently re-shape the other.
|
|
|
|
- name: APP_FILESERVER_PLATFORM_ENABLED
|
|
# Master switch. While false the platform block is not bound at all: the auto-configuration that
|
|
# binds it is not processed, so no bean, route, thread, schema check or filesystem call exists.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_INSTANCE_ID
|
|
# Writer-lease owner; must be unique per instance. The startup gate treats the default as
|
|
# single-instance and refuses a shared-metadata claim it cannot support.
|
|
type: string
|
|
default: local-node
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: non_empty_string
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_DEFAULT_NAMESPACE
|
|
# Namespace applied to a request that does not name one.
|
|
type: string
|
|
default: default
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: non_empty_string
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_STORAGE_ROOT
|
|
# Absolute path on its own volume. A relative root resolves against the process working
|
|
# directory, which differs between a container and a test, so it is refused.
|
|
type: string
|
|
default: /var/lib/backend/files
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: absolute_path_outside_forbidden_ancestors
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_STORAGE_PUBLISH_MODE
|
|
# atomic-move-required fails startup when the probe cannot prove an atomic rename.
|
|
type: string
|
|
default: atomic-move-preferred
|
|
allowed_values: [atomic-move-required, atomic-move-preferred, metadata-pointer]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_STORAGE_BUFFER_SIZE
|
|
# Bounds every transfer allocation, so resident bytes never scale with file size.
|
|
type: data_size
|
|
default: 128KB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: between_4kb_and_8mb
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_STORAGE_FORBIDDEN_ROOT_ANCESTORS
|
|
# A storage root under a web root turns every upload into a published file; under a config
|
|
# root, into a configuration change. Both are refused at binding time.
|
|
type: csv_list
|
|
default: /app,/etc,/usr/share/nginx/html
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: absolute_path_list
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_UPLOAD_MAX_FILE_SIZE
|
|
# Also drives spring.servlet.multipart.max-file-size. One placeholder for both: a smaller
|
|
# servlet ceiling rejects the upload before any Fileserver code, including its error mapping.
|
|
type: data_size
|
|
default: 100MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_data_size
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_UPLOAD_MAX_REQUEST_SIZE
|
|
# Also drives spring.servlet.multipart.max-request-size.
|
|
type: data_size
|
|
default: 110MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: at_least_max_file_size
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_UPLOAD_INITIAL_RESERVATION
|
|
# Quota reserved for an upload that does not declare its length.
|
|
type: data_size
|
|
default: 8MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: at_most_max_file_size
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_UPLOAD_MAX_PARTS
|
|
# Ceiling on parts in one multipart/batch request.
|
|
type: integer
|
|
default: 16
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_UPLOAD_TTL
|
|
# Lifetime of an upload resource before it is reclaimable.
|
|
type: duration
|
|
default: 1h
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_duration
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_UPLOAD_RESERVATION_TTL
|
|
# Lifetime of a quota reservation whose upload never completed.
|
|
type: duration
|
|
default: 24h
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_duration
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_UPLOAD_LEASE_DURATION
|
|
# Writer lease. Renewed at one third of this while a transfer runs; a transfer that cannot
|
|
# renew is fenced out before its next physical write.
|
|
type: duration
|
|
default: 30s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_duration
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_UPLOAD_REQUIRE_CONTENT_LENGTH
|
|
# When true a raw upload without Content-Length is refused with 411.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_DOWNLOAD_CACHE_CONTROL
|
|
# Cache-Control emitted on every download response.
|
|
type: string
|
|
default: private, no-store
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: non_empty_string
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_DOWNLOAD_INLINE_ALLOWED
|
|
# Inline rendering is off by default; scriptable content is forced to attachment regardless.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_DOWNLOAD_MAX_RANGES
|
|
# Multi-range is opt-in; above one the response is multipart/byteranges.
|
|
type: integer
|
|
default: 1
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: between_1_and_8
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_DOWNLOAD_MAX_RANGE_BYTES
|
|
# Applies to the single-range profile too, so the ceiling is not inert in the default
|
|
# configuration that almost every deployment runs.
|
|
type: data_size
|
|
default: 100MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_data_size
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_DOWNLOAD_ZERO_COPY_ENABLED
|
|
# Changes only where bytes are copied, never a header or a status.
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_DOWNLOAD_ZERO_COPY_MINIMUM_BYTES
|
|
# Below this the syscall setup costs more than it saves.
|
|
type: data_size
|
|
default: 16MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_data_size
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_TRANSFER_CORE_SIZE
|
|
# Bounded transfer pool; rejection becomes a retryable 429, never caller-runs.
|
|
type: integer
|
|
default: 8
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer_at_most_max_size
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_TRANSFER_MAX_SIZE
|
|
# Upper bound of the transfer pool.
|
|
type: integer
|
|
default: 32
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_TRANSFER_QUEUE_CAPACITY
|
|
# Bounded queue; an unbounded one trades a fast 429 for eventual heap exhaustion.
|
|
type: integer
|
|
default: 64
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_TRANSFER_AWAIT_SECONDS
|
|
# Shutdown drain and per-transfer caller wait.
|
|
type: integer
|
|
default: 300
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_SECURITY_ACCESS_POLICY
|
|
# No permissive default. `required` fails startup unless the deployment supplies a
|
|
# FileAccessPolicy bean; `unenforced` is refused under a production profile.
|
|
type: string
|
|
default: required
|
|
allowed_values: [required, role-based, unenforced]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_SECURITY_READ_ROLES
|
|
# Roles accepted for read operations under the role-based policy.
|
|
type: csv_list
|
|
default: ROLE_FILE_READ
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: non_empty_role_list
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_SECURITY_WRITE_ROLES
|
|
# Roles accepted for write operations under the role-based policy.
|
|
type: csv_list
|
|
default: ROLE_FILE_WRITE
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: non_empty_role_list
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_SECURITY_ADMIN_ROLES
|
|
# Roles accepted for the management plane. Admin routes additionally require this role at the
|
|
# servlet chain, not only in application policy.
|
|
type: csv_list
|
|
default: ROLE_FILE_ADMIN
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: non_empty_role_list
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_VERIFICATION_TIMEOUT
|
|
# Whole-chain verification budget for one upload.
|
|
type: duration
|
|
default: 5s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_duration
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_VERIFICATION_REQUIRE_MEDIA_TYPE_VERDICT
|
|
# When true a file whose type could not be determined is refused rather than published.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_VERIFICATION_INLINE_SAFE_PROFILE
|
|
# When true scriptable content is accepted instead of quarantined; only safe when downloads
|
|
# are never served inline from a trusted origin.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_QUOTA_INSTANCE_UPLOAD_PERMITS
|
|
# Concurrent uploads admitted per instance.
|
|
type: integer
|
|
default: 16
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_QUOTA_SCOPE_UPLOAD_PERMITS
|
|
# Concurrent uploads admitted per namespace.
|
|
type: integer
|
|
default: 4
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer_at_most_instance_permits
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_QUOTA_DIRECT_DOWNLOAD_PERMITS
|
|
# Concurrent direct downloads admitted per instance.
|
|
type: integer
|
|
default: 64
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_QUOTA_SOFT_HIGH_WATER
|
|
# Storage fraction at which new uploads start being shed.
|
|
type: string
|
|
default: 0.70
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: fraction_below_hard_high_water
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_QUOTA_HARD_HIGH_WATER
|
|
# Storage fraction at which every upload is refused.
|
|
type: string
|
|
default: 0.85
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: fraction_within_zero_and_one
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_ADMIN_ENABLED
|
|
# Management plane, a separate decision from the data plane. Requires the master switch too:
|
|
# enabling it alone now does nothing instead of half-building a bean graph.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_ADMIN_ORPHAN_MINIMUM_AGE
|
|
# How long an unreferenced object must exist before a scan may name it; anything younger is
|
|
# assumed mid-commit rather than abandoned.
|
|
type: duration
|
|
default: 1h
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_duration
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_CLEANUP_ENABLED
|
|
# Background reclamation. Off by default because the worker deletes physical objects.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_CLEANUP_INTERVAL
|
|
# Fixed delay between batches; sole owner of the schedule, with no @Scheduled placeholder
|
|
# carrying a second default.
|
|
type: duration
|
|
default: 60s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_duration
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_CLEANUP_MAX_ITEMS
|
|
# Item ceiling for one batch, so a backlog cannot monopolise the scheduler.
|
|
type: integer
|
|
default: 100
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_integer
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_CLEANUP_MAX_BYTES
|
|
# Byte ceiling for one batch.
|
|
type: data_size
|
|
default: 1GB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_data_size
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_CLEANUP_RETRY_BACKOFF
|
|
# Delay before a failed cleanup item is retried.
|
|
type: duration
|
|
default: 5m
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_duration
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_TUS_ENABLED
|
|
# tus 1.0. Requires the master switch too.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_HTTPBIS_DRAFT12_ENABLED
|
|
# Unratified draft whose contract can change without notice. Requires the master switch too.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_NGINX_ENABLED
|
|
# Front-proxy delegation. Startup attests the internal mapping by exercising it; a mapping the
|
|
# proxy cannot resolve answers 200 with an empty body, so it fails closed instead.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_NGINX_INTERNAL_PREFIX
|
|
# Internal location the proxy resolves to the storage root.
|
|
type: string
|
|
default: /__files/
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: internal_uri_prefix
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_NGINX_OBJECT_SUFFIX
|
|
# Suffix appended to the sharded object key in the internal URI.
|
|
type: string
|
|
default: .bin
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: non_empty_string
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_NGINX_MINIMUM_SIZE
|
|
# Below this the request is served by the application rather than delegated.
|
|
type: data_size
|
|
default: 16MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: positive_data_size
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_OBSERVABILITY_METRICS_ENABLED
|
|
# When false neither the metrics port nor the fingerprint is created, and no key is required.
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: boolean_strict
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
- name: APP_FILESERVER_PLATFORM_OBSERVABILITY_FINGERPRINT_KEY
|
|
# Keyed HMAC over file identifiers. An unkeyed digest of an enumerable identifier is
|
|
# reversible, so startup fails while metrics are on and this is blank.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: fileserver-http-platform-activation-boundary
|
|
validation: non_empty_when_metrics_enabled
|
|
compatibility_impact: additive
|
|
required_test: fileserver-platform:off-state-zero-side-effects-and-env-round-trip
|
|
|
|
# === File / Upload (feature-file-resource-handling-contract) ===
|
|
|
|
- name: APP_FILE_UPLOAD_MAX_SIZE
|
|
# source: feature-file-resource-handling-contract 2026-05-22
|
|
# "Spring spring.servlet.multipart.max-file-size 10MB"
|
|
type: data_size
|
|
default: 10MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-file-resource-handling-contract
|
|
validation: spring_data_size_le_10MB_by_default
|
|
compatibility_impact: behavior-change
|
|
required_test: file-contract:upload-size-enforced
|
|
|
|
- name: APP_FILE_UPLOAD_GLOBAL_REQUEST_MAX_SIZE
|
|
# source: feature-file-resource-handling-contract 2026-05-22
|
|
# "global request size 12MB"
|
|
type: data_size
|
|
default: 12MB
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-file-resource-handling-contract
|
|
validation: spring_data_size
|
|
compatibility_impact: behavior-change
|
|
required_test: file-contract:global-request-size-enforced
|
|
|
|
# === Runtime / Lifecycle (feature-runtime-health-lifecycle-contract + container-runtime) ===
|
|
|
|
# APP_SHUTDOWN_TIMEOUT superseded by APP_SERVER_SHUTDOWN_TIMEOUT (HTTP server section,
|
|
# owner feature-env-driven-runtime-configuration). The k8s terminationGracePeriod
|
|
# alignment requirement (feature-container-runtime-contract) now applies to
|
|
# APP_SERVER_SHUTDOWN_TIMEOUT.
|
|
|
|
# === Async executor (feature-background-job-async-contract) ===
|
|
|
|
- name: APP_ASYNC_EXECUTOR_CORE_SIZE
|
|
# source: feature-background-job-async-contract 2026-05-22
|
|
# "executor pool sizing default = core=10, max=50, queue=200"
|
|
type: int
|
|
default: 10
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-background-job-async-contract
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: async-contract:executor-core-size
|
|
|
|
- name: APP_ASYNC_EXECUTOR_MAX_SIZE
|
|
# source: feature-background-job-async-contract 2026-05-22
|
|
# "core=10, max=50, queue=200"
|
|
type: int
|
|
default: 50
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-background-job-async-contract
|
|
validation: positive_int_ge_core
|
|
compatibility_impact: behavior-change
|
|
required_test: async-contract:executor-max-size
|
|
|
|
- name: APP_ASYNC_EXECUTOR_QUEUE_CAPACITY
|
|
# source: feature-background-job-async-contract 2026-05-22
|
|
# "queue=200" + "unbounded queue forbidden"
|
|
type: int
|
|
default: 200
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: feature-background-job-async-contract
|
|
validation: positive_int_bounded
|
|
compatibility_impact: behavior-change
|
|
required_test: async-contract:executor-queue-bounded
|
|
|
|
# === Notification delivery platform (NTF-025 — configuration surface) ===
|
|
# The tree exists in application.yml as ca-skeleton.notification.platform, disabled by
|
|
# default. Every key carries an inline default so a deployment that leaves the platform off
|
|
# supplies nothing. Reference: docs/notification/configuration.md.
|
|
|
|
- name: APP_PERSISTENCE_JPA_ENABLED
|
|
# source: five-adapter-runtime-remediation §5.1 — master switch for relational persistence.
|
|
# false means no DataSource, no entity scan, no repositories, no Hibernate, no Flyway and no DB
|
|
# health contributor; the old app.jpa-platform.enabled gated three add-on beans while reading
|
|
# like this one and defaulting to on.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-five-adapter-activation
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:persistence-jpa-disabled-safe
|
|
- name: APP_PERSISTENCE_MONGO_ENABLED
|
|
# source: five-adapter-runtime-remediation §5.1 — master switch for MongoDB persistence.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-five-adapter-activation
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:persistence-mongo-disabled-safe
|
|
- name: APP_PERSISTENCE_MONGO_ACTIVE_PROFILE
|
|
# source: five-adapter-runtime-remediation §5.1 — selects exactly one Mongo profile. The runtime
|
|
# builds one sync client and one pool; a profile present in the map but not selected has neither
|
|
# its secret resolved nor a client created.
|
|
type: string
|
|
default: ""
|
|
classification: public-config
|
|
required: false
|
|
required_when: APP_PERSISTENCE_MONGO_ENABLED=true
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-five-adapter-activation
|
|
validation: nonblank-when-required
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:persistence-mongo-active-profile
|
|
- name: APP_MESSAGING_ENABLED
|
|
# source: five-adapter-runtime-remediation §5.1 — master switch for broker publication.
|
|
# APP_MESSAGING_BROKER selects which transport and is no longer the de-facto switch.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-five-adapter-activation
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:messaging-disabled-safe
|
|
- name: APP_GRAPHQL_ENABLED
|
|
# source: five-adapter-runtime-remediation §5.1 — master switch for the GraphQL transport.
|
|
# false publishes no /graphql route, including the one Spring GraphQL would publish by itself.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-five-adapter-activation
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:graphql-disabled-safe
|
|
- name: APP_GRAPHQL_DEPLOYMENT_MODE
|
|
# source: five-adapter-runtime-remediation §5.1 / GQL-INT-002 — replaces backend.graphql.production
|
|
# and backend.graphql.environment, which defaulted to production=false with
|
|
# environment=PRODUCTION_PUBLIC and let anonymous-principal and allow-by-default authorization
|
|
# read one axis while the other claimed production.
|
|
type: enum
|
|
default: ""
|
|
allowed_values: [LOCAL, DEV, PRODUCTION_INTERNAL, PRODUCTION_PUBLIC]
|
|
classification: public-config
|
|
required: false
|
|
required_when: APP_GRAPHQL_ENABLED=true
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-five-adapter-activation
|
|
validation: enum
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:graphql-deployment-mode
|
|
- name: APP_OUTBOX_ENABLED
|
|
# source: five-adapter-runtime-remediation §6.1 JPA-INT-004 — the outbox capability switch.
|
|
# relay-enabled below only starts the scheduler; conflating the two meant a relay-off deployment
|
|
# still assembled outbox metrics over a store port a database-less runtime does not have.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-five-adapter-activation
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:outbox-capability-disabled-safe
|
|
- name: APP_OUTBOX_RELAY_ENABLED
|
|
# source: five-adapter-runtime-remediation §6.3 MSG-INT-001 — starts the relay scheduler.
|
|
# Requires APP_OUTBOX_ENABLED, APP_PERSISTENCE_JPA_ENABLED and APP_MESSAGING_ENABLED with a
|
|
# broker; the shipped default was true beside a blank broker, which refused every startup.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-five-adapter-activation
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:outbox-relay-dependency
|
|
- name: APP_NOTIFICATION_PLATFORM_ENABLED
|
|
# source: NTF-025 — master switch for the notification delivery platform; false binds nothing at all
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-platform-disabled-safe
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CONTACT_ENCRYPTION_KEY
|
|
# source: NTF-INT-007 — Encrypts recipient contact points at rest — addresses and phone numbers.
|
|
# Full row owned by secrets-classification.yaml. Bound by
|
|
# ca-skeleton.notification.platform.secrets.contact-encryption-key; the platform decodes it at startup and
|
|
# refuses to boot if it is blank, shorter than 32 bytes, or equal to another purpose's key.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: base64_at_least_32_bytes_and_distinct_per_purpose
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CONTACT_LOOKUP_HMAC_KEY
|
|
# source: NTF-INT-007 — Blind index over contact points, so a lookup never needs the plaintext.
|
|
# Full row owned by secrets-classification.yaml. Bound by
|
|
# ca-skeleton.notification.platform.secrets.contact-lookup-hmac-key; the platform decodes it at startup and
|
|
# refuses to boot if it is blank, shorter than 32 bytes, or equal to another purpose's key.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: base64_at_least_32_bytes_and_distinct_per_purpose
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CALLBACK_SIGNING_KEY
|
|
# source: NTF-INT-007 — Signs the callback URLs a provider posts delivery outcomes back to.
|
|
# Full row owned by secrets-classification.yaml. Bound by
|
|
# ca-skeleton.notification.platform.secrets.callback-signing-key; the platform decodes it at startup and
|
|
# refuses to boot if it is blank, shorter than 32 bytes, or equal to another purpose's key.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: base64_at_least_32_bytes_and_distinct_per_purpose
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_PROVIDER_CREDENTIAL_KEY
|
|
# source: NTF-INT-007 — Encrypts stored provider credentials, which are themselves secrets.
|
|
# Full row owned by secrets-classification.yaml. Bound by
|
|
# ca-skeleton.notification.platform.secrets.provider-credential-key; the platform decodes it at startup and
|
|
# refuses to boot if it is blank, shorter than 32 bytes, or equal to another purpose's key.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: base64_at_least_32_bytes_and_distinct_per_purpose
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_PAYLOAD_ENCRYPTION_KEY
|
|
# source: NTF-INT-007 — Encrypts notification variables and retained callback bodies at rest.
|
|
# Full row owned by secrets-classification.yaml. Bound by
|
|
# ca-skeleton.notification.platform.secrets.payload-encryption-key; the platform decodes it at startup and
|
|
# refuses to boot if it is blank, shorter than 32 bytes, or equal to another purpose's key.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: base64_at_least_32_bytes_and_distinct_per_purpose
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_VAPID_SIGNING_KEY
|
|
# source: NTF-INT-007 — Signs Web Push requests; the browser push service rejects anything else.
|
|
# Full row owned by secrets-classification.yaml. Bound by
|
|
# ca-skeleton.notification.platform.secrets.vapid-signing-key; the platform decodes it at startup and
|
|
# refuses to boot if it is blank, shorter than 32 bytes, or equal to another purpose's key.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: base64_at_least_32_bytes_and_distinct_per_purpose
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_PROVIDER_REQUEST_LOOKUP_HMAC_KEY
|
|
# source: NTF-INT-007 — Keyed hash of provider request ids, which are provider-side identifiers.
|
|
# Full row owned by secrets-classification.yaml. Bound by
|
|
# ca-skeleton.notification.platform.secrets.provider-request-lookup-hmac-key; the platform decodes it at startup and
|
|
# refuses to boot if it is blank, shorter than 32 bytes, or equal to another purpose's key.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: base64_at_least_32_bytes_and_distinct_per_purpose
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CALLBACK_FINGERPRINT_HMAC_KEY
|
|
# source: NTF-INT-007 — Keyed fingerprint of callback bodies, used to detect replays.
|
|
# Full row owned by secrets-classification.yaml. Bound by
|
|
# ca-skeleton.notification.platform.secrets.callback-fingerprint-hmac-key; the platform decodes it at startup and
|
|
# refuses to boot if it is blank, shorter than 32 bytes, or equal to another purpose's key.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: secret
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: base64_at_least_32_bytes_and_distinct_per_purpose
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CONTACT_ENCRYPTION_KEY_ID
|
|
# source: NTF-INT-007 — the id written into every envelope the CONTACT_ENCRYPTION key produces.
|
|
# An identifier, not key material, so it is public-config; the material itself is the
|
|
# APP_NOTIFICATION_PLATFORM_CONTACT_ENCRYPTION_KEY row above. Bound into
|
|
# ca-skeleton.notification.platform.secrets.active-key-ids.CONTACT_ENCRYPTION.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank_when_platform_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CONTACT_LOOKUP_HMAC_KEY_ID
|
|
# source: NTF-INT-007 — the id written into every envelope the CONTACT_LOOKUP_HMAC key produces.
|
|
# An identifier, not key material, so it is public-config; the material itself is the
|
|
# APP_NOTIFICATION_PLATFORM_CONTACT_LOOKUP_HMAC_KEY row above. Bound into
|
|
# ca-skeleton.notification.platform.secrets.active-key-ids.CONTACT_LOOKUP_HMAC.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank_when_platform_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CALLBACK_SIGNING_KEY_ID
|
|
# source: NTF-INT-007 — the id written into every envelope the CALLBACK_SIGNING key produces.
|
|
# An identifier, not key material, so it is public-config; the material itself is the
|
|
# APP_NOTIFICATION_PLATFORM_CALLBACK_SIGNING_KEY row above. Bound into
|
|
# ca-skeleton.notification.platform.secrets.active-key-ids.CALLBACK_SIGNING.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank_when_platform_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_PROVIDER_CREDENTIAL_KEY_ID
|
|
# source: NTF-INT-007 — the id written into every envelope the PROVIDER_CREDENTIAL key produces.
|
|
# An identifier, not key material, so it is public-config; the material itself is the
|
|
# APP_NOTIFICATION_PLATFORM_PROVIDER_CREDENTIAL_KEY row above. Bound into
|
|
# ca-skeleton.notification.platform.secrets.active-key-ids.PROVIDER_CREDENTIAL.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank_when_platform_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_PAYLOAD_ENCRYPTION_KEY_ID
|
|
# source: NTF-INT-007 — the id written into every envelope the PAYLOAD_ENCRYPTION key produces.
|
|
# An identifier, not key material, so it is public-config; the material itself is the
|
|
# APP_NOTIFICATION_PLATFORM_PAYLOAD_ENCRYPTION_KEY row above. Bound into
|
|
# ca-skeleton.notification.platform.secrets.active-key-ids.PAYLOAD_ENCRYPTION.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank_when_platform_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_VAPID_SIGNING_KEY_ID
|
|
# source: NTF-INT-007 — the id written into every envelope the VAPID_SIGNING key produces.
|
|
# An identifier, not key material, so it is public-config; the material itself is the
|
|
# APP_NOTIFICATION_PLATFORM_VAPID_SIGNING_KEY row above. Bound into
|
|
# ca-skeleton.notification.platform.secrets.active-key-ids.VAPID_SIGNING.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank_when_platform_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_PROVIDER_REQUEST_LOOKUP_HMAC_KEY_ID
|
|
# source: NTF-INT-007 — the id written into every envelope the PROVIDER_REQUEST_LOOKUP_HMAC key produces.
|
|
# An identifier, not key material, so it is public-config; the material itself is the
|
|
# APP_NOTIFICATION_PLATFORM_PROVIDER_REQUEST_LOOKUP_HMAC_KEY row above. Bound into
|
|
# ca-skeleton.notification.platform.secrets.active-key-ids.PROVIDER_REQUEST_LOOKUP_HMAC.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank_when_platform_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CALLBACK_FINGERPRINT_HMAC_KEY_ID
|
|
# source: NTF-INT-007 — the id written into every envelope the CALLBACK_FINGERPRINT_HMAC key produces.
|
|
# An identifier, not key material, so it is public-config; the material itself is the
|
|
# APP_NOTIFICATION_PLATFORM_CALLBACK_FINGERPRINT_HMAC_KEY row above. Bound into
|
|
# ca-skeleton.notification.platform.secrets.active-key-ids.CALLBACK_FINGERPRINT_HMAC.
|
|
type: string
|
|
default: null
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank_when_platform_enabled
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-secret-material-required
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_ENABLED
|
|
# source: NTF-INT-001 — master switch of the shipped SMTP provider profile; false means assembly skips it entirely.
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_PRIMARY
|
|
# source: NTF-INT-001 — whether this profile is the primary route for EMAIL; exactly one primary per channel.
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_ENVIRONMENT
|
|
# source: NTF-INT-001 — the profile's declared environment, carried on every dispatch record.
|
|
type: string
|
|
default: local
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_CREDENTIAL_PROFILE
|
|
# source: NTF-INT-001 — the credential profile the relay's credentials are resolved through.
|
|
type: string
|
|
default: default
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_blank
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_TIMEOUT
|
|
# source: NTF-INT-001 — per-attempt provider timeout for this profile.
|
|
type: duration
|
|
default: 10s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: duration_spring_shorthand
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_MAX_CONCURRENCY
|
|
# source: NTF-INT-001 — how many attempts this profile may have in flight.
|
|
type: int
|
|
default: 4
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_RATE_PER_SECOND
|
|
# source: NTF-INT-001 — the profile's attempt rate limit.
|
|
type: int
|
|
default: 10
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_TLS_MODE
|
|
# source: NTF-INT-001 — transport security of the SMTP session; the type has no plaintext member.
|
|
type: enum
|
|
default: STARTTLS_REQUIRED
|
|
allowed_values: [STARTTLS_REQUIRED, IMPLICIT_TLS]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: enum_in_allowed_values
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_SENDER_IDENTITY
|
|
# source: NTF-INT-001 — the envelope sender every message is sent as.
|
|
type: string
|
|
default: no-reply@example.invalid
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: email_address
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_CONNECT_TIMEOUT
|
|
# source: NTF-INT-001 — how long a connection attempt to the relay may take.
|
|
type: duration
|
|
default: 5s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: duration_spring_shorthand
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_READ_TIMEOUT
|
|
# source: NTF-INT-001 — how long a relay reply may take.
|
|
type: duration
|
|
default: 10s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: duration_spring_shorthand
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_WRITE_TIMEOUT
|
|
# source: NTF-INT-001 — how long a write to the relay may take.
|
|
type: duration
|
|
default: 10s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: duration_spring_shorthand
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_SMTP_DISPATCH_CONCURRENCY
|
|
# source: NTF-INT-001 — size of the bounded executor SMTP sends run on.
|
|
type: int
|
|
default: 4
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: positive_int
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-smtp-provider-assembled
|
|
|
|
- name: APP_OPENAPI_DOCS_ENABLED
|
|
# source: five-adapter-runtime-remediation §9 — whether /v3/api-docs is served; application-prod.yml pins it false. Stated rather than defaulted because
|
|
# SpringDoc warns on every startup until a deployment decides, and a warning on every start is
|
|
# one nobody reads.
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: main
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:openapi-exposure-decided
|
|
|
|
- name: APP_OPENAPI_UI_ENABLED
|
|
# source: five-adapter-runtime-remediation §9 — whether the Swagger UI is served; application-prod.yml pins it false. Stated rather than defaulted because
|
|
# SpringDoc warns on every startup until a deployment decides, and a warning on every start is
|
|
# one nobody reads.
|
|
type: boolean
|
|
default: true
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: main
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: env-contract:openapi-exposure-decided
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_MODE
|
|
# source: NTF-025 — SERVING refuses to start without a working provider; INGEST_ONLY stores and does not dispatch.
|
|
# The constant is INGEST_ONLY. This row said ACCEPT_ONLY, a name NotificationPlatformMode has
|
|
# never had, so an operator following the registry got a binding failure naming a value the
|
|
# documentation does not mention. NotificationModeSsotTest derives the list below from the enum.
|
|
type: enum
|
|
default: SERVING
|
|
allowed_values: [SERVING, INGEST_ONLY]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: enum_of_notification_platform_mode
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-platform-mode
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CLAIM_BATCH_SIZE
|
|
# source: NTF-025 — how many recipient deliveries one scheduler pass claims; 1..1000, refused outside that at binding
|
|
type: integer
|
|
default: 50
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: integer_1_to_1000
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-dispatch-bounds
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_LEASE_DURATION
|
|
# source: NTF-025 — must outlast a provider call plus its timeout, or a live worker's delivery is claimed by a second one
|
|
type: duration
|
|
default: 2m
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: positive_duration
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-lease-fencing
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_POLL_INTERVAL
|
|
# source: NTF-025 — how often the scheduler asks for work when the last pass claimed nothing
|
|
type: duration
|
|
default: 1s
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: positive_duration
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-dispatch-bounds
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_MAX_CONCURRENCY
|
|
# source: NTF-025 — ceiling on in-flight provider calls across the whole process
|
|
type: integer
|
|
default: 64
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: positive_integer
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-dispatch-bounds
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_MAX_ADDITIONAL_ATTEMPTS
|
|
# source: NTF-025 — retries after the first attempt; 0 means one attempt and no retry
|
|
type: integer
|
|
default: 4
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: non_negative_integer
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-retry-policy
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_MAX_QUEUE_AGE
|
|
# source: NTF-025 — after this, a queued delivery expires rather than being sent late
|
|
type: duration
|
|
default: 24h
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: positive_duration
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-expiry
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_ALLOW_AMBIGUOUS_FALLBACK
|
|
# source: NTF-025 — an ambiguous attempt reached the provider with an unread outcome; falling back risks a duplicate send
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-ambiguity
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CALLBACKS_ENABLED
|
|
# source: NTF-025 — whether the platform exposes provider callback endpoints
|
|
type: boolean
|
|
default: false
|
|
allowed_values: [true, false]
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: boolean
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-callback-ingestion
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CALLBACK_MAX_BODY_BYTES
|
|
# source: NTF-025 — ceiling is 65508 = ciphertext column minus AES-GCM nonce and tag; larger is refused at binding
|
|
type: integer
|
|
default: 65508
|
|
allowed_values: null
|
|
classification: public-config
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: integer_1_to_65508
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-callback-body-bound
|
|
|
|
- name: APP_NOTIFICATION_PLATFORM_CALLBACK_TRUSTED_PROXIES
|
|
# source: NTF-001 — peers whose forwarded headers may be believed when reconstructing the URL a
|
|
# provider signed. Empty means the resolver uses what the container observed; honouring
|
|
# forwarded headers unconditionally would let any caller pick the URL its signature is checked
|
|
# against, which defeats the signature.
|
|
type: csv
|
|
default: ""
|
|
allowed_values: null
|
|
classification: security-relevant
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: none
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-callback-url-resolution
|
|
- name: APP_NOTIFICATION_PLATFORM_CALLBACK_REPLAY_SKEW
|
|
# source: NTF-025 — how far a callback timestamp may differ from local time before it is treated as a replay
|
|
type: duration
|
|
default: 5m
|
|
allowed_values: null
|
|
classification: security-relevant
|
|
required: false
|
|
reload_policy: restart-only
|
|
owner_branch: worktree-notification-platform
|
|
validation: positive_duration
|
|
compatibility_impact: behavior-change
|
|
required_test: adapter-contract:notification-callback-replay
|