@things-factory/auth-base 10.1.44 → 10.1.47

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/auth-base",
3
- "version": "10.1.44",
3
+ "version": "10.1.47",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -34,9 +34,9 @@
34
34
  "@reduxjs/toolkit": "^2.2.5",
35
35
  "@simplewebauthn/browser": "^13.0.0",
36
36
  "@simplewebauthn/server": "^13.0.0",
37
- "@things-factory/email-base": "^10.1.44",
37
+ "@things-factory/email-base": "^10.1.47",
38
38
  "@things-factory/env": "^10.1.20",
39
- "@things-factory/shell": "^10.1.44",
39
+ "@things-factory/shell": "^10.1.47",
40
40
  "@things-factory/utils": "^10.1.20",
41
41
  "@types/webappsec-credential-management": "^0.6.9",
42
42
  "jsonwebtoken": "^9.0.0",
@@ -48,5 +48,5 @@
48
48
  "passport-jwt": "^4.0.0",
49
49
  "passport-local": "^1.0.0"
50
50
  },
51
- "gitHead": "7c95c4e75e155e51c714409e865d96f317232c23"
51
+ "gitHead": "185f20d7d9a15715a0ee2757a6a8189ec36cfb9d"
52
52
  }
@@ -0,0 +1,125 @@
1
+ /**
2
+ * What a role lacks against the template of its name - against a real database (ADR-0075 decision 1).
3
+ *
4
+ * A template is a seed and nothing pushes its later grants into roles already standing. When
5
+ * operato-plant's templates gained ai-assistant, the roles in miratek stayed without it and only
6
+ * plant's security runner noticed. The role screen now shows the gap and the administrator adds
7
+ * it; these are the facts that screen stands on.
8
+ */
9
+
10
+ import { closeAuthDatabase, Domain, getRepository, openAuthDatabase, resetAuthDatabase, authDataSource } from './db'
11
+ import { loadCompiled } from './compiled'
12
+
13
+ const { Role } = loadCompiled('service/role/role')
14
+ const { Privilege } = loadCompiled('service/privilege/privilege')
15
+ const { User } = loadCompiled('service/user/user')
16
+ const { RoleTemplateMutation } = loadCompiled('service/role-template/role-template-mutation')
17
+ const { RoleTemplateGapResolver } = loadCompiled('service/role-template/role-template-gap-resolver')
18
+ const { registerRoleTemplate } = loadCompiled('service/role-template/role-template')
19
+
20
+ const mutation = new RoleTemplateMutation()
21
+ const gapOf = (role: any) => new RoleTemplateGapResolver().templateGap(role)
22
+
23
+ let domain: any
24
+ let actor: any
25
+
26
+ const context = () => ({ state: { domain, user: actor, tx: authDataSource().manager } }) as any
27
+
28
+ /** The template as it stood when the role was made, then as it stands after it gained a door. */
29
+ function declareTemplate(axes: string[], extra: { category: string; axes: string[] }[] = []) {
30
+ ;(process as any)['ROLE_TEMPLATES'] = {}
31
+ registerRoleTemplate({ id: 'plant.qi', name: 'QUALITY-INSPECTOR', grants: [{ category: 'board', axes }, ...extra] })
32
+ }
33
+
34
+ beforeAll(async () => {
35
+ await openAuthDatabase()
36
+ })
37
+
38
+ afterAll(async () => {
39
+ await closeAuthDatabase()
40
+ })
41
+
42
+ beforeEach(async () => {
43
+ await resetAuthDatabase()
44
+
45
+ const saved = await getRepository(Domain).save({ name: 'Plant A', subdomain: 'plant-a' })
46
+ domain = await getRepository(Domain).findOneBy({ id: saved.id })
47
+
48
+ await getRepository(Privilege).save({ name: 'query', category: 'board' })
49
+ await getRepository(Privilege).save({ name: 'mutation', category: 'board' })
50
+ ;(process as any).PRIVILEGES = {
51
+ 'board query': ['board', 'query'],
52
+ 'board mutation': ['board', 'mutation']
53
+ }
54
+
55
+ actor = await getRepository(User).save({
56
+ username: 'admin',
57
+ email: 'admin@example.com',
58
+ name: 'Admin',
59
+ salt: User.generateSalt(),
60
+ status: 'activated',
61
+ domains: [domain]
62
+ })
63
+ })
64
+
65
+ describe('the gap between a role and its template', () => {
66
+ it('is zero for a role made from the template as it stands', async () => {
67
+ declareTemplate(['query'])
68
+ const role = await mutation.createRoleFromTemplate('plant.qi', undefined, context())
69
+
70
+ expect(await gapOf(role)).toEqual({
71
+ templateId: 'plant.qi',
72
+ templateName: 'QUALITY-INSPECTOR',
73
+ missing: [],
74
+ missingCount: 0
75
+ })
76
+ })
77
+
78
+ it('★ names what the template gained after the role was made', async () => {
79
+ declareTemplate(['query'])
80
+ const role = await mutation.createRoleFromTemplate('plant.qi', undefined, context())
81
+
82
+ declareTemplate(['query', 'mutation'])
83
+
84
+ const gap = await gapOf(role)
85
+ expect(gap.missingCount).toBe(1)
86
+ expect(gap.missing).toEqual([{ category: 'board', axes: ['mutation'] }])
87
+ })
88
+
89
+ it('★ closes when the administrator adds it - the same top-up the template button runs', async () => {
90
+ declareTemplate(['query'])
91
+ const role = await mutation.createRoleFromTemplate('plant.qi', undefined, context())
92
+ declareTemplate(['query', 'mutation'])
93
+
94
+ await mutation.createRoleFromTemplate('plant.qi', 'QUALITY-INSPECTOR', context())
95
+
96
+ expect((await gapOf(role)).missingCount).toBe(0)
97
+ })
98
+
99
+ it('★ does not count what this installation does not declare', async () => {
100
+ declareTemplate(['query'], [{ category: 'order', axes: ['query'] }])
101
+ const role = await mutation.createRoleFromTemplate('plant.qi', undefined, context())
102
+
103
+ expect((await gapOf(role)).missingCount).toBe(0)
104
+ })
105
+
106
+ it('★ is null for a role no template names - a renamed role belongs to its administrator', async () => {
107
+ declareTemplate(['query'])
108
+ const role = await mutation.createRoleFromTemplate('plant.qi', 'NIGHT-INSPECTOR', context())
109
+
110
+ expect(await gapOf(role)).toBeNull()
111
+ })
112
+
113
+ it('does not take away what the administrator added beyond the template', async () => {
114
+ declareTemplate(['query'])
115
+ const role = await mutation.createRoleFromTemplate('plant.qi', undefined, context())
116
+ const stored = await getRepository(Role).findOne({ where: { id: role.id }, relations: ['privileges'] })
117
+ stored.privileges = [
118
+ ...stored.privileges,
119
+ await getRepository(Privilege).findOneBy({ category: 'board', name: 'mutation' })
120
+ ]
121
+ await getRepository(Role).save(stored)
122
+
123
+ expect((await gapOf(role)).missingCount).toBe(0)
124
+ })
125
+ })
@@ -0,0 +1,134 @@
1
+ /**
2
+ * `User.roles` — 사용자 목록이 한 사람마다 드는 역할 필드.
3
+ *
4
+ * `userRoles` · `myRoles` 와 같은 결함(`role-query.ts` 의 ③)을 갖고 있던 세 번째 자리다.
5
+ * 사용자를 `relations: ['roles']` 로 읽어 **가진 역할 전부**를 돌려줬다. 도메인 A 와 B 에
6
+ * 함께 속한 사람을 A 의 `users { items { roles { name } } }` 로 읽으면 B 의 역할 이름이 나왔다.
7
+ *
8
+ * 범위는 이 도메인이 부여할 수 있는 것이다 — 내 도메인, 부모 1단, 파트너가 이 도메인에 grant 한
9
+ * 역할. 셋째는 사용자 상세가 체크 상태를 이 필드로 채우기 때문에 빠지면 안 된다: 빠지면 저장할
10
+ * 때 파트너 역할이 떼어진다.
11
+ */
12
+
13
+ import { closeAuthDatabase, Domain, getRepository, openAuthDatabase, resetAuthDatabase } from './db'
14
+ import { loadCompiled } from './compiled'
15
+
16
+ const { Role } = loadCompiled('service/role/role')
17
+ const { GrantedRole } = loadCompiled('service/granted-role/granted-role')
18
+ const { User } = loadCompiled('service/user/user')
19
+ const { UserQuery } = loadCompiled('service/user/user-query')
20
+
21
+ const query = new UserQuery()
22
+
23
+ let parent: any
24
+ let child: any
25
+ let stranger: any
26
+
27
+ /** `parentId` 는 `@RelationId` 라 저장소로 읽은 도메인에만 실린다. */
28
+ async function loadDomain(id: string) {
29
+ return await getRepository(Domain).findOneBy({ id })
30
+ }
31
+
32
+ /** 필드 리졸버 본문을 직접 부른다 — 목록 질의가 `context.state.domain` 을 채운 상태다. */
33
+ async function rolesOf(user: any, domain: any) {
34
+ const roles = await query.roles(user, { state: { domain } } as any)
35
+ return roles.map((role: any) => role.name).sort()
36
+ }
37
+
38
+ async function makeUser(domains: any[], roles: any[]) {
39
+ const tag = Math.random().toString(36).slice(2, 8)
40
+ return await getRepository(User).save({
41
+ username: `u-${tag}`,
42
+ email: `u-${tag}@example.com`,
43
+ name: 'Kim',
44
+ salt: User.generateSalt(),
45
+ status: 'activated',
46
+ domains,
47
+ roles
48
+ })
49
+ }
50
+
51
+ beforeAll(async () => {
52
+ await openAuthDatabase()
53
+ })
54
+
55
+ afterAll(async () => {
56
+ await closeAuthDatabase()
57
+ })
58
+
59
+ beforeEach(async () => {
60
+ await resetAuthDatabase()
61
+
62
+ const domainRepository = getRepository(Domain)
63
+
64
+ const savedParent = await domainRepository.save({ name: 'HQ', subdomain: 'hq' })
65
+ const savedChild = await domainRepository.save({ name: 'Plant A', subdomain: 'plant-a', parent: savedParent })
66
+ const savedStranger = await domainRepository.save({ name: 'Other', subdomain: 'other' })
67
+
68
+ parent = await loadDomain(savedParent.id)
69
+ child = await loadDomain(savedChild.id)
70
+ stranger = await loadDomain(savedStranger.id)
71
+ })
72
+
73
+ describe('두 도메인에 속한 사람', () => {
74
+ it('A 에서 읽으면 A 의 역할만 나온다 — B 의 역할 이름이 새지 않는다', async () => {
75
+ const mine = await getRepository(Role).save({ name: 'operator', domain: child })
76
+ const theirs = await getRepository(Role).save({ name: 'auditor', domain: stranger })
77
+ const user = await makeUser([child, stranger], [mine, theirs])
78
+
79
+ expect(await rolesOf(user, child)).toEqual(['operator'])
80
+ })
81
+
82
+ it('B 에서 읽으면 B 의 역할만 나온다', async () => {
83
+ const mine = await getRepository(Role).save({ name: 'operator', domain: child })
84
+ const theirs = await getRepository(Role).save({ name: 'auditor', domain: stranger })
85
+ const user = await makeUser([child, stranger], [mine, theirs])
86
+
87
+ expect(await rolesOf(user, stranger)).toEqual(['auditor'])
88
+ })
89
+ })
90
+
91
+ describe('상속 범위', () => {
92
+ it('부모 도메인의 역할은 나온다 — 자식 도메인에서 부여할 수 있는 범위다', async () => {
93
+ const shared = await getRepository(Role).save({ name: 'shared', domain: parent })
94
+ const local = await getRepository(Role).save({ name: 'local', domain: child })
95
+ const user = await makeUser([child], [shared, local])
96
+
97
+ expect(await rolesOf(user, child)).toEqual(['local', 'shared'])
98
+ })
99
+
100
+ it('부모에서 읽으면 자식 도메인의 역할은 나오지 않는다 — 상속은 위로 한 단이다', async () => {
101
+ const shared = await getRepository(Role).save({ name: 'shared', domain: parent })
102
+ const local = await getRepository(Role).save({ name: 'local', domain: child })
103
+ const user = await makeUser([parent, child], [shared, local])
104
+
105
+ expect(await rolesOf(user, parent)).toEqual(['shared'])
106
+ })
107
+ })
108
+
109
+ describe('파트너가 grant 한 역할', () => {
110
+ it('이 도메인에 grant 된 파트너 역할은 나온다 — 빠지면 사용자 상세가 저장할 때 뗀다', async () => {
111
+ const partnerRole = await getRepository(Role).save({ name: 'partner-viewer', domain: stranger })
112
+ await getRepository(GrantedRole).save({ role: partnerRole, domain: child })
113
+ const user = await makeUser([child], [partnerRole])
114
+
115
+ expect(await rolesOf(user, child)).toEqual(['partner-viewer'])
116
+ })
117
+
118
+ it('다른 도메인에 grant 된 것은 나오지 않는다 — grant 는 받은 도메인에서만 보인다', async () => {
119
+ const partnerRole = await getRepository(Role).save({ name: 'partner-viewer', domain: stranger })
120
+ await getRepository(GrantedRole).save({ role: partnerRole, domain: child })
121
+ const user = await makeUser([child, parent], [partnerRole])
122
+
123
+ expect(await rolesOf(user, parent)).toEqual([])
124
+ })
125
+ })
126
+
127
+ describe('역할이 없는 사람', () => {
128
+ it('빈 목록을 준다', async () => {
129
+ await getRepository(Role).save({ name: 'operator', domain: child })
130
+ const user = await makeUser([child], [])
131
+
132
+ expect(await rolesOf(user, child)).toEqual([])
133
+ })
134
+ })
@@ -19,7 +19,7 @@
19
19
  "error.user credential not found": "user credential not found. You need to register device to use biometric authentication.",
