-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompose.development.yaml
More file actions
124 lines (119 loc) · 6.29 KB
/
Copy pathcompose.development.yaml
File metadata and controls
124 lines (119 loc) · 6.29 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
# What a laptop adds, and the only file to read to know what that is.
#
# docker compose -f compose.yaml -f compose.development.yaml up
#
# make development does exactly that. This was a compose profile until an audit
# found the profile could be asked for two ways that disagreed: the routes were
# derived from COMPOSE_PROFILES, so `docker compose --profile development`,
# which sets no such variable, started the mock and left Caddy serving the
# deployment's 404 in front of it. An override file has one way to ask.
services:
caddy:
environment:
# Deployment serves TLS and a 404. Development serves the portal, proxies
# /v1 to the mock, and carries no certificate at all, which ADR 0003
# explains and which is what lets a browser open it with nothing to accept.
ORO_ROUTES: development
identity:
environment:
# A laptop reaches the identity service at http://localhost on the port
# below, not at id.localhost through Caddy. That name does not resolve
# without an entry in /etc/hosts, and asking a volunteer to edit that file
# before they can open a login screen is the friction ADR 0003 refused
# when it chose plain HTTP over a certificate nothing trusts.
#
# These are set here rather than derived from anything in compose.yaml.
# One variable doing two jobs is what the profile did, and ADR 0002
# records what it cost.
ZITADEL_EXTERNALDOMAIN: "${ORO_HOSTNAME}"
ZITADEL_EXTERNALPORT: "${ORO_IDENTITY_PORT:-8180}"
ZITADEL_EXTERNALSECURE: "false"
ports:
# Loopback only. Nothing off this machine has any business signing in to
# a laptop's identity service.
- "127.0.0.1:${ORO_IDENTITY_PORT:-8180}:8080"
api:
environment:
# The one thing about the members API that a laptop changes. The issuer is
# the string the identity service signs into every token, and this shape
# reaches that service on a published port rather than under id. through
# Caddy, so the string is different. Measured on 2026-08-30: the discovery
# document at http://localhost:8180/.well-known/openid-configuration
# carries exactly this, and the development suite checks the two agree.
#
# The key set URL is not overridden. It goes through Caddy in both shapes,
# and the route file is where the two names differ.
ORO_API_TOKEN_ISSUER: "http://${ORO_HOSTNAME}:${ORO_IDENTITY_PORT:-8180}"
mail:
# Somewhere for the identity service to send to. Registration, a forgotten
# password and a changed address all end in a code that arrives by mail, and
# without a server to take it a person who registers is stopped on a screen
# asking for a code nobody can send. Measured on 2026-08-31: the account is
# created USER_STATE_INITIAL, and the Activate User screen after the
# password has a required code field, Next, and Resend Code, and no way
# past. tools/identity/README.md has why that state is the worst one.
#
# This catches mail rather than delivering it. Nothing leaves the laptop, and
# a .invalid address could not be delivered to anyway. Open the web interface
# on ORO_MAIL_PORT and the code is the newest message. A deployment points
# the identity service at the lab's real server instead, which is a step in
# docs/runbooks/deploy-beside-the-legacy-system.md.
#
# Pinned by digest as well as tag. mailpit v1.27.11, digest read from Docker
# Hub on 2026-08-31. The index carries linux/amd64 and linux/arm64.
image: axllent/mailpit:v1.27.11@sha256:e22dce5b36f93c77082e204a3942fb6b283b7896e057458400a4c88344c3df68
restart: unless-stopped
environment:
# It holds invented codes for invented people and it is on loopback, so
# there is nothing here worth a password.
MP_SMTP_AUTH_ACCEPT_ANY: "true"
MP_SMTP_AUTH_ALLOW_INSECURE: "true"
ports:
# The web interface, on loopback. Nothing off this machine reads a laptop's
# mail. The SMTP port is not published: the identity service reaches it
# over the compose network by name.
- "127.0.0.1:${ORO_MAIL_PORT:-8025}:8025"
healthcheck:
test: ["CMD", "/mailpit", "readyz"]
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
mock:
# The members API contract, served as a mock. It answered /v1 on the portal's
# origin until 2026-08-30, when the real service took that prefix, and it now
# answers on ORO_MOCK_PORT and nowhere else. Caddy routes nothing to it.
#
# It stays because it is the contract proof: tools/mock/tests/ starts this
# service by name and calls it on that port, which is how make mock-test has
# always worked. It answers with invented records, which is why it lives in
# this file and reaches no deployment. ADR 0002.
#
# Pinned by digest as well as by tag, because a tag can be moved onto a
# different build by whoever publishes it. stoplight/prism 5.15.10,
# published 2026-04-20, read from Docker Hub on 2026-08-27. The image has one
# manifest and it is linux/amd64, so naming the platform stops a warning on
# every start on an arm64 machine, where it runs emulated.
image: stoplight/prism:5.15.10@sha256:586d1f0f94f8d0eaf20b26b8b41f985f2a2d494bea297bd3988c3de3eb87094e
platform: linux/amd64
volumes:
- ./docs/api:/spec:ro
ports:
# Loopback only, and now the only way in. The contract checks read it, and
# so does anybody curling the contract by hand.
- "127.0.0.1:${ORO_MOCK_PORT:-4010}:4010"
# --multiprocess false because the default forks the server off the CLI and
# reads cluster.isPrimary on a Node version where it is undefined, so this
# image exits 1 with a TypeError before serving anything. Static examples
# rather than --dynamic, which answers /me with a 500 on this document.
command: ["mock", "--host", "0.0.0.0", "--port", "4010",
"--multiprocess", "false", "/spec/members-v1.yaml"]
healthcheck:
# The contract refuses a call carrying no bearer token, so the header is
# what makes a healthy mock answer 200 rather than 401.
test: ["CMD", "wget", "--quiet", "--spider", "--header",
"Authorization: Bearer healthcheck", "http://127.0.0.1:4010/me"]
interval: 5s
timeout: 5s
retries: 10
start_period: 20s