Skip to content

feat: implement submission draft system#119

Merged
Benjtalkshow merged 4 commits intoboundlessfi:mainfrom
devJaja:feat/submission-draft-system
Feb 26, 2026
Merged

feat: implement submission draft system#119
Benjtalkshow merged 4 commits intoboundlessfi:mainfrom
devJaja:feat/submission-draft-system

Conversation

@devJaja
Copy link
Contributor

@devJaja devJaja commented Feb 25, 2026

Implement Submission Draft System

Summary

Added auto-save draft functionality for bounty submissions. Users can now save unfinished submissions that
automatically restore when they return.

Changes

  • Added types/submission-draft.ts - Type definitions for draft data
  • Added hooks/use-submission-draft.ts - Draft management hook with auto-save
  • Added hooks/tests/use-submission-draft.test.ts - Test coverage
  • Modified components/bounty-detail/bounty-detail-submissions-card.tsx - Integrated draft system

Features

  • Auto-saves 1 second after user stops typing
  • Persists drafts in localStorage per bounty
  • Restores drafts automatically on return
  • Clears drafts after successful submission
  • Shows draft timestamp in UI

Testing

bash
npm test use-submission-draft

Acceptance Criteria

  • ✅ Draft saves automatically
  • ✅ Draft reloads when user returns

Closes: #82

Summary by CodeRabbit

  • New Features
    • Submission drafts auto-save while filling PR URL and comments, restore automatically with a last-saved timestamp, and clear after successful submission.
  • Documentation
    • Added an example demonstrating draft loading, auto-saving, and clearing in the submission flow.
  • Tests
    • Added tests covering draft save, clear, auto-save behavior, and cross-instance persistence.

@vercel
Copy link

vercel bot commented Feb 25, 2026

@devJaja is attempting to deploy a commit to the Threadflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

Adds a submission-draft system: new types, a localStorage-backed useSubmissionDraft hook (save/clear/autoSave), unit tests, an example component, and integrates draft restore, auto-save, and draft clearing into the bounty submissions card component.

Changes

Cohort / File(s) Summary
Type Definitions
types/submission-draft.ts
Add SubmissionForm and SubmissionDraft interfaces (id, bountyId, formData, updatedAt).
Draft Hook
hooks/use-submission-draft.ts
New useSubmissionDraft(bountyId) hook: localStorage-backed draft state, saveDraft, clearDraft, and debounced autoSave (1s) with conditional saves.
Hook Tests
hooks/__tests__/use-submission-draft.test.ts
Add tests for init, save, clear, auto-save debounce, and cross-instance persistence for same bountyId.
Component Integration
components/bounty-detail/bounty-detail-submissions-card.tsx
Integrates hook: restore draft into PR URL/comments on mount, trigger autoSave while editing, show a timestamped “Draft restored” message, and call clearDraft() after successful submit.
Example Component
docs/SUBMISSION_DRAFTS_EXAMPLE.tsx
Add SubmissionFormExample demonstrating draft load, auto-save behavior, submit flow (mock), and draft clearing.

Sequence Diagram

sequenceDiagram
    actor User
    participant Component as BountyDetailSubmissionsCard
    participant Hook as useSubmissionDraft
    participant Storage as localStorage
    participant API as SubmissionAPI

    User->>Component: Open submit PR dialog
    Component->>Hook: initialize(bountyId)
    Hook->>Storage: load draft for bountyId
    Storage-->>Hook: return draft (if present)
    Hook-->>Component: provide draft state
    Component->>Component: restore fields & show "Draft restored"

    User->>Component: Edit PR URL / comments
    Component->>Hook: autoSave(formData)
    Note over Hook: debounce 1s, save only if fields present
    Hook->>Storage: persist draft with updatedAt
    Storage-->>Hook: confirm save

    User->>Component: Submit form
    Component->>API: submit
    API-->>Component: success
    Component->>Hook: clearDraft()
    Hook->>Storage: remove draft
    Storage-->>Hook: confirm clear
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • Benjtalkshow
  • 0xdevcollins

Poem

🐇 I nibble lines and tuck them snug away,

