Why
#19 shipped the content.fetch-policy consumer. The producer half is issuer-side
(CannObserv/watcher#245) and has not landed, so today there is no supported way to put a policy
on the stream — which means there is no supported way to exercise the consumer end to end
outside the test suite.
scripts/seed_fetch.py exists for exactly this reason on the command stream: hand-rolling wire
fields at a REPL is how a frame ends up on the wrong stream, or on production's, or with an
envelope that does not match what the real producer emits. The policy stream now has the same
gap and one extra hazard — it is read without a consumer group, so a bad frame is not
dead-lettered anywhere. It is skipped past and gone.
What
A --policy mode on seed_fetch.py, or a sibling seed_policy.py. Either is fine; the
existing script's argument surface is the thing worth copying, not its file.
Requirements, all inherited from seed_fetch.py for the same reasons:
- Publishes through co-core's
to_wire and FetchPolicyState, never a hand-built field
map. A FetchPolicyEmit (extra="forbid") on the emit path would catch a typo'd field, which
is what that strict variant is for.
--redis-url and --topic required explicitly, with --production additionally required
for the one combination the live worker consumes (db 0 and content.fetch-policy). A
frame there changes how the running service paces real origins.
--revoke publishes a tombstone (revoked=True, no interval) rather than making the
caller reason about which fields to omit — the model rejects a live policy with no interval,
and getting that wrong at a REPL is the likely first attempt.
--watch tails the stream with a plain XREAD and never joins a group. Same rule as
seed_fetch.py --watch: a group left behind by an operator tool accumulates a PEL nothing
drains, and on this stream that is doubly wrong because the design has no group at all.
Not in scope
- Anything that looks like a policy store. The numbers belong to the issuer; this is a test
harness for the consumer, and it should stay obviously that. If it starts holding a set of
hosts it becomes the thing docs/contracts/replicator-boundaries.md says Replicator must not
become.
Refs
Why
#19 shipped the
content.fetch-policyconsumer. The producer half is issuer-side(CannObserv/watcher#245) and has not landed, so today there is no supported way to put a policy
on the stream — which means there is no supported way to exercise the consumer end to end
outside the test suite.
scripts/seed_fetch.pyexists for exactly this reason on the command stream: hand-rolling wirefields at a REPL is how a frame ends up on the wrong stream, or on production's, or with an
envelope that does not match what the real producer emits. The policy stream now has the same
gap and one extra hazard — it is read without a consumer group, so a bad frame is not
dead-lettered anywhere. It is skipped past and gone.
What
A
--policymode onseed_fetch.py, or a siblingseed_policy.py. Either is fine; theexisting script's argument surface is the thing worth copying, not its file.
Requirements, all inherited from
seed_fetch.pyfor the same reasons:to_wireandFetchPolicyState, never a hand-built fieldmap. A
FetchPolicyEmit(extra="forbid") on the emit path would catch a typo'd field, whichis what that strict variant is for.
--redis-urland--topicrequired explicitly, with--productionadditionally requiredfor the one combination the live worker consumes (db 0 and
content.fetch-policy). Aframe there changes how the running service paces real origins.
--revokepublishes a tombstone (revoked=True, no interval) rather than making thecaller reason about which fields to omit — the model rejects a live policy with no interval,
and getting that wrong at a REPL is the likely first attempt.
--watchtails the stream with a plainXREADand never joins a group. Same rule asseed_fetch.py --watch: a group left behind by an operator tool accumulates a PEL nothingdrains, and on this stream that is doubly wrong because the design has no group at all.
Not in scope
harness for the consumer, and it should stay obviously that. If it starts holding a set of
hosts it becomes the thing
docs/contracts/replicator-boundaries.mdsays Replicator must notbecome.
Refs
scripts/seed_fetch.py— the precedent, including the--productionguard and the groupless--watch