create-entity-server 0.0.27 → 0.0.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/package.json +1 -1
  2. package/template/configs/auth/password.json +17 -5
  3. package/template/configs/cache.json +2 -1
  4. package/template/entities/System/Auth/account.json +158 -18
  5. package/template/entities/System/Auth/account_audit.json +11 -3
  6. package/template/entities/System/Auth/account_device.json +13 -12
  7. package/template/entities/System/Auth/account_login_log.json +21 -6
  8. package/template/entities/System/Auth/account_oauth.json +42 -13
  9. package/template/entities/System/Auth/api_keys.json +18 -9
  10. package/template/entities/System/Auth/identity_verification.json +18 -7
  11. package/template/entities/System/Auth/license.json +41 -20
  12. package/template/entities/System/Auth/password_history.json +4 -5
  13. package/template/entities/System/Auth/rbac_roles.json +10 -7
  14. package/template/entities/System/Backup/backup_log.json +11 -7
  15. package/template/entities/System/Email/smtp_log.json +9 -5
  16. package/template/entities/System/Email/smtp_msg.json +5 -5
  17. package/template/entities/System/Notification/alimtalk_log.json +32 -12
  18. package/template/entities/System/Notification/alimtalk_msg.json +23 -9
  19. package/template/entities/System/Notification/friendtalk_log.json +59 -18
  20. package/template/entities/System/Notification/friendtalk_msg.json +43 -15
  21. package/template/entities/System/Notification/sms_log.json +55 -16
  22. package/template/entities/System/Notification/sms_msg.json +45 -15
  23. package/template/entities/System/Notification/sms_verification.json +17 -7
  24. package/template/entities/System/Payment/pg_cancel.json +25 -10
  25. package/template/entities/System/Payment/pg_order.json +40 -13
  26. package/template/entities/System/Payment/pg_webhook_log.json +24 -9
  27. package/template/entities/System/Push/push_log.json +18 -3
  28. package/template/entities/System/Push/push_msg.json +6 -5
  29. package/template/entities/System/Storage/file_backup_log.json +11 -6
  30. package/template/entities/System/Storage/file_download_log.json +7 -5
  31. package/template/entities/System/Storage/file_meta.json +20 -7
  32. package/template/entities/System/system_audit_log.json +38 -34
  33. package/template/entities/company.json +5 -2
  34. package/template/entities/goods.json +10 -3
  35. package/template/entities/todo.json +4 -2
  36. package/template/samples/entities/01_basic_fields.json +15 -2
  37. package/template/samples/entities/02_types_and_defaults.json +15 -5
  38. package/template/samples/entities/03_hash_and_unique.json +18 -3
  39. package/template/samples/entities/04_fk_and_composite_unique.json +18 -3
  40. package/template/samples/entities/05_cache.json +15 -9
  41. package/template/samples/entities/06_history_and_hard_delete.json +19 -6
  42. package/template/samples/entities/07_license_scope.json +18 -3
  43. package/template/samples/entities/08_hook_sql.json +24 -5
  44. package/template/samples/entities/09_hook_entity.json +12 -2
  45. package/template/samples/entities/10_hook_submit_delete.json +14 -5
  46. package/template/samples/entities/11_hook_webhook.json +20 -6
  47. package/template/samples/entities/12_hook_push.json +15 -2
  48. package/template/samples/entities/13_read_only.json +8 -4
  49. package/template/samples/entities/14_optimistic_lock.json +13 -2
  50. package/template/samples/entities/15_reset_defaults.json +7 -1
  51. package/template/samples/entities/16_isolated_license.json +19 -6
  52. package/template/scripts/reset-all.sh +57 -3
  53. package/template/scripts/run.sh +56 -6
  54. package/template/templates/ocr/business_reg.json +145 -0
  55. package/template/templates/ocr/career_cert.json +93 -0
  56. package/template/templates/ocr/driver_license.json +89 -0
  57. package/template/templates/ocr/facility_card.json +82 -0
  58. package/template/templates/ocr/id_card.json +55 -0
  59. package/template/templates/ocr/invoice.json +92 -0
  60. package/template/templates/ocr/namecard.json +116 -0
  61. package/template/templates/ocr/prompts/business_reg.json +14 -0
  62. package/template/templates/ocr/prompts/career_cert.json +16 -0
  63. package/template/templates/ocr/prompts/driver_license.json +14 -0
  64. package/template/templates/ocr/prompts/facility_card.json +15 -0
  65. package/template/templates/ocr/prompts/general.json +13 -0
  66. package/template/templates/ocr/prompts/id_card.json +11 -0
  67. package/template/templates/ocr/prompts/invoice.json +17 -0
  68. package/template/templates/ocr/prompts/namecard.json +15 -0
  69. package/template/templates/ocr/prompts/receipt.json +14 -0
  70. package/template/templates/ocr/receipt.json +79 -0
  71. package/template/configs/auth/identity.json +0 -27
  72. package/template/configs/auth/privacy_policy.json +0 -28
  73. package/template/configs/auth/two_factor.json +0 -12
  74. package/template/configs/extensions/pg.json +0 -37
  75. package/template/configs/extensions/tax-invoice.json +0 -59
  76. package/template/configs/notification/alimtalk.json +0 -75
  77. package/template/configs/notification/sms.json +0 -54
  78. package/template/templates/email/account/dormancy_warning.html +0 -20
  79. package/template/templates/email/account/password_expiry_warning.html +0 -21
  80. package/template/templates/email/auth/email_verification.html +0 -18
  81. package/template/templates/email/auth/force_reset.html +0 -18
  82. package/template/templates/email/auth/password_reset.html +0 -19
  83. package/template/templates/email/auth/verification.html +0 -15
  84. package/template/templates/email/auth/verification_link.html +0 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-entity-server",
