~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain

photography-focused photo sharing platform

grain.social
1 collaborator
0
2

grain-serve is set by flags, as knotless-serve is

Closed
Closed chadtmiller.com asked to merge into feature/rust from grain.social/grain:infra/flags

What changes

grain-serve is set by flags, as knotless-serve is. Where it listens, its index, its public URL, the Jetstream it follows, backfill, the CDN's address, the Bluesky appview, the sign-up PDS, how long old cookies carry, and the non-secret parts of push and Clef are each a --flag with a value (grain_serve::FLAGS, grain_serve::USAGE), and a flag given empty is as if not given, so a compose file can pass --jetstream "${GRAIN_JETSTREAM:-}" and turn a part off by leaving the variable unset. A flag it does not take, or one with no value, exits 2 with the usage, as knotless-serve does.

wasis
GRAIN_LISTEN--listen
GRAIN_INDEX--index
GRAIN_PUBLIC_URL--public-url
GRAIN_JETSTREAM (1 for default)--jetstream <wss://host>
GRAIN_BACKFILL=1 + _DIRECTORIES--backfill <https://directory>[,...]
GRAIN_BACKFILL_MIRROR/_SKIP/_CONCURRENCY--backfill-mirror/-skip/-concurrency
GRAIN_CDN_URL--cdn
GRAIN_BSKY_APPVIEW (1 for default)--bsky-appview <https://appview>
GRAIN_SIGN_UP_PDS--sign-up-pds
GRAIN_CARRY_COOKIES_UNTIL--carry-cookies-until
GRAIN_APNS_KEY_ID/_TEAM_ID/_TOPIC--apns-key-id/-team-id/-topic
GRAIN_APNS_SANDBOX=1--apns-url https://api.sandbox.push.apple.com
GRAIN_FCM_PROJECT_ID--fcm-project-id
GRAIN_CLEF_MODEL/_URL--clef-model/--clef-url
GRAIN_ADMINSGRAIN_ADMIN_DIDS (still the environment)

The environment keeps what knotless keeps there: secrets, key files and identity lists. GRAIN_CDN_KEY and GRAIN_CDN_SALT, GRAIN_APNS_KEY_FILE and GRAIN_FCM_KEY_FILE, CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_AI_TOKEN (the account goes with the token it is for), GRAIN_ADMIN_DIDS, renamed from GRAIN_ADMINS as KNOTLESS_ADMIN_DIDS is named, RUST_LOG, and grain::env's directories and resolvers (GRAIN_CONFIG_DIR, GRAIN_CACHE_DIR, ...), which the CLI reads too.

The 1 shorthands for Jetstream and the Bluesky appview are gone, as knotless-serve has none: a compose file gives the URL as its default (${GRAIN_JETSTREAM-wss://...}), and jetstream::DEFAULT and read::search::BSKY_APPVIEW stay as the values to give.

Why

The audit against knotless: knotless-serve takes its settings as flags (parse_args, crates/knotless-serve/src/lib.rs) and reads the environment only for secrets, directories and identity lists, and its compose passes ${VAR:-} into flags. grain-serve read every setting from GRAIN_*. Its compose (the image pull) comes after this, so it can pass flags from the start.

Mirrors parse_args, Options and its usage string in crates/knotless-serve/src/lib.rs, main.rs's exit 2 on a usage error, and KNOTLESS_ADMIN_DIDS in crates/knotless/src/env.rs. Kept grain-specific: the struct is still Settings, not Options, and its fields are as they were, since every pull in flight that builds one (Settings { index, ..Default::default() }) keeps compiling; and the flags are parsed from a table, FLAGS, into one lookup that each part's config reads (backfill::Config::given, push::Config::given, clef::Config::given), rather than one match arm a flag, so the push and Clef configs read their flags and their key files from one place. --backfill-mirror "" and --backfill-skip "" are none, not the default, as the empty variables were.

How it was checked

The settings tests (lib.rs, tests/backfill.rs, tests/jetstream.rs, push/tests.rs, clef.rs) parse flags now, every flag given empty is every part off, the old variable is not read for a setting, and a flag it does not take is refused with the usage; tests/main.rs runs the binary with flags, and checks it exits 2 with its usage. Clippy run here on grain-serve; the rest left to the checks.

Shortcomings

  • Another pull in flight adds a GRAIN_WEB fallback; whichever lands second makes it --web <http://pages>, as knotless-serve's is.
  • Nothing deploys grain-serve yet, so no compose or env file names the old variables; the image and compose pull passes these flags.

Review

Start at Settings::parse in crates/grain-serve/src/lib.rs.

🤖 Generated with Claude Code

Approved

This moves grain-serve's settings from GRAIN_* variables to a table of --flags. Secrets, key files and the admin list stay in the environment, and GRAIN_ADMINS becomes GRAIN_ADMIN_DIDS. I read Settings::parse, FLAGS, USAGE and Settings in crates/grain-serve/src/lib.rs, and they look right. An empty flag counts as unset, an unknown flag returns the usage, and a flag with no value returns an error. The environment names that remain match the environment: line in the usage. The rest of the diff, including the per-part given readers, the tests and main.rs, is about 64k characters. My tools couldn't page through it, so I didn't read it.

All four checks (check, rust, test, harness) were still queued when I looked. Please make sure they pass, in particular the harness coverage gate, before this lands.

Two minor points, neither blocking:

  • A value that is itself a flag name is accepted as a value. For example, --jetstream --listen sets the Jetstream to --listen. knotless-serve may behave the same way.
  • The "takes a value" error doesn't include the usage, unlike the unknown-flag error. If main.rs doesn't add it, you could append USAGE there.

Both minor points are left as knotless-serve has them: its parse_args takes the next argument as the value whatever it is, and says only "<flag> takes a value" without the usage. Changing either would move grain away from the shape this copies.

Landed on feature/rust at fc5f686 through the batch pull Seven reviewed pulls land on feature/rust together, checked once, checked there as a whole. This pull's head is in feature/rust's history.