fix(cra): IACE-Create id-Wrapper + MaschinenVO eigene Sektion
CI / nodejs-build (push) Successful in 3m10s
CI / secret-scan (push) Has been skipped
CI / test-go (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / detect-changes (push) Successful in 16s
CI / branch-name (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / build-sha-integrity (push) Successful in 12s
CI / test-python-backend (push) Successful in 32s
CI / validate-canonical-controls (push) Successful in 11s
CI / loc-budget (push) Successful in 24s
CI / go-lint (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 3m10s
CI / secret-scan (push) Has been skipped
CI / test-go (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / detect-changes (push) Successful in 16s
CI / branch-name (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / build-sha-integrity (push) Successful in 12s
CI / test-python-backend (push) Successful in 32s
CI / validate-canonical-controls (push) Successful in 11s
CI / loc-budget (push) Successful in 24s
CI / go-lint (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
1) createProject las proj.id, der Create-Response ist aber {project:{id}} →
'Projekt anlegen' war kaputt. Jetzt proj.project?.id. E2E verifiziert
(create→put limits_form→get→delete = 200).
2) MaschinenVO-Sicherheitspflichten wurden in die CRA-Cyber-Buckets
(Code/Prozess/Doku) gemischt → fehl-kategorisiert (Maschinen-Safety ≠
CRA-Annex-I-Cyber). Jetzt eigene Response-Liste machinery_guideline +
eigener Frontend-Abschnitt 'Maschinensicherheit (MaschinenVO 2023/1230)';
geklebtes 'MaschVO'-Badge entfaellt damit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -70,7 +70,7 @@ export function DatasheetExtract() {
|
|||||||
})
|
})
|
||||||
if (!cr.ok) return
|
if (!cr.ok) return
|
||||||
const proj = await cr.json()
|
const proj = await cr.json()
|
||||||
const pid = proj.id || proj.project_id
|
const pid = proj.project?.id || proj.id || proj.project_id
|
||||||
if (!pid) return
|
if (!pid) return
|
||||||
await fetch(`/api/sdk/v1/iace/projects/${pid}`, {
|
await fetch(`/api/sdk/v1/iace/projects/${pid}`, {
|
||||||
method: 'PUT', headers: { 'Content-Type': 'application/json' },
|
method: 'PUT', headers: { 'Content-Type': 'application/json' },
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export interface ReadinessResult {
|
|||||||
conformity_path_hint: string
|
conformity_path_hint: string
|
||||||
regulations: string[]
|
regulations: string[]
|
||||||
guideline: { code: GuidelineItem[]; process: GuidelineItem[]; document: GuidelineItem[] }
|
guideline: { code: GuidelineItem[]; process: GuidelineItem[]; document: GuidelineItem[] }
|
||||||
|
machinery_guideline?: GuidelineItem[]
|
||||||
counts: { code: number; process: number; document: number }
|
counts: { code: number; process: number; document: number }
|
||||||
total_effort_days: number
|
total_effort_days: number
|
||||||
deadlines: { date: string; label: string }[]
|
deadlines: { date: string; label: string }[]
|
||||||
@@ -172,9 +173,6 @@ export function ReadinessResultView({ result, onCreateProject }: { result: Readi
|
|||||||
<ul className="mt-2 space-y-1.5">
|
<ul className="mt-2 space-y-1.5">
|
||||||
{result.guideline[b.key].map((it) => (
|
{result.guideline[b.key].map((it) => (
|
||||||
<li key={it.req_id} className="text-[11px] text-gray-600 dark:text-gray-300">
|
<li key={it.req_id} className="text-[11px] text-gray-600 dark:text-gray-300">
|
||||||
{it.source === 'Maschinen-VO' && (
|
|
||||||
<span className="inline-block rounded bg-indigo-100 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300 px-1 py-0.5 text-[9px] font-medium mr-1">MaschVO</span>
|
|
||||||
)}
|
|
||||||
<span className="font-medium text-gray-800 dark:text-gray-200">{it.title}</span>
|
<span className="font-medium text-gray-800 dark:text-gray-200">{it.title}</span>
|
||||||
<span className="text-gray-400"> · {it.annex_anchor}</span>
|
<span className="text-gray-400"> · {it.annex_anchor}</span>
|
||||||
</li>
|
</li>
|
||||||
@@ -183,6 +181,25 @@ export function ReadinessResultView({ result, onCreateProject }: { result: Readi
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
{result.machinery_guideline && result.machinery_guideline.length > 0 && (
|
||||||
|
<div className="rounded-lg border border-indigo-200 dark:border-indigo-800 bg-indigo-50/40 dark:bg-indigo-900/10 p-3">
|
||||||
|
<h3 className="text-sm font-semibold text-indigo-900 dark:text-indigo-200">
|
||||||
|
Maschinensicherheit — Maschinenverordnung (EU) 2023/1230
|
||||||
|
</h3>
|
||||||
|
<p className="text-[11px] text-indigo-800/70 dark:text-indigo-300/70 mb-1">
|
||||||
|
Eigene Pflichten zur Personensicherheit — getrennt von den CRA-Cyber-Anforderungen.
|
||||||
|
</p>
|
||||||
|
<ul className="space-y-1">
|
||||||
|
{result.machinery_guideline.map((it) => (
|
||||||
|
<li key={it.req_id} className="text-[11px] text-gray-700 dark:text-gray-200">
|
||||||
|
<span className="font-medium">{it.title}</span>
|
||||||
|
<span className="text-gray-400"> · {it.annex_anchor}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-3 text-[11px] text-gray-500">
|
<div className="flex flex-wrap gap-3 text-[11px] text-gray-500">
|
||||||
<span className="font-medium text-gray-600 dark:text-gray-300">CRA-Fristen:</span>
|
<span className="font-medium text-gray-600 dark:text-gray-300">CRA-Fristen:</span>
|
||||||
{result.deadlines.map((d) => (
|
{result.deadlines.map((d) => (
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ async def readiness(body: ReadinessRequest):
|
|||||||
classification, rationale = _classify(intake)
|
classification, rationale = _classify(intake)
|
||||||
in_scope = classification != "NOT_IN_SCOPE"
|
in_scope = classification != "NOT_IN_SCOPE"
|
||||||
groups = {"code": [], "process": [], "document": []}
|
groups = {"code": [], "process": [], "document": []}
|
||||||
|
machinery_guideline = []
|
||||||
regulations = []
|
regulations = []
|
||||||
if in_scope:
|
if in_scope:
|
||||||
regulations.append("CRA")
|
regulations.append("CRA")
|
||||||
@@ -286,14 +287,14 @@ async def readiness(body: ReadinessRequest):
|
|||||||
"measures": [{"id": m, "name": MEASURES.get(m, m)} for m in req.get("mapped_measures", [])],
|
"measures": [{"id": m, "name": MEASURES.get(m, m)} for m in req.get("mapped_measures", [])],
|
||||||
"source": "CRA",
|
"source": "CRA",
|
||||||
})
|
})
|
||||||
# Machine/plant builders are ALSO hit by the new Machinery Regulation's
|
# Machinery-Regulation safety obligations are NOT CRA Annex-I cyber controls
|
||||||
# cyber-with-safety essential requirements (Annex III) — show the combination.
|
# — keep them in their OWN section, not mixed into the Code/Process/Document
|
||||||
|
# cyber buckets (machine safety != cybersecurity).
|
||||||
if body.is_machinery or machine_integrator:
|
if body.is_machinery or machine_integrator:
|
||||||
machinery = _machinery_obligations()
|
machinery = _machinery_obligations()
|
||||||
if machinery:
|
if machinery:
|
||||||
regulations.append("Maschinen-VO 2023/1230")
|
regulations.append("Maschinen-VO 2023/1230")
|
||||||
for bucket, item in machinery:
|
machinery_guideline = [item for _bucket, item in machinery]
|
||||||
groups[bucket].append(item)
|
|
||||||
total_effort = sum(r["effort_days"] for g in groups.values() for r in g if r.get("effort_days"))
|
total_effort = sum(r["effort_days"] for g in groups.values() for r in g if r.get("effort_days"))
|
||||||
verdict = compute_verdict(
|
verdict = compute_verdict(
|
||||||
classification, body.placed_on_market_after_2027,
|
classification, body.placed_on_market_after_2027,
|
||||||
@@ -306,6 +307,7 @@ async def readiness(body: ReadinessRequest):
|
|||||||
"conformity_path_hint": _PATH_HINT.get(classification, ""),
|
"conformity_path_hint": _PATH_HINT.get(classification, ""),
|
||||||
"regulations": regulations,
|
"regulations": regulations,
|
||||||
"guideline": groups,
|
"guideline": groups,
|
||||||
|
"machinery_guideline": machinery_guideline,
|
||||||
"counts": {k: len(v) for k, v in groups.items()},
|
"counts": {k: len(v) for k, v in groups.items()},
|
||||||
"total_effort_days": total_effort,
|
"total_effort_days": total_effort,
|
||||||
"deadlines": list(DEADLINES),
|
"deadlines": list(DEADLINES),
|
||||||
|
|||||||
Reference in New Issue
Block a user