portal-mojo 0.1.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.
Files changed (369) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +55 -0
  3. package/docs/DetailView.md +173 -0
  4. package/docs/ModelTable.md +128 -0
  5. package/docs/README.md +98 -0
  6. package/docs/admin-assistant.md +72 -0
  7. package/docs/admin-bouncer.md +120 -0
  8. package/docs/admin-cloudwatch.md +38 -0
  9. package/docs/admin-credentials.md +116 -0
  10. package/docs/admin-dashboard.md +15 -0
  11. package/docs/admin-devices-geoip.md +284 -0
  12. package/docs/admin-dns-certificates.md +122 -0
  13. package/docs/admin-dns-records.md +65 -0
  14. package/docs/admin-dns-registrar.md +33 -0
  15. package/docs/admin-dns.md +80 -0
  16. package/docs/admin-identity-users.md +103 -0
  17. package/docs/admin-incidents.md +71 -0
  18. package/docs/admin-jobs.md +426 -0
  19. package/docs/admin-members.md +112 -0
  20. package/docs/admin-messaging.md +56 -0
  21. package/docs/admin-metrics-explorer.md +63 -0
  22. package/docs/admin-monitoring.md +99 -0
  23. package/docs/admin-network-security.md +393 -0
  24. package/docs/admin-phonehub.md +27 -0
  25. package/docs/admin-push.md +36 -0
  26. package/docs/admin-rules.md +87 -0
  27. package/docs/admin-security-tickets.md +40 -0
  28. package/docs/admin-settings.md +78 -0
  29. package/docs/admin-shortlinks.md +32 -0
  30. package/docs/admin-storage.md +141 -0
  31. package/docs/auth-pages.md +212 -0
  32. package/docs/auth.md +58 -0
  33. package/docs/calendar.md +122 -0
  34. package/docs/charts.md +303 -0
  35. package/docs/client.md +206 -0
  36. package/docs/collection-multiselect.md +117 -0
  37. package/docs/collection-select.md +132 -0
  38. package/docs/combobox.md +105 -0
  39. package/docs/dataview.md +226 -0
  40. package/docs/datepicker.md +151 -0
  41. package/docs/daterange.md +170 -0
  42. package/docs/datetimepicker.md +249 -0
  43. package/docs/defineModel.md +72 -0
  44. package/docs/detail-primitives.md +174 -0
  45. package/docs/feedback.md +85 -0
  46. package/docs/file-upload-ux.md +146 -0
  47. package/docs/forms.md +435 -0
  48. package/docs/grouping-and-fmt.md +98 -0
  49. package/docs/idioms.md +112 -0
  50. package/docs/image-editor.md +101 -0
  51. package/docs/loading.md +242 -0
  52. package/docs/location-address.md +76 -0
  53. package/docs/markdown.md +203 -0
  54. package/docs/menus-and-access.md +89 -0
  55. package/docs/multiselect-dropdown.md +153 -0
  56. package/docs/params.md +73 -0
  57. package/docs/popover.md +130 -0
  58. package/docs/realtime.md +61 -0
  59. package/docs/record-feed.md +238 -0
  60. package/docs/right-panel.md +42 -0
  61. package/docs/tabs-and-form-wizard.md +60 -0
  62. package/docs/taginput.md +120 -0
  63. package/docs/timepicker.md +173 -0
  64. package/docs/timezone-select.md +147 -0
  65. package/docs/worldmap.md +302 -0
  66. package/package.json +55 -0
  67. package/src/admin/assistant/AssistantFeed.tsx +29 -0
  68. package/src/admin/assistant/AssistantPanel.tsx +65 -0
  69. package/src/admin/assistant/api.ts +17 -0
  70. package/src/admin/assistant/data.ts +63 -0
  71. package/src/admin/assistant/index.ts +21 -0
  72. package/src/admin/assistant/launchers.tsx +33 -0
  73. package/src/admin/assistant/pages.tsx +78 -0
  74. package/src/admin/assistant/streaming.ts +238 -0
  75. package/src/admin/assistant/types.ts +30 -0
  76. package/src/admin/bouncer/devices.tsx +230 -0
  77. package/src/admin/bouncer/index.ts +34 -0
  78. package/src/admin/bouncer/models.ts +199 -0
  79. package/src/admin/bouncer/signals.tsx +182 -0
  80. package/src/admin/bouncer/signatures.tsx +220 -0
  81. package/src/admin/cloudwatch/CloudWatchChart.tsx +61 -0
  82. package/src/admin/cloudwatch/CloudWatchDashboardPage.tsx +52 -0
  83. package/src/admin/cloudwatch/CloudWatchResourceDetail.tsx +33 -0
  84. package/src/admin/cloudwatch/data.ts +163 -0
  85. package/src/admin/cloudwatch/index.ts +16 -0
  86. package/src/admin/credentials/group-api-keys.tsx +433 -0
  87. package/src/admin/credentials/index.ts +4 -0
  88. package/src/admin/credentials/models.ts +244 -0
  89. package/src/admin/credentials/secret-dialog.tsx +77 -0
  90. package/src/admin/credentials/webhook-subscriptions.tsx +423 -0
  91. package/src/admin/dashboard/AdminDashboardPage.tsx +101 -0
  92. package/src/admin/dashboard/data.ts +60 -0
  93. package/src/admin/dashboard/index.ts +2 -0
  94. package/src/admin/dns/CertificateDetail.tsx +115 -0
  95. package/src/admin/dns/CertificateLifecyclePoller.tsx +141 -0
  96. package/src/admin/dns/CertificateRequestDialog.tsx +103 -0
  97. package/src/admin/dns/CertificatesPage.tsx +85 -0
  98. package/src/admin/dns/DnsRecordEditor.tsx +110 -0
  99. package/src/admin/dns/DnsRecordsPage.tsx +36 -0
  100. package/src/admin/dns/DnsRecordsPanel.tsx +71 -0
  101. package/src/admin/dns/DomainCertificatesSection.tsx +40 -0
  102. package/src/admin/dns/DomainDetail.tsx +41 -0
  103. package/src/admin/dns/DomainOnboardingDialog.tsx +27 -0
  104. package/src/admin/dns/DomainPurchaseDetail.tsx +11 -0
  105. package/src/admin/dns/DomainPurchaseWizard.tsx +112 -0
  106. package/src/admin/dns/DomainPurchasesPage.tsx +16 -0
  107. package/src/admin/dns/DomainsPage.tsx +27 -0
  108. package/src/admin/dns/ProviderCredentialsPage.tsx +304 -0
  109. package/src/admin/dns/RegistrantContactPage.tsx +42 -0
  110. package/src/admin/dns/api.ts +515 -0
  111. package/src/admin/dns/certificate-data.ts +221 -0
  112. package/src/admin/dns/data.ts +32 -0
  113. package/src/admin/dns/dns-data.ts +266 -0
  114. package/src/admin/dns/dns-integration.ts +24 -0
  115. package/src/admin/dns/domain-links.ts +37 -0
  116. package/src/admin/dns/index.ts +86 -0
  117. package/src/admin/dns/models.ts +418 -0
  118. package/src/admin/dns/purchase-data.ts +67 -0
  119. package/src/admin/dns/registrant-data.ts +52 -0
  120. package/src/admin/identity/index.ts +5 -0
  121. package/src/admin/identity/members/GroupMembersPanel.tsx +146 -0
  122. package/src/admin/identity/members/MemberDetail.tsx +226 -0
  123. package/src/admin/identity/members/MembersPage.tsx +144 -0
  124. package/src/admin/identity/members/index.ts +24 -0
  125. package/src/admin/identity/members/member-flows.tsx +132 -0
  126. package/src/admin/identity/members/models.ts +204 -0
  127. package/src/admin/identity/users/UserDetail.tsx +257 -0
  128. package/src/admin/identity/users/UsersPage.tsx +163 -0
  129. package/src/admin/identity/users/index.ts +27 -0
  130. package/src/admin/identity/users/models.ts +232 -0
  131. package/src/admin/identity/users/sections/ApiKeysSection.tsx +119 -0
  132. package/src/admin/identity/users/sections/AuditSection.tsx +190 -0
  133. package/src/admin/identity/users/sections/DevicesSection.tsx +140 -0
  134. package/src/admin/identity/users/sections/GroupsSection.tsx +64 -0
  135. package/src/admin/identity/users/sections/LoginsSection.tsx +106 -0
  136. package/src/admin/identity/users/sections/MetadataPanel.tsx +36 -0
  137. package/src/admin/identity/users/sections/NotificationsSection.tsx +117 -0
  138. package/src/admin/identity/users/sections/OAuthSection.tsx +72 -0
  139. package/src/admin/identity/users/sections/OverviewSection.tsx +109 -0
  140. package/src/admin/identity/users/sections/PermissionsSection.tsx +35 -0
  141. package/src/admin/identity/users/sections/PersonalSection.tsx +73 -0
  142. package/src/admin/identity/users/sections/ProfileSection.tsx +175 -0
  143. package/src/admin/identity/users/sections/SecuritySection.tsx +123 -0
  144. package/src/admin/identity/users/sections/actions.tsx +752 -0
  145. package/src/admin/identity/users/sections/permission-catalog.ts +138 -0
  146. package/src/admin/identity/users/sections/queries.ts +74 -0
  147. package/src/admin/identity/users/sections/shared.tsx +299 -0
  148. package/src/admin/incidents/EventDetail.tsx +43 -0
  149. package/src/admin/incidents/EventsPage.tsx +52 -0
  150. package/src/admin/incidents/IncidentDetail.tsx +68 -0
  151. package/src/admin/incidents/IncidentsPage.tsx +102 -0
  152. package/src/admin/incidents/forensics.tsx +73 -0
  153. package/src/admin/incidents/index.ts +16 -0
  154. package/src/admin/incidents/models.ts +113 -0
  155. package/src/admin/incidents/sanitize.ts +71 -0
  156. package/src/admin/index.ts +383 -0
  157. package/src/admin/jobs/JobDashboardPage.tsx +111 -0
  158. package/src/admin/jobs/JobDetail.tsx +721 -0
  159. package/src/admin/jobs/JobRunnersPage.tsx +216 -0
  160. package/src/admin/jobs/JobsTablePage.tsx +122 -0
  161. package/src/admin/jobs/RunnerDetail.tsx +576 -0
  162. package/src/admin/jobs/ScheduledTaskDetail.tsx +421 -0
  163. package/src/admin/jobs/ScheduledTasksPage.tsx +167 -0
  164. package/src/admin/jobs/columns.tsx +297 -0
  165. package/src/admin/jobs/control.ts +488 -0
  166. package/src/admin/jobs/index.ts +85 -0
  167. package/src/admin/jobs/models.ts +599 -0
  168. package/src/admin/jobs/queries.ts +272 -0
  169. package/src/admin/jobs/scheduled-task-form.tsx +493 -0
  170. package/src/admin/jobs/sections/JobChannelsPanel.tsx +142 -0
  171. package/src/admin/jobs/sections/JobOperationsSection.tsx +423 -0
  172. package/src/admin/jobs/sections/JobRunnersStrip.tsx +82 -0
  173. package/src/admin/jobs/sections/JobThroughputSection.tsx +118 -0
  174. package/src/admin/messaging/EmailDomainWizard.tsx +24 -0
  175. package/src/admin/messaging/EmailDomainsPage.tsx +17 -0
  176. package/src/admin/messaging/EmailTemplatesPage.tsx +13 -0
  177. package/src/admin/messaging/MailboxesPage.tsx +15 -0
  178. package/src/admin/messaging/PublicMessagesPage.tsx +13 -0
  179. package/src/admin/messaging/SandboxedEmailPreview.tsx +23 -0
  180. package/src/admin/messaging/SentMessagesPage.tsx +11 -0
  181. package/src/admin/messaging/api.ts +17 -0
  182. package/src/admin/messaging/data.ts +10 -0
  183. package/src/admin/messaging/index.ts +23 -0
  184. package/src/admin/messaging/models.ts +76 -0
  185. package/src/admin/messaging/push/PushPage.tsx +44 -0
  186. package/src/admin/messaging/push/api.ts +17 -0
  187. package/src/admin/messaging/push/index.ts +9 -0
  188. package/src/admin/messaging/push/models.ts +43 -0
  189. package/src/admin/messaging/sanitize.ts +44 -0
  190. package/src/admin/monitoring/LogInspector.tsx +160 -0
  191. package/src/admin/monitoring/LogsPage.tsx +135 -0
  192. package/src/admin/monitoring/MetricsExplorerPage.tsx +360 -0
  193. package/src/admin/monitoring/MetricsPermissionsPage.tsx +166 -0
  194. package/src/admin/monitoring/MetricsSourcePicker.tsx +136 -0
  195. package/src/admin/monitoring/index.ts +55 -0
  196. package/src/admin/monitoring/metrics-explorer-client.ts +229 -0
  197. package/src/admin/monitoring/metrics-explorer-data.ts +158 -0
  198. package/src/admin/monitoring/models.ts +155 -0
  199. package/src/admin/network/BlockedIPsPage.tsx +194 -0
  200. package/src/admin/network/BlockedIpDetail.tsx +262 -0
  201. package/src/admin/network/FirewallLogPage.tsx +115 -0
  202. package/src/admin/network/IPSetDetail.tsx +280 -0
  203. package/src/admin/network/IPSetEditor.tsx +191 -0
  204. package/src/admin/network/IPSetsPage.tsx +177 -0
  205. package/src/admin/network/geofence/BlocksTab.tsx +289 -0
  206. package/src/admin/network/geofence/ExemptionsTab.tsx +349 -0
  207. package/src/admin/network/geofence/GeofencingPage.tsx +119 -0
  208. package/src/admin/network/geofence/PostureHeader.tsx +184 -0
  209. package/src/admin/network/geofence/RuleEditor.tsx +176 -0
  210. package/src/admin/network/geofence/RulesTab.tsx +254 -0
  211. package/src/admin/network/geofence/SimulatorTab.tsx +281 -0
  212. package/src/admin/network/geofence/geofence-data.ts +674 -0
  213. package/src/admin/network/index.ts +68 -0
  214. package/src/admin/network/models.ts +607 -0
  215. package/src/admin/phonehub/PhoneHubPage.tsx +57 -0
  216. package/src/admin/phonehub/api.ts +47 -0
  217. package/src/admin/phonehub/data.ts +6 -0
  218. package/src/admin/phonehub/index.ts +10 -0
  219. package/src/admin/phonehub/models.ts +68 -0
  220. package/src/admin/rules/HandlerChainBuilder.tsx +51 -0
  221. package/src/admin/rules/RuleSetDetailPage.tsx +33 -0
  222. package/src/admin/rules/RuleSetsPage.tsx +33 -0
  223. package/src/admin/rules/editors.tsx +54 -0
  224. package/src/admin/rules/handler-dsl.ts +213 -0
  225. package/src/admin/rules/index.ts +13 -0
  226. package/src/admin/rules/models.ts +112 -0
  227. package/src/admin/security/devices/LoginEventDetail.tsx +123 -0
  228. package/src/admin/security/devices/LoginLocationMap.tsx +321 -0
  229. package/src/admin/security/devices/LoginLocationsPage.tsx +162 -0
  230. package/src/admin/security/devices/UserDeviceDetail.tsx +546 -0
  231. package/src/admin/security/devices/UserDeviceLocationDetail.tsx +272 -0
  232. package/src/admin/security/devices/UserDevicesPage.tsx +84 -0
  233. package/src/admin/security/devices/index.ts +40 -0
  234. package/src/admin/security/devices/models.ts +470 -0
  235. package/src/admin/security/geoip/GeoIpCachePage.tsx +135 -0
  236. package/src/admin/security/geoip/GeoIpDossier.tsx +804 -0
  237. package/src/admin/security/geoip/geoip-forms.ts +102 -0
  238. package/src/admin/security/geoip/index.ts +27 -0
  239. package/src/admin/security/geoip/models.ts +397 -0
  240. package/src/admin/security/index.ts +31 -0
  241. package/src/admin/security/models.ts +137 -0
  242. package/src/admin/security/tickets.tsx +562 -0
  243. package/src/admin/security-permissions.ts +5 -0
  244. package/src/admin/settings/SettingDetail.tsx +57 -0
  245. package/src/admin/settings/SettingEditor.tsx +157 -0
  246. package/src/admin/settings/SettingsPage.tsx +72 -0
  247. package/src/admin/settings/index.ts +19 -0
  248. package/src/admin/settings/model.ts +143 -0
  249. package/src/admin/shortlinks/ShortlinkDetail.tsx +55 -0
  250. package/src/admin/shortlinks/ShortlinkHistoryPage.tsx +18 -0
  251. package/src/admin/shortlinks/ShortlinksPage.tsx +59 -0
  252. package/src/admin/shortlinks/index.ts +18 -0
  253. package/src/admin/shortlinks/models.ts +246 -0
  254. package/src/admin/storage/BackendsPage.tsx +43 -0
  255. package/src/admin/storage/BucketDetail.tsx +77 -0
  256. package/src/admin/storage/BucketsPage.tsx +64 -0
  257. package/src/admin/storage/FileManagerDetail.tsx +36 -0
  258. package/src/admin/storage/FilePreview.tsx +54 -0
  259. package/src/admin/storage/FileUploadSurface.tsx +250 -0
  260. package/src/admin/storage/FileView.tsx +109 -0
  261. package/src/admin/storage/FilesPage.tsx +53 -0
  262. package/src/admin/storage/file-renditions.ts +99 -0
  263. package/src/admin/storage/index.ts +31 -0
  264. package/src/admin/storage/models.ts +585 -0
  265. package/src/admin/storage/storage-dialogs.tsx +80 -0
  266. package/src/charts/CircularProgress.tsx +281 -0
  267. package/src/charts/KPIStrip.tsx +162 -0
  268. package/src/charts/KPITile.tsx +125 -0
  269. package/src/charts/MetricsChart.tsx +459 -0
  270. package/src/charts/MetricsMiniWidget.tsx +588 -0
  271. package/src/charts/MiniChart.tsx +283 -0
  272. package/src/charts/PieChart.tsx +354 -0
  273. package/src/charts/SeriesChart.tsx +378 -0
  274. package/src/charts/chart-dialogs.tsx +149 -0
  275. package/src/charts/exportChart.ts +144 -0
  276. package/src/charts/index.ts +28 -0
  277. package/src/charts/pie-math.ts +127 -0
  278. package/src/charts/stats.ts +265 -0
  279. package/src/charts/worldmap/WorldMap.tsx +649 -0
  280. package/src/charts/worldmap/countryCentroids.ts +304 -0
  281. package/src/charts/worldmap/geo.ts +293 -0
  282. package/src/charts/worldmap/use-world-land.ts +47 -0
  283. package/src/charts/worldmap/world-land.ts +18 -0
  284. package/src/charts/worldmap/worldmap-data.ts +285 -0
  285. package/src/client/auth.ts +737 -0
  286. package/src/client/client.ts +268 -0
  287. package/src/client/duid.ts +31 -0
  288. package/src/client/errors.ts +33 -0
  289. package/src/client/group-context.ts +28 -0
  290. package/src/client/group.tsx +126 -0
  291. package/src/client/hooks.ts +50 -0
  292. package/src/client/index.ts +37 -0
  293. package/src/client/jwt.ts +75 -0
  294. package/src/client/location.ts +285 -0
  295. package/src/client/lookups.ts +41 -0
  296. package/src/client/markdown-fallback.tsx +115 -0
  297. package/src/client/markdown-parse.ts +386 -0
  298. package/src/client/markdown-sanitize.ts +217 -0
  299. package/src/client/markdown.ts +122 -0
  300. package/src/client/me.ts +188 -0
  301. package/src/client/mock.ts +9984 -0
  302. package/src/client/model.ts +227 -0
  303. package/src/client/params.ts +292 -0
  304. package/src/client/realtime-mock.ts +221 -0
  305. package/src/client/realtime.ts +561 -0
  306. package/src/client/record-feed.ts +329 -0
  307. package/src/client/safe-export.ts +71 -0
  308. package/src/client/types.ts +278 -0
  309. package/src/client/upload.ts +421 -0
  310. package/src/ui/AddressField.tsx +273 -0
  311. package/src/ui/AttachmentQueue.tsx +92 -0
  312. package/src/ui/CollectionMultiSelect.tsx +622 -0
  313. package/src/ui/CollectionSelect.tsx +517 -0
  314. package/src/ui/ComboBox.tsx +336 -0
  315. package/src/ui/DetailView.tsx +438 -0
  316. package/src/ui/FileDrop.tsx +194 -0
  317. package/src/ui/FileField.tsx +369 -0
  318. package/src/ui/FilterBar.tsx +269 -0
  319. package/src/ui/FormFields.tsx +77 -0
  320. package/src/ui/FormView.tsx +360 -0
  321. package/src/ui/FormWizard.tsx +336 -0
  322. package/src/ui/GroupSwitcher.tsx +202 -0
  323. package/src/ui/Guarded.tsx +16 -0
  324. package/src/ui/MarkdownView.tsx +89 -0
  325. package/src/ui/ModelTable.tsx +848 -0
  326. package/src/ui/MultiSelectDropdown.tsx +390 -0
  327. package/src/ui/Popover.tsx +204 -0
  328. package/src/ui/RecordFeed.tsx +627 -0
  329. package/src/ui/RequiresGroup.tsx +32 -0
  330. package/src/ui/RightPanel.tsx +107 -0
  331. package/src/ui/SidebarNav.tsx +330 -0
  332. package/src/ui/Tabs.tsx +161 -0
  333. package/src/ui/TagInput.tsx +381 -0
  334. package/src/ui/ThemeProvider.tsx +52 -0
  335. package/src/ui/UploadQueue.tsx +603 -0
  336. package/src/ui/armed-button.tsx +91 -0
  337. package/src/ui/date/Calendar.tsx +498 -0
  338. package/src/ui/date/DatePicker.tsx +289 -0
  339. package/src/ui/date/DateRangePicker.tsx +280 -0
  340. package/src/ui/date/DateTimePicker.tsx +587 -0
  341. package/src/ui/date/PresetRail.tsx +165 -0
  342. package/src/ui/date/TimePicker.tsx +624 -0
  343. package/src/ui/date/TimezoneSelect.tsx +267 -0
  344. package/src/ui/date/fns.ts +679 -0
  345. package/src/ui/detail/DataView.tsx +692 -0
  346. package/src/ui/detail/FlowStrip.tsx +80 -0
  347. package/src/ui/detail/KnownFieldsCard.tsx +121 -0
  348. package/src/ui/detail/MetadataSection.tsx +219 -0
  349. package/src/ui/detail/StackTraceView.tsx +150 -0
  350. package/src/ui/detail/StatusPanel.tsx +73 -0
  351. package/src/ui/detail/Timeline.tsx +52 -0
  352. package/src/ui/detail/index.ts +12 -0
  353. package/src/ui/field-registry.tsx +428 -0
  354. package/src/ui/field-wire.ts +322 -0
  355. package/src/ui/form-autosave.ts +583 -0
  356. package/src/ui/format.ts +444 -0
  357. package/src/ui/grouping.ts +150 -0
  358. package/src/ui/image-editor/ImageEditor.tsx +484 -0
  359. package/src/ui/image-editor/canvas.ts +254 -0
  360. package/src/ui/image-editor/index.ts +3 -0
  361. package/src/ui/image-editor/math.ts +416 -0
  362. package/src/ui/index.ts +58 -0
  363. package/src/ui/loading.tsx +604 -0
  364. package/src/ui/menu-registry.ts +213 -0
  365. package/src/ui/modal.tsx +297 -0
  366. package/src/ui/password.tsx +302 -0
  367. package/src/ui/schema-form-core.tsx +315 -0
  368. package/src/ui/toast.tsx +219 -0
  369. package/src/ui/ui.tsx +45 -0