3
- "version": "0.0.27",
3
+ "version": "0.0.31",
4
4
  "description": "Create a new entity-server project in one command — like create-react-app or create-vite.",
5
5
  "keywords": [
6
6
  "entity-server",
@@ -1,10 +1,22 @@
1
1
  {
2
2
  "password_policy": {
3
3
  "min_length": 8,
4
+ "max_length": 128,
4
5
  "require_mixed_case": false,
5
6
  "require_number": false,
6
7
  "require_special": false,
7
- "history_count": 5
8
+ "history_count": 5,
9
+ "forbidden_patterns": {
10
+ "sequential_digits": true,
11
+ "repeated_chars": true,
12
+ "keyboard_patterns": false,
13
+ "sequential_length": 4
14
+ },
15
+ "pii_check": {
16
+ "enabled": false,
17
+ "entity": "user",
18
+ "fields": ["phone", "birthday"]
19
+ }
8
20
  },
9
21
  "admin_force_reset": {
10
22
  "temp_password_length": 12,
@@ -12,16 +24,16 @@
12
24
  "notify_email": true
13
25
  },
14
26
  "password_reset": {
15
- "enabled": false,
16
- "token_ttl_sec": 300,
17
- "base_url": "/password-reset",
27
+ "enabled": true,
28
+ "temp_password_ttl_sec": 300,
29
+ "temp_password_length": 12,
18
30
  "rate_limit": {
19
31
  "per_email_per_hour": 5,
20
32
  "per_ip_per_minute": 10
21
33
  }
22
34
  },
23
35
  "email_verification": {
24
- "enabled": false,
36
+ "enabled": true,
25
37
  "required": false,
26
38
  "code_length": 6,
27
39
  "code_ttl_sec": 300,
@@ -16,7 +16,8 @@
16
16
  "addr": "127.0.0.1:6379",
17
17
  "password": "",
18
18
  "db": 0,
19
- "prefix": "entity_cache:"
19
+ "prefix": "entity_cache:",
20
+ "op_timeout_seconds": 2
20
21
  }
21
22
  }
22
23
  }