20
20
  "error.user credential registration failed": "registration did not complete. the device was cancelled, or the server could not be reached.",
21
21
  "error.user credential registration not allowed": "this device could not be registered. the registration timed out, or the credential is already registered.",
22
- "error.user duplicated.": "there is a user account using same email or user ID.",
22
+ "error.user duplicated": "there is a user account using same email or user ID.",
23
23
  "error.user not activated": "user is not activated",
24
24
  "error.user not found": "user not found",
25
25
  "error.user or verification token not found": "user or verification token not found",
@@ -27,12 +27,8 @@
27
27
  "error.username already exists": "username already used by another user",
28
28
  "error.x is not a member of y": "{x} is not a member of {y}",
29
29
  "error.x privilege required": "unauthorized! {x} privilege required",
30
- "field.active": "active",
31
30
  "field.appliance_id": "appliance id",
32
31
  "field.brand": "brand",
33
- "field.category": "category",
34
- "field.email": "email address",
35
- "field.model": "model",
36
32
  "field.password": "password",
37
33
  "field.privileges": "privileges",
38
34
  "field.token": "token",
@@ -225,5 +221,6 @@
225
221
  "text.user credential registered successfully": "device registration has been successfully completed. You can now use biometric authentication.",
226
222
  "text.user inactivated successfully": "user inactivated successfully",
