Files
KArtSell.Aegis/contracts/data/identity-data-contract.v1.json
T
kjh2064 a7f4ec8759 feat(wbs): AEG-VS-01-02 Identity & Access Control data contract
AEG-VS-01-02: Data Schema & Contract Definition

Implementation:
1. db/migrations/0042_iam_tables.sql
   - identity table: PIT versioning (published_at, revision_version)
   - role table: Hierarchy levels (GUEST/USER/OPERATOR/ADMIN/SUPER_ADMIN)
   - role_assignment table: Maker-Checker workflow (PENDING_APPROVAL → ACTIVE)
   - permission table: Granular permissions (RESOURCE:ACTION)
   - role_permission table: M:N role-to-permission mapping
   - mfa_device table: TOTP/WebAuthn/SMS/EMAIL support

2. contracts/data/identity-data-contract.v1.json
   - Full JSON Schema for 5 tables
   - PIT (Point-in-Time) versioning strategy
   - Maker-Checker workflow constraints
   - Unique constraints (username, email, role_name, resource+action)
   - Referential integrity (cascade on delete)
   - Lineage: upstream (OIDC), downstream (Auth middleware, Authorization policy)
   - Quality rules: no circular hierarchies, MFA verification, approval counts

Principles Applied:
- 정규화: 5NF (identity/role/permission separation)
- 역정규화: role_assignment.approved_by_identity_ids (array for audit)
- 정공법: Maker-Checker enforced at schema level (approval_count constraint)
- 안정성: Immutable append-only (published_at, revision_version)
- 데이터 정합성: referential integrity, unique constraints, quality rules

Next: AEG-VS-01-03 (Domain Policy Implementation)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-17 17:26:55 +09:00

346 lines
11 KiB
JSON

