@fonderie/react-admin-screens 0.1.0 → 0.2.0

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/README.md CHANGED
@@ -10,12 +10,13 @@ Status: **experimental** (0.x).
10
10
  |---|---|---|
11
11
  | Today | Attention | what needs me today — empty is green |
12
12
  | System | Modules · Configuration · Doctor · Routes | what did I deploy · is it configured · is it working · what is exposed |
13
+ | People | Users | why can't this person log in — lookup, sessions, sign-ins, suspend, sign out everywhere (`authClient`) |
13
14
  | Settings | Config & secrets | the `@fonderie/config` admin screens, as a sub-page |
14
15
  | Messaging | Templates | the `@fonderie/courier` admin screens, as a sub-page |
15
16
  | Activity | Admin log · Access | who did what · who can be here |
16
17
 
17
18
  ```ts
18
- import { AdminClient, ConfigAdminClient, CourierAdminClient } from '@fonderie/client';
19
+ import { AdminClient, AuthAdminClient, ConfigAdminClient, CourierAdminClient } from '@fonderie/client';
19
20
  import { AdminShell } from '@fonderie/react-admin-screens';
20
21
 
21
22
  const base = { baseUrl: 'https://api.example.com', adminToken, actor: 'louis' };
@@ -23,10 +24,11 @@ const client = new AdminClient(base);
23
24
  // prefix: the composed surface under /_admin — one token for everything.
24
25
  const configClient = new ConfigAdminClient({ ...base, prefix: '/_admin' });
25
26
  const courierClient = new CourierAdminClient({ ...base, prefix: '/_admin' });
27
+ const authClient = new AuthAdminClient(base); // @fonderie/auth ≥ 7.8
26
28
  ```
27
29
 
28
30
  ```tsx
29
- <AdminShell client={client} configClient={configClient} courierClient={courierClient} />
31
+ <AdminShell client={client} configClient={configClient} courierClient={courierClient} authClient={authClient} />
30
32
  ```
31
33
 
32
34
  Pass `page` and `onNavigate` to own the URL (one route per page); omit both
package/dist/index.cjs CHANGED
@@ -27,14 +27,15 @@ __export(index_exports, {
27
27
  DoctorScreen: () => DoctorScreen,
28
28
  ModulesScreen: () => ModulesScreen,
29
29
  RoutesScreen: () => RoutesScreen,
30
- TokensScreen: () => TokensScreen
30
+ TokensScreen: () => TokensScreen,
31
+ UsersScreen: () => UsersScreen
31
32
  });
32
33
  module.exports = __toCommonJS(index_exports);
33
34
 
34
35
  // src/screens/AdminShell.tsx
35
36
  var import_react_config_admin_screens = require("@fonderie/react-config-admin-screens");
36
37
  var import_react_courier_admin_screens = require("@fonderie/react-courier-admin-screens");
37
- var import_react = require("react");
38
+ var import_react2 = require("react");
38
39
 
39
40
  // src/styles.ts
40
41
  var styles = {
@@ -363,8 +364,153 @@ function TokensScreen({ client }) {
363
364
  ] });
364
365
  }
365
366
 
366
- // src/screens/AdminShell.tsx
367
+ // src/screens/UsersScreen.tsx
368
+ var import_react_admin8 = require("@fonderie/react-admin");
369
+ var import_react = require("react");
367
370
  var import_jsx_runtime8 = require("react/jsx-runtime");
371
+ function UsersScreen({ client }) {
372
+ const [input, setInput] = (0, import_react.useState)("");
373
+ const [email, setEmail] = (0, import_react.useState)(void 0);
374
+ const { user, isLoading, error, suspend, unsuspend, revokeSessions } = (0, import_react_admin8.useAdminUser)(
375
+ client,
376
+ email ? { email } : {}
377
+ );
378
+ const userId = user?.id ?? null;
379
+ const sessions = (0, import_react_admin8.useAdminUserSessions)(client, userId);
380
+ const history = (0, import_react_admin8.useAdminLoginHistory)(client, userId, { limit: 20 });
381
+ const yesNo = (v) => v ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.ok, children: "yes" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.muted, children: "no" });
382
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.container, children: [
383
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { style: styles.title, children: "Users" }),
384
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
385
+ "form",
386
+ {
387
+ style: styles.toolbar,
388
+ onSubmit: (e) => {
389
+ e.preventDefault();
390
+ setEmail(input.trim() || void 0);
391
+ },
392
+ children: [
393
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
394
+ "input",
395
+ {
396
+ type: "email",
397
+ value: input,
398
+ onChange: (e) => setInput(e.target.value),
399
+ placeholder: "email address",
400
+ style: { ...styles.button, cursor: "text", minWidth: 280 },
401
+ "aria-label": "Email"
402
+ }
403
+ ),
404
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "submit", style: styles.button, disabled: isLoading, children: "Look up" })
405
+ ]
406
+ }
407
+ ),
408
+ error ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: styles.error, role: "alert", children: error.status === 404 ? "No user with that email." : error.explanation }) : null,
409
+ user ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
410
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("h2", { style: styles.subtitle, children: [
411
+ user.firstName || user.lastName ? `${user.firstName} ${user.lastName}`.trim() : user.email,
412
+ " ",
413
+ user.suspended ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.badge, children: "suspended" }) : null,
414
+ user.deletedAt ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.badge, children: "deleted" }) : null
415
+ ] }),
416
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("table", { style: styles.table, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tbody", { children: [
417
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tr", { children: [
418
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: "id" }),
419
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: user.id })
420
+ ] }),
421
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tr", { children: [
422
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: "email" }),
423
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("td", { style: styles.td, children: [
424
+ user.email,
425
+ " \xB7 verified ",
426
+ yesNo(user.isEmailVerified)
427
+ ] })
428
+ ] }),
429
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tr", { children: [
430
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: "MFA" }),
431
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: yesNo(user.mfaEnabled) })
432
+ ] }),
433
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tr", { children: [
434
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: "provider" }),
435
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("td", { style: styles.td, children: [
436
+ user.provider || "password",
437
+ user.hasPassword ? "" : " \xB7 no password set"
438
+ ] })
439
+ ] }),
440
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tr", { children: [
441
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: "last login" }),
442
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: user.lastLogin ? new Date(user.lastLogin).toLocaleString() : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.muted, children: "never" }) })
443
+ ] }),
444
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("tr", { children: [
445
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: "created" }),
446
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { style: styles.td, children: new Date(user.createdAt).toLocaleString() })
447
+ ] })
448
+ ] }) }),
449
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { ...styles.toolbar, marginTop: 12 }, children: [
450
+ user.suspended ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
451
+ "button",
452
+ {
453
+ type: "button",
454
+ style: styles.button,
455
+ onClick: () => void unsuspend(),
456
+ disabled: isLoading,
457
+ children: "Unsuspend"
458
+ }
459
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
460
+ "button",
461
+ {
462
+ type: "button",
463
+ style: styles.button,
464
+ onClick: () => void suspend(),
465
+ disabled: isLoading,
466
+ children: "Suspend"
467
+ }
468
+ ),
469
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
470
+ "button",
471
+ {
472
+ type: "button",
473
+ style: styles.button,
474
+ onClick: () => void revokeSessions().then(() => sessions.refresh()),
475
+ disabled: isLoading,
476
+ children: "Sign out everywhere"
477
+ }
478
+ )
479
+ ] }),
480
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { style: styles.subtitle, children: "Live sessions" }),
481
+ sessions.sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: styles.muted, children: "None." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { style: styles.list, children: sessions.sessions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { style: styles.row, children: [
482
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.mono, children: s.ipAddress ?? "\u2014" }),
483
+ " ",
484
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.muted, children: s.userAgent ?? "" }),
485
+ " ",
486
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { style: styles.muted, children: [
487
+ "since ",
488
+ new Date(s.createdAt).toLocaleString()
489
+ ] })
490
+ ] }, s.id)) }),
491
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { style: styles.subtitle, children: "Recent sign-ins" }),
492
+ history.events.length === 0 && !history.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: styles.muted, children: "None recorded." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("ul", { style: styles.list, children: history.events.map((e) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("li", { style: styles.row, children: [
493
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: e.outcome === "success" ? styles.ok : styles.bad, children: e.outcome }),
494
+ " ",
495
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.muted, children: e.method }),
496
+ " ",
497
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: styles.muted, children: new Date(e.createdAt).toLocaleString() })
498
+ ] }, e.id)) }),
499
+ history.hasMore && !history.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
500
+ "button",
501
+ {
502
+ type: "button",
503
+ style: { ...styles.button, marginTop: 8 },
504
+ onClick: () => void history.loadMore(),
505
+ children: "Load more"
506
+ }
507
+ ) : null
508
+ ] }) : null
509
+ ] });
510
+ }
511
+
512
+ // src/screens/AdminShell.tsx
513
+ var import_jsx_runtime9 = require("react/jsx-runtime");
368
514
  var NAV = [
369
515
  { group: "Today", items: [{ page: "attention", label: "Attention" }] },
370
516
  {
@@ -376,6 +522,7 @@ var NAV = [
376
522
  { page: "routes", label: "Routes" }
377
523
  ]
378
524
  },
525
+ { group: "People", items: [{ page: "users", label: "Users", needs: "auth" }] },
379
526
  { group: "Settings", items: [{ page: "settings", label: "Config & secrets", needs: "config" }] },
380
527
  { group: "Messaging", items: [{ page: "templates", label: "Templates", needs: "courier" }] },
381
528
  {
@@ -390,45 +537,53 @@ function AdminShell({
390
537
  client,
391
538
  configClient,
392
539
  courierClient,
540
+ authClient,
393
541
  environment,
394
542
  page,
395
543
  onNavigate
396
544
  }) {
397
- const [own, setOwn] = (0, import_react.useState)("attention");
545
+ const [own, setOwn] = (0, import_react2.useState)("attention");
398
546
  const current = page ?? own;
399
547
  const go = (p) => {
400
548
  if (onNavigate) onNavigate(p);
401
549
  if (page === void 0) setOwn(p);
402
550
  };
403
- const [editing, setEditing] = (0, import_react.useState)(null);
404
- const has = { config: Boolean(configClient), courier: Boolean(courierClient) };
551
+ const [editing, setEditing] = (0, import_react2.useState)(null);
552
+ const has = {
553
+ config: Boolean(configClient),
554
+ courier: Boolean(courierClient),
555
+ auth: Boolean(authClient)
556
+ };
405
557
  let body;
406
558
  switch (current) {
407
559
  case "attention":
408
- body = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AttentionScreen, { client });
560
+ body = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AttentionScreen, { client });
409
561
  break;
410
562
  case "modules":
411
- body = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ModulesScreen, { client });
563
+ body = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ModulesScreen, { client });
412
564
  break;
413
565
  case "doctor":
414
- body = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DoctorScreen, { client });
566
+ body = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DoctorScreen, { client });
415
567
  break;
416
568
  case "config":
417
- body = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ConfigScreen, { client });
569
+ body = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ConfigScreen, { client });
418
570
  break;
419
571
  case "routes":
420
- body = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(RoutesScreen, { client });
572
+ body = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(RoutesScreen, { client });
421
573
  break;
422
574
  case "tokens":
423
- body = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TokensScreen, { client });
575
+ body = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TokensScreen, { client });
424
576
  break;
425
577
  case "log":
426
- body = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AdminLogScreen, { client });
578
+ body = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AdminLogScreen, { client });
579
+ break;
580
+ case "users":
581
+ body = authClient ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(UsersScreen, { client: authClient }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: styles.status, children: "Pass an AuthAdminClient to look up users here." });
427
582
  break;
428
583
  case "settings":
429
- body = !configClient ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: styles.status, children: "Pass a ConfigAdminClient to manage config and secrets here." }) : editing && editing.kind !== "template" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
430
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
431
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
584
+ body = !configClient ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: styles.status, children: "Pass a ConfigAdminClient to manage config and secrets here." }) : editing && editing.kind !== "template" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
585
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
586
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
432
587
  import_react_config_admin_screens.ConfigEditorScreen,
433
588
  {
434
589
  client: configClient,
@@ -438,7 +593,7 @@ function AdminShell({
438
593
  onSaved: () => setEditing(null)
439
594
  }
440
595
  )
441
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
596
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
442
597
  import_react_config_admin_screens.ConfigListScreen,
443
598
  {
444
599
  client: configClient,
@@ -449,9 +604,9 @@ function AdminShell({
449
604
  );
450
605
  break;
451
606
  case "templates":
452
- body = !courierClient ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: styles.status, children: "Pass a CourierAdminClient to manage templates here." }) : editing?.kind === "template" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
453
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
454
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
607
+ body = !courierClient ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: styles.status, children: "Pass a CourierAdminClient to manage templates here." }) : editing?.kind === "template" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
608
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
609
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
455
610
  import_react_courier_admin_screens.TemplateEditorScreen,
456
611
  {
457
612
  client: courierClient,
@@ -459,7 +614,7 @@ function AdminShell({
459
614
  onSaved: () => setEditing(null)
460
615
  }
461
616
  )
462
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
617
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
463
618
  import_react_courier_admin_screens.TemplateListScreen,
464
619
  {
465
620
  client: courierClient,
@@ -468,13 +623,13 @@ function AdminShell({
468
623
  );
469
624
  break;
470
625
  }
471
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.shell, children: [
472
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("nav", { style: styles.nav, "aria-label": "Admin", children: NAV.map((g) => {
626
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.shell, children: [
627
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("nav", { style: styles.nav, "aria-label": "Admin", children: NAV.map((g) => {
473
628
  const items = g.items.filter((i) => !i.needs || has[i.needs]);
474
629
  if (items.length === 0) return null;
475
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
476
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: styles.navGroup, children: g.group }),
477
- items.map((i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
630
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
631
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.navGroup, children: g.group }),
632
+ items.map((i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
478
633
  "button",
479
634
  {
480
635
  type: "button",
@@ -490,7 +645,7 @@ function AdminShell({
490
645
  ))
491
646
  ] }, g.group);
492
647
  }) }),
493
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("main", { style: styles.main, children: body })
648
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("main", { style: styles.main, children: body })
494
649
  ] });
495
650
  }
496
651
  // Annotate the CommonJS export names for ESM import in node:
@@ -502,6 +657,7 @@ function AdminShell({
502
657
  DoctorScreen,
503
658
  ModulesScreen,
504
659
  RoutesScreen,
505
- TokensScreen
660
+ TokensScreen,
661
+ UsersScreen
506
662
  });
507
663
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/screens/AdminShell.tsx","../src/styles.ts","../src/screens/AdminLogScreen.tsx","../src/screens/AttentionScreen.tsx","../src/screens/ConfigScreen.tsx","../src/screens/DoctorScreen.tsx","../src/screens/ModulesScreen.tsx","../src/screens/RoutesScreen.tsx","../src/screens/TokensScreen.tsx"],"sourcesContent":["export type {\n\tAdminPage,\n\tIAdminLogScreenProps,\n\tIAdminShellProps,\n\tIAttentionScreenProps,\n\tIConfigScreenProps,\n\tIDoctorScreenProps,\n\tIModulesScreenProps,\n\tIRoutesScreenProps,\n\tITokensScreenProps,\n} from './screens';\nexport {\n\tAdminLogScreen,\n\tAdminShell,\n\tAttentionScreen,\n\tConfigScreen,\n\tDoctorScreen,\n\tModulesScreen,\n\tRoutesScreen,\n\tTokensScreen,\n} from './screens';\n","import type { AdminClient, ConfigAdminClient, CourierAdminClient } from '@fonderie/client';\nimport { ConfigEditorScreen, ConfigListScreen } from '@fonderie/react-config-admin-screens';\nimport { TemplateEditorScreen, TemplateListScreen } from '@fonderie/react-courier-admin-screens';\nimport { useState } from 'react';\nimport { styles } from '../styles';\nimport { AdminLogScreen } from './AdminLogScreen';\nimport { AttentionScreen } from './AttentionScreen';\nimport { ConfigScreen } from './ConfigScreen';\nimport { DoctorScreen } from './DoctorScreen';\nimport { ModulesScreen } from './ModulesScreen';\nimport { RoutesScreen } from './RoutesScreen';\nimport { TokensScreen } from './TokensScreen';\n\nexport type AdminPage =\n\t| 'attention'\n\t| 'modules'\n\t| 'doctor'\n\t| 'config'\n\t| 'routes'\n\t| 'tokens'\n\t| 'log'\n\t| 'settings'\n\t| 'templates';\n\nexport interface IAdminShellProps {\n\tclient: AdminClient;\n\t// Given ⇒ the Settings (config + secrets) and Messaging (templates) pages\n\t// appear. Construct them with `prefix: '/_admin'` to go through the one token.\n\tconfigClient?: ConfigAdminClient;\n\tcourierClient?: CourierAdminClient;\n\tenvironment?: string;\n\t// Controlled navigation: pass both to own the URL. Omit both and the shell\n\t// keeps the page itself.\n\tpage?: AdminPage;\n\tonNavigate?: (page: AdminPage) => void;\n}\n\nconst NAV: Array<{\n\tgroup: string;\n\titems: Array<{ page: AdminPage; label: string; needs?: 'config' | 'courier' }>;\n}> = [\n\t{ group: 'Today', items: [{ page: 'attention', label: 'Attention' }] },\n\t{\n\t\tgroup: 'System',\n\t\titems: [\n\t\t\t{ page: 'modules', label: 'Modules' },\n\t\t\t{ page: 'config', label: 'Configuration' },\n\t\t\t{ page: 'doctor', label: 'Doctor' },\n\t\t\t{ page: 'routes', label: 'Routes' },\n\t\t],\n\t},\n\t{ group: 'Settings', items: [{ page: 'settings', label: 'Config & secrets', needs: 'config' }] },\n\t{ group: 'Messaging', items: [{ page: 'templates', label: 'Templates', needs: 'courier' }] },\n\t{\n\t\tgroup: 'Activity',\n\t\titems: [\n\t\t\t{ page: 'log', label: 'Admin log' },\n\t\t\t{ page: 'tokens', label: 'Access' },\n\t\t],\n\t},\n];\n\nexport function AdminShell({\n\tclient,\n\tconfigClient,\n\tcourierClient,\n\tenvironment,\n\tpage,\n\tonNavigate,\n}: IAdminShellProps) {\n\tconst [own, setOwn] = useState<AdminPage>('attention');\n\tconst current = page ?? own;\n\tconst go = (p: AdminPage) => {\n\t\tif (onNavigate) onNavigate(p);\n\t\tif (page === undefined) setOwn(p);\n\t};\n\tconst [editing, setEditing] = useState<\n\t\t{ kind: 'config' | 'secret'; key: string } | { kind: 'template'; type: string } | null\n\t>(null);\n\n\tconst has = { config: Boolean(configClient), courier: Boolean(courierClient) };\n\n\tlet body: React.ReactNode;\n\tswitch (current) {\n\t\tcase 'attention':\n\t\t\tbody = <AttentionScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'modules':\n\t\t\tbody = <ModulesScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'doctor':\n\t\t\tbody = <DoctorScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'config':\n\t\t\tbody = <ConfigScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'routes':\n\t\t\tbody = <RoutesScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'tokens':\n\t\t\tbody = <TokensScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'log':\n\t\t\tbody = <AdminLogScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'settings':\n\t\t\tbody = !configClient ? (\n\t\t\t\t<p style={styles.status}>Pass a ConfigAdminClient to manage config and secrets here.</p>\n\t\t\t) : editing && editing.kind !== 'template' ? (\n\t\t\t\t<>\n\t\t\t\t\t<button type=\"button\" style={styles.button} onClick={() => setEditing(null)}>\n\t\t\t\t\t\t← Back\n\t\t\t\t\t</button>\n\t\t\t\t\t<ConfigEditorScreen\n\t\t\t\t\t\tclient={configClient}\n\t\t\t\t\t\tkind={editing.kind}\n\t\t\t\t\t\tconfigKey={editing.key}\n\t\t\t\t\t\t{...(environment !== undefined ? { environment } : {})}\n\t\t\t\t\t\tonSaved={() => setEditing(null)}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<ConfigListScreen\n\t\t\t\t\tclient={configClient}\n\t\t\t\t\t{...(environment !== undefined ? { environment } : {})}\n\t\t\t\t\tonSelectConfig={(key) => setEditing({ kind: 'config', key })}\n\t\t\t\t\tonSelectSecret={(key) => setEditing({ kind: 'secret', key })}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tbreak;\n\t\tcase 'templates':\n\t\t\tbody = !courierClient ? (\n\t\t\t\t<p style={styles.status}>Pass a CourierAdminClient to manage templates here.</p>\n\t\t\t) : editing?.kind === 'template' ? (\n\t\t\t\t<>\n\t\t\t\t\t<button type=\"button\" style={styles.button} onClick={() => setEditing(null)}>\n\t\t\t\t\t\t← Back\n\t\t\t\t\t</button>\n\t\t\t\t\t<TemplateEditorScreen\n\t\t\t\t\t\tclient={courierClient}\n\t\t\t\t\t\ttype={editing.type}\n\t\t\t\t\t\tonSaved={() => setEditing(null)}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<TemplateListScreen\n\t\t\t\t\tclient={courierClient}\n\t\t\t\t\tonSelectTemplate={(t) => setEditing({ kind: 'template', type: t.type })}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tbreak;\n\t}\n\n\treturn (\n\t\t<div style={styles.shell}>\n\t\t\t<nav style={styles.nav} aria-label=\"Admin\">\n\t\t\t\t{NAV.map((g) => {\n\t\t\t\t\tconst items = g.items.filter((i) => !i.needs || has[i.needs]);\n\t\t\t\t\tif (items.length === 0) return null;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={g.group}>\n\t\t\t\t\t\t\t<div style={styles.navGroup}>{g.group}</div>\n\t\t\t\t\t\t\t{items.map((i) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={i.page}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tstyle={{ ...styles.navItem, ...(current === i.page ? styles.navItemActive : {}) }}\n\t\t\t\t\t\t\t\t\taria-current={current === i.page ? 'page' : undefined}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetEditing(null);\n\t\t\t\t\t\t\t\t\t\tgo(i.page);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{i.label}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</nav>\n\t\t\t<main style={styles.main}>{body}</main>\n\t\t</div>\n\t);\n}\n","import type { CSSProperties } from 'react';\n\n// One palette for every admin page; the same values as the config and courier\n// admin screens so the shell reads as one surface.\nexport const styles: Record<string, CSSProperties> = {\n\tshell: {\n\t\tdisplay: 'flex',\n\t\tminHeight: '100vh',\n\t\tfontFamily: 'system-ui, sans-serif',\n\t\tcolor: '#111',\n\t},\n\tnav: { width: 220, borderRight: '1px solid #eee', padding: 16, flexShrink: 0 },\n\tnavGroup: {\n\t\tfontSize: 11,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: 0.6,\n\t\tcolor: '#888',\n\t\tmargin: '16px 0 6px',\n\t},\n\tnavItem: {\n\t\tdisplay: 'block',\n\t\twidth: '100%',\n\t\ttextAlign: 'left',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tborderRadius: 6,\n\t\tpadding: '6px 8px',\n\t\tcursor: 'pointer',\n\t\tfontSize: 14,\n\t\tcolor: '#111',\n\t},\n\tnavItemActive: { background: '#f3f4f6', fontWeight: 600 },\n\tmain: { flex: 1, padding: 24, maxWidth: 960 },\n\tcontainer: { padding: 24, maxWidth: 960 },\n\ttitle: { fontSize: 20, fontWeight: 700, marginTop: 0, marginBottom: 12 },\n\tsubtitle: { fontSize: 15, fontWeight: 600, marginTop: 24, marginBottom: 8 },\n\tstatus: { padding: 12, color: '#666' },\n\terror: { color: '#e11d48', marginBottom: 12, fontSize: 14 },\n\tok: { color: '#15803d', fontWeight: 600 },\n\tbad: { color: '#e11d48', fontWeight: 600 },\n\tadvice: { color: '#b45309' },\n\tmuted: { color: '#666', fontSize: 13 },\n\tmono: { fontFamily: 'ui-monospace, monospace', fontSize: 13 },\n\ttable: { width: '100%', borderCollapse: 'collapse', fontSize: 14 },\n\tth: {\n\t\ttextAlign: 'left',\n\t\tborderBottom: '1px solid #ddd',\n\t\tpadding: '6px 8px',\n\t\tfontWeight: 600,\n\t\tcolor: '#444',\n\t},\n\ttd: { borderBottom: '1px solid #eee', padding: '6px 8px', verticalAlign: 'top' },\n\tlist: { listStyle: 'none', padding: 0, margin: 0 },\n\trow: { borderBottom: '1px solid #eee', padding: '8px 0' },\n\tbadge: {\n\t\tdisplay: 'inline-block',\n\t\tborderRadius: 999,\n\t\tpadding: '1px 8px',\n\t\tfontSize: 12,\n\t\tbackground: '#f3f4f6',\n\t},\n\tbutton: {\n\t\tbackground: 'none',\n\t\tborder: '1px solid #ddd',\n\t\tborderRadius: 8,\n\t\tpadding: '4px 10px',\n\t\tcursor: 'pointer',\n\t\tfontSize: 13,\n\t},\n\ttoolbar: { display: 'flex', gap: 8, alignItems: 'center', marginBottom: 12 },\n};\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminLog } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IAdminLogScreenProps {\n\tclient: AdminClient;\n\tpageSize?: number;\n}\n\n// Who did what through the surface, newest first — refused requests included.\nexport function AdminLogScreen({ client, pageSize = 50 }: IAdminLogScreenProps) {\n\tconst { entries, hasMore, isLoading, error, refresh, loadMore } = useAdminLog(client, {\n\t\tlimit: pageSize,\n\t});\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Admin log</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRefresh\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.status === 404\n\t\t\t\t\t\t? 'The admin log is off — give AdminModule a store.'\n\t\t\t\t\t\t: error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style={styles.th}>When</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Actor</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Request</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Status</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{entries.map((e) => (\n\t\t\t\t\t\t\t\t<tr key={e.id}>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>\n\t\t\t\t\t\t\t\t\t\t{new Date(e.at).toLocaleString()}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>{e.actor}</td>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>\n\t\t\t\t\t\t\t\t\t\t{e.method} {e.path}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t<span style={e.status >= 400 ? styles.bad : styles.ok}>{e.status}</span>{' '}\n\t\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{e.durationMs} ms</span>\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>{e.module}</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t\t{isLoading ? <p style={styles.status}>Loading…</p> : null}\n\t\t\t\t\t{hasMore && !isLoading ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={{ ...styles.button, marginTop: 12 }}\n\t\t\t\t\t\t\tonClick={() => void loadMore()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tLoad more\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : null}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAttention } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IAttentionScreenProps {\n\tclient: AdminClient;\n}\n\n// What needs the operator today. Empty is green.\nexport function AttentionScreen({ client }: IAttentionScreenProps) {\n\tconst { attention, isLoading, error, refresh } = useAttention(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Attention</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRefresh\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{isLoading && !attention ? (\n\t\t\t\t<p style={styles.status}>Running the checks…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : attention?.items.length === 0 ? (\n\t\t\t\t<p style={styles.ok}>\n\t\t\t\t\tNothing needs you. Checked {new Date(attention.generatedAt).toLocaleString()}.\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{attention?.items.map((item) => (\n\t\t\t\t\t\t<li key={`${item.source}:${item.message}`} style={styles.row}>\n\t\t\t\t\t\t\t<span style={item.severity === 'error' ? styles.bad : styles.advice}>\n\t\t\t\t\t\t\t\t{item.severity === 'error' ? 'error' : 'advice'}\n\t\t\t\t\t\t\t</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.mono}>{item.source}</span> — {item.message}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminConfig } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IConfigScreenProps {\n\tclient: AdminClient;\n}\n\n// Declared vs held: readiness per module, and whether each environment\n// variable the app reads is set. Values are never shown.\nexport function ConfigScreen({ client }: IConfigScreenProps) {\n\tconst { report, isLoading, error } = useAdminConfig(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Configuration</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : report ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>Readiness</h2>\n\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t{report.modules.map((m) => (\n\t\t\t\t\t\t\t<li key={m.name} style={styles.row}>\n\t\t\t\t\t\t\t\t<span style={styles.mono}>{m.name}</span>{' '}\n\t\t\t\t\t\t\t\t{m.problems.length === 0 ? (\n\t\t\t\t\t\t\t\t\t<span style={styles.ok}>ok</span>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\tm.problems.map((p) => (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={p.message}\n\t\t\t\t\t\t\t\t\t\t\tstyle={p.severity === 'error' ? styles.bad : styles.advice}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t\t<h2 style={styles.subtitle}>Environment</h2>\n\t\t\t\t\t{report.env.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>No variables declared — pass `env` to AdminModule.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{report.env.map((e) => (\n\t\t\t\t\t\t\t\t<li key={e.name} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{e.name}</span>{' '}\n\t\t\t\t\t\t\t\t\t{e.set ? (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.ok}>set</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.bad}>missing</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useDoctor } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IDoctorScreenProps {\n\tclient: AdminClient;\n}\n\n// Every reconciliation check, on demand. ok is false only for a hard failure;\n// findings on a passing check are advice.\nexport function DoctorScreen({ client }: IDoctorScreenProps) {\n\tconst { report, isLoading, error, refresh } = useDoctor(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Doctor</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRun again\n\t\t\t\t</button>\n\t\t\t\t{report && !isLoading ? (\n\t\t\t\t\t<span style={report.ok ? styles.ok : styles.bad}>\n\t\t\t\t\t\t{report.ok ? 'all checks pass' : 'a check failed'}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t{isLoading && !report ? (\n\t\t\t\t<p style={styles.status}>Running the checks…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{report?.checks.map((c) => (\n\t\t\t\t\t\t<li key={c.name} style={styles.row}>\n\t\t\t\t\t\t\t<span style={c.skipped ? styles.muted : c.ok ? styles.ok : styles.bad}>\n\t\t\t\t\t\t\t\t{c.skipped ? 'skipped' : c.ok ? 'ok' : 'failed'}\n\t\t\t\t\t\t\t</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.mono}>{c.name}</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.muted}>\n\t\t\t\t\t\t\t\t{c.module} · {c.durationMs} ms\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{c.skipped ? <div style={styles.muted}>{c.skipped}</div> : null}\n\t\t\t\t\t\t\t{c.findings.map((f) => (\n\t\t\t\t\t\t\t\t<div key={f} style={c.ok ? styles.advice : styles.bad}>\n\t\t\t\t\t\t\t\t\t{f}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useManifest } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IModulesScreenProps {\n\tclient: AdminClient;\n}\n\n// What is deployed: every module, its version, readiness, and whether it\n// offers anything to this surface.\nexport function ModulesScreen({ client }: IModulesScreenProps) {\n\tconst { manifest, isLoading, error } = useManifest(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Modules</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : manifest ? (\n\t\t\t\t<>\n\t\t\t\t\t<p style={styles.muted}>\n\t\t\t\t\t\t{manifest.env} · admin {manifest.admin.version} · admin log{' '}\n\t\t\t\t\t\t{manifest.admin.log ? 'on' : 'off'} · {manifest.routes.length} routes\n\t\t\t\t\t</p>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Version</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Readiness</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Describes admin</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{manifest.modules.map((m) => (\n\t\t\t\t\t\t\t\t<tr key={m.name}>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{m.name}</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.version ?? <span style={styles.muted}>not reported</span>}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.readiness.ok ? (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.ok}>ok</span>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.bad}>error</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{m.readiness.problems.map((p) => (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tkey={p.message}\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={p.severity === 'error' ? styles.bad : styles.advice}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.describesAdmin ? 'yes' : <span style={styles.muted}>no</span>}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminRoutes } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IRoutesScreenProps {\n\tclient: AdminClient;\n}\n\nexport function RoutesScreen({ client }: IRoutesScreenProps) {\n\tconst { report, isLoading, error } = useAdminRoutes(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Routes</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th style={styles.th}>Method</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Path</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Guard</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{report?.routes.map((r) => (\n\t\t\t\t\t\t\t<tr key={`${r.method} ${r.path}`}>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{r.method}</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{r.path}</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t<span style={styles.badge}>{r.guard}</span>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>{r.module ?? 'application'}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminTokens } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface ITokensScreenProps {\n\tclient: AdminClient;\n}\n\nexport function TokensScreen({ client }: ITokensScreenProps) {\n\tconst { report, isLoading, error } = useAdminTokens(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Access</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : report ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>Admin token</h2>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t{report.admin.ok ? (\n\t\t\t\t\t\t\t<span style={styles.ok}>strong</span>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span style={styles.bad}>weak</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{report.admin.problems.map((p) => (\n\t\t\t\t\t\t\t<div key={p.message} style={styles.bad}>\n\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</p>\n\t\t\t\t\t<h2 style={styles.subtitle}>Legacy per-brick tokens</h2>\n\t\t\t\t\t{report.legacy.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>None — every brick's admin surface goes through this token.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{report.legacy.map((l) => (\n\t\t\t\t\t\t\t\t<li key={l.module} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{l.module}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>\n\t\t\t\t\t\t\t\t\t\tstill registers its standalone routes with its own token (deprecated)\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":"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","names":["import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/screens/AdminShell.tsx","../src/styles.ts","../src/screens/AdminLogScreen.tsx","../src/screens/AttentionScreen.tsx","../src/screens/ConfigScreen.tsx","../src/screens/DoctorScreen.tsx","../src/screens/ModulesScreen.tsx","../src/screens/RoutesScreen.tsx","../src/screens/TokensScreen.tsx","../src/screens/UsersScreen.tsx"],"sourcesContent":["export type {\n\tAdminPage,\n\tIAdminLogScreenProps,\n\tIAdminShellProps,\n\tIAttentionScreenProps,\n\tIConfigScreenProps,\n\tIDoctorScreenProps,\n\tIModulesScreenProps,\n\tIRoutesScreenProps,\n\tITokensScreenProps,\n\tIUsersScreenProps,\n} from './screens';\nexport {\n\tAdminLogScreen,\n\tAdminShell,\n\tAttentionScreen,\n\tConfigScreen,\n\tDoctorScreen,\n\tModulesScreen,\n\tRoutesScreen,\n\tTokensScreen,\n\tUsersScreen,\n} from './screens';\n","import type {\n\tAdminClient,\n\tAuthAdminClient,\n\tConfigAdminClient,\n\tCourierAdminClient,\n} from '@fonderie/client';\nimport { ConfigEditorScreen, ConfigListScreen } from '@fonderie/react-config-admin-screens';\nimport { TemplateEditorScreen, TemplateListScreen } from '@fonderie/react-courier-admin-screens';\nimport { useState } from 'react';\nimport { styles } from '../styles';\nimport { AdminLogScreen } from './AdminLogScreen';\nimport { AttentionScreen } from './AttentionScreen';\nimport { ConfigScreen } from './ConfigScreen';\nimport { DoctorScreen } from './DoctorScreen';\nimport { ModulesScreen } from './ModulesScreen';\nimport { RoutesScreen } from './RoutesScreen';\nimport { TokensScreen } from './TokensScreen';\nimport { UsersScreen } from './UsersScreen';\n\nexport type AdminPage =\n\t| 'attention'\n\t| 'modules'\n\t| 'doctor'\n\t| 'config'\n\t| 'routes'\n\t| 'tokens'\n\t| 'log'\n\t| 'settings'\n\t| 'templates'\n\t| 'users';\n\nexport interface IAdminShellProps {\n\tclient: AdminClient;\n\t// Given ⇒ the Settings (config + secrets) and Messaging (templates) pages\n\t// appear. Construct them with `prefix: '/_admin'` to go through the one token.\n\tconfigClient?: ConfigAdminClient;\n\tcourierClient?: CourierAdminClient;\n\t// Given ⇒ the People page (users) appears; needs @fonderie/auth ≥ 7.8.\n\tauthClient?: AuthAdminClient;\n\tenvironment?: string;\n\t// Controlled navigation: pass both to own the URL. Omit both and the shell\n\t// keeps the page itself.\n\tpage?: AdminPage;\n\tonNavigate?: (page: AdminPage) => void;\n}\n\nconst NAV: Array<{\n\tgroup: string;\n\titems: Array<{ page: AdminPage; label: string; needs?: 'config' | 'courier' | 'auth' }>;\n}> = [\n\t{ group: 'Today', items: [{ page: 'attention', label: 'Attention' }] },\n\t{\n\t\tgroup: 'System',\n\t\titems: [\n\t\t\t{ page: 'modules', label: 'Modules' },\n\t\t\t{ page: 'config', label: 'Configuration' },\n\t\t\t{ page: 'doctor', label: 'Doctor' },\n\t\t\t{ page: 'routes', label: 'Routes' },\n\t\t],\n\t},\n\t{ group: 'People', items: [{ page: 'users', label: 'Users', needs: 'auth' }] },\n\t{ group: 'Settings', items: [{ page: 'settings', label: 'Config & secrets', needs: 'config' }] },\n\t{ group: 'Messaging', items: [{ page: 'templates', label: 'Templates', needs: 'courier' }] },\n\t{\n\t\tgroup: 'Activity',\n\t\titems: [\n\t\t\t{ page: 'log', label: 'Admin log' },\n\t\t\t{ page: 'tokens', label: 'Access' },\n\t\t],\n\t},\n];\n\nexport function AdminShell({\n\tclient,\n\tconfigClient,\n\tcourierClient,\n\tauthClient,\n\tenvironment,\n\tpage,\n\tonNavigate,\n}: IAdminShellProps) {\n\tconst [own, setOwn] = useState<AdminPage>('attention');\n\tconst current = page ?? own;\n\tconst go = (p: AdminPage) => {\n\t\tif (onNavigate) onNavigate(p);\n\t\tif (page === undefined) setOwn(p);\n\t};\n\tconst [editing, setEditing] = useState<\n\t\t{ kind: 'config' | 'secret'; key: string } | { kind: 'template'; type: string } | null\n\t>(null);\n\n\tconst has = {\n\t\tconfig: Boolean(configClient),\n\t\tcourier: Boolean(courierClient),\n\t\tauth: Boolean(authClient),\n\t};\n\n\tlet body: React.ReactNode;\n\tswitch (current) {\n\t\tcase 'attention':\n\t\t\tbody = <AttentionScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'modules':\n\t\t\tbody = <ModulesScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'doctor':\n\t\t\tbody = <DoctorScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'config':\n\t\t\tbody = <ConfigScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'routes':\n\t\t\tbody = <RoutesScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'tokens':\n\t\t\tbody = <TokensScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'log':\n\t\t\tbody = <AdminLogScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'users':\n\t\t\tbody = authClient ? (\n\t\t\t\t<UsersScreen client={authClient} />\n\t\t\t) : (\n\t\t\t\t<p style={styles.status}>Pass an AuthAdminClient to look up users here.</p>\n\t\t\t);\n\t\t\tbreak;\n\t\tcase 'settings':\n\t\t\tbody = !configClient ? (\n\t\t\t\t<p style={styles.status}>Pass a ConfigAdminClient to manage config and secrets here.</p>\n\t\t\t) : editing && editing.kind !== 'template' ? (\n\t\t\t\t<>\n\t\t\t\t\t<button type=\"button\" style={styles.button} onClick={() => setEditing(null)}>\n\t\t\t\t\t\t← Back\n\t\t\t\t\t</button>\n\t\t\t\t\t<ConfigEditorScreen\n\t\t\t\t\t\tclient={configClient}\n\t\t\t\t\t\tkind={editing.kind}\n\t\t\t\t\t\tconfigKey={editing.key}\n\t\t\t\t\t\t{...(environment !== undefined ? { environment } : {})}\n\t\t\t\t\t\tonSaved={() => setEditing(null)}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<ConfigListScreen\n\t\t\t\t\tclient={configClient}\n\t\t\t\t\t{...(environment !== undefined ? { environment } : {})}\n\t\t\t\t\tonSelectConfig={(key) => setEditing({ kind: 'config', key })}\n\t\t\t\t\tonSelectSecret={(key) => setEditing({ kind: 'secret', key })}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tbreak;\n\t\tcase 'templates':\n\t\t\tbody = !courierClient ? (\n\t\t\t\t<p style={styles.status}>Pass a CourierAdminClient to manage templates here.</p>\n\t\t\t) : editing?.kind === 'template' ? (\n\t\t\t\t<>\n\t\t\t\t\t<button type=\"button\" style={styles.button} onClick={() => setEditing(null)}>\n\t\t\t\t\t\t← Back\n\t\t\t\t\t</button>\n\t\t\t\t\t<TemplateEditorScreen\n\t\t\t\t\t\tclient={courierClient}\n\t\t\t\t\t\ttype={editing.type}\n\t\t\t\t\t\tonSaved={() => setEditing(null)}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<TemplateListScreen\n\t\t\t\t\tclient={courierClient}\n\t\t\t\t\tonSelectTemplate={(t) => setEditing({ kind: 'template', type: t.type })}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tbreak;\n\t}\n\n\treturn (\n\t\t<div style={styles.shell}>\n\t\t\t<nav style={styles.nav} aria-label=\"Admin\">\n\t\t\t\t{NAV.map((g) => {\n\t\t\t\t\tconst items = g.items.filter((i) => !i.needs || has[i.needs]);\n\t\t\t\t\tif (items.length === 0) return null;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={g.group}>\n\t\t\t\t\t\t\t<div style={styles.navGroup}>{g.group}</div>\n\t\t\t\t\t\t\t{items.map((i) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={i.page}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tstyle={{ ...styles.navItem, ...(current === i.page ? styles.navItemActive : {}) }}\n\t\t\t\t\t\t\t\t\taria-current={current === i.page ? 'page' : undefined}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetEditing(null);\n\t\t\t\t\t\t\t\t\t\tgo(i.page);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{i.label}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</nav>\n\t\t\t<main style={styles.main}>{body}</main>\n\t\t</div>\n\t);\n}\n","import type { CSSProperties } from 'react';\n\n// One palette for every admin page; the same values as the config and courier\n// admin screens so the shell reads as one surface.\nexport const styles: Record<string, CSSProperties> = {\n\tshell: {\n\t\tdisplay: 'flex',\n\t\tminHeight: '100vh',\n\t\tfontFamily: 'system-ui, sans-serif',\n\t\tcolor: '#111',\n\t},\n\tnav: { width: 220, borderRight: '1px solid #eee', padding: 16, flexShrink: 0 },\n\tnavGroup: {\n\t\tfontSize: 11,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: 0.6,\n\t\tcolor: '#888',\n\t\tmargin: '16px 0 6px',\n\t},\n\tnavItem: {\n\t\tdisplay: 'block',\n\t\twidth: '100%',\n\t\ttextAlign: 'left',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tborderRadius: 6,\n\t\tpadding: '6px 8px',\n\t\tcursor: 'pointer',\n\t\tfontSize: 14,\n\t\tcolor: '#111',\n\t},\n\tnavItemActive: { background: '#f3f4f6', fontWeight: 600 },\n\tmain: { flex: 1, padding: 24, maxWidth: 960 },\n\tcontainer: { padding: 24, maxWidth: 960 },\n\ttitle: { fontSize: 20, fontWeight: 700, marginTop: 0, marginBottom: 12 },\n\tsubtitle: { fontSize: 15, fontWeight: 600, marginTop: 24, marginBottom: 8 },\n\tstatus: { padding: 12, color: '#666' },\n\terror: { color: '#e11d48', marginBottom: 12, fontSize: 14 },\n\tok: { color: '#15803d', fontWeight: 600 },\n\tbad: { color: '#e11d48', fontWeight: 600 },\n\tadvice: { color: '#b45309' },\n\tmuted: { color: '#666', fontSize: 13 },\n\tmono: { fontFamily: 'ui-monospace, monospace', fontSize: 13 },\n\ttable: { width: '100%', borderCollapse: 'collapse', fontSize: 14 },\n\tth: {\n\t\ttextAlign: 'left',\n\t\tborderBottom: '1px solid #ddd',\n\t\tpadding: '6px 8px',\n\t\tfontWeight: 600,\n\t\tcolor: '#444',\n\t},\n\ttd: { borderBottom: '1px solid #eee', padding: '6px 8px', verticalAlign: 'top' },\n\tlist: { listStyle: 'none', padding: 0, margin: 0 },\n\trow: { borderBottom: '1px solid #eee', padding: '8px 0' },\n\tbadge: {\n\t\tdisplay: 'inline-block',\n\t\tborderRadius: 999,\n\t\tpadding: '1px 8px',\n\t\tfontSize: 12,\n\t\tbackground: '#f3f4f6',\n\t},\n\tbutton: {\n\t\tbackground: 'none',\n\t\tborder: '1px solid #ddd',\n\t\tborderRadius: 8,\n\t\tpadding: '4px 10px',\n\t\tcursor: 'pointer',\n\t\tfontSize: 13,\n\t},\n\ttoolbar: { display: 'flex', gap: 8, alignItems: 'center', marginBottom: 12 },\n};\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminLog } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IAdminLogScreenProps {\n\tclient: AdminClient;\n\tpageSize?: number;\n}\n\n// Who did what through the surface, newest first — refused requests included.\nexport function AdminLogScreen({ client, pageSize = 50 }: IAdminLogScreenProps) {\n\tconst { entries, hasMore, isLoading, error, refresh, loadMore } = useAdminLog(client, {\n\t\tlimit: pageSize,\n\t});\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Admin log</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRefresh\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.status === 404\n\t\t\t\t\t\t? 'The admin log is off — give AdminModule a store.'\n\t\t\t\t\t\t: error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style={styles.th}>When</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Actor</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Request</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Status</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{entries.map((e) => (\n\t\t\t\t\t\t\t\t<tr key={e.id}>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>\n\t\t\t\t\t\t\t\t\t\t{new Date(e.at).toLocaleString()}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>{e.actor}</td>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>\n\t\t\t\t\t\t\t\t\t\t{e.method} {e.path}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t<span style={e.status >= 400 ? styles.bad : styles.ok}>{e.status}</span>{' '}\n\t\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{e.durationMs} ms</span>\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>{e.module}</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t\t{isLoading ? <p style={styles.status}>Loading…</p> : null}\n\t\t\t\t\t{hasMore && !isLoading ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={{ ...styles.button, marginTop: 12 }}\n\t\t\t\t\t\t\tonClick={() => void loadMore()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tLoad more\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : null}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAttention } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IAttentionScreenProps {\n\tclient: AdminClient;\n}\n\n// What needs the operator today. Empty is green.\nexport function AttentionScreen({ client }: IAttentionScreenProps) {\n\tconst { attention, isLoading, error, refresh } = useAttention(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Attention</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRefresh\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{isLoading && !attention ? (\n\t\t\t\t<p style={styles.status}>Running the checks…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : attention?.items.length === 0 ? (\n\t\t\t\t<p style={styles.ok}>\n\t\t\t\t\tNothing needs you. Checked {new Date(attention.generatedAt).toLocaleString()}.\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{attention?.items.map((item) => (\n\t\t\t\t\t\t<li key={`${item.source}:${item.message}`} style={styles.row}>\n\t\t\t\t\t\t\t<span style={item.severity === 'error' ? styles.bad : styles.advice}>\n\t\t\t\t\t\t\t\t{item.severity === 'error' ? 'error' : 'advice'}\n\t\t\t\t\t\t\t</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.mono}>{item.source}</span> — {item.message}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminConfig } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IConfigScreenProps {\n\tclient: AdminClient;\n}\n\n// Declared vs held: readiness per module, and whether each environment\n// variable the app reads is set. Values are never shown.\nexport function ConfigScreen({ client }: IConfigScreenProps) {\n\tconst { report, isLoading, error } = useAdminConfig(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Configuration</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : report ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>Readiness</h2>\n\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t{report.modules.map((m) => (\n\t\t\t\t\t\t\t<li key={m.name} style={styles.row}>\n\t\t\t\t\t\t\t\t<span style={styles.mono}>{m.name}</span>{' '}\n\t\t\t\t\t\t\t\t{m.problems.length === 0 ? (\n\t\t\t\t\t\t\t\t\t<span style={styles.ok}>ok</span>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\tm.problems.map((p) => (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={p.message}\n\t\t\t\t\t\t\t\t\t\t\tstyle={p.severity === 'error' ? styles.bad : styles.advice}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t\t<h2 style={styles.subtitle}>Environment</h2>\n\t\t\t\t\t{report.env.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>No variables declared — pass `env` to AdminModule.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{report.env.map((e) => (\n\t\t\t\t\t\t\t\t<li key={e.name} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{e.name}</span>{' '}\n\t\t\t\t\t\t\t\t\t{e.set ? (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.ok}>set</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.bad}>missing</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useDoctor } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IDoctorScreenProps {\n\tclient: AdminClient;\n}\n\n// Every reconciliation check, on demand. ok is false only for a hard failure;\n// findings on a passing check are advice.\nexport function DoctorScreen({ client }: IDoctorScreenProps) {\n\tconst { report, isLoading, error, refresh } = useDoctor(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Doctor</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRun again\n\t\t\t\t</button>\n\t\t\t\t{report && !isLoading ? (\n\t\t\t\t\t<span style={report.ok ? styles.ok : styles.bad}>\n\t\t\t\t\t\t{report.ok ? 'all checks pass' : 'a check failed'}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t{isLoading && !report ? (\n\t\t\t\t<p style={styles.status}>Running the checks…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{report?.checks.map((c) => (\n\t\t\t\t\t\t<li key={c.name} style={styles.row}>\n\t\t\t\t\t\t\t<span style={c.skipped ? styles.muted : c.ok ? styles.ok : styles.bad}>\n\t\t\t\t\t\t\t\t{c.skipped ? 'skipped' : c.ok ? 'ok' : 'failed'}\n\t\t\t\t\t\t\t</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.mono}>{c.name}</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.muted}>\n\t\t\t\t\t\t\t\t{c.module} · {c.durationMs} ms\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{c.skipped ? <div style={styles.muted}>{c.skipped}</div> : null}\n\t\t\t\t\t\t\t{c.findings.map((f) => (\n\t\t\t\t\t\t\t\t<div key={f} style={c.ok ? styles.advice : styles.bad}>\n\t\t\t\t\t\t\t\t\t{f}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useManifest } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IModulesScreenProps {\n\tclient: AdminClient;\n}\n\n// What is deployed: every module, its version, readiness, and whether it\n// offers anything to this surface.\nexport function ModulesScreen({ client }: IModulesScreenProps) {\n\tconst { manifest, isLoading, error } = useManifest(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Modules</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : manifest ? (\n\t\t\t\t<>\n\t\t\t\t\t<p style={styles.muted}>\n\t\t\t\t\t\t{manifest.env} · admin {manifest.admin.version} · admin log{' '}\n\t\t\t\t\t\t{manifest.admin.log ? 'on' : 'off'} · {manifest.routes.length} routes\n\t\t\t\t\t</p>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Version</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Readiness</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Describes admin</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{manifest.modules.map((m) => (\n\t\t\t\t\t\t\t\t<tr key={m.name}>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{m.name}</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.version ?? <span style={styles.muted}>not reported</span>}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.readiness.ok ? (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.ok}>ok</span>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.bad}>error</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{m.readiness.problems.map((p) => (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tkey={p.message}\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={p.severity === 'error' ? styles.bad : styles.advice}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.describesAdmin ? 'yes' : <span style={styles.muted}>no</span>}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminRoutes } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IRoutesScreenProps {\n\tclient: AdminClient;\n}\n\nexport function RoutesScreen({ client }: IRoutesScreenProps) {\n\tconst { report, isLoading, error } = useAdminRoutes(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Routes</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th style={styles.th}>Method</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Path</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Guard</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{report?.routes.map((r) => (\n\t\t\t\t\t\t\t<tr key={`${r.method} ${r.path}`}>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{r.method}</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{r.path}</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t<span style={styles.badge}>{r.guard}</span>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>{r.module ?? 'application'}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminTokens } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface ITokensScreenProps {\n\tclient: AdminClient;\n}\n\nexport function TokensScreen({ client }: ITokensScreenProps) {\n\tconst { report, isLoading, error } = useAdminTokens(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Access</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : report ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>Admin token</h2>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t{report.admin.ok ? (\n\t\t\t\t\t\t\t<span style={styles.ok}>strong</span>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span style={styles.bad}>weak</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{report.admin.problems.map((p) => (\n\t\t\t\t\t\t\t<div key={p.message} style={styles.bad}>\n\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</p>\n\t\t\t\t\t<h2 style={styles.subtitle}>Legacy per-brick tokens</h2>\n\t\t\t\t\t{report.legacy.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>None — every brick's admin surface goes through this token.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{report.legacy.map((l) => (\n\t\t\t\t\t\t\t\t<li key={l.module} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{l.module}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>\n\t\t\t\t\t\t\t\t\t\tstill registers its standalone routes with its own token (deprecated)\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AuthAdminClient } from '@fonderie/client';\nimport { useAdminLoginHistory, useAdminUser, useAdminUserSessions } from '@fonderie/react-admin';\nimport { useState } from 'react';\nimport { styles } from '../styles';\n\nexport interface IUsersScreenProps {\n\tclient: AuthAdminClient;\n}\n\n// Why can't this person log in. Look up by email, see the account, its live\n// sessions and recent sign-ins; suspend, unsuspend, or sign them out everywhere.\nexport function UsersScreen({ client }: IUsersScreenProps) {\n\tconst [input, setInput] = useState('');\n\tconst [email, setEmail] = useState<string | undefined>(undefined);\n\tconst { user, isLoading, error, suspend, unsuspend, revokeSessions } = useAdminUser(\n\t\tclient,\n\t\temail ? { email } : {},\n\t);\n\tconst userId = user?.id ?? null;\n\tconst sessions = useAdminUserSessions(client, userId);\n\tconst history = useAdminLoginHistory(client, userId, { limit: 20 });\n\n\tconst yesNo = (v: boolean) =>\n\t\tv ? <span style={styles.ok}>yes</span> : <span style={styles.muted}>no</span>;\n\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Users</h1>\n\t\t\t<form\n\t\t\t\tstyle={styles.toolbar}\n\t\t\t\tonSubmit={(e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tsetEmail(input.trim() || undefined);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tvalue={input}\n\t\t\t\t\tonChange={(e) => setInput(e.target.value)}\n\t\t\t\t\tplaceholder=\"email address\"\n\t\t\t\t\tstyle={{ ...styles.button, cursor: 'text', minWidth: 280 }}\n\t\t\t\t\taria-label=\"Email\"\n\t\t\t\t/>\n\t\t\t\t<button type=\"submit\" style={styles.button} disabled={isLoading}>\n\t\t\t\t\tLook up\n\t\t\t\t</button>\n\t\t\t</form>\n\t\t\t{error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.status === 404 ? 'No user with that email.' : error.explanation}\n\t\t\t\t</p>\n\t\t\t) : null}\n\t\t\t{user ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>\n\t\t\t\t\t\t{user.firstName || user.lastName\n\t\t\t\t\t\t\t? `${user.firstName} ${user.lastName}`.trim()\n\t\t\t\t\t\t\t: user.email}{' '}\n\t\t\t\t\t\t{user.suspended ? <span style={styles.badge}>suspended</span> : null}\n\t\t\t\t\t\t{user.deletedAt ? <span style={styles.badge}>deleted</span> : null}\n\t\t\t\t\t</h2>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>id</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{user.id}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>email</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t{user.email} · verified {yesNo(user.isEmailVerified)}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>MFA</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>{yesNo(user.mfaEnabled)}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>provider</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t{user.provider || 'password'}\n\t\t\t\t\t\t\t\t\t{user.hasPassword ? '' : ' · no password set'}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>last login</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t{user.lastLogin ? (\n\t\t\t\t\t\t\t\t\t\tnew Date(user.lastLogin).toLocaleString()\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.muted}>never</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>created</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>{new Date(user.createdAt).toLocaleString()}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t\t<div style={{ ...styles.toolbar, marginTop: 12 }}>\n\t\t\t\t\t\t{user.suspended ? (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\t\t\t\tonClick={() => void unsuspend()}\n\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tUnsuspend\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\t\t\t\tonClick={() => void suspend()}\n\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tSuspend\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\t\t\tonClick={() => void revokeSessions().then(() => sessions.refresh())}\n\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tSign out everywhere\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<h2 style={styles.subtitle}>Live sessions</h2>\n\t\t\t\t\t{sessions.sessions.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>None.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{sessions.sessions.map((s) => (\n\t\t\t\t\t\t\t\t<li key={s.id} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{s.ipAddress ?? '—'}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{s.userAgent ?? ''}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>since {new Date(s.createdAt).toLocaleString()}</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<h2 style={styles.subtitle}>Recent sign-ins</h2>\n\t\t\t\t\t{history.events.length === 0 && !history.isLoading ? (\n\t\t\t\t\t\t<p style={styles.muted}>None recorded.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{history.events.map((e) => (\n\t\t\t\t\t\t\t\t<li key={e.id} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={e.outcome === 'success' ? styles.ok : styles.bad}>{e.outcome}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{e.method}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{new Date(e.createdAt).toLocaleString()}</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t\t{history.hasMore && !history.isLoading ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={{ ...styles.button, marginTop: 8 }}\n\t\t\t\t\t\t\tonClick={() => void history.loadMore()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tLoad more\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : null}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":"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","names":["import_react","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_react_admin","import_jsx_runtime","import_jsx_runtime"]}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/screens/AdminShell.tsx
2
2
  import { ConfigEditorScreen, ConfigListScreen } from "@fonderie/react-config-admin-screens";
3
3
  import { TemplateEditorScreen, TemplateListScreen } from "@fonderie/react-courier-admin-screens";
4
- import { useState } from "react";
4
+ import { useState as useState2 } from "react";
5
5
 
6
6
  // src/styles.ts
7
7
  var styles = {
@@ -330,8 +330,153 @@ function TokensScreen({ client }) {
330
330
  ] });
331
331
  }
332
332
 
333
- // src/screens/AdminShell.tsx
333
+ // src/screens/UsersScreen.tsx
334
+ import { useAdminLoginHistory, useAdminUser, useAdminUserSessions } from "@fonderie/react-admin";
335
+ import { useState } from "react";
334
336
  import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
337
+ function UsersScreen({ client }) {
338
+ const [input, setInput] = useState("");
339
+ const [email, setEmail] = useState(void 0);
340
+ const { user, isLoading, error, suspend, unsuspend, revokeSessions } = useAdminUser(
341
+ client,
342
+ email ? { email } : {}
343
+ );
344
+ const userId = user?.id ?? null;
345
+ const sessions = useAdminUserSessions(client, userId);
346
+ const history = useAdminLoginHistory(client, userId, { limit: 20 });
347
+ const yesNo = (v) => v ? /* @__PURE__ */ jsx8("span", { style: styles.ok, children: "yes" }) : /* @__PURE__ */ jsx8("span", { style: styles.muted, children: "no" });
348
+ return /* @__PURE__ */ jsxs8("div", { style: styles.container, children: [
349
+ /* @__PURE__ */ jsx8("h1", { style: styles.title, children: "Users" }),
350
+ /* @__PURE__ */ jsxs8(
351
+ "form",
352
+ {
353
+ style: styles.toolbar,
354
+ onSubmit: (e) => {
355
+ e.preventDefault();
356
+ setEmail(input.trim() || void 0);
357
+ },
358
+ children: [
359
+ /* @__PURE__ */ jsx8(
360
+ "input",
361
+ {
362
+ type: "email",
363
+ value: input,
364
+ onChange: (e) => setInput(e.target.value),
365
+ placeholder: "email address",
366
+ style: { ...styles.button, cursor: "text", minWidth: 280 },
367
+ "aria-label": "Email"
368
+ }
369
+ ),
370
+ /* @__PURE__ */ jsx8("button", { type: "submit", style: styles.button, disabled: isLoading, children: "Look up" })
371
+ ]
372
+ }
373
+ ),
374
+ error ? /* @__PURE__ */ jsx8("p", { style: styles.error, role: "alert", children: error.status === 404 ? "No user with that email." : error.explanation }) : null,
375
+ user ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
376
+ /* @__PURE__ */ jsxs8("h2", { style: styles.subtitle, children: [
377
+ user.firstName || user.lastName ? `${user.firstName} ${user.lastName}`.trim() : user.email,
378
+ " ",
379
+ user.suspended ? /* @__PURE__ */ jsx8("span", { style: styles.badge, children: "suspended" }) : null,
380
+ user.deletedAt ? /* @__PURE__ */ jsx8("span", { style: styles.badge, children: "deleted" }) : null
381
+ ] }),
382
+ /* @__PURE__ */ jsx8("table", { style: styles.table, children: /* @__PURE__ */ jsxs8("tbody", { children: [
383
+ /* @__PURE__ */ jsxs8("tr", { children: [
384
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: "id" }),
385
+ /* @__PURE__ */ jsx8("td", { style: { ...styles.td, ...styles.mono }, children: user.id })
386
+ ] }),
387
+ /* @__PURE__ */ jsxs8("tr", { children: [
388
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: "email" }),
389
+ /* @__PURE__ */ jsxs8("td", { style: styles.td, children: [
390
+ user.email,
391
+ " \xB7 verified ",
392
+ yesNo(user.isEmailVerified)
393
+ ] })
394
+ ] }),
395
+ /* @__PURE__ */ jsxs8("tr", { children: [
396
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: "MFA" }),
397
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: yesNo(user.mfaEnabled) })
398
+ ] }),
399
+ /* @__PURE__ */ jsxs8("tr", { children: [
400
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: "provider" }),
401
+ /* @__PURE__ */ jsxs8("td", { style: styles.td, children: [
402
+ user.provider || "password",
403
+ user.hasPassword ? "" : " \xB7 no password set"
404
+ ] })
405
+ ] }),
406
+ /* @__PURE__ */ jsxs8("tr", { children: [
407
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: "last login" }),
408
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: user.lastLogin ? new Date(user.lastLogin).toLocaleString() : /* @__PURE__ */ jsx8("span", { style: styles.muted, children: "never" }) })
409
+ ] }),
410
+ /* @__PURE__ */ jsxs8("tr", { children: [
411
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: "created" }),
412
+ /* @__PURE__ */ jsx8("td", { style: styles.td, children: new Date(user.createdAt).toLocaleString() })
413
+ ] })
414
+ ] }) }),
415
+ /* @__PURE__ */ jsxs8("div", { style: { ...styles.toolbar, marginTop: 12 }, children: [
416
+ user.suspended ? /* @__PURE__ */ jsx8(
417
+ "button",
418
+ {
419
+ type: "button",
420
+ style: styles.button,
421
+ onClick: () => void unsuspend(),
422
+ disabled: isLoading,
423
+ children: "Unsuspend"
424
+ }
425
+ ) : /* @__PURE__ */ jsx8(
426
+ "button",
427
+ {
428
+ type: "button",
429
+ style: styles.button,
430
+ onClick: () => void suspend(),
431
+ disabled: isLoading,
432
+ children: "Suspend"
433
+ }
434
+ ),
435
+ /* @__PURE__ */ jsx8(
436
+ "button",
437
+ {
438
+ type: "button",
439
+ style: styles.button,
440
+ onClick: () => void revokeSessions().then(() => sessions.refresh()),
441
+ disabled: isLoading,
442
+ children: "Sign out everywhere"
443
+ }
444
+ )
445
+ ] }),
446
+ /* @__PURE__ */ jsx8("h2", { style: styles.subtitle, children: "Live sessions" }),
447
+ sessions.sessions.length === 0 ? /* @__PURE__ */ jsx8("p", { style: styles.muted, children: "None." }) : /* @__PURE__ */ jsx8("ul", { style: styles.list, children: sessions.sessions.map((s) => /* @__PURE__ */ jsxs8("li", { style: styles.row, children: [
448
+ /* @__PURE__ */ jsx8("span", { style: styles.mono, children: s.ipAddress ?? "\u2014" }),
449
+ " ",
450
+ /* @__PURE__ */ jsx8("span", { style: styles.muted, children: s.userAgent ?? "" }),
451
+ " ",
452
+ /* @__PURE__ */ jsxs8("span", { style: styles.muted, children: [
453
+ "since ",
454
+ new Date(s.createdAt).toLocaleString()
455
+ ] })
456
+ ] }, s.id)) }),
457
+ /* @__PURE__ */ jsx8("h2", { style: styles.subtitle, children: "Recent sign-ins" }),
458
+ history.events.length === 0 && !history.isLoading ? /* @__PURE__ */ jsx8("p", { style: styles.muted, children: "None recorded." }) : /* @__PURE__ */ jsx8("ul", { style: styles.list, children: history.events.map((e) => /* @__PURE__ */ jsxs8("li", { style: styles.row, children: [
459
+ /* @__PURE__ */ jsx8("span", { style: e.outcome === "success" ? styles.ok : styles.bad, children: e.outcome }),
460
+ " ",
461
+ /* @__PURE__ */ jsx8("span", { style: styles.muted, children: e.method }),
462
+ " ",
463
+ /* @__PURE__ */ jsx8("span", { style: styles.muted, children: new Date(e.createdAt).toLocaleString() })
464
+ ] }, e.id)) }),
465
+ history.hasMore && !history.isLoading ? /* @__PURE__ */ jsx8(
466
+ "button",
467
+ {
468
+ type: "button",
469
+ style: { ...styles.button, marginTop: 8 },
470
+ onClick: () => void history.loadMore(),
471
+ children: "Load more"
472
+ }
473
+ ) : null
474
+ ] }) : null
475
+ ] });
476
+ }
477
+
478
+ // src/screens/AdminShell.tsx
479
+ import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
335
480
  var NAV = [
336
481
  { group: "Today", items: [{ page: "attention", label: "Attention" }] },
337
482
  {
@@ -343,6 +488,7 @@ var NAV = [
343
488
  { page: "routes", label: "Routes" }
344
489
  ]
345
490
  },
491
+ { group: "People", items: [{ page: "users", label: "Users", needs: "auth" }] },
346
492
  { group: "Settings", items: [{ page: "settings", label: "Config & secrets", needs: "config" }] },
347
493
  { group: "Messaging", items: [{ page: "templates", label: "Templates", needs: "courier" }] },
348
494
  {
@@ -357,45 +503,53 @@ function AdminShell({
357
503
  client,
358
504
  configClient,
359
505
  courierClient,
506
+ authClient,
360
507
  environment,
361
508
  page,
362
509
  onNavigate
363
510
  }) {
364
- const [own, setOwn] = useState("attention");
511
+ const [own, setOwn] = useState2("attention");
365
512
  const current = page ?? own;
366
513
  const go = (p) => {
367
514
  if (onNavigate) onNavigate(p);
368
515
  if (page === void 0) setOwn(p);
369
516
  };
370
- const [editing, setEditing] = useState(null);
371
- const has = { config: Boolean(configClient), courier: Boolean(courierClient) };
517
+ const [editing, setEditing] = useState2(null);
518
+ const has = {
519
+ config: Boolean(configClient),
520
+ courier: Boolean(courierClient),
521
+ auth: Boolean(authClient)
522
+ };
372
523
  let body;
373
524
  switch (current) {
374
525
  case "attention":
375
- body = /* @__PURE__ */ jsx8(AttentionScreen, { client });
526
+ body = /* @__PURE__ */ jsx9(AttentionScreen, { client });
376
527
  break;
377
528
  case "modules":
378
- body = /* @__PURE__ */ jsx8(ModulesScreen, { client });
529
+ body = /* @__PURE__ */ jsx9(ModulesScreen, { client });
379
530
  break;
380
531
  case "doctor":
381
- body = /* @__PURE__ */ jsx8(DoctorScreen, { client });
532
+ body = /* @__PURE__ */ jsx9(DoctorScreen, { client });
382
533
  break;
383
534
  case "config":
384
- body = /* @__PURE__ */ jsx8(ConfigScreen, { client });
535
+ body = /* @__PURE__ */ jsx9(ConfigScreen, { client });
385
536
  break;
386
537
  case "routes":
387
- body = /* @__PURE__ */ jsx8(RoutesScreen, { client });
538
+ body = /* @__PURE__ */ jsx9(RoutesScreen, { client });
388
539
  break;
389
540
  case "tokens":
390
- body = /* @__PURE__ */ jsx8(TokensScreen, { client });
541
+ body = /* @__PURE__ */ jsx9(TokensScreen, { client });
391
542
  break;
392
543
  case "log":
393
- body = /* @__PURE__ */ jsx8(AdminLogScreen, { client });
544
+ body = /* @__PURE__ */ jsx9(AdminLogScreen, { client });
545
+ break;
546
+ case "users":
547
+ body = authClient ? /* @__PURE__ */ jsx9(UsersScreen, { client: authClient }) : /* @__PURE__ */ jsx9("p", { style: styles.status, children: "Pass an AuthAdminClient to look up users here." });
394
548
  break;
395
549
  case "settings":
396
- body = !configClient ? /* @__PURE__ */ jsx8("p", { style: styles.status, children: "Pass a ConfigAdminClient to manage config and secrets here." }) : editing && editing.kind !== "template" ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
397
- /* @__PURE__ */ jsx8("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
398
- /* @__PURE__ */ jsx8(
550
+ body = !configClient ? /* @__PURE__ */ jsx9("p", { style: styles.status, children: "Pass a ConfigAdminClient to manage config and secrets here." }) : editing && editing.kind !== "template" ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
551
+ /* @__PURE__ */ jsx9("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
552
+ /* @__PURE__ */ jsx9(
399
553
  ConfigEditorScreen,
400
554
  {
401
555
  client: configClient,
@@ -405,7 +559,7 @@ function AdminShell({
405
559
  onSaved: () => setEditing(null)
406
560
  }
407
561
  )
408
- ] }) : /* @__PURE__ */ jsx8(
562
+ ] }) : /* @__PURE__ */ jsx9(
409
563
  ConfigListScreen,
410
564
  {
411
565
  client: configClient,
@@ -416,9 +570,9 @@ function AdminShell({
416
570
  );
417
571
  break;
418
572
  case "templates":
419
- body = !courierClient ? /* @__PURE__ */ jsx8("p", { style: styles.status, children: "Pass a CourierAdminClient to manage templates here." }) : editing?.kind === "template" ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
420
- /* @__PURE__ */ jsx8("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
421
- /* @__PURE__ */ jsx8(
573
+ body = !courierClient ? /* @__PURE__ */ jsx9("p", { style: styles.status, children: "Pass a CourierAdminClient to manage templates here." }) : editing?.kind === "template" ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
574
+ /* @__PURE__ */ jsx9("button", { type: "button", style: styles.button, onClick: () => setEditing(null), children: "\u2190 Back" }),
575
+ /* @__PURE__ */ jsx9(
422
576
  TemplateEditorScreen,
423
577
  {
424
578
  client: courierClient,
@@ -426,7 +580,7 @@ function AdminShell({
426
580
  onSaved: () => setEditing(null)
427
581
  }
428
582
  )
429
- ] }) : /* @__PURE__ */ jsx8(
583
+ ] }) : /* @__PURE__ */ jsx9(
430
584
  TemplateListScreen,
431
585
  {
432
586
  client: courierClient,
@@ -435,13 +589,13 @@ function AdminShell({
435
589
  );
436
590
  break;
437
591
  }
438
- return /* @__PURE__ */ jsxs8("div", { style: styles.shell, children: [
439
- /* @__PURE__ */ jsx8("nav", { style: styles.nav, "aria-label": "Admin", children: NAV.map((g) => {
592
+ return /* @__PURE__ */ jsxs9("div", { style: styles.shell, children: [
593
+ /* @__PURE__ */ jsx9("nav", { style: styles.nav, "aria-label": "Admin", children: NAV.map((g) => {
440
594
  const items = g.items.filter((i) => !i.needs || has[i.needs]);
441
595
  if (items.length === 0) return null;
442
- return /* @__PURE__ */ jsxs8("div", { children: [
443
- /* @__PURE__ */ jsx8("div", { style: styles.navGroup, children: g.group }),
444
- items.map((i) => /* @__PURE__ */ jsx8(
596
+ return /* @__PURE__ */ jsxs9("div", { children: [
597
+ /* @__PURE__ */ jsx9("div", { style: styles.navGroup, children: g.group }),
598
+ items.map((i) => /* @__PURE__ */ jsx9(
445
599
  "button",
446
600
  {
447
601
  type: "button",
@@ -457,7 +611,7 @@ function AdminShell({
457
611
  ))
458
612
  ] }, g.group);
459
613
  }) }),
460
- /* @__PURE__ */ jsx8("main", { style: styles.main, children: body })
614
+ /* @__PURE__ */ jsx9("main", { style: styles.main, children: body })
461
615
  ] });
462
616
  }
463
617
  export {
@@ -468,6 +622,7 @@ export {
468
622
  DoctorScreen,
469
623
  ModulesScreen,
470
624
  RoutesScreen,
471
- TokensScreen
625
+ TokensScreen,
626
+ UsersScreen
472
627
  };
473
628
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/screens/AdminShell.tsx","../src/styles.ts","../src/screens/AdminLogScreen.tsx","../src/screens/AttentionScreen.tsx","../src/screens/ConfigScreen.tsx","../src/screens/DoctorScreen.tsx","../src/screens/ModulesScreen.tsx","../src/screens/RoutesScreen.tsx","../src/screens/TokensScreen.tsx"],"sourcesContent":["import type { AdminClient, ConfigAdminClient, CourierAdminClient } from '@fonderie/client';\nimport { ConfigEditorScreen, ConfigListScreen } from '@fonderie/react-config-admin-screens';\nimport { TemplateEditorScreen, TemplateListScreen } from '@fonderie/react-courier-admin-screens';\nimport { useState } from 'react';\nimport { styles } from '../styles';\nimport { AdminLogScreen } from './AdminLogScreen';\nimport { AttentionScreen } from './AttentionScreen';\nimport { ConfigScreen } from './ConfigScreen';\nimport { DoctorScreen } from './DoctorScreen';\nimport { ModulesScreen } from './ModulesScreen';\nimport { RoutesScreen } from './RoutesScreen';\nimport { TokensScreen } from './TokensScreen';\n\nexport type AdminPage =\n\t| 'attention'\n\t| 'modules'\n\t| 'doctor'\n\t| 'config'\n\t| 'routes'\n\t| 'tokens'\n\t| 'log'\n\t| 'settings'\n\t| 'templates';\n\nexport interface IAdminShellProps {\n\tclient: AdminClient;\n\t// Given ⇒ the Settings (config + secrets) and Messaging (templates) pages\n\t// appear. Construct them with `prefix: '/_admin'` to go through the one token.\n\tconfigClient?: ConfigAdminClient;\n\tcourierClient?: CourierAdminClient;\n\tenvironment?: string;\n\t// Controlled navigation: pass both to own the URL. Omit both and the shell\n\t// keeps the page itself.\n\tpage?: AdminPage;\n\tonNavigate?: (page: AdminPage) => void;\n}\n\nconst NAV: Array<{\n\tgroup: string;\n\titems: Array<{ page: AdminPage; label: string; needs?: 'config' | 'courier' }>;\n}> = [\n\t{ group: 'Today', items: [{ page: 'attention', label: 'Attention' }] },\n\t{\n\t\tgroup: 'System',\n\t\titems: [\n\t\t\t{ page: 'modules', label: 'Modules' },\n\t\t\t{ page: 'config', label: 'Configuration' },\n\t\t\t{ page: 'doctor', label: 'Doctor' },\n\t\t\t{ page: 'routes', label: 'Routes' },\n\t\t],\n\t},\n\t{ group: 'Settings', items: [{ page: 'settings', label: 'Config & secrets', needs: 'config' }] },\n\t{ group: 'Messaging', items: [{ page: 'templates', label: 'Templates', needs: 'courier' }] },\n\t{\n\t\tgroup: 'Activity',\n\t\titems: [\n\t\t\t{ page: 'log', label: 'Admin log' },\n\t\t\t{ page: 'tokens', label: 'Access' },\n\t\t],\n\t},\n];\n\nexport function AdminShell({\n\tclient,\n\tconfigClient,\n\tcourierClient,\n\tenvironment,\n\tpage,\n\tonNavigate,\n}: IAdminShellProps) {\n\tconst [own, setOwn] = useState<AdminPage>('attention');\n\tconst current = page ?? own;\n\tconst go = (p: AdminPage) => {\n\t\tif (onNavigate) onNavigate(p);\n\t\tif (page === undefined) setOwn(p);\n\t};\n\tconst [editing, setEditing] = useState<\n\t\t{ kind: 'config' | 'secret'; key: string } | { kind: 'template'; type: string } | null\n\t>(null);\n\n\tconst has = { config: Boolean(configClient), courier: Boolean(courierClient) };\n\n\tlet body: React.ReactNode;\n\tswitch (current) {\n\t\tcase 'attention':\n\t\t\tbody = <AttentionScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'modules':\n\t\t\tbody = <ModulesScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'doctor':\n\t\t\tbody = <DoctorScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'config':\n\t\t\tbody = <ConfigScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'routes':\n\t\t\tbody = <RoutesScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'tokens':\n\t\t\tbody = <TokensScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'log':\n\t\t\tbody = <AdminLogScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'settings':\n\t\t\tbody = !configClient ? (\n\t\t\t\t<p style={styles.status}>Pass a ConfigAdminClient to manage config and secrets here.</p>\n\t\t\t) : editing && editing.kind !== 'template' ? (\n\t\t\t\t<>\n\t\t\t\t\t<button type=\"button\" style={styles.button} onClick={() => setEditing(null)}>\n\t\t\t\t\t\t← Back\n\t\t\t\t\t</button>\n\t\t\t\t\t<ConfigEditorScreen\n\t\t\t\t\t\tclient={configClient}\n\t\t\t\t\t\tkind={editing.kind}\n\t\t\t\t\t\tconfigKey={editing.key}\n\t\t\t\t\t\t{...(environment !== undefined ? { environment } : {})}\n\t\t\t\t\t\tonSaved={() => setEditing(null)}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<ConfigListScreen\n\t\t\t\t\tclient={configClient}\n\t\t\t\t\t{...(environment !== undefined ? { environment } : {})}\n\t\t\t\t\tonSelectConfig={(key) => setEditing({ kind: 'config', key })}\n\t\t\t\t\tonSelectSecret={(key) => setEditing({ kind: 'secret', key })}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tbreak;\n\t\tcase 'templates':\n\t\t\tbody = !courierClient ? (\n\t\t\t\t<p style={styles.status}>Pass a CourierAdminClient to manage templates here.</p>\n\t\t\t) : editing?.kind === 'template' ? (\n\t\t\t\t<>\n\t\t\t\t\t<button type=\"button\" style={styles.button} onClick={() => setEditing(null)}>\n\t\t\t\t\t\t← Back\n\t\t\t\t\t</button>\n\t\t\t\t\t<TemplateEditorScreen\n\t\t\t\t\t\tclient={courierClient}\n\t\t\t\t\t\ttype={editing.type}\n\t\t\t\t\t\tonSaved={() => setEditing(null)}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<TemplateListScreen\n\t\t\t\t\tclient={courierClient}\n\t\t\t\t\tonSelectTemplate={(t) => setEditing({ kind: 'template', type: t.type })}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tbreak;\n\t}\n\n\treturn (\n\t\t<div style={styles.shell}>\n\t\t\t<nav style={styles.nav} aria-label=\"Admin\">\n\t\t\t\t{NAV.map((g) => {\n\t\t\t\t\tconst items = g.items.filter((i) => !i.needs || has[i.needs]);\n\t\t\t\t\tif (items.length === 0) return null;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={g.group}>\n\t\t\t\t\t\t\t<div style={styles.navGroup}>{g.group}</div>\n\t\t\t\t\t\t\t{items.map((i) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={i.page}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tstyle={{ ...styles.navItem, ...(current === i.page ? styles.navItemActive : {}) }}\n\t\t\t\t\t\t\t\t\taria-current={current === i.page ? 'page' : undefined}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetEditing(null);\n\t\t\t\t\t\t\t\t\t\tgo(i.page);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{i.label}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</nav>\n\t\t\t<main style={styles.main}>{body}</main>\n\t\t</div>\n\t);\n}\n","import type { CSSProperties } from 'react';\n\n// One palette for every admin page; the same values as the config and courier\n// admin screens so the shell reads as one surface.\nexport const styles: Record<string, CSSProperties> = {\n\tshell: {\n\t\tdisplay: 'flex',\n\t\tminHeight: '100vh',\n\t\tfontFamily: 'system-ui, sans-serif',\n\t\tcolor: '#111',\n\t},\n\tnav: { width: 220, borderRight: '1px solid #eee', padding: 16, flexShrink: 0 },\n\tnavGroup: {\n\t\tfontSize: 11,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: 0.6,\n\t\tcolor: '#888',\n\t\tmargin: '16px 0 6px',\n\t},\n\tnavItem: {\n\t\tdisplay: 'block',\n\t\twidth: '100%',\n\t\ttextAlign: 'left',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tborderRadius: 6,\n\t\tpadding: '6px 8px',\n\t\tcursor: 'pointer',\n\t\tfontSize: 14,\n\t\tcolor: '#111',\n\t},\n\tnavItemActive: { background: '#f3f4f6', fontWeight: 600 },\n\tmain: { flex: 1, padding: 24, maxWidth: 960 },\n\tcontainer: { padding: 24, maxWidth: 960 },\n\ttitle: { fontSize: 20, fontWeight: 700, marginTop: 0, marginBottom: 12 },\n\tsubtitle: { fontSize: 15, fontWeight: 600, marginTop: 24, marginBottom: 8 },\n\tstatus: { padding: 12, color: '#666' },\n\terror: { color: '#e11d48', marginBottom: 12, fontSize: 14 },\n\tok: { color: '#15803d', fontWeight: 600 },\n\tbad: { color: '#e11d48', fontWeight: 600 },\n\tadvice: { color: '#b45309' },\n\tmuted: { color: '#666', fontSize: 13 },\n\tmono: { fontFamily: 'ui-monospace, monospace', fontSize: 13 },\n\ttable: { width: '100%', borderCollapse: 'collapse', fontSize: 14 },\n\tth: {\n\t\ttextAlign: 'left',\n\t\tborderBottom: '1px solid #ddd',\n\t\tpadding: '6px 8px',\n\t\tfontWeight: 600,\n\t\tcolor: '#444',\n\t},\n\ttd: { borderBottom: '1px solid #eee', padding: '6px 8px', verticalAlign: 'top' },\n\tlist: { listStyle: 'none', padding: 0, margin: 0 },\n\trow: { borderBottom: '1px solid #eee', padding: '8px 0' },\n\tbadge: {\n\t\tdisplay: 'inline-block',\n\t\tborderRadius: 999,\n\t\tpadding: '1px 8px',\n\t\tfontSize: 12,\n\t\tbackground: '#f3f4f6',\n\t},\n\tbutton: {\n\t\tbackground: 'none',\n\t\tborder: '1px solid #ddd',\n\t\tborderRadius: 8,\n\t\tpadding: '4px 10px',\n\t\tcursor: 'pointer',\n\t\tfontSize: 13,\n\t},\n\ttoolbar: { display: 'flex', gap: 8, alignItems: 'center', marginBottom: 12 },\n};\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminLog } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IAdminLogScreenProps {\n\tclient: AdminClient;\n\tpageSize?: number;\n}\n\n// Who did what through the surface, newest first — refused requests included.\nexport function AdminLogScreen({ client, pageSize = 50 }: IAdminLogScreenProps) {\n\tconst { entries, hasMore, isLoading, error, refresh, loadMore } = useAdminLog(client, {\n\t\tlimit: pageSize,\n\t});\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Admin log</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRefresh\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.status === 404\n\t\t\t\t\t\t? 'The admin log is off — give AdminModule a store.'\n\t\t\t\t\t\t: error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style={styles.th}>When</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Actor</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Request</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Status</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{entries.map((e) => (\n\t\t\t\t\t\t\t\t<tr key={e.id}>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>\n\t\t\t\t\t\t\t\t\t\t{new Date(e.at).toLocaleString()}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>{e.actor}</td>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>\n\t\t\t\t\t\t\t\t\t\t{e.method} {e.path}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t<span style={e.status >= 400 ? styles.bad : styles.ok}>{e.status}</span>{' '}\n\t\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{e.durationMs} ms</span>\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>{e.module}</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t\t{isLoading ? <p style={styles.status}>Loading…</p> : null}\n\t\t\t\t\t{hasMore && !isLoading ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={{ ...styles.button, marginTop: 12 }}\n\t\t\t\t\t\t\tonClick={() => void loadMore()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tLoad more\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : null}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAttention } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IAttentionScreenProps {\n\tclient: AdminClient;\n}\n\n// What needs the operator today. Empty is green.\nexport function AttentionScreen({ client }: IAttentionScreenProps) {\n\tconst { attention, isLoading, error, refresh } = useAttention(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Attention</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRefresh\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{isLoading && !attention ? (\n\t\t\t\t<p style={styles.status}>Running the checks…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : attention?.items.length === 0 ? (\n\t\t\t\t<p style={styles.ok}>\n\t\t\t\t\tNothing needs you. Checked {new Date(attention.generatedAt).toLocaleString()}.\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{attention?.items.map((item) => (\n\t\t\t\t\t\t<li key={`${item.source}:${item.message}`} style={styles.row}>\n\t\t\t\t\t\t\t<span style={item.severity === 'error' ? styles.bad : styles.advice}>\n\t\t\t\t\t\t\t\t{item.severity === 'error' ? 'error' : 'advice'}\n\t\t\t\t\t\t\t</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.mono}>{item.source}</span> — {item.message}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminConfig } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IConfigScreenProps {\n\tclient: AdminClient;\n}\n\n// Declared vs held: readiness per module, and whether each environment\n// variable the app reads is set. Values are never shown.\nexport function ConfigScreen({ client }: IConfigScreenProps) {\n\tconst { report, isLoading, error } = useAdminConfig(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Configuration</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : report ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>Readiness</h2>\n\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t{report.modules.map((m) => (\n\t\t\t\t\t\t\t<li key={m.name} style={styles.row}>\n\t\t\t\t\t\t\t\t<span style={styles.mono}>{m.name}</span>{' '}\n\t\t\t\t\t\t\t\t{m.problems.length === 0 ? (\n\t\t\t\t\t\t\t\t\t<span style={styles.ok}>ok</span>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\tm.problems.map((p) => (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={p.message}\n\t\t\t\t\t\t\t\t\t\t\tstyle={p.severity === 'error' ? styles.bad : styles.advice}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t\t<h2 style={styles.subtitle}>Environment</h2>\n\t\t\t\t\t{report.env.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>No variables declared — pass `env` to AdminModule.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{report.env.map((e) => (\n\t\t\t\t\t\t\t\t<li key={e.name} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{e.name}</span>{' '}\n\t\t\t\t\t\t\t\t\t{e.set ? (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.ok}>set</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.bad}>missing</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useDoctor } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IDoctorScreenProps {\n\tclient: AdminClient;\n}\n\n// Every reconciliation check, on demand. ok is false only for a hard failure;\n// findings on a passing check are advice.\nexport function DoctorScreen({ client }: IDoctorScreenProps) {\n\tconst { report, isLoading, error, refresh } = useDoctor(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Doctor</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRun again\n\t\t\t\t</button>\n\t\t\t\t{report && !isLoading ? (\n\t\t\t\t\t<span style={report.ok ? styles.ok : styles.bad}>\n\t\t\t\t\t\t{report.ok ? 'all checks pass' : 'a check failed'}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t{isLoading && !report ? (\n\t\t\t\t<p style={styles.status}>Running the checks…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{report?.checks.map((c) => (\n\t\t\t\t\t\t<li key={c.name} style={styles.row}>\n\t\t\t\t\t\t\t<span style={c.skipped ? styles.muted : c.ok ? styles.ok : styles.bad}>\n\t\t\t\t\t\t\t\t{c.skipped ? 'skipped' : c.ok ? 'ok' : 'failed'}\n\t\t\t\t\t\t\t</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.mono}>{c.name}</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.muted}>\n\t\t\t\t\t\t\t\t{c.module} · {c.durationMs} ms\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{c.skipped ? <div style={styles.muted}>{c.skipped}</div> : null}\n\t\t\t\t\t\t\t{c.findings.map((f) => (\n\t\t\t\t\t\t\t\t<div key={f} style={c.ok ? styles.advice : styles.bad}>\n\t\t\t\t\t\t\t\t\t{f}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useManifest } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IModulesScreenProps {\n\tclient: AdminClient;\n}\n\n// What is deployed: every module, its version, readiness, and whether it\n// offers anything to this surface.\nexport function ModulesScreen({ client }: IModulesScreenProps) {\n\tconst { manifest, isLoading, error } = useManifest(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Modules</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : manifest ? (\n\t\t\t\t<>\n\t\t\t\t\t<p style={styles.muted}>\n\t\t\t\t\t\t{manifest.env} · admin {manifest.admin.version} · admin log{' '}\n\t\t\t\t\t\t{manifest.admin.log ? 'on' : 'off'} · {manifest.routes.length} routes\n\t\t\t\t\t</p>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Version</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Readiness</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Describes admin</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{manifest.modules.map((m) => (\n\t\t\t\t\t\t\t\t<tr key={m.name}>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{m.name}</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.version ?? <span style={styles.muted}>not reported</span>}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.readiness.ok ? (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.ok}>ok</span>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.bad}>error</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{m.readiness.problems.map((p) => (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tkey={p.message}\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={p.severity === 'error' ? styles.bad : styles.advice}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.describesAdmin ? 'yes' : <span style={styles.muted}>no</span>}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminRoutes } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IRoutesScreenProps {\n\tclient: AdminClient;\n}\n\nexport function RoutesScreen({ client }: IRoutesScreenProps) {\n\tconst { report, isLoading, error } = useAdminRoutes(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Routes</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th style={styles.th}>Method</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Path</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Guard</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{report?.routes.map((r) => (\n\t\t\t\t\t\t\t<tr key={`${r.method} ${r.path}`}>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{r.method}</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{r.path}</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t<span style={styles.badge}>{r.guard}</span>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>{r.module ?? 'application'}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminTokens } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface ITokensScreenProps {\n\tclient: AdminClient;\n}\n\nexport function TokensScreen({ client }: ITokensScreenProps) {\n\tconst { report, isLoading, error } = useAdminTokens(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Access</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : report ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>Admin token</h2>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t{report.admin.ok ? (\n\t\t\t\t\t\t\t<span style={styles.ok}>strong</span>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span style={styles.bad}>weak</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{report.admin.problems.map((p) => (\n\t\t\t\t\t\t\t<div key={p.message} style={styles.bad}>\n\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</p>\n\t\t\t\t\t<h2 style={styles.subtitle}>Legacy per-brick tokens</h2>\n\t\t\t\t\t{report.legacy.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>None — every brick's admin surface goes through this token.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{report.legacy.map((l) => (\n\t\t\t\t\t\t\t\t<li key={l.module} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{l.module}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>\n\t\t\t\t\t\t\t\t\t\tstill registers its standalone routes with its own token (deprecated)\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":"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","names":["jsx","jsxs","Fragment","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","Fragment","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/screens/AdminShell.tsx","../src/styles.ts","../src/screens/AdminLogScreen.tsx","../src/screens/AttentionScreen.tsx","../src/screens/ConfigScreen.tsx","../src/screens/DoctorScreen.tsx","../src/screens/ModulesScreen.tsx","../src/screens/RoutesScreen.tsx","../src/screens/TokensScreen.tsx","../src/screens/UsersScreen.tsx"],"sourcesContent":["import type {\n\tAdminClient,\n\tAuthAdminClient,\n\tConfigAdminClient,\n\tCourierAdminClient,\n} from '@fonderie/client';\nimport { ConfigEditorScreen, ConfigListScreen } from '@fonderie/react-config-admin-screens';\nimport { TemplateEditorScreen, TemplateListScreen } from '@fonderie/react-courier-admin-screens';\nimport { useState } from 'react';\nimport { styles } from '../styles';\nimport { AdminLogScreen } from './AdminLogScreen';\nimport { AttentionScreen } from './AttentionScreen';\nimport { ConfigScreen } from './ConfigScreen';\nimport { DoctorScreen } from './DoctorScreen';\nimport { ModulesScreen } from './ModulesScreen';\nimport { RoutesScreen } from './RoutesScreen';\nimport { TokensScreen } from './TokensScreen';\nimport { UsersScreen } from './UsersScreen';\n\nexport type AdminPage =\n\t| 'attention'\n\t| 'modules'\n\t| 'doctor'\n\t| 'config'\n\t| 'routes'\n\t| 'tokens'\n\t| 'log'\n\t| 'settings'\n\t| 'templates'\n\t| 'users';\n\nexport interface IAdminShellProps {\n\tclient: AdminClient;\n\t// Given ⇒ the Settings (config + secrets) and Messaging (templates) pages\n\t// appear. Construct them with `prefix: '/_admin'` to go through the one token.\n\tconfigClient?: ConfigAdminClient;\n\tcourierClient?: CourierAdminClient;\n\t// Given ⇒ the People page (users) appears; needs @fonderie/auth ≥ 7.8.\n\tauthClient?: AuthAdminClient;\n\tenvironment?: string;\n\t// Controlled navigation: pass both to own the URL. Omit both and the shell\n\t// keeps the page itself.\n\tpage?: AdminPage;\n\tonNavigate?: (page: AdminPage) => void;\n}\n\nconst NAV: Array<{\n\tgroup: string;\n\titems: Array<{ page: AdminPage; label: string; needs?: 'config' | 'courier' | 'auth' }>;\n}> = [\n\t{ group: 'Today', items: [{ page: 'attention', label: 'Attention' }] },\n\t{\n\t\tgroup: 'System',\n\t\titems: [\n\t\t\t{ page: 'modules', label: 'Modules' },\n\t\t\t{ page: 'config', label: 'Configuration' },\n\t\t\t{ page: 'doctor', label: 'Doctor' },\n\t\t\t{ page: 'routes', label: 'Routes' },\n\t\t],\n\t},\n\t{ group: 'People', items: [{ page: 'users', label: 'Users', needs: 'auth' }] },\n\t{ group: 'Settings', items: [{ page: 'settings', label: 'Config & secrets', needs: 'config' }] },\n\t{ group: 'Messaging', items: [{ page: 'templates', label: 'Templates', needs: 'courier' }] },\n\t{\n\t\tgroup: 'Activity',\n\t\titems: [\n\t\t\t{ page: 'log', label: 'Admin log' },\n\t\t\t{ page: 'tokens', label: 'Access' },\n\t\t],\n\t},\n];\n\nexport function AdminShell({\n\tclient,\n\tconfigClient,\n\tcourierClient,\n\tauthClient,\n\tenvironment,\n\tpage,\n\tonNavigate,\n}: IAdminShellProps) {\n\tconst [own, setOwn] = useState<AdminPage>('attention');\n\tconst current = page ?? own;\n\tconst go = (p: AdminPage) => {\n\t\tif (onNavigate) onNavigate(p);\n\t\tif (page === undefined) setOwn(p);\n\t};\n\tconst [editing, setEditing] = useState<\n\t\t{ kind: 'config' | 'secret'; key: string } | { kind: 'template'; type: string } | null\n\t>(null);\n\n\tconst has = {\n\t\tconfig: Boolean(configClient),\n\t\tcourier: Boolean(courierClient),\n\t\tauth: Boolean(authClient),\n\t};\n\n\tlet body: React.ReactNode;\n\tswitch (current) {\n\t\tcase 'attention':\n\t\t\tbody = <AttentionScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'modules':\n\t\t\tbody = <ModulesScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'doctor':\n\t\t\tbody = <DoctorScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'config':\n\t\t\tbody = <ConfigScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'routes':\n\t\t\tbody = <RoutesScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'tokens':\n\t\t\tbody = <TokensScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'log':\n\t\t\tbody = <AdminLogScreen client={client} />;\n\t\t\tbreak;\n\t\tcase 'users':\n\t\t\tbody = authClient ? (\n\t\t\t\t<UsersScreen client={authClient} />\n\t\t\t) : (\n\t\t\t\t<p style={styles.status}>Pass an AuthAdminClient to look up users here.</p>\n\t\t\t);\n\t\t\tbreak;\n\t\tcase 'settings':\n\t\t\tbody = !configClient ? (\n\t\t\t\t<p style={styles.status}>Pass a ConfigAdminClient to manage config and secrets here.</p>\n\t\t\t) : editing && editing.kind !== 'template' ? (\n\t\t\t\t<>\n\t\t\t\t\t<button type=\"button\" style={styles.button} onClick={() => setEditing(null)}>\n\t\t\t\t\t\t← Back\n\t\t\t\t\t</button>\n\t\t\t\t\t<ConfigEditorScreen\n\t\t\t\t\t\tclient={configClient}\n\t\t\t\t\t\tkind={editing.kind}\n\t\t\t\t\t\tconfigKey={editing.key}\n\t\t\t\t\t\t{...(environment !== undefined ? { environment } : {})}\n\t\t\t\t\t\tonSaved={() => setEditing(null)}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<ConfigListScreen\n\t\t\t\t\tclient={configClient}\n\t\t\t\t\t{...(environment !== undefined ? { environment } : {})}\n\t\t\t\t\tonSelectConfig={(key) => setEditing({ kind: 'config', key })}\n\t\t\t\t\tonSelectSecret={(key) => setEditing({ kind: 'secret', key })}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tbreak;\n\t\tcase 'templates':\n\t\t\tbody = !courierClient ? (\n\t\t\t\t<p style={styles.status}>Pass a CourierAdminClient to manage templates here.</p>\n\t\t\t) : editing?.kind === 'template' ? (\n\t\t\t\t<>\n\t\t\t\t\t<button type=\"button\" style={styles.button} onClick={() => setEditing(null)}>\n\t\t\t\t\t\t← Back\n\t\t\t\t\t</button>\n\t\t\t\t\t<TemplateEditorScreen\n\t\t\t\t\t\tclient={courierClient}\n\t\t\t\t\t\ttype={editing.type}\n\t\t\t\t\t\tonSaved={() => setEditing(null)}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<TemplateListScreen\n\t\t\t\t\tclient={courierClient}\n\t\t\t\t\tonSelectTemplate={(t) => setEditing({ kind: 'template', type: t.type })}\n\t\t\t\t/>\n\t\t\t);\n\t\t\tbreak;\n\t}\n\n\treturn (\n\t\t<div style={styles.shell}>\n\t\t\t<nav style={styles.nav} aria-label=\"Admin\">\n\t\t\t\t{NAV.map((g) => {\n\t\t\t\t\tconst items = g.items.filter((i) => !i.needs || has[i.needs]);\n\t\t\t\t\tif (items.length === 0) return null;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={g.group}>\n\t\t\t\t\t\t\t<div style={styles.navGroup}>{g.group}</div>\n\t\t\t\t\t\t\t{items.map((i) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={i.page}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tstyle={{ ...styles.navItem, ...(current === i.page ? styles.navItemActive : {}) }}\n\t\t\t\t\t\t\t\t\taria-current={current === i.page ? 'page' : undefined}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetEditing(null);\n\t\t\t\t\t\t\t\t\t\tgo(i.page);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{i.label}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</nav>\n\t\t\t<main style={styles.main}>{body}</main>\n\t\t</div>\n\t);\n}\n","import type { CSSProperties } from 'react';\n\n// One palette for every admin page; the same values as the config and courier\n// admin screens so the shell reads as one surface.\nexport const styles: Record<string, CSSProperties> = {\n\tshell: {\n\t\tdisplay: 'flex',\n\t\tminHeight: '100vh',\n\t\tfontFamily: 'system-ui, sans-serif',\n\t\tcolor: '#111',\n\t},\n\tnav: { width: 220, borderRight: '1px solid #eee', padding: 16, flexShrink: 0 },\n\tnavGroup: {\n\t\tfontSize: 11,\n\t\ttextTransform: 'uppercase',\n\t\tletterSpacing: 0.6,\n\t\tcolor: '#888',\n\t\tmargin: '16px 0 6px',\n\t},\n\tnavItem: {\n\t\tdisplay: 'block',\n\t\twidth: '100%',\n\t\ttextAlign: 'left',\n\t\tbackground: 'none',\n\t\tborder: 'none',\n\t\tborderRadius: 6,\n\t\tpadding: '6px 8px',\n\t\tcursor: 'pointer',\n\t\tfontSize: 14,\n\t\tcolor: '#111',\n\t},\n\tnavItemActive: { background: '#f3f4f6', fontWeight: 600 },\n\tmain: { flex: 1, padding: 24, maxWidth: 960 },\n\tcontainer: { padding: 24, maxWidth: 960 },\n\ttitle: { fontSize: 20, fontWeight: 700, marginTop: 0, marginBottom: 12 },\n\tsubtitle: { fontSize: 15, fontWeight: 600, marginTop: 24, marginBottom: 8 },\n\tstatus: { padding: 12, color: '#666' },\n\terror: { color: '#e11d48', marginBottom: 12, fontSize: 14 },\n\tok: { color: '#15803d', fontWeight: 600 },\n\tbad: { color: '#e11d48', fontWeight: 600 },\n\tadvice: { color: '#b45309' },\n\tmuted: { color: '#666', fontSize: 13 },\n\tmono: { fontFamily: 'ui-monospace, monospace', fontSize: 13 },\n\ttable: { width: '100%', borderCollapse: 'collapse', fontSize: 14 },\n\tth: {\n\t\ttextAlign: 'left',\n\t\tborderBottom: '1px solid #ddd',\n\t\tpadding: '6px 8px',\n\t\tfontWeight: 600,\n\t\tcolor: '#444',\n\t},\n\ttd: { borderBottom: '1px solid #eee', padding: '6px 8px', verticalAlign: 'top' },\n\tlist: { listStyle: 'none', padding: 0, margin: 0 },\n\trow: { borderBottom: '1px solid #eee', padding: '8px 0' },\n\tbadge: {\n\t\tdisplay: 'inline-block',\n\t\tborderRadius: 999,\n\t\tpadding: '1px 8px',\n\t\tfontSize: 12,\n\t\tbackground: '#f3f4f6',\n\t},\n\tbutton: {\n\t\tbackground: 'none',\n\t\tborder: '1px solid #ddd',\n\t\tborderRadius: 8,\n\t\tpadding: '4px 10px',\n\t\tcursor: 'pointer',\n\t\tfontSize: 13,\n\t},\n\ttoolbar: { display: 'flex', gap: 8, alignItems: 'center', marginBottom: 12 },\n};\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminLog } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IAdminLogScreenProps {\n\tclient: AdminClient;\n\tpageSize?: number;\n}\n\n// Who did what through the surface, newest first — refused requests included.\nexport function AdminLogScreen({ client, pageSize = 50 }: IAdminLogScreenProps) {\n\tconst { entries, hasMore, isLoading, error, refresh, loadMore } = useAdminLog(client, {\n\t\tlimit: pageSize,\n\t});\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Admin log</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRefresh\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.status === 404\n\t\t\t\t\t\t? 'The admin log is off — give AdminModule a store.'\n\t\t\t\t\t\t: error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style={styles.th}>When</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Actor</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Request</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Status</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{entries.map((e) => (\n\t\t\t\t\t\t\t\t<tr key={e.id}>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>\n\t\t\t\t\t\t\t\t\t\t{new Date(e.at).toLocaleString()}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>{e.actor}</td>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>\n\t\t\t\t\t\t\t\t\t\t{e.method} {e.path}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t<span style={e.status >= 400 ? styles.bad : styles.ok}>{e.status}</span>{' '}\n\t\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{e.durationMs} ms</span>\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>{e.module}</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t\t{isLoading ? <p style={styles.status}>Loading…</p> : null}\n\t\t\t\t\t{hasMore && !isLoading ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={{ ...styles.button, marginTop: 12 }}\n\t\t\t\t\t\t\tonClick={() => void loadMore()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tLoad more\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : null}\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAttention } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IAttentionScreenProps {\n\tclient: AdminClient;\n}\n\n// What needs the operator today. Empty is green.\nexport function AttentionScreen({ client }: IAttentionScreenProps) {\n\tconst { attention, isLoading, error, refresh } = useAttention(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Attention</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRefresh\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{isLoading && !attention ? (\n\t\t\t\t<p style={styles.status}>Running the checks…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : attention?.items.length === 0 ? (\n\t\t\t\t<p style={styles.ok}>\n\t\t\t\t\tNothing needs you. Checked {new Date(attention.generatedAt).toLocaleString()}.\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{attention?.items.map((item) => (\n\t\t\t\t\t\t<li key={`${item.source}:${item.message}`} style={styles.row}>\n\t\t\t\t\t\t\t<span style={item.severity === 'error' ? styles.bad : styles.advice}>\n\t\t\t\t\t\t\t\t{item.severity === 'error' ? 'error' : 'advice'}\n\t\t\t\t\t\t\t</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.mono}>{item.source}</span> — {item.message}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminConfig } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IConfigScreenProps {\n\tclient: AdminClient;\n}\n\n// Declared vs held: readiness per module, and whether each environment\n// variable the app reads is set. Values are never shown.\nexport function ConfigScreen({ client }: IConfigScreenProps) {\n\tconst { report, isLoading, error } = useAdminConfig(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Configuration</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : report ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>Readiness</h2>\n\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t{report.modules.map((m) => (\n\t\t\t\t\t\t\t<li key={m.name} style={styles.row}>\n\t\t\t\t\t\t\t\t<span style={styles.mono}>{m.name}</span>{' '}\n\t\t\t\t\t\t\t\t{m.problems.length === 0 ? (\n\t\t\t\t\t\t\t\t\t<span style={styles.ok}>ok</span>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\tm.problems.map((p) => (\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tkey={p.message}\n\t\t\t\t\t\t\t\t\t\t\tstyle={p.severity === 'error' ? styles.bad : styles.advice}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t\t<h2 style={styles.subtitle}>Environment</h2>\n\t\t\t\t\t{report.env.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>No variables declared — pass `env` to AdminModule.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{report.env.map((e) => (\n\t\t\t\t\t\t\t\t<li key={e.name} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{e.name}</span>{' '}\n\t\t\t\t\t\t\t\t\t{e.set ? (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.ok}>set</span>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.bad}>missing</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useDoctor } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IDoctorScreenProps {\n\tclient: AdminClient;\n}\n\n// Every reconciliation check, on demand. ok is false only for a hard failure;\n// findings on a passing check are advice.\nexport function DoctorScreen({ client }: IDoctorScreenProps) {\n\tconst { report, isLoading, error, refresh } = useDoctor(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<div style={styles.toolbar}>\n\t\t\t\t<h1 style={{ ...styles.title, marginBottom: 0 }}>Doctor</h1>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\tonClick={() => void refresh()}\n\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t>\n\t\t\t\t\tRun again\n\t\t\t\t</button>\n\t\t\t\t{report && !isLoading ? (\n\t\t\t\t\t<span style={report.ok ? styles.ok : styles.bad}>\n\t\t\t\t\t\t{report.ok ? 'all checks pass' : 'a check failed'}\n\t\t\t\t\t</span>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t{isLoading && !report ? (\n\t\t\t\t<p style={styles.status}>Running the checks…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t{report?.checks.map((c) => (\n\t\t\t\t\t\t<li key={c.name} style={styles.row}>\n\t\t\t\t\t\t\t<span style={c.skipped ? styles.muted : c.ok ? styles.ok : styles.bad}>\n\t\t\t\t\t\t\t\t{c.skipped ? 'skipped' : c.ok ? 'ok' : 'failed'}\n\t\t\t\t\t\t\t</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.mono}>{c.name}</span>{' '}\n\t\t\t\t\t\t\t<span style={styles.muted}>\n\t\t\t\t\t\t\t\t{c.module} · {c.durationMs} ms\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{c.skipped ? <div style={styles.muted}>{c.skipped}</div> : null}\n\t\t\t\t\t\t\t{c.findings.map((f) => (\n\t\t\t\t\t\t\t\t<div key={f} style={c.ok ? styles.advice : styles.bad}>\n\t\t\t\t\t\t\t\t\t{f}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useManifest } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IModulesScreenProps {\n\tclient: AdminClient;\n}\n\n// What is deployed: every module, its version, readiness, and whether it\n// offers anything to this surface.\nexport function ModulesScreen({ client }: IModulesScreenProps) {\n\tconst { manifest, isLoading, error } = useManifest(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Modules</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : manifest ? (\n\t\t\t\t<>\n\t\t\t\t\t<p style={styles.muted}>\n\t\t\t\t\t\t{manifest.env} · admin {manifest.admin.version} · admin log{' '}\n\t\t\t\t\t\t{manifest.admin.log ? 'on' : 'off'} · {manifest.routes.length} routes\n\t\t\t\t\t</p>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Version</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Readiness</th>\n\t\t\t\t\t\t\t\t<th style={styles.th}>Describes admin</th>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t{manifest.modules.map((m) => (\n\t\t\t\t\t\t\t\t<tr key={m.name}>\n\t\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{m.name}</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.version ?? <span style={styles.muted}>not reported</span>}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.readiness.ok ? (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.ok}>ok</span>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<span style={styles.bad}>error</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{m.readiness.problems.map((p) => (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tkey={p.message}\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={p.severity === 'error' ? styles.bad : styles.advice}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t\t{m.describesAdmin ? 'yes' : <span style={styles.muted}>no</span>}\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminRoutes } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface IRoutesScreenProps {\n\tclient: AdminClient;\n}\n\nexport function RoutesScreen({ client }: IRoutesScreenProps) {\n\tconst { report, isLoading, error } = useAdminRoutes(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Routes</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th style={styles.th}>Method</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Path</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Guard</th>\n\t\t\t\t\t\t\t<th style={styles.th}>Module</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t{report?.routes.map((r) => (\n\t\t\t\t\t\t\t<tr key={`${r.method} ${r.path}`}>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{r.method}</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{r.path}</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t<span style={styles.badge}>{r.guard}</span>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.muted }}>{r.module ?? 'application'}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { AdminClient } from '@fonderie/client';\nimport { useAdminTokens } from '@fonderie/react-admin';\nimport { styles } from '../styles';\n\nexport interface ITokensScreenProps {\n\tclient: AdminClient;\n}\n\nexport function TokensScreen({ client }: ITokensScreenProps) {\n\tconst { report, isLoading, error } = useAdminTokens(client);\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Access</h1>\n\t\t\t{isLoading ? (\n\t\t\t\t<p style={styles.status}>Loading…</p>\n\t\t\t) : error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.explanation}\n\t\t\t\t</p>\n\t\t\t) : report ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>Admin token</h2>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t{report.admin.ok ? (\n\t\t\t\t\t\t\t<span style={styles.ok}>strong</span>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span style={styles.bad}>weak</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{report.admin.problems.map((p) => (\n\t\t\t\t\t\t\t<div key={p.message} style={styles.bad}>\n\t\t\t\t\t\t\t\t{p.message}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</p>\n\t\t\t\t\t<h2 style={styles.subtitle}>Legacy per-brick tokens</h2>\n\t\t\t\t\t{report.legacy.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>None — every brick's admin surface goes through this token.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{report.legacy.map((l) => (\n\t\t\t\t\t\t\t\t<li key={l.module} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{l.module}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>\n\t\t\t\t\t\t\t\t\t\tstill registers its standalone routes with its own token (deprecated)\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n","import type { AuthAdminClient } from '@fonderie/client';\nimport { useAdminLoginHistory, useAdminUser, useAdminUserSessions } from '@fonderie/react-admin';\nimport { useState } from 'react';\nimport { styles } from '../styles';\n\nexport interface IUsersScreenProps {\n\tclient: AuthAdminClient;\n}\n\n// Why can't this person log in. Look up by email, see the account, its live\n// sessions and recent sign-ins; suspend, unsuspend, or sign them out everywhere.\nexport function UsersScreen({ client }: IUsersScreenProps) {\n\tconst [input, setInput] = useState('');\n\tconst [email, setEmail] = useState<string | undefined>(undefined);\n\tconst { user, isLoading, error, suspend, unsuspend, revokeSessions } = useAdminUser(\n\t\tclient,\n\t\temail ? { email } : {},\n\t);\n\tconst userId = user?.id ?? null;\n\tconst sessions = useAdminUserSessions(client, userId);\n\tconst history = useAdminLoginHistory(client, userId, { limit: 20 });\n\n\tconst yesNo = (v: boolean) =>\n\t\tv ? <span style={styles.ok}>yes</span> : <span style={styles.muted}>no</span>;\n\n\treturn (\n\t\t<div style={styles.container}>\n\t\t\t<h1 style={styles.title}>Users</h1>\n\t\t\t<form\n\t\t\t\tstyle={styles.toolbar}\n\t\t\t\tonSubmit={(e) => {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tsetEmail(input.trim() || undefined);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"email\"\n\t\t\t\t\tvalue={input}\n\t\t\t\t\tonChange={(e) => setInput(e.target.value)}\n\t\t\t\t\tplaceholder=\"email address\"\n\t\t\t\t\tstyle={{ ...styles.button, cursor: 'text', minWidth: 280 }}\n\t\t\t\t\taria-label=\"Email\"\n\t\t\t\t/>\n\t\t\t\t<button type=\"submit\" style={styles.button} disabled={isLoading}>\n\t\t\t\t\tLook up\n\t\t\t\t</button>\n\t\t\t</form>\n\t\t\t{error ? (\n\t\t\t\t<p style={styles.error} role=\"alert\">\n\t\t\t\t\t{error.status === 404 ? 'No user with that email.' : error.explanation}\n\t\t\t\t</p>\n\t\t\t) : null}\n\t\t\t{user ? (\n\t\t\t\t<>\n\t\t\t\t\t<h2 style={styles.subtitle}>\n\t\t\t\t\t\t{user.firstName || user.lastName\n\t\t\t\t\t\t\t? `${user.firstName} ${user.lastName}`.trim()\n\t\t\t\t\t\t\t: user.email}{' '}\n\t\t\t\t\t\t{user.suspended ? <span style={styles.badge}>suspended</span> : null}\n\t\t\t\t\t\t{user.deletedAt ? <span style={styles.badge}>deleted</span> : null}\n\t\t\t\t\t</h2>\n\t\t\t\t\t<table style={styles.table}>\n\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>id</td>\n\t\t\t\t\t\t\t\t<td style={{ ...styles.td, ...styles.mono }}>{user.id}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>email</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t{user.email} · verified {yesNo(user.isEmailVerified)}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>MFA</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>{yesNo(user.mfaEnabled)}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>provider</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t{user.provider || 'password'}\n\t\t\t\t\t\t\t\t\t{user.hasPassword ? '' : ' · no password set'}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>last login</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>\n\t\t\t\t\t\t\t\t\t{user.lastLogin ? (\n\t\t\t\t\t\t\t\t\t\tnew Date(user.lastLogin).toLocaleString()\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<span style={styles.muted}>never</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td style={styles.td}>created</td>\n\t\t\t\t\t\t\t\t<td style={styles.td}>{new Date(user.createdAt).toLocaleString()}</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</tbody>\n\t\t\t\t\t</table>\n\t\t\t\t\t<div style={{ ...styles.toolbar, marginTop: 12 }}>\n\t\t\t\t\t\t{user.suspended ? (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\t\t\t\tonClick={() => void unsuspend()}\n\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tUnsuspend\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\t\t\t\tonClick={() => void suspend()}\n\t\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tSuspend\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={styles.button}\n\t\t\t\t\t\t\tonClick={() => void revokeSessions().then(() => sessions.refresh())}\n\t\t\t\t\t\t\tdisabled={isLoading}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tSign out everywhere\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<h2 style={styles.subtitle}>Live sessions</h2>\n\t\t\t\t\t{sessions.sessions.length === 0 ? (\n\t\t\t\t\t\t<p style={styles.muted}>None.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{sessions.sessions.map((s) => (\n\t\t\t\t\t\t\t\t<li key={s.id} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={styles.mono}>{s.ipAddress ?? '—'}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{s.userAgent ?? ''}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>since {new Date(s.createdAt).toLocaleString()}</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<h2 style={styles.subtitle}>Recent sign-ins</h2>\n\t\t\t\t\t{history.events.length === 0 && !history.isLoading ? (\n\t\t\t\t\t\t<p style={styles.muted}>None recorded.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ul style={styles.list}>\n\t\t\t\t\t\t\t{history.events.map((e) => (\n\t\t\t\t\t\t\t\t<li key={e.id} style={styles.row}>\n\t\t\t\t\t\t\t\t\t<span style={e.outcome === 'success' ? styles.ok : styles.bad}>{e.outcome}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{e.method}</span>{' '}\n\t\t\t\t\t\t\t\t\t<span style={styles.muted}>{new Date(e.createdAt).toLocaleString()}</span>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t\t{history.hasMore && !history.isLoading ? (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tstyle={{ ...styles.button, marginTop: 8 }}\n\t\t\t\t\t\t\tonClick={() => void history.loadMore()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tLoad more\n\t\t\t\t\t\t</button>\n\t\t\t\t\t) : null}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n"],"mappings":"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","names":["useState","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","Fragment","jsx","jsxs","Fragment","jsx","jsxs","useState"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonderie/react-admin-screens",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "fonderie": {
5
5
  "stability": "experimental"
6
6
  },
package/dist/index.d.cts DELETED
@@ -1,51 +0,0 @@
1
- import * as react from 'react';
2
- import { AdminClient, ConfigAdminClient, CourierAdminClient } from '@fonderie/client';
3
-
4
- type AdminPage = 'attention' | 'modules' | 'doctor' | 'config' | 'routes' | 'tokens' | 'log' | 'settings' | 'templates';
5
- interface IAdminShellProps {
6
- client: AdminClient;
7
- configClient?: ConfigAdminClient;
8
- courierClient?: CourierAdminClient;
9
- environment?: string;
10
- page?: AdminPage;
11
- onNavigate?: (page: AdminPage) => void;
12
- }
13
- declare function AdminShell({ client, configClient, courierClient, environment, page, onNavigate, }: IAdminShellProps): react.JSX.Element;
14
-
15
- interface IAttentionScreenProps {
16
- client: AdminClient;
17
- }
18
- declare function AttentionScreen({ client }: IAttentionScreenProps): react.JSX.Element;
19
-
20
- interface IModulesScreenProps {
21
- client: AdminClient;
22
- }
23
- declare function ModulesScreen({ client }: IModulesScreenProps): react.JSX.Element;
24
-
25
- interface IDoctorScreenProps {
26
- client: AdminClient;
27
- }
28
- declare function DoctorScreen({ client }: IDoctorScreenProps): react.JSX.Element;
29
-
30
- interface IConfigScreenProps {
31
- client: AdminClient;
32
- }
33
- declare function ConfigScreen({ client }: IConfigScreenProps): react.JSX.Element;
34
-
35
- interface IRoutesScreenProps {
36
- client: AdminClient;
37
- }
38
- declare function RoutesScreen({ client }: IRoutesScreenProps): react.JSX.Element;
39
-
40
- interface ITokensScreenProps {
41
- client: AdminClient;
42
- }
43
- declare function TokensScreen({ client }: ITokensScreenProps): react.JSX.Element;
44
-
45
- interface IAdminLogScreenProps {
46
- client: AdminClient;
47
- pageSize?: number;
48
- }
49
- declare function AdminLogScreen({ client, pageSize }: IAdminLogScreenProps): react.JSX.Element;
50
-
51
- export { AdminLogScreen, type AdminPage, AdminShell, AttentionScreen, ConfigScreen, DoctorScreen, type IAdminLogScreenProps, type IAdminShellProps, type IAttentionScreenProps, type IConfigScreenProps, type IDoctorScreenProps, type IModulesScreenProps, type IRoutesScreenProps, type ITokensScreenProps, ModulesScreen, RoutesScreen, TokensScreen };
package/dist/index.d.ts DELETED
@@ -1,51 +0,0 @@
1
- import * as react from 'react';
2
- import { AdminClient, ConfigAdminClient, CourierAdminClient } from '@fonderie/client';
3
-
4
- type AdminPage = 'attention' | 'modules' | 'doctor' | 'config' | 'routes' | 'tokens' | 'log' | 'settings' | 'templates';
5
- interface IAdminShellProps {
6
- client: AdminClient;
7
- configClient?: ConfigAdminClient;
8
- courierClient?: CourierAdminClient;
9
- environment?: string;
10
- page?: AdminPage;
11
- onNavigate?: (page: AdminPage) => void;
12
- }
13
- declare function AdminShell({ client, configClient, courierClient, environment, page, onNavigate, }: IAdminShellProps): react.JSX.Element;
14
-
15
- interface IAttentionScreenProps {
16
- client: AdminClient;
17
- }
18
- declare function AttentionScreen({ client }: IAttentionScreenProps): react.JSX.Element;
19
-
20
- interface IModulesScreenProps {
21
- client: AdminClient;
22
- }
23
- declare function ModulesScreen({ client }: IModulesScreenProps): react.JSX.Element;
24
-
25
- interface IDoctorScreenProps {
26
- client: AdminClient;
27
- }
28
- declare function DoctorScreen({ client }: IDoctorScreenProps): react.JSX.Element;
29
-
30
- interface IConfigScreenProps {
31
- client: AdminClient;
32
- }
33
- declare function ConfigScreen({ client }: IConfigScreenProps): react.JSX.Element;
34
-
35
- interface IRoutesScreenProps {
36
- client: AdminClient;
37
- }
38
- declare function RoutesScreen({ client }: IRoutesScreenProps): react.JSX.Element;
39
-
40
- interface ITokensScreenProps {
41
- client: AdminClient;
42
- }
43
- declare function TokensScreen({ client }: ITokensScreenProps): react.JSX.Element;
44
-
45
- interface IAdminLogScreenProps {
46
- client: AdminClient;
47
- pageSize?: number;
48
- }
49
- declare function AdminLogScreen({ client, pageSize }: IAdminLogScreenProps): react.JSX.Element;
50
-
51
- export { AdminLogScreen, type AdminPage, AdminShell, AttentionScreen, ConfigScreen, DoctorScreen, type IAdminLogScreenProps, type IAdminShellProps, type IAttentionScreenProps, type IConfigScreenProps, type IDoctorScreenProps, type IModulesScreenProps, type IRoutesScreenProps, type ITokensScreenProps, ModulesScreen, RoutesScreen, TokensScreen };