diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b087abab..e0491c63 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -22,7 +22,13 @@ Before getting started, please **star our repository** to show your support for
- Browse our open issues.
- If you find an issue you want to work on, comment on it expressing your interest and wait to be officially assigned by a maintainer.
-- ⚠️ **Do not start coding or open a Pull Request before being assigned to the issue.** Unassigned PRs or PRs targeting unclaimed issues may be closed without review to avoid duplicate work.
+- ⚠️ **Do not start coding or open a Pull Request before being assigned to the issue.**
+- **Strict Issue Claiming & Pull Request Rules:**
+ - **Claim Before Coding:** You must officially claim and be assigned an issue before you start working on it or submit a Pull Request.
+ - **Priority for Rule Followers:** If a contributor submits a PR without being assigned to the issue, and another contributor subsequently requests to claim/work on that issue following the correct procedure (commenting on the issue to request assignment), priority will be given to the contributor who requested the claim.
+ - **Unassigned PR Procedure:** If a PR is opened without an associated claim/assignment, maintainers will post a comment on the corresponding issue directing the author to claim it.
+ - **7-Day Grace Period:** Maintainers will wait for up to **7 days** for the PR author to claim the issue. If the author fails to comment on the issue and claim it within 7 days, the PR may not be merged (even if the code is correct) and may be closed.
+ - **Claim Priority:** If another contributor claims the issue during this grace period, the contributor who officially requested the claim will be considered first.
### 3. Fork & Clone 🍴
diff --git a/README.md b/README.md
index 19c018e0..986a1c15 100644
--- a/README.md
+++ b/README.md
@@ -168,7 +168,7 @@ VeriWorkly is built on open-source principles, and we welcome community contribu
> Before checking out a branch or creating a pull request, please review our full **[Contributing Guidelines](CONTRIBUTING.md)**.
>
> 1. 🌟 **Star the repository** to show your support.
-> 2. 📋 **Claim an issue** by commenting on it and waiting to be assigned before starting work.
+> 2. 📋 **Claim an issue** by commenting on it and waiting to be assigned before starting work. **PRs submitted for unclaimed/unassigned issues will not be merged unless claimed. Authors have a 7-day grace period to claim them, otherwise they may be closed. Priority always goes to the contributor who officially requested the claim.**
> 3. 📝 Ensure your **PR titles** follow the standard naming convention.
### Ways to Help Out
diff --git a/apps/docs-platform/content/docs/contributing/index.mdx b/apps/docs-platform/content/docs/contributing/index.mdx
index 41befb33..0adef688 100644
--- a/apps/docs-platform/content/docs/contributing/index.mdx
+++ b/apps/docs-platform/content/docs/contributing/index.mdx
@@ -15,6 +15,20 @@ To ensure a smooth collaboration, please follow these steps to set up your contr
1. **Star the Repository** 🌟: Before getting started, please star the [VeriWorkly Repository](https://github.com/VeriWorkly/veriworkly) to show your support for this open-source project!
2. **Claim an Issue** 📋: Browse our open issues. Comment on the one you would like to work on and wait to be officially assigned by a maintainer. **Please do not start coding or open a PR until you are officially assigned to the issue** to avoid duplicate efforts.
+
+
+ * **Priority for Rule Followers:** If a contributor submits a PR without being assigned to the
+ issue, and another contributor subsequently requests to claim/work on that issue following the
+ correct procedure (commenting on the issue), priority will be given to the contributor who
+ requested the claim. * **No-Claim PR Procedure:** If a PR is opened without an associated
+ claim/assignment, maintainers will post a comment on the corresponding issue directing the
+ author to claim it. * **7-Day Grace Period:** Maintainers will wait for up to **7 days** for
+ the PR author to claim the issue. If the author fails to comment on the issue and claim it
+ within 7 days, the PR may not be merged (even if the code is correct) and may be closed. *
+ **Claim Priority:** If another contributor claims the issue during this grace period, the
+ contributor who officially requested the claim will be considered first.
+
+
3. **Fork the repository** on GitHub by clicking the **Fork** button on the [VeriWorkly Repository](https://github.com/VeriWorkly/veriworkly).
4. **Clone your personal fork** to your local machine:
```bash
diff --git a/apps/server/src/auth/index.ts b/apps/server/src/auth/index.ts
index 5fb0f758..e5f0049f 100644
--- a/apps/server/src/auth/index.ts
+++ b/apps/server/src/auth/index.ts
@@ -11,7 +11,7 @@ import { prisma } from "#utils/prisma";
import { sendAuthOtpEmail } from "#auth/mailer";
import { createAuthMiddleware } from "better-auth/api";
-import { invalidateSessionCache } from "#utils/authCache";
+import { invalidateSessionCache, invalidateCacheByToken } from "#utils/authCache";
export const auth = betterAuth({
database: prismaAdapter(prisma, {
@@ -83,6 +83,37 @@ export const auth = betterAuth({
}
}),
},
+
+ databaseHooks: {
+ user: {
+ delete: {
+ before: async (user) => {
+ try {
+ const sessions = await prisma.session.findMany({
+ where: { userId: user.id },
+ select: { token: true },
+ });
+
+ await Promise.all(sessions.map((session) => invalidateCacheByToken(session.token)));
+ } catch {
+ // Ignore database hook errors to avoid blocking deletes
+ }
+ },
+ },
+ },
+
+ session: {
+ delete: {
+ after: async (session) => {
+ try {
+ await invalidateCacheByToken(session.token);
+ } catch {
+ // Ignore database hook errors to avoid blocking deletes
+ }
+ },
+ },
+ },
+ },
});
export const authNodeHandler = toNodeHandler(auth);
diff --git a/apps/server/src/utils/authCache.ts b/apps/server/src/utils/authCache.ts
index 66003d77..09a3dc70 100644
--- a/apps/server/src/utils/authCache.ts
+++ b/apps/server/src/utils/authCache.ts
@@ -42,3 +42,13 @@ export async function invalidateSessionCache(cookieHeader: string): Promise {
+ const prefix1 = `veriworkly-auth.session_token=${token}`;
+ const prefix2 = `__Secure-veriworkly-auth.session_token=${token}`;
+
+ const hash1 = createHash("md5").update(prefix1).digest("hex");
+ const hash2 = createHash("md5").update(prefix2).digest("hex");
+
+ await Promise.all([cacheDel(`auth:session:${hash1}`), cacheDel(`auth:session:${hash2}`)]);
+}