227
223
  "text.user registered successfully": "user registered successfully. find your email to activate account",
228
- "text.verification email sent": "verification email sent"
224
+ "text.verification email sent": "verification email sent",
225
+ "privilege.description": "{name} {category}"
229
226
  }
@@ -19,7 +19,7 @@
19
19
  "error.user credential not found": "ユーザー資格情報が見つかりません. 生体認証を使用するにはデバイスを登録する必要があります.",
20
20
  "error.user credential registration failed": "登録を完了できませんでした。デバイスでキャンセルされたか、サーバーに到達できませんでした。",
21
21
  "error.user credential registration not allowed": "このデバイスは登録できませんでした。登録がタイムアウトしたか、すでに登録済みです。",
22
- "error.user duplicated.": "ユーザーが重複しています.",
22
+ "error.user duplicated": "同じメールアドレスまたはユーザーIDで登録されたアカウントがすでにあります。",
23
23
  "error.user not activated": "ユーザーがアクティブ化されていません.",
24
24
  "error.user not found": "ユーザーが存在しません.",
25
25
  "error.user or verification token not found": "ユーザーまたは確認トークンが見つかりません.",
@@ -27,12 +27,8 @@
27
27
  "error.username already exists": "ユーザー名はすでに他のユーザーによって使用されています.",
