@things-factory/integration-label-studio 9.1.19

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 (152) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/EXTERNAL_DATA_SOURCING.md +484 -0
  3. package/IMPLEMENTATION_GUIDE.md +469 -0
  4. package/INTEGRATION.md +279 -0
  5. package/README.md +1014 -0
  6. package/SETUP_GUIDE.md +577 -0
  7. package/TEST_GUIDE.md +387 -0
  8. package/UI_CUSTOMIZATION.md +395 -0
  9. package/USER_SYNC_GUIDE.md +514 -0
  10. package/client/bootstrap.ts +1 -0
  11. package/client/index.ts +1 -0
  12. package/client/label-studio-label-page.ts +52 -0
  13. package/client/label-studio-project-create.ts +216 -0
  14. package/client/label-studio-project-list.ts +214 -0
  15. package/client/label-studio-wrapper.ts +294 -0
  16. package/client/route.ts +15 -0
  17. package/client/tsconfig.json +13 -0
  18. package/config/config.development.js +124 -0
  19. package/config/config.production.js +182 -0
  20. package/dist-client/bootstrap.d.ts +1 -0
  21. package/dist-client/bootstrap.js +2 -0
  22. package/dist-client/bootstrap.js.map +1 -0
  23. package/dist-client/index.d.ts +1 -0
  24. package/dist-client/index.js +2 -0
  25. package/dist-client/index.js.map +1 -0
  26. package/dist-client/label-studio-label-page.d.ts +8 -0
  27. package/dist-client/label-studio-label-page.js +54 -0
  28. package/dist-client/label-studio-label-page.js.map +1 -0
  29. package/dist-client/label-studio-project-create.d.ts +16 -0
  30. package/dist-client/label-studio-project-create.js +235 -0
  31. package/dist-client/label-studio-project-create.js.map +1 -0
  32. package/dist-client/label-studio-project-list.d.ts +16 -0
  33. package/dist-client/label-studio-project-list.js +222 -0
  34. package/dist-client/label-studio-project-list.js.map +1 -0
  35. package/dist-client/label-studio-wrapper.d.ts +57 -0
  36. package/dist-client/label-studio-wrapper.js +304 -0
  37. package/dist-client/label-studio-wrapper.js.map +1 -0
  38. package/dist-client/route.d.ts +1 -0
  39. package/dist-client/route.js +14 -0
  40. package/dist-client/route.js.map +1 -0
  41. package/dist-client/tsconfig.tsbuildinfo +1 -0
  42. package/dist-server/controller/label-studio-role-mapper.d.ts +35 -0
  43. package/dist-server/controller/label-studio-role-mapper.js +65 -0
  44. package/dist-server/controller/label-studio-role-mapper.js.map +1 -0
  45. package/dist-server/controller/user-provisioning-service.d.ts +66 -0
  46. package/dist-server/controller/user-provisioning-service.js +264 -0
  47. package/dist-server/controller/user-provisioning-service.js.map +1 -0
  48. package/dist-server/index.d.ts +7 -0
  49. package/dist-server/index.js +19 -0
  50. package/dist-server/index.js.map +1 -0
  51. package/dist-server/route/label-studio-sso.d.ts +2 -0
  52. package/dist-server/route/label-studio-sso.js +156 -0
  53. package/dist-server/route/label-studio-sso.js.map +1 -0
  54. package/dist-server/route/webhook.d.ts +65 -0
  55. package/dist-server/route/webhook.js +248 -0
  56. package/dist-server/route/webhook.js.map +1 -0
  57. package/dist-server/route.d.ts +1 -0
  58. package/dist-server/route.js +21 -0
  59. package/dist-server/route.js.map +1 -0
  60. package/dist-server/service/ai-prediction-service.d.ts +27 -0
  61. package/dist-server/service/ai-prediction-service.js +222 -0
  62. package/dist-server/service/ai-prediction-service.js.map +1 -0
  63. package/dist-server/service/dataset-labeling-integration.d.ts +44 -0
  64. package/dist-server/service/dataset-labeling-integration.js +512 -0
  65. package/dist-server/service/dataset-labeling-integration.js.map +1 -0
  66. package/dist-server/service/external-data-source-service.d.ts +78 -0
  67. package/dist-server/service/external-data-source-service.js +415 -0
  68. package/dist-server/service/external-data-source-service.js.map +1 -0
  69. package/dist-server/service/index.d.ts +12 -0
  70. package/dist-server/service/index.js +27 -0
  71. package/dist-server/service/index.js.map +1 -0
  72. package/dist-server/service/label-studio-sso-service.d.ts +38 -0
  73. package/dist-server/service/label-studio-sso-service.js +98 -0
  74. package/dist-server/service/label-studio-sso-service.js.map +1 -0
  75. package/dist-server/service/ml/ml-backend-service.d.ts +23 -0
  76. package/dist-server/service/ml/ml-backend-service.js +153 -0
  77. package/dist-server/service/ml/ml-backend-service.js.map +1 -0
  78. package/dist-server/service/prediction/prediction-management.d.ts +32 -0
  79. package/dist-server/service/prediction/prediction-management.js +299 -0
  80. package/dist-server/service/prediction/prediction-management.js.map +1 -0
  81. package/dist-server/service/project/project-management.d.ts +36 -0
  82. package/dist-server/service/project/project-management.js +309 -0
  83. package/dist-server/service/project/project-management.js.map +1 -0
  84. package/dist-server/service/task/task-management.d.ts +42 -0
  85. package/dist-server/service/task/task-management.js +372 -0
  86. package/dist-server/service/task/task-management.js.map +1 -0
  87. package/dist-server/service/user-provisioning/user-sync-mutation.d.ts +28 -0
  88. package/dist-server/service/user-provisioning/user-sync-mutation.js +111 -0
  89. package/dist-server/service/user-provisioning/user-sync-mutation.js.map +1 -0
  90. package/dist-server/service/webhook/webhook-management.d.ts +21 -0
  91. package/dist-server/service/webhook/webhook-management.js +134 -0
  92. package/dist-server/service/webhook/webhook-management.js.map +1 -0
  93. package/dist-server/tsconfig.tsbuildinfo +1 -0
  94. package/dist-server/types/dataset-labeling-types.d.ts +71 -0
  95. package/dist-server/types/dataset-labeling-types.js +259 -0
  96. package/dist-server/types/dataset-labeling-types.js.map +1 -0
  97. package/dist-server/types/label-studio-types.d.ts +128 -0
  98. package/dist-server/types/label-studio-types.js +494 -0
  99. package/dist-server/types/label-studio-types.js.map +1 -0
  100. package/dist-server/types/prediction-types.d.ts +39 -0
  101. package/dist-server/types/prediction-types.js +121 -0
  102. package/dist-server/types/prediction-types.js.map +1 -0
  103. package/dist-server/utils/annotation-exporter.d.ts +104 -0
  104. package/dist-server/utils/annotation-exporter.js +261 -0
  105. package/dist-server/utils/annotation-exporter.js.map +1 -0
  106. package/dist-server/utils/label-config-builder.d.ts +117 -0
  107. package/dist-server/utils/label-config-builder.js +286 -0
  108. package/dist-server/utils/label-config-builder.js.map +1 -0
  109. package/dist-server/utils/label-studio-api-client.d.ts +180 -0
  110. package/dist-server/utils/label-studio-api-client.js +401 -0
  111. package/dist-server/utils/label-studio-api-client.js.map +1 -0
  112. package/dist-server/utils/media-url-extractor.d.ts +45 -0
  113. package/dist-server/utils/media-url-extractor.js +152 -0
  114. package/dist-server/utils/media-url-extractor.js.map +1 -0
  115. package/dist-server/utils/task-transformer.d.ts +108 -0
  116. package/dist-server/utils/task-transformer.js +260 -0
  117. package/dist-server/utils/task-transformer.js.map +1 -0
  118. package/package.json +47 -0
  119. package/server/SERVER_STRUCTURE.md +351 -0
  120. package/server/controller/label-studio-role-mapper.ts +76 -0
  121. package/server/controller/user-provisioning-service.ts +340 -0
  122. package/server/index.ts +19 -0
  123. package/server/route/label-studio-sso.ts +194 -0
  124. package/server/route/webhook.ts +304 -0
  125. package/server/route.ts +35 -0
  126. package/server/service/ai-prediction-service.ts +239 -0
  127. package/server/service/dataset-labeling-integration.ts +590 -0
  128. package/server/service/external-data-source-service.ts +438 -0
  129. package/server/service/index.ts +24 -0
  130. package/server/service/label-studio-sso-service.ts +108 -0
  131. package/server/service/labeling-scenario-service.ts.deprecated +566 -0
  132. package/server/service/ml/ml-backend-service.ts +127 -0
  133. package/server/service/prediction/prediction-management.ts +281 -0
  134. package/server/service/project/project-management.ts +284 -0
  135. package/server/service/task/task-management.ts +363 -0
  136. package/server/service/user-provisioning/user-sync-mutation.ts +80 -0
  137. package/server/service/webhook/webhook-management.ts +109 -0
  138. package/server/tsconfig.json +11 -0
  139. package/server/types/dataset-labeling-types.ts +181 -0
  140. package/server/types/global.d.ts +23 -0
  141. package/server/types/label-studio-types.ts +346 -0
  142. package/server/types/prediction-types.ts +86 -0
  143. package/server/types/scenario-types.ts.deprecated +362 -0
  144. package/server/utils/annotation-exporter.ts +340 -0
  145. package/server/utils/label-config-builder.ts +340 -0
  146. package/server/utils/label-studio-api-client.ts +487 -0
  147. package/server/utils/media-url-extractor.ts +193 -0
  148. package/server/utils/task-transformer.ts +342 -0
  149. package/test-ai-prediction.js +268 -0
  150. package/test-dataset-integration.js +449 -0
  151. package/test-simple.js +89 -0
  152. package/things-factory.config.js +12 -0
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Label Studio Wrapper Component for Things Factory
3
+ *
4
+ * This component embeds Label Studio within Things Factory using an iframe.
5
+ * It uses subdomain-based cookie sharing for SSO authentication, eliminating
6
+ * the need for proxying.
7
+ *
8
+ * ## Key Features:
9
+ * - Direct Label Studio access (no proxy needed)
10
+ * - Automatic SSO cookie setup via shared domain
11
+ * - Hidden header for seamless integration
12
+ * - Floating Action Buttons (FAB) for Reload and Fullscreen
13
+ *
14
+ * ## Architecture:
15
+ * 1. Client calls /label-studio/sso/setup
16
+ * 2. Backend sets cookie with shared domain (e.g., .nubison.localhost)
17
+ * 3. Browser → Label Studio (direct, with cookie)
18
+ *
19
+ * ## Configuration Requirements:
20
+ * - Label Studio and Things Factory must use subdomain pattern (e.g., label.example.com, app.example.com)
21
+ * - Label Studio .env must include:
22
+ * - CSRF_TRUSTED_ORIGINS: Include Things Factory frontend domain
23
+ * - ALLOWED_HOSTS: Include subdomain patterns
24
+ * - JWT_SSO_* settings for SSO authentication
25
+ * - Things Factory config must include:
26
+ * - labelStudio.serverUrl: Label Studio URL
27
+ * - labelStudio.cookieDomain: Shared cookie domain (e.g., .example.com)
28
+ *
29
+ * ## Usage:
30
+ * ```html
31
+ * <label-studio-wrapper></label-studio-wrapper>
32
+ * ```
33
+ *
34
+ * The component automatically:
35
+ * 1. Calls SSO setup endpoint to establish authentication
36
+ * 2. Builds iframe URL pointing directly to Label Studio
37
+ * 3. Adds ?hideHeader=true to hide Label Studio's header
38
+ * 4. Provides FAB buttons for reload and fullscreen
39
+ */
40
+ import { css, html, LitElement } from 'lit'
41
+ import { customElement, state, query } from 'lit/decorators.js'
42
+
43
+ @customElement('label-studio-wrapper')
44
+ export class LabelStudioWrapper extends LitElement {
45
+ static styles = css`
46
+ :host {
47
+ display: flex;
48
+ flex-direction: column;
49
+ height: 100%;
50
+ overflow: hidden;
51
+ }
52
+
53
+ .container {
54
+ flex: 1;
55
+ display: flex;
56
+ flex-direction: column;
57
+ overflow: hidden;
58
+ position: relative;
59
+ }
60
+
61
+ .iframe-container {
62
+ flex: 1;
63
+ position: relative;
64
+ overflow: hidden;
65
+ }
66
+
67
+ iframe {
68
+ width: 100%;
69
+ height: 100%;
70
+ border: none;
71
+ }
72
+
73
+ .fab-container {
74
+ position: absolute;
75
+ bottom: 24px;
76
+ left: 24px;
77
+ display: flex;
78
+ flex-direction: column;
79
+ gap: 12px;
80
+ z-index: 1000;
81
+ }
82
+
83
+ .fab-button {
84
+ width: 56px;
85
+ height: 56px;
86
+ border-radius: 16px;
87
+ background-color: var(--md-sys-color-primary-container);
88
+ color: var(--md-sys-color-on-primary-container);
89
+ border: none;
90
+ cursor: pointer;
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
95
+ transition: all 0.2s ease;
96
+ }
97
+
98
+ .fab-button:hover {
99
+ background-color: var(--md-sys-color-primary);
100
+ color: var(--md-sys-color-on-primary);
101
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
102
+ transform: translateY(-2px);
103
+ }
104
+
105
+ .fab-button md-icon {
106
+ font-size: 24px;
107
+ }
108
+
109
+ .loading {
110
+ display: flex;
111
+ justify-content: center;
112
+ align-items: center;
113
+ height: 100%;
114
+ font-size: 18px;
115
+ color: var(--md-sys-color-on-surface-variant);
116
+ }
117
+
118
+ .error {
119
+ display: flex;
120
+ justify-content: center;
121
+ align-items: center;
122
+ height: 100%;
123
+ color: var(--md-sys-color-error);
124
+ flex-direction: column;
125
+ gap: 10px;
126
+ }
127
+
128
+ md-filled-button {
129
+ --md-filled-button-container-color: var(--md-sys-color-primary);
130
+ }
131
+ `
132
+
133
+ @state() private loading: boolean = true
134
+ @state() private error: string | null = null
135
+ @state() private iframeUrl: string = ''
136
+ @state() private path: string = ''
137
+ @state() private iframeLoaded: boolean = false
138
+ @state() private labelStudioUrl: string = ''
139
+ @query('iframe') private iframe!: HTMLIFrameElement
140
+
141
+ async updated(changes: any) {
142
+ if (changes.has('path') && this.path) {
143
+ await this.buildIframeUrl()
144
+
145
+ setTimeout(() => {
146
+ if (!this.iframeLoaded && !this.error && !this.loading) {
147
+ this.error = 'Failed to load Label Studio. The server may be unavailable.'
148
+ }
149
+ }, 15000)
150
+ }
151
+ }
152
+
153
+ async buildIframeUrl() {
154
+ try {
155
+ this.loading = true
156
+ this.error = null
157
+
158
+ // Step 1: Get Label Studio configuration
159
+ console.log('[Label Studio Wrapper] Fetching Label Studio configuration...')
160
+
161
+ const configResponse = await fetch('/label-studio/sso/config', {
162
+ method: 'GET',
163
+ credentials: 'include'
164
+ })
165
+
166
+ if (!configResponse.ok) {
167
+ throw new Error(`Failed to fetch Label Studio config: ${configResponse.status}`)
168
+ }
169
+
170
+ const configData = await configResponse.json()
171
+ this.labelStudioUrl = configData.labelStudioUrl
172
+
173
+ if (!this.labelStudioUrl || this.labelStudioUrl === 'not configured') {
174
+ throw new Error('Label Studio URL is not configured. Please check your settings.')
175
+ }
176
+
177
+ console.log('[Label Studio Wrapper] Label Studio URL:', this.labelStudioUrl)
178
+ console.log('[Label Studio Wrapper] Cookie domain:', configData.cookieDomain)
179
+
180
+ // Step 2: Setup SSO token before loading iframe
181
+ console.log('[Label Studio Wrapper] Setting up SSO token...')
182
+
183
+ const ssoResponse = await fetch('/label-studio/sso/setup', {
184
+ method: 'GET',
185
+ credentials: 'include' // Include cookies in request
186
+ })
187
+
188
+ if (!ssoResponse.ok) {
189
+ const errorData = await ssoResponse.json().catch(() => ({}))
190
+ throw new Error(errorData.message || `SSO setup failed: ${ssoResponse.status}`)
191
+ }
192
+
193
+ const ssoData = await ssoResponse.json()
194
+ console.log('[Label Studio Wrapper] SSO setup complete:', ssoData.message)
195
+
196
+ // Step 3: Build iframe URL pointing directly to Label Studio
197
+ // No proxy needed - cookie is shared via domain
198
+ let url = this.labelStudioUrl + this.path
199
+
200
+ // Build query parameters
201
+ const params = new URLSearchParams()
202
+
203
+ // Hide header for seamless iframe embedding
204
+ params.set('hideHeader', 'true')
205
+
206
+ // Combine URL with parameters
207
+ const queryString = params.toString()
208
+ this.iframeUrl = queryString ? `${url}?${queryString}` : url
209
+
210
+ console.log('[Label Studio Wrapper] iframe URL:', this.iframeUrl)
211
+ } catch (err: any) {
212
+ console.error('[Label Studio Wrapper] Failed to build iframe URL:', err)
213
+ this.error = `Failed to initialize: ${err.message}`
214
+ } finally {
215
+ this.loading = false
216
+ }
217
+ }
218
+
219
+ handleIframeLoad() {
220
+ console.log('Label Studio iframe loaded successfully')
221
+ this.iframeLoaded = true
222
+ this.loading = false
223
+ }
224
+
225
+ handleIframeError() {
226
+ console.error('Label Studio iframe failed to load')
227
+ this.error = 'Failed to load Label Studio iframe. Please check the server connection.'
228
+ this.loading = false
229
+ }
230
+
231
+ handleReload() {
232
+ if (this.iframe) {
233
+ this.iframe.src = this.iframeUrl
234
+ }
235
+ }
236
+
237
+ handleFullscreen() {
238
+ if (this.iframe) {
239
+ if (this.iframe.requestFullscreen) {
240
+ this.iframe.requestFullscreen()
241
+ }
242
+ }
243
+ }
244
+
245
+ render() {
246
+ if (this.loading) {
247
+ return html`
248
+ <div class="loading">
249
+ <md-circular-progress indeterminate></md-circular-progress>
250
+ <span>Loading Label Studio...</span>
251
+ </div>
252
+ `
253
+ }
254
+
255
+ if (this.error) {
256
+ return html`
257
+ <div class="error">
258
+ <md-icon>error</md-icon>
259
+ <div>${this.error}</div>
260
+ <md-filled-button @click=${this.buildIframeUrl}>
261
+ <md-icon slot="icon">refresh</md-icon>
262
+ Retry
263
+ </md-filled-button>
264
+ </div>
265
+ `
266
+ }
267
+
268
+ return html`
269
+ <div class="container">
270
+ <div class="iframe-container">
271
+ <iframe
272
+ src=${this.iframeUrl}
273
+ @load=${this.handleIframeLoad}
274
+ @error=${this.handleIframeError}
275
+ allow="fullscreen"
276
+ allow-same-origin
277
+ allow-scripts
278
+ allow-forms
279
+ allow-popups
280
+ allow-top-navigation
281
+ ></iframe>
282
+ </div>
283
+ <div class="fab-container">
284
+ <button class="fab-button" @click=${this.handleReload} title="Reload">
285
+ <md-icon>refresh</md-icon>
286
+ </button>
287
+ <button class="fab-button" @click=${this.handleFullscreen} title="Fullscreen">
288
+ <md-icon>fullscreen</md-icon>
289
+ </button>
290
+ </div>
291
+ </div>
292
+ `
293
+ }
294
+ }
@@ -0,0 +1,15 @@
1
+ export default function route(page: string) {
2
+ switch (page) {
3
+ case 'label-studio-project-list':
4
+ import('./label-studio-project-list.js')
5
+ return page
6
+
7
+ case 'label-studio-project-create':
8
+ import('./label-studio-project-create.js')
9
+ return page
10
+
11
+ case 'label-studio-label':
12
+ import('./label-studio-label-page.js')
13
+ return page
14
+ }
15
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../tsconfig-base.json",
3
+ "compilerOptions": {
4
+ "experimentalDecorators": true,
5
+ "skipLibCheck": true,
6
+ "strict": true,
7
+ "declaration": true,
8
+ "module": "esnext",
9
+ "outDir": "../dist-client",
10
+ "baseUrl": "./"
11
+ },
12
+ "include": ["./**/*"]
13
+ }
@@ -0,0 +1,124 @@
1
+ module.exports = {
2
+ // Label Studio Custom integration configuration for DEVELOPMENT
3
+ labelStudio: {
4
+ // Label Studio Custom server URL (subdomain approach recommended)
5
+ // Development: http://label.hatiolab.localhost:8080
6
+ // Production: https://label.example.com
7
+ serverUrl: process.env.LABEL_STUDIO_URL || 'http://label.hatiolab.localhost:8080',
8
+
9
+ // API Token for Label Studio (REQUIRED for user synchronization and API access)
10
+ // How to get:
11
+ // 1. Login to Label Studio with admin account
12
+ // 2. Go to Account Settings → Access Token
13
+ // 3. Click "Create new token"
14
+ // 4. Copy the generated token
15
+ apiToken: process.env.LABEL_STUDIO_API_TOKEN || '',
16
+
17
+ // Cookie domain for subdomain sharing (SSO)
18
+ // Development: .hatiolab.localhost
19
+ // Production: .example.com
20
+ // IMPORTANT: Must start with a dot (.) for subdomain sharing
21
+ cookieDomain: process.env.LABEL_STUDIO_COOKIE_DOMAIN || '.hatiolab.localhost',
22
+
23
+ // Label Studio UI interface elements to display
24
+ // Options: panel, controls, annotations:menu, side-column, predictions:menu
25
+ interfaces: 'panel,controls,annotations:menu'
26
+ }
27
+ }
28
+
29
+ // ============================================================================
30
+ // Label Studio Custom (SSO Edition) - v1.20.0-sso.38
31
+ // ============================================================================
32
+ //
33
+ // This configuration is for Label Studio Custom Docker image with built-in SSO:
34
+ // ghcr.io/aidoop/label-studio-custom:1.20.0-sso.38
35
+ //
36
+ // Features:
37
+ // - Native JWT SSO authentication (label-studio-sso v6.0.8 integrated)
38
+ // - JWT → Django Session conversion for performance
39
+ // - Automatic Organization assignment
40
+ // - Custom SSO Token API
41
+ // - iframe-friendly configuration
42
+ //
43
+ // ============================================================================
44
+ // Required Environment Variables
45
+ // ============================================================================
46
+ //
47
+ // Things-Factory (.env):
48
+ // LABEL_STUDIO_URL=http://label.hatiolab.localhost:8080
49
+ // LABEL_STUDIO_API_TOKEN=your-api-token-here
50
+ // LABEL_STUDIO_COOKIE_DOMAIN=.hatiolab.localhost
51
+ //
52
+ // Label Studio Custom (.env):
53
+ // # Database
54
+ // POSTGRES_HOST=postgres
55
+ // POSTGRES_DB=labelstudio
56
+ // POSTGRES_USER=postgres
57
+ // POSTGRES_PASSWORD=your-password
58
+ //
59
+ // # SSO Configuration
60
+ // JWT_SSO_NATIVE_USER_ID_CLAIM=user_id
61
+ // JWT_SSO_COOKIE_NAME=ls_auth_token
62
+ // JWT_SSO_TOKEN_PARAM=token
63
+ // SSO_TOKEN_EXPIRY=600
64
+ //
65
+ // # Cookie Domain (must match Things-Factory)
66
+ // SESSION_COOKIE_DOMAIN=.hatiolab.localhost
67
+ // CSRF_COOKIE_DOMAIN=.hatiolab.localhost
68
+ //
69
+ // # iframe Security Headers
70
+ // CSP_FRAME_ANCESTORS='self' http://localhost:3000 http://hatiolab.localhost:3000
71
+ //
72
+ // ============================================================================
73
+ // Docker Deployment
74
+ // ============================================================================
75
+ //
76
+ // docker-compose.yml:
77
+ //
78
+ // services:
79
+ // labelstudio:
80
+ // image: ghcr.io/aidoop/label-studio-custom:1.20.0-sso.38
81
+ // environment:
82
+ // POSTGRES_HOST: postgres
83
+ // POSTGRES_DB: labelstudio
84
+ // SESSION_COOKIE_DOMAIN: .hatiolab.localhost
85
+ // CSRF_COOKIE_DOMAIN: .hatiolab.localhost
86
+ // CSP_FRAME_ANCESTORS: "'self' http://hatiolab.localhost:3000"
87
+ // ports:
88
+ // - "8080:8080"
89
+ //
90
+ // ============================================================================
91
+ // User Synchronization
92
+ // ============================================================================
93
+ //
94
+ // Things-Factory users with 'label-studio' privileges will be synced to Label Studio:
95
+ //
96
+ // Privilege mapping:
97
+ // - user.owner === true + label-studio privilege → Admin (is_superuser=true)
98
+ // - label-studio privilege only → Staff (is_superuser=false)
99
+ // - No label-studio privilege → Inactive (is_active=false)
100
+ //
101
+ // GraphQL API:
102
+ // mutation { syncMyUserToLabelStudio { success email action } }
103
+ // mutation { syncAllUsersToLabelStudio { total created updated } }
104
+ //
105
+ // ============================================================================
106
+ // Security Checklist
107
+ // ============================================================================
108
+ //
109
+ // Development (HTTP):
110
+ // □ Label Studio Custom image v1.20.0-sso.32 running
111
+ // □ Cookie domain matches (.hatiolab.localhost)
112
+ // □ API token generated and configured
113
+ // □ CSP frame-ancestors includes Things-Factory URL
114
+ // □ Users synced with correct privileges
115
+ //
116
+ // Production (HTTPS):
117
+ // □ SESSION_COOKIE_SECURE=true (Label Studio)
118
+ // □ CSRF_COOKIE_SECURE=true (Label Studio)
119
+ // □ HTTPS URLs for both systems
120
+ // □ Cookie domain matches production domain (.example.com)
121
+ // □ JWT secret is strong (32+ characters)
122
+ // □ API token is kept secret
123
+ //
124
+ // ============================================================================
@@ -0,0 +1,182 @@
1
+ module.exports = {
2
+ // Label Studio Custom integration configuration for PRODUCTION
3
+ labelStudio: {
4
+ // Label Studio Custom server URL (HTTPS required for production)
5
+ // Production: https://label.example.com
6
+ serverUrl: process.env.LABEL_STUDIO_URL || '',
7
+
8
+ // API Token for Label Studio (REQUIRED for user synchronization and API access)
9
+ // How to get:
10
+ // 1. Login to Label Studio with admin account
11
+ // 2. Go to Account Settings → Access Token
12
+ // 3. Click "Create new token"
13
+ // 4. Copy the generated token
14
+ // IMPORTANT: Use environment variable in production
15
+ apiToken: process.env.LABEL_STUDIO_API_TOKEN || '',
16
+
17
+ // Cookie domain for subdomain sharing (SSO)
18
+ // Production: .example.com
19
+ // IMPORTANT: Must start with a dot (.) for subdomain sharing
20
+ cookieDomain: process.env.LABEL_STUDIO_COOKIE_DOMAIN || '',
21
+
22
+ // Label Studio UI interface elements to display
23
+ // Options: panel, controls, annotations:menu, side-column, predictions:menu
24
+ interfaces: 'panel,controls,annotations:menu'
25
+ }
26
+ }
27
+
28
+ // ============================================================================
29
+ // Label Studio Custom (SSO Edition) - v1.20.0-sso.32 PRODUCTION
30
+ // ============================================================================
31
+ //
32
+ // This configuration is for Label Studio Custom Docker image with built-in SSO:
33
+ // ghcr.io/aidoop/label-studio-custom:1.20.0-sso.38
34
+ //
35
+ // Features:
36
+ // - Native JWT SSO authentication (label-studio-sso v6.0.8 integrated)
37
+ // - JWT → Django Session conversion for performance
38
+ // - Automatic Organization assignment
39
+ // - Custom SSO Token API
40
+ // - iframe-friendly configuration
41
+ // - HTTPS production-ready deployment
42
+ //
43
+ // ============================================================================
44
+ // Required Environment Variables (PRODUCTION)
45
+ // ============================================================================
46
+ //
47
+ // Things-Factory (.env.production):
48
+ // LABEL_STUDIO_URL=https://label.example.com
49
+ // LABEL_STUDIO_API_TOKEN=your-api-token-here
50
+ // LABEL_STUDIO_COOKIE_DOMAIN=.example.com
51
+ //
52
+ // Label Studio Custom (.env):
53
+ // # Database (RDS/Aurora recommended)
54
+ // POSTGRES_HOST=your-db-endpoint.rds.amazonaws.com
55
+ // POSTGRES_DB=labelstudio
56
+ // POSTGRES_USER=postgres
57
+ // POSTGRES_PASSWORD=your-secure-password
58
+ //
59
+ // # SSO Configuration
60
+ // JWT_SSO_NATIVE_USER_ID_CLAIM=user_id
61
+ // JWT_SSO_COOKIE_NAME=ls_auth_token
62
+ // JWT_SSO_TOKEN_PARAM=token
63
+ // SSO_TOKEN_EXPIRY=600
64
+ //
65
+ // # Cookie Domain (must match Things-Factory)
66
+ // SESSION_COOKIE_DOMAIN=.example.com
67
+ // CSRF_COOKIE_DOMAIN=.example.com
68
+ //
69
+ // # ⚠️ HTTPS Cookie Security (REQUIRED for production)
70
+ // SESSION_COOKIE_SECURE=true
71
+ // CSRF_COOKIE_SECURE=true
72
+ //
73
+ // # iframe Security Headers
74
+ // CSP_FRAME_ANCESTORS='self' https://app.example.com https://console.example.com
75
+ //
76
+ // # Label Studio URL
77
+ // LABEL_STUDIO_HOST=https://label.example.com
78
+ //
79
+ // ============================================================================
80
+ // Docker Deployment (Production)
81
+ // ============================================================================
82
+ //
83
+ // docker-compose.production.yml:
84
+ //
85
+ // services:
86
+ // labelstudio:
87
+ // image: ghcr.io/aidoop/label-studio-custom:1.20.0-sso.38
88
+ //
89
+ // environment:
90
+ // # Database
91
+ // POSTGRES_HOST: your-db-endpoint.rds.amazonaws.com
92
+ // POSTGRES_DB: labelstudio
93
+ // POSTGRES_USER: ${POSTGRES_USER}
94
+ // POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
95
+ //
96
+ // # SSO
97
+ // JWT_SSO_NATIVE_USER_ID_CLAIM: user_id
98
+ // JWT_SSO_COOKIE_NAME: ls_auth_token
99
+ // SSO_TOKEN_EXPIRY: 600
100
+ //
101
+ // # Cookie Domain
102
+ // SESSION_COOKIE_DOMAIN: .example.com
103
+ // CSRF_COOKIE_DOMAIN: .example.com
104
+ //
105
+ // # ⚠️ HTTPS Security (REQUIRED)
106
+ // SESSION_COOKIE_SECURE: "true"
107
+ // CSRF_COOKIE_SECURE: "true"
108
+ // LABEL_STUDIO_HOST: https://label.example.com
109
+ //
110
+ // # iframe Security
111
+ // CSP_FRAME_ANCESTORS: "'self' https://app.example.com"
112
+ //
113
+ // ports:
114
+ // - "8080:8080"
115
+ //
116
+ // # Health check
117
+ // healthcheck:
118
+ // test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
119
+ // interval: 30s
120
+ // timeout: 10s
121
+ // retries: 3
122
+ //
123
+ // ============================================================================
124
+ // Kubernetes Deployment (Production)
125
+ // ============================================================================
126
+ //
127
+ // See: /Users/super/Documents/GitHub/label-studio-custom/k8s/04-deployment.yaml
128
+ //
129
+ // Key configuration:
130
+ // - Image: ghcr.io/aidoop/label-studio-custom:1.20.0-sso.38
131
+ // - Replicas: 2+ (for high availability)
132
+ // - Health checks: /health endpoint
133
+ // - Ingress: ALB with HTTPS
134
+ // - Database: RDS Aurora PostgreSQL
135
+ //
136
+ // ============================================================================
137
+ // User Synchronization
138
+ // ============================================================================
139
+ //
140
+ // Things-Factory users with 'label-studio' privileges will be synced to Label Studio:
141
+ //
142
+ // Privilege mapping:
143
+ // - user.owner === true + label-studio privilege → Admin (is_superuser=true)
144
+ // - label-studio privilege only → Staff (is_superuser=false)
145
+ // - No label-studio privilege → Inactive (is_active=false)
146
+ //
147
+ // GraphQL API:
148
+ // mutation { syncMyUserToLabelStudio { success email action } }
149
+ // mutation { syncAllUsersToLabelStudio { total created updated } }
150
+ //
151
+ // ============================================================================
152
+ // PRODUCTION Security Checklist
153
+ // ============================================================================
154
+ //
155
+ // Infrastructure:
156
+ // □ HTTPS enabled for both Things-Factory and Label Studio
157
+ // □ SSL certificates valid and auto-renewed
158
+ // □ Database (RDS) with encrypted storage
159
+ // □ VPC with private subnets for database
160
+ // □ Security groups restrict database access
161
+ //
162
+ // Label Studio Configuration:
163
+ // □ SESSION_COOKIE_SECURE=true
164
+ // □ CSRF_COOKIE_SECURE=true
165
+ // □ Cookie domain matches production (.example.com)
166
+ // □ CSP frame-ancestors restricts iframe embedding
167
+ // □ API token stored in secrets manager
168
+ // □ JWT secret is strong (32+ characters)
169
+ //
170
+ // Things-Factory Configuration:
171
+ // □ LABEL_STUDIO_URL uses HTTPS
172
+ // □ LABEL_STUDIO_API_TOKEN from secrets manager
173
+ // □ Cookie domain matches Label Studio
174
+ // □ CORS properly configured
175
+ //
176
+ // Monitoring:
177
+ // □ Health checks configured
178
+ // □ Application logs centralized
179
+ // □ Alert on service failures
180
+ // □ Database backup enabled
181
+ //
182
+ // ============================================================================
@@ -0,0 +1 @@
1
+ export default function bootstrap(): void;
@@ -0,0 +1,2 @@
1
+ export default function bootstrap() { }
2
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,UAAU,SAAS,KAAI,CAAC","sourcesContent":["export default function bootstrap() {}\n"]}
@@ -0,0 +1 @@
1
+ export * from './label-studio-wrapper.js';
@@ -0,0 +1,2 @@
1
+ export * from './label-studio-wrapper.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAA","sourcesContent":["export * from './label-studio-wrapper.js'\n"]}
@@ -0,0 +1,8 @@
1
+ import './label-studio-wrapper.js';
2
+ import { PageView } from '@things-factory/shell/client';
3
+ export declare class LabelStudioLabelPage extends PageView {
4
+ static styles: import("lit").CSSResult;
5
+ projectId: string;
6
+ pageUpdated(changes: any, lifecycle: any, changedBefore: any): Promise<void>;
7
+ render(): import("lit-html").TemplateResult<1>;
8
+ }