@@ -1,36 +1,125 @@
1
1
  {
2
2
  "name": "account",
3
- "description": "JWT 로그인/인증 계정 예제. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
4
- "index": {
5
- "user_seq": {
6
- "comment": "사용자번호"
7
- },
3
+ "description": "JWT 로그인/인증용 계정 정보. 사용자 환경에 맞게 fields를 자유롭게 확장할 수 있습니다.",
4
+ "fields": {
8
5
  "email": {
6
+ "index": true,
7
+ "hash": true,
9
8
  "comment": "이메일",
10
9
  "type": "email",
11
10
  "required": true,
12
11
  "unique": true
13
12
  },
14
- "status": {
15
- "comment": "상태",
16
- "type": ["active", "inactive", "blocked"],
17
- "default": "active"
18
- },
19
13
  "rbac_role": {
20
- "comment": "RBAC 역할 (JWT 인증/인가에 사용)",
14
+ "index": true,
15
+ "comment": "엔티티 접근 역할",
21
16
  "type": ["admin", "editor", "viewer", "auditor", "user"],
22
17
  "default": "user"
18
+ },
19
+ "status": {
20
+ "index": true,
21
+ "comment": "계정 상태",
22
+ "type": ["active", "inactive", "blocked", "dormant"],
23
+ "default": "active"
24
+ },
25
+ "user_seq": {
26
+ "index": true,
27
+ "comment": "사용자번호"
28
+ },
29
+ "max_session_cnt": {
30
+ "type": "uint"
31
+ },
32
+ "has_password": {
33
+ "type": "bool",
34
+ "comment": "비밀번호 설정 여부 (소셜 전용 계정 구분)"
35
+ },
36
+ "last_login_time": {
37
+ "comment": "마지막 로그인 시각 (휴면 판단 기준)"
38
+ },
39
+ "passwd_changed_time": {
40
+ "comment": "마지막 비밀번호 변경 시각 (만료 정책 기준)"
41
+ },
42
+ "temp_password_hash": {
43
+ "type": "varchar(128)",
44
+ "comment": "임시 비밀번호 해시 (비밀번호 초기화 요청 시 발급)"
45
+ },
46
+ "temp_password_issued_time": {
47
+ "comment": "임시 비밀번호 발급 시각"
48
+ },
49
+ "force_password_change": {
50
+ "type": "bool",
51
+ "default": false,
52
+ "comment": "다음 로그인 시 비밀번호 변경 강제"
53
+ },
54
+ "name": {
55
+ "no_store": true,
56
+ "comment": "가입 요청 시 전달되는 이름. account에는 저장되지 않고 after_insert 훅(user 엔티티 생성 등)에서만 사용됩니다."
57
+ },
58
+ "phone": {
59
+ "no_store": true,
60
+ "comment": "가입 요청 시 전달되는 전화번호. no_store."
61
+ },
62
+ "birth_date": {
63
+ "no_store": true,
64
+ "comment": "가입 요청 시 전달되는 생년월일. no_store."
65
+ },
66
+ "gender": {
67
+ "no_store": true,
68
+ "comment": "가입 요청 시 전달되는 성별. no_store."
69
+ },
70
+ "profile_image": {
71
+ "no_store": true,
72
+ "comment": "가입 요청 시 전달되는 프로필 이미지. no_store."
23
73
  }
24
74
  },
25
- "fk": {
26
- "user_seq": "user.seq"
27
- },
28
75
  "reset_defaults": [
29
76
  {
30
- "email": "admin@example.com",
77
+ "email": "admin1@${DEFAULT_EMAIL_DOMAIN}",
78
+ "passwd": "admin12345",
79
+ "rbac_role": "admin",
80
+ "status": "active"
81
+ },
82
+ {
83
+ "email": "admin2@${DEFAULT_EMAIL_DOMAIN}",
84
+ "passwd": "admin12345",
85
+ "rbac_role": "admin",
86
+ "status": "active"
87
+ },
88
+ {
89
+ "email": "admin3@${DEFAULT_EMAIL_DOMAIN}",
31
90
  "passwd": "admin12345",
32
91
  "rbac_role": "admin",
33
92
  "status": "active"
93
+ },
94
+ {
95
+ "email": "test1@${DEFAULT_EMAIL_DOMAIN}",
96
+ "passwd": "test12345",
97
+ "rbac_role": "user",
98
+ "status": "active"
99
+ },
100
+ {
101
+ "email": "test2@${DEFAULT_EMAIL_DOMAIN}",
102
+ "passwd": "test12345",
103
+ "rbac_role": "user",
104
+ "status": "active"
105
+ },
106
+ {
107
+ "email": "test3@${DEFAULT_EMAIL_DOMAIN}",
108
+ "passwd": "test12345",
109
+ "rbac_role": "user",
110
+ "status": "active"
111
+ },
112
+ {
113
+ "email": "test4@${DEFAULT_EMAIL_DOMAIN}",
114
+ "passwd": "test12345",
115
+ "rbac_role": "user",
116
+ "status": "active"
117
+ },
118
+ {
119
+ "email": "test5@${DEFAULT_EMAIL_DOMAIN}",
120
+ "passwd": "test12345",
121
+ "rbac_role": "user",
122
+ "status": "active"
34
123
  }
35
124
  ],
36
125
  "hooks": {
@@ -39,7 +128,22 @@
39
128
  "type": "sql",
40
129
  "query": "INSERT INTO account_audit (account_seq, action, email, created_time) VALUES (?, ?, ?, NOW())",
41
130
  "params": ["${new.seq}", "INSERT", "${new.email}"],
42
- "async": false
131
+ "required": true
132
+ },
133
+ {
134
+ "_comment": "가입 시 user 엔티티 자동 생성. enabled: true로 바꾸면 활성화됩니다. assign_seq_to로 account.user_seq에 자동 반영됩니다.",
135
+ "type": "submit",
136
+ "enabled": false,
137
+ "entity": "user",
138
+ "data": {
139
+ "account_seq": "${new.seq}",
140
+ "name": "${new.name}",
141
+ "phone": "${new.phone}",
142
+ "birth_date": "${new.birth_date}",
143
+ "gender": "${new.gender}",
144
+ "profile_image": "${new.profile_image}"
145
+ },
146
+ "assign_seq_to": "user_seq"
43
147
  }
44
148
  ],
45
149
  "after_update": [
@@ -47,7 +151,23 @@
47
151
  "type": "sql",
48
152
  "query": "INSERT INTO account_audit (account_seq, action, email, created_time) VALUES (?, ?, ?, NOW())",
49
153
  "params": ["${new.seq}", "UPDATE", "${new.email}"],
50
- "async": false
154
+ "required": true
155
+ },
156
+ {
157
+ "_comment": "계정 업데이트 시 user 프로필 동기화. enabled: true로 바꾸면 활성화됩니다.",
158
+ "type": "submit",
159
+ "enabled": false,
160
+ "entity": "user",
161
+ "match": {
162
+ "account_seq": "${new.seq}"
163
+ },
164
+ "data": {
165
+ "name": "${new.name}",
166
+ "phone": "${new.phone}",
167
+ "birth_date": "${new.birth_date}",
168
+ "gender": "${new.gender}",
169
+ "profile_image": "${new.profile_image}"
170
+ }
51
171
  }
52
172
  ],
