@alliance-droid/status-feedback-system 4.0.1 → 4.0.2

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.
@@ -51,7 +51,9 @@
51
51
  let posKey = $derived(`${menuOpen}:${loading}:${pendingTarget?.status ?? ''}:${txns?.targets.length ?? 0}`);
52
52
 
53
53
  onMount(() => {
54
- if (loadOnMount && board.canManageStatus) void board.loadTransitions(item.id);
54
+ // Eagerly load in the detail view: this both readies the menu and lets the
55
+ // board confirm privilege (loadTransitions is a no-op without a token).
56
+ if (loadOnMount) void board.loadTransitions(item.id);
55
57
  });
56
58
 
57
59
  /** Teleport the menu to <body> and keep it positioned under the trigger.
@@ -59,7 +59,12 @@ export interface FeedbackBoardState {
59
59
  pastedImage?: string | null;
60
60
  }): Promise<void>;
61
61
  submitResponse(itemId: string, message: string, pastedImage?: string | null): Promise<void>;
62
- /** Whether a token provider was configured (status controls may be available). */
62
+ /**
63
+ * Whether the current user may manage status — resolved against the backend
64
+ * (valid token AND a qualifying role + project access), not merely whether a
65
+ * token getter was provided. Starts `false` and flips `true` once confirmed,
66
+ * so UI can gate the status control by actual privilege.
67
+ */
63
68
  readonly canManageStatus: boolean;
64
69
  /** Cached allowed transitions per item id, populated by loadTransitions. */
65
70
  readonly transitions: Record<string, BoardTransitions>;
@@ -26,6 +26,9 @@ export function createFeedbackBoard(options) {
26
26
  let voteErrors = $state({});
27
27
  let loadMoreError = $state('');
28
28
  let transitions = $state({});
29
+ // Resolved status-management privilege (one-time backend probe, not token presence).
30
+ let statusPrivilege = $state(false);
31
+ let privilegeProbed = false;
29
32
  // Response cache
30
33
  const responseCache = {};
31
34
  // Track in-flight votes to prevent duplicate requests. A plain Set is correct
@@ -46,6 +49,7 @@ export function createFeedbackBoard(options) {
46
49
  items = data.items;
47
50
  total = data.total;
48
51
  categories = data.categories;
52
+ void ensureStatusPrivilege();
49
53
  }
50
54
  catch (e) {
51
55
  error = e instanceof Error ? e.message : 'Failed to load';
@@ -180,6 +184,7 @@ export function createFeedbackBoard(options) {
180
184
  try {
181
185
  const result = await client.getBoardTransitions(itemId, token);
182
186
  transitions = { ...transitions, [itemId]: result };
187
+ statusPrivilege = true; // a successful load means the backend authorized this user
183
188
  return result;
184
189
  }
185
190
  catch {
@@ -187,6 +192,21 @@ export function createFeedbackBoard(options) {
187
192
  return null;
188
193
  }
189
194
  }
195
+ /**
196
+ * One-time probe so the UI can gate the status control by *actual* privilege
197
+ * (valid token + qualifying role + project access), not merely token presence.
198
+ * Loads the first item's transitions once; a non-null result confirms the
199
+ * backend authorized the user. No token / no items / a 403 leaves it `false`.
200
+ */
201
+ async function ensureStatusPrivilege() {
202
+ if (privilegeProbed || !getAuthToken)
203
+ return;
204
+ const sample = items[0];
205
+ if (!sample)
206
+ return;
207
+ privilegeProbed = true;
208
+ statusPrivilege = (await loadTransitions(sample.id)) !== null;
209
+ }
190
210
  async function setStatus(itemId, status, reason) {
191
211
  const token = await resolveToken();
192
212
  if (!token)
@@ -226,7 +246,7 @@ export function createFeedbackBoard(options) {
226
246
  getResponses,
227
247
  submitFeedback,
228
248
  submitResponse,
229
- get canManageStatus() { return !!getAuthToken; },
249
+ get canManageStatus() { return statusPrivilege; },
230
250
  get transitions() { return transitions; },
231
251
  loadTransitions,
232
252
  setStatus,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alliance-droid/status-feedback-system",
3
- "version": "4.0.1",
3
+ "version": "4.0.2",
4
4
  "type": "module",
5
5
  "description": "Drop-in system status pages and user feedback forms for SvelteKit apps",
6
6
  "svelte": "./dist/index.js",