Your half-done PR I keep for another day,
I whisper “restored” when you return to write,
I clear my trail when you press send tonight,
Hop happy — your draft is safe till morning light ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat: implement submission draft system' directly and clearly summarizes the main objective, matching the PR objectives and linked issue #82.
Linked Issues check ✅ Passed All acceptance criteria from issue #82 are satisfied: drafts auto-save via 1-second debounce and localStorage persistence, and restore automatically when users return to the submission form.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the submission draft system as defined in issue #82; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
hooks/__tests__/use-submission-draft.test.ts (1)

52-69: Use fake timers for deterministic debounce testing.

The 1.5s real-time waitFor window makes this test slower and potentially flaky under load. Advance fake timers instead: setup jest.useFakeTimers() before the test, call jest.advanceTimersByTime(AUTO_SAVE_DELAY) after autoSave(), and assert immediately.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/__tests__/use-submission-draft.test.ts` around lines 52 - 69, The test
currently relies on a real wait window; make it deterministic by using Jest fake
timers: in the "should auto-save after delay" test enable fake timers with
jest.useFakeTimers(), call result.current.autoSave(formData) and then advance
timers by the debounce constant (AUTO_SAVE_DELAY) via
jest.advanceTimersByTime(AUTO_SAVE_DELAY), then assert
result.current.draft?.formData equals formData immediately (remove the long
waitFor). Ensure to restore timers after the test if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/bounty-detail/bounty-detail-submissions-card.tsx`:
- Around line 69-81: The auto-save runs immediately after the draft hydration
and overwrites updatedAt; to fix, add a hydration guard (e.g., a ref or state
like isHydrated) that is set true inside the draft-useEffect after
setPrUrl/setSubmitComments, and change the auto-save useEffect to return early
(or not call autoSave) when isHydrated is false so autosave only starts after
the initial draft values are loaded; reference the existing symbols draft,
setPrUrl, setSubmitComments, prUrl, submitComments, and autoSave to implement
this guard.

In `@docs/SUBMISSION_DRAFTS_EXAMPLE.tsx`:
- Around line 35-49: The handleSubmit async function is missing
event.preventDefault(), so update handleSubmit to accept the form event (e.g.,
event: React.FormEvent) and immediately call event.preventDefault() before
awaiting submitToAPI({ prUrl, comments }); to prevent the browser from doing a
full page submit and interrupting the async flow; keep the existing
clearDraft(), setPrUrl(""), and setComments("") logic after the await so the
draft reset still occurs on success.

In `@hooks/use-submission-draft.ts`:
- Around line 29-38: The autoSave callback currently skips saving when both
formData.githubPullRequestUrl and formData.comments are empty, leaving stale
drafts; update the autoSave logic (in use-submission-draft.ts -> autoSave) to
always call saveDraft(formData) after the debounce (or call a dedicated
clearDraft when available) instead of only when those fields are present so an
empty form clears the persisted draft; keep the same AUTO_SAVE_DELAY and return
the clearTimeout cleanup as before.

---

Nitpick comments:
In `@hooks/__tests__/use-submission-draft.test.ts`:
- Around line 52-69: The test currently relies on a real wait window; make it
deterministic by using Jest fake timers: in the "should auto-save after delay"
test enable fake timers with jest.useFakeTimers(), call
result.current.autoSave(formData) and then advance timers by the debounce
constant (AUTO_SAVE_DELAY) via jest.advanceTimersByTime(AUTO_SAVE_DELAY), then
assert result.current.draft?.formData equals formData immediately (remove the
long waitFor). Ensure to restore timers after the test if needed.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9955bb3 and dc75003.

📒 Files selected for processing (5)
  • components/bounty-detail/bounty-detail-submissions-card.tsx
  • docs/SUBMISSION_DRAFTS_EXAMPLE.tsx
  • hooks/__tests__/use-submission-draft.test.ts
  • hooks/use-submission-draft.ts
  • types/submission-draft.ts

Comment on lines +35 to +49
const handleSubmit = async () => {
// Your submit logic here
await submitToAPI({ prUrl, comments });

// Clear draft after success
clearDraft();

// Reset form
setPrUrl("");
setComments("");
};

