Evidence Integration Adapter Specification
Version: 1.0.0
Status: Draft
Date: 2025-12-31
Context: shared/adapters
Satisfies: PRD-021, SDS-047, ADR-011
Purpose
This specification defines the adapter layer for integrating Giskard AI testing evidence with the GovernedSpeed™ Governance Runtime (SDS-047) and anchoring evidence hashes to the Internal Federated Ledger (IFL per ADR-011).
Architecture
sequenceDiagram
participant Giskard
participant EvidenceAdapter
participant SDS047 as SDS-047 Evidence Service
participant IFL as Internal Federated Ledger
participant OTLP as OpenTelemetry Collector
Giskard->>EvidenceAdapter: submit_test_results(fairness_report)
EvidenceAdapter->>EvidenceAdapter: compute_sha256(content)
EvidenceAdapter->>SDS047: SubmitEvidence(artifactType, content, hash)
SDS047->>SDS047: validate_hash(content, hash)
SDS047->>IFL: anchor_hash(artifactId, hash)
IFL-->>SDS047: anchor_receipt
SDS047->>OTLP: emit_metric(evidence.submitted)
SDS047-->>EvidenceAdapter: EvidenceSubmitted(artifactId, hash)
EvidenceAdapter-->>Giskard: submission_receipt
Components
1. GiskardEvidenceAdapter
Responsibility: Transforms Giskard test outputs into SDS-047 evidence artifacts
Interface:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| class GiskardEvidenceAdapter:
def submit_fairness_report(
self,
model_version: str,
test_suite: GiskardTestSuite,
results: GiskardTestResults
) -> EvidenceReceipt:
"""
Submits Giskard fairness test results as evidence.
Args:
model_version: Model version being tested
test_suite: Giskard test suite configuration
results: Test execution results
Returns:
EvidenceReceipt with artifact ID and hash
Raises:
HashValidationError: If computed hash doesn't match
SubmissionError: If SDS-047 submission fails
"""
pass
def submit_safety_report(
self,
model_version: str,
adversarial_tests: GiskardAdversarialResults
) -> EvidenceReceipt:
"""Submits adversarial/safety test results as evidence."""
pass
|
Mapping:
| Giskard Output |
Evidence Artifact Type |
Required Fields |
fairness_report.json |
fairness_report |
protected_attributes, subgroup_delta, disparate_impact_ratio |
adversarial_report.json |
safety_report |
attack_types, success_rate, mitigation |
data_quality_report.json |
evaluation |
completeness_score, accuracy_score, known_issues |
2. IFLAnchorAdapter
Responsibility: Anchors evidence hashes to Internal Federated Ledger for immutability
Interface:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| class IFLAnchorAdapter:
def anchor_evidence_hash(
self,
artifact_id: str,
evidence_hash: str,
timestamp: datetime
) -> AnchorReceipt:
"""
Anchors evidence hash to IFL.
Args:
artifact_id: UUID of evidence artifact
evidence_hash: SHA256 hash (64 hex chars)
timestamp: Submission timestamp
Returns:
AnchorReceipt with ledger transaction ID and merkle proof
Raises:
LedgerUnavailableError: If IFL is unreachable
InvalidHashError: If hash format is invalid
"""
pass
def verify_anchor(
self,
artifact_id: str,
evidence_hash: str
) -> AnchorVerification:
"""Verifies evidence hash exists in IFL and hasn't been tampered."""
pass
|
IFL Integration:
Per ADR-011, the IFL provides:
- Append-only ledger for tamper-evident storage
- Merkle tree for efficient verification
- Break-glass audit trail for high-stakes decisions
3. EvidenceSubmissionWorkflow
End-to-End Flow:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| # 1. Giskard executes tests
test_suite = GiskardTestSuite.from_yaml("fairness_tests.yaml")
results = test_suite.run(model)
# 2. Adapter transforms results
adapter = GiskardEvidenceAdapter(
sds047_client=Evidence ServiceClient("http://localhost:8080"),
ifl_client=IFLClient("http://localhost:5000")
)
# 3. Submit to SDS-047 with automatic hashing
receipt = adapter.submit_fairness_report(
model_version="customer-churn-v2.1.0",
test_suite=test_suite,
results=results
)
# Output:
# EvidenceReceipt(
# artifact_id="01932e5f-8c7a-7b6c-9d8e-0f1a2b3c4d5e",
# evidence_hash="a3f5d8c2e7b4f9a1c6d8e2f5a3b7c9d1e4f8a2b5c7d9e1f3a5b8c2d4e6f9a1c3",
# ifl_anchor_id="tx-2025123123456789",
# submitted_at="2025-12-31T12:34:56Z"
# )
|
Data Schemas
EvidenceReceipt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "EvidenceReceipt",
"type": "object",
"required": ["artifact_id", "evidence_hash", "ifl_anchor_id", "submitted_at"],
"properties": {
"artifact_id": {
"type": "string",
"format": "uuid",
"description": "UUID v7 of evidence artifact"
},
"evidence_hash": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA256 hash of artifact content"
},
"ifl_anchor_id": {
"type": "string",
"description": "IFL transaction ID for ledger anchor"
},
"submitted_at": {
"type": "string",
"format": "date-time"
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| {
"model_version": "customer-churn-v2.1.0",
"test_suite_id": "fairness-suite-v1",
"protected_attributes": ["gender", "race", "age"],
"subgroup_delta": 0.03,
"disparate_impact_ratio": 0.15,
"test_results": [
{
"test_name": "demographic_parity",
"passed": true,
"threshold": 0.05,
"actual": 0.03
}
],
"executed_at": "2025-12-31T12:00:00Z"
}
|
Error Handling
| Error |
Cause |
Recovery |
HashValidationError |
Computed hash ≠ SDS-047 hash |
Recompute and retry |
SubmissionError |
SDS-047 service unavailable |
Retry with exponential backoff |
LedgerUnavailableError |
IFL unreachable |
Queue for retry; proceed without anchor (logged) |
InvalidHashError |
Hash format incorrect |
Fix input data; don’t submit |
Idempotency:
Per SDS-047 SubmitEvidence command:
- Idempotency key:
sha256(content)
- On duplicate: Return existing artifact ID (no-op)
Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # config/evidence-integration.yaml
giskard:
api_url: "http://localhost:9000"
timeout_seconds: 30
sds047:
evidence_service_url: "http://localhost:8080"
retry_attempts: 3
retry_backoff_ms: [1000, 2000, 4000]
ifl:
ledger_url: "http://localhost:5000"
enable_anchoring: true # Set to false to disable IFL anchoring
anchor_timeout_seconds: 10
observability:
export_metrics: true
otlp_endpoint: "http://localhost:4317"
|
Testing Strategy
Unit Tests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| def test_giskard_adapter_fairness_report_submission():
# Mock Giskard results
results = GiskardTestResults(
protected_attributes=["gender"],
subgroup_delta=0.03
)
# Mock SDS-047 client
sds047_mock = Mock(spec=EvidenceServiceClient)
sds047_mock.submit_evidence.return_value = EvidenceReceipt(...)
# Test adapter
adapter = GiskardEvidenceAdapter(sds047_client=sds047_mock)
receipt = adapter.submit_fairness_report("v1.0", test_suite, results)
# Assertions
assert receipt.artifact_id is not None
assert len(receipt.evidence_hash) == 64
sds047_mock.submit_evidence.assert_called_once()
|
Integration Tests
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| def test_end_to_end_evidence_submission_with_ifl():
# Use Testcontainers for SDS-047 + IFL
with EvidenceServiceContainer() as sds047, IFLContainer() as ifl:
adapter = GiskardEvidenceAdapter(
sds047_client=EvidenceServiceClient(sds047.get_url()),
ifl_client=IFLClient(ifl.get_url())
)
# Submit real evidence
receipt = adapter.submit_fairness_report(...)
# Verify IFL anchor
verification = adapter.ifl_client.verify_anchor(
receipt.artifact_id,
receipt.evidence_hash
)
assert verification.is_valid
|
Deployment
Python Package
1
| pip install sea-evidence-adapters
|
Usage in Model Training Pipeline
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| from sea_evidence_adapters import GiskardEvidenceAdapter
# After model evaluation
adapter = GiskardEvidenceAdapter.from_config("evidence-integration.yaml")
# Submit fairness evidence
fairness_receipt = adapter.submit_fairness_report(
model_version=model.version,
test_suite=fairness_suite,
results=fairness_results
)
# Submit safety evidence
safety_receipt = adapter.submit_safety_report(
model_version=model.version,
adversarial_tests=safety_results
)
# Check compliance
if not fairness_receipt.artifact_id:
raise ComplianceError("Fairness evidence submission failed")
|
- SDS-047: GovernedSpeed™ Governance Runtime (SubmitEvidence command)
- ADR-011: Internal Federated Ledger (IFL architecture)
- ADR-028: GovernedSpeed™ LLMOps (evidence collection patterns)
- INV-GR-002: All Evidence SHA256 Hashed (invariant)
- REF-020: IAGPM-GenAI Framework (evidence artifacts)
- OSCAL ai-fairness-001: Fairness evidence requirement
- OSCAL eu-ai-art10: Data governance evidence
Revision History
| Version |
Date |
Changes |
| 1.0.0 |
2025-12-31 |
Initial specification |
References
- SDS-031: Authority and Ownership Boundaries
- SDS-050: Semantic Identity Provenance