53
173
  "after_delete": [
@@ -55,7 +175,27 @@
55
175
  "type": "sql",
56
176
  "query": "INSERT INTO account_audit (account_seq, action, email, created_time) VALUES (?, ?, ?, NOW())",
57
177
  "params": ["${old.seq}", "DELETE", "${old.email}"],
58
- "async": false
178
+ "required": true
179
+ }
180
+ ],
181
+ "after_get": [
182
+ {
183
+ "type": "entity",
184
+ "entity": "user",
185
+ "action": "find",
186
+ "conditions": {
187
+ "seq": "${new.user_seq}"
188
+ },
189
+ "assign_to": "user_profile"
190
+ },
191
+ {
192
+ "type": "entity",
193
+ "entity": "account_device",
194
+ "action": "list",
195
+ "conditions": {
196
+ "account_seq": "${new.seq}"
197
+ },
198
+ "assign_to": "devices"
59
199
  }
60
200
  ]
61
201
  }
@@ -1,21 +1,29 @@
1
1
  {
2
2
  "name": "account_audit",
3
- "description": "account 감사 로그. account.json 훅(after_insert/after_update/after_delete)에 의해 자동 기록됩니다. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
3
+ "description": "account 감사 로그. account.json 훅(after_insert/after_update/after_delete)에 의해 자동 기록됩니다. 사용자 환경에 맞게 fields를 자유롭게 확장할 수 있습니다.",
4
4
  "hard_delete": true,
5
5
  "read_only": true,
6
6
  "compress": true,
7
- "index": {
7
+ "fields": {
8
8
  "account_seq": {
9
+ "index": true,
9
10
  "comment": "계정 seq (JWT 인증 시 account.seq 참조. HMAC은 nullable)",
10
11
  "type": "bigint",
11
12
  "nullable": true
12
13
  },
13
14
  "action": {
15
+ "index": true,
14
16
  "comment": "작업 유형 (after_insert → INSERT, after_update → UPDATE, after_delete → DELETE)",
15
- "type": ["INSERT", "UPDATE", "DELETE"],
17
+ "type": [
18
+ "INSERT",
19
+ "UPDATE",
20
+ "DELETE"
21
+ ],
16
22
  "required": true
17
23
  },
18
24
  "email": {
25
+ "index": true,
26
+ "hash": true,
19
27
  "comment": "작업 대상 계정 이메일",
20
28
  "nullable": true
21
29
  }
@@ -1,27 +1,22 @@
1
1
  {
2
2
  "name": "account_device",
3
- "description": "계정 기기 정보 및 푸시 토큰 관리. JWT 인증 시 account_seq로 계정과 연결. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
3
+ "description": "계정 기기 정보 및 푸시 토큰 관리. JWT 인증 시 account_seq로 계정과 연결. 사용자 환경에 맞게 fields를 자유롭게 확장할 수 있습니다.",
4
4
  "license_scope": false,
5
- "index": {
5
+ "fields": {
6
6
  "account_seq": {
7
+ "index": true,
7
8
  "comment": "계정seq (JWT 인증 시 필수. HMAC 인증은 nullable)"
8
9
  },
9
10
  "id": {
11
+ "index": true,
10
12
  "comment": "기기ID"
11
13
  },
12
14
  "push_enabled": {
15
+ "index": true,
13
16
  "comment": "푸시 수신 허용",
14
17
  "type": "bool",
15
18
  "default": true
16
- }
17
- },
18
- "unique": [
19
- [
20
- "id",
21
- "account_seq"
22
- ]
23
- ],
24
- "fields": {
19
+ },
25
20
  "device_type": {
26
21
  "comment": "기기유형",
27
22
  "type": [
@@ -59,5 +54,11 @@
59
54
  "last_ip_addr": {
60
55
  "comment": "마지막IP주소"
61
56
  }
62
- }
57
+ },
58
+ "unique": [
59
+ [
60
+ "id",
61
+ "account_seq"
62
+ ]
63
+ ]
63
64
  }
@@ -1,46 +1,61 @@
1
1
  {
2
2
  "name": "account_login_log",
3
- "description": "account_login_log 엔티티. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
3
+ "description": "account_login_log 엔티티. 사용자 환경에 맞게 fields를 자유롭게 확장할 수 있습니다.",
4
4
  "compress": true,
5
- "index": {
5
+ "fields": {
6
6
  "browser": {
7
+ "index": true,
7
8
  "comment": "브라우저"
8
9
  },
9
10
  "country_code": {
11
+ "index": true,
10
12
  "comment": "국가코드 iso2"
11
13
  },
12
14
  "device_id": {
15
+ "index": true,
13
16
  "comment": "디바이스 ID",
14
17
  "type": "string"
15
18
  },
16
19
  "device_type": {
20
+ "index": true,
17
21
  "comment": "장치종류"
18
22
  },
19
23
  "domain": {
24
+ "index": true,
20
25
  "comment": "도메인"
21
26
  },
22
27
  "email": {
28
+ "index": true,
29
+ "hash": true,
23
30
  "comment": "로그인 이메일"
24
31
  },
25
32
  "ip_address": {
33
+ "index": true,
34
+ "hash": true,
26
35
  "comment": "접속아이피"
27
36
  },
28
37
  "is_success": {
38
+ "index": true,
29
39
  "comment": "성공여부"
30
40
  },
31
41
  "language": {
32
42
  "comment": "언어"
33
43
  },
34
44
  "user_seq": {
45
+ "index": true,
35
46
  "comment": "사용자번호"
36
47
  },
37
48
  "auth_method": {
49
+ "index": true,
38
50
  "comment": "인증 방식",
39
- "type": ["password", "oauth", "2fa_totp", "2fa_recovery"],
51
+ "type": [
52
+ "password",
53
+ "oauth",
54
+ "2fa_totp",
55
+ "2fa_recovery"
56
+ ],
40
57
  "default": "password"
41
- }
42
- },
43
- "fields": {
58
+ },
44
59
  "location_info": {
45
60
  "comment": "위치"
46
61
  },
@@ -1,31 +1,51 @@
1
1
  {
2
2
  "name": "account_oauth",
3
- "description": "소셜 로그인 OAuth 프로바이더 연동 정보. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
3
+ "description": "소셜 로그인 OAuth 프로바이더 연동 정보. 사용자 환경에 맞게 fields를 자유롭게 확장할 수 있습니다.",
4
4
  "history": false,
5
5
  "hard_delete": true,
6
- "index": {
6
+ "fields": {
7
7
  "account_seq": {
8
+ "index": true,
8
9
  "required": true,
9
10
  "comment": "계정 seq"
10
11
  },
11
12
  "provider": {
12
- "type": ["google", "github", "naver", "kakao", "apple"],
13
+ "index": true,
14
+ "type": [
15
+ "google",
16
+ "github",
17
+ "naver",
18
+ "kakao",
19
+ "apple"
20
+ ],
13
21
  "required": true
14
22
  },
15
23
  "provider_id": {
24
+ "index": true,
16
25
  "type": "string",
17
26
  "required": true,
18
27
  "comment": "프로바이더 고유 사용자 ID"
19
28
  },
20
29
  "status": {
21
- "type": ["active", "unlinked"],
30
+ "index": true,
31
+ "type": [
32
+ "active",
33
+ "unlinked"
34
+ ],
22
35
  "default": "active"
23
- }
24
- },
25
- "fields": {
26
- "email": { "type": "email", "comment": "프로바이더에서 제공한 이메일" },
27
- "name": { "type": "string", "comment": "프로바이더에서 제공한 이름" },
28
- "profile_image": { "type": "string", "comment": "프로필 이미지 URL" },
36
+ },
37
+ "email": {
38
+ "type": "email",
39
+ "comment": "프로바이더에서 제공한 이메일"
40
+ },
41
+ "name": {
42
+ "type": "string",
43
+ "comment": "프로바이더에서 제공한 이름"
44
+ },
45
+ "profile_image": {
46
+ "type": "string",
47
+ "comment": "프로필 이미지 URL"
48
+ },
29
49
  "access_token": {
30
50
  "type": "string",
31
51
  "comment": "OAuth access token (암호화 저장)"
@@ -38,8 +58,17 @@
38
58
  "type": "string",
39
59
  "comment": "access token 만료 시각 (RFC3339)"
40
60
  },
41
- "raw": { "type": "json", "comment": "프로바이더 원본 응답 (디버깅용)" },
42
- "linked_at": { "type": "string", "comment": "연결 시각" },
43
- "unlinked_at": { "type": "string", "comment": "연결 해제 시각" }
61
+ "raw": {
62
+ "type": "json",
63
+ "comment": "프로바이더 원본 응답 (디버깅용)"
64
+ },
65
+ "linked_at": {
66
+ "type": "string",
67
+ "comment": "연결 시각"
68
+ },
69
+ "unlinked_at": {
70
+ "type": "string",
71
+ "comment": "연결 해제 시각"
72
+ }
44
73
  }
45
74
  }
@@ -1,26 +1,35 @@
1
1
  {
2
2
  "name": "api_keys",
3
+ "description": "API 키 및 HMAC 시크릿 관리. account_seq는 JWT 인증 시에만 FK. 사용자 환경에 맞게 fields를 자유롭게 확장할 수 있습니다.",
3
4
  "license_scope": false,
4
- "description": "API 키 및 HMAC 시크릿 관리. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
5
- "index": {
5
+ "fields": {
6
6
  "key_value": {
7
- "comment": "API 키 값 (해시 저장)",
7
+ "index": true,
8
+ "comment": "API 키 Hash 값",
8
9
  "required": true,
9
10
  "unique": true,
10
11
  "hash": true
11
12
  },
12
13
  "enabled": {
14
+ "index": true,
13
15
  "comment": "활성 여부",
14
16
  "type": "bool",
15
17
  "default": true
16
18
  },
17
- "user_seq": {
18
- "comment": "발급 대상 사용자 seq (nullable, user 엔티티 참조)"
19
+ "account_seq": {
20
+ "index": true,
21
+ "comment": "발급 대상 사용자 seq (nullable, JWT 인증 시 account 참조)"
22
+ },
23
+ "hmac_secret": {
24
+ "comment": "HMAC 시크릿",
25
+ "type": "text",
26
+ "nullable": true
27
+ },
28
+ "entities": {
29
+ "comment": "접근 허용 엔티티 목록 (쉼표구분)",
30
+ "type": "text",
31
+ "nullable": true
19
32
  }
20
33
  },
21
- "types": {
22
- "hmac_secret": "text",
23
- "entities": "text"
24
- },
25
34
  "hard_delete": true
26
35
  }
@@ -1,21 +1,29 @@
1
1
  {
2
2
  "name": "identity_verification",
3
- "description": "휴대폰 본인인증 요청 및 결과 저장. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
3
+ "description": "휴대폰 본인인증 요청 및 결과 저장. 사용자 환경에 맞게 fields를 자유롭게 확장할 수 있습니다.",
4
4
  "history": false,
5
5
  "hard_delete": false,
6
6
  "compress": true,
7
- "index": {
7
+ "fields": {
8
8
  "request_id": {
9
+ "index": true,
9
10
  "type": "string",
10
11
  "required": true,
11
12
  "unique": true,
12
13
  "comment": "인증 요청 고유 ID (32바이트 hex)"
13
14
  },
14
15
  "status": {
15
- "type": ["pending", "verified", "failed", "expired"],
16
+ "index": true,
17
+ "type": [
18
+ "pending",
19
+ "verified",
20
+ "failed",
21
+ "expired"
22
+ ],
16
23
  "default": "pending"
17
24
  },
18
25
  "purpose": {
26
+ "index": true,
19
27
  "type": [
20
28
  "signup",
21
29
  "find_account",
@@ -26,11 +34,14 @@
26
34
  "required": true
27
35
  },
28
36
  "provider": {
29
- "type": ["nice", "kmc", "danal"],
37
+ "index": true,
38
+ "type": [
39
+ "nice",
40
+ "kmc",
41
+ "danal"
42
+ ],
30
43
  "required": true
31
- }
32
- },
33
- "fields": {
44
+ },
34
45
  "ci_hash": {
35
46
  "type": "string",
36
47
  "comment": "CI의 SHA-256 해시 (중복 조회용)"