return (
<form onSubmit={handleSubmit}>
{/* Show draft indicator */}
Copy link

@coderabbitai coderabbitai bot Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -t f "SUBMISSION_DRAFTS_EXAMPLE.tsx"

Repository: boundlessfi/bounties

Length of output: 98


🏁 Script executed:

cat -n docs/SUBMISSION_DRAFTS_EXAMPLE.tsx

Repository: boundlessfi/bounties

Length of output: 2523


Add preventDefault() to the async form submit handler to prevent page reload.

The form handler is missing event.preventDefault(), which allows the browser's default form submission to interrupt the async submitToAPI call and draft system flow.

Required changes
-import { useState, useEffect } from "react";
+import { useState, useEffect } from "react";
+import type { FormEvent } from "react";

-  const handleSubmit = async () => {
+  const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
+    event.preventDefault();
     // Your submit logic here
     await submitToAPI({ prUrl, comments });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/SUBMISSION_DRAFTS_EXAMPLE.tsx` around lines 35 - 49, The handleSubmit
async function is missing event.preventDefault(), so update handleSubmit to
accept the form event (e.g., event: React.FormEvent) and immediately call
event.preventDefault() before awaiting submitToAPI({ prUrl, comments }); to
prevent the browser from doing a full page submit and interrupting the async
flow; keep the existing clearDraft(), setPrUrl(""), and setComments("") logic
after the await so the draft reset still occurs on success.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@devJaja you skipped this

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines +29 to +38
const autoSave = useCallback(
(formData: SubmissionForm) => {
const timer = setTimeout(() => {
if (formData.githubPullRequestUrl || formData.comments) {
saveDraft(formData);
}
}, AUTO_SAVE_DELAY);
return () => clearTimeout(timer);
},
[saveDraft]
Copy link

@coderabbitai coderabbitai bot Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Clear persisted draft when form content becomes empty.

At Line 32, empty form state is ignored rather than persisted/cleared, so stale draft data can be restored later.

💡 Proposed fix
   const autoSave = useCallback(
     (formData: SubmissionForm) => {
       const timer = setTimeout(() => {
-        if (formData.githubPullRequestUrl || formData.comments) {
+        const hasContent =
+          formData.githubPullRequestUrl.trim().length > 0 ||
+          formData.comments.trim().length > 0;
+
+        if (hasContent) {
           saveDraft(formData);
+        } else {
+          clearDraft();
         }
       }, AUTO_SAVE_DELAY);
       return () => clearTimeout(timer);
     },
-    [saveDraft]
+    [saveDraft, clearDraft]
   );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@hooks/use-submission-draft.ts` around lines 29 - 38, The autoSave callback
currently skips saving when both formData.githubPullRequestUrl and
formData.comments are empty, leaving stale drafts; update the autoSave logic (in
use-submission-draft.ts -> autoSave) to always call saveDraft(formData) after
the debounce (or call a dedicated clearDraft when available) instead of only
when those fields are present so an empty form clears the persisted draft; keep
the same AUTO_SAVE_DELAY and return the clearTimeout cleanup as before.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@devJaja you skipped this

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

@0xdevcollins
Copy link
Contributor

@devJaja Resolve coderabbit comments and also. thhe conflict

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
components/bounty-detail/bounty-detail-submissions-card.tsx (1)

69-81: ⚠️ Potential issue | 🟠 Major

Skip the first auto-save cycle after draft hydration (still unresolved).

Line 69-75 hydrates prUrl/submitComments, then Line 77-81 immediately schedules auto-save, which rewrites updatedAt without user input and can mislead the restored timestamp UI.

💡 Proposed fix
-import { useState, useEffect } from "react";
+import { useState, useEffect, useRef } from "react";
@@
   const [prUrl, setPrUrl] = useState("");
-    const [submitComments, setSubmitComments] = useState("");
-    const [reviewComments, setReviewComments] = useState("");
+  const [submitComments, setSubmitComments] = useState("");
+  const [reviewComments, setReviewComments] = useState("");
+  const skipNextAutoSaveRef = useRef(false);
@@
   useEffect(() => {
     if (draft?.formData) {
       setPrUrl(draft.formData.githubPullRequestUrl);
       setSubmitComments(draft.formData.comments);
+      skipNextAutoSaveRef.current = true;
     }
   }, [draft]);
@@
   useEffect(() => {
+    if (skipNextAutoSaveRef.current) {
+      skipNextAutoSaveRef.current = false;
+      return;
+    }
     const cleanup = autoSave({ githubPullRequestUrl: prUrl, comments: submitComments });
     return cleanup;
   }, [prUrl, submitComments, autoSave]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/bounty-detail/bounty-detail-submissions-card.tsx` around lines 69
- 81, The current auto-save effect immediately runs after draft hydration and
overwrites updatedAt; prevent that by skipping the first auto-save run triggered
by the hydration effect: add a hydration flag/ref (e.g., hasHydratedDraft) that
you set to true at the end of the draft hydration useEffect (the block that
calls setPrUrl/setSubmitComments) and then guard the autoSave effect to no-op
unless hasHydratedDraft is true (use a ref or state checked inside the useEffect
that calls autoSave). This keeps symbols clear: set hasHydratedDraft after the
draft useEffect finishes, and only call autoSave({ githubPullRequestUrl: prUrl,
comments: submitComments }) from the auto-save useEffect when hasHydratedDraft
is true to avoid the unwanted initial save.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/bounty-detail/bounty-detail-submissions-card.tsx`:
- Around line 69-81: The current auto-save effect immediately runs after draft
hydration and overwrites updatedAt; prevent that by skipping the first auto-save
run triggered by the hydration effect: add a hydration flag/ref (e.g.,
hasHydratedDraft) that you set to true at the end of the draft hydration
useEffect (the block that calls setPrUrl/setSubmitComments) and then guard the
autoSave effect to no-op unless hasHydratedDraft is true (use a ref or state
checked inside the useEffect that calls autoSave). This keeps symbols clear: set
hasHydratedDraft after the draft useEffect finishes, and only call autoSave({
githubPullRequestUrl: prUrl, comments: submitComments }) from the auto-save
useEffect when hasHydratedDraft is true to avoid the unwanted initial save.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between dc75003 and c830445.

📒 Files selected for processing (1)
  • components/bounty-detail/bounty-detail-submissions-card.tsx

@devJaja
Copy link
Contributor Author

devJaja commented Feb 25, 2026

@devJaja Resolve coderabbit comments and also. thhe conflict

@0xdevcollins Done

@Benjtalkshow
Copy link
Contributor

@devJaja
One last thing to fix, the CI is failing😊
Kindly fix lints

@devJaja
Copy link
Contributor Author

devJaja commented Feb 26, 2026

@devJaja One last thing to fix, the CI is failing😊 Kindly fix you can have a llok now
@Benjtalkshow you can have a look now

@Benjtalkshow
Copy link
Contributor

@devJaja One last thing to fix, the CI is failing😊 Kindly fix you can have a llok now
@Benjtalkshow you can have a look now

@devJaja
Wave 2 ends in few hours. Quickly attend to the coderabbit correction so your PR can be merged.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
components/bounty-detail/bounty-detail-submissions-card.tsx (1)

69-85: ⚠️ Potential issue | 🟠 Major

Hydration guard still allows one immediate re-save of restored values.

This still updates updatedAt right after restore (no user edit): hydration sets state, then the next autosave run persists the same values. Add a one-shot skip flag for the first autosave after hydration.

💡 Proposed fix
-  const hasHydratedDraft = useRef(false);
+  const hasHydratedDraft = useRef(false);
+  const skipNextAutoSaveRef = useRef(false);

   // Load draft on mount
   useEffect(() => {
     if (draft?.formData) {
       setPrUrl(draft.formData.githubPullRequestUrl);
       setSubmitComments(draft.formData.comments);
+      skipNextAutoSaveRef.current = true;
     }
     hasHydratedDraft.current = true;
   }, [draft]);

   // Auto-save on form changes
   useEffect(() => {
     if (!hasHydratedDraft.current) return;
+    if (skipNextAutoSaveRef.current) {
+      skipNextAutoSaveRef.current = false;
+      return;
+    }
     const cleanup = autoSave({ githubPullRequestUrl: prUrl, comments: submitComments });
     return cleanup;
   }, [prUrl, submitComments, autoSave]);

Please verify by restoring an existing draft and waiting >1s without typing; the displayed draft timestamp should remain unchanged.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/bounty-detail/bounty-detail-submissions-card.tsx` around lines 69
- 85, The hydration guard currently sets hasHydratedDraft.current = true
immediately, allowing the very next autosave to persist restored values; modify
the logic to add a one-shot skip flag (e.g., skipNextAutosaveRef) that is set to
true when you hydrate the draft (inside the first useEffect where draft is
applied) and checked in the autosave useEffect before calling autoSave; if
skipNextAutosaveRef.current is true, clear it and return without saving so the
first autosave after hydration is skipped, otherwise call autoSave({
githubPullRequestUrl: prUrl, comments: submitComments }) as before. Ensure you
reference hasHydratedDraft, skipNextAutosaveRef (new), autoSave, prUrl,
submitComments and draft in the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/bounty-detail/bounty-detail-submissions-card.tsx`:
- Line 48: The draft storage is currently only keyed by bounty id, allowing
drafts to leak between accounts; update the draft hook and its usage so drafts
are scoped by both user id and bounty id. Change the call site that currently
does useSubmissionDraft(bounty.id) (and references draft, clearDraft, autoSave)
to pass the current user's stable id as well (e.g.,
useSubmissionDraft(bounty.id, userId)), and modify the useSubmissionDraft
implementation to incorporate userId into the persistence key and to include a
canonical bountyId and userId in the stored payload so restore/clear operations
validate both identifiers.

---

Duplicate comments:
In `@components/bounty-detail/bounty-detail-submissions-card.tsx`:
- Around line 69-85: The hydration guard currently sets hasHydratedDraft.current
= true immediately, allowing the very next autosave to persist restored values;
modify the logic to add a one-shot skip flag (e.g., skipNextAutosaveRef) that is
set to true when you hydrate the draft (inside the first useEffect where draft
is applied) and checked in the autosave useEffect before calling autoSave; if
skipNextAutosaveRef.current is true, clear it and return without saving so the
first autosave after hydration is skipped, otherwise call autoSave({
githubPullRequestUrl: prUrl, comments: submitComments }) as before. Ensure you
reference hasHydratedDraft, skipNextAutosaveRef (new), autoSave, prUrl,
submitComments and draft in the change.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4273c4f and f937a7d.

📒 Files selected for processing (1)
  • components/bounty-detail/bounty-detail-submissions-card.tsx

}: BountyDetailSubmissionsCardProps) {
const { data: session } = authClient.useSession();
const submissions = bounty.submissions || [];
const { draft, clearDraft, autoSave } = useSubmissionDraft(bounty.id);
Copy link

@coderabbitai coderabbitai bot Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Scope draft storage by user identity to prevent cross-account draft exposure.

useSubmissionDraft(bounty.id) scopes persisted data only by bounty. On shared browsers, a different signed-in user visiting the same bounty can restore someone else’s draft content. Please key drafts by both user id and bounty id (likely by extending the hook API so bountyId in the stored payload remains canonical).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/bounty-detail/bounty-detail-submissions-card.tsx` at line 48, The
draft storage is currently only keyed by bounty id, allowing drafts to leak
between accounts; update the draft hook and its usage so drafts are scoped by
both user id and bounty id. Change the call site that currently does
useSubmissionDraft(bounty.id) (and references draft, clearDraft, autoSave) to
pass the current user's stable id as well (e.g., useSubmissionDraft(bounty.id,
userId)), and modify the useSubmissionDraft implementation to incorporate userId
into the persistence key and to include a canonical bountyId and userId in the
stored payload so restore/clear operations validate both identifiers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Scope draft storage by user identity to prevent cross-account draft exposure.

useSubmissionDraft(bounty.id) scopes persisted data only by bounty. On shared browsers, a different signed-in user visiting the same bounty can restore someone else’s draft content. Please key drafts by both user id and bounty id (likely by extending the hook API so bountyId in the stored payload remains canonical).

🤖 Prompt for AI Agents

skip it

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@devJaja, understood – I'll skip this suggestion. Feel free to revisit it later if cross-user draft isolation becomes a concern.

    /)_/)
   (•_• )
   />💭 (okay...)

@Benjtalkshow Benjtalkshow merged commit 94fbe90 into boundlessfi:main Feb 26, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Submission Draft System

3 participants