Merge pull request 'Workstream D: AEG-X-009 Source Catalog Consolidation' (#25) from feat/D-aeg-x009-source-catalog into main
Reviewed-on: #25
This commit was merged in pull request #25.
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Data Source Approval Contract",
|
||||
"description": "Master contract for external data source approval, SLA, and lineage",
|
||||
"version": "1.0",
|
||||
"type": "object",
|
||||
"required": ["sources", "metadata"],
|
||||
"properties": {
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"required": ["version", "owner", "approved_date", "approval_status"],
|
||||
"properties": {
|
||||
"version": { "type": "string", "example": "1.0" },
|
||||
"owner": { "type": "string", "example": "Data Governance Team" },
|
||||
"approved_date": { "type": "string", "format": "date", "example": "2026-08-07" },
|
||||
"approval_status": { "type": "string", "enum": ["APPROVED", "PENDING", "REJECTED"], "example": "APPROVED" },
|
||||
"last_updated": { "type": "string", "format": "date-time" }
|
||||
}
|
||||
},
|
||||
"sources": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["id", "name", "type", "url", "frequency", "sla"],
|
||||
"properties": {
|
||||
"id": { "type": "string", "description": "Unique source ID", "example": "krx-openapi-001" },
|
||||
"name": { "type": "string", "example": "KRX OpenAPI" },
|
||||
"type": { "type": "string", "enum": ["external_rest", "external_soap", "internal_form", "internal_db", "computed"], "example": "external_rest" },
|
||||
"url": { "type": "string", "format": "uri", "example": "https://openapi.krx.co.kr" },
|
||||
"authentication": {
|
||||
"type": "object",
|
||||
"required": ["method", "credential_key"],
|
||||
"properties": {
|
||||
"method": { "type": "string", "enum": ["api_key", "oauth2", "jwt", "basic_auth", "none"], "example": "api_key" },
|
||||
"credential_key": { "type": "string", "description": "Secret manager key", "example": "KRX_OPENAPI_KEY" },
|
||||
"rate_limit": { "type": "string", "example": "1000 req/day" }
|
||||
}
|
||||
},
|
||||
"frequency": {
|
||||
"type": "object",
|
||||
"required": ["schedule", "unit"],
|
||||
"properties": {
|
||||
"schedule": { "type": "string", "enum": ["real_time", "hourly", "daily", "weekly", "monthly", "on_demand"], "example": "daily" },
|
||||
"unit": { "type": "string", "example": "T+0 EOD" },
|
||||
"import_delay_sla": { "type": "string", "description": "Max acceptable delay", "example": "<4 hours" }
|
||||
}
|
||||
},
|
||||
"sla": {
|
||||
"type": "object",
|
||||
"required": ["availability", "support_hours"],
|
||||
"properties": {
|
||||
"availability": { "type": "string", "example": "99.5%" },
|
||||
"support_hours": { "type": "string", "example": "Weekdays 9 AM-5 PM KST" },
|
||||
"incident_contact": { "type": "string", "example": "support@krx.co.kr" },
|
||||
"escalation": { "type": "string", "example": "Operations Manager" }
|
||||
}
|
||||
},
|
||||
"retention": {
|
||||
"type": "object",
|
||||
"required": ["hot_storage", "cold_storage", "archive"],
|
||||
"properties": {
|
||||
"hot_storage": { "type": "integer", "description": "Days in primary DB", "example": 365 },
|
||||
"cold_storage": { "type": "integer", "description": "Days before archival", "example": 730 },
|
||||
"archive": { "type": "integer", "description": "Total retention years", "example": 5 }
|
||||
}
|
||||
},
|
||||
"fallback_strategy": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["priority", "source", "description"],
|
||||
"properties": {
|
||||
"priority": { "type": "integer", "minimum": 1, "example": 1 },
|
||||
"source": { "type": "string", "enum": ["live_api", "cache", "snapshot", "manual"], "example": "live_api" },
|
||||
"description": { "type": "string", "example": "Live API call to KRX endpoint" },
|
||||
"max_age": { "type": "string", "description": "Max acceptable data age", "example": "1 trading day" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"data_quality_rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"rule_name": { "type": "string", "example": "no_null_prices" },
|
||||
"condition": { "type": "string", "example": "volume >= 0 AND high >= low" },
|
||||
"severity": { "type": "string", "enum": ["critical", "warning", "info"], "example": "critical" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"consumers": {
|
||||
"type": "array",
|
||||
"items": { "type": "string", "example": "signal_engine" }
|
||||
},
|
||||
"owner": { "type": "string", "example": "KRX" },
|
||||
"approved_by": { "type": "string", "example": "Data Governance Lead" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"error_classification": {
|
||||
"type": "object",
|
||||
"description": "Retry and fallback rules for different error types",
|
||||
"properties": {
|
||||
"transient": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error_code": { "type": "string", "example": "429" },
|
||||
"description": { "type": "string", "example": "Rate limit exceeded" },
|
||||
"retry_delay_ms": { "type": "integer", "example": 60000 },
|
||||
"max_attempts": { "type": "integer", "example": 3 }
|
||||
}
|
||||
}
|
||||
},
|
||||
"permanent": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error_code": { "type": "string", "example": "400" },
|
||||
"description": { "type": "string", "example": "Bad request" },
|
||||
"action": { "type": "string", "enum": ["alert", "quarantine", "manual_review"], "example": "alert" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user