@fuzdev/fuz_app 0.30.0 → 0.32.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 (222) hide show
  1. package/dist/actions/CLAUDE.md +630 -0
  2. package/dist/actions/action_rpc.d.ts +29 -0
  3. package/dist/actions/action_rpc.d.ts.map +1 -1
  4. package/dist/actions/action_rpc.js +42 -6
  5. package/dist/actions/action_types.d.ts +2 -2
  6. package/dist/actions/cancel.d.ts +12 -13
  7. package/dist/actions/cancel.d.ts.map +1 -1
  8. package/dist/actions/cancel.js +10 -13
  9. package/dist/actions/heartbeat.d.ts +8 -13
  10. package/dist/actions/heartbeat.d.ts.map +1 -1
  11. package/dist/actions/heartbeat.js +5 -8
  12. package/dist/actions/register_action_ws.d.ts +3 -3
  13. package/dist/actions/register_action_ws.js +2 -2
  14. package/dist/actions/register_ws_endpoint.d.ts +4 -4
  15. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  16. package/dist/actions/register_ws_endpoint.js +3 -3
  17. package/dist/actions/rpc_client.d.ts +29 -0
  18. package/dist/actions/rpc_client.d.ts.map +1 -1
  19. package/dist/actions/rpc_client.js +31 -0
  20. package/dist/actions/socket.svelte.d.ts +16 -16
  21. package/dist/actions/socket.svelte.d.ts.map +1 -1
  22. package/dist/actions/socket.svelte.js +15 -15
  23. package/dist/actions/transports_ws_auth_guard.d.ts.map +1 -1
  24. package/dist/auth/CLAUDE.md +945 -0
  25. package/dist/auth/account_action_specs.d.ts +216 -0
  26. package/dist/auth/account_action_specs.d.ts.map +1 -0
  27. package/dist/auth/account_action_specs.js +159 -0
  28. package/dist/auth/account_actions.d.ts +51 -0
  29. package/dist/auth/account_actions.d.ts.map +1 -0
  30. package/dist/auth/account_actions.js +119 -0
  31. package/dist/auth/account_queries.d.ts +6 -2
  32. package/dist/auth/account_queries.d.ts.map +1 -1
  33. package/dist/auth/account_queries.js +40 -4
  34. package/dist/auth/account_routes.d.ts +94 -16
  35. package/dist/auth/account_routes.d.ts.map +1 -1
  36. package/dist/auth/account_routes.js +108 -180
  37. package/dist/auth/account_schema.d.ts +85 -30
  38. package/dist/auth/account_schema.d.ts.map +1 -1
  39. package/dist/auth/account_schema.js +40 -8
  40. package/dist/auth/admin_action_specs.d.ts +674 -0
  41. package/dist/auth/admin_action_specs.d.ts.map +1 -0
  42. package/dist/auth/admin_action_specs.js +287 -0
  43. package/dist/auth/admin_actions.d.ts +69 -0
  44. package/dist/auth/admin_actions.d.ts.map +1 -0
  45. package/dist/auth/admin_actions.js +256 -0
  46. package/dist/auth/admin_rpc_actions.d.ts +49 -0
  47. package/dist/auth/admin_rpc_actions.d.ts.map +1 -0
  48. package/dist/auth/admin_rpc_actions.js +32 -0
  49. package/dist/auth/api_token.d.ts +10 -0
  50. package/dist/auth/api_token.d.ts.map +1 -1
  51. package/dist/auth/api_token.js +9 -0
  52. package/dist/auth/api_token_queries.d.ts +3 -3
  53. package/dist/auth/api_token_queries.js +3 -3
  54. package/dist/auth/app_settings_schema.d.ts +4 -3
  55. package/dist/auth/app_settings_schema.d.ts.map +1 -1
  56. package/dist/auth/app_settings_schema.js +2 -1
  57. package/dist/auth/audit_log_routes.d.ts +14 -6
  58. package/dist/auth/audit_log_routes.d.ts.map +1 -1
  59. package/dist/auth/audit_log_routes.js +22 -79
  60. package/dist/auth/audit_log_schema.d.ts +100 -29
  61. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  62. package/dist/auth/audit_log_schema.js +83 -11
  63. package/dist/auth/bootstrap_routes.d.ts +14 -0
  64. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  65. package/dist/auth/bootstrap_routes.js +10 -3
  66. package/dist/auth/cleanup.d.ts +63 -0
  67. package/dist/auth/cleanup.d.ts.map +1 -0
  68. package/dist/auth/cleanup.js +80 -0
  69. package/dist/auth/invite_schema.d.ts +11 -10
  70. package/dist/auth/invite_schema.d.ts.map +1 -1
  71. package/dist/auth/invite_schema.js +4 -3
  72. package/dist/auth/migrations.d.ts +6 -0
  73. package/dist/auth/migrations.d.ts.map +1 -1
  74. package/dist/auth/migrations.js +28 -0
  75. package/dist/auth/permit_offer_action_specs.d.ts +364 -0
  76. package/dist/auth/permit_offer_action_specs.d.ts.map +1 -0
  77. package/dist/auth/permit_offer_action_specs.js +216 -0
  78. package/dist/auth/permit_offer_actions.d.ts +96 -0
  79. package/dist/auth/permit_offer_actions.d.ts.map +1 -0
  80. package/dist/auth/permit_offer_actions.js +428 -0
  81. package/dist/auth/permit_offer_notifications.d.ts +361 -0
  82. package/dist/auth/permit_offer_notifications.d.ts.map +1 -0
  83. package/dist/auth/permit_offer_notifications.js +179 -0
  84. package/dist/auth/permit_offer_queries.d.ts +165 -0
  85. package/dist/auth/permit_offer_queries.d.ts.map +1 -0
  86. package/dist/auth/permit_offer_queries.js +390 -0
  87. package/dist/auth/permit_offer_schema.d.ts +103 -0
  88. package/dist/auth/permit_offer_schema.d.ts.map +1 -0
  89. package/dist/auth/permit_offer_schema.js +142 -0
  90. package/dist/auth/permit_queries.d.ts +77 -14
  91. package/dist/auth/permit_queries.d.ts.map +1 -1
  92. package/dist/auth/permit_queries.js +119 -24
  93. package/dist/auth/session_queries.d.ts +4 -2
  94. package/dist/auth/session_queries.d.ts.map +1 -1
  95. package/dist/auth/session_queries.js +4 -2
  96. package/dist/auth/signup_routes.d.ts +13 -0
  97. package/dist/auth/signup_routes.d.ts.map +1 -1
  98. package/dist/auth/signup_routes.js +14 -7
  99. package/dist/http/CLAUDE.md +584 -0
  100. package/dist/http/pending_effects.d.ts +29 -0
  101. package/dist/http/pending_effects.d.ts.map +1 -0
  102. package/dist/http/pending_effects.js +31 -0
  103. package/dist/http/route_spec.d.ts.map +1 -1
  104. package/dist/http/route_spec.js +4 -3
  105. package/dist/rate_limiter.d.ts +30 -0
  106. package/dist/rate_limiter.d.ts.map +1 -1
  107. package/dist/rate_limiter.js +25 -2
  108. package/dist/realtime/sse_auth_guard.d.ts +2 -0
  109. package/dist/realtime/sse_auth_guard.d.ts.map +1 -1
  110. package/dist/realtime/sse_auth_guard.js +5 -3
  111. package/dist/server/app_server.d.ts +13 -2
  112. package/dist/server/app_server.d.ts.map +1 -1
  113. package/dist/server/app_server.js +12 -1
  114. package/dist/testing/CLAUDE.md +668 -1
  115. package/dist/testing/admin_integration.d.ts +10 -7
  116. package/dist/testing/admin_integration.d.ts.map +1 -1
  117. package/dist/testing/admin_integration.js +382 -482
  118. package/dist/testing/app_server.d.ts +7 -6
  119. package/dist/testing/app_server.d.ts.map +1 -1
  120. package/dist/testing/attack_surface.d.ts +9 -3
  121. package/dist/testing/attack_surface.d.ts.map +1 -1
  122. package/dist/testing/attack_surface.js +4 -4
  123. package/dist/testing/audit_completeness.d.ts +11 -0
  124. package/dist/testing/audit_completeness.d.ts.map +1 -1
  125. package/dist/testing/audit_completeness.js +169 -134
  126. package/dist/testing/auth_apps.d.ts.map +1 -1
  127. package/dist/testing/auth_apps.js +4 -33
  128. package/dist/testing/db.d.ts +1 -1
  129. package/dist/testing/db.d.ts.map +1 -1
  130. package/dist/testing/db.js +2 -0
  131. package/dist/testing/entities.d.ts +35 -13
  132. package/dist/testing/entities.d.ts.map +1 -1
  133. package/dist/testing/entities.js +17 -0
  134. package/dist/testing/integration.d.ts +10 -0
  135. package/dist/testing/integration.d.ts.map +1 -1
  136. package/dist/testing/integration.js +352 -340
  137. package/dist/testing/integration_helpers.d.ts +16 -5
  138. package/dist/testing/integration_helpers.d.ts.map +1 -1
  139. package/dist/testing/integration_helpers.js +24 -4
  140. package/dist/testing/rate_limiting.d.ts +7 -0
  141. package/dist/testing/rate_limiting.d.ts.map +1 -1
  142. package/dist/testing/rate_limiting.js +41 -10
  143. package/dist/testing/rpc_helpers.d.ts +153 -1
  144. package/dist/testing/rpc_helpers.d.ts.map +1 -1
  145. package/dist/testing/rpc_helpers.js +184 -8
  146. package/dist/testing/sse_round_trip.d.ts +8 -0
  147. package/dist/testing/sse_round_trip.d.ts.map +1 -1
  148. package/dist/testing/sse_round_trip.js +10 -3
  149. package/dist/testing/standard.d.ts +9 -1
  150. package/dist/testing/standard.d.ts.map +1 -1
  151. package/dist/testing/standard.js +6 -2
  152. package/dist/testing/stubs.d.ts +10 -2
  153. package/dist/testing/stubs.d.ts.map +1 -1
  154. package/dist/testing/stubs.js +17 -2
  155. package/dist/testing/surface_invariants.d.ts +7 -3
  156. package/dist/testing/surface_invariants.d.ts.map +1 -1
  157. package/dist/testing/surface_invariants.js +5 -4
  158. package/dist/testing/ws_round_trip.d.ts.map +1 -1
  159. package/dist/testing/ws_round_trip.js +9 -38
  160. package/dist/ui/AccountSessions.svelte +8 -4
  161. package/dist/ui/AccountSessions.svelte.d.ts.map +1 -1
  162. package/dist/ui/AdminAccounts.svelte +61 -33
  163. package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
  164. package/dist/ui/AdminAuditLog.svelte +3 -2
  165. package/dist/ui/AdminAuditLog.svelte.d.ts.map +1 -1
  166. package/dist/ui/AdminInvites.svelte +3 -2
  167. package/dist/ui/AdminInvites.svelte.d.ts.map +1 -1
  168. package/dist/ui/AdminOverview.svelte +14 -9
  169. package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
  170. package/dist/ui/AdminPermitHistory.svelte +3 -2
  171. package/dist/ui/AdminPermitHistory.svelte.d.ts.map +1 -1
  172. package/dist/ui/AdminSessions.svelte +29 -25
  173. package/dist/ui/AdminSessions.svelte.d.ts.map +1 -1
  174. package/dist/ui/CLAUDE.md +363 -0
  175. package/dist/ui/OpenSignupToggle.svelte +6 -3
  176. package/dist/ui/OpenSignupToggle.svelte.d.ts.map +1 -1
  177. package/dist/ui/PermitOfferForm.svelte +141 -0
  178. package/dist/ui/PermitOfferForm.svelte.d.ts +14 -0
  179. package/dist/ui/PermitOfferForm.svelte.d.ts.map +1 -0
  180. package/dist/ui/PermitOfferHistory.svelte +109 -0
  181. package/dist/ui/PermitOfferHistory.svelte.d.ts +11 -0
  182. package/dist/ui/PermitOfferHistory.svelte.d.ts.map +1 -0
  183. package/dist/ui/PermitOfferInbox.svelte +121 -0
  184. package/dist/ui/PermitOfferInbox.svelte.d.ts +12 -0
  185. package/dist/ui/PermitOfferInbox.svelte.d.ts.map +1 -0
  186. package/dist/ui/account_sessions_state.svelte.d.ts +53 -3
  187. package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
  188. package/dist/ui/account_sessions_state.svelte.js +39 -16
  189. package/dist/ui/admin_accounts_state.svelte.d.ts +118 -2
  190. package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
  191. package/dist/ui/admin_accounts_state.svelte.js +99 -23
  192. package/dist/ui/admin_invites_state.svelte.d.ts +47 -1
  193. package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -1
  194. package/dist/ui/admin_invites_state.svelte.js +38 -26
  195. package/dist/ui/admin_rpc_adapters.d.ts +94 -0
  196. package/dist/ui/admin_rpc_adapters.d.ts.map +1 -0
  197. package/dist/ui/admin_rpc_adapters.js +100 -0
  198. package/dist/ui/admin_sessions_state.svelte.d.ts +26 -0
  199. package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -1
  200. package/dist/ui/admin_sessions_state.svelte.js +35 -21
  201. package/dist/ui/app_settings_state.svelte.d.ts +39 -0
  202. package/dist/ui/app_settings_state.svelte.d.ts.map +1 -1
  203. package/dist/ui/app_settings_state.svelte.js +34 -18
  204. package/dist/ui/audit_log_state.svelte.d.ts +40 -3
  205. package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
  206. package/dist/ui/audit_log_state.svelte.js +36 -42
  207. package/dist/ui/auth_state.svelte.d.ts +4 -3
  208. package/dist/ui/auth_state.svelte.d.ts.map +1 -1
  209. package/dist/ui/auth_state.svelte.js +4 -1
  210. package/dist/ui/permit_offers_state.svelte.d.ts +125 -0
  211. package/dist/ui/permit_offers_state.svelte.d.ts.map +1 -0
  212. package/dist/ui/permit_offers_state.svelte.js +197 -0
  213. package/package.json +3 -3
  214. package/dist/auth/admin_routes.d.ts +0 -29
  215. package/dist/auth/admin_routes.d.ts.map +0 -1
  216. package/dist/auth/admin_routes.js +0 -226
  217. package/dist/auth/app_settings_routes.d.ts +0 -27
  218. package/dist/auth/app_settings_routes.d.ts.map +0 -1
  219. package/dist/auth/app_settings_routes.js +0 -66
  220. package/dist/auth/invite_routes.d.ts +0 -18
  221. package/dist/auth/invite_routes.d.ts.map +0 -1
  222. package/dist/auth/invite_routes.js +0 -129
