Description
The codebase contains a complete, tested JetStream durability subsystem for GitHub webhook events:
internal/config/config.go parses JS_ENABLED (JetStreamEnabled), JS_STREAM_NAME, JS_CONSUMER_NAME, JS_MAX_DELIVER, JS_ACK_WAIT, and JS_MAX_AGE.
internal/bus/natsbus/jetstream.go implements JetStreamBus/NewJetStreamBus, a bus.Bus backed by NATS JetStream with js.Publish (blocks for server ack — "prevents event loss on publish").
internal/worker/github_webhook_consumer.go implements GitHubWebhookJetStreamConsumer.SubscribeJetStream, a durable push consumer with explicit ack/nak, MaxDeliver-based dead-lettering, and configurable AckWait.
None of this is ever instantiated by a running binary. cfg.JetStreamEnabled is written into Config by Load() and then never read again — grep -rn "JetStreamEnabled" internal cmd outside config.go returns nothing. Both entrypoints unconditionally use the plain core-NATS path instead:
// cmd/api/main.go and cmd/worker/main.go
b, err := natsbus.Connect(cfg.NATSURL) // always the plain core Bus, never JetStreamBus
// cmd/worker/main.go
consumer := &worker.GitHubWebhookConsumer{
Ingest: &ingest.GitHubWebhookIngestor{Pool: dbConn.Pool},
LivenessTracker: livenessTracker,
}
if err := consumer.Subscribe(workerCtx, nbus.Conn(), worker.GitHubWebhookQueueGroup); err != nil {
consumer.Subscribe (the core, non-JetStream implementation) is a fire-and-forget queue-group subscription: natsbus.Bus.Publish calls plain nc.Publish, which has no persistence, no redelivery, and no dead-lettering. SubscribeJetStream/NewJetStreamBus are never called from any cmd/ package or from each other — they are reachable only from their own test files.
Requirements
cfg.JetStreamEnabled must actually gate which bus/consumer implementation cmd/api/main.go and cmd/worker/main.go construct.
- When
JS_ENABLED=true, the API process must publish GitHub webhook events via natsbus.NewJetStreamBus (or equivalent) instead of the plain core Bus, and the worker process must consume via GitHubWebhookJetStreamConsumer.SubscribeJetStream instead of the plain GitHubWebhookConsumer.Subscribe.
- When
JS_ENABLED=false (the default), current at-most-once behavior must be preserved so this is a strictly additive, opt-in change.
Suggested execution
- In
cmd/api/main.go and cmd/worker/main.go, branch on cfg.JetStreamEnabled right after natsbus.Connect to construct either the plain *natsbus.Bus or a *natsbus.JetStreamBus (via NewJetStreamBus with cfg.JetStreamStreamName/cfg.JetStreamMaxAge).
- In
cmd/worker/main.go, when JetStream is enabled, replace the worker.GitHubWebhookConsumer{...}.Subscribe(...) call with construction of a worker.GitHubWebhookJetStreamConsumer and a call to SubscribeJetStream using cfg.JetStreamConsumerName, cfg.JetStreamMaxDeliver, and cfg.JetStreamAckWait.
- Ensure
internal/api (wherever it currently calls bus.Publish for events.SubjectGitHubWebhookReceived) works unchanged against either bus.Bus implementation (it already should, since both satisfy the same interface).
- Add an integration-style test (or extend
internal/bus/natsbus/jetstream_test.go) that starts a worker with JS_ENABLED=true against a real/embedded NATS server and asserts a published event survives a simulated consumer restart (proving at-least-once delivery is actually active).
- Document in
docs/deployment that JS_ENABLED=true is required for durable webhook delivery in production, since today it silently does nothing.
Acceptance criteria
Security notes
This is a durability/data-integrity gap rather than a direct auth vulnerability: today, a worker crash or NATS hiccup between publish and consume permanently drops in-flight GitHub webhook events (issue/PR sync triggers, installation events) with no redelivery, regardless of how JS_ENABLED is configured — the operator has no way to actually turn on the durability guarantees this code was clearly built to provide.
Guidelines
- Minimum 95% test coverage
- Timeframe: 96 hours
Description
The codebase contains a complete, tested JetStream durability subsystem for GitHub webhook events:
internal/config/config.goparsesJS_ENABLED(JetStreamEnabled),JS_STREAM_NAME,JS_CONSUMER_NAME,JS_MAX_DELIVER,JS_ACK_WAIT, andJS_MAX_AGE.internal/bus/natsbus/jetstream.goimplementsJetStreamBus/NewJetStreamBus, abus.Busbacked by NATS JetStream withjs.Publish(blocks for server ack — "prevents event loss on publish").internal/worker/github_webhook_consumer.goimplementsGitHubWebhookJetStreamConsumer.SubscribeJetStream, a durable push consumer with explicit ack/nak,MaxDeliver-based dead-lettering, and configurableAckWait.None of this is ever instantiated by a running binary.
cfg.JetStreamEnabledis written intoConfigbyLoad()and then never read again —grep -rn "JetStreamEnabled" internal cmdoutsideconfig.goreturns nothing. Both entrypoints unconditionally use the plain core-NATS path instead:consumer.Subscribe(the core, non-JetStream implementation) is a fire-and-forget queue-group subscription:natsbus.Bus.Publishcalls plainnc.Publish, which has no persistence, no redelivery, and no dead-lettering.SubscribeJetStream/NewJetStreamBusare never called from anycmd/package or from each other — they are reachable only from their own test files.Requirements
cfg.JetStreamEnabledmust actually gate which bus/consumer implementationcmd/api/main.goandcmd/worker/main.goconstruct.JS_ENABLED=true, the API process must publish GitHub webhook events vianatsbus.NewJetStreamBus(or equivalent) instead of the plain coreBus, and the worker process must consume viaGitHubWebhookJetStreamConsumer.SubscribeJetStreaminstead of the plainGitHubWebhookConsumer.Subscribe.JS_ENABLED=false(the default), current at-most-once behavior must be preserved so this is a strictly additive, opt-in change.Suggested execution
cmd/api/main.goandcmd/worker/main.go, branch oncfg.JetStreamEnabledright afternatsbus.Connectto construct either the plain*natsbus.Busor a*natsbus.JetStreamBus(viaNewJetStreamBuswithcfg.JetStreamStreamName/cfg.JetStreamMaxAge).cmd/worker/main.go, when JetStream is enabled, replace theworker.GitHubWebhookConsumer{...}.Subscribe(...)call with construction of aworker.GitHubWebhookJetStreamConsumerand a call toSubscribeJetStreamusingcfg.JetStreamConsumerName,cfg.JetStreamMaxDeliver, andcfg.JetStreamAckWait.internal/api(wherever it currently callsbus.Publishforevents.SubjectGitHubWebhookReceived) works unchanged against eitherbus.Busimplementation (it already should, since both satisfy the same interface).internal/bus/natsbus/jetstream_test.go) that starts a worker withJS_ENABLED=trueagainst a real/embedded NATS server and asserts a published event survives a simulated consumer restart (proving at-least-once delivery is actually active).docs/deploymentthatJS_ENABLED=trueis required for durable webhook delivery in production, since today it silently does nothing.Acceptance criteria
JS_ENABLED=truecausescmd/apito publish throughJetStreamBusandcmd/workerto consume throughGitHubWebhookJetStreamConsumer.SubscribeJetStream.JS_ENABLED=false(or leaving it unset) preserves today's plain core-NATS behavior exactly.Security notes
This is a durability/data-integrity gap rather than a direct auth vulnerability: today, a worker crash or NATS hiccup between publish and consume permanently drops in-flight GitHub webhook events (issue/PR sync triggers, installation events) with no redelivery, regardless of how
JS_ENABLEDis configured — the operator has no way to actually turn on the durability guarantees this code was clearly built to provide.Guidelines