28
28
  "error.x is not a member of y": "{x}は{y}のメンバーではありません.",
29
29
  "error.x privilege required": "権限がありません。{x} 権限が必要です。",
30
- "field.active": "アクティブ",
31
30
  "field.appliance_id": "器具ID",
32
31
  "field.brand": "ブランド",
33
- "field.category": "カテゴリー",
34
- "field.email": "メール",
35
- "field.model": "モデル",
36
32
  "field.password": "パスワード",
37
33
  "field.privileges": "権限",
38
34
  "field.token": "トークン",
@@ -65,5 +61,166 @@
65
61
  "text.user credential registered successfully": "デバイスの登録が正常に完了しました。今後は生体認証を使用できます。",
66
62
  "text.user inactivated successfully": "ユーザーが正常に非アクティブ化されました.",
67
63
  "text.user registered successfully": "ユーザーが正常に登録されました. 確認メールでアカウントを有効にしてください.",
68
- "text.verification email sent": "確認メールを送りました."
64
+ "text.verification email sent": "確認メールを送りました.",
65
+ "privilege.allows.accounting.mutation": "伝票を起票・修正・締めできます。",
66
+ "privilege.allows.accounting.query": "伝票と勘定残高を閲覧できます。",
67
+ "privilege.allows.activity-instance.mutation": "業務を開始・引き継ぎ・完了・中断できます。",
68
+ "privilege.allows.activity-instance.query": "進行中または完了した業務を閲覧できます。",
69
+ "privilege.allows.activity.mutation": "業務活動の種類と手順を作成・修正できます。",
70
+ "privilege.allows.ai-assistant.mutation": "AIアシスタントに作業を任せられます。",
71
+ "privilege.allows.ai-assistant.query": "AIアシスタントとの会話を閲覧できます。",
72
+ "privilege.allows.ai-inference.query": "学習済みモデルの推論結果を閲覧できます。",
73
+ "privilege.allows.attachment.mutation": "ファイルをアップロード・削除できます。",
74
+ "privilege.allows.attachment.query": "アップロードされたファイルを開けます。",
75
+ "privilege.allows.bizplace.mutation": "事業所を登録・修正できます。",
76
+ "privilege.allows.bizplace.query": "事業所とその住所を閲覧できます。",
77
+ "privilege.allows.board-ai.mutation": "AIにボードを作成させられます。",
78
+ "privilege.allows.board-ai.query": "AIが作成したボードの下書きを閲覧できます。",
79
+ "privilege.allows.board-import.mutation": "外部ファイルからボードを取り込めます。",
80
+ "privilege.allows.board-import.query": "ボードの取り込み履歴を閲覧できます。",
81
+ "privilege.allows.board-template.mutation": "ボードテンプレートを作成・修正できます。",
82
+ "privilege.allows.board-template.query": "ボードテンプレートを閲覧できます。",
83
+ "privilege.allows.board.mutation": "ボードを作成・修正・削除できます。",
84
+ "privilege.allows.board.query": "ボードを開いて閲覧できます。",
85
+ "privilege.allows.company.mutation": "会社情報を修正できます。",
86
+ "privilege.allows.company.query": "会社情報を閲覧できます。",
87
+ "privilege.allows.connection.mutation": "接続を作成・修正・切断できます。接続情報はここに保存されます。",
88
+ "privilege.allows.connection.query": "他システムとの接続とその状態を閲覧できます。",
89
+ "privilege.allows.contact_point.mutation": "連絡先を登録・修正できます。",
90
+ "privilege.allows.contact_point.query": "取引先担当者の連絡先を閲覧できます。",
91
+ "privilege.allows.data-archive.mutation": "データをアーカイブに移し、復元できます。",
92
+ "privilege.allows.data-archive.query": "アーカイブに移したデータを閲覧できます。",
93
+ "privilege.allows.data-ooc.mutation": "逸脱と判定された値を処置し、その理由を記録できます。",
94
+ "privilege.allows.data-ooc.query": "管理限界を外れた値を閲覧できます。",
95
+ "privilege.allows.data-sample.mutation": "サンプルを登録し、測定値を入力できます。",
96
+ "privilege.allows.data-sample.query": "採取したサンプルとその測定値を閲覧できます。",
97
+ "privilege.allows.data-set-history.query": "データセットの構成がいつどう変わったかを閲覧できます。",
98
+ "privilege.allows.data-set.mutation": "データセットを作成し、項目を修正できます。",
99
+ "privilege.allows.data-set.query": "データセットとその項目構成を閲覧できます。",
100
+ "privilege.allows.data-summary.query": "期間と項目で集計した値を閲覧できます。",
101
+ "privilege.allows.department.mutation": "部署を作成・修正・移動できます。",
102
+ "privilege.allows.department.query": "部署とその所属を閲覧できます。",
103
+ "privilege.allows.disposition.mutation": "不適合品の処置を判断し、承認を申請できます。廃棄・手直しはここで決まります。",
104
+ "privilege.allows.disposition.query": "不適合となったものがどう処置されたかを閲覧できます。",
105
+ "privilege.allows.employee.mutation": "従業員を登録し、所属を修正できます。",
106
+ "privilege.allows.employee.query": "従業員名簿と所属を閲覧できます。",
107
+ "privilege.allows.env-var.mutation": "環境変数を追加・修正できます。サーバーの動作が変わります。",
108
+ "privilege.allows.env-var.query": "サーバー環境変数の名前と値を閲覧できます。",
109
+ "privilege.allows.equipment-state.mutation": "設備の状態を変更し、停止理由を記録できます。",
110
+ "privilege.allows.equipment-state.query": "設備が稼働中か停止中かを閲覧できます。",
111
+ "privilege.allows.figure.mutation": "Figureモデルを作成・修正できます。",
112
+ "privilege.allows.figure.query": "Figureモデルとその構成を閲覧できます。",
113
+ "privilege.allows.inspection.mutation": "検査結果を入力し、合否を判定できます。",
114
+ "privilege.allows.inspection.query": "検査基準と検査結果を閲覧できます。",
115
+ "privilege.allows.job-order.mutation": "作業指示を発行・修正・完了できます。",
116
+ "privilege.allows.job-order.query": "作業指示とその進捗を閲覧できます。",
117
+ "privilege.allows.kpi.mutation": "指標を作成し、目標値と計算式を修正できます。",
118
+ "privilege.allows.kpi.query": "成果指標とその目標達成度を閲覧できます。",
119
+ "privilege.allows.label-studio.mutation": "Label Studioとの接続を設定し、作業を送信できます。",
120
+ "privilege.allows.label-studio.query": "Label Studioとやり取りした作業を閲覧できます。",
121
+ "privilege.allows.labeling.mutation": "ラベルを付与・修正できます。",
122
+ "privilege.allows.labeling.query": "ラベリング作業とその結果を閲覧できます。",
123
+ "privilege.allows.maintenance.mutation": "保全計画を立て、実施結果を登録できます。",
124
+ "privilege.allows.maintenance.query": "保全計画と実施履歴を閲覧できます。",
125
+ "privilege.allows.menu.mutation": "メニューの構成と順序を修正できます。他の人に表示される画面一覧が変わります。",
126
+ "privilege.allows.mes-outbox.mutation": "送信先を設定し、失敗したものを再送信できます。",
127
+ "privilege.allows.mes-outbox.query": "外部システムへの送信が滞っていないかを閲覧できます。",
128
+ "privilege.allows.mlflow.mutation": "MLflowとの接続を設定し、モデルを登録できます。",
129
+ "privilege.allows.mlflow.query": "MLflowに記録された実験とモデルを閲覧できます。",
130
+ "privilege.allows.mlops.mutation": "パイプラインを作成し、学習とデプロイを実行できます。",
131
+ "privilege.allows.mlops.query": "学習・デプロイパイプラインの実行履歴を閲覧できます。",
132
+ "privilege.allows.ops-master.mutation": "運用基準を修正できます。日程計算はこの値に従います。",
133
+ "privilege.allows.ops-master.query": "稼働日・非稼働日などの運用基準を閲覧できます。",
134
+ "privilege.allows.order.mutation": "注文を受け付け・修正・取消できます。",
135
+ "privilege.allows.order.query": "注文とその品目を閲覧できます。",
136
+ "privilege.allows.organization.mutation": "組織構造を修正できます。",
137
+ "privilege.allows.organization.query": "組織構造を閲覧できます。",
138
+ "privilege.allows.partner.mutation": "協力会社を登録し、連携を解除できます。",
139
+ "privilege.allows.partner.query": "協力会社とその$t(term.domain)の連携を閲覧できます。",
140
+ "privilege.allows.privilege.query": "このシステムで定義された権限一覧を閲覧できます。",
141
+ "privilege.allows.process-instance.query": "プロセスがどこまで進んだかを閲覧できます。",
142
+ "privilege.allows.process.mutation": "プロセスを作成し、ステップを修正できます。",
143
+ "privilege.allows.process.query": "プロセス定義とそのステップを閲覧できます。",
144
+ "privilege.allows.production-report.mutation": "生産実績を登録し、訂正を行えます。",
145
+ "privilege.allows.production-report.query": "生産実績とその訂正履歴を閲覧できます。",
146
+ "privilege.allows.scenario.mutation": "シナリオを作成・実行・停止できます。",
147
+ "privilege.allows.scenario.query": "連携シナリオとその実行履歴を閲覧できます。",
148
+ "privilege.allows.schedule.mutation": "日程を組み、移動できます。",
149
+ "privilege.allows.schedule.query": "生産日程を閲覧できます。",
150
+ "privilege.allows.security.mutation": "セキュリティ設定を修正できます。誰がアクセスできるかが変わります。",
151
+ "privilege.allows.security.query": "アクセス制限などのセキュリティ設定を閲覧できます。",
152
+ "privilege.allows.setting.mutation": "基本設定値を修正できます。",
153
+ "privilege.allows.setting.query": "システムの基本設定値を閲覧できます。",
154
+ "privilege.allows.state-register.mutation": "その記録を修正できます。次の連携はここから再開します。",
155
+ "privilege.allows.state-register.query": "連携がどこまで処理したかの記録を閲覧できます。",
156
+ "privilege.allows.station.mutation": "作業ステーションを割り当て、作業指示を送れます。",
157
+ "privilege.allows.station.query": "作業ステーションと割り当てられた人を閲覧できます。",
158
+ "privilege.allows.terminology.mutation": "画面に表示される用語とその翻訳を修正できます。",
159
+ "privilege.allows.tutorial.mutation": "チュートリアルを作成・修正できます。",
160
+ "privilege.allows.twin.mutation": "ツインを作成・修正・実行・停止できます。",
161
+ "privilege.allows.twin.query": "ツインとその現場構成を閲覧できます。",
162
+ "privilege.allows.user.mutation": "ユーザーを招待し、ロールを付与し、ロックできます。誰が何をできるかはここで決まります。",
163
+ "privilege.allows.user.query": "ユーザー名簿と各自のロールを閲覧できます。",
164
+ "privilege.allows.webhook.mutation": "Webhookを作成し、送信先アドレスを修正できます。",
165
+ "privilege.allows.webhook.query": "Webhook設定と送信履歴を閲覧できます。",
166
+ "privilege.allows.work-shift.mutation": "交代勤務表を作成・修正できます。",
167
+ "privilege.allows.worker.mutation": "作業者を登録し、配置を修正できます。",
168
+ "privilege.allows.worker.query": "作業者名簿と配置を閲覧できます。",
169
+ "privilege.category.accounting": "会計",
170
+ "privilege.category.activity": "業務活動定義",
171
+ "privilege.category.activity-instance": "進行中の業務",
172
+ "privilege.category.ai-assistant": "AIアシスタント",
173
+ "privilege.category.ai-inference": "AI推論",
174
+ "privilege.category.attachment": "添付ファイル",
175
+ "privilege.category.bizplace": "事業所",
176
+ "privilege.category.board": "ボード",
177
+ "privilege.category.board-ai": "ボードAI",
178
+ "privilege.category.board-import": "ボード取り込み",
179
+ "privilege.category.board-template": "ボードテンプレート",
180
+ "privilege.category.company": "会社",
181
+ "privilege.category.connection": "システム接続",
182
+ "privilege.category.contact_point": "連絡先",
183
+ "privilege.category.data-archive": "データアーカイブ",
184
+ "privilege.category.data-ooc": "管理逸脱データ",
185
+ "privilege.category.data-sample": "データサンプル",
186
+ "privilege.category.data-set": "データセット",
187
+ "privilege.category.data-set-history": "データセット変更履歴",
188
+ "privilege.category.data-summary": "データ集計",
189
+ "privilege.category.department": "部署",
190
+ "privilege.category.disposition": "不適合品処置",
191
+ "privilege.category.employee": "従業員",
192
+ "privilege.category.env-var": "環境変数",
193
+ "privilege.category.equipment-state": "設備状態",
194
+ "privilege.category.figure": "Figureモデル",
195
+ "privilege.category.inspection": "検査",
196
+ "privilege.category.job-order": "作業指示",
197
+ "privilege.category.kpi": "成果指標",
198
+ "privilege.category.label-studio": "Label Studio接続",
199
+ "privilege.category.labeling": "データラベリング",
200
+ "privilege.category.maintenance": "設備保全",
201
+ "privilege.category.menu": "メニュー",
202
+ "privilege.category.mes-outbox": "MES送信ボックス",
203
+ "privilege.category.mlflow": "MLflow接続",
204
+ "privilege.category.mlops": "MLOps",
205
+ "privilege.category.ops-master": "運用基準情報",
206
+ "privilege.category.order": "注文",
207
+ "privilege.category.organization": "組織",
208
+ "privilege.category.partner": "協力会社",
209
+ "privilege.category.privilege": "権限一覧",
210
+ "privilege.category.process": "プロセス定義",
211
+ "privilege.category.process-instance": "プロセス実行",
212
+ "privilege.category.production-report": "生産実績",
213
+ "privilege.category.scenario": "連携シナリオ",
214
+ "privilege.category.schedule": "生産日程",
215
+ "privilege.category.security": "セキュリティ",
216
+ "privilege.category.setting": "基本設定",
217
+ "privilege.category.state-register": "連携状態レジスタ",
218
+ "privilege.category.station": "作業ステーション",
219
+ "privilege.category.terminology": "用語",
220
+ "privilege.category.tutorial": "チュートリアル",
221
+ "privilege.category.twin": "デジタルツイン",
222
+ "privilege.category.user": "ユーザー",
223
+ "privilege.category.webhook": "Webhook",
224
+ "privilege.category.work-shift": "勤務交代",
225
+ "privilege.category.worker": "作業者"
69
226
  }
