1
0

The sky is not something an account grants you

`liveData` was one flag meaning two unrelated things, and it was set to
`tier !== "anon"`. That reasoning does not survive asking what the data actually
is. Cloud cover over San Francisco is a reading from a government sensor. The
aircraft are broadcasting their positions, unencrypted, to anyone within range
who owns a forty-dollar receiver. Neither is withheld from anybody by anybody,
so neither is a thing an account can grant access to — and putting them behind a
sign-in cost the only moment that makes this project land: real fog rolling off
the Pacific onto a city you recognise, at the real time of day, on a first
visit. On an SSO-gated deployment it cost that moment for every visitor there
currently is.

So `liveData` splits. `liveEnvironment` is public and unconditional.
`liveMarkers` is asked for by everyone and granted by the server, because the
marker set is the one feed here that can carry something private — a company's
pipeline, a person's job search — and whether it is public is a property of the
deployment, not of a file in this repo.

`TERA_MARKERS_ACCESS` is therefore a server switch and its default is `members`,
which is the safe answer rather than the common one. The failure mode of getting
this wrong is silent: nothing throws, nothing looks broken, the data is simply
readable by the internet. An operator who wires real markers up gets the shut
door without having chosen it and has to say `public` out loud — and saying it
appends a line to `degraded[]`, so `/api/v1/health` reports that this box is
publishing its map without anyone having to go and read the env file. Same
reasoning as `TERA_ADMIN_SUBJECTS=*`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-06 03:36:12 -07:00
parent e41c90fe8d
commit 1db868ad70
6 changed files with 146 additions and 19 deletions
+9 -2
View File
@@ -54,9 +54,16 @@ const UNAUTHORIZED: ErrorBody = {
export function registerMarkers(app: FastifyInstance, services: Services): void {
app.get("/api/v1/markers", async (req, reply) => {
if (services.config.markers.source === "none") {
const { markers } = services.config;
// Two ways to be public and they are not the same fact. `source === "none"`
// is "there is nothing here to protect" — the body is the bundled sample
// set. `access === "public"` is an operator saying this deployment's real
// marker set is meant to be read by anyone. Both end up here; only the
// second one is a decision, and `config.ts` announces it in `degraded[]`
// so it cannot be made silently.
if (markers.source === "none" || markers.access === "public") {
const body = await services.markers.current();
publicCache(req, reply, services.config.markers.ttlSeconds);
publicCache(req, reply, markers.ttlSeconds);
return body;
}