{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Identity & Access Control Data Contract v1.0",
"description": "PIT (Point-in-Time) contract for Identity, Role, Permission, and MFA data (AEG-VS-01-02)",
"version": "1.0",
"type": "object",
"definitions": {
"identity": {
"type": "object",
"description": "User identity record (PIT: published_at + revision_version)",
"properties": {
"identity_id": {
"type": "string",
"format": "uuid",
"description": "Unique identity identifier"
},
"username": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Unique username"
},
"email": {
"type": "string",
"format": "email",
"description": "Unique email address"
},
"display_name": {
"type": "string",
"maxLength": 255,
"description": "Human-readable display name"
},
"state": {
"type": "string",
"enum": ["UNDEFINED", "ACTIVE", "REQUIRES_MFA_SETUP", "MFA_CONFIGURED", "MFA_SUSPENDED", "INACTIVE", "REVOKED"],
"description": "Identity lifecycle state"
},
"mfa_required": {
"type": "boolean",
"description": "Whether MFA is required for this identity"
},
"mfa_enforced_at": {
"type": "string",
"format": "date-time",
"description": "When MFA enforcement was applied"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "Original creation timestamp"
},
"published_at": {
"type": "string",
"format": "date-time",
"description": "PIT publication timestamp (for versioning)"
},
"revision_version": {
"type": "integer",
"minimum": 1,
"description": "Immutable revision counter"
},
"correlation_id": {
"type": "string",
"format": "uuid",
"description": "Links to approval/correction events"
}
},
"required": ["identity_id", "username", "email", "state", "created_at", "published_at", "revision_version"]
},
"role": {
"type": "object",
"description": "Role definition (Core or Domain-Specific)",
"properties": {
"role_id": {
"type": "string",
"format": "uuid"
},
"role_name": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"examples": ["GUEST", "USER", "OPERATOR", "ADMIN", "SUPER_ADMIN", "QUANT_ENGINEER"]
},
"description": {
"type": "string"
},
"hierarchy_level": {
"type": "integer",
"minimum": 0,
"description": "0=GUEST, 1=USER, 2=OPERATOR, 3=ADMIN, 4=SUPER_ADMIN, 100+=domain-specific"
},
"role_type": {
"type": "string",
"enum": ["CORE", "DOMAIN_SPECIFIC", "TEMPORARY", "SERVICE"]
},
"expires_at": {
"type": "string",
"format": "date-time",
"description": "Optional expiration for TEMPORARY roles"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"published_at": {
"type": "string",
"format": "date-time"
},
"revision_version": {
"type": "integer",
"minimum": 1
}
},
"required": ["role_id", "role_name", "hierarchy_level", "role_type", "created_at", "published_at", "revision_version"]
},
"role_assignment": {
"type": "object",
"description": "Identity-to-Role mapping with Maker-Checker workflow",
"properties": {
"role_assignment_id": {
"type": "string",
"format": "uuid"
},
"identity_id": {
"type": "string",
"format": "uuid"
},
"role_id": {
"type": "string",
"format": "uuid"
},
"assignment_state": {
"type": "string",
"enum": ["PENDING_APPROVAL", "APPROVED_BY_1", "APPROVED_BY_2", "ACTIVE", "EXPIRED", "REVOKED", "REJECTED"],
"description": "Maker-Checker workflow state"
},
"approval_count": {
"type": "integer",
"minimum": 0,
"maximum": 10
},
"required_approval_count": {
"type": "integer",
"minimum": 1,
"default": 2
},
"approved_by_identity_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "List of approver identity IDs (append-only)"
},
"approval_reason": {
"type": "string"
},
"effective_at": {
"type": "string",
"format": "date-time",
"description": "When the role becomes ACTIVE"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"published_at": {
"type": "string",
"format": "date-time"
},
"revision_version": {
"type": "integer",
"minimum": 1
},
"correlation_id": {
"type": "string",
"format": "uuid",
"description": "Links to approval request/event"
}
},
"required": ["role_assignment_id", "identity_id", "role_id", "assignment_state", "created_at", "published_at", "correlation_id"]
},
"permission": {
"type": "object",
"description": "Granular permission (resource:action)",
"properties": {
"permission_id": {
"type": "string",
"format": "uuid"
},
"permission_name": {
"type": "string",
"examples": ["MODEL:READ", "DATASET:WRITE", "AUDIT_LOG:READ"]
},
"resource": {
"type": "string",
"enum": ["MODEL", "DATASET", "PORTFOLIO", "AUDIT_LOG", "IDENTITY", "CONFIG"]
},
"action": {
"type": "string",
"enum": ["READ", "WRITE", "DELETE", "APPROVE", "AUDIT"]
},
"permission_category": {
"type": "string",
"enum": ["DATA_ACCESS", "WORKFLOW_APPROVAL", "ADMIN", "AUDIT"]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"published_at": {
"type": "string",
"format": "date-time"
},
"revision_version": {
"type": "integer",
"minimum": 1
}
},
"required": ["permission_id", "permission_name", "resource", "action", "permission_category"]
},
"mfa_device": {
"type": "object",
"description": "Multi-Factor Authentication device",
"properties": {
"mfa_device_id": {
"type": "string",
"format": "uuid"
},
"identity_id": {
"type": "string",
"format": "uuid"
},
"device_type": {
"type": "string",
"enum": ["TOTP", "WEBAUTHN", "SMS", "EMAIL"],
"description": "MFA technology"
},
"device_name": {
"type": "string",
"description": "User-friendly device name (e.g., 'My iPhone')"
},
"state": {
"type": "string",
"enum": ["PENDING_VERIFICATION", "VERIFIED", "REVOKED"],
"description": "Device lifecycle state"
},
"last_used_at": {
"type": "string",
"format": "date-time",
"description": "Anomaly detection hint"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"published_at": {
"type": "string",
"format": "date-time"
},
"revision_version": {
"type": "integer",
"minimum": 1
}
},
"required": ["mfa_device_id", "identity_id", "device_type", "state", "created_at", "published_at"]
}
},
"properties": {
"tables": {
"type": "object",
"properties": {
"identity": {
"type": "array",
"items": {
"$ref": "#/definitions/identity"
},
"description": "Identity records (PIT versioned)"
},
"role": {
"type": "array",
"items": {
"$ref": "#/definitions/role"
},
"description": "Role definitions"
},
"role_assignment": {
"type": "array",
"items": {
"$ref": "#/definitions/role_assignment"
},
"description": "Identity-to-Role mappings (Maker-Checker workflow)"
},
"permission": {
"type": "array",
"items": {
"$ref": "#/definitions/permission"
},
"description": "Granular permissions"
},
"mfa_device": {
"type": "array",
"items": {
"$ref": "#/definitions/mfa_device"
},
"description": "MFA device registrations"
}
}
}
},
"constraints": {
"immutability": "All records append-only via published_at + revision_version. No UPDATE/DELETE in write path.",
"maker_checker": "role_assignment transitions require approval_count >= required_approval_count before ACTIVE state.",
"mfa_enforcement": "If mfa_required=true, identity.state must be MFA_CONFIGURED before ACTIVE workflows.",
"unique_constraints": {
"identity": ["username", "email"],
"role": ["role_name"],
"permission": ["resource + action"],
"role_assignment": ["identity_id + role_id (excluding REVOKED/REJECTED)"],
"mfa_device": ["device_identifier"]
},
"referential_integrity": {
"role_assignment.identity_id": "REFERENCES identity(identity_id) ON DELETE CASCADE",
"role_assignment.role_id": "REFERENCES role(role_id) ON DELETE CASCADE",
"mfa_device.identity_id": "REFERENCES identity(identity_id) ON DELETE CASCADE"
}
},
"lineage": {
"upstream_sources": ["Active Directory / OIDC provider (external, seeded by operations)"],
"transformations": ["Schema normalization, PIT versioning, Maker-Checker annotation"],
"downstream_consumers": ["Authentication Middleware (checks identity.state), Authorization Policy (checks role_assignment.assignment_state + role_permission)]",
"quality_rules": [
"All identities must have valid username + email (no nulls)",
"role_assignment.approval_count <= role_assignment.required_approval_count",
"No circular role hierarchies (role.hierarchy_level is monotonic)",
"MFA device verification before identity.mfa_required enforcement"
]
},
"metadata": {
"owner": "Security & Identity Architecture",
"version_history": "v1.0 (2026-08-17): Initial Identity, Role, MFA contract",
"sla": "Read latency <10ms, Write consistency ACID (single-db commit)",
"retention_policy": "Immutable; corrected via correction_event (never DELETE/UPDATE)"
}
}