feat(canopy-mq): compile-time EventPayload macro + CI grep lint (event-bus-enforcement Steps 2+4)
Follow-up to the event-bus-enforcement plan, Steps 2 + 4 — both deferred at landing (2026-04-09) when runtime RestrictedFieldDetector was deemed sufficient for UAT.
Step 2 — compile-time EventPayload proc macro
Currently EventPayload is a marker trait. Convert to #[derive(EventPayload)] with a #[deny_field(...)] attribute, so a struct that adds (e.g.) an ssn: String field at construction time fails the build. This complements the existing runtime check by catching violations before they reach Publisher::publish.
Step 4 — CI grep lint
Add a defence-in-depth event-bus-lint GitLab CI job that greps services/*/src/events.rs for the same pattern set as RESTRICTED_FIELDS. Sketch lives in the plan; pull it onto .gitlab-ci.yml directly.
Why deferred
Runtime enforcement (Step 1 + 3 + 5 + 6, all done) already rejects payloads at publish time and is covered by 7+ unit tests. The compile-time + CI layers are pure defence-in-depth and add complexity without proportional safety gain pre-UAT.
References
- xref:plans/event-bus-enforcement.adoc[event-bus-enforcement plan] (Steps 2, 4 — Deferred)
crates/canopy-mq/src/restricted.rs— runtime detector