feat(control-library): document-grouped batching, generation strategy tracking, sort by source
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 31s
CI/CD / test-python-backend-compliance (push) Successful in 31s
CI/CD / test-python-document-crawler (push) Successful in 21s
CI/CD / test-python-dsms-gateway (push) Successful in 18s
CI/CD / validate-canonical-controls (push) Successful in 11s
CI/CD / Deploy (push) Successful in 2s

- Group chunks by regulation_code before batching for better LLM context
- Add generation_strategy column (ungrouped=v1, document_grouped=v2)
- Add v1/v2 badge to control cards in frontend
- Add sort-by-source option with visual group headers
- Add frontend page tests (18 tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-15 15:10:52 +01:00
parent 0d95c3bb44
commit c8fd9cc780
9 changed files with 1000 additions and 137 deletions

View File

@@ -25,22 +25,35 @@ export async function GET(request: NextRequest) {
break
case 'controls': {
const severity = searchParams.get('severity')
const domain = searchParams.get('domain')
const verificationMethod = searchParams.get('verification_method')
const categoryFilter = searchParams.get('category')
const targetAudience = searchParams.get('target_audience')
const params = new URLSearchParams()
if (severity) params.set('severity', severity)
if (domain) params.set('domain', domain)
if (verificationMethod) params.set('verification_method', verificationMethod)
if (categoryFilter) params.set('category', categoryFilter)
if (targetAudience) params.set('target_audience', targetAudience)
const qs = params.toString()
const controlParams = new URLSearchParams()
const passthrough = ['severity', 'domain', 'verification_method', 'category',
'target_audience', 'source', 'search', 'sort', 'order', 'limit', 'offset']
for (const key of passthrough) {
const val = searchParams.get(key)
if (val) controlParams.set(key, val)
}
const qs = controlParams.toString()
backendPath = `/api/compliance/v1/canonical/controls${qs ? `?${qs}` : ''}`
break
}
case 'controls-count': {
const countParams = new URLSearchParams()
const countPassthrough = ['severity', 'domain', 'verification_method', 'category',
'target_audience', 'source', 'search']
for (const key of countPassthrough) {
const val = searchParams.get(key)
if (val) countParams.set(key, val)
}
const countQs = countParams.toString()
backendPath = `/api/compliance/v1/canonical/controls-count${countQs ? `?${countQs}` : ''}`
break
}
case 'controls-meta':
backendPath = '/api/compliance/v1/canonical/controls-meta'
break
case 'control': {
const controlId = searchParams.get('id')
if (!controlId) {