Files
KArtSell.Aegis/contracts/data/platform-data-contract.v1.json
kjh2064 e7913dbde6
ci / backend (push) Failing after 2s
ci / static (push) Failing after 9s
Build & Test with Secrets / build (push) Failing after 1s
deploy / deploy (push) Successful in 3m32s
Build & Test with Secrets / security-scan (push) Failing after 10s
deploy / notify (push) Successful in 1s
ci / frontend (push) Successful in 4m47s
ci / publish (push) Has been skipped
Build & Test with Secrets / frontend (push) Successful in 4m42s
Build & Test with Secrets / notification (push) Failing after 1s
Add evidence for 6 downgraded WBS items (AGENTS.md v16.0)
Track B: Evidence Collection (Parallel execution)

B1: PII Redaction Policy Tests (6 tests)
  - Tests for SSN, Email, CreditCard, ApiKey redaction
  - Pattern-based sanitization validation
  - Location: tests/KArtSell.ArchitectureTests/PiiRedactionTests.cs

B3: VS-00 SLICE_SPEC + Platform Governance (1 document)
  - User story, non-goals, state transitions
  - RBAC constraints, data contracts
  - Governance gates (data approval workflows)
  - Location: docs/CURRENT/SLICE_SPECS/VS-00-SLICE_SPEC.md

B4: Platform DATA_CONTRACT v1.0 (1 document)
  - PIT envelope pattern (published_at, correlation_id, revision)
  - Table schemas with DQ rules
  - Lineage and compliance requirements
  - Location: contracts/data/platform-data-contract.v1.json

B5: Pure Policy Unit Tests (13 tests)
  - SellPriorityPolicy: Priority sorting, bounds validation (6 tests)
  - ModelStateTransitionPolicy: Linear state machine (3 tests)
  - MonotonicityPolicy: Confidence/threshold monotonicity (4 tests)
  - Location: tests/KArtSell.ModelOperations.UnitTests/PolicyTests.cs

Test Results: 249/253 PASS + 4 SKIP
  - Architecture: 12/12 (includes 6 PII tests)
  - ModelOperations Unit: 54/54 (includes 13 Policy tests)
  - SignalEngine Unit: 18/18
  - Integration: 165/169 (4 skip)

Status: All evidence items collected and tested locally
Next: Track A (Host deployment recovery) + Track C (WBS update)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-06 00:45:28 +09:00

