Skip to content
Open
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
625 commits
Select commit Hold shift + click to select a range
b9b9d59
test: Rename lock specs to components_lock_* — correct namespace
aaronlippold Jun 6, 2026
bd2ff37
test: add fixtures + factory traits for merge analyzer specs — v2-480.1
wdower Jun 6, 2026
6e2136c
feat(merge): ReviewMatcher composite-key partition — v2-480.1
wdower Jun 6, 2026
57a4f69
feat(merge): MergeInput normalizes JSON archive + spreadsheet — v2-480.1
wdower Jun 6, 2026
9aa2fb1
feat(merge): Strategy with per-entity defaults — v2-480.1
wdower Jun 6, 2026
5ea5a4f
refactor(rule): extract MERGEABLE_FIELDS constant — v2-480.1
wdower Jun 6, 2026
eecaf18
feat(merge): RuleFieldDiffer via hash comparison — v2-480.1
wdower Jun 6, 2026
830d1c8
feat(merge): RuleThreeWay per-field 3-way resolver — v2-480.1
wdower Jun 6, 2026
6165c17
feat(merge): MergePlan + MergeResult + partition invariant — v2-480.1
wdower Jun 6, 2026
b762f52
feat(merge): Analyzer assembles MergePlan + preconditions — v2-480.1
wdower Jun 6, 2026
2974326
feat(sync): rake sync:diff + sync:preview CLI — v2-480.1
wdower Jun 6, 2026
d0c2b21
test(perf): merge analyzer 500/5000 benchmark — v2-480.1
wdower Jun 6, 2026
fcdaed0
test: Extract srg_model_base — DRY shared context for reviews + rules
aaronlippold Jun 6, 2026
91eae55
test: Regroup 7 misplaced test blocks into correct domain files
aaronlippold Jun 6, 2026
65cb18e
test: Remove redundant rubocop:disable + dead let_it_be + stale refs
aaronlippold Jun 6, 2026
d3cf0d7
test: Fix parallel safety — Review.last → scoped queries + remove ensure
aaronlippold Jun 6, 2026
534a7ef
test: Add Review callback coverage — triage_status + redirect + replies
aaronlippold Jun 6, 2026
da1d727
test: Add Review.bulk_triage model-level unit tests — 5 untested paths
aaronlippold Jun 6, 2026
abbf365
test: Fix RSpec/IndexedLet cop — rename indexed let vars
aaronlippold Jun 6, 2026
71bb97f
test: Add valid?(:import_integrity) context tests — verify scoping
aaronlippold Jun 6, 2026
4549eaf
test: Fix RSpec/DescribeMethod cop — nest describe inside RSpec.describe
aaronlippold Jun 6, 2026
443b723
test: Add Component#overlay + #duplicate new_srg + import failure tests
aaronlippold Jun 6, 2026
f1926dd
test: Add Component member search + validation edge cases
aaronlippold Jun 6, 2026
a5bc527
test: Add Review edge case coverage — scopes + accessor + sync
aaronlippold Jun 6, 2026
5052f16
test: Add Component amoeba + comment_period boundary tests
aaronlippold Jun 6, 2026
32c6845
test: Cover skipped v2-8ea.9 ACs — no more deferred gaps
aaronlippold Jun 6, 2026
cb6c9ee
test: Cover skipped v2-8ea.13 ACs — name delegation + merge + FK
aaronlippold Jun 6, 2026
4757247
test: Cover skipped v2-8ea.15 ACs — amoeba + admin + metadata
aaronlippold Jun 6, 2026
4271c98
feat: Add SPA auth endpoints — GET /me + POST login + DELETE logout
aaronlippold Jun 6, 2026
5e6a14d
feat: Add GET /api/settings — public pre-auth UI config
aaronlippold Jun 6, 2026
2732afa
feat: Add effective_permissions to project/component JSON
aaronlippold Jun 6, 2026
cfd5654
fix: Add effective_permissions to OpenAPI schemas + contract tests
aaronlippold Jun 6, 2026
9f8892b
feat: Add GET /api/navigation — app shell data for SPA
aaronlippold Jun 6, 2026
1372cdc
fix: Centralize review serialization on ReviewBlueprint
aaronlippold Jun 6, 2026
665a35c
docs: ADR for API filtering concern — pagy + has_scope
aaronlippold Jun 6, 2026
18c2534
feat: Add ApiFilterable concern with pagy + has_scope
aaronlippold Jun 7, 2026
59d6777
fix: Replace MAX(version) string sort with numeric SUBSTRING parsing
aaronlippold Jun 7, 2026
007dabd
refactor: Migrate render_as_hash to render_as_json
aaronlippold Jun 7, 2026
4c438d0
fix: Add commenter_email + auth coverage + schema fixes
aaronlippold Jun 7, 2026
7d44af8
chore: Add OpenAPI bundle staleness check + remove dead overcommit
aaronlippold Jun 7, 2026
e7ac60c
feat: Integrate Scalar API docs with Vulcan design system
aaronlippold Jun 7, 2026
ac18be3
refactor: Migrate render_as_hash in Blueprint nested calls
aaronlippold Jun 7, 2026
1d604fe
chore: Exclude HAML files from rubocop — parser cannot handle them
aaronlippold Jun 7, 2026
bdc26a1
fix: Eliminate brakeman SQL injection warning in VersionSortable
aaronlippold Jun 7, 2026
d1ec351
chore: Fix Gemfile lint + lefthook openapi --quiet flag
aaronlippold Jun 7, 2026
a11363d
test: Migrate spec files to render_as_json string keys
aaronlippold Jun 7, 2026
6dc1545
feat: Add ProjectAccessRequestBlueprint — replace hand-built hashes
aaronlippold Jun 7, 2026
8f5703b
feat: Add AuditBlueprint — replace VulcanAudit#format in controllers
aaronlippold Jun 7, 2026
db6f2a9
refactor: Replace current_user.slice with UserBlueprint in layout
aaronlippold Jun 7, 2026
95813d4
fix: Use string key for consent_config required field
aaronlippold Jun 7, 2026
9494d71
feat: Add usePermissions composable + roleGteTo utility
aaronlippold Jun 7, 2026
bae1688
feat: Root components provide permissions from Blueprint data
aaronlippold Jun 7, 2026
f9cfccf
chore: Delete EmptyObjectMixin — dead code, zero consumers
aaronlippold Jun 7, 2026
2ffa786
feat: Add useDateFormat composable + begin mixin migration
aaronlippold Jun 7, 2026
0c5f678
feat: Add useAuthToken composable — extract from FormMixin
aaronlippold Jun 7, 2026
51cbe7c
feat: Add 4 utility composables from mixins
aaronlippold Jun 7, 2026
4e81048
fix: Update jwt 3.2.0 + puma 7.2.1 — resolve 3 CVEs
aaronlippold Jun 7, 2026
1c5b96e
fix: Stabilize upgrade:verify + admin:bootstrap tests
aaronlippold Jun 7, 2026
ce9e18d
fix: Add bundler/setup to legacy_db_renamer
aaronlippold Jun 7, 2026
9053f75
test: Fix missed render_as_json string key migrations
aaronlippold Jun 8, 2026
a4382a3
wip: Scalar agent investigation + openapi route aliases
aaronlippold Jun 8, 2026
6bf42b5
test: Fix remaining render_as_json string key migrations
aaronlippold Jun 8, 2026
507fdcd
fix: Standardize Settings integer types + add type contract test
aaronlippold Jun 8, 2026
2439dd4
fix: Disable auditing in test env — eliminate parallel deadlocks
aaronlippold Jun 8, 2026
60227f8
fix: Add network reachability guard to Okta OIDC integration tests
aaronlippold Jun 8, 2026
c5b94f2
fix: Restore authenticate_scope! for Devise edit/update/destroy
aaronlippold Jun 8, 2026
8ab53f0
chore: Update devise-security to 65683e9 — nil record guard
aaronlippold Jun 8, 2026
b3d0705
feat: Load Scalar API docs from registry + CSP update
aaronlippold Jun 9, 2026
32119b2
chore: Add OpenAPI registry publish to release workflow + Node 24
aaronlippold Jun 9, 2026
8b01ed6
feat: Add vitepress-openapi auto-generated API reference
aaronlippold Jun 9, 2026
0c010ea
chore: Add openapi:docs command + CI workflow + documentation updates
aaronlippold Jun 9, 2026
0129174
bd: clear sync.remote
wdower Jun 7, 2026
6955818
bd: update sync.remote
wdower Jun 7, 2026
15461bd
fix(merge): RuleFieldDiffer reads locked_fields correctly — v2-dqx
wdower Jun 7, 2026
5539f6b
feat(rule): NESTED_MERGEABLE_ASSOCIATIONS schema — v2-dqx
wdower Jun 7, 2026
1670b83
feat(merge): NestedAssociationDiffer service — v2-dqx
wdower Jun 7, 2026
295eba6
feat(merge): VirtualRule exposes nested associations — v2-dqx
wdower Jun 7, 2026
1a357ba
feat(merge): wire NestedAssociationDiffer into Analyzer — v2-dqx
wdower Jun 8, 2026
4b0dacb
test(merge): rake-CLI regression for locked-section bypass — v2-dqx
wdower Jun 8, 2026
63abe6d
fix(merge): analyzer skips comment_phase precondition — v2-dqx
wdower Jun 8, 2026
9b9780b
feat(merge): MergeApplier skeleton + sync event lifecycle — v2-480.8
wdower Jun 8, 2026
f30e5cc
feat(merge): snapshot + archive hash + apply precondition — v2-480.8
wdower Jun 8, 2026
187aa6a
feat(merge): apply rule auto-merged field changes — v2-480.8
wdower Jun 8, 2026
fb7de56
feat(merge): skip conflicts with explicit log row — v2-480.8
wdower Jun 8, 2026
ac6d3ca
refactor(merge): MergePlan stores partition records — v2-480.8
wdower Jun 8, 2026
e10587d
feat(merge): import only_theirs reviews via ReviewBuilder — v2-480.8
wdower Jun 8, 2026
1fd9b7f
feat(merge): review field updates + dual-write commentable — v2-480.8
wdower Jun 8, 2026
62291c2
feat(merge): apply only_theirs satisfactions via upsert_all — v2-480.8
wdower Jun 8, 2026
9f1a342
feat(merge): apply only_theirs memberships at viewer tier — v2-480.8
wdower Jun 8, 2026
980aae8
feat(merge): quarantine invalid records — v2-480.8
wdower Jun 8, 2026
f443eed
feat(merge): VulcanAudit correlation scope — v2-480.8
wdower Jun 8, 2026
f3c5900
feat(merge): stamp component sync metadata on apply — v2-480.8
wdower Jun 8, 2026
2471867
test(merge): integration round-trip via Analyzer + Applier — v2-480.8
wdower Jun 8, 2026
9a98623
test(perf): MergeApplier 500-write benchmark — v2-480.8
wdower Jun 8, 2026
2e223c2
feat(merge): one-pending-sync-per-component invariant — v2-480.30
wdower Jun 8, 2026
4c2c003
feat(merge): advisory lock + reload-locked precondition — v2-480.30
wdower Jun 8, 2026
91b876d
feat(merge): log_review_insert maps to actual Review.id — v2-480.31
wdower Jun 8, 2026
92ba525
perf(merge): eager_load helper + memoize rule_id_map — v2-480.32
wdower Jun 8, 2026
04e2822
feat(merge): savepoint quarantine + buffered drain — v2-480.27
wdower Jun 8, 2026
53f1a0c
feat(merge): import review reactions on insert path — v2-480.28
wdower Jun 8, 2026
6889d7a
feat(merge): archive_hash replay protection — v2-480.29
wdower Jun 8, 2026
4ffeb2f
feat(merge): apply_new_rules imports only_theirs rules — v2-480.24
wdower Jun 8, 2026
a356ed9
fix(merge): remap addressed_by_rule_id via rule_id_map — v2-480.25
wdower Jun 8, 2026
5459ebf
feat(merge): bump backup_format_version to 1.1 — v2-480.26
wdower Jun 8, 2026
d411c96
fix(merge): route nested FieldChanges to nested records — v2-480.23
wdower Jun 8, 2026
f13ba2d
fix(merge): move severity_override_guidance to Severity — v2-480.33
wdower Jun 8, 2026
a9c2bd0
feat(merge): surface nested one-sided records in plan log — v2-480.34
wdower Jun 8, 2026
b501cb4
feat(merge): surface collisions + add ceilings — v2-480.35
wdower Jun 9, 2026
73a71bb
feat(merge): atomic snapshot + retention + scoped repair — v2-480.38
wdower Jun 9, 2026
9782aa5
feat(merge): persist failure_diagnostics on sync events — v2-480.36
wdower Jun 9, 2026
b6b9f49
feat(merge): plumb actor + bulk-insert review audit rows — v2-480.37
wdower Jun 9, 2026
4e4c094
docs(merge): component meta is preserved, not merged — v2-480.41
wdower Jun 9, 2026
f18bb04
feat(merge): review skip audit + status state machine — v2-480.40
wdower Jun 9, 2026
c138cc6
refactor(merge): MergePlan exposes frozen accessors — v2-480.42
wdower Jun 9, 2026
50f6341
feat(merge): central verb map + Review::MERGEABLE_FIELDS — v2-480.39
wdower Jun 9, 2026
00e9c6e
feat(import): manifest validator merge-mode warning — v2-480.9
wdower Jun 9, 2026
ca10569
feat(merge): signed-archive gate — v2-480.9
wdower Jun 9, 2026
1e115b7
feat(merge): MergeOrchestrator service — v2-480.9
wdower Jun 9, 2026
070d3fe
feat(merge): MergeJob wraps Orchestrator on ActiveJob — v2-480.9
wdower Jun 9, 2026
941bafb
feat: Add DISA guide migration rake task
aaronlippold Jun 9, 2026
77677f0
feat: Update DISA Vendor STIG Process Guide to V4R3
aaronlippold Jun 9, 2026
e492fc0
feat: Add native HTML element dark mode variables
aaronlippold Jun 9, 2026
4a4cfb8
chore: Untrack .beads/interactions.jsonl
aaronlippold Jun 9, 2026
58e8126
fix: Blank VulnDiscussion + Severity for NA, Check/Fix for ADNM
aaronlippold Jun 9, 2026
1f6140a
refactor: Regroup component specs by domain + fix shared context
aaronlippold Jun 9, 2026
fd9c0c9
test: Add auth tests for 9 component controller actions
aaronlippold Jun 9, 2026
8e6dd57
test: Add auth rejection tests for 8 partial-coverage actions
aaronlippold Jun 9, 2026
d33064c
feat: Add Phase 1 composables — mixin migration prep
aaronlippold Jun 9, 2026
b19b3a0
fix: Eliminate all unit suite stderr noise — six root causes
aaronlippold Jun 9, 2026
ecf215a
test: Pin single-Vue-copy invariant for the vitest Vue alias
aaronlippold Jun 10, 2026
ca10a67
test: Assert navigation and window.open side effects in specs
aaronlippold Jun 10, 2026
d8ac385
refactor: Migrate shared/ components off non-Alert mixins
aaronlippold Jun 10, 2026
7cc353b
refactor: Migrate project/ components off non-Alert mixins
aaronlippold Jun 10, 2026
35ad7bb
fix: Float navbar utility dropdowns over content at all widths
aaronlippold Jun 10, 2026
11ddc8e
fix: Wrap ComponentCard action toolbar cleanly at narrow widths
aaronlippold Jun 10, 2026
b6f0426
refactor: Migrate permissions cluster to inject — delete dead components
aaronlippold Jun 11, 2026
87520cc
refactor: Remove dead FormMixin imports from components/
aaronlippold Jun 11, 2026
a8b6a45
refactor: Migrate real authenticityToken consumers to useAuthToken
aaronlippold Jun 11, 2026
6e1d509
refactor: Migrate ComponentComments to composables — delete dead modal
aaronlippold Jun 11, 2026
e4fc833
refactor: Migrate ProjectComponent off non-Alert mixins
aaronlippold Jun 11, 2026
a579fd9
fix: Point navbar DISA guide link at the process guide page
aaronlippold Jun 11, 2026
83cfb7d
test: Fix merge engine spec failures — auditing opt-in + fixture shape
aaronlippold Jun 11, 2026
97facb9
fix: Convert project_metadata.data to jsonb — parity with components
aaronlippold Jun 11, 2026
c59f3dc
fix: Reload on expired-session 401 — surface Devise flash + return-to
aaronlippold Jun 11, 2026
f9db29d
docs: Add Bootstrap tier-wiring design + evidence appendix
aaronlippold Jun 11, 2026
b461f70
refactor: Migrate rules/ components off non-Alert mixins
aaronlippold Jun 11, 2026
b6f83c6
chore: Remove tracker card IDs from code and test comments
aaronlippold Jun 11, 2026
f3a8e28
chore: Enforce zero-warning ESLint on spec/javascript
aaronlippold Jun 11, 2026
436f6dd
chore: Remove tracker card IDs from Ruby code and specs
aaronlippold Jun 11, 2026
b0d5074
fix: Match current board prefix in tracker-ID lint rules
aaronlippold Jun 11, 2026
3ccd6d7
chore: Remove bare card-ID fragments from comments
aaronlippold Jun 11, 2026
6599aef
refactor: Migrate users/triage/projects/navbar off non-Alert mixins
aaronlippold Jun 11, 2026
d5027c9
fix: Use ky's pre-parsed error.data for HTTP error bodies in baseApi
aaronlippold Jun 11, 2026
7636ed0
feat: Add useToast composable with cross-pack Toaster event bridge
aaronlippold Jun 11, 2026
d4e38c4
refactor: Migrate all AlertMixin consumers to useToast
aaronlippold Jun 11, 2026
b40f754
fix: Wire missing toast handler in Projects refresh error path
aaronlippold Jun 11, 2026
cc85743
refactor: Delete mixins directory — composables migration complete
aaronlippold Jun 11, 2026
072bcfa
refactor: Derive comment-period help card from triageVocabulary
aaronlippold Jun 11, 2026
80f6ead
fix: Redirect sign-out to the sign-in page so the flash survives
aaronlippold Jun 11, 2026
7406264
fix: Make navbar sign-out a navigational DELETE so Devise can flash
aaronlippold Jun 11, 2026
775ec5c
test: Cover the Projects refresh error handler wiring
aaronlippold Jun 11, 2026
3af4ab2
feat(merge): SyncController + merge/status routes — v2-480.9
wdower Jun 10, 2026
b584335
refactor(merge): align Phase 2c with card — import_backup?merge=true
wdower Jun 13, 2026
51d7583
fix: Gate profile email changes on password, not every save
aaronlippold Jun 12, 2026
af30152
feat: Land OIDC sign-out on /users/signed_out with correct fallback
aaronlippold Jun 12, 2026
a41f50d
docs: Rewrite SSO setup guide operator-first with provider table
aaronlippold Jun 12, 2026
d6dcf2f
docs: Add multi-provider OIDC ADR (multi-link identities)
aaronlippold Jun 13, 2026
be83f52
feat: Add multi-provider OIDC registry (Settings.oidc.providers)
aaronlippold Jun 13, 2026
e75ed0f
feat: Register an OIDC strategy per provider with per-provider buttons
aaronlippold Jun 14, 2026
7c279b8
feat: Add identities table for multi-link provider accounts
aaronlippold Jun 14, 2026
60c7ab0
feat: Rewrite from_omniauth to identity-first with cold-match block
aaronlippold Jun 14, 2026
83258f6
feat: Backfill identities from existing non-local users
aaronlippold Jun 14, 2026
ac06732
feat: Wire jwt_bearer private key loading for login.gov auth
aaronlippold Jun 14, 2026
b6f3c40
feat: Resolve OIDC logout per provider from session
aaronlippold Jun 14, 2026
331db01
feat: Make CSP and health check multi-provider OIDC aware
aaronlippold Jun 14, 2026
480ea9c
feat: Add User identity mutation API — link/unlink/can_unlink
aaronlippold Jun 14, 2026
2ab55e3
refactor: Replace upsert_identity with link_identity! in from_omniauth
aaronlippold Jun 14, 2026
f25c72a
refactor: Thin identity controllers — link/unlink use model API
aaronlippold Jun 14, 2026
56c58b2
feat: Add Connected Accounts profile section and admin view
aaronlippold Jun 14, 2026
4dab840
feat: Add provider rename rake task + rubocop task exclusion
aaronlippold Jun 14, 2026
6c8bfba
feat: Polish Connected Accounts with Add Account dropdown
aaronlippold Jun 14, 2026
f37149f
fix: Update OpenAPI schema + contract tests for identity fields
aaronlippold Jun 14, 2026
1e33e6a
feat: Add Register with provider buttons to registration tab
aaronlippold Jun 14, 2026
daad80d
feat: Add per-provider logos with proper aspect ratios
aaronlippold Jun 14, 2026
a819bbd
docs: Add multi-provider OIDC + Login.gov to .env.example
aaronlippold Jun 14, 2026
849f6b8
refactor: DRY provider buttons into shared partial
aaronlippold Jun 14, 2026
9ce696f
fix: Replace provider logos with official dark-mode-aware SVGs
aaronlippold Jun 14, 2026
54e27ec
refactor: Redesign login page layout — centered, balanced, polished
aaronlippold Jun 14, 2026
22c47ba
fix: Strengthen login card visibility with shadow + border
aaronlippold Jun 14, 2026
2cff8d3
chore: Add provider-logo class to button partial images
aaronlippold Jun 14, 2026
22aca0d
feat: Allow SSO users to set a local password (GitLab pattern)
aaronlippold Jun 14, 2026
a5a4a83
feat: Stack provider logos above text in login/register buttons
aaronlippold Jun 14, 2026
3760016
revert: Return provider buttons to inline logo + text layout
aaronlippold Jun 14, 2026
eda6ad2
feat: Add Link Existing Account flow on cold-match conflict
aaronlippold Jun 14, 2026
dd665ec
feat: Add Link Existing Account form to login page
aaronlippold Jun 14, 2026
55f4988
docs: Add Login.gov setup guide + multi-provider env var docs
aaronlippold Jun 14, 2026
3b89c47
fix: Update specs for multi-provider registry (oidc → okta)
aaronlippold Jun 15, 2026
a363376
fix: Move fields-hidden alert above Status + add rule histories
aaronlippold Jun 16, 2026
d940afc
refactor: Rename Activity/History/Comment History labels
aaronlippold Jun 16, 2026
4878e82
feat: Add SRG info with version currency to comment views
aaronlippold Jun 16, 2026
2119a0f
feat: Add VuePropsHelper + HAML serialization standard
aaronlippold Jun 16, 2026
5843ca5
feat: Add VersionCurrency — is_latest dots on all list pages
aaronlippold Jun 16, 2026
734299e
docs: Add DISA Library Service ADR + v2.x roadmap
aaronlippold Jun 16, 2026
623c52d
fix: Update UserProfile unlink tests for identity-based model
aaronlippold Jun 16, 2026
a731ed6
docs: SPA spike report + updated roadmap
aaronlippold Jun 16, 2026
0d8258e
fix: Use configured Devise unlock strategy in test environment
aaronlippold Jul 9, 2026
a80edde
feat: Add JSON support to Devise auth flows
aaronlippold Jul 9, 2026
7582af0
docs: Add OpenAPI specs + contract tests for Devise auth flows
aaronlippold Jul 9, 2026
2557cf3
chore(deps): Update 10 gems with security patches
aaronlippold Jul 9, 2026
9245cfd
fix: Log swallowed exceptions in the catch-all error handler
aaronlippold Jul 10, 2026
c706448
fix: Self-delete 500 — skip session_limitable on destroyed records
aaronlippold Jul 10, 2026
5092b87
feat: Require re-authentication and last-admin guard on self-delete
aaronlippold Jul 10, 2026
db40a68
feat: Enforce project admin continuity at the membership layer
aaronlippold Jul 10, 2026
df9e0ef
feat: Block user deletion when sole project admin
aaronlippold Jul 10, 2026
e5d9d6d
fix: Add JSON response path to project access request creation
aaronlippold Jul 10, 2026
94f4041
feat: Add latest-benchmark endpoints — SRGs, STIGs, components
aaronlippold Jul 10, 2026
b9b08fb
feat: Add benchmark stats endpoints — rule counts and SRG usage
aaronlippold Jul 10, 2026
8e88a28
feat: Add component summary endpoint with comment-phase state
aaronlippold Jul 10, 2026
3f57ef5
docs: Document GET /api/projects in OpenAPI with contract tests
aaronlippold Jul 10, 2026
969778a
feat: Add dashboard endpoints — stats, workflow state, triage summary
aaronlippold Jul 10, 2026
7f300cf
docs: Add SRG Component authoring ADR
aaronlippold Jul 11, 2026
790f535
test: Make sync-metadata timestamp assertion load-independent
aaronlippold Jul 11, 2026
e96c34a
test: Freeze time in login and comment throttle specs
aaronlippold Jul 11, 2026
0f22662
fix: Re-apply Settings defaults on reload! to stop seed-order flakes
aaronlippold Jul 11, 2026
c1e0634
test: Convert wall-clock timestamp assertions to bounds pattern
aaronlippold Jul 12, 2026
3d6d9fc
test: Quiet ambient backend-suite noise
aaronlippold Jul 12, 2026
b642946
test: Extract with_settings_env shared reload helper
aaronlippold Jul 12, 2026
ef8320f
refactor: Remove component sync/merge engine from #731
wdower Jul 12, 2026
4887a9c
Merge origin/master into merge-removal CI branch
wdower Jul 12, 2026
7ef2830
fix: Restore #731 Gemfile.lock + drop merge tests from validator spec
wdower Jul 12, 2026
761cfa5
docs: Reframe SRG ADR as generalized XCCDF authoring + add user workflow
wdower Jul 12, 2026
43e5921
Merge chore/731-remove-merge-engine: split out component sync/merge
wdower Jul 12, 2026
780fe67
fix: Serialize collections in deterministic canonical order
aaronlippold Jul 13, 2026
efb1f70
test: Make settings defaults deterministic; drop source-grep spec
aaronlippold Jul 13, 2026
bf3f97e
docs: Add dual-version XCCDF export ADR — 1.1.4 and 1.2
aaronlippold Jul 13, 2026
023e0bb
Merge origin branch: ADR v6 + merge-engine split to own PR
aaronlippold Jul 13, 2026
587a8b8
fix: Recount rules_count when a rule is soft-deleted
aaronlippold Jul 13, 2026
1bfb3c5
docs: SRG ADR v7 — resolve all five review items + backups
aaronlippold Jul 13, 2026
570000f
docs: Align ADR remaining sections with Design C relocation
aaronlippold Jul 13, 2026
f5afc4f
docs: ADR v7.1 — five code-verified mechanics fixes from review
aaronlippold Jul 13, 2026
845d58b
docs: ADR v7.2 — migration-plan hardening from schema review
aaronlippold Jul 13, 2026
81b3ea4
docs: ADR v7.3 — collision review sizes the real blast radius
aaronlippold Jul 13, 2026
6423533
docs: ADR v7.4 — consistency pass reconciles doc with its fixes
aaronlippold Jul 13, 2026
8b228ac
docs: ADR erratum — backup serializer joins the scoping-site list
aaronlippold Jul 13, 2026
25eb80c
feat: Surface satisfied-by parent context across all rule views
aaronlippold Jul 13, 2026
cd8b42e
refactor: Unify comment rendering on CommentItem and CommentList
aaronlippold Jul 13, 2026
833804a
feat: Add SRG authoring storage seam — schema + SrgRule expansion
aaronlippold Jul 14, 2026
5bce6c6
chore: Note Vue 3 migration debt on CommentList updateRow
aaronlippold Jul 14, 2026
df04852
chore: Remove internal tracker and design-doc references from source
aaronlippold Jul 14, 2026
a253402
feat: Add SRG status model backend — registry, vocabulary, scoping
aaronlippold Jul 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **Three-column triage split-pane** — triagers see a persistent rule sidebar (col-2), rule content (col-5), and comment + triage form (col-5) side by side, replacing the prev/next nav + modal workflow. Sidebar shows rules grouped with pending/total counts, search filter, and keyboard navigation. Reuses BenchmarkViewer layout pattern. (PR #731)
- **Triage progress bar** — summary pills with clickable status filter + thin stacked bar above the comments table. Shows per-status counts (All, Pending, Accepted, Declined, etc.) with "N of M resolved (X%)" summary. Click a pill to filter; click again to reset. Works on both component and project triage pages. (PR #731)
- **DRY triage color palette** — centralized CSS custom properties in `triage-tints.css` as single source of truth. Colors: green (Accepted), blue (Accepted with Changes — ISO 3864 mandatory-action), red (Declined), yellow (Informational), grey (Pending), purple (Withdrawn — GitHub pattern), teal (Duplicate — Linear pattern). (PR #731)
- **ARIA landmarks + focus management** — split-pane uses `<nav>`, `role="main"`, `role="complementary"` landmarks. Skip links for keyboard users. Focus lands on content heading on entry and after Save & Next (WAI-ARIA APG content-first pattern). Sidebar is a composite widget (single Tab stop, arrow keys inside). (PR #731)
- **InfoTooltip + InfoNotice shared components** — consistent (i) icon tooltip pattern (15 instances migrated) and inline info notice pattern (2 instances) across the app. (PR #731)
- **2D queue navigation** — skip-start/end icons for rule-level nav, chevrons for comment-level, Browse popover panel with search + keyboard nav. (PR #731)
- **By-rule accordion view** — collapsible groups by rule with pending/total counts, Expand All toggle, auto-expand on filter change. (PR #731)
- **Staleness badge** — "Section updated since this comment" when rule content changed after comment was posted. (PR #731)
- **Admin actions inline** — dropdown on triage form button row (replaces sidebar). Force-withdraw, restore, move-to-rule, hard-delete with typed-ID confirmation. (PR #731)

### Changed

- **Show Resolved toggle removed** — replaced by clickable progress bar pills that serve as both status indicators and filter controls. "Pending" pill replaces the default filter; "All" pill shows everything. Eliminates the state model conflict between toggle and pill filters. (PR #731)
- Renamed "Triage Queue" to "Comments" (heading, breadcrumbs, aria labels). (PR #731)
- Commented/All toggle moved to rule ID row as simple switch. (PR #731)
- Locked fields now allow comments (lock prevents editing, not commenting). (PR #731)

### Fixed

- SRG viewer sidebar highlighted all rules instead of first selected — `SrgRuleBlueprint` was missing `identifier :id`. (PR #731)
- Split-pane exits when filter changes — watcher now selects first available comment instead of exiting when the active comment is filtered out. (PR #731)
- `doSave` only adjudicates on "Save & next", not "Save decision". (PR #731)
- Factory traits `after(:build)` DB writes fixed to `before(:create)`. (PR #731)

## [v2.3.7] - 2026-05-10

### Added
Expand Down
48 changes: 24 additions & 24 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ GEM
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
addressable (2.8.9)
addressable (2.9.0)
public_suffix (>= 2.0.2, < 8.0)
aes_key_wrap (1.1.0)
amoeba (3.3.0)
Expand Down Expand Up @@ -168,7 +168,7 @@ GEM
database_cleaner-core (~> 2.0)
database_cleaner-core (2.0.1)
date (3.5.1)
devise (5.0.3)
devise (5.0.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 7.0)
Expand All @@ -184,7 +184,7 @@ GEM
dotenv (= 3.2.0)
railties (>= 6.1)
drb (2.2.3)
erb (6.0.2)
erb (6.0.4)
erubi (1.13.1)
factory_bot (6.5.6)
activesupport (>= 6.1.0)
Expand Down Expand Up @@ -278,7 +278,7 @@ GEM
tty-prompt (~> 0.17)
tty-table (~> 0.10)
io-console (0.8.2)
irb (1.17.0)
irb (1.18.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
Expand Down Expand Up @@ -331,7 +331,7 @@ GEM
mime-types-data (3.2025.0812)
mini_mime (1.1.5)
mini_portile2 (2.8.9)
minitest (6.0.3)
minitest (6.0.6)
drb (~> 2.0)
prism (~> 1.5)
mitre-inspec-objects (0.3.3)
Expand All @@ -348,7 +348,7 @@ GEM
bigdecimal (~> 3.1)
multipart-post (2.4.1)
mutex_m (0.3.0)
net-imap (0.6.3)
net-imap (0.6.4)
date
net-protocol
net-ldap (0.20.0)
Expand All @@ -365,16 +365,16 @@ GEM
net-ssh (7.3.0)
netrc (0.11.0)
nio4r (2.7.5)
nokogiri (1.19.2)
nokogiri (1.19.3)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.19.2-aarch64-linux-gnu)
nokogiri (1.19.3-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.19.2-arm64-darwin)
nokogiri (1.19.3-arm64-darwin)
racc (~> 1.4)
nokogiri (1.19.2-x86_64-linux-gnu)
nokogiri (1.19.3-x86_64-linux-gnu)
racc (~> 1.4)
nokogiri (1.19.2-x86_64-linux-musl)
nokogiri (1.19.3-x86_64-linux-musl)
racc (~> 1.4)
nokogiri-happymapper (0.10.0)
nokogiri (~> 1.5)
Expand Down Expand Up @@ -458,12 +458,12 @@ GEM
psych (5.3.1)
date
stringio
public_suffix (7.0.2)
public_suffix (7.0.5)
puma (7.2.0)
nio4r (~> 2.0)
pyu-ruby-sasl (0.0.3.3)
racc (1.8.1)
rack (2.2.23)
rack (3.2.6)
rack-attack (6.8.0)
rack (>= 1.0, < 4)
rack-oauth2 (1.21.3)
Expand All @@ -472,16 +472,17 @@ GEM
httpclient
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
rack-protection (3.2.0)
rack-protection (4.2.1)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
rack-session (1.0.2)
rack (< 3)
logger (>= 1.6.0)
rack (>= 3.0.0, < 4)
rack-session (2.1.2)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (1.0.1)
rack (< 3)
webrick
rackup (2.3.1)
rack (>= 3)
rails (8.0.5)
actioncable (= 8.0.5)
actionmailbox (= 8.0.5)
Expand Down Expand Up @@ -513,7 +514,7 @@ GEM
tsort (>= 0.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.3.1)
rake (13.4.2)
rake-compiler-dock (1.11.0)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
Expand Down Expand Up @@ -706,7 +707,6 @@ GEM
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webrick (1.9.2)
websocket (1.2.11)
websocket-driver (0.8.0)
base64
Expand All @@ -718,7 +718,7 @@ GEM
zeitwerk (>= 2.6)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.7.5)
zeitwerk (2.8.1)

PLATFORMS
aarch64-linux
Expand Down Expand Up @@ -805,4 +805,4 @@ RUBY VERSION
ruby 3.4.9p82

BUNDLED WITH
2.7.2
2.6.9
2 changes: 1 addition & 1 deletion app/blueprints/srg_rule_blueprint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Used as nested data inside RuleBlueprint :editor view for the srg_rule_attributes field.
# Excludes internal fields that the editor doesn't need (id, locked, timestamps, etc.).
class SrgRuleBlueprint < Blueprinter::Base
# No identifier — this is always nested, never fetched by ID
identifier :id

fields :rule_id, :title, :version, :rule_severity, :rule_weight,
:ident, :ident_system, :fixtext, :fixtext_fixref, :fix_id,
Expand Down
36 changes: 21 additions & 15 deletions app/controllers/components_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -340,21 +340,27 @@ def settings
def comments
return head :not_found unless @component

result = @component.paginated_comments(
triage_status: params[:triage_status].presence || 'pending',
section: params[:section].presence,
rule_id: params[:rule_id].presence,
author_id: params[:author_id].presence,
query: params[:q].presence,
page: params[:page].presence || 1,
per_page: params[:per_page].presence || 25,
resolved: params[:resolved].presence || 'all',
commentable_type: params[:commentable_type].presence
)

inject_reactions_mine!(result[:rows])
response.headers['Cache-Control'] = 'no-store'
render json: result
respond_to do |format|
format.html { redirect_to "/components/#{@component.id}/triage" }
format.json do
result = @component.paginated_comments(
triage_status: params[:triage_status].presence || 'pending',
section: params[:section].presence,
rule_id: params[:rule_id].presence,
author_id: params[:author_id].presence,
query: params[:q].presence,
page: params[:page].presence || 1,
per_page: params[:per_page].presence || 25,
resolved: params[:resolved].presence || 'all',
commentable_type: params[:commentable_type].presence,
include_rule_content: ActiveModel::Type::Boolean.new.cast(params[:include_rule_content])
)

inject_reactions_mine!(result[:rows])
response.headers['Cache-Control'] = 'no-store'
render json: result
end
end
end

def based_on_same_srg
Expand Down
31 changes: 18 additions & 13 deletions app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,24 @@ def triage
def comments
return head :not_found unless @project

result = @project.paginated_comments(
triage_status: params[:triage_status].presence || 'pending',
section: params[:section].presence,
component_id: params[:component_id].presence,
author_id: params[:author_id].presence,
query: params[:q].presence,
page: params[:page].presence || 1,
per_page: params[:per_page].presence || 25,
resolved: params[:resolved].presence || 'all'
)
inject_reactions_mine!(result[:rows])
response.headers['Cache-Control'] = 'no-store'
render json: result
respond_to do |format|
format.html { redirect_to "/projects/#{@project.id}/triage" }
format.json do
result = @project.paginated_comments(
triage_status: params[:triage_status].presence || 'pending',
section: params[:section].presence,
component_id: params[:component_id].presence,
author_id: params[:author_id].presence,
query: params[:q].presence,
page: params[:page].presence || 1,
per_page: params[:per_page].presence || 25,
resolved: params[:resolved].presence || 'all'
)
inject_reactions_mine!(result[:rows])
response.headers['Cache-Control'] = 'no-store'
render json: result
end
end
end

def create
Expand Down
1 change: 1 addition & 0 deletions app/javascript/application.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@import "bootstrap/scss/bootstrap";
@import "bootstrap-vue/src/index.scss";
@import "./styles/triage-tints.css";

// Bootstrap Icons are included via the IconsPlugin in Vue
// No need to import separate icon CSS files
Expand Down
17 changes: 11 additions & 6 deletions app/javascript/components/components/CommentDedupBanner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
</button>
</b-alert>
<ul v-show="expanded" :id="listId" class="list-unstyled mb-0 pl-3">
<li v-for="row in rows" :key="row.id" class="mb-2">
<li
v-for="row in rows"
:key="row.id"
class="mb-2 rounded px-2 py-1"
:class="triageBgClass(row.triage_status)"
>
<div class="text-break">
<strong>{{ row.author_name }}</strong>
<SectionLabel v-if="row.section" :section="row.section" class="badge badge-light ml-1" />
Expand All @@ -27,7 +32,7 @@
:duplicate-of-id="row.duplicate_of_review_id"
class="ml-1"
/>
({{ relativeTime(row.created_at) }}) — &quot;{{ row.comment }}&quot;
({{ friendlyDateTime(row.created_at) }}) — &quot;{{ row.comment }}&quot;
</div>
<ReactionButtons
v-if="row.reactions"
Expand Down Expand Up @@ -55,11 +60,13 @@ import CommentThread from "../shared/CommentThread.vue";
import ReactionButtons from "../shared/ReactionButtons.vue";
import AlertMixin from "../../mixins/AlertMixin.vue";
import ReactionToggleMixin from "../../mixins/ReactionToggleMixin.vue";
import DateFormatMixin from "../../mixins/DateFormatMixin.vue";
import { triageBgClass } from "../../utils/triageBgClass";

export default {
name: "CommentDedupBanner",
components: { SectionLabel, TriageStatusBadge, CommentThread, ReactionButtons },
mixins: [AlertMixin, ReactionToggleMixin],
mixins: [AlertMixin, ReactionToggleMixin, DateFormatMixin],
props: {
componentId: { type: [Number, String], required: true },
ruleId: { type: [Number, String], default: null },
Expand Down Expand Up @@ -96,9 +103,7 @@ export default {
componentScoped: "fetch",
},
methods: {
relativeTime(iso) {
return iso ? new Date(iso).toLocaleDateString() : "";
},
triageBgClass,
async fetch() {
try {
// Fetch all comments at the current scope (rule-level or
Expand Down
Loading
Loading