@@ -27,12 +27,8 @@
27
27
  "error.username already exists": "사용자 아이디가 이미 사용되고 있습니다.",
28
28
  "error.x is not a member of y": "{x}은(는) {y}의 멤버가 아닙니다.",
29
29
  "error.x privilege required": "권한이 없습니다. {x} 권한이 필요합니다.",
30
- "field.active": "활성화",
31
30
  "field.appliance_id": "기구 아이디",
32
31
  "field.brand": "브랜드",
33
- "field.category": "카테고리",
34
- "field.email": "이메일",
35
- "field.model": "모델",
36
32
  "field.password": "비밀번호",
37
33
  "field.privileges": "권한",
38
34
  "field.token": "토큰",
@@ -225,5 +221,6 @@
225
221
  "text.user credential registered successfully": "기기 등록이 성공적으로 완료되었습니다. 이제 바이오메트릭 인증을 사용할 수 있습니다.",
226
222
  "text.user inactivated successfully": "사용자가 성공적으로 비활성화되었습니다.",
227
223
  "text.user registered successfully": "사용자가 성공적으로 등록되었습니다. 확인 이메일을 통해서 계정을 활성화하시기 바랍니다.",
228
- "text.verification email sent": "확인 이메일을 보냈습니다."
224
+ "text.verification email sent": "확인 이메일을 보냈습니다.",
225
+ "privilege.description": "{category} {name}"
229
226
  }