fix(mc-browser): scope fallback + severity/domain filters
- Add scope/risk_score/implementation_effort fallbacks to prevent 'undefined is not an object' crash in ControlDetail - Add severity filter (high/medium/low based on total_controls) - Add domain filter (L1 token prefix match) - Fix sort options (source → canonical_name) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -60,8 +60,23 @@ async function handleControls(params: URLSearchParams) {
|
|||||||
idx++
|
idx++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const severity = params.get('severity') || ''
|
||||||
|
if (severity) {
|
||||||
|
if (severity === 'high') { where += ` AND mc.total_controls > 100` }
|
||||||
|
else if (severity === 'medium') { where += ` AND mc.total_controls BETWEEN 20 AND 100` }
|
||||||
|
else if (severity === 'low') { where += ` AND mc.total_controls < 20` }
|
||||||
|
}
|
||||||
|
|
||||||
|
const domain = params.get('domain') || ''
|
||||||
|
if (domain) {
|
||||||
|
where += ` AND mc.canonical_name LIKE $${idx}`
|
||||||
|
args.push(`${domain}%`)
|
||||||
|
idx++
|
||||||
|
}
|
||||||
|
|
||||||
const sortCol = sort === 'control_id' ? 'mc.master_control_id' :
|
const sortCol = sort === 'control_id' ? 'mc.master_control_id' :
|
||||||
sort === 'created_at' ? 'mc.created_at' : 'mc.master_control_id'
|
sort === 'created_at' ? 'mc.created_at' :
|
||||||
|
sort === 'source' ? 'mc.canonical_name' : 'mc.master_control_id'
|
||||||
|
|
||||||
args.push(limit, offset)
|
args.push(limit, offset)
|
||||||
const res = await pool.query(`
|
const res = await pool.query(`
|
||||||
@@ -102,6 +117,9 @@ async function handleControls(params: URLSearchParams) {
|
|||||||
total_controls: r.total_controls,
|
total_controls: r.total_controls,
|
||||||
phases_covered: r.phases_covered,
|
phases_covered: r.phases_covered,
|
||||||
created_at: r.created_at,
|
created_at: r.created_at,
|
||||||
|
scope: { platforms: [], components: [], data_classes: [] },
|
||||||
|
risk_score: null,
|
||||||
|
implementation_effort: null,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return NextResponse.json(controls)
|
return NextResponse.json(controls)
|
||||||
@@ -203,6 +221,9 @@ async function handleDetail(params: URLSearchParams) {
|
|||||||
open_anchors: [],
|
open_anchors: [],
|
||||||
target_audience: [],
|
target_audience: [],
|
||||||
source_citation: null,
|
source_citation: null,
|
||||||
|
scope: { platforms: [], components: [], data_classes: [] },
|
||||||
|
risk_score: null,
|
||||||
|
implementation_effort: null,
|
||||||
created_at: mc.created_at,
|
created_at: mc.created_at,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,11 +35,22 @@ export default function MasterControlsPage() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DETAIL mode
|
// DETAIL mode — add fallback fields that ControlDetail expects
|
||||||
if (state.mode === 'detail' && state.selectedControl) {
|
if (state.mode === 'detail' && state.selectedControl) {
|
||||||
|
const safeCtrl = {
|
||||||
|
...state.selectedControl,
|
||||||
|
scope: state.selectedControl.scope || { platforms: [], components: [], data_classes: [] },
|
||||||
|
target_audience: state.selectedControl.target_audience || [],
|
||||||
|
requirements: state.selectedControl.requirements || [],
|
||||||
|
test_procedure: state.selectedControl.test_procedure || [],
|
||||||
|
evidence: state.selectedControl.evidence || [],
|
||||||
|
open_anchors: state.selectedControl.open_anchors || [],
|
||||||
|
risk_score: state.selectedControl.risk_score || null,
|
||||||
|
implementation_effort: state.selectedControl.implementation_effort || null,
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<ControlDetail
|
<ControlDetail
|
||||||
ctrl={state.selectedControl}
|
ctrl={safeCtrl}
|
||||||
onBack={() => { state.setMode('list'); state.setSelectedControl(null) }}
|
onBack={() => { state.setMode('list'); state.setSelectedControl(null) }}
|
||||||
onEdit={() => {}}
|
onEdit={() => {}}
|
||||||
onDelete={async () => {}}
|
onDelete={async () => {}}
|
||||||
|
|||||||
Reference in New Issue
Block a user