feat(dsms): Stufe 2+3 — Evidence/TechFile → DSMS + Version Chains + Audit Timeline
Build + Deploy / build-admin-compliance (push) Successful in 1m58s
Build + Deploy / build-backend-compliance (push) Successful in 12s
Build + Deploy / build-ai-sdk (push) Successful in 11s
Build + Deploy / build-developer-portal (push) Successful in 11s
Build + Deploy / build-tts (push) Successful in 21s
Build + Deploy / build-document-crawler (push) Successful in 11s
Build + Deploy / build-dsms-gateway (push) Successful in 14s
Build + Deploy / build-dsms-node (push) Successful in 14s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 15s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 2m40s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Successful in 40s
CI / test-python-backend (push) Successful in 37s
CI / test-python-document-crawler (push) Successful in 26s
CI / test-python-dsms-gateway (push) Successful in 22s
CI / validate-canonical-controls (push) Successful in 14s
Build + Deploy / trigger-orca (push) Successful in 2m26s
Build + Deploy / build-admin-compliance (push) Successful in 1m58s
Build + Deploy / build-backend-compliance (push) Successful in 12s
Build + Deploy / build-ai-sdk (push) Successful in 11s
Build + Deploy / build-developer-portal (push) Successful in 11s
Build + Deploy / build-tts (push) Successful in 21s
Build + Deploy / build-document-crawler (push) Successful in 11s
Build + Deploy / build-dsms-gateway (push) Successful in 14s
Build + Deploy / build-dsms-node (push) Successful in 14s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 15s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 2m40s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Successful in 40s
CI / test-python-backend (push) Successful in 37s
CI / test-python-document-crawler (push) Successful in 26s
CI / test-python-dsms-gateway (push) Successful in 22s
CI / validate-canonical-controls (push) Successful in 14s
Build + Deploy / trigger-orca (push) Successful in 2m26s
Stufe 2A: Evidence Upload → automatische DSMS-Archivierung
- Nach SHA-256 Hash → archive_to_dsms(), CID im Audit-Trail
- Evidence mit CID wird automatisch zu E2 (hash-verifiziert) hochgestuft
Stufe 2B: IACE Tech-File Export → DSMS
- PDF/Excel/DOCX/Markdown Exporte werden nach DSMS archiviert
- archiveTechFile() Helper fuer alle 4 Formate
Stufe 3A: DSMS Gateway — parent_cid + History Endpoint
- parent_cid + tenant_id Felder in DocumentMetadata
- GET /documents/{cid}/history — folgt parent_cid-Chain (max 50 deep)
Stufe 3C: Audit Timeline UI
- Neue Seite /sdk/audit-timeline
- Vertikale Timeline mit farbigen Action-Dots
- Filter: Alle, Nachweis, DSMS-Archiv, Control, Dokument, DSFA, VVT, TOM
- CID-Badges fuer DSMS-archivierte Eintraege
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -248,7 +248,10 @@ async def create_evidence(
|
||||
)
|
||||
db.commit()
|
||||
|
||||
return _build_evidence_response(evidence)
|
||||
resp = _build_evidence_response(evidence)
|
||||
if dsms_cid:
|
||||
resp["dsms_cid"] = dsms_cid
|
||||
return resp
|
||||
|
||||
|
||||
@router.delete("/evidence/{evidence_id}")
|
||||
@@ -313,6 +316,25 @@ async def upload_evidence(
|
||||
evidence.confidence_level = EvidenceConfidenceEnum.E1
|
||||
evidence.truth_status = EvidenceTruthStatusEnum.UPLOADED
|
||||
|
||||
# Archive to DSMS (best-effort, non-blocking)
|
||||
dsms_cid = None
|
||||
try:
|
||||
from compliance.services.dsms_client import archive_to_dsms
|
||||
dsms_result = await archive_to_dsms(
|
||||
content=content, filename=file.filename,
|
||||
document_type="evidence", document_id=str(evidence.id),
|
||||
version="1", tenant_id=control_id,
|
||||
)
|
||||
dsms_cid = dsms_result.get("cid")
|
||||
if dsms_cid:
|
||||
evidence.confidence_level = EvidenceConfidenceEnum.E2
|
||||
from compliance.api.audit_trail_utils import log_audit_trail
|
||||
log_audit_trail(db, "evidence", str(evidence.id), title, "archive",
|
||||
"system", field_changed="dsms_cid", new_value=dsms_cid,
|
||||
change_summary=f"Evidence archived to DSMS: {dsms_cid}")
|
||||
except Exception:
|
||||
pass # DSMS unavailable
|
||||
|
||||
# Four-Eyes: check if the linked control's domain requires it
|
||||
control_domain = control.domain.value if control.domain else ""
|
||||
if _requires_four_eyes(control_domain):
|
||||
@@ -321,7 +343,10 @@ async def upload_evidence(
|
||||
|
||||
db.commit()
|
||||
|
||||
return _build_evidence_response(evidence)
|
||||
resp = _build_evidence_response(evidence)
|
||||
if dsms_cid:
|
||||
resp["dsms_cid"] = dsms_cid
|
||||
return resp
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -813,7 +838,10 @@ async def review_evidence(
|
||||
db.commit()
|
||||
|
||||
db.refresh(evidence)
|
||||
return _build_evidence_response(evidence)
|
||||
resp = _build_evidence_response(evidence)
|
||||
if dsms_cid:
|
||||
resp["dsms_cid"] = dsms_cid
|
||||
return resp
|
||||
|
||||
|
||||
@router.patch("/evidence/{evidence_id}/reject", response_model=EvidenceResponse)
|
||||
@@ -840,7 +868,10 @@ async def reject_evidence(
|
||||
db.commit()
|
||||
|
||||
db.refresh(evidence)
|
||||
return _build_evidence_response(evidence)
|
||||
resp = _build_evidence_response(evidence)
|
||||
if dsms_cid:
|
||||
resp["dsms_cid"] = dsms_cid
|
||||
return resp
|
||||
|
||||
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user