@@ -0,0 +1,109 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Both-directions permit offer history table.
4
+ *
5
+ * Shows every offer involving the current account — recipient or grantor
6
+ * — including terminal rows (accepted, declined, retracted, superseded,
7
+ * expired). Backed by `permit_offer_history` (new RPC action); seeded
8
+ * via `PermitOffersState.fetch_history()`.
9
+ *
10
+ * Consumers plug in optional `format_actor` / `format_scope` callbacks
11
+ * for display names.
12
+ */
13
+
14
+ import {permit_offers_state_context} from './permit_offers_state.svelte.js';
15
+ import Datatable from './Datatable.svelte';
16
+ import type {DatatableColumn} from './datatable.js';
17
+ import {format_relative_time, format_datetime_local, truncate_uuid} from './ui_format.js';
18
+ import type {PermitOfferJson} from '../auth/permit_offer_schema.js';
19
+
20
+ const {
21
+ current_actor_id,
22
+ format_actor = truncate_uuid,
23
+ format_scope,
24
+ format_role = (role: string) => role,
25
+ }: {
26
+ /** Used to label a row as sent vs received. When `null`, direction shows as `-`. */
27
+ current_actor_id: string | null;
28
+ format_actor?: (from_actor_id: string) => string;
29
+ format_scope?: (scope_id: string | null, role: string) => string;
30
+ format_role?: (role: string) => string;
31
+ } = $props();
32
+
33
+ const permit_offers = permit_offers_state_context.get();
34
+
35
+ const now = $state.raw(Date.now());
36
+
37
+ const status_of = (offer: PermitOfferJson): string => {
38
+ if (offer.accepted_at) return 'accepted';
39
+ if (offer.declined_at) return 'declined';
40
+ if (offer.retracted_at) return 'retracted';
41
+ if (offer.superseded_at) return 'superseded';
42
+ if (Date.parse(offer.expires_at) <= now) return 'expired';
43
+ return 'pending';
44
+ };
45
+
46
+ const status_chip_class = (status: string): string => {
47
+ switch (status) {
48
+ case 'accepted':
49
+ return 'chip color_b';
50
+ case 'pending':
51
+ return 'chip color_a';
52
+ case 'declined':
53
+ case 'retracted':
54
+ case 'superseded':
55
+ case 'expired':
56
+ return 'chip color_c';
57
+ default:
58
+ return 'chip';
59
+ }
60
+ };
61
+
62
+ const scope_label = (scope_id: string | null, role: string): string => {
63
+ if (format_scope) return format_scope(scope_id, role);
64
+ return scope_id === null ? 'global' : truncate_uuid(scope_id);
65
+ };
66
+
67
+ const columns: Array<DatatableColumn<PermitOfferJson>> = [
68
+ {key: 'from_actor_id', label: 'direction', width: 110},
69
+ {key: 'role', label: 'role', width: 140},
70
+ {key: 'scope_id', label: 'scope', width: 160},
71
+ {key: 'created_at', label: 'status', width: 120},
72
+ {key: 'expires_at', label: 'time', width: 110},
73
+ ];
74
+ </script>
75
+
76
+ <section>
77
+ <h2>offer history</h2>
78
+
79
+ {#if permit_offers.loading}
80
+ <p class="text_50">loading history...</p>
81
+ {:else if permit_offers.error}
82
+ <p class="color_c_50">{permit_offers.error}</p>
83
+ {:else}
84
+ <Datatable {columns} rows={permit_offers.history} height="400px" row_key="id">
85
+ {#snippet cell(column, row)}
86
+ {#if column.key === 'from_actor_id'}
87
+ {#if current_actor_id && row.from_actor_id === current_actor_id}
88
+ <span class="chip">sent</span>
89
+ <span class="text_50 font_size_sm">to {truncate_uuid(row.to_account_id)}</span>
90
+ {:else}
91
+ <span class="chip">received</span>
92
+ <span class="text_50 font_size_sm">from {format_actor(row.from_actor_id)}</span>
93
+ {/if}
94
+ {:else if column.key === 'role'}
95
+ {format_role(row.role)}
96
+ {:else if column.key === 'scope_id'}
97
+ <span class="text_50">{scope_label(row.scope_id, row.role)}</span>
98
+ {:else if column.key === 'created_at'}
99
+ {@const status = status_of(row)}
100
+ <span class={status_chip_class(status)}>{status}</span>
101
+ {:else if column.key === 'expires_at'}
102
+ <span title={format_datetime_local(row.created_at)}>
103
+ {format_relative_time(row.created_at)}
104
+ </span>
105
+ {/if}
106
+ {/snippet}
107
+ </Datatable>
108
+ {/if}
109
+ </section>
@@ -0,0 +1,11 @@
1
+ type $$ComponentProps = {
2
+ /** Used to label a row as sent vs received. When `null`, direction shows as `-`. */
3
+ current_actor_id: string | null;
4
+ format_actor?: (from_actor_id: string) => string;
5
+ format_scope?: (scope_id: string | null, role: string) => string;
6
+ format_role?: (role: string) => string;
7
+ };
8
+ declare const PermitOfferHistory: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type PermitOfferHistory = ReturnType<typeof PermitOfferHistory>;
10
+ export default PermitOfferHistory;
11
+ //# sourceMappingURL=PermitOfferHistory.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PermitOfferHistory.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/PermitOfferHistory.svelte"],"names":[],"mappings":"AAoBC,KAAK,gBAAgB,GAAI;IACxB,oFAAoF;IACpF,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,YAAY,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;IACjD,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACjE,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC,CAAC;AAiGH,QAAA,MAAM,kBAAkB,sDAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,121 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Recipient-side pending offer inbox.
4
+ *
5
+ * Renders `PermitOffersState.incoming` (pending, soonest-expiry first)
6
+ * with accept + decline-with-reason controls. Grantor and scope rendering
7
+ * are delegated via optional callback props — consumers plug in display
8
+ * names once they know what a `from_actor_id` / `scope_id` represents
9
+ * in their domain (usernames, classroom names, etc.).
10
+ */
11
+
12
+ import PendingButton from '@fuzdev/fuz_ui/PendingButton.svelte';
13
+ import {SvelteMap} from 'svelte/reactivity';
14
+
15
+ import {permit_offers_state_context} from './permit_offers_state.svelte.js';
16
+ import ConfirmButton from './ConfirmButton.svelte';
17
+ import {format_relative_time, format_datetime_local, truncate_uuid} from './ui_format.js';
18
+ import {PERMIT_OFFER_MESSAGE_LENGTH_MAX} from '../auth/permit_offer_schema.js';
19
+
20
+ const {
21
+ format_actor = truncate_uuid,
22
+ format_scope,
23
+ format_role = (role: string) => role,
24
+ }: {
25
+ /** Display label for `from_actor_id`. Defaults to a truncated uuid. */
26
+ format_actor?: (from_actor_id: string) => string;
27
+ /** Display label for an offer's scope. Defaults to truncated uuid or "global" when `null`. */
28
+ format_scope?: (scope_id: string | null, role: string) => string;
29
+ /** Display label for a role constant. Defaults to identity (role name as stored). */
30
+ format_role?: (role: string) => string;
31
+ } = $props();
32
+
33
+ const permit_offers = permit_offers_state_context.get();
34
+
35
+ const scope_label = (scope_id: string | null, role: string): string => {
36
+ if (format_scope) return format_scope(scope_id, role);
37
+ return scope_id === null ? 'global' : truncate_uuid(scope_id);
38
+ };
39
+
40
+ const decline_reasons: SvelteMap<string, string> = new SvelteMap();
41
+ </script>
42
+
43
+ <section class="permit-offer-inbox">
44
+ <h2>pending offers</h2>
45
+
46
+ {#if permit_offers.error}
47
+ <p class="color_c_50">{permit_offers.error}</p>
48
+ {/if}
49
+
50
+ {#if permit_offers.incoming.length === 0}
51
+ <p class="text_50">No pending offers.</p>
52
+ {:else}
53
+ <ul class="column gap_md">
54
+ {#each permit_offers.incoming as offer (offer.id)}
55
+ <li class="box p_md column gap_sm">
56
+ <div class="row gap_sm align_center">
57
+ <span class="chip color_a">{format_role(offer.role)}</span>
58
+ <span class="text_50 font_size_sm">{scope_label(offer.scope_id, offer.role)}</span>
59
+ <span class="text_50 font_size_sm">from {format_actor(offer.from_actor_id)}</span>
60
+ <span
61
+ class="text_50 font_size_sm ml_auto"
62
+ title={format_datetime_local(offer.expires_at)}
63
+ >
64
+ expires {format_relative_time(offer.expires_at)}
65
+ </span>
66
+ </div>
67
+
68
+ {#if offer.message}
69
+ <p class="mb_0">{offer.message}</p>
70
+ {/if}
71
+
72
+ <div class="row gap_sm">
73
+ <PendingButton
74
+ pending={permit_offers.loading}
75
+ disabled={permit_offers.loading}
76
+ onclick={() => permit_offers.accept(offer.id)}
77
+ class="color_b"
78
+ >
79
+ accept
80
+ </PendingButton>
81
+
82
+ <ConfirmButton
83
+ title="decline offer"
84
+ position="bottom"
85
+ onconfirm={() => {
86
+ const reason = decline_reasons.get(offer.id) ?? '';
87
+ void permit_offers.decline(offer.id, reason || null);
88
+ decline_reasons.delete(offer.id);
89
+ }}
90
+ >
91
+ {#snippet children(_popover, _confirm)}
92
+ decline
93
+ {/snippet}
94
+ {#snippet popover_content(popover, confirm)}
95
+ <div class="column gap_sm p_sm">
96
+ <label>
97
+ <div class="title">reason (optional)</div>
98
+ <textarea
99
+ name="decline-reason"
100
+ maxlength={PERMIT_OFFER_MESSAGE_LENGTH_MAX}
101
+ placeholder="optional reason"
102
+ value={decline_reasons.get(offer.id) ?? ''}
103
+ oninput={(e) =>
104
+ decline_reasons.set(offer.id, (e.target as HTMLTextAreaElement).value)}
105
+ ></textarea>
106
+ </label>
107
+ <div class="row gap_sm">
108
+ <button type="button" class="color_c bg_100" onclick={confirm}>
109
+ confirm decline
110
+ </button>
111
+ <button type="button" onclick={() => popover.hide()}>cancel</button>
112
+ </div>
113
+ </div>
114
+ {/snippet}
115
+ </ConfirmButton>
116
+ </div>
117
+ </li>
118
+ {/each}
119
+ </ul>
120
+ {/if}
121
+ </section>
@@ -0,0 +1,12 @@
1
+ type $$ComponentProps = {
2
+ /** Display label for `from_actor_id`. Defaults to a truncated uuid. */
3
+ format_actor?: (from_actor_id: string) => string;
4
+ /** Display label for an offer's scope. Defaults to truncated uuid or "global" when `null`. */
5
+ format_scope?: (scope_id: string | null, role: string) => string;
6
+ /** Display label for a role constant. Defaults to identity (role name as stored). */
7
+ format_role?: (role: string) => string;
8
+ };
9
+ declare const PermitOfferInbox: import("svelte").Component<$$ComponentProps, {}, "">;
10
+ type PermitOfferInbox = ReturnType<typeof PermitOfferInbox>;
11
+ export default PermitOfferInbox;
12
+ //# sourceMappingURL=PermitOfferInbox.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PermitOfferInbox.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/PermitOfferInbox.svelte"],"names":[],"mappings":"AAoBC,KAAK,gBAAgB,GAAI;IACxB,uEAAuE;IACvE,YAAY,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,CAAC;IACjD,8FAA8F;IAC9F,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACjE,qFAAqF;IACrF,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC,CAAC;AA0FH,QAAA,MAAM,gBAAgB,sDAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
@@ -1,13 +1,63 @@
1
1
  /**
2
- * Reactive state for managing auth sessions on a settings page.
2
+ * Reactive state for managing the authenticated account's auth sessions on a
3
+ * settings page. Reads and mutations flow through a narrow RPC adapter; the
4
+ * REST routes that backed this class moved to `account_actions.ts` in the
5
+ * 2026-04-23 RPC migration.
3
6
  *
4
7
  * @module
5
8
  */
6
9
  import { Loadable } from './loadable.svelte.js';
7
- import type { AuthSession } from '../auth/account_schema.js';
10
+ import type { AuthSessionJson } from '../auth/account_schema.js';
11
+ /**
12
+ * Narrow RPC surface consumed by `AccountSessionsState`. Consumers adapt their
13
+ * typed RPC client to this shape. Mirrors the other per-domain `*Rpc`
14
+ * interfaces (`AdminAccountsRpc`, `AuditLogRpc`, `AdminInvitesRpc`).
15
+ *
16
+ * The three methods wrap the corresponding action specs on
17
+ * `account_actions.ts`:
18
+ *
19
+ * - `list` → `account_session_list`
20
+ * - `revoke` → `account_session_revoke` (IDOR-guarded by `account_id` server-side)
21
+ * - `revoke_all` → `account_session_revoke_all`
22
+ */
23
+ export interface AccountSessionsRpc {
24
+ list: () => Promise<{
25
+ sessions: Array<AuthSessionJson>;
26
+ }>;
27
+ revoke: (params: {
28
+ session_id: string;
29
+ }) => Promise<{
30
+ ok: true;
31
+ revoked: boolean;
32
+ }>;
33
+ revoke_all: () => Promise<{
34
+ ok: true;
35
+ count: number;
36
+ }>;
37
+ }
38
+ /**
39
+ * Svelte context carrying the reactive `AccountSessionsRpc` accessor. Mirrors
40
+ * the admin-side RPC contexts. Unset context falls back to `() => null` so
41
+ * components render the usual "rpc adapter not wired" state.
42
+ */
43
+ export declare const account_sessions_rpc_context: {
44
+ get: () => () => AccountSessionsRpc | null;
45
+ set: (value?: (() => AccountSessionsRpc | null) | undefined) => () => AccountSessionsRpc | null;
46
+ };
47
+ export interface AccountSessionsStateOptions {
48
+ /**
49
+ * Reactive accessor for the RPC adapter; returns `null` when unwired.
50
+ * Matches the `get_rpc` pattern on the admin state classes.
51
+ */
52
+ get_rpc?: () => AccountSessionsRpc | null;
53
+ }
8
54
  export declare class AccountSessionsState extends Loadable {
9
- sessions: Array<AuthSession>;
55
+ #private;
56
+ sessions: Array<AuthSessionJson>;
10
57
  readonly active_count: number;
58
+ constructor(options?: AccountSessionsStateOptions);
59
+ /** True when an RPC adapter is wired. `fetch` / `revoke` / `revoke_all` no-op without it. */
60
+ get has_rpc(): boolean;
11
61
  fetch(): Promise<void>;
12
62
  revoke(id: string): Promise<void>;
13
63
  revoke_all(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"account_sessions_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/account_sessions_state.svelte.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAE9C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,2BAA2B,CAAC;AAE3D,qBAAa,oBAAqB,SAAQ,QAAQ;IACjD,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,CAAkB;IAE9C,QAAQ,CAAC,YAAY,SAAkC;IAEjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAajC"}
1
+ {"version":3,"file":"account_sessions_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/account_sessions_state.svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAC9C,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,2BAA2B,CAAC;AAE/D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,OAAO,CAAC;QAAC,QAAQ,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CAAC;IACxD,MAAM,EAAE,CAAC,MAAM,EAAE;QAAC,UAAU,EAAE,MAAM,CAAA;KAAC,KAAK,OAAO,CAAC;QAAC,EAAE,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAC,CAAC,CAAC;IAChF,UAAU,EAAE,MAAM,OAAO,CAAC;QAAC,EAAE,EAAE,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;CACrD;AAED;;;;GAIG;AACH,eAAO,MAAM,4BAA4B;qBAAwB,kBAAkB,GAAG,IAAI;yBAAzB,kBAAkB,GAAG,IAAI,wBAAzB,kBAAkB,GAAG,IAAI;CAEzF,CAAC;AAEF,MAAM,WAAW,2BAA2B;IAC3C;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,kBAAkB,GAAG,IAAI,CAAC;CAC1C;AAED,qBAAa,oBAAqB,SAAQ,QAAQ;;IAGjD,QAAQ,EAAE,KAAK,CAAC,eAAe,CAAC,CAAkB;IAElD,QAAQ,CAAC,YAAY,SAAkC;gBAE3C,OAAO,CAAC,EAAE,2BAA2B;IAKjD,6FAA6F;IAC7F,IAAI,OAAO,IAAI,OAAO,CAErB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcjC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAejC"}
@@ -1,40 +1,63 @@
1
1
  /**
2
- * Reactive state for managing auth sessions on a settings page.
2
+ * Reactive state for managing the authenticated account's auth sessions on a
3
+ * settings page. Reads and mutations flow through a narrow RPC adapter; the
4
+ * REST routes that backed this class moved to `account_actions.ts` in the
5
+ * 2026-04-23 RPC migration.
3
6
  *
4
7
  * @module
5
8
  */
9
+ import { create_context } from '@fuzdev/fuz_ui/context_helpers.js';
6
10
  import { Loadable } from './loadable.svelte.js';
7
- import { parse_response_error, ui_fetch } from './ui_fetch.js';
11
+ /**
12
+ * Svelte context carrying the reactive `AccountSessionsRpc` accessor. Mirrors
13
+ * the admin-side RPC contexts. Unset context falls back to `() => null` so
14
+ * components render the usual "rpc adapter not wired" state.
15
+ */
16
+ export const account_sessions_rpc_context = create_context(() => () => null);
8
17
  export class AccountSessionsState extends Loadable {
18
+ #get_rpc;
9
19
  sessions = $state.raw([]);
10
20
  active_count = $derived(this.sessions.length);
21
+ constructor(options) {
22
+ super();
23
+ this.#get_rpc = options?.get_rpc ?? (() => null);
24
+ }
25
+ /** True when an RPC adapter is wired. `fetch` / `revoke` / `revoke_all` no-op without it. */
26
+ get has_rpc() {
27
+ return this.#get_rpc() !== null;
28
+ }
11
29
  async fetch() {
30
+ const rpc = this.#get_rpc();
31
+ if (!rpc) {
32
+ this.error = 'rpc adapter not wired';
33
+ return;
34
+ }
12
35
  await this.run(async () => {
13
- const response = await ui_fetch('/api/account/sessions');
14
- if (!response.ok) {
15
- throw new Error(await parse_response_error(response, 'Failed to fetch sessions'));
16
- }
17
- const data = await response.json();
18
- this.sessions = data.sessions ?? [];
36
+ const { sessions } = await rpc.list();
37
+ this.sessions = sessions;
19
38
  });
20
39
  }
21
40
  async revoke(id) {
41
+ const rpc = this.#get_rpc();
42
+ if (!rpc) {
43
+ this.error = 'rpc adapter not wired';
44
+ return;
45
+ }
22
46
  await this.run(async () => {
23
- const response = await ui_fetch(`/api/account/sessions/${id}/revoke`, { method: 'POST' });
24
- if (!response.ok) {
25
- throw new Error(await parse_response_error(response, 'Failed to revoke session'));
26
- }
47
+ await rpc.revoke({ session_id: id });
27
48
  });
28
49
  if (!this.error) {
29
50
  await this.fetch();
30
51
  }
31
52
  }
32
53
  async revoke_all() {
54
+ const rpc = this.#get_rpc();
55
+ if (!rpc) {
56
+ this.error = 'rpc adapter not wired';
57
+ return;
58
+ }
33
59
  await this.run(async () => {
34
- const response = await ui_fetch('/api/account/sessions/revoke-all', { method: 'POST' });
35
- if (!response.ok) {
36
- throw new Error(await parse_response_error(response, 'Failed to revoke sessions'));
37
- }
60
+ await rpc.revoke_all();
38
61
  });
39
62
  if (!this.error) {
40
63
  // Current session is now revoked — next API call will 401.
@@ -6,14 +6,130 @@
6
6
  import { SvelteSet } from 'svelte/reactivity';
7
7
  import { Loadable } from './loadable.svelte.js';
8
8
  import type { AdminAccountEntryJson } from '../auth/account_schema.js';
9
+ import type { AdminSessionJson } from '../auth/audit_log_schema.js';
10
+ import type { PermitOfferJson } from '../auth/permit_offer_schema.js';
11
+ /**
12
+ * Narrow RPC surface consumed by `AdminAccountsState`. Consumers adapt their
13
+ * typed RPC client (e.g. a `create_rpc_client` Proxy) to this shape — the
14
+ * state class stays decoupled from the client's `Result` return type so
15
+ * tests can inject plain-function stubs. Mirrors the `PermitOffersRpc`
16
+ * pattern.
17
+ *
18
+ * Every operation flows through RPC: the listing reuses `admin_account_list`,
19
+ * grant reuses `permit_offer_create`, revoke and retract have dedicated
20
+ * actions, and the session / token revoke-all mutations reuse
21
+ * `admin_session_revoke_all` and `admin_token_revoke_all`. Without the
22
+ * adapter the state class cannot fetch, grant, revoke, retract, or
23
+ * revoke-all sessions/tokens.
24
+ */
25
+ export interface AdminAccountsRpc {
26
+ list_accounts: () => Promise<{
27
+ accounts: Array<AdminAccountEntryJson>;
28
+ grantable_roles: Array<string>;
29
+ }>;
30
+ list_sessions: () => Promise<{
31
+ sessions: Array<AdminSessionJson>;
32
+ }>;
33
+ grant_permit: (params: {
34
+ to_account_id: string;
35
+ role: string;
36
+ }) => Promise<{
37
+ offer: PermitOfferJson;
38
+ }>;
39
+ revoke_permit: (params: {
40
+ actor_id: string;
41
+ permit_id: string;
42
+ reason?: string | null;
43
+ }) => Promise<{
44
+ ok: true;
45
+ revoked: true;
46
+ }>;
47
+ retract_offer: (offer_id: string) => Promise<{
48
+ ok: true;
49
+ }>;
50
+ session_revoke_all: (params: {
51
+ account_id: string;
52
+ }) => Promise<{
53
+ ok: true;
54
+ count: number;
55
+ }>;
56
+ token_revoke_all: (params: {
57
+ account_id: string;
58
+ }) => Promise<{
59
+ ok: true;
60
+ count: number;
61
+ }>;
62
+ }
63
+ /**
64
+ * Svelte context carrying the reactive `AdminAccountsRpc` accessor. The
65
+ * provisioner (typically the admin route shell) calls `set(() => rpc)`;
66
+ * consumers read with `const get_rpc = admin_accounts_rpc_context.get();`
67
+ * and either pass the accessor straight to `AdminAccountsState`/
68
+ * `AdminSessionsState` or wrap it with `const rpc = $derived(get_rpc());`
69
+ * for direct RPC calls. Unset context falls back to `() => null` so
70
+ * components mounted without a provisioner surface the usual "rpc adapter
71
+ * not wired" path.
72
+ */
73
+ export declare const admin_accounts_rpc_context: {
74
+ get: () => () => AdminAccountsRpc | null;
75
+ set: (value?: (() => AdminAccountsRpc | null) | undefined) => () => AdminAccountsRpc | null;
76
+ };
77
+ export interface AdminAccountsStateOptions {
78
+ /**
79
+ * Reactive accessor for the RPC adapter; returns `null` when unwired.
80
+ * Matches `PermitOffersStateOptions.account_id` / `actor_id` pattern —
81
+ * lets the component pass a `$props()`-sourced rpc without tripping
82
+ * Svelte's `state_referenced_locally` warning.
83
+ */
84
+ get_rpc?: () => AdminAccountsRpc | null;
85
+ }
9
86
  export declare class AdminAccountsState extends Loadable {
87
+ #private;
10
88
  accounts: Array<AdminAccountEntryJson>;
11
89
  grantable_roles: Array<string>;
12
90
  readonly granting_keys: SvelteSet<string>;
13
91
  readonly revoking_ids: SvelteSet<string>;
92
+ readonly retracting_ids: SvelteSet<string>;
14
93
  readonly account_count: number;
94
+ constructor(options?: AdminAccountsStateOptions);
95
+ /**
96
+ * True when an RPC adapter is wired. UI uses this to gate all controls
97
+ * — fetch, grant, revoke, retract all flow through the same adapter.
98
+ */
99
+ get has_rpc(): boolean;
15
100
  fetch(): Promise<void>;
16
- grant_permit(account_id: string, role: string): Promise<void>;
17
- revoke_permit(account_id: string, permit_id: string): Promise<void>;
101
+ /**
102
+ * Offer the role to the recipient via the `permit_offer_create` RPC.
103
+ * Server returns the pending offer; the recipient must accept before
104
+ * the permit materializes. Returns the offer payload on success so
105
+ * callers can drive follow-up UX (e.g. seed `PermitOffersState.outgoing`).
106
+ *
107
+ * A re-offer from the same admin to the same `(account, role)`
108
+ * refreshes the existing pending row — the returned offer id is stable
109
+ * across those calls.
110
+ *
111
+ * No-op when the rpc adapter is absent; `error` is set to a descriptive
112
+ * message so the UI surfaces the misconfiguration.
113
+ */
114
+ grant_permit(account_id: string, role: string): Promise<PermitOfferJson | undefined>;
115
+ /**
116
+ * Revoke an active permit via the `permit_revoke` RPC.
117
+ *
118
+ * `actor_id` is the natural key — permits are actor-scoped, and the
119
+ * admin UI reads `row.actor.id` straight from the listing, so the state
120
+ * class takes it directly rather than deriving it from `account_id`.
121
+ * The optional `reason` is stamped on `permit.revoked_reason` and
122
+ * surfaced on the revokee's WS notification.
123
+ */
124
+ revoke_permit(actor_id: string, permit_id: string, reason?: string | null): Promise<void>;
125
+ /**
126
+ * Retract a pending offer the admin issued via the `permit_offer_retract`
127
+ * RPC. The action handles auth, audit, and the
128
+ * `permit_offer_retracted` WS notification.
129
+ *
130
+ * After success, refetches the listing so `pending_offers` drops the
131
+ * row and the "+ {role}" button un-hides.
132
+ */
133
+ retract_offer(offer_id: string): Promise<void>;
18
134
  }
19
135
  //# sourceMappingURL=admin_accounts_state.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin_accounts_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/admin_accounts_state.svelte.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAE9C,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,2BAA2B,CAAC;AAErE,qBAAa,kBAAmB,SAAQ,QAAQ;IAC/C,QAAQ,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAkB;IACxD,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAkB;IAChD,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,MAAM,CAAC,CAAmB;IAC5D,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,MAAM,CAAC,CAAmB;IAE3D,QAAQ,CAAC,aAAa,SAAkC;IAElD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB7D,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAkBzE"}
1
+ {"version":3,"file":"admin_accounts_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/ui/admin_accounts_state.svelte.ts"],"names":[],"mappings":"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"}