@arcblock/did-connect-service 4.1.11 → 4.1.13

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 (121) hide show
  1. package/dist/_generated/asset-bytes.js +1 -1
  2. package/dist/_generated/asset-manifest.js +3 -3
  3. package/dist/_generated/login-bundle-string.d.ts +1 -1
  4. package/dist/_generated/login-bundle-string.d.ts.map +1 -1
  5. package/dist/_generated/login-bundle-string.js +1 -1
  6. package/dist/_generated/login-bundle-string.js.map +1 -1
  7. package/dist/access/change-role.d.ts +48 -0
  8. package/dist/access/change-role.d.ts.map +1 -0
  9. package/dist/access/change-role.js +52 -0
  10. package/dist/access/change-role.js.map +1 -0
  11. package/dist/assets/admin-core.a63bbc69.js +1464 -0
  12. package/dist/assets/admin-extra.143b5774.js +2543 -0
  13. package/dist/assets/admin-extra.5b309e5e.js +2547 -0
  14. package/dist/assets/login.4404e695.js +720 -0
  15. package/dist/assets/login.76c483c2.js +720 -0
  16. package/dist/assets/login.bb9f8b03.js +720 -0
  17. package/dist/assets/login.fa25f37a.js +720 -0
  18. package/dist/handler-errors.d.ts +118 -0
  19. package/dist/handler-errors.d.ts.map +1 -0
  20. package/dist/handler-errors.js +38 -0
  21. package/dist/handler-errors.js.map +1 -0
  22. package/dist/handlers/access-key-connect-handler.d.ts.map +1 -1
  23. package/dist/handlers/access-key-connect-handler.js +2 -1
  24. package/dist/handlers/access-key-connect-handler.js.map +1 -1
  25. package/dist/handlers/admin-instance-handler.d.ts.map +1 -1
  26. package/dist/handlers/admin-instance-handler.js +2 -1
  27. package/dist/handlers/admin-instance-handler.js.map +1 -1
  28. package/dist/handlers/auth-handler.d.ts.map +1 -1
  29. package/dist/handlers/auth-handler.js +32 -9
  30. package/dist/handlers/auth-handler.js.map +1 -1
  31. package/dist/handlers/branding-handler.d.ts.map +1 -1
  32. package/dist/handlers/branding-handler.js +12 -9
  33. package/dist/handlers/branding-handler.js.map +1 -1
  34. package/dist/handlers/did-connect-handler.d.ts.map +1 -1
  35. package/dist/handlers/did-connect-handler.js +6 -5
  36. package/dist/handlers/did-connect-handler.js.map +1 -1
  37. package/dist/handlers/email-login-handler.d.ts +1 -1
  38. package/dist/handlers/email-login-handler.d.ts.map +1 -1
  39. package/dist/handlers/email-login-handler.js +63 -12
  40. package/dist/handlers/email-login-handler.js.map +1 -1
  41. package/dist/handlers/federation-admin-handler.d.ts.map +1 -1
  42. package/dist/handlers/federation-admin-handler.js +48 -45
  43. package/dist/handlers/federation-admin-handler.js.map +1 -1
  44. package/dist/handlers/oauth-handler.d.ts.map +1 -1
  45. package/dist/handlers/oauth-handler.js +23 -12
  46. package/dist/handlers/oauth-handler.js.map +1 -1
  47. package/dist/handlers/passkey-handler.d.ts.map +1 -1
  48. package/dist/handlers/passkey-handler.js +5 -4
  49. package/dist/handlers/passkey-handler.js.map +1 -1
  50. package/dist/handlers/team-handler.d.ts.map +1 -1
  51. package/dist/handlers/team-handler.js +19 -19
  52. package/dist/handlers/team-handler.js.map +1 -1
  53. package/dist/http/security-headers.d.ts +38 -0
  54. package/dist/http/security-headers.d.ts.map +1 -0
  55. package/dist/http/security-headers.js +67 -0
  56. package/dist/http/security-headers.js.map +1 -0
  57. package/dist/identity/refresh-tokens.d.ts +21 -0
  58. package/dist/identity/refresh-tokens.d.ts.map +1 -0
  59. package/dist/identity/refresh-tokens.js +45 -0
  60. package/dist/identity/refresh-tokens.js.map +1 -0
  61. package/dist/identity/session-context.d.ts +12 -0
  62. package/dist/identity/session-context.d.ts.map +1 -1
  63. package/dist/identity/session-context.js +12 -0
  64. package/dist/identity/session-context.js.map +1 -1
  65. package/dist/identity/session-tokens.d.ts +15 -0
  66. package/dist/identity/session-tokens.d.ts.map +1 -0
  67. package/dist/identity/session-tokens.js +15 -0
  68. package/dist/identity/session-tokens.js.map +1 -0
  69. package/dist/locale.d.ts +1 -1
  70. package/dist/locale.d.ts.map +1 -1
  71. package/dist/og/ssrf-guard.d.ts.map +1 -1
  72. package/dist/og/ssrf-guard.js +21 -3
  73. package/dist/og/ssrf-guard.js.map +1 -1
  74. package/dist/og/templates.d.ts.map +1 -1
  75. package/dist/og/templates.js +33 -4
  76. package/dist/og/templates.js.map +1 -1
  77. package/dist/pages/admin/i18n.d.ts.map +1 -1
  78. package/dist/pages/admin/i18n.js +33 -9
  79. package/dist/pages/admin/i18n.js.map +1 -1
  80. package/dist/pages/admin/scripts/api-client.d.ts +1 -1
  81. package/dist/pages/admin/scripts/api-client.d.ts.map +1 -1
  82. package/dist/pages/admin/scripts/api-client.js +4 -4
  83. package/dist/pages/admin/scripts/utils.d.ts +1 -1
  84. package/dist/pages/admin/scripts/utils.d.ts.map +1 -1
  85. package/dist/pages/admin/scripts/utils.js +7 -8
  86. package/dist/pages/admin/scripts/utils.js.map +1 -1
  87. package/dist/pages/admin/tab-access-keys.d.ts +1 -1
  88. package/dist/pages/admin/tab-access-keys.d.ts.map +1 -1
  89. package/dist/pages/admin/tab-access-keys.js +4 -4
  90. package/dist/pages/admin/tab-invitations.d.ts +1 -1
  91. package/dist/pages/admin/tab-invitations.d.ts.map +1 -1
  92. package/dist/pages/admin/tab-invitations.js +2 -2
  93. package/dist/pages/admin/tab-members.d.ts +1 -1
  94. package/dist/pages/admin/tab-members.d.ts.map +1 -1
  95. package/dist/pages/admin/tab-members.js +7 -3
  96. package/dist/pages/admin/tab-members.js.map +1 -1
  97. package/dist/pages/admin/tab-profile-accounts.js +1 -1
  98. package/dist/pages/admin-instances-page.d.ts +1 -1
  99. package/dist/pages/admin-instances-page.d.ts.map +1 -1
  100. package/dist/pages/admin-instances-page.js +195 -65
  101. package/dist/pages/admin-instances-page.js.map +1 -1
  102. package/dist/pages/gen-access-key-page.d.ts +1 -1
  103. package/dist/pages/gen-access-key-page.d.ts.map +1 -1
  104. package/dist/pages/gen-access-key-page.js +163 -35
  105. package/dist/pages/gen-access-key-page.js.map +1 -1
  106. package/dist/pages/homepage.d.ts.map +1 -1
  107. package/dist/pages/homepage.js +0 -4
  108. package/dist/pages/homepage.js.map +1 -1
  109. package/dist/pages/invite-page.d.ts +1 -1
  110. package/dist/pages/invite-page.d.ts.map +1 -1
  111. package/dist/pages/invite-page.js +91 -21
  112. package/dist/pages/invite-page.js.map +1 -1
  113. package/dist/pages/oauth-callback-page.d.ts.map +1 -1
  114. package/dist/pages/oauth-callback-page.js +7 -3
  115. package/dist/pages/oauth-callback-page.js.map +1 -1
  116. package/dist/store/d1-store.d.ts +55 -1
  117. package/dist/store/d1-store.d.ts.map +1 -1
  118. package/dist/store/d1-store.js +162 -9
  119. package/dist/store/d1-store.js.map +1 -1
  120. package/migrations/0011_refresh_tokens.sql +23 -0
  121. package/package.json +5 -5
