docs(architecture): add VS-01/VS-02 slice specs, register VS-02 tech debt
- VS-01-SLICE_SPEC.md: Identity/MFA/RBAC/maker-checker contract (draft, ready for security review)
* Roles: GUEST/USER/OPERATOR/ADMIN/SUPER_ADMIN
* MFA tiers: NO_MFA → TOTP_REQUIRED → HARDWARE_KEY
* Maker-checker approval workflow for role elevation
* Schema: users/roles/user_roles/role_approval_requests/mfa_devices/permissions (PIT-tracked)
* Prerequisite AEG-X-001/AEG-VS-00-02 already COMPLETED → can proceed immediately
- VS-02-SLICE_SPEC.md: Financial security master (listing/delisting/product structure) [DRAFT]
* Correct domain: Financial PIT data, NOT access-control rules
* Existing VS-02 code (RBAC rule sync) is mislabeled → registered as tech debt
* Schema stub: securities/trading_restrictions (PIT-tracked)
* CRITICAL: Source Unknown — awaiting data governance approval of:
(1) KRX data source endpoint (not in source-catalog.md)
(2) Import SLA (daily? intraday?)
(3) Audit/corrections policy
* Status: DRAFT (cannot proceed without unknowns resolved)
- TECH_DEBT_REGISTER.md: Added DEBT-016 (VS-02 mislabeled)
* Impact: Medium (design confusion), Effort: Low (doc) → Medium (code removal)
* Endpoints disabled (DISABLED comment), schema never migrated, never deployed
* Dead code marked for removal decision (separate PR recommended)
- WBS_PROGRESS_TRACKER.csv: Updated status
* AEG-VS-01-01: PLANNED → IN_PROGRESS (SLICE_SPEC ready)
* AEG-VS-02-01: PLANNED → DRAFT (unknowns documented, data gov approval needed)
AGENTS.md: Maturity (contract before code), Necessity (fix only real issues — domain confusion + unknowns)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,7 @@
|
|||||||
|----|----------|--------|--------|--------|-------|-------|-----|
|
|----|----------|--------|--------|--------|-------|-------|-----|
|
||||||
| DEBT-007 | Newtonsoft.Json override | Medium (2) | Medium (2) | Completed | Fixed in 88ea5ed: CA1848/CA1859 actual implementation. LoggerMessage + HashSet/Dictionary. | @claude | - |
|
| DEBT-007 | Newtonsoft.Json override | Medium (2) | Medium (2) | Completed | Fixed in 88ea5ed: CA1848/CA1859 actual implementation. LoggerMessage + HashSet/Dictionary. | @claude | - |
|
||||||
| DEBT-008 | Namespace consistency | Medium (2) | Low (1) | Accepted | All projects use RootNamespace=KArtSell.Aegis; AssemblyName retained per-project for DLL clarity. Trade-off accepted: DLL clarity > namespace alignment. No action. | @claude | PR 4d |
|
| DEBT-008 | Namespace consistency | Medium (2) | Low (1) | Accepted | All projects use RootNamespace=KArtSell.Aegis; AssemblyName retained per-project for DLL clarity. Trade-off accepted: DLL clarity > namespace alignment. No action. | @claude | PR 4d |
|
||||||
|
| DEBT-016 | VS-02 mislabeled domain | Medium (2) | Low (1) | Backlog | Existing code `VS02_SyncSecurityMasterEndpoint.cs`, `VS02_SecurityMasterJobs.cs`, `VS02_SecurityMasterPolicy.cs` implement RBAC rule synchronization (access control), not financial security master data (listing/delisting/product structure). Dead code: endpoints disabled (DISABLED comment), schema `security_master.rules` table never migrated, never deployed. Correct domain documented in `docs/CURRENT/SLICE_SPECS/VS-02-SLICE_SPEC.md` (financial PIT). Removal decision deferred pending architect review (PR recommended). | @claude | docs/CURRENT/SLICE_SPECS/VS-02-SLICE_SPEC.md |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ AEG-VS-00-05,S0,VS-00,Event/Job/Inbox·재처리 구현,COMPLETED,2026-08-04,"do
|
|||||||
AEG-VS-00-06,S0,VS-00,Vue feature·Zod·Query·컴포넌트 구현,COMPLETED,2026-08-04,"docs/CURRENT/ARTIFACTS/AEG-VS-00-06_ACCEPTANCE_EVIDENCE.md + frontend/src/features/shadow-run/",FE Lead,"✅ Vue 3 feature module complete: ShadowRunPage + ShadowRunForm + Results + Chart, Pinia store, TanStack Query, Zod validation, vee-validate, 40/40 component tests PASS. Acceptance_Evidence: All criteria verified (accessibility, responsive, state ownership, error handling)."
|
AEG-VS-00-06,S0,VS-00,Vue feature·Zod·Query·컴포넌트 구현,COMPLETED,2026-08-04,"docs/CURRENT/ARTIFACTS/AEG-VS-00-06_ACCEPTANCE_EVIDENCE.md + frontend/src/features/shadow-run/",FE Lead,"✅ Vue 3 feature module complete: ShadowRunPage + ShadowRunForm + Results + Chart, Pinia store, TanStack Query, Zod validation, vee-validate, 40/40 component tests PASS. Acceptance_Evidence: All criteria verified (accessibility, responsive, state ownership, error handling)."
|
||||||
AEG-VS-00-07,S0,VS-00,회귀·관제·Runbook·Rollback 증거,COMPLETED,2026-08-04,docs/operational-runbook.md + PRODUCTION_READINESS.md + scripts/*.ps1 + commit ca2aeae,QA/SRE,"Golden/integration/failure/replay/E2E + metric/alert/Owner/Secondary/rollback rehearsal complete (Acceptance_Evidence: '회귀·관제·Runbook·Rollback 증거') - 7 scenarios, 4 scripts, 18 queries verified"
|
AEG-VS-00-07,S0,VS-00,회귀·관제·Runbook·Rollback 증거,COMPLETED,2026-08-04,docs/operational-runbook.md + PRODUCTION_READINESS.md + scripts/*.ps1 + commit ca2aeae,QA/SRE,"Golden/integration/failure/replay/E2E + metric/alert/Owner/Secondary/rollback rehearsal complete (Acceptance_Evidence: '회귀·관제·Runbook·Rollback 증거') - 7 scenarios, 4 scripts, 18 queries verified"
|
||||||
AEG-X-009,S1,Cross,Source catalog 고도화,PLANNED,-,-,Data Governance,"Deferred to Phase 2 (after Gate 1 completion)"
|
AEG-X-009,S1,Cross,Source catalog 고도화,PLANNED,-,-,Data Governance,"Deferred to Phase 2 (after Gate 1 completion)"
|
||||||
AEG-VS-01-01,S1,VS-01,정책·범위·실패상태 계약 확정,PLANNED,-,-,PM/Architect,"Blocked: Depends on AEG-X-001. Future sprint."
|
AEG-VS-01-01,S1,VS-01,정책·범위·실패상태 계약 확정,IN_PROGRESS,2026-08-07,docs/CURRENT/SLICE_SPECS/VS-01-SLICE_SPEC.md,PM/Architect,"✅ SLICE_SPEC produced: VS-01-SLICE_SPEC.md (identity/MFA/RBAC/maker-checker contract). Prerequisite AEG-X-001 + AEG-VS-00-02 already COMPLETED. Ready for security team review and schema implementation."
|
||||||
AEG-VS-02-01,S1,VS-02,정책·범위·실패상태 계약 확정,PLANNED,-,-,PM/Architect,"Blocked: Depends on AEG-VS-00-02. Future sprint."
|
AEG-VS-02-01,S1,VS-02,정책·범위·실패상태 계약 확정,DRAFT,2026-08-07,docs/CURRENT/SLICE_SPECS/VS-02-SLICE_SPEC.md,PM/Architect,"⚠️ DRAFT (Source Unknown): Existing VS-02 code implements RBAC rule sync (wrong domain), registered as DEBT-016. Correct domain (financial security master: listing/delisting/product structure) documented in VS-02-SLICE_SPEC.md stub with Source/Assumption/Unknown. Blockers: (1) KRX data source not in source-catalog.md, (2) import SLA not confirmed, (3) audit/correction policy undefined. Awaiting data governance approval of unknowns before schema implementation."
|
||||||
AEG-VS-03-01,S2,VS-03,정책·범위·실패상태 계약 확정,PLANNED,-,-,PM/Architect,"Blocked: Depends on AEG-VS-02-01. Future sprint."
|
AEG-VS-03-01,S2,VS-03,정책·범위·실패상태 계약 확정,PLANNED,-,-,PM/Architect,"Blocked: Depends on AEG-VS-02-01. Future sprint."
|
||||||
AEG-VS-04-01,S2,VS-04,정책·범위·실패상태 계약 확정,PLANNED,-,-,PM/Architect,"Blocked: Depends on AEG-VS-03-01. Future sprint."
|
AEG-VS-04-01,S2,VS-04,정책·범위·실패상태 계약 확정,PLANNED,-,-,PM/Architect,"Blocked: Depends on AEG-VS-03-01. Future sprint."
|
||||||
AEG-VS-05-01,S3,VS-05,정책·범위·실패상태 계약 확정,PLANNED,-,-,PM/Architect,"Blocked: Depends on Gate 1 (Phase 1). Waiting for Job 976 (~50-90 days)."
|
AEG-VS-05-01,S3,VS-05,정책·범위·실패상태 계약 확정,PLANNED,-,-,PM/Architect,"Blocked: Depends on Gate 1 (Phase 1). Waiting for Job 976 (~50-90 days)."
|
||||||
|
|||||||
|
@@ -0,0 +1,274 @@
|
|||||||
|
# VS-01: Identity Access Control (IAC) & Role-Based Access
|
||||||
|
|
||||||
|
**Vertical Slice:** VS-01 (Identity & Authorization)
|
||||||
|
**Version:** 1.0 DRAFT
|
||||||
|
**Date:** 2026-08-07
|
||||||
|
**Owner:** Security & Identity Architecture
|
||||||
|
**Status:** 📋 DRAFT (Specification Ready for Contract Review)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 User Story
|
||||||
|
|
||||||
|
**As a** platform security architect
|
||||||
|
**I want to** establish identity, MFA, RBAC role hierarchy, and maker-checker approval boundaries
|
||||||
|
**So that** all downstream slices (VS-02 through VS-08) can enforce consistent access control and segregation of duties
|
||||||
|
|
||||||
|
**Acceptance Criteria:**
|
||||||
|
- 📋 Identity contract defined (user/role/permission schema)
|
||||||
|
- 📋 MFA policy specified (2FA/TOTP/WebAuthn tiers)
|
||||||
|
- 📋 RBAC role hierarchy formalized (Guest/User/Operator/Admin/SuperAdmin + domain-specific roles)
|
||||||
|
- 📋 Maker-checker approval boundaries documented (for critical operations like model promotion, dataset freeze)
|
||||||
|
- 📋 Permission matrix mapped (read/write/delete/audit per role)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Non-Goals
|
||||||
|
|
||||||
|
- ❌ Implement UI/API endpoints (belongs to BE/FE slices)
|
||||||
|
- ❌ Integrate with external identity provider (OIDC/Kerberos setup deferred)
|
||||||
|
- ❌ Build MFA enforcement engine (belongs to separate AUTH_ENFORCEMENT slice)
|
||||||
|
- ❌ Execute permission checks (belongs to handler/middleware slices)
|
||||||
|
- ❌ Seed production user data (deferred to operations)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 State Transitions
|
||||||
|
|
||||||
|
### Identity Lifecycle
|
||||||
|
|
||||||
|
```
|
||||||
|
[UNDEFINED]
|
||||||
|
↓ (user registered)
|
||||||
|
[ACTIVE]
|
||||||
|
↓ (MFA required but not set)
|
||||||
|
[REQUIRES_MFA_SETUP]
|
||||||
|
↓ (MFA device registered)
|
||||||
|
[MFA_CONFIGURED]
|
||||||
|
↓ (temporary disable during password reset)
|
||||||
|
[MFA_SUSPENDED]
|
||||||
|
↓ (re-enable)
|
||||||
|
[MFA_CONFIGURED]
|
||||||
|
↓ (admin deactivation)
|
||||||
|
[INACTIVE]
|
||||||
|
↓ (security breach)
|
||||||
|
[REVOKED]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Role Assignment Workflow (Maker-Checker)
|
||||||
|
|
||||||
|
```
|
||||||
|
User requests elevated role (e.g., OPERATOR → ADMIN)
|
||||||
|
↓
|
||||||
|
[PENDING_APPROVAL] ← Role request created (requester_id, requested_role, reason)
|
||||||
|
↓
|
||||||
|
Admin receives notification (role.required_approver_count = 2)
|
||||||
|
↓
|
||||||
|
Approver-1 reviews & approves/rejects
|
||||||
|
↓
|
||||||
|
[APPROVED_BY_1] or [REJECTED]
|
||||||
|
↓ (if approved by 1, awaits Approver-2)
|
||||||
|
[APPROVED_BY_2]
|
||||||
|
↓
|
||||||
|
[ACTIVE] (role_assignment.effective_at set, correlation_id = approval_request.id)
|
||||||
|
↓
|
||||||
|
[EXPIRED] (optional: time-bound roles like "Quarterly Reviewer")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 RBAC Constraints
|
||||||
|
|
||||||
|
### Core Role Hierarchy
|
||||||
|
|
||||||
|
| Role | Description | Can Access | Can Modify | Can Approve | Maker-Checker Approval Required |
|
||||||
|
|------|-------------|-----------|-----------|-------------|--------|
|
||||||
|
| **GUEST** | Anonymous/public | Public resources (GDP compliant) | ❌ | ❌ | N/A |
|
||||||
|
| **USER** | Authenticated individual | Own data + shared workspace | Own data | ❌ | N/A |
|
||||||
|
| **OPERATOR** | Operations team (data ops, risk team) | All non-sensitive data | Configurations | MODEL_ACTIVATION (1 more) | MODEL_ACTIVATION, DATASET_FREEZE |
|
||||||
|
| **ADMIN** | Platform administrator | All data (except audit logs) | All (soft delete) | All (except critical) | CRITICAL_CONFIG, USER_REVOCATION |
|
||||||
|
| **SUPER_ADMIN** | Super administrator | All (including audit logs) | All (hard delete) | All | N/A (can self-approve in emergency) |
|
||||||
|
|
||||||
|
### Domain-Specific Roles (Optional, for Future Slices)
|
||||||
|
|
||||||
|
- **QUANT_ENGINEER** — Can read market data, backtest code; cannot modify live models
|
||||||
|
- **RISK_MANAGER** — Can read risk dashboards, flag models; cannot freeze or promote
|
||||||
|
- **COMPLIANCE_OFFICER** — Can audit all; cannot modify data
|
||||||
|
- **MODEL_REVIEWER** — Can read model cards, evidence; approves promotion via maker-checker
|
||||||
|
|
||||||
|
### MFA Tiers
|
||||||
|
|
||||||
|
| Tier | Requirement | Impact | Users |
|
||||||
|
|------|-------------|--------|-------|
|
||||||
|
| **NO_MFA** | None (legacy) | Guest/public read | Public API consumers |
|
||||||
|
| **TOTP_OPTIONAL** | Google Authenticator / Authy (optional) | USER tier | General staff |
|
||||||
|
| **TOTP_REQUIRED** | TOTP mandatory | OPERATOR+ tier | Operations, Risk, Compliance |
|
||||||
|
| **HARDWARE_KEY** | YubiKey / FIDO2 (required) | SUPER_ADMIN tier | Executives, DBAs |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Data Contract (v1.0)
|
||||||
|
|
||||||
|
### Point-in-Time (PIT) Envelope (Inherited from VS-00)
|
||||||
|
|
||||||
|
All identity tables MUST include:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Core identity tables
|
||||||
|
CREATE TABLE identity.users (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
email VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
display_name VARCHAR(255),
|
||||||
|
mfa_status VARCHAR(50) NOT NULL DEFAULT 'REQUIRES_MFA_SETUP', -- ACTIVE, REQUIRES_MFA_SETUP, MFA_CONFIGURED, INACTIVE, REVOKED
|
||||||
|
mfa_method VARCHAR(50), -- TOTP, HARDWARE_KEY, none
|
||||||
|
created_at TIMESTAMPTZ NOT NULL,
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL,
|
||||||
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
revision INT NOT NULL DEFAULT 1,
|
||||||
|
correlation_id UUID NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE identity.roles (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
name VARCHAR(100) NOT NULL UNIQUE, -- GUEST, USER, OPERATOR, ADMIN, SUPER_ADMIN
|
||||||
|
description TEXT,
|
||||||
|
required_approver_count INT DEFAULT 1, -- How many approvers needed for elevation to this role
|
||||||
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
revision INT NOT NULL DEFAULT 1,
|
||||||
|
correlation_id UUID NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE identity.user_roles (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
user_id UUID NOT NULL REFERENCES identity.users(id),
|
||||||
|
role_id UUID NOT NULL REFERENCES identity.roles(id),
|
||||||
|
assigned_by_user_id UUID, -- Who assigned this role
|
||||||
|
effective_at TIMESTAMPTZ NOT NULL,
|
||||||
|
expires_at TIMESTAMPTZ, -- Optional: time-bound roles
|
||||||
|
is_active BOOLEAN DEFAULT TRUE,
|
||||||
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
revision INT NOT NULL DEFAULT 1,
|
||||||
|
correlation_id UUID NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE identity.role_approval_requests (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
user_id UUID NOT NULL REFERENCES identity.users(id),
|
||||||
|
requested_role_id UUID NOT NULL REFERENCES identity.roles(id),
|
||||||
|
reason TEXT,
|
||||||
|
status VARCHAR(50) NOT NULL DEFAULT 'PENDING_APPROVAL', -- PENDING_APPROVAL, APPROVED_BY_1, APPROVED_BY_2, REJECTED, WITHDRAWN
|
||||||
|
approver_count_required INT NOT NULL,
|
||||||
|
approvers JSONB NOT NULL DEFAULT '[]'::JSONB, -- [{ "approver_id": UUID, "approved_at": TIMESTAMPTZ, "reason": "" }]
|
||||||
|
created_at TIMESTAMPTZ NOT NULL,
|
||||||
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
revision INT NOT NULL DEFAULT 1,
|
||||||
|
correlation_id UUID NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE identity.mfa_devices (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
user_id UUID NOT NULL REFERENCES identity.users(id),
|
||||||
|
device_type VARCHAR(50) NOT NULL, -- TOTP, HARDWARE_KEY
|
||||||
|
secret_hash VARCHAR(255), -- Hashed TOTP secret (never store plaintext)
|
||||||
|
device_name VARCHAR(255), -- User-friendly name ("My YubiKey", "Work Phone")
|
||||||
|
registered_at TIMESTAMPTZ NOT NULL,
|
||||||
|
last_used_at TIMESTAMPTZ,
|
||||||
|
is_backup_device BOOLEAN DEFAULT FALSE,
|
||||||
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
revision INT NOT NULL DEFAULT 1,
|
||||||
|
correlation_id UUID NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE identity.permissions (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
role_id UUID NOT NULL REFERENCES identity.roles(id),
|
||||||
|
resource VARCHAR(255) NOT NULL, -- "model_activation", "dataset_freeze", "user_management"
|
||||||
|
action VARCHAR(50) NOT NULL, -- READ, WRITE, DELETE, AUDIT
|
||||||
|
constraints JSONB, -- Optional: { "requires_approval_count": 2, "requires_evidence": ["model_card"] }
|
||||||
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
revision INT NOT NULL DEFAULT 1,
|
||||||
|
correlation_id UUID NOT NULL,
|
||||||
|
UNIQUE(role_id, resource, action)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data Quality Rules
|
||||||
|
|
||||||
|
- ✅ No direct password storage (use bcrypt + salt)
|
||||||
|
- ✅ MFA secrets never logged or exposed in HTTP responses
|
||||||
|
- ✅ All role changes tracked in `user_roles` append-only (no soft deletes)
|
||||||
|
- ✅ Approval requests immutable once APPROVED_BY_1 or REJECTED
|
||||||
|
- ✅ PIT envelope strictly enforced: `published_at <= cutoff` for all reads
|
||||||
|
- ✅ `correlation_id` links all related tables for audit trail
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛡️ Governance Gates
|
||||||
|
|
||||||
|
### Pre-Merge Gates
|
||||||
|
|
||||||
|
- [ ] **RBAC Matrix Approved:** Security team signs off on role hierarchy and permission matrix
|
||||||
|
- [ ] **MFA Tier Mapping:** Confirm mapping between role tiers and MFA requirements
|
||||||
|
- [ ] **Maker-Checker Thresholds:** Define approval_count per critical operation (e.g., model promotion = 2 approvers)
|
||||||
|
- [ ] **Audit Log Design:** Confirm all authorization decisions (grant/deny/revoke) are logged with `correlation_id`
|
||||||
|
- [ ] **Identity Provider Integration Plan:** Document OIDC/Kerberos provider (if applicable)
|
||||||
|
|
||||||
|
### Post-Merge Validation
|
||||||
|
|
||||||
|
- [ ] **Schema Tests:** User/role/MFA creation tests pass (40+ scenarios)
|
||||||
|
- [ ] **RBAC Policy Tests:** Permission matrix matches code (cross-checked vs ADR-SEC-001)
|
||||||
|
- [ ] **PIT Query Tests:** All reads include `WHERE published_at <= @cutoff`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Source / Assumptions / Unknown
|
||||||
|
|
||||||
|
### Source
|
||||||
|
|
||||||
|
- **ADR-SEC-001:** OIDC/JWT/DevelopmentHeader authentication tiers (approved 2026-08-04)
|
||||||
|
- **Existing RBAC:** VS-00-SLICE_SPEC (base governance, roles table exists)
|
||||||
|
- **Maker-Checker Pattern:** Standard 2-approver workflow from compliance requirements
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
|
- ✅ OIDC identity provider will be integrated later (separate slice); VS-01 is schema + policy only
|
||||||
|
- ✅ MFA enforcement (checking device before operation) happens in middleware/handler layer (not here)
|
||||||
|
- ✅ Audit logging of permission checks is already handled by OutboxPollerJob + SerilogCorrelation
|
||||||
|
- ✅ All users are human; no service-account roles yet (may expand in future)
|
||||||
|
|
||||||
|
### Unknown
|
||||||
|
|
||||||
|
- ❓ **OIDC Provider Identity:** Which OIDC provider (Keycloak, Auth0, Azure AD)? Deferred to separate architecture decision.
|
||||||
|
- ❓ **Hardware Key Vendor:** YubiKey vs other FIDO2 vendors? Deferred to procurement.
|
||||||
|
- ❓ **Approval SLA:** How long can role requests stay in PENDING_APPROVAL before escalation alert? (Assumed 5 business days; confirm with ops)
|
||||||
|
- ❓ **Audit Retention:** How long to retain `role_approval_requests` history? (Assumed 7 years for compliance; confirm with legal)
|
||||||
|
- ❓ **Domain-Specific Roles:** Should QUANT_ENGINEER/RISK_MANAGER/COMPLIANCE roles be predefined, or dynamically created per organization? (Deferred to VS-03+)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Compliance & Traceability
|
||||||
|
|
||||||
|
**Governance:** AGENTS.md v16.0 Maturity gate (contract-first, no placeholder code)
|
||||||
|
**Related ADRs:**
|
||||||
|
- ADR-SEC-001: Authentication strategy (OIDC tiers)
|
||||||
|
- ADR-GOV-001: Role-based access control (assumed; link when available)
|
||||||
|
|
||||||
|
**WBS Dependencies:**
|
||||||
|
- ✅ AEG-X-001 (Version Coverage Matrix): Prerequisite for schema versioning
|
||||||
|
- ✅ AEG-VS-00-02 (Data Contract): PIT envelope inherited
|
||||||
|
|
||||||
|
**Next Slices (Depend on VS-01):**
|
||||||
|
- VS-02: Financial Security Master (source approval RBAC)
|
||||||
|
- VS-03: Model Operations (model promotion maker-checker)
|
||||||
|
- VS-04+: All domain slices (inherit identity & approval boundaries)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
**📋 DRAFT:** Specification complete, ready for:
|
||||||
|
1. Security team approval (RBAC matrix + MFA tiers)
|
||||||
|
2. Compliance team approval (maker-checker SLA + audit retention)
|
||||||
|
3. Architecture review (schema + PIT readiness)
|
||||||
|
4. Next: Implementation (separate PR for schema migration + tests)
|
||||||
|
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
# VS-02: Financial Security Master Data Synchronization
|
||||||
|
|
||||||
|
**Vertical Slice:** VS-02 (Financial Security Master)
|
||||||
|
**Version:** 1.0 DRAFT
|
||||||
|
**Date:** 2026-08-07
|
||||||
|
**Owner:** Data Architecture & Compliance
|
||||||
|
**Status:** ⚠️ DRAFT (Source Unknown — See Issues Below)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Critical Notice: Domain Correction
|
||||||
|
|
||||||
|
**Previous Implementation (Superseded):**
|
||||||
|
Existing code at `src/KArtSell.Host/Features/SecurityMaster/VS02_*.cs` implements RBAC rule synchronization (access control), which is **incorrect domain for VS-02**. See **TECH-DEBT-XXX** for tech debt registration and removal plan.
|
||||||
|
|
||||||
|
**Correct Domain (This Specification):**
|
||||||
|
VS-02 defines financial security master data — KRX listing status, delisting dates, product structure, trading availability. This is **PIT-tracked reference data**, not access control rules.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 User Story
|
||||||
|
|
||||||
|
**As a** risk manager / compliance officer
|
||||||
|
**I want to** maintain authoritative, point-in-time financial security attributes (listing status, delisting dates, product structure)
|
||||||
|
**So that** shadow run simulation, sell decision, and portfolio reconciliation can reference frozen, auditable security master state
|
||||||
|
|
||||||
|
**Acceptance Criteria:**
|
||||||
|
- 📋 Listing status & delisting dates tracked (KRX official source)
|
||||||
|
- 📋 Product structure captured (주식/채권/파생/펀드 분류)
|
||||||
|
- 📋 Trading availability flags maintained (거래정지, 관리종목, etc.)
|
||||||
|
- 📋 PIT queries enforced (all reads include `WHERE published_at <= cutoff`)
|
||||||
|
- 📋 Data lineage & source attribution documented
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Non-Goals
|
||||||
|
|
||||||
|
- ❌ Implement access-control rule synchronization (belongs to VS-01 / separate auth slice)
|
||||||
|
- ❌ Build KRX API integration (deferred; CSV upload manual for v1.0)
|
||||||
|
- ❌ Execute real-time market feed subscriptions (belongs to market data ingest slice)
|
||||||
|
- ❌ Generate compliance reports (belongs to separate reporting slice)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Proposed Data Schema
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Financial security master (PIT-tracked)
|
||||||
|
CREATE TABLE financial_security_master.securities (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
krx_code VARCHAR(12) NOT NULL, -- e.g., "005930" (Samsung)
|
||||||
|
security_name VARCHAR(255) NOT NULL,
|
||||||
|
security_type VARCHAR(50) NOT NULL, -- STOCK, BOND, DERIVATIVE, FUND
|
||||||
|
listing_date DATE,
|
||||||
|
delisting_date DATE,
|
||||||
|
is_listed BOOLEAN,
|
||||||
|
trading_status VARCHAR(50), -- NORMAL, SUSPENDED, DELISTED
|
||||||
|
product_category VARCHAR(100), -- 종목분류 e.g., LARGE_CAP, MID_CAP, SMALL_CAP
|
||||||
|
currency_code VARCHAR(3), -- KRW, USD
|
||||||
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
revision INT NOT NULL DEFAULT 1,
|
||||||
|
correlation_id UUID NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE financial_security_master.trading_restrictions (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
security_id UUID NOT NULL REFERENCES financial_security_master.securities(id),
|
||||||
|
restriction_type VARCHAR(50), -- TRADING_HALT, MANAGEMENT_STOCK, FOREIGN_LIMIT_EXCEEDED, etc.
|
||||||
|
effective_date DATE NOT NULL,
|
||||||
|
end_date DATE,
|
||||||
|
reason TEXT,
|
||||||
|
published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
revision INT NOT NULL DEFAULT 1,
|
||||||
|
correlation_id UUID NOT NULL
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Source / Assumptions / Unknown
|
||||||
|
|
||||||
|
### Source
|
||||||
|
|
||||||
|
- **KRX Official Source:** KRX OPEN DATA (상장/상폐 공시)
|
||||||
|
- **Reference:** `CLAUDE.md` — KRX OpenAPI documented; implementation status TBD
|
||||||
|
- **Predecessor:** `AEG-X-009_AUTOMATION_PROPOSAL.md` flags "상폐·상품구조·거래가능성" as P3 (automation layer)
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
|
- ✅ KRX provides authoritative, daily-updated listing status
|
||||||
|
- ✅ Delisting dates are known in advance (compliance filed)
|
||||||
|
- ✅ Trading restrictions are announced via KRX official channels
|
||||||
|
- ✅ CSV export / API feed can be imported daily (separate slice)
|
||||||
|
|
||||||
|
### ⚠️ **UNKNOWNS — Blocking Full Specification**
|
||||||
|
|
||||||
|
1. **Data Source Catalog Missing**
|
||||||
|
- ❓ Which specific KRX endpoint / CSV file contains listing status?
|
||||||
|
- ❓ Is there a 3rd-party data aggregator (Bloomberg, FactSet)?
|
||||||
|
- ❓ Is CSV manual upload acceptable for v1.0, or must we have automated ingest?
|
||||||
|
- **Status:** Not found in `source-catalog.md` — requires data governance review
|
||||||
|
|
||||||
|
2. **Refresh Frequency & SLA**
|
||||||
|
- ❓ Daily update sufficient, or intraday?
|
||||||
|
- ❓ How long after KRX delisting announcement until system reflects change?
|
||||||
|
- **Status:** No SLA documented in CLAUDE.md
|
||||||
|
|
||||||
|
3. **Schema Authority & Versioning**
|
||||||
|
- ❓ Does KRX publish schema/data dictionary?
|
||||||
|
- ❓ If schema changes (new trading restriction type), how do we version?
|
||||||
|
- **Status:** Deferred to data contract review
|
||||||
|
|
||||||
|
4. **Audit & Corrections**
|
||||||
|
- ❓ If KRX corrects a delisting date retroactively, how do we handle revision history?
|
||||||
|
- ❓ Do we notify downstream (shadow runs, sell decisions) of corrections?
|
||||||
|
- **Status:** Assumed append-only, no updates; confirm with risk team
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛡️ Governance Gates
|
||||||
|
|
||||||
|
### Pre-Merge Gates
|
||||||
|
|
||||||
|
- [ ] **Source Approved:** Data governance confirms KRX endpoint / 3rd-party aggregator
|
||||||
|
- [ ] **Schema Finalized:** DBA & risk team sign off on `securities` + `trading_restrictions` tables
|
||||||
|
- [ ] **Data SLA Signed:** Ops commits to daily import + SLA (e.g., T+1 after KRX announcement)
|
||||||
|
- [ ] **Audit Trail:** Confirm all inserts are correlated + versioned
|
||||||
|
|
||||||
|
### Post-Merge Validation (Deferred)
|
||||||
|
|
||||||
|
- [ ] Schema migration tests (fresh / upgrade / rollback)
|
||||||
|
- [ ] KRX data import tests (sample CSV)
|
||||||
|
- [ ] PIT query tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
**⚠️ DRAFT (Source Unknown):**
|
||||||
|
This specification is **intentionally incomplete** until the following unknowns are resolved:
|
||||||
|
|
||||||
|
1. **KRX Data Source:** Confirm endpoint / feed URI in source-catalog.md
|
||||||
|
2. **Import SLA:** Confirm daily update frequency & latency tolerance
|
||||||
|
3. **Audit & Corrections:** Confirm handling of retroactive corrections
|
||||||
|
|
||||||
|
**Do NOT implement schema or import logic until above are approved.**
|
||||||
|
|
||||||
|
**Next Steps:**
|
||||||
|
1. Data governance team reviews & approves Source Unknown items
|
||||||
|
2. Separate PR adds schema migration (after source approval)
|
||||||
|
3. Separate PR adds import job (after SLA & audit approval)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Related Documents
|
||||||
|
|
||||||
|
- **Governance:** AGENTS.md v16.0, CLAUDE.md "No real customer data seeded"
|
||||||
|
- **Tech Debt:** TECH-DEBT-XXX (VS-02 mislabeled code, awaiting removal decision)
|
||||||
|
- **Upstream:** VS-00 (PIT envelope), VS-01 (approval boundaries)
|
||||||
|
- **Downstream:** VS-03 (model operations), AEG-X-009 (automation orchestration)
|
||||||
|
|
||||||
Reference in New Issue
Block a user