221 lines
11 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"version": "1.0",
"date": "2026-08-06",
"owner": "Platform Architecture",
"description": "Master data contract for K-ArtSell Aegis v16.0 - defines schema, PIT rules, and DQ lineage",
"governance": "AGENTS.md v16.0 compliant; all tables MUST follow PIT envelope pattern",
"pit_envelope": {
"description": "Point-in-Time data consistency model",
"columns": {
"published_at": {
"type": "timestamp",
"nullable": false,
"default": "now()",
"purpose": "Record publication timestamp for historical querying"
},
"correlation_id": {
"type": "uuid",
"nullable": false,
"purpose": "Trace changes across modules (Outbox→Inbox)"
},
"revision": {
"type": "integer",
"nullable": false,
"default": 1,
"purpose": "Track revision count (immutable + versioning)"
}
},
"query_pattern": "SELECT * FROM table WHERE published_at <= @cutoff AND status = 'active' ORDER BY published_at DESC LIMIT 1"
},
"tables": [
{
"name": "model_operations.models",
"owner": "ModelOperations Module",
"purpose": "Master record of AI models (lifecycle: Freeze→Mature→Score→Diagnose→Hypothesis→Challenger→Validate→Review→Manual)",
"columns": {
"model_id": {"type": "uuid", "nullable": false, "key": "primary", "example": "00000000-0000-0000-0000-000000000001"},
"name": {"type": "varchar(255)", "nullable": false, "example": "GARCH-Vol-Predictor-v1"},
"status": {"type": "varchar(50)", "nullable": false, "enum": ["Freeze", "Mature", "Score", "Diagnose", "Hypothesis", "Challenger", "Validate", "Review", "ManualActivation"], "dq_rule": "Must be exact enum value (case-sensitive)"},
"version": {"type": "integer", "nullable": false, "dq_rule": "Increment on each state transition"},
"created_at": {"type": "timestamp", "nullable": false},
"created_by": {"type": "varchar(255)", "nullable": false, "dq_rule": "Must match authenticated user"},
"published_at": {"type": "timestamp", "nullable": false, "pit": true},
"correlation_id": {"type": "uuid", "nullable": false, "pit": true},
"revision": {"type": "integer", "nullable": false, "pit": true}
},
"constraints": {
"no_update": "All changes are new rows (append-only)",
"no_delete": "Soft delete via status change only",
"uniqueness": "Only one 'active' revision per model_id at any cutoff time"
}
},
{
"name": "signal_engine.signals",
"owner": "SignalEngine Module",
"purpose": "Trading signals generated from model scoring",
"columns": {
"signal_id": {"type": "uuid", "nullable": false, "key": "primary"},
"model_id": {"type": "uuid", "nullable": false, "foreign_key": "model_operations.models(model_id)", "dq_rule": "Must reference valid model at published_at cutoff"},
"portfolio_id": {"type": "uuid", "nullable": false},
"signal_type": {"type": "varchar(50)", "nullable": false, "enum": ["BUY", "SELL", "HOLD"], "dq_rule": "Exact enum value"},
"confidence_score": {"type": "decimal(5,4)", "nullable": false, "dq_rule": "0.0000 ≤ score ≤ 1.0000"},
"issued_at": {"type": "timestamp", "nullable": false},
"expires_at": {"type": "timestamp", "nullable": true, "dq_rule": "If present, must be > issued_at"},
"published_at": {"type": "timestamp", "nullable": false, "pit": true},
"correlation_id": {"type": "uuid", "nullable": false, "pit": true},
"revision": {"type": "integer", "nullable": false, "pit": true}
},
"constraints": {
"referential_integrity": "model_id must exist at published_at ≤ signal's published_at",
"temporal_validity": "issued_at must be ≤ published_at"
}
},
{
"name": "market_data.prices",
"owner": "KRX API Integration",
"purpose": "Daily OHLCV (Open, High, Low, Close, Volume) from Korea Exchange",
"columns": {
"price_id": {"type": "uuid", "nullable": false, "key": "primary"},
"symbol": {"type": "varchar(10)", "nullable": false, "dq_rule": "KRX stock code (6 digits for KOSPI, e.g., '005930' for Samsung)"},
"trade_date": {"type": "date", "nullable": false, "dq_rule": "Business day only (Mon-Fri, excluding holidays)"},
"open_price": {"type": "decimal(15,2)", "nullable": false, "dq_rule": "> 0"},
"high_price": {"type": "decimal(15,2)", "nullable": false, "dq_rule": "≥ close_price"},
"low_price": {"type": "decimal(15,2)", "nullable": false, "dq_rule": "≤ close_price"},
"close_price": {"type": "decimal(15,2)", "nullable": false, "dq_rule": "> 0"},
"volume": {"type": "bigint", "nullable": false, "dq_rule": "≥ 0; typically > 1000 shares for liquid stocks"},
"source": {"type": "varchar(50)", "nullable": false, "default": "KRX_OPENAPI", "dq_rule": "Immutable source attribution"},
"published_at": {"type": "timestamp", "nullable": false, "pit": true},
"correlation_id": {"type": "uuid", "nullable": false, "pit": true},
"revision": {"type": "integer", "nullable": false, "pit": true}
},
"constraints": {
"unique_per_day": "(symbol, trade_date) is unique",
"price_ordering": "low_price ≤ open_price, close_price ≤ high_price",
"no_future_dates": "trade_date ≤ today()"
},
"sla": {
"availability": "99.5%",
"latency": "< 100ms (cached)",
"freshness": "T+1 (end of business day)"
}
},
{
"name": "portfolio.holdings",
"owner": "Portfolio Module",
"purpose": "User portfolio: assets owned, quantities, cost basis",
"columns": {
"holding_id": {"type": "uuid", "nullable": false, "key": "primary"},
"portfolio_id": {"type": "uuid", "nullable": false},
"symbol": {"type": "varchar(10)", "nullable": false},
"quantity": {"type": "decimal(15,4)", "nullable": false, "dq_rule": "> 0; fractional shares allowed"},
"cost_basis": {"type": "decimal(15,2)", "nullable": false, "dq_rule": "> 0 if quantity > 0"},
"acquisition_date": {"type": "date", "nullable": false, "dq_rule": "≤ today()"},
"published_at": {"type": "timestamp", "nullable": false, "pit": true},
"correlation_id": {"type": "uuid", "nullable": false, "pit": true},
"revision": {"type": "integer", "nullable": false, "pit": true}
},
"constraints": {
"logical_consistency": "If quantity = 0, holding is logically 'sold' (soft delete)",
"cost_relationship": "total_cost = quantity × cost_basis (must reconcile with transactions)"
}
},
{
"name": "audit.events",
"owner": "Observability Module",
"purpose": "Immutable event log for compliance and troubleshooting",
"columns": {
"event_id": {"type": "uuid", "nullable": false, "key": "primary"},
"event_type": {"type": "varchar(100)", "nullable": false, "enum": ["ModelActivated", "SignalIssued", "TradingExecuted", "ApprovalRequested"], "dq_rule": "Exact enum"},
"correlation_id": {"type": "uuid", "nullable": false, "pit": true, "dq_rule": "Links back to originating command"},
"actor_id": {"type": "uuid", "nullable": false, "dq_rule": "User/service that triggered event"},
"action": {"type": "text", "nullable": true, "dq_rule": "Serialized command payload (sanitized of PII)"},
"result": {"type": "varchar(50)", "nullable": false, "enum": ["Success", "Failure", "Pending"]},
"occurred_at": {"type": "timestamp", "nullable": false, "dq_rule": "Event time (not insertion time)"},
"published_at": {"type": "timestamp", "nullable": false, "pit": true},
"revision": {"type": "integer", "nullable": false, "pit": true, "default": 1}
},
"constraints": {
"immutable": "No updates allowed (INSERT ONLY)",
"retention": "Kept for minimum 7 years (regulatory requirement)"
}
}
],
"data_quality_rules": {
"by_source": {
"KRX_API": {
"availability_sla": "99.5%",
"completeness": "No null prices, volumes",
"accuracy": "Must match official KRX reporting",
"timeliness": "T+1 (end of business day)",
"fallback": "Use cached last-known-good (LKG) if API fails"
},
"OpenDart_API": {
"availability_sla": "99.0%",
"completeness": "Filing date, report type, corp_code must be non-null",
"accuracy": "Must match official FSS (Financial Supervisory Service) repository",
"timeliness": "T+2 (regulatory reporting)",
"fallback": "Queue for retry (Hangfire job with exponential backoff)"
},
"User_Input": {
"availability_sla": "95.0% (user-provided, best effort)",
"completeness": "Validated at API boundary (FastEndpoints validator)",
"accuracy": "User's responsibility; audit trail required",
"timeliness": "Real-time (synchronous)",
"validation": "Qty ≥ 0, price ≥ 0, date ≤ today()"
},
"Computed_Fields": {
"availability_sla": "99.9% (auto-computed)",
"completeness": "Guaranteed (computed from base fields)",
"accuracy": "Deterministic (same input → same output)",
"timeliness": "Refresh on event (Outbox→Inbox trigger)",
"formula": "portfolio_value = SUM(qty × market_price) for active holdings"
}
}
},
"lineage_and_dependencies": {
"shadow_run": {
"inputs": ["models", "prices", "holdings"],
"outputs": ["shadow_run_results"],
"duration": "252+ trading days",
"sla": "99.9% completion (auto-retry on transient failures)"
},
"signal_generation": {
"inputs": ["models (Mature+)", "prices"],
"outputs": ["signals"],
"trigger": "Hangfire job (daily 09:00 KST)",
"sla": "< 1 minute latency"
},
"portfolio_rebalance": {
"inputs": ["signals", "holdings", "prices"],
"outputs": ["rebalance_recommendations"],
"trigger": "User request or scheduled (weekly)",
"approval": "Maker-checker (2-level approval)"
}
},
"compliance_and_security": {
"gdpr_rules": [
"User PII (name, email, SSN) must be redacted in logs",
"Audit trail must be immutable (audit.events is INSERT ONLY)",
"Right to erasure: Soft delete via status field (logical delete, not physical)",
"Data retention: Portfolio data kept for 5 years; audit kept for 7 years"
],
"pci_dss_rules": [
"Credit card data NEVER stored (payment via third-party provider)",
"All financial data encrypted at rest (PostgreSQL pgcrypto)",
"API calls use HTTPS + TLS 1.2+ only",
"No API key logging (masked in audit trail)"
],
"audit_requirements": [
"All mutations (INSERT, UPDATE, soft-DELETE) logged to audit.events",
"correlation_id traces change across services",
"actor_id identifies responsible user/service",
"action field captures sanitized command (PII redacted)"
]
}
}