@@ -9,15 +9,124 @@ import { assetUrl } from "../asset-registry.js";
9
9
  function escapeForScript(s) {
10
10
  return s.replace(/<\/(script)/gi, "<\\/$1");
11
11
  }
12
- /** HTML-escape a string to prevent XSS in rendered content. */
13
- function escapeHtml(s) {
14
- return s
15
- .replace(/&/g, "&amp;")
16
- .replace(/</g, "&lt;")
17
- .replace(/>/g, "&gt;")
18
- .replace(/"/g, "&quot;")
19
- .replace(/'/g, "&#39;");
20
- }
12
+ /**
13
+ * Admin-instances-page copy, localized. `en` is the default fallback for any
14
+ * unknown locale. Technical identifiers (App PSK/SK/EK, Instance DID, Owner DID,
15
+ * Hosts, BLOCKLET_APP_EK) are intentionally kept untranslated — they are field
16
+ * names / env-var names, not prose. Only the descriptive/instructional text is
17
+ * localized.
18
+ */
19
+ const ADMIN_INSTANCES_I18N = {
20
+ en: {
21
+ title: "Instance Registration",
22
+ backToAdmin: "Back to Admin",
23
+ registerHeading: "Register Instance",
24
+ appPskLabel: "App PSK (Permanent Secret Key) *",
25
+ appPskPlaceholder: "Permanent secret key",
26
+ appPskHint: "Required. Used to derive the Instance DID.",
27
+ instanceDidLabel: "Instance DID (auto-derived)",
28
+ derivedDidPlaceholder: "Enter App PSK to see derived DID",
29
+ appSkLabel: "App SK (Current Secret Key) *",
30
+ appSkPlaceholder: "Current session secret key",
31
+ appEkLabel: "App EK (Encryption Key)",
32
+ appEkPlaceholder: "Optional encryption key (BLOCKLET_APP_EK)",
33
+ appEkHint: "Used by consumers to decrypt AES-encrypted data (e.g. Stripe keys). From BLOCKLET_APP_EK.",
34
+ appNameLabel: "App Name",
35
+ appNamePlaceholder: "Optional display name",
36
+ ownerDidLabel: "Owner DID",
37
+ ownerDidPlaceholder: "Optional owner DID",
38
+ ownerDidHint: "If provided, creates owner membership for this DID.",
39
+ hostsLabel: "Hosts",
40
+ hostsPlaceholder: "Optional, comma-separated (e.g. app.example.com, alt.example.com)",
41
+ hostsHint: "Routes these hosts to this instance. Rejected if a host is already bound elsewhere.",
42
+ registerBtn: "Register Instance",
43
+ registeredHeading: "Registered Instances",
44
+ loading: "Loading...",
45
+ editHeading: "Edit Instance: ",
46
+ editAppNameLabel: "App Name",
47
+ editAppNamePlaceholder: "Display name",
48
+ editAppSkLabel: "App SK (Current Secret Key)",
49
+ keepCurrentPlaceholder: "Leave empty to keep current",
50
+ editAppPskLabel: "App PSK (Permanent Secret Key)",
51
+ editAppEkLabel: "App EK (Encryption Key)",
52
+ editAppEkPlaceholder: "BLOCKLET_APP_EK — leave empty to keep current",
53
+ editAppEkHint: "Used to decrypt AES-encrypted data (e.g. Stripe keys)",
54
+ editOwnerDidLabel: "Owner DID",
55
+ editOwnerDidPlaceholder: "Leave empty to skip",
56
+ cancel: "Cancel",
57
+ save: "Save",
58
+ // client-side (serialized into the page script)
59
+ adminRequired: "Admin access required.",
60
+ noInstances: "No registered instances.",
61
+ unnamed: "(unnamed)",
62
+ registeredTimePrefix: "Registered: ",
63
+ members: "Members",
64
+ edit: "Edit",
65
+ delete: "Delete",
66
+ failedToLoad: "Failed to load instances.",
67
+ registeredStatusPrefix: "Registered: ",
68
+ registrationFailed: "Registration failed",
69
+ networkError: "Network error",
70
+ confirmDeletePrefix: "Delete instance ",
71
+ deleteFailed: "Delete failed",
72
+ noChanges: "No changes to save.",
73
+ updateFailed: "Update failed",
74
+ },
75
+ zh: {
76
+ title: "实例注册",
77
+ backToAdmin: "返回管理后台",
78
+ registerHeading: "注册实例",
79
+ appPskLabel: "App PSK(永久密钥)*",
80
+ appPskPlaceholder: "永久密钥",
81
+ appPskHint: "必填。用于派生实例 DID。",
82
+ instanceDidLabel: "实例 DID(自动派生)",
83
+ derivedDidPlaceholder: "输入 App PSK 以查看派生的 DID",
84
+ appSkLabel: "App SK(当前密钥)*",
85
+ appSkPlaceholder: "当前会话密钥",
86
+ appEkLabel: "App EK(加密密钥)",
87
+ appEkPlaceholder: "可选的加密密钥(BLOCKLET_APP_EK)",
88
+ appEkHint: "供接入方解密 AES 加密的数据(如 Stripe 密钥)。来自 BLOCKLET_APP_EK。",
89
+ appNameLabel: "应用名称",
90
+ appNamePlaceholder: "可选的显示名称",
91
+ ownerDidLabel: "Owner DID",
92
+ ownerDidPlaceholder: "可选的 owner DID",
93
+ ownerDidHint: "若填写,将为该 DID 创建 owner 成员身份。",
94
+ hostsLabel: "Hosts",
95
+ hostsPlaceholder: "可选,逗号分隔(如 app.example.com, alt.example.com)",
96
+ hostsHint: "将这些 host 路由到该实例。若某 host 已绑定到其他实例则会被拒绝。",
97
+ registerBtn: "注册实例",
98
+ registeredHeading: "已注册的实例",
99
+ loading: "加载中…",
100
+ editHeading: "编辑实例:",
101
+ editAppNameLabel: "应用名称",
102
+ editAppNamePlaceholder: "显示名称",
103
+ editAppSkLabel: "App SK(当前密钥)",
104
+ keepCurrentPlaceholder: "留空则保持当前值",
105
+ editAppPskLabel: "App PSK(永久密钥)",
106
+ editAppEkLabel: "App EK(加密密钥)",
107
+ editAppEkPlaceholder: "BLOCKLET_APP_EK —— 留空则保持当前值",
108
+ editAppEkHint: "用于解密 AES 加密的数据(如 Stripe 密钥)",
109
+ editOwnerDidLabel: "Owner DID",
110
+ editOwnerDidPlaceholder: "留空则跳过",
111
+ cancel: "取消",
112
+ save: "保存",
113
+ adminRequired: "需要管理员权限。",
114
+ noInstances: "暂无已注册的实例。",
115
+ unnamed: "(未命名)",
116
+ registeredTimePrefix: "注册时间:",
117
+ members: "成员",
118
+ edit: "编辑",
119
+ delete: "删除",
120
+ failedToLoad: "加载实例失败。",
121
+ registeredStatusPrefix: "已注册:",
122
+ registrationFailed: "注册失败",
123
+ networkError: "网络错误",
124
+ confirmDeletePrefix: "删除实例 ",
125
+ deleteFailed: "删除失败",
126
+ noChanges: "没有需要保存的更改。",
127
+ updateFailed: "更新失败",
128
+ },
129
+ };
21
130
  const PAGE_STYLES = /* css */ `
22
131
  .hidden { display: none !important; }
23
132
 
@@ -198,14 +307,34 @@ const PAGE_STYLES = /* css */ `
198
307
  #edit-status { margin-top: 8px; font-size: 13px; }
199
308
  #edit-status.error { color: var(--red-text, #ef4444); }
200
309
  `;
201
- export function buildAdminInstancesPageHTML() {
310
+ export function buildAdminInstancesPageHTML(locale = "en") {
202
311
  const apiPrefix = "/.well-known/service/api/did";
312
+ const lang = locale === "zh" ? "zh" : "en";
313
+ const t = ADMIN_INSTANCES_I18N[lang];
314
+ const clientI18n = JSON.stringify({
315
+ adminRequired: t.adminRequired,
316
+ noInstances: t.noInstances,
317
+ unnamed: t.unnamed,
318
+ registeredTimePrefix: t.registeredTimePrefix,
319
+ members: t.members,
320
+ edit: t.edit,
321
+ delete: t.delete,
322
+ failedToLoad: t.failedToLoad,
323
+ registeredStatusPrefix: t.registeredStatusPrefix,
324
+ registrationFailed: t.registrationFailed,
325
+ networkError: t.networkError,
326
+ confirmDeletePrefix: t.confirmDeletePrefix,
327
+ deleteFailed: t.deleteFailed,
328
+ noChanges: t.noChanges,
329
+ updateFailed: t.updateFailed,
330
+ derivedDidPlaceholder: t.derivedDidPlaceholder,
331
+ });
203
332
  return /* html */ `<!DOCTYPE html>
204
- <html lang="en">
333
+ <html lang="${lang}">
205
334
  <head>
206
335
  <meta charset="utf-8" />
207
336
  <meta name="viewport" content="width=device-width, initial-scale=1" />
208
- <title>Instance Registration</title>
337
+ <title>${t.title}</title>
209
338
  <link rel="stylesheet" href="${assetUrl("login.css")}" />
210
339
  <style>
211
340
  ${PAGE_STYLES}
@@ -221,55 +350,55 @@ export function buildAdminInstancesPageHTML() {
221
350
 
222
351
  <a href="/.well-known/service" style="display:inline-flex;align-items:center;gap:4px;color:var(--text-secondary);font-size:14px;text-decoration:none;margin-bottom:16px">
223
352
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5"/><path d="M12 19l-7-7 7-7"/></svg>
224
- Back to Admin
353
+ ${t.backToAdmin}
225
354
  </a>
226
355
 
227
356
  <!-- Registration form -->
228
357
  <div class="admin-card">
229
- <h2>Register Instance</h2>
358
+ <h2>${t.registerHeading}</h2>
230
359
  <form id="register-form" method="POST" action="/.well-known/service/api/admin/instances">
231
360
  <div class="form-group">
232
- <label for="appPsk">App PSK (Permanent Secret Key) *</label>
233
- <input type="text" id="appPsk" name="appPsk" required placeholder="Permanent secret key" />
234
- <div class="hint">Required. Used to derive the Instance DID.</div>
361
+ <label for="appPsk">${t.appPskLabel}</label>
362
+ <input type="text" id="appPsk" name="appPsk" required placeholder="${t.appPskPlaceholder}" />
363
+ <div class="hint">${t.appPskHint}</div>
235
364
  </div>
236
365
  <div class="form-group">
237
- <label>Instance DID (auto-derived)</label>
238
- <div class="derived-did" id="derived-did">Enter App PSK to see derived DID</div>
366
+ <label>${t.instanceDidLabel}</label>
367
+ <div class="derived-did" id="derived-did">${t.derivedDidPlaceholder}</div>
239
368
  </div>
240
369
  <div class="form-group">
241
- <label for="appSk">App SK (Current Secret Key) *</label>
242
- <input type="text" id="appSk" name="appSk" required placeholder="Current session secret key" />
370
+ <label for="appSk">${t.appSkLabel}</label>
371
+ <input type="text" id="appSk" name="appSk" required placeholder="${t.appSkPlaceholder}" />
243
372
  </div>
244
373
  <div class="form-group">
245
- <label for="appEk">App EK (Encryption Key)</label>
246
- <input type="text" id="appEk" name="appEk" placeholder="Optional encryption key (BLOCKLET_APP_EK)" />
247
- <div class="hint">Used by consumers to decrypt AES-encrypted data (e.g. Stripe keys). From BLOCKLET_APP_EK.</div>
374
+ <label for="appEk">${t.appEkLabel}</label>
375
+ <input type="text" id="appEk" name="appEk" placeholder="${t.appEkPlaceholder}" />
376
+ <div class="hint">${t.appEkHint}</div>
248
377
  </div>
249
378
  <div class="form-group">
250
- <label for="appName">App Name</label>
251
- <input type="text" id="appName" name="appName" placeholder="Optional display name" />
379
+ <label for="appName">${t.appNameLabel}</label>
380
+ <input type="text" id="appName" name="appName" placeholder="${t.appNamePlaceholder}" />
252
381
  </div>
253
382
  <div class="form-group">
254
- <label for="ownerDid">Owner DID</label>
255
- <input type="text" id="ownerDid" name="ownerDid" placeholder="Optional owner DID" />
256
- <div class="hint">If provided, creates owner membership for this DID.</div>
383
+ <label for="ownerDid">${t.ownerDidLabel}</label>
384
+ <input type="text" id="ownerDid" name="ownerDid" placeholder="${t.ownerDidPlaceholder}" />
385
+ <div class="hint">${t.ownerDidHint}</div>
257
386
  </div>
258
387
  <div class="form-group">
259
- <label for="hosts">Hosts</label>
260
- <input type="text" id="hosts" name="hosts" placeholder="Optional, comma-separated (e.g. app.example.com, alt.example.com)" />
261
- <div class="hint">Routes these hosts to this instance. Rejected if a host is already bound elsewhere.</div>
388
+ <label for="hosts">${t.hostsLabel}</label>
389
+ <input type="text" id="hosts" name="hosts" placeholder="${t.hostsPlaceholder}" />
390
+ <div class="hint">${t.hostsHint}</div>
262
391
  </div>
263
- <button type="submit" class="btn" id="register-btn">Register Instance</button>
392
+ <button type="submit" class="btn" id="register-btn">${t.registerBtn}</button>
264
393
  <div id="register-status"></div>
265
394
  </form>
266
395
  </div>
267
396
 
268
397
  <!-- Registered instances list -->
269
398
  <div class="admin-card">
270
- <h2>Registered Instances</h2>
399
+ <h2>${t.registeredHeading}</h2>
271
400
  <div id="instance-list">
272
- <div class="empty-state">Loading...</div>
401
+ <div class="empty-state">${t.loading}</div>
273
402
  </div>
274
403
  </div>
275
404
  </div>
@@ -278,33 +407,33 @@ export function buildAdminInstancesPageHTML() {
278
407
  <!-- Edit Instance Modal -->
279
408
  <div class="modal-overlay" id="edit-modal">
280
409
  <div class="modal-content">
281
- <h3>Edit Instance: <span id="edit-modal-did"></span></h3>
410
+ <h3>${t.editHeading}<span id="edit-modal-did"></span></h3>
282
411
  <input type="hidden" id="edit-instanceDid" />
283
412
  <div class="form-group">
284
- <label for="edit-appName">App Name</label>
285
- <input type="text" id="edit-appName" placeholder="Display name" />
413
+ <label for="edit-appName">${t.editAppNameLabel}</label>
414
+ <input type="text" id="edit-appName" placeholder="${t.editAppNamePlaceholder}" />
286
415
  </div>
287
416
  <div class="form-group">
288
- <label for="edit-appSk">App SK (Current Secret Key)</label>
289
- <input type="text" id="edit-appSk" placeholder="Leave empty to keep current" />
417
+ <label for="edit-appSk">${t.editAppSkLabel}</label>
418
+ <input type="text" id="edit-appSk" placeholder="${t.keepCurrentPlaceholder}" />
290
419
  </div>
291
420
  <div class="form-group">
292
- <label for="edit-appPsk">App PSK (Permanent Secret Key)</label>
293
- <input type="text" id="edit-appPsk" placeholder="Leave empty to keep current" />
421
+ <label for="edit-appPsk">${t.editAppPskLabel}</label>
422
+ <input type="text" id="edit-appPsk" placeholder="${t.keepCurrentPlaceholder}" />
294
423
  </div>
295
424
  <div class="form-group">
296
- <label for="edit-appEk">App EK (Encryption Key)</label>
297
- <input type="text" id="edit-appEk" placeholder="BLOCKLET_APP_EK — leave empty to keep current" />
298
- <div class="hint">Used to decrypt AES-encrypted data (e.g. Stripe keys)</div>
425
+ <label for="edit-appEk">${t.editAppEkLabel}</label>
426
+ <input type="text" id="edit-appEk" placeholder="${t.editAppEkPlaceholder}" />
427
+ <div class="hint">${t.editAppEkHint}</div>
299
428
  </div>
300
429
  <div class="form-group">
301
- <label for="edit-ownerDid">Owner DID</label>
302
- <input type="text" id="edit-ownerDid" placeholder="Leave empty to skip" />
430
+ <label for="edit-ownerDid">${t.editOwnerDidLabel}</label>
431
+ <input type="text" id="edit-ownerDid" placeholder="${t.editOwnerDidPlaceholder}" />
303
432
  </div>
304
433
  <div id="edit-status"></div>
305
434
  <div class="modal-actions">
306
- <button class="btn-cancel" onclick="closeEditModal()">Cancel</button>
307
- <button class="btn" onclick="submitEdit()">Save</button>
435
+ <button class="btn-cancel" onclick="closeEditModal()">${t.cancel}</button>
436
+ <button class="btn" onclick="submitEdit()">${t.save}</button>
308
437
  </div>
309
438
  </div>
310
439
  </div>
@@ -316,6 +445,7 @@ export function buildAdminInstancesPageHTML() {
316
445
  var LB = __LoginBundle;
317
446
  var apiPrefix = '${escapeForScript(apiPrefix)}';
318
447
  var adminApi = '/.well-known/service/api/admin/instances';
448
+ var I18N = ${clientI18n};
319
449
  // Looked up by editInstance/deleteInstance instead of passing appName through
320
450
  // an onclick= string — see escapeHtml below for why entity-escaping alone
321
451
  // can't fully neutralize a value re-embedded as a JS string inside onclick.
@@ -331,7 +461,7 @@ export function buildAdminInstancesPageHTML() {
331
461
  } else if (data.authenticated) {
332
462
  document.getElementById('admin-content').classList.remove('hidden');
333
463
  document.getElementById('admin-content').innerHTML =
334
- '<div class="admin-card"><div class="empty-state">Admin access required.</div></div>';
464
+ '<div class="admin-card"><div class="empty-state">' + I18N.adminRequired + '</div></div>';
335
465
  } else {
336
466
  showLogin();
337
467
  }
@@ -372,25 +502,25 @@ export function buildAdminInstancesPageHTML() {
372
502
  var container = document.getElementById('instance-list');
373
503
  if (!data.ok || !data.instances || data.instances.length === 0) {
374
504
  currentInstances = [];
375
- container.innerHTML = '<div class="empty-state">No registered instances.</div>';
505
+ container.innerHTML = '<div class="empty-state">' + I18N.noInstances + '</div>';
376
506
  return;
377
507
  }
378
508
  currentInstances = data.instances;
379
509
  var html = '<ul class="instance-list">';
380
510
  data.instances.forEach(function(inst) {
381
- var name = inst.appName ? escapeHtml(inst.appName) : '(unnamed)';
511
+ var name = inst.appName ? escapeHtml(inst.appName) : I18N.unnamed;
382
512
  var didHtml = '<did-address did="' + escapeHtml(inst.instanceDid) + '" compact></did-address>';
383
513
  var time = inst.registeredAt ? new Date(inst.registeredAt).toLocaleString() : '';
384
514
  html += '<li class="instance-item">'
385
515
  + '<div class="instance-info">'
386
516
  + '<div class="instance-name">' + name + '</div>'
387
517
  + '<div class="instance-did">' + didHtml + '</div>'
388
- + (time ? '<div class="instance-time">Registered: ' + escapeHtml(time) + '</div>' : '')
518
+ + (time ? '<div class="instance-time">' + I18N.registeredTimePrefix + escapeHtml(time) + '</div>' : '')
389
519
  + '</div>'
390
520
  + '<div style="display:flex;gap:8px;align-items:center">'
391
- + '<button class="btn-secondary" onclick="location.href=\\'/.well-known/service/admin?instance=' + encodeURIComponent(inst.instanceDid) + '#members\\'">Members</button>'
392
- + '<button class="btn-secondary" onclick="editInstance(&apos;' + escapeHtml(inst.instanceDid) + '&apos;)">Edit</button>'
393
- + '<button class="btn-delete" onclick="deleteInstance(&apos;' + escapeHtml(inst.instanceDid) + '&apos;)">Delete</button>'
521
+ + '<button class="btn-secondary" onclick="location.href=\\'/.well-known/service/admin?instance=' + encodeURIComponent(inst.instanceDid) + '#members\\'">' + I18N.members + '</button>'
522
+ + '<button class="btn-secondary" onclick="editInstance(&apos;' + escapeHtml(inst.instanceDid) + '&apos;)">' + I18N.edit + '</button>'
523
+ + '<button class="btn-delete" onclick="deleteInstance(&apos;' + escapeHtml(inst.instanceDid) + '&apos;)">' + I18N.delete + '</button>'
394
524
  + '</div>'
395
525
  + '</li>';
396
526
  });
@@ -399,7 +529,7 @@ export function buildAdminInstancesPageHTML() {
399
529
  })
400
530
  .catch(function() {
401
531
  document.getElementById('instance-list').innerHTML =
402
- '<div class="empty-state">Failed to load instances.</div>';
532
+ '<div class="empty-state">' + I18N.failedToLoad + '</div>';
403
533
  });
404
534
  }
405
535
 
@@ -443,19 +573,19 @@ export function buildAdminInstancesPageHTML() {
443
573
  .then(function(r) { return r.json(); })
444
574
  .then(function(data) {
445
575
  if (data.ok) {
446
- status.innerHTML = 'Registered: <did-address did="' + escapeHtml(data.instanceDid) + '" compact></did-address>';
576
+ status.innerHTML = I18N.registeredStatusPrefix + '<did-address did="' + escapeHtml(data.instanceDid) + '" compact></did-address>';
447
577
  status.className = 'success';
448
578
  form.reset();
449
- document.getElementById('derived-did').textContent = 'Enter App PSK to see derived DID';
579
+ document.getElementById('derived-did').textContent = I18N.derivedDidPlaceholder;
450
580
  loadInstances();
451
581
  } else {
452
- status.textContent = data.error || 'Registration failed';
582
+ status.textContent = data.error || I18N.registrationFailed;
453
583
  status.className = 'error';
454
584
  }
455
585
  btn.disabled = false;
456
586
  })
457
587
  .catch(function(err) {
458
- status.textContent = err.message || 'Network error';
588
+ status.textContent = err.message || I18N.networkError;
459
589
  status.className = 'error';
460
590
  btn.disabled = false;
461
591
  });
@@ -463,7 +593,7 @@ export function buildAdminInstancesPageHTML() {
463
593
  }
464
594
 
465
595
  window.deleteInstance = function(did) {
466
- if (!confirm('Delete instance ' + did + '?')) return;
596
+ if (!confirm(I18N.confirmDeletePrefix + did + '?')) return;
467
597
  fetch(adminApi + '/' + encodeURIComponent(did), {
468
598
  method: 'DELETE',
469
599
  credentials: 'include',
@@ -471,7 +601,7 @@ export function buildAdminInstancesPageHTML() {
471
601
  .then(function(r) { return r.json(); })
472
602
  .then(function(data) {
473
603
  if (data.ok) loadInstances();
474
- else alert(data.error || 'Delete failed');
604
+ else alert(data.error || I18N.deleteFailed);
475
605
  })
476
606
  .catch(function(err) { alert(err.message); });
477
607
  };
@@ -503,7 +633,7 @@ export function buildAdminInstancesPageHTML() {
503
633
  if (val) body[f] = val;
504
634
  });
505
635
  if (Object.keys(body).length === 0) {
506
- document.getElementById('edit-status').textContent = 'No changes to save.';
636
+ document.getElementById('edit-status').textContent = I18N.noChanges;
507
637
  document.getElementById('edit-status').className = 'error';
508
638
  return;
509
639
  }
@@ -522,7 +652,7 @@ export function buildAdminInstancesPageHTML() {
522
652
  closeEditModal();
523
653
  loadInstances();
524
654
  } else {
525
- document.getElementById('edit-status').textContent = data.error || 'Update failed';
655
+ document.getElementById('edit-status').textContent = data.error || I18N.updateFailed;
526
656
  document.getElementById('edit-status').className = 'error';
527
657
  }
528
658
  })
@@ -1 +1 @@
1
- {"version":3,"file":"admin-instances-page.js","sourceRoot":"","sources":["../../src/pages/admin-instances-page.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,uEAAuE;AACvE,SAAS,eAAe,CAAC,CAAS;IAChC,OAAO,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAC9C,CAAC;AAED,+DAA+D;AAC/D,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,WAAW,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmL7B,CAAC;AAEF,MAAM,UAAU,2BAA2B;IACzC,MAAM,SAAS,GAAG,8BAA8B,CAAC;IAEjD,OAAO,UAAU,CAAC;;;;;;iCAMa,QAAQ,CAAC,WAAW,CAAC;;MAEhD,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAqGF,QAAQ,CAAC,gBAAgB,CAAC;eAC1B,QAAQ,CAAC,UAAU,CAAC;;;;qBAId,eAAe,CAAC,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA6NvC,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"admin-instances-page.js","sourceRoot":"","sources":["../../src/pages/admin-instances-page.ts"],"names":[],"mappings":"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"}
@@ -23,5 +23,5 @@ export interface GenAccessKeyPageOptions {
23
23
  /** API prefix for DID endpoints (default: /.well-known/service/api/did) */
24
24
  apiPrefix?: string;
25
25
  }
26
- export declare function buildGenAccessKeyPageHTML(options?: GenAccessKeyPageOptions): string;
26
+ export declare function buildGenAccessKeyPageHTML(options?: GenAccessKeyPageOptions, locale?: string): string;
27
27
  //# sourceMappingURL=gen-access-key-page.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gen-access-key-page.d.ts","sourceRoot":"","sources":["../../src/pages/gen-access-key-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,0BAA0B;IAC1B,cAAc,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACtF,uBAAuB;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsID,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CA2QnF"}
1
+ {"version":3,"file":"gen-access-key-page.d.ts","sourceRoot":"","sources":["../../src/pages/gen-access-key-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,0BAA0B;IAC1B,cAAc,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACtF,uBAAuB;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuMD,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,uBAAuB,EAAE,MAAM,SAAO,GAAG,MAAM,CA6UlG"}