curated_feed.validate

Preflight checks on a runner’s configuration and the files it names.

The settings model refuses what is provably wrong — an unknown key, a floor that does not match the consequence scale — and refusing is the right answer there, because a config that cannot load is a config nobody can run against. This module is for what is probably wrong: an editorial policy that was copied but never written, a subscription list that lists nothing, two runners that name one state directory. None of those stops a run. Each of them ruins one, silently, at six in the morning.

The line the two sit either side of is who pays for a false positive. A model validator that guesses wrong makes the config unloadable and the only escape is patching the engine; a check here that guesses wrong is a line to argue with.

Nothing here touches the network, resolves a feed or needs a credential, which is what lets the same command serve as a pull-request gate, an unattended preflight inside a container that holds no secrets, and something run by hand after copying a runner’s directory.

Attributes

Functions

check_the_editorial_policy_is_written(→ str | None)

The runner's half of the prompt, which the engine ships the other half of.

check_the_subscription_list_holds_feeds(→ str | None)

The runner's subscriptions, parsed rather than resolved.

check_the_feed_has_an_id(→ str | None)

A feed that is uploaded needs an address to call its own.

check_the_site_url_is_absolute(→ str | None)

The feed's own address, which is published verbatim.

check_the_worker_matches_the_host(→ str | None)

Where the bytes go, against what the bytes claim about themselves.

validate_config(→ list[str])

Every problem in one runner's settings and the files they name.

validate_runner(→ list[str])

Every problem in the runner whose config is at config_path.

find_runners(→ list[pathlib.Path])

The runner directories under root, in name order.

check_runners_share_nothing(→ list[str])

No two runners may name one resource.

validate_directory(→ list[str])

Every problem in every runner under root, and between them.

validate_path(→ list[str])

Every problem under one config file, or under one directory of runners.

build_parser(→ argparse.ArgumentParser)

main(→ int)

Module Contents

curated_feed.validate.WORKERS_DEV = '.workers.dev'
curated_feed.validate.RESOURCE_READERS: dict[str, collections.abc.Callable[[curated_feed.config.Config], object]]
curated_feed.validate.UNSET_RESOURCES
curated_feed.validate.check_the_editorial_policy_is_written(paths: curated_feed.config.Paths) → str | None[source]

The runner’s half of the prompt, which the engine ships the other half of.

Present but empty is the state a copied template is left in, and it reaches the model as a heading and nothing else: every article scores on consequence alone, and the day looks merely disappointing rather than broken.

curated_feed.validate.check_the_subscription_list_holds_feeds(paths: curated_feed.config.Paths) → str | None[source]

The runner’s subscriptions, parsed rather than resolved.

Reading the file is filesystem work; asking each feed whether it answers is the network call this command may not make. A list that is present but lists nothing fails at fetch instead, unattended, with a run summary reporting zero items and no reason for it.

curated_feed.validate.check_the_feed_has_an_id(publish: curated_feed.config.PublishSettings, deploy: curated_feed.config.DeploySettings) → str | None[source]

A feed that is uploaded needs an address to call its own.

feed_url falls back to a fixed urn when site_url is empty, so the published document’s id and self-link are a placeholder shared with every other runner in that state — and a reader keys on the id.

>>> print(check_the_feed_has_an_id(
...     PublishSettings(site_url=""), DeploySettings(provider="wrangler")))
[deploy] provider is 'wrangler' but [publish] site_url is empty, so the feed's id is the placeholder 'urn:curated-feed'
>>> check_the_feed_has_an_id(PublishSettings(site_url=""), DeploySettings())
curated_feed.validate.check_the_site_url_is_absolute(publish: curated_feed.config.PublishSettings) → str | None[source]

The feed’s own address, which is published verbatim.

It becomes the id and the self-link of every document rendered, so a value a reader cannot resolve is not caught by anything downstream.

>>> print(check_the_site_url_is_absolute(PublishSettings(site_url="a.example")))
[publish] site_url 'a.example' is not an absolute URL; it needs a scheme and a host
>>> check_the_site_url_is_absolute(PublishSettings(site_url="https://a.example"))
curated_feed.validate.check_the_worker_matches_the_host(publish: curated_feed.config.PublishSettings, deploy: curated_feed.config.DeploySettings) → str | None[source]

Where the bytes go, against what the bytes claim about themselves.

deploy.project becomes wrangler deploy –name <project> and decides the first; publish.site_url feeds feed_url and decides the second. Nothing ties them together but a comment in each config, and the edit where they drift is rotating the random name after a leak — which is exactly when a feed served at one address and advertising another matters most.

Only inferable on a workers.dev host: the convention is Cloudflare’s rather than a rule, and a custom domain breaks it entirely. Being an inference is also why it lives here and not in a model validator — a wrong guess there makes the config unloadable and stops the 06:00 run outright.

>>> print(check_the_worker_matches_the_host(
...     PublishSettings(site_url="https://frog-a8b1.someone.workers.dev"),
...     DeploySettings(provider="wrangler", project="frog-a8b2")))
[publish] site_url is served by Worker 'frog-a8b1', but [deploy] project is 'frog-a8b2'
>>> check_the_worker_matches_the_host(
...     PublishSettings(site_url="https://feed.example.com"),
...     DeploySettings(provider="wrangler", project="frog-a8b2"))
curated_feed.validate.RUNNER_CHECKS: tuple[collections.abc.Callable[[curated_feed.config.Config], str | None], ...]
curated_feed.validate.validate_config(config: curated_feed.config.Config) → list[str][source]

Every problem in one runner’s settings and the files they name.

What the runner writes to — its corpus, state and build directories — is deliberately not required to exist. A fresh checkout has none of them, and neither does the container this runs in as a preflight.

curated_feed.validate.validate_runner(config_path: pathlib.Path) → list[str][source]

Every problem in the runner whose config is at config_path.

The directory names the runner, as it does everywhere else (ARCHITECTURE.md D8), so that is what each line is prefixed with.

curated_feed.validate.find_runners(root: pathlib.Path) → list[pathlib.Path][source]

The runner directories under root, in name order.

A runner is a subdirectory holding a config, which is the same rule the workflow’s matrix is held to. Anything else under root is reported rather than curated, so that a directory copied but not yet given a config says so.

curated_feed.validate.check_runners_share_nothing(config_by_runner: dict[str, curated_feed.config.Config]) → list[str][source]

No two runners may name one resource.

Nothing derives these locations from the runner’s name, so a config that was copied and half-edited would publish two feeds into one log and upload each over the other. Both feeds still render, which is why this is checked rather than left to be noticed.

curated_feed.validate.validate_directory(root: pathlib.Path) → list[str][source]

Every problem in every runner under root, and between them.

curated_feed.validate.validate_path(path: pathlib.Path) → list[str][source]

Every problem under one config file, or under one directory of runners.

curated_feed.validate.build_parser() → argparse.ArgumentParser[source]
curated_feed.validate.main(argv: collections.abc.Sequence[str] | None = None) → int[source]