Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
254 lines (212 loc) · 11.7 KB
/
Copy path.env.example
File metadata and controls
254 lines (212 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# SentinelFlow local environment - TEMPLATE
#
# Copy to .env and fill in the secret values, or run `make bootstrap`, which
# generates them for you. .env is git-ignored and must never be committed.
#
# cp .env.example .env # then edit
# make bootstrap # or let it generate the secrets
#
# Every variable is listed with its default, whether it is required, whether it
# is sensitive, and which component reads it. A variable with no default is
# required: compose fails to start rather than falling back to something
# guessable.
#
# These values configure a stack that binds to your own machine and contains
# nothing but synthetic data. None of them is a production credential, and this
# stack is not a deployment target.
# =============================================================================
# Secrets - REQUIRED, no default. Generated by `make bootstrap`.
# =============================================================================
# Sensitive | required | read by: postgres, and from Phase 2 by apps/api
# Local database password. Generate with:
# openssl rand -base64 24
POSTGRES_PASSWORD=
# Sensitive | required | read by: grafana
# Local Grafana admin password. Generate with:
# openssl rand -base64 24
GRAFANA_ADMIN_PASSWORD=
# Sensitive | required | read by: apps/api
# Signs and verifies operator tokens (ADR-0012). At least 32 characters, or the
# API refuses to start: a shorter key is weaker than the HMAC-SHA256 it claims,
# and nothing downstream would report it. Generate with:
# openssl rand -base64 48
SENTINELFLOW_JWT_SECRET=
# Sensitive | required when seeding | read by: apps/api
# The password given to every seeded demo operator - analyst.one, analyst.two,
# administrator.one and auditor.one. Required whenever SENTINELFLOW_SEED_ENABLED
# is true, with no default, because a value in the repository would be the same
# password on every machine that ever ran the seed. Generate with:
# openssl rand -base64 24
SENTINELFLOW_DEMO_OPERATOR_PASSWORD=
# Sensitive | required | read by: apps/api, scripts/dev/replay.sh, scripts/dev/sf.ps1
# The credential POST /api/v1/transactions requires (ADR-0017 section 1). This
# is a machine-to-machine surface whose caller is a payment pipeline rather than
# a person, so it carries its own key rather than an operator's password. At
# least 32 characters, or the API refuses to start. No default, for a stronger
# reason than the JWT secret's: this key grants the right to write to the
# database and the outbox, so a default would grant that on every deployment
# that forgot to override it. Generate with:
# openssl rand -base64 48
SENTINELFLOW_INGEST_API_KEY=
# =============================================================================
# PostgreSQL - not sensitive
# =============================================================================
# Default: sentinelflow | read by: postgres, apps/api
POSTGRES_DB=sentinelflow
# Default: sentinelflow | read by: postgres, apps/api
POSTGRES_USER=sentinelflow
# Default: 5432 | read by: compose (host port publication)
# Change if something else on your machine already owns 5432.
POSTGRES_PORT=5432
# =============================================================================
# Kafka - not sensitive
# =============================================================================
# Default: 5L6g3nShT-eMCtK--X86sw | read by: kafka
# KRaft cluster id. Keep it stable: changing it after the volume has been
# formatted makes the broker refuse to start against its existing data
# directory. `make reset-demo` is the way to start over.
KAFKA_CLUSTER_ID=5L6g3nShT-eMCtK--X86sw
# Default: 29092 | read by: compose (host port publication)
# The host-facing listener. Containers use kafka:9092 internally and are
# unaffected by this.
KAFKA_HOST_PORT=29092
# =============================================================================
# Application ports - not sensitive
# =============================================================================
# Default: 127.0.0.1 | read by: compose (every published port)
# Which host address the stack publishes on. Loopback by default, so nothing in
# this stack is reachable from another machine: it holds a database with a
# generated password, a Grafana with a generated admin password, and an
# ingestion endpoint that stays unauthenticated until Phase 8 gives it its own
# credential (ADR-0012 section 5).
#
# Set it to 0.0.0.0 only to show the demo to somebody on another machine, and
# only knowing that the database and the broker are published with everything
# else. There is no per-service override on purpose - a stack that is half
# exposed is harder to reason about than one that is or is not.
SENTINELFLOW_BIND_ADDRESS=127.0.0.1
# Default: 8080 | read by: compose, apps/api
API_PORT=8080
# Default: 8000 | read by: compose, apps/scoring
SCORING_PORT=8000
# Default: 5173 | read by: compose (the console container listens on 8080)
WEB_PORT=5173
# Default: http://localhost:5173,http://localhost:5174 | read by: apps/api
# Which web origins a browser may let read this API (ADR-0013). The console is a
# separate origin from the API, so without a matching entry here every request
# the console makes is refused by the browser before this service sees it.
#
# The two defaults are the compose console (WEB_PORT above) and the Vite dev
# server. Comma-separated, exact matches: a scheme, a host and a port, with no
# trailing slash. "*" is refused at startup - a wildcard is not a permission.
SENTINELFLOW_CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:5174
# Default: http://localhost:8080/api/v1 | read by: apps/web at BUILD time
# Where the console sends its requests. Baked into the bundle by Vite when the
# console is built, not read at runtime, so changing it means rebuilding the
# web image - `make up --build` or `docker compose build web`.
#
# If you change API_PORT above, change this too; if you change this, add the
# console's origin to SENTINELFLOW_CORS_ALLOWED_ORIGINS.
VITE_API_BASE_URL=http://localhost:8080/api/v1
# =============================================================================
# Demo data - not sensitive, and synthetic by construction
# =============================================================================
# Default: false | read by: apps/api
# Loads synthetic customers, accounts, merchants and analyst logins at startup.
# Off everywhere, including local: a service that populates whatever database
# it is pointed at is a service nobody can safely point at anything. Turn it on
# deliberately, for one run. A second run over already-seeded data writes
# nothing.
SENTINELFLOW_SEED_ENABLED=false
# Default: 20260826 | read by: apps/api
# The same value produces the same dataset on any machine. Quote it in a bug
# report; pin it in CI. Changing it changes every generated row.
SENTINELFLOW_SEED=20260826
# Default: DEMO | read by: apps/api
# CI (20 customers), DEMO (200), or LOCAL (2000). See docs/data/DATA_PROVENANCE.md.
SENTINELFLOW_SEED_PROFILE=DEMO
# =============================================================================
# Scoring context - not sensitive
# =============================================================================
# Default: 24h | read by: apps/api
# How much account history crosses the scoring boundary (ADR-0008), and how much
# goes into the labelled training export (ADR-0010 section 1). 24h is the longest
# window any current feature is defined over - the 24-hour amount sum. Shortening
# it does not make that feature cheaper, it makes it wrong: the value is sent on
# every request as lookbackWindowSeconds so the scoring service warns rather than
# answering confidently from history it never received.
SENTINELFLOW_SCORING_LOOKBACK_WINDOW=24h
# Default: 200 | read by: apps/api
# The cap on recentTransactions. 200 is the contract's maxItems, and the
# application clamps to it - a larger value here would build requests the scoring
# service is required to reject, which presents as a scoring outage rather than
# as a misconfiguration. Lower it to send less; you cannot raise it.
SENTINELFLOW_SCORING_MAX_RECENT_TRANSACTIONS=200
# Default: false | read by: apps/api
# Writes the labelled training dataset at startup (ADR-0010 section 1). Off
# everywhere, including local, for the same reason as the seed: an application
# that writes files and reads the whole transaction table wherever it is pointed
# is one nobody can safely point anywhere. `make export-dataset` sets it for one
# recreate of the api service and then puts it back.
SENTINELFLOW_SCORING_EXPORT_ENABLED=false
# Default: false | read by: apps/api
# Whether to replace an existing export. An export is reproducible, so rewriting
# one is either pointless work or the loss of a dataset whose metrics someone has
# already published. The export refuses and names this variable rather than
# overwriting quietly.
SENTINELFLOW_SCORING_EXPORT_OVERWRITE=false
# =============================================================================
# Observability - not sensitive
# =============================================================================
# Default: 9090 | read by: compose
PROMETHEUS_PORT=9090
# Default: 3000 | read by: compose
GRAFANA_PORT=3000
# Default: 3200 | read by: compose (tempo)
# Tempo's query API, published so a trace can be fetched with curl when a
# dashboard is the thing under suspicion. The collector that feeds it has no
# published port on purpose: nothing outside the compose network sends it
# spans, and an unauthenticated trace-ingest endpoint on the host is a write
# surface for no gain.
TEMPO_PORT=3200
# Default: true | read by: apps/api
# Whether the API exports spans to the collector. On in compose, where the
# collector exists; off by default in application.yaml, so a local
# `./mvnw spring-boot:run` does not retry a connection to something that was
# never started. Tracing itself stays on either way, so trace and span ids
# still reach every log line.
SENTINELFLOW_OTLP_EXPORT_ENABLED=true
# Default: 1.0 | read by: apps/api
# The fraction of traces recorded. 1.0 locally because this stack is idle
# between bursts and sampling a tenth of a four-record replay gives a trace
# view that is empty when somebody looks at it (ADR-0016 section 5). The first
# number to change if this ever runs somewhere continuous.
SENTINELFLOW_TRACING_SAMPLE_RATE=1.0
# Default: admin | read by: grafana
GRAFANA_ADMIN_USER=admin
# =============================================================================
# Build and runtime identity - not sensitive
# =============================================================================
# Default: dev | read by: compose (image tag)
SENTINELFLOW_VERSION=dev
# Default: unknown | read by: apps/scoring (/info), apps/api (service.version
# on every structured log line)
# Set by CI so a running instance can be traced back to the commit that built
# it. Locally: SENTINELFLOW_GIT_SHA=$(git rev-parse HEAD)
SENTINELFLOW_GIT_SHA=unknown
# Default: INFO | read by: apps/scoring
# One of: CRITICAL, ERROR, WARNING, INFO, DEBUG
SCORING_LOG_LEVEL=INFO
# Default: json | read by: apps/scoring
# One of: json, console. JSON in the container because a log line is only
# structured if something can read the fields (ADR-0016 section 4); `console`
# is what a local `python -m sentinelflow_scoring` uses, because a person
# reading a traceback should not be reading escaped JSON. Set this to console
# to make `docker compose logs scoring` readable while debugging by eye.
SCORING_LOG_FORMAT=json
# Default: ecs | read by: apps/api (as LOGGING_STRUCTURED_FORMAT_CONSOLE)
# One of: ecs, logstash, gelf - or empty for Spring Boot's ordinary pattern
# encoder, which is what a local `./mvnw spring-boot:run` gets because nothing
# sets the variable there. ecs is a published schema with names for the fields
# this application already has, so a collector needs no hand-written mapping.
API_LOG_FORMAT=ecs