80d1636107
Deliverables: - Enhanced source-catalog.md v2.0: KRX/OpenDart/KIS APIs with full SLA/retention/fallback - New source-approval.v1.json: JSON schema contract for data source governance - New AEG-X-009_SOURCE_CATALOG_CONSOLIDATION.md: Execution summary (45 min) Resolves VS-02 data governance unknowns: ✅ KRX listing/delisting source confirmed ✅ Import SLA documented (T+0, <4 hours) ✅ Audit/correction policy defined Enables parallel development: → VS-02-01: Data governance UNBLOCKED → VS-03-01/04-01: Design can proceed → Phase 2 implementation: No source unknowns AGENTS.md v16.0: 13/13 criteria ✅ Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
133 lines
5.8 KiB
JSON
133 lines
5.8 KiB
JSON
{
|
|
"$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" }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|