@@ -0,0 +1,112 @@
1
+ # Admin Members
2
+
3
+ Reusable global membership administration for django-mojo. Import from
4
+ `portal-mojo/admin`:
5
+
6
+ ```tsx
7
+ import {
8
+ MembersPage,
9
+ MemberDetail,
10
+ GroupMembersPanel,
11
+ MemberModel,
12
+ MEMBERS_ADMIN_SECTION,
13
+ openMemberAdmissionDialog,
14
+ registerMemberPermissions,
15
+ } from 'portal-mojo/admin';
16
+ ```
17
+
18
+ ## Wire contract
19
+
20
+ `MemberModel` speaks `/api/group/member`. Its default row is:
21
+
22
+ ```ts
23
+ {
24
+ id, created, modified, is_active,
25
+ permissions: Record<string, unknown>,
26
+ metadata: { role?: string, ... },
27
+ user: User | null,
28
+ group: Group | null,
29
+ }
30
+ ```
31
+
32
+ There is no top-level `role` or `status`: the presentation label is
33
+ `metadata.role`, and state is `is_active`. Relation columns are rendered but
34
+ not sortable. The model normalizes list state to verified parameters only:
35
+ search, paging, `id|created|modified|is_active` ordering, exact group/user and
36
+ active filters, `__icontains` lookups for user email/display name, group name
37
+ and role metadata, plus created/modified date ranges.
38
+
39
+ Supported mutations are collection create `{group,user}`, detail update, and
40
+ the `resend_invite` POST_SAVE_ACTION. Resend returns a payload (`{status:true}`),
41
+ not a refreshed member row. GroupMember declares neither delete nor generic
42
+ batch support, and has no move action. Remove and Move are intentionally absent:
43
+ a generic `{group:newId}` update is not a target-authorized move contract.
44
+
45
+ Audit rows filter `/api/logs` with `model_name=account.GroupMember` and the
46
+ membership `model_id`. `account.Member` is the obsolete web-mojo value.
47
+
48
+ ## Admission and the no-oracle boundary
49
+
50
+ `openMemberAdmissionDialog` makes Invite and Add-existing separate choices.
51
+ Global Members selects a group first; `GroupMembersPanel` already has a fixed
52
+ group. Invite posts the supplied email directly to
53
+ `/api/group/member/invite`—it never probes `/api/user`. The confirmation is
54
+ the same whether the address is new, existing, or already associated.
55
+
56
+ Add-existing is deliberately directory-backed. It appears only when the
57
+ operator has both the Member create gate and the global user-directory gate;
58
+ only then does the `/api/user` picker run before collection POST.
59
+
60
+ ## Permission tiers
61
+
62
+ Every global Admin clause is system-pinned:
63
+
64
+ - read: `sys.view_members | sys.view_groups | sys.manage_groups |
65
+ sys.manage_group | sys.groups`
66
+ - save/create: `sys.manage_groups | sys.manage_group | sys.groups`
67
+ - invite: `sys.manage_users | sys.manage_members | sys.manage_group |
68
+ sys.manage_groups`
69
+ - directory: `sys.view_users | sys.manage_users | sys.users`
70
+
71
+ Literal member `sys.*` keys always fail `memberHasPermission`, including a
72
+ malformed dictionary containing the exact requested key. User-level system
73
+ grants and superuser behavior in `hasPermission` are unchanged.
74
+
75
+ Three permission views must remain distinct:
76
+
77
+ 1. Raw stored grants are the truthy keys in the JSON dictionary.
78
+ 2. Effective member grants omit literal `sys.*`, stored `full_member`, and
79
+ legacy `admin`; `member` is intrinsic and `full_member` is derived when
80
+ `guest` is false.
81
+ 3. User-level `sys.*` grants come only from the User permission dictionary.
82
+
83
+ The client retains the historical non-system member `admin` wildcard for
84
+ product portals, but django-mojo GroupMember does not honor it server-side.
85
+ Admin is labeled as client compatibility only and is never an editable grant.
86
+ `metadata.role` is also display-only and confers no authority.
87
+
88
+ ## Extensible editable grants
89
+
90
+ The safe baseline includes ordinary group grants and the `guest` marker.
91
+ Products register additional controls:
92
+
93
+ ```ts
94
+ registerMemberPermissions([
95
+ { name: 'view_orders', label: 'View orders' },
96
+ { name: 'manage_orders', label: 'Manage orders' },
97
+ ]);
98
+ ```
99
+
100
+ `sys.*`, `admin`, `member`, and `full_member` registrations are rejected.
101
+ Stored deployment-specific grants without a registered editor stay visible
102
+ and read-only rather than disappearing. Permission switches autosave through
103
+ `FormView`; a deployment's `MEMBER_PERMS_PROTECTION` remains authoritative,
104
+ and rejected changes revert with the server error shown.
105
+
106
+ ## Composition
107
+
108
+ `MEMBERS_ADMIN_SECTION` is root-relative and dual-mounts as `/members` in the
109
+ standalone Admin and `/system/members` when embedded. It never consumes active
110
+ group context. `GroupMembersPanel` is the reusable Group-detail composition;
111
+ pass optional `onNavigateUser` and `onNavigateGroup` callbacks to connect
112
+ sibling identity details without coupling the package to an app.
@@ -0,0 +1,56 @@
1
+ # Communications Admin
2
+
3
+ ```ts
4
+ import {
5
+ EMAIL_ADMIN_SECTION, PUBLIC_MESSAGES_ADMIN_SECTION,
6
+ EmailDomainModel, MailboxModel, SentMessageModel,
7
+ EmailTemplateModel, PublicMessageModel,
8
+ } from 'portal-mojo/admin';
9
+ ```
10
+
11
+ The global, no-group Communications workspace mounts at `email/domains`,
12
+ `email/mailboxes`, `email/sent`, `email/templates`, and
13
+ `messaging/public-messages` (or under `/system` in an embedded portal). Every
14
+ record opens in a native KISS detail modal; there are no record-detail routes
15
+ or drawers.
16
+
17
+ Email uses global `sys.manage_aws | sys.comms` for both view and mutation,
18
+ matching django-mojo's current single tier. Contact-message view uses
19
+ `sys.view_support | sys.security | sys.support`, status mutation uses
20
+ `sys.manage_support | sys.security | sys.support`, and delete uses only
21
+ `sys.manage_support`. A granular manager must also hold a view grant to open
22
+ the page. Active-group membership never satisfies a global Admin gate.
23
+
24
+ Domain credentials are write-only. Secret-bearing saves, onboarding, audit,
25
+ reconcile, and send are imperative and never use MutationCache. Audit is POST,
26
+ has no automatic retry, and always refreshes because it persists readiness.
27
+ Create reports only that the row was created: django-mojo's best-effort
28
+ create-time audit/reconcile can fail after the row exists. Delete warns that
29
+ local mailboxes and sent audit history disappear while SES/SNS/S3/DNS
30
+ resources may remain.
31
+
32
+ Onboarding composes the shared `FormWizard`. Managed mode is available only
33
+ when the optional DNS Admin integration resolves the normalized domain and
34
+ uses its one record store; no provider key is submitted. Manual mode always
35
+ shows the complete returned verification, DKIM, and MAIL-FROM records. Managed
36
+ failure never silently retries manually because SES-side work may already
37
+ have occurred.
38
+
39
+ Sent-message and template HTML is untrusted. `SandboxedEmailPreview` uses a
40
+ bare iframe sandbox, `referrerPolicy="no-referrer"`, an offline CSP, removed
41
+ meta refresh, and neutralized links. Safe exports are explicit projections:
42
+ template bodies, message bodies, BCC, template context, provider metadata,
43
+ contact-message body/IP/user-agent/metadata, and credential masks never leave.
44
+
45
+ Stable mock identities (password `mojo`):
46
+
47
+ - `email.operator@nativemojo.com` — email only (`comms`).
48
+ - `support.viewer@nativemojo.com` — contact read only.
49
+ - `support.manager@nativemojo.com` — contact read/update/delete.
50
+ - `support.manage-only@nativemojo.com` — delete authority but intentionally no page view.
51
+ - `showcase.operator@nativemojo.com` — executable showcase coverage.
52
+
53
+ Live verification is read-only by default. Never create/edit/delete a domain,
54
+ replace credentials, audit, onboard, reconcile, or send without explicit
55
+ authorization for that exact live action. SES quota is intentionally absent;
56
+ django-mojo #1310 tracks the missing backend endpoint.
@@ -0,0 +1,63 @@
1
+ # Admin Metrics Explorer
2
+
3
+ `MetricsExplorerPage` is the read-only, global Admin workspace for django-mojo's recorded time-series metrics. Import it, its route contribution, or its exact adapters from `portal-mojo/admin`; import the reusable chart seam from `portal-mojo/charts`.
4
+
5
+ ```tsx
6
+ import { MONITORING_ADMIN_SECTION, MetricsExplorerPage } from 'portal-mojo/admin';
7
+
8
+ <MetricsExplorerPage />
9
+ ```
10
+
11
+ The registered route is `/metrics/explorer` standalone and `/system/metrics/explorer` when `adminSectionRoutes()` is mounted below `/system`. Its exact any-of gate is `sys.view_metrics | sys.metrics`. That clause stays separate from the existing metrics-permission editor gate; `sys.manage_metrics` alone does not imply read access.
12
+
13
+ ## Discovery wire
14
+
15
+ The page consumes only django-mojo #1438:
16
+
17
+ ```text
18
+ GET /api/metrics/discover?resource=accounts|categories|slugs
19
+ ```
20
+
21
+ `discoverMetrics()` uses `mojoCall`, because the stable response fields `resource`, `filters`, `count`, `page_count`, and `next_start` are top-level envelope metadata that `mojoList` would discard. It validates the exact resource/filter echo and internally consistent paging before returning a `MetricsDiscoveryPage`. Permission failures reject; they never become an empty authorized catalog.
22
+
23
+ Account entry accepts exact `public`, `global`, `group-<positive-id>`, `user-<positive-id>`, or a bounded opaque custom account. Invalid reserved forms do not fall back to custom interpretation. Registry selection is URL-backed, with one repeated `slug` parameter per full slug. Comma-bearing slugs are reported as unaddressable because history endpoints use a comma-delimited request grammar.
24
+
25
+ Group and User `CollectionSelect` conveniences are separate capabilities. They mount only under `sys.view_groups|sys.manage_groups|sys.groups` and `sys.view_users|sys.manage_users|sys.users`, respectively. Without those clauses the exact account input remains available and no directory picker request can start.
26
+
27
+ ## Full-slug identity
28
+
29
+ Full colon-bearing strings are the client identity. The backend responses are deliberately asymmetric:
30
+
31
+ - `/api/metrics/fetch` and fan-out sum key each dataset by the last colon segment;
32
+ - `/api/metrics/series?with_delta=true` preserves full keys;
33
+ - `/api/metrics/value/get` again truncates to the last segment.
34
+
35
+ `loadExactMetricSeries()` repairs history at the boundary. It batches globally unique tails, splits every member of a duplicate-tail group into its own request, validates exact response keys and compatible labels, and reassembles datasets in original request order. It rejects missing, extra, or ambiguous results. Fan-out breakdown requires one slug and preserves the returned child labels plus required `groups` map. `fetchMetricPoints()` validates full-key current/previous/delta maps, including the valid previous-zero case where `delta_pct` is absent. `readMetricValue()` reads one exact full slug per request.
36
+
37
+ History uses `dt_start` and `dt_end` epoch seconds. `dr_*` belongs to model-list aggregation and is never emitted here. The explorer has no record, value-set, permission mutation, or arbitrary `_mode` surface.
38
+
39
+ ## Chart seam and cache
40
+
41
+ `MetricsChart` adds these optional props without changing existing callers:
42
+
43
+ ```ts
44
+ loadSeries?: MetricsSeriesLoader;
45
+ seriesCacheKey?: string;
46
+ childKind?: string;
47
+ breakdown?: boolean;
48
+ preserveSeriesLabels?: boolean;
49
+ ```
50
+
51
+ The default loader remains `mojoMetrics` and repairs a tail-only response key when the configured full-slug set makes that mapping unique; ambiguous duplicate tails still require the exact loader. A custom loader must supply a stable namespace through `seriesCacheKey`; the namespace is part of the TanStack key so exact explorer data cannot reuse a cached lossy default response. The explorer namespace and every discovery/KPI/scalar key use the synchronous auth-token uid. Protected reads stay disabled until the async `me` identity agrees with that uid, preventing boot or direct identity switches from caching authenticated data under a shared placeholder.
52
+
53
+ ## Fan-out, KPI, scalar, and export
54
+
55
+ Fan-out appears only for a parsed group account. Sum supports multiple selected slugs through the collision-safe adapter. Breakdown limits selection to one slug and requires an explicit child kind. KPI tiles issue one `/series?with_delta=true` request at an explicit `when` and granularity.
56
+
57
+ The scalar card reads a known exact slug and opens the standard KISS native-dialog detail. Its optional scale changes presentation only; raw values remain visible. There is no gauge catalog or fabricated health classification.
58
+
59
+ Chart CSV export flows through shared `csvEscape()`. String cells beginning with `=`, `+`, `-`, `@`, tab, or carriage return gain a leading apostrophe before normal RFC quoting. Numeric negatives remain numeric.
60
+
61
+ ## Styling
62
+
63
+ The explorer extends the semantic `admin-monitoring.css` token stylesheet used by the Portal and showcase. It adds no UI or chart dependency. Consumers already including the Monitoring section stylesheet need no additional CSS entry.
@@ -0,0 +1,99 @@
1
+ # Admin monitoring
2
+
3
+ `portal-mojo/admin` packages the immutable Logs feed, one-record log inspector,
4
+ read-only Metrics Explorer, and metrics-permission administration for standalone
5
+ or embedded admin portals. See [admin-metrics-explorer.md](admin-metrics-explorer.md)
6
+ for the discovery, identity, KPI, fan-out, scalar, and cache contracts.
7
+
8
+ ## Admin registration and gates
9
+
10
+ `MONITORING_ADMIN_SECTION` contributes three root-relative routes:
11
+
12
+ | Route | Component | Any-of gate |
13
+ |---|---|---|
14
+ | `/logs` | `LogsPage` | `sys.manage_logs`, `sys.view_logs`, `sys.security` |
15
+ | `/metrics/explorer` | `MetricsExplorerPage` | `sys.view_metrics`, `sys.metrics` |
16
+ | `/metrics/permissions` | `MetricsPermissionsPage` | `sys.manage_incidents`, `sys.metrics`, `sys.manage_metrics` |
17
+
18
+ The section clause is the union of these route audiences, while each route
19
+ retains its exact clause. In particular, `sys.view_metrics` reveals only the
20
+ explorer, `sys.metrics` reveals explorer and editor, and `sys.manage_metrics`
21
+ reveals only the editor. The `sys.` prefix is intentional: these are global operator surfaces and must
22
+ not inherit a similarly named active-group permission. `adminSectionRoutes()`
23
+ wraps each component before it mounts, so a denied direct route cannot fetch.
24
+ The backend remains authoritative.
25
+
26
+ ```tsx
27
+ import {
28
+ MONITORING_ADMIN_SECTION,
29
+ adminSectionRoutes,
30
+ adminSectionsMenu,
31
+ } from 'portal-mojo/admin';
32
+
33
+ const sections = [MONITORING_ADMIN_SECTION];
34
+ const routes = adminSectionRoutes(sections, { mount: '/system' });
35
+ const menu = adminSectionsMenu(sections, { mount: '/system' });
36
+ ```
37
+
38
+ ## Logs and inspector
39
+
40
+ ```tsx
41
+ import { LogsPage, LogInspector, LogModel, type LogRow } from 'portal-mojo/admin';
42
+
43
+ <LogInspector log={row} />
44
+ ```
45
+
46
+ `LogsPage` is the canonical `/api/logs` table: server search/filter/sort,
47
+ day grouping, column persistence, export, quick-look chevron, and a full-size
48
+ row-click inspector. The table is read-only because log rows are immutable
49
+ records. The chevron cell stops propagation in `ModelTable`, so expanding a
50
+ quick look does not also open the inspector.
51
+
52
+ `LogModel` therefore publishes only its exact view gate. Although the backend
53
+ has separate `security|admin` save and `admin` delete gates, this immutable
54
+ package surface advertises no `manage` contract or mutation control. The
55
+ client's normal admin/superuser wildcard remains separate from `sys.security`.
56
+
57
+ The inspector recognizes explicit request and response `kind` tokens. All
58
+ other kinds are messages. The `log` field is the primary stored content and is
59
+ labelled “Stored request content,” “Stored response content,” or “Message” from
60
+ that kind. `payload` is always labelled “Auxiliary payload”; it is never
61
+ presented as the response body. The inspector also renders request context,
62
+ user, device, IP, related model, and user agent. Valid JSON goes through
63
+ `JsonBlock`; everything else is a React text child in a `<pre>`. HTML-looking
64
+ stored data is never an HTML rendering boundary. Clipboard absence and rejected
65
+ writes surface an error toast instead of reporting false success.
66
+
67
+ A response row is only a stored response row. `/api/logs` exposes no request
68
+ correlation key, so the inspector never searches for or claims a paired request.
69
+
70
+ ## Metrics permission wire
71
+
72
+ The endpoint is Redis-backed and intentionally not modeled as a paged
73
+ `ModelTable`:
74
+
75
+ - `GET /api/metrics/permissions` returns a normal `{data, count}` envelope.
76
+ The complete set is normalized and sorted by account in the client because
77
+ Redis ordering is nondeterministic.
78
+ - A permission value may be a single string, an array, or `null`; all normalize
79
+ to `string[]` for the controlled `TagInput` fields.
80
+ - `POST /api/metrics/permissions/<encoded-account>` sends
81
+ `view_permissions` and `write_permissions` as CSV strings.
82
+ - The POST result is asymmetric: `account`, `view_permissions`, and
83
+ `write_permissions` are top-level envelope fields, not nested under `data`.
84
+ - `DELETE /api/metrics/permissions/<encoded-account>` clears both permission
85
+ keys. It does not delete the metrics account registry entry, so the table
86
+ refetches authoritatively and retains the row with empty tags.
87
+
88
+ Accounts are immutable in this surface. There is no fake add, search, paging,
89
+ or client table framework. Every save and clear refetches the authoritative
90
+ list. Empty tags are submitted as empty CSV strings, matching the backend's
91
+ current contract.
92
+
93
+ ## Styling and showcase
94
+
95
+ Monitoring components use semantic `monitoring-*` classes and application
96
+ tokens only. A consuming app must include `admin-monitoring.css`. This repo's
97
+ portal and showcase theme entries do so. The showcase's Admin Monitoring demo
98
+ contains static request, response, JSON, and HTML-looking plain-text cases for
99
+ both-theme verification without mutating a backend.