Vulcan v2.3.7
Released: 2026-05-10
A maintenance release that responds to public-comment-feature feedback from v2.3.6 with three meaningful additions plus a vocabulary refresh. No breaking changes — drop-in upgrade from v2.3.6.
Highlights
- Component-level comments — comments can now attach to a
Componentdirectly (not just to individual rules). Useful for component-wide feedback that doesn't belong on any one rule. Implemented via a polymorphiccommentableassociation onReview; existing rule-scoped comments are unaffected. - Project-aggregate disposition CSV export — a new project-level endpoint joins disposition data across every component in the project into a single CSV. Mirrors the per-component endpoint's shape, gates, and PII-aware email column behavior.
- Replies allowed on active threads after a comment period closes — once a component transitions to
closed(adjudicating / finalized), commenters and triagers can keep replying to existing threads. New top-level comments still respect the period gate. - Vocabulary refresh — the placeholder label for a comment that isn't tied to a specific XCCDF section is now Overall Requirement instead of
(general). Cleaner to authors and consistent with DISA's section terminology. - Toolbar rename — the rule editor's "Leave a Comment" button is now just Comment, matching the parallel "Comment History" panel button and the new component-level entry point.
Component-level comments
Previously, every Review (comment, response, approval) was tied to a Rule. v2.3.7 introduces a polymorphic commentable association so a Review can target a Component instead. The component triage page now exposes a top-level "Comment" button that opens the composer in component scope; rows in the triage table show whether each comment is component-level or rule-level.
This is purely additive — no migration of existing data is required; existing rule-level comments retain their original behavior.
Project-aggregate disposition CSV
GET /projects/:id/export/disposition_csvSame shape as the per-component endpoint, but rows are joined across every component in the project. Author-tier+ membership of the project is required; admin tier unlocks the include_email column. Filename: <project-name>-disposition-matrix-YYYY-MM-DD.csv.
The ComponentComments Vue surface (used in project-aggregate scope) now renders the Export CSV button that targets this endpoint.
Reply-after-close
When a component's comment period transitions to closed (adjudicating or finalized), POST /reviews for new top-level comments is rejected as before. Replies to threads that already have an active root comment, however, are now accepted — triagers can keep round-tripping with commenters on existing items without re-opening the period.
The validation lives on Review; the closed_period_message toast wording is unchanged but now only fires on actual top-level-comment posts during a closed period.
Upgrade notes
This is a drop-in upgrade from v2.3.6.
- A schema migration adds
commentable_type+commentable_idtoreviews, with a backfill that setscommentable_type = 'Rule'andcommentable_id = rule_idfor every existing row. Runbundle exec rails db:migrate(the entrypoint does this automatically on container start). - No env-var or Docker Compose changes.
- No new RuboCop, ESLint, or test-suite expectations beyond v2.3.6.
Internal
- The
lefthook.ymlpre-commit eslint step dropped--fixto match CI's strict mode. Developers runyarn lintmanually for autofixes — keeps formatting failures from being silently rewritten before commit. - Several stale frontend specs were refreshed alongside the UX changes (
SectionLabel,triageVocabulary,RuleActionsToolbar,ComponentComments).
