Repository: kindfi-org/kindfi
Pull request #239: wip: feat(api): add milestone review payload and validation
Author: login: 0xdevcollins
Labels: name: enhancement
description: New feature improvement or request
name: feature
description: New requested feature
name: webapp
description: web app related
name: supabase
description: supabase (database) service related
name: TL
description: Trustless Work Escrow API Development Related
name: backend
description: Back-end development related
Created: 2025-02-27T08:21:47Z | Merged: 2025-03-20T17:14:44Z

Closes: #50

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced an API endpoint for processing milestone reviews, validating submissions, and handling approval workflows.
  - Enhanced the review process with authorization verification, milestone status updates, and user notifications upon status changes.
  - Added a new interface for handling milestone review data.

- **Documentation**
  - Updated usage examples for improved consistency and clarity in code demonstration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/apps/web/app/api/escrow/review/route.ts b/apps/web/app/api/escrow/review/route.ts
new file mode 100644
index 000000000..f180aa277
--- /dev/null
+++ b/apps/web/app/api/escrow/review/route.ts
@@ -0,0 +1,160 @@
+import { Networks } from '@stellar/stellar-sdk'
+import { type NextRequest, NextResponse } from 'next/server'
+import { AppError } from '~/lib/error'
+import { createEscrowRequest } from '~/lib/stellar/utils/create-escrow'
+import { sendTransaction } from '~/lib/stellar/utils/send-transaction'
+import { signTransaction } from '~/lib/stellar/utils/sign-transaction'
+import { supabase } from '~/lib/supabase/config'
+import type { MilestoneReviewPayload } from '~/lib/types/escrow/escrow-payload.types'
+import { validateMilestoneReview } from '~/lib/validators/escrow'
+
+export async function POST(req: NextRequest) {
+	try {
+		const reviewData: MilestoneReviewPayload = await req.json()
+		const validationResult = validateMilestoneReview(reviewData)
+
+		if (!validationResult.success) {
+			return NextResponse.json(
+				{
+					error: 'Invalid milestone review data',
+					details: validationResult.errors,
+				},
+				{ status: 400 },
+			)
+		}
+
+		const {
+			milestoneId,
+			reviewerId,
+			status,
+			comments,
+			signer,
+			escrowContractAddress,
+		} = reviewData
+
+		// Step 1: Validate Milestone Exists
+		const { data: milestone, error: milestoneError } = await supabase
+			.from('escrow_milestones')
+			.select('*')
+			.eq('id', milestoneId)
+			.single()
+
+		if (milestoneError || !milestone) {
+			return NextResponse.json(
+				{ error: 'Milestone not found' },
+				{ status: 404 },
+			)
+		}
+
+		// Step 2: Validate Reviewer Exists
+		const { data: reviewer, error: reviewerError } = await supabase
+			.from('reviewers')
+			.select('*')
+			.eq('id', reviewerId)
+			.single()
+
+		if (reviewerError || !reviewer) {
+			return NextResponse.json(
+				{ error: 'Reviewer not authorized' },
+				{ status: 403 },
+			)
+		}
+
+		// Step 4: Finalize Milestone On-Chain if Approved
+		if (status === 'approved') {
+			const escrowResponse = await createEscrowRequest({
+				action: 'approveMilestone',
+				method: 'POST',
+				data: { signer, contractId: escrowContractAddress },
+			})
+
+			if (!escrowResponse.unsignedTransaction) {
+				throw new Error('Failed to retrieve unsigned transaction XDR')
+			}
+
+			// Sign transaction
+			const signedTxXdr = signTransaction(
+				escrowResponse.unsignedTransaction,
+				Networks.TESTNET, // Change to MAINNET if in production
+				signer,
+			)
+
+			if (!signedTxXdr) {
+				throw new Error('Transaction signing failed')
+			}
+
+			// Send signed transaction on-chain
+			const txResponse = await sendTransaction(signedTxXdr)
+
+			if (!txResponse || !txResponse.txHash) {
+				throw new Error('Failed to finalize milestone on-chain')
+			}
+		}
+
+		// Step 5: Update Milestone Status in DB
+		const { data: updatedMilestone, error: updateError } = await supabase
+			.from('escrow_milestones')
+			.update({
+				status,
+				completed_at: status === 'approved' ? new Date().toISOString() : null,
+			})
+			.eq('id', milestoneId)
+			.select('*')
+			.single()
+
+		if (updateError) {
+			throw new Error('Failed to update milestone status')
+		}
+
+		// Step 6: Save Review Comments
+		const { error: commentError } = await supabase
+			.from('review_comments')
+			.insert({
+				milestone_id: milestoneId,
+				reviewer_id: reviewerId,
+				comments,
+			})
+
+		if (commentError) {
+			throw new Error('Failed to add review comments')
+		}
+
+		// Step 7: Send Notification
+		const { error: notificationError } = await supabase
+			.from('notifications')
+			.insert({
+				user_id: milestone.user_id,
+				milestone_id: milestoneId,
+				message: `Your milestone status has been updated to ${status}.`,
+			})
+
+		if (notificationError) {
+			throw new Error('Failed to send notification')
+		}
+
+		return NextResponse.json(
+			{
+				success: true,
+				message: 'Milestone reviewed successfully',
+				data: { milestone: updatedMilestone },
+			},
+			{ status: 200 },
+		)
+	} catch (error) {
+
+		console.error('Milestone Review Error:', error)
+
+
+		if (error instanceof AppError) {
+			return NextResponse.json(
+				{ error: error.message, details: error.details },
+				{ status: error.statusCode },
+			)
+		}
+
+		return NextResponse.json(
+			{ error: 'Invalid JSON format in request body' },
+			{ status: 400 },
+		)
+	}
+}
diff --git a/apps/web/lib/types/escrow/escrow-payload.types.ts b/apps/web/lib/types/escrow/escrow-payload.types.ts
index 564583b30..96a17bba0 100644
--- a/apps/web/lib/types/escrow/escrow-payload.types.ts
+++ b/apps/web/lib/types/escrow/escrow-payload.types.ts
@@ -89,3 +89,12 @@ export interface EscrowFundUpdateData {
 	transactionHash: string
 	status: TransactionStatus
 }
+
+export interface MilestoneReviewPayload {
+	milestoneId: string
+	reviewerId: string
+	status: MilestoneStatus
+	comments?: string
+	signer: string
+	escrowContractAddress: string
+}
diff --git a/apps/web/lib/validators/escrow.ts b/apps/web/lib/validators/escrow.ts
index da3117866..5cad217bd 100644
--- a/apps/web/lib/validators/escrow.ts
+++ b/apps/web/lib/validators/escrow.ts
@@ -2,6 +2,7 @@ import type {
 	EscrowFundData,
 	EscrowFundUpdateData,
 	EscrowPayload,
+	MilestoneReviewPayload,
 } from '../types/escrow/escrow-payload.types'
 import type { Milestone } from '../types/escrow/escrow.types'
 
@@ -193,3 +194,38 @@ export function validateEscrowFundUpdate(
 		errors,
 	}
 }
+
+export function validateMilestoneReview(
+	data: MilestoneReviewPayload,
+): ValidationResult {
+	const errors: string[] = []
+
+	// Validate milestoneId
+	if (!data.milestoneId?.trim()) {
+		errors.push('Milestone ID is required.')
+	}
+
+	// Validate reviewerId
+	if (!data.reviewerId?.trim()) {
+		errors.push('Reviewer ID is required.')
+	}
+
+	// Validate status
+	if (!data.status) {
+		errors.push('Milestone status is required.')
+	} else if (
+		!['pending', 'approved', 'rejected', 'completed'].includes(data.status)
+	) {
+		errors.push('Invalid milestone status.')
+	}
+
+	// Validate comments (optional but should not be empty if provided)
+	if (data.comments && !data.comments.trim()) {
+		errors.push('Comments cannot be empty.')
+	}
+
+	return {
+		success: errors.length === 0,
+		errors,
+	}
+}
diff --git a/docs/component-usage-example.md b/docs/component-usage-example.md
index faa9e3710..db040ada6 100644
--- a/docs/component-usage-example.md
+++ b/docs/component-usage-example.md
@@ -1,6 +1,7 @@
 # KindFi Integration & Usage Guide
 
 ## Table of Contents
+
 - [UI Components](#ui-components)
   - [Basic UI Component Example](#1-basic-ui-component-example)
   - [Complex Integration Scenerio](#2-complex-integration-scenerio)
@@ -17,35 +18,37 @@
 
 The KindFi web application, located in the apps/web directory, utilizes React for building user interfaces. To illustrate basic usage of UI components, consider the following example of a button component:
 
-
 ```tsx
 // File: ~/components/base/button.tsx
-import { Slot } from '@radix-ui/react-slot';
-import { type VariantProps, cva } from 'class-variance-authority';
-import { cn } from '~/lib/utils';
+import { Slot } from "@radix-ui/react-slot";
+import { type VariantProps, cva } from "class-variance-authority";
+import { cn } from "~/lib/utils";
 
 const buttonVariants = cva(
-  'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
+  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
   {
     variants: {
       variant: {
-        default: 'text-blue-700',
-        destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
-        outline: 'border border-input bg-background text-black hover:text-blue-700',
-        secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
-        ghost: 'hover:gradient-border-btn',
-        link: 'text-primary underline-offset-4 hover:underline',
+        default: "text-blue-700",
+        destructive:
+          "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+        outline:
+          "border border-input bg-background text-black hover:text-blue-700",
+        secondary:
+          "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+        ghost: "hover:gradient-border-btn",
+        link: "text-primary underline-offset-4 hover:underline",
       },
       size: {
-        default: 'h-10 px-4 py-2',
-        sm: 'h-9 rounded-md px-3',
-        lg: 'h-11 rounded-md px-8',
-        icon: 'h-10 w-10',
+        default: "h-10 px-4 py-2",
+        sm: "h-9 rounded-md px-3",
+        lg: "h-11 rounded-md px-8",
+        icon: "h-10 w-10",
       },
     },
     defaultVariants: {
-      variant: 'default',
-      size: 'default',
+      variant: "default",
+      size: "default",
     },
   },
 );
@@ -58,7 +61,7 @@ export interface ButtonProps
 
 const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
   ({ className, variant, size, asChild = false, ...props }, ref) => {
-    const Comp = asChild ? Slot : 'button';
+    const Comp = asChild ? Slot : "button";
     return (
       <Comp
         className={cn(buttonVariants({ variant, size, className }))}
@@ -69,21 +72,20 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
   },
 );
 
-
-Button.displayName = 'Button';
+Button.displayName = "Button";
 
 export { Button, buttonVariants };
-
 ```
-### Usage 
+
+### Usage
 
 ```tsx
 // File: ~/app/home/page.tsx
-import { Button } from '~/components/base/button';
+import { Button } from "~/components/base/button";
 
 const Home = () => {
   const handleClick = () => {
-    alert('Button clicked!');
+    alert("Button clicked!");
   };
 
   return (
@@ -96,20 +98,23 @@ const Home = () => {
 
 export default Home;
 ```
+
 In this example, the Button component is a reusable UI element that can be integrated into various parts of the application.
 
 ### 2. Complex Integration Scenerio
-For more complex scenarios, such as integrating third-party libraries, the project employs components like react-dropzone for file uploads. The react-dropzone library provides a simple way to create an HTML5-compliant drag-and-drop zone for files. Documentation and examples are available at https://react-dropzone.js.org.
+
+For more complex scenarios, such as integrating third-party libraries, the project employs components like react-dropzone for file uploads. The react-dropzone library provides a simple way to create an HTML5-compliant drag-and-drop zone for files. Documentation and examples are available at [https://react-dropzone.js.org](https://react-dropzone.js.org).
 
 ### Example
+
 ```tsx
 // File: ~/components/sections/project/project-media.tsx
-'use client';
+"use client";
 
-import { useCallback } from 'react';
-import { useDropzone } from 'react-dropzone';
-import { Card } from '~/components/base/card';
-import { Input } from '~/components/base/input';
+import { useCallback } from "react";
+import { useDropzone } from "react-dropzone";
+import { Card } from "~/components/base/card";
+import { Input } from "~/components/base/input";
 
 interface ProjectMediaProps {
   onFileUpload: (file: File) => void;
@@ -120,10 +125,7 @@ interface ProjectMediaProps {
 export function ProjectMedia({
   onFileUpload,
   onVideoUrlChange,
-  videoUrl = '',
-  onFileUpload,
-  onVideoUrlChange,
-  videoUrl = '',
+  videoUrl = "",
 }: ProjectMediaProps) {
   const onDrop = useCallback(
     (acceptedFiles: File[]) => {
@@ -138,8 +140,9 @@ export function ProjectMedia({
   const { getRootProps, getInputProps, isDragActive } = useDropzone({
     onDrop,
     accept: {
-      'application/pdf': ['.pdf'],
-      'application/vnd.openxmlformats-officedocument.presentationml.presentation': ['.pptx'],
+      "application/pdf": [".pdf"],
+      "application/vnd.openxmlformats-officedocument.presentationml.presentation":
+        [".pptx"],
     },
     maxFiles: 1,
     maxSize: 10 * 1024 * 1024, // 10MB
@@ -154,14 +157,20 @@ export function ProjectMedia({
           <div
             {...getRootProps()}
             className={`border-2 border-dashed rounded-lg p-6 text-center cursor-pointer transition-colors ${
-              isDragActive ? 'border-blue-500 bg-blue-50' : 'border-gray-300 hover:border-gray-400'
+              isDragActive
+                ? "border-blue-500 bg-blue-50"
+                : "border-gray-300 hover:border-gray-400"
             }`}
           >
             <input {...getInputProps()} />
             <p className="text-gray-600">
-              {isDragActive ? 'Drop the file here...' : 'Drag & drop your pitch deck here, or click to select'}
+              {isDragActive
+                ? "Drop the file here..."
+                : "Drag & drop your pitch deck here, or click to select"}
+            </p>
+            <p className="text-sm text-gray-500 mt-1">
+              PDF or PowerPoint, max 10MB
             </p>
-            <p className="text-sm text-gray-500 mt-1">PDF or PowerPoint, max 10MB</p>
           </div>
         </div>
         <div>
@@ -173,27 +182,28 @@ export function ProjectMedia({
             onChange={(e) => onVideoUrlChange(e.target.value)}
             className="w-full"
           />
-          <p className="text-sm text-gray-500 mt-1">Optional: Add a video to enhance your pitch</p>
+          <p className="text-sm text-gray-500 mt-1">
+            Optional: Add a video to enhance your pitch
+          </p>
         </div>
       </div>
     </Card>
   );
 }
-
 ```
 
 ### Usage
 
 ```tsx
 // File: ~/app/projects/page.tsx
-import { ProjectMedia } from '~/components/sections/project/project-media';
+import { ProjectMedia } from "~/components/sections/project/project-media";
 
 export default function ProjectsPage() {
   const handleFileUpload = (file: File) => {
-    console.log('File uploaded:', file.name);
+    console.log("File uploaded:", file.name);
   };
   const handleVideoUrlChange = (url: string) => {
-    console.log('Video URL updated:', url);
+    console.log("Video URL updated:", url);
   };
 
   return (
@@ -207,16 +217,15 @@ export default function ProjectsPage() {
 }
 ```
 
-### 3. State Management Example 
+### 3. State Management Example
 
 For state management, KindFi uses React Context and server actions in Next.js 15. Here's an example:
 
-
 ```tsx
 // File: ~/context/project-context.tsx
-'use client';
+"use client";
 
-import { createContext, useContext, useReducer } from 'react';
+import { createContext, useContext, useReducer } from "react";
 
 const initialState = {
   projects: [],
@@ -224,7 +233,7 @@ const initialState = {
 
 const projectReducer = (state, action) => {
   switch (action.type) {
-    case 'SET_PROJECTS':
+    case "SET_PROJECTS":
       return { ...state, projects: action.payload };
     default:
       return state;
@@ -249,6 +258,7 @@ export const useProject = () => useContext(ProjectContext);
 ### Using a fetch request
 
 Making a fetch Request from your API
+
 ```tsx
 // File: ~/app/projects/page.tsx
 export default function async Page(){
@@ -269,6 +279,7 @@ export default function async Page(){
 };
 
 ```
+
 This approach ensures predictable state transitions and makes the application easier to debug and maintain.
 
 ### 4. Form Handling Example
@@ -277,12 +288,12 @@ For form handling, KindFi uses server actions in Next.js 15. Here's an example:
 
 ```tsx
 // File: ~/components/forms/contribution-form.tsx
-'use client';
+"use client";
 
-import { useState } from 'react';
+import { useState } from "react";
 
 export default function ContributionForm({ onSubmit }) {
-  const [amount, setAmount] = useState('');
+  const [amount, setAmount] = useState("");
 
   const handleSubmit = (e) => {
     e.preventDefault();
@@ -308,12 +319,11 @@ export default function ContributionForm({ onSubmit }) {
 ### Usage with Server Action
 
 ```tsx
-
 // File: ~/app/projects/[id]/page.tsx
-import ContributionForm from '~/components/forms/contribution-form';
+import ContributionForm from "~/components/forms/contribution-form";
 export default function ProjectDetails() {
   const handleContribution = async (amount) => {
-    'use server';
+    "use server";
     console.log(`Contributed: ${amount}`);
   };
 
@@ -324,39 +334,43 @@ export default function ProjectDetails() {
     </div>
   );
 }
-
 ```
 
 ## Service Integration
+
 ### 1. KYC Service Integration
 
 ```tsx
 // File: ~/services/kyc.ts
 export const submitKYC = async (baseUrl: string, data: any) => {
   const formData = new FormData();
-  formData.append('userId', data.userId);
-  formData.append('documentType', data.documentType);
-  formData.append('documentFront', data.documentFront);
-  if (data.documentBack) formData.append('documentBack', data.documentBack);
-  formData.append('selfie', data.selfie);
+  formData.append("userId", data.userId);
+  formData.append("documentType", data.documentType);
+  formData.append("documentFront", data.documentFront);
+  if (data.documentBack) formData.append("documentBack", data.documentBack);
+  formData.append("selfie", data.selfie);
 
   const response = await fetch(`${baseUrl}/kyc/submit`, {
-    method: 'POST',
+    method: "POST",
     body: formData,
   });
 
-  if (!response.ok) throw new Error('KYC submission failed');
+  if (!response.ok) throw new Error("KYC submission failed");
   return response.json();
 };
 
-export const checkKYCStatus = async (baseUrl: string, verificationId: string) => {
+export const checkKYCStatus = async (
+  baseUrl: string,
+  verificationId: string,
+) => {
   const response = await fetch(`${baseUrl}/kyc/status/${verificationId}`);
-  if (!response.ok) throw new Error('Failed to check KYC status');
+  if (!response.ok) throw new Error("Failed to check KYC status");
   return response.json();
 };
 ```
 
 ### 2. AI Service Integration
+
 ```tsx
 // File: ~/services/ai.ts
 interface AICampaignAnalysis {
@@ -371,15 +385,15 @@ export const analyzeCampaign = async (
   campaignData: { title: string; description: string; goals: string[] },
 ): Promise<AICampaignAnalysis> => {
   const response = await fetch(`${baseUrl}/analyze`, {
-    method: 'POST',
+    method: "POST",
     headers: {
-      'Content-Type': 'application/json',
+      "Content-Type": "application/json",
       Authorization: `Bearer ${apiKey}`,
     },
     body: JSON.stringify(campaignData),
   });
 
-  if (!response.ok) throw new Error('Campaign analysis failed');
+  if (!response.ok) throw new Error("Campaign analysis failed");
   return response.json();
 };
 ```
@@ -388,7 +402,7 @@ export const analyzeCampaign = async (
 
 ```tsx
 // File: ~/services/supabase.ts
-import { createClient, SupabaseClient } from '@supabase/supabase-js';
+import { createClient, SupabaseClient } from "@supabase/supabase-js";
 
 interface Campaign {
   id: string;
@@ -397,28 +411,35 @@ interface Campaign {
   target_amount: number;
   current_amount: number;
   creator_id: string;
-  status: 'draft' | 'active' | 'completed' | 'cancelled';
+  status: "draft" | "active" | "completed" | "cancelled";
   created_at: string;
 }
 
-export const createSupabaseClient = (supabaseUrl: string, supabaseKey: string): SupabaseClient => {
+export const createSupabaseClient = (
+  supabaseUrl: string,
+  supabaseKey: string,
+): SupabaseClient => {
   return createClient(supabaseUrl, supabaseKey);
 };
 
 export const createCampaign = async (
   supabase: SupabaseClient,
-  campaign: Omit<Campaign, 'id' | 'created_at'>,
+  campaign: Omit<Campaign, "id" | "created_at">,
 ) => {
-  const { data, error } = await supabase.from('campaigns').insert(campaign).select().single();
+  const { data, error } = await supabase
+    .from("campaigns")
+    .insert(campaign)
+    .select()
+    .single();
   if (error) throw error;
   return data;
 };
 
 export const getCampaign = async (supabase: SupabaseClient, id: string) => {
   const { data, error } = await supabase
-    .from('campaigns')
-    .select('*, creator:profiles(*)')
-    .eq('id', id)
+    .from("campaigns")
+    .select("*, creator:profiles(*)")
+    .eq("id", id)
     .single();
   if (error) throw error;
   return data;
@@ -429,8 +450,13 @@ export const updateCampaign = async (
   id: string,
   updates: Partial<Campaign>,
 ) => {
-  const { data, error } = await supabase.from('campaigns').update(updates).eq('id', id).select().single();
+  const { data, error } = await supabase
+    .from("campaigns")
+    .update(updates)
+    .eq("id", id)
+    .select()
+    .single();
   if (error) throw error;
   return data;
 };
-```
\ No newline at end of file
+```


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (5)</summary><blockquote>

<details>
<summary>apps/web/lib/types/escrow/escrow-payload.types.ts (1)</summary><blockquote>

`93-98`: **Encourage consistent status usage and clarify relationships**  
We appreciate this well-defined interface; it effectively outlines the shape of the milestone review. We could enhance clarity by referencing a shared enum or type for `status` if one exists, ensuring consistent usage across the codebase. Additionally, consider confirming how `reviewerId` maps to user entities elsewhere, so that integration points remain clear.

</blockquote></details>
<details>
<summary>apps/web/lib/validators/escrow.ts (1)</summary><blockquote>

`214-220`: **Consider normalizing milestone status casing**  
We notice that `'REJECTED'` is uppercase, while the other statuses (`'pending'`, `'approved'`, and `'completed'`) are lowercase. We could enhance readability and consistency by normalizing the casing or extracting these into a shared enum.

</blockquote></details>
<details>
<summary>apps/web/app/api/escrow/review/route.ts (3)</summary><blockquote>

`39-51`: **Verify reviewer authorization with authentication**  
We appreciate the direct validation against the `reviewers` table. We could enhance security by ensuring that the caller is also authenticated (e.g., using session data or tokens) and that `reviewerId` indeed matches the logged-in user. This approach helps guard against unauthorized updates.

---

`53-67`: **Consider wrapping updates in a transaction**  
Here, we update the milestone status, then insert comments and notifications in subsequent calls. We could enhance data integrity by wrapping these steps in a single transaction, so if any step fails, the entire operation is rolled back automatically.

---

`94-99`: **Extract and handle blockchain calls separately**  
We notice the TODO for releasing funds once a milestone is approved. We could enhance maintainability by abstracting this blockchain interaction into a dedicated service or queued process. This separation would keep the route handler lean and allow for more robust error handling and retries in case of on-chain delays.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b4b0da87c7955bad1e9b8fdc0c5d68181d36d874 and b63bcc0bf2d6538850817364f96dee1dcbeee075.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `bun.lockb` is excluded by `!**/bun.lockb`

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `apps/web/app/api/escrow/review/route.ts` (1 hunks)
* `apps/web/components/shared/kyc/kyc-2/kyc-2-upload.tsx` (1 hunks)
* `apps/web/hooks/kyc/use-document-validation.ts` (1 hunks)
* `apps/web/lib/types/escrow/escrow-payload.types.ts` (1 hunks)
* `apps/web/lib/validators/escrow.ts` (2 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (2)</summary>

* apps/web/hooks/kyc/use-document-validation.ts
* apps/web/components/shared/kyc/kyc-2/kyc-2-upload.tsx

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/*.ts`: Review TypeScript files ensuring type safety with...</summary>

> `**/*.ts`: Review TypeScript files ensuring type safety with no 'any' usage unless justified. Verify named exports, proper error handling with typed errors, and pure functions. Check module encapsulation and consistent naming using camelCase for functions and PascalCase for types. Validate unit test coverage for utilities if required.

- `apps/web/lib/types/escrow/escrow-payload.types.ts`
- `apps/web/app/api/escrow/review/route.ts`
- `apps/web/lib/validators/escrow.ts`

</details>
<details>
<summary>`apps/web/app/api/**/*.ts`: Review API routes ensuring prope...</summary>

> `apps/web/app/api/**/*.ts`: Review API routes ensuring proper input validation and error handling. Verify security measures including rate limiting and authentication. Check response formatting and error states.

- `apps/web/app/api/escrow/review/route.ts`

</details>

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-27T22:15:53Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-02-27T22:15:57Z
user: login: AndlerRL
body: Changes are looking good! Code looks clean and straight forward however, we miss to add one step of the process: The Escrow integration with the Trustless Work API. 

[In the code](https://github.com/kindfi-org/kindfi/blob/b87514748a6ceaf7eb5bde98bd73e2217aea1f52/apps/web/app/api/escrow/initialize/route.ts#L29) we have already a [few routes](https://github.com/kindfi-org/kindfi/blob/b21610fbdea972080d445d1b2c7d850a99a583ea/apps/web/app/api/escrow/fund/route.ts#L27) implementing them. Please take them a look!

Additionally, take a look into the Trustless Work API docs to know how to update a milestone. We always receive an unsigned trnx to finalize it as the fund route.

### TL;DR
This milestone review depends whether we decide to accept a milestone or not and, depending the state we will update but first on-chain and when transaction is completed, we update with the selected state coming from the body. A Passkey signature will be required to verify in the API route therefore, we have to prepare the body to receive the passkey credentials for verification once this is connected.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-28T07:46:06Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b63bcc0bf2d6538850817364f96dee1dcbeee075 and 65f77a3e14e722c0864ea644b2ae85efe276df95.

</details>

<details>
<summary>📒 Files selected for processing (9)</summary>

* `apps/web/components/featured/projects-grid.tsx` (2 hunks)
* `apps/web/components/sections/projects/projects-grid.tsx` (2 hunks)
* `apps/web/components/shared/project-card.tsx` (10 hunks)
* `apps/web/hooks/use-projects-filter.ts` (1 hunks)
* `apps/web/lib/mock-data/featured-projects/mock-featured-projets.ts` (4 hunks)
* `apps/web/lib/mock-data/mock-projects-view.tsx` (16 hunks)
* `apps/web/lib/types/featured-projects/featured-projects.types.ts` (1 hunks)
* `apps/web/lib/types/projects.types.ts` (1 hunks)
* `apps/web/lib/types/user-dashboard.types.ts` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (6)</summary>

* apps/web/lib/mock-data/mock-projects-view.tsx
* apps/web/lib/types/projects.types.ts
* apps/web/lib/mock-data/featured-projects/mock-featured-projets.ts
* apps/web/components/shared/project-card.tsx
* apps/web/lib/types/featured-projects/featured-projects.types.ts
* apps/web/hooks/use-projects-filter.ts

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (1)</summary>

<details>
<summary>`**/*.ts`: Review TypeScript files ensuring type safety with...</summary>

> `**/*.ts`: Review TypeScript files ensuring type safety with no 'any' usage unless justified. Verify named exports, proper error handling with typed errors, and pure functions. Check module encapsulation and consistent naming using camelCase for functions and PascalCase for types. Validate unit test coverage for utilities if required.

- `apps/web/lib/types/user-dashboard.types.ts`

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>apps/web/lib/types/user-dashboard.types.ts (1)</summary>

`2-2`: **Nice improvement to type imports!**

The change from a standard import to a type-only import enhances clarity by explicitly indicating `Tag` is used solely as a type. This aligns with TypeScript best practices and can help with tree-shaking during build optimization.

</details>
<details>
<summary>apps/web/components/featured/projects-grid.tsx (1)</summary>

`4-4`: **Good use of explicit type imports**

Great job using the `type` keyword when importing `Project`. This clarifies that it's being used only as a type, which enhances code readability and helps with optimization.

</details>
<details>
<summary>apps/web/components/sections/projects/projects-grid.tsx (2)</summary>

`2-2`: **Good type-only import**

Well done on using the explicit `type` keyword when importing the `Project` type. This follows TypeScript best practices and is consistent with the changes made in other files.

---

`9-9`: **Clean function signature formatting**

The simplified function signature improves code readability while maintaining the same functionality. This format works well for functions with a small number of parameters.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T08:41:42Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (6)</summary><blockquote>

<details>
<summary>apps/web/lib/types/escrow/escrow-payload.types.ts (1)</summary><blockquote>

`92-100`: **Consider refining naming for clarity**  
We could enhance readability by clarifying that `escrowContract` is the contract address if that’s the intended meaning. For example, renaming it to `escrowContractAddress` would make the domain intent more explicit. This change would require an update in all references to ensure consistency across the codebase.  


```diff
-  escrowContract: string
+  escrowContractAddress: string
```

</blockquote></details>
<details>
<summary>apps/web/app/api/escrow/review/route.ts (5)</summary><blockquote>

`13-15`: **Handle JSON parsing errors more gracefully**  
Consider catching and handling JSON parsing issues at this stage to return a more descriptive 400 response on malformed requests, rather than triggering the more generic 500 error. This would offer API consumers clearer feedback on how to fix their request.

---

`63-92`: **Evaluate transactional approach for partial failures**  
We could enhance reliability by wrapping the blockchain finalization and subsequent steps in a single orchestrated flow or compensating transaction. Currently, if the on-chain step succeeds but a later step fails, the system might be left in an inconsistent state.

---

`94-133`: **Use a single database transaction to avoid partial updates**  
When updating the milestone, adding comments, and sending notifications, grouping these in a single DB transaction best ensures atomicity. If any of these steps fail, rolling back would maintain data integrity.

---

`142-156`: **Enhance error handling with more specific logging**  
We could enrich error handling here by integrating a structured logger or service like Sentry. This would provide better traceability and insights into errors, helping reduce MTTR (mean time to resolution).

---

`11-157`: <details>
<summary>❓ Verification inconclusive</summary>

**Consider adding test coverage for the new route**  
Adding unit or integration tests for this newly introduced POST method would foster confidence that these DB operations and on-chain interactions function as intended.  


---

🏁 Script executed:

```shell
#!/bin/bash
# Description: Search for existing tests referencing the escrow review route
fd "test" | xargs rg "escrow/review"
```

Length of output: 34

---



</details>

**Enhancement Suggestion: Add Comprehensive Test Coverage for the New Route**

Great work on implementing the POST route with its DB and on-chain interactions! As the exploratory search didn’t yield any tests referencing this endpoint, please consider adding unit and integration tests to further bolster confidence in the implementation. In particular, we could enhance this by:

- **Validating Error Paths:**  
  - Verify that an invalid milestone ID returns a 404 error.
  - Confirm that an unauthorized reviewer leads to a 403 status.
  
- **Testing On-Chain Interactions:**  
  - Simulate conditions where signing fails or the unsigned transaction is missing, ensuring that appropriate errors are thrown.
  - Ensure the successful flow (for an approved status) properly finalizes the on-chain process and returns the expected transaction hash.
  
- **Verifying Database Operations:**  
  - Test that the milestone status updates correctly.
  - Confirm that review comments and notifications are inserted into the respective tables.

Such test scenarios will help guard against regressions and ensure that both the positive flows and failure conditions are handled gracefully. If you need any guidance setting up these tests, feel free to reach out.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 65f77a3e14e722c0864ea644b2ae85efe276df95 and 9a318b0c74fe5106eea932d0a743896c5f21a1f6.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `apps/web/app/api/escrow/review/route.ts` (1 hunks)
* `apps/web/lib/types/escrow/escrow-payload.types.ts` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/*.ts`: Review TypeScript files ensuring type safety with...</summary>

> `**/*.ts`: Review TypeScript files ensuring type safety with no 'any' usage unless justified. Verify named exports, proper error handling with typed errors, and pure functions. Check module encapsulation and consistent naming using camelCase for functions and PascalCase for types. Validate unit test coverage for utilities if required.

- `apps/web/lib/types/escrow/escrow-payload.types.ts`
- `apps/web/app/api/escrow/review/route.ts`

</details>
<details>
<summary>`apps/web/app/api/**/*.ts`: Review API routes ensuring prope...</summary>

> `apps/web/app/api/**/*.ts`: Review API routes ensuring proper input validation and error handling. Verify security measures including rate limiting and authentication. Check response formatting and error states.

- `apps/web/app/api/escrow/review/route.ts`

</details>

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T10:46:50Z
user: login: Bran18
body: Hey @0xdevcollins can you please check these things: 

- This branch is out-of-date with the base branch
- Commits must have verified signatures
- All AI comments must be resolved
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-03-02T19:08:31Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>apps/web/lib/validators/escrow.ts (1)</summary><blockquote>

`198-231`: **Consider standardizing status values casing for consistency**

The validation function looks well-structured and follows the established pattern in the file. I appreciate the thorough validation of each field with clear error messages. 

One observation: there's an inconsistency in the casing convention for status values. Other validators in this file use uppercase status values (e.g., 'PENDING', 'SUCCESSFUL', 'FAILED' on line 188), while this new function uses lowercase ('pending', 'approved', 'rejected', 'completed'). 



Consider standardizing the casing convention across all validators:

```diff
- if (!['pending', 'approved', 'rejected', 'completed'].includes(data.status)
+ if (!['PENDING', 'APPROVED', 'REJECTED', 'COMPLETED'].includes(data.status)
```

This would maintain consistency throughout the codebase and prevent potential errors when comparing status values.

</blockquote></details>
<details>
<summary>docs/component-usage-example.md (2)</summary><blockquote>

`105-106`: **Consider formatting the bare URL for better documentation**

The document contains a bare URL which could be improved by using proper Markdown link formatting.


Consider formatting the URL as a proper Markdown link:

```diff
- For more complex scenarios, such as integrating third-party libraries, the project employs components like react-dropzone for file uploads. The react-dropzone library provides a simple way to create an HTML5-compliant drag-and-drop zone for files. Documentation and examples are available at https://react-dropzone.js.org.
+ For more complex scenarios, such as integrating third-party libraries, the project employs components like react-dropzone for file uploads. The react-dropzone library provides a simple way to create an HTML5-compliant drag-and-drop zone for files. Documentation and examples are available at [https://react-dropzone.js.org](https://react-dropzone.js.org).
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

106-106: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

---

`198-198`: **Consider distinguishing the second "Usage" heading**

The document contains duplicate "Usage" headings, which could cause confusion for readers and navigation issues.


Consider making the second heading more specific to distinguish it from the first one:

```diff
- ### Usage
+ ### Usage in Projects Page
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

198-198: Multiple headings with the same content
null

(MD024, no-duplicate-heading)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9a318b0c74fe5106eea932d0a743896c5f21a1f6 and b0f7d8cda96694a00258e312288f5aec70ad9b63.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `apps/web/app/api/escrow/review/route.ts` (1 hunks)
* `apps/web/lib/types/escrow/escrow-payload.types.ts` (1 hunks)
* `apps/web/lib/validators/escrow.ts` (2 hunks)
* `docs/component-usage-example.md` (19 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* apps/web/lib/types/escrow/escrow-payload.types.ts
* apps/web/app/api/escrow/review/route.ts

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/*.ts`: Review TypeScript files ensuring type safety with...</summary>

> `**/*.ts`: Review TypeScript files ensuring type safety with no 'any' usage unless justified. Verify named exports, proper error handling with typed errors, and pure functions. Check module encapsulation and consistent naming using camelCase for functions and PascalCase for types. Validate unit test coverage for utilities if required.

- `apps/web/lib/validators/escrow.ts`

</details>
<details>
<summary>`**/*.md`: Review documentation for technical accuracy and c...</summary>

> `**/*.md`: Review documentation for technical accuracy and completeness. Verify code examples are correct and up-to-date. Ensure clear installation instructions and proper API documentation.

- `docs/component-usage-example.md`

</details>

</details><details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>docs/component-usage-example.md (1)</summary>

```
Learnt from: Bran18
PR: kindfi-org/kindfi#220
File: apps/web/components/base/button.tsx:5-5
Timestamp: 2025-02-27T03:14:18.241Z
Learning: The project uses the '~/' import convention rather than relative imports with '../' patterns.
```

</details>

</details><details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>docs/component-usage-example.md</summary>

106-106: Bare URL used
null

(MD034, no-bare-urls)

---

198-198: Multiple headings with the same content
null

(MD024, no-duplicate-heading)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (6)</summary><blockquote>

<details>
<summary>apps/web/lib/validators/escrow.ts (2)</summary>

`5-5`: **Great addition of the MilestoneReviewPayload type import**

The import looks good and follows the existing pattern in the file. Including specific type imports enhances type safety and makes the code more maintainable.

---

`223-225`: **The comments validation approach is well implemented**

Nice work on handling the optional comments field. The validation correctly allows for comments to be absent but ensures they're not empty strings when provided.

</details>
<details>
<summary>docs/component-usage-example.md (4)</summary>

`4-4`: **Good improvement to document formatting**

The added whitespace enhances readability by properly separating sections of the table of contents.

---

`23-25`: **Nice update to import syntax following project conventions**

The change to double quotes for imports aligns with the project's style conventions. I also appreciate seeing the use of the "~/" import convention rather than relative paths, which matches the project's established pattern as noted in the retrieved learnings.

---

`27-28`: **Well-formatted string definition in buttonVariants**

The update to double quotes and proper spacing in the buttonVariants definition improves readability and consistency in the codebase.

---

`264-264`: **Well-organized section transition with improved spacing**

The spacing added before the fetch request example enhances document readability by clearly separating different sections of the documentation.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T02:14:15Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>docs/component-usage-example.md (1)</summary><blockquote>

`269-277`: _💡 Verification agent_

<details>
<summary>❓ Verification inconclusive</summary>

**Correct Data Mapping in Fetch Request Example**  
In the fetch request example (lines 263–280), the fetched data is assigned to the `projects` variable. However, the JSX later maps over `state.projects` (line 273), which seems unintended. Consider updating to:
  
```diff
-        {state.projects.map((project) => (
+        {projects.map((project) => (
```  
  
This change ensures that the rendered list reflects the fetched projects.

---



</details>

**Attention: Correct Variable Mapping for Project Rendering**

We could enhance the fetch request example by ensuring consistency between the fetched data and the rendered list. In the file `docs/component-usage-example.md`, the fetched data is assigned to the `projects` variable, but the JSX later maps over `state.projects`. To ensure the rendered list reflects the correct data, please update the snippet as follows:

- **Change in Code Example:**
  ```diff
  -        {state.projects.map((project) => (
  +        {projects.map((project) => (
  ```

This update aligns the variable used for rendering with the variable that holds the fetched projects, eliminating potential confusion.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>docs/component-usage-example.md (4)</summary><blockquote>

`4-4`: **Improve TOC Formatting for Clarity**  
The change at line 4 (Table of Contents) appears to adjust the list formatting. Consider reviewing the rendered output to ensure that the TOC renders as expected across devices.

---

`167-170`: **Clear Messaging for Drag-and-Drop Feedback**  
The conditional message rendering for the dropzone (lines 167–170) is clear and user friendly. Consider adding ARIA attributes where appropriate to further enhance accessibility.

---

`106-106`: **Convert Bare URL to Markdown Link**  
The documentation at line 106 features a bare URL (`https://react-dropzone.js.org`). Consider converting it into a clickable Markdown link to enhance readability and compliance with Markdown linting rules. For example:
  
```diff
-Documentation and examples are available at https://react-dropzone.js.org.
+Documentation and examples are available at [https://react-dropzone.js.org](https://react-dropzone.js.org).
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

106-106: Bare URL used
null

(MD034, no-bare-urls)

</details>

</details>

---

`80-80`: **Avoid Duplicate Section Headings**  
There are multiple sections titled "### Usage" (e.g., at lines 80 and 195). To improve document navigation and reduce potential confusion, consider renaming these headings to more descriptive titles (for example, "Button Usage Example" and "ProjectMedia Usage Example").  



Also applies to: 195-195

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between b0f7d8cda96694a00258e312288f5aec70ad9b63 and 377bdb8e2757ab6554a018084bba31b416df537e.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `docs/component-usage-example.md` (19 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (1)</summary>

<details>
<summary>`**/*.md`: Review documentation for technical accuracy and c...</summary>

> `**/*.md`: Review documentation for technical accuracy and completeness. Verify code examples are correct and up-to-date. Ensure clear installation instructions and proper API documentation.

- `docs/component-usage-example.md`

</details>

</details><details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>docs/component-usage-example.md (1)</summary>

```
Learnt from: Bran18
PR: kindfi-org/kindfi#220
File: apps/web/components/base/button.tsx:5-5
Timestamp: 2025-02-27T03:14:18.241Z
Learning: The project uses the '~/' import convention rather than relative imports with '../' patterns.
```

</details>

</details><details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>docs/component-usage-example.md</summary>

106-106: Bare URL used
null

(MD034, no-bare-urls)

---

195-195: Multiple headings with the same content
null

(MD024, no-duplicate-heading)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (19)</summary><blockquote>

<details>
<summary>docs/component-usage-example.md (19)</summary>

`23-25`: **Consistent Import Statement Formatting**  
The updated import statements for the Button component (lines 23–25) now uniformly use double quotes and the tilde convention. This aligns with project best practices as noted in long-term learnings.

---

`32-39`: **Consistent Button Variant Styling**  
The variants defined in the `buttonVariants` object (lines 32–39) now use double quotes consistently. The styling values appear clear and well‑formatted.

---

`43-46`: **Uniform Size Variant Definitions**  
The size definitions for the button (lines 43–46) have been updated to maintain consistent string literal formatting, which improves readability.

---

`50-52`: **Clear Default Variants Configuration**  
The default variant settings (lines 50–52) are now uniformly formatted with double quotes. This ensures consistency throughout the component configuration.

---

`75-75`: **Proper Component Display Name Assignment**  
Assigning `Button.displayName` at line 75 is a good practice for debugging and clarity in React DevTools.

---

`84-84`: **Adherence to Tilde Import Convention**  
The updated import for the Button component in the usage example (line 84) correctly uses the `'~/'` convention, aligning with project guidelines.

---

`128-128`: **Clear Default Prop Assignment in ProjectMedia**  
Setting the default value for `videoUrl` to an empty string at line 128 enhances clarity regarding the expected prop type.

---

`143-145`: **Explicit Mime Type Definitions for File Uploads**  
The updates in the dropzone configuration (lines 143–145) explicitly define accepted file types using consistent double quotes. This makes the file acceptance criteria clear.

---

`160-163`: **Consistent Conditional Styling for Dropzone**  
The inline conditional for applying border and background classes (lines 160–163) is clearly structured and maintains consistent string formatting.

---

`199-207`: **Consistent Usage Example for ProjectMedia**  
The usage example for the ProjectMedia component (lines 199, 203, and 207) now uses the tilde import and clear console logs. The logging messages help trace user interactions.

---

`226-228`: **Correct Client-Side Configuration for State Management**  
Adding the `"use client";` directive (line 226) and updating the imports for context and reducer (line 228) ensure that the state management example behaves as a client component in Next.js.

---

`291-296`: **Enhanced Client-Side Form Component Setup**  
The ContributionForm component (lines 291, 293, and 296) now properly includes the `"use client";` directive and uses consistent state initialization. This setup is clear and concise.

---

`323-326`: **Effective Server Action Integration**  
The usage of the `ContributionForm` within the server action example (lines 323 and 326) is clear. The `"use server";` directive is appropriately applied inside the handler, ensuring the server action context is maintained.

---

`347-351`: **Robust KYC Service Payload Handling**  
The KYC service integration (lines 347–351 and 358) now uses clear FormData field appending with consistent string literals. The conditional inclusion of `documentBack` is correctly implemented.  



Also applies to: 358-358

---

`388-390`: **Improved AI Service Request Structure**  
The AI service integration now consistently applies the POST method with proper headers and error handling (lines 388, 390, and 396). This ensures that the API call is both secure and predictable.  



Also applies to: 396-396

---

`405-414`: **Consistent Supabase Client Setup and Schema Definition**  
The Supabase integration updates (lines 405–414) introduce uniform usage of double quotes and a clear definition of the `Campaign` interface, including the union type for `status`. This improves type safety and clarity.

---

`418-433`: **Streamlined Campaign Creation Flow**  
The `createCampaign` function (lines 418–433) presents clear method chaining with proper formatting. The diffused use of the tilde markers indicates clean-up in formatting; the logic appears sound.

---

`440-443`: **Clear Campaign Retrieval Query**  
The `getCampaign` function (lines 440–443) correctly structures its query with consistent syntax. The inline chaining ensures readability and operational correctness.

---

`453-458`: **Reliable Campaign Update Operation**  
The `updateCampaign` function (lines 453–458) uses a neat method chain for updating the database record. The updated chaining methods are consistent and maintain clarity throughout the process.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T02:24:26Z
user: login: coderabbitai[bot]
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T03:26:19Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>docs/component-usage-example.md (1)</summary><blockquote>

`263-279`: _🛠️ Refactor suggestion_

_⚠️ Potential issue_

**Syntax Correction Needed for Async Function Declaration**  
The function declaration on line 264 uses an incorrect syntax:  
```diff
-export default function async Page(){
+export default async function Page(){
```  
In JavaScript/TypeScript, the `async` keyword should come before `function`. This change is essential to ensure the function is properly recognized as asynchronous.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>docs/component-usage-example.md (2)</summary><blockquote>

`1-4`: **Improve Consistency in Table of Contents Formatting**  
The whitespace adjustment on line 4 helps ensure a more consistent layout in the Table of Contents.

---

`80-80`: **Consider Refining Duplicate Headings**  
There are multiple "Usage" headings in the document which might trigger markdown lint warnings (MD024). Consider renaming them to clarify context (e.g., "Button Usage" vs. "ProjectMedia Usage") to improve navigability and avoid potential confusion.  



Also applies to: 195-195

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 377bdb8e2757ab6554a018084bba31b416df537e and fa977a45efb7d5b37b7b095de78a89a57f155d90.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `docs/component-usage-example.md` (19 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (1)</summary>

<details>
<summary>`**/*.md`: Review documentation for technical accuracy and c...</summary>

> `**/*.md`: Review documentation for technical accuracy and completeness. Verify code examples are correct and up-to-date. Ensure clear installation instructions and proper API documentation.

- `docs/component-usage-example.md`

</details>

</details><details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>docs/component-usage-example.md (1)</summary>

```
Learnt from: Bran18
PR: kindfi-org/kindfi#220
File: apps/web/components/base/button.tsx:5-5
Timestamp: 2025-02-27T03:14:18.241Z
Learning: The project uses the '~/' import convention rather than relative imports with '../' patterns.
```

</details>

</details><details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>docs/component-usage-example.md</summary>

195-195: Multiple headings with the same content
null

(MD024, no-duplicate-heading)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (10)</summary><blockquote>

<details>
<summary>docs/component-usage-example.md (10)</summary>

`23-25`: **Consistent Button Component Implementation**  
The updated imports, string literal formatting, and configuration of variants and default values in the Button component now adhere nicely to our project conventions. The usage of the "~/..." import paths supports our established guidelines, and setting `Button.displayName` improves debuggability.  



Also applies to: 28-41, 43-47, 50-52, 64-64, 75-75

---

`80-100`: **Clear Button Usage Example**  
The usage section for the Button component is straightforward and well-documented, making it easy for developers to understand how to integrate the component.

---

`111-193`: **Enhanced ProjectMedia Component Example**  
The ProjectMedia component now includes the `"use client"` directive and consistent "~/..." imports which align with our standards. The conditional styling for the drag-and-drop state is clearly implemented, enhancing the user experience.

---

`195-218`: **Concise ProjectMedia Usage Example**  
The usage example for the ProjectMedia component is clearly presented. The updated console log messages effectively indicate file upload and video URL events, aiding in debugging.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

195-195: Multiple headings with the same content
null

(MD024, no-duplicate-heading)

</details>

</details>

---

`225-256`: **Effective State Management Example**  
The state management snippet using React Context is concise and demonstrates best practices well—especially with the inclusion of the `"use client"` directive and proper usage of React hooks.

---

`289-317`: **Solid Form Handling Example**  
The ContributionForm component clearly demonstrates client-side form handling using React state and event management. The changes are clean and follow our best practices.

---

`322-337`: **Well-Structured Server Action Example**  
The example showcasing server action usage is effective. The placement of the `"use server"` directive within the asynchronous function is clear and helps illustrate the integration of server components.

---

`344-370`: **Robust KYC Service Integration**  
The KYC integration snippet is well-structured, using FormData appropriately and ensuring error handling for the fetch request. The conditional inclusion of `documentBack` is clear and correct.

---

`373-399`: **Clear AI Service Integration Example**  
The AI service integration code uses proper JSON formatting, correct header configuration, and error checking. This implementation is easy to follow and well-aligned with our API practices.

---

`404-462`: **Solid Database Integration (Supabase) Practices**  
The Supabase integration section demonstrates best practices with type-safe client creation, appropriate usage of the query chain (`.select().single()`), and clear error handling in campaign operations.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T03:33:37Z
user: login: coderabbitai[bot]
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T03:33:40Z
user: login: AndlerRL
body: Thanks for you patience 🙏 after reviewing the PR all changes look very good! Very clean process on updating a milestone after review status verification. This is now ready for a merge!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-20T17:04:48Z

Review comments:
path: bun.lockb
user: login: AndlerRL
body: We can remove this file with `git rm --cache ./bun.lockb`. We are using now `bun.lock`, recently standardized at bun v1.2
created_at: 2025-02-28T07:12:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -24,8 +24,10 @@ export const ProjectsGrid: React.FC<ProjectsGridProps> = ({
 
 		// Apply filtering
 		if (filter !== 'all') {
-			result = result.filter(
-				(project) => project.category ? project.category.toLowerCase() === filter.toLowerCase() : "",
+			result = result.filter((project) =>
+				project.category
+					? project.category.toLowerCase() === filter.toLowerCase()
+					: '',
 			)
path: apps/web/components/featured/projects-grid.tsx
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Consider improving the filter logic**

The formatting improvements look good, but there's a potential logical issue with the ternary operator. When `project.category` is falsy, returning an empty string in a filter context could lead to unexpected behavior.


Consider revising to explicitly return a boolean:

```diff
result = result.filter((project) =>
	project.category
		? project.category.toLowerCase() === filter.toLowerCase()
-		: '',
+		: false,
)
```

This makes it clear that projects without a category will be excluded when filtering is applied.


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
			result = result.filter((project) =>
				project.category
					? project.category.toLowerCase() === filter.toLowerCase()
					: false,
			)
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-02T08:41:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -120,10 +125,10 @@ interface ProjectMediaProps {
 export function ProjectMedia({
   onFileUpload,
   onVideoUrlChange,
-  videoUrl = '',
+  videoUrl = "",
   onFileUpload,
   onVideoUrlChange,
-  videoUrl = '',
+  videoUrl = "",
 }: ProjectMediaProps) {
path: docs/component-usage-example.md
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Duplicated videoUrl default parameter needs to be removed**

There appears to be a duplication of the videoUrl parameter with default values in the ProjectMedia component destructuring.


Remove the duplicated parameter:

```diff
export function ProjectMedia({
  onFileUpload,
  onVideoUrlChange,
  videoUrl = "",
- onFileUpload,
- onVideoUrlChange,
- videoUrl = "",
}: ProjectMediaProps) {
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
export function ProjectMedia({
  onFileUpload,
  onVideoUrlChange,
  videoUrl = "",
}: ProjectMediaProps) {
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-03-05T02:14:13Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-02-27T08:21:51Z
body: [vc]: #K338o4AlRsCT2Rmu5VeYv4E13Qp9Bwg22z9x5oMwMjc=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJraW5kZmkiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20va2luZGZpL2tpbmRmaS81dkpTb253dlRQTGNjWU1NM0ZUS05HWUtvektnIiwicHJldmlld1VybCI6ImtpbmRmaS1naXQtZmVhdC01MC1pbXBsZW1lbnQtbWlsZXN0b25lLXJldmlldy1wcm9jZXNzLWtpbmRmaS52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImtpbmRmaS1naXQtZmVhdC01MC1pbXBsZW1lbnQtbWlsZXN0b25lLXJldmlldy1wcm9jZXNzLWtpbmRmaS52ZXJjZWwuYXBwIn0sInJvb3REaXJlY3RvcnkiOiJhcHBzL3dlYiJ9XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **kindfi** | ✅ Ready ([Inspect](https://vercel.com/kindfi/kindfi/5vJSonwvTPLccYMM3FTKNGYKozKg)) | [Visit Preview](https://kindfi-git-feat-50-implement-milestone-review-process-kindfi.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/kindfi-git-feat-50-implement-milestone-review-process-kindfi.vercel.app?via=pr-comment-feedback-link) | Mar 19, 2025 5:58pm |


author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-02-27T08:21:53Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request introduces a new POST endpoint for handling milestone reviews in the escrow system. The endpoint validates incoming JSON payloads, checks for milestone existence and reviewer authorization, and processes on-chain transactions if the review is approved. Additionally, it updates the milestone status, records review comments, and sends notifications. Supporting changes include the addition of a new payload interface and a validator function for milestone review data. Minor formatting updates were also made in a documentation file.

## Changes

| File / Files                                            | Change Summary                                                                                                                                                                                                                                                  |
|---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `apps/web/.../review/route.ts`                          | Added a new API POST route for milestone reviews. It validates the input, checks milestone existence and reviewer authorization, processes on-chain transactions, updates the DB, inserts review comments, and sends notifications.                                |
| `apps/web/.../escrow-payload.types.ts`                  | Introduced a new `MilestoneReviewPayload` interface detailing the data structure for milestone reviews, including properties like milestoneId, reviewerId, status, optional comments, signer, and escrowContractAddress.                                       |
| `apps/web/.../validators/escrow.ts`                     | Added the `validateMilestoneReview` function to validate milestone review payloads, ensuring required fields are provided and that the status matches one of the allowed values.                                                                                 |
| `docs/component-usage-example.md`                       | Made formatting changes for consistency, replacing single quotes with double quotes and adjusting whitespace for improved readability, without altering the underlying functionality shown in the examples.                                               |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant C as Client
    participant A as Milestone Review API
    participant V as Validator
    participant DB as Database
    participant Chain as On-Chain Service
    participant N as Notification Service

    C->>A: POST /api/escrow/review with JSON payload
    A->>V: validateMilestoneReview(payload)
    V-->>A: Validation result
    A->>DB: Check milestone existence
    DB-->>A: Milestone found / not found
    A->>DB: Check reviewer authorization
    DB-->>A: Reviewer authorized / not authorized
    alt Status is "approved"
        A->>Chain: Create & sign transaction
        Chain-->>A: Transaction result / error
    end
    A->>DB: Update milestone status
    A->>DB: Insert review comments
    A->>N: Send notification to user
    N-->>A: Notification result
    A-->>C: Return response with status and updated data
```

## Possibly related PRs
- **kindfi-org/kindfi#86**: The changes in this PR are related as both involve the introduction of new functions and interfaces for handling milestone reviews and escrow initialization, specifically through the use of the `MilestoneReviewPayload` and validation functions in the same validation module.

## Suggested reviewers
- Bran18
- AndlerRL

## Poem
> In lines of code that now align,  
> A pathway set for reviews divine!  
> Data validated with care and grace,  
> On-chain signed at a brisk pace.  
> Let these changes shine like a star 🌟,  
> CodeRabbit's art takes us far!  
> Cheers to progress, near and far!

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=kindfi-org/kindfi&utm_content=239):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: Bran18
created_at: 2025-02-28T20:53:04Z
body: @0xdevcollins hey do you need any help with the errors and the suggestions? 

CC. @AndlerRL 
author_association: MEMBER
user: login: 0xdevcollins
created_at: 2025-03-02T19:22:59Z
body: > Hey @0xdevcollins can you please check these things:
> 
> * This branch is out-of-date with the base branch
> * Commits must have verified signatures
> * All AI comments must be resolved

okay
author_association: CONTRIBUTOR
user: login: Bran18
created_at: 2025-03-04T21:37:14Z
body: @0xdevcollins can you please confirm if you’re planning to make the corrections so we can merge this before the ODB ends? If not, that's okay—we just need to know

CC. @AndlerRL 
author_association: MEMBER
user: login: 0xdevcollins
created_at: 2025-03-04T21:51:37Z
body: I will update the pr soon 
author_association: CONTRIBUTOR
user: login: 0xdevcollins
created_at: 2025-03-05T19:01:04Z
body: @Bran18 please check 
author_association: CONTRIBUTOR
user: login: AndlerRL
created_at: 2025-03-20T17:12:49Z
body: @coderabbitai I noticed that we are missing the review tables. These tables will handle the allowed reviewers (kindfi admin users) and the review comments, which are important if we want to keep communication clear and transparent. These reviews are related to project milestones. Please proceed to create the issues for each table creation and/or updates related with the project pitch and projects.
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-03-20T17:14:17Z
body: <!-- This is an auto-generated reply by CodeRabbit -->
> [!TIP]
> For best results, initiate chat on the files or code changes.

<details>
<summary>🧩 Analysis chain</summary>

🏁 Script executed:
```
#!/bin/bash
# First, let's look for database schema files or migration files
echo "=== Searching for database schema and migration files ==="
fd "schema|migration" --type f

# Look for references to review-related tables in the codebase
echo -e "\n=== Searching for references to review tables ==="
rg -i "reviewers|review_comments" --type sql

# Check if these tables are referenced in the code
echo -e "\n=== Checking code references to review tables ==="
rg -i "reviewers|review_comments" --type ts -A 3 -B 3
```

Length of output: 2079

---

🏁 Script executed:
```
#!/bin/bash
# Check the migration file that creates the project schema
echo "=== Migration File Content ==="
cat services/supabase/migrations/20250212015319_create_project_schema.sql

# Check the schema documentation
echo -e "\n=== Schema Documentation ==="
cat services/supabase/schema_docs/create_project_schema.md

# Look for any database schema references to reviewers or review_comments
echo -e "\n=== Database Schema TypeScript Definitions ==="
cat services/supabase/src/database.schemas.ts | grep -A 20 -B 20 "review\|Review"

# Let's also check if there are any other relevant SQL files we missed
echo -e "\n=== Other SQL files ==="
fd ".sql$" --type f
```

Length of output: 10412

---

🏁 Script executed:
```
#!/bin/bash
# Let's examine the migration file that might include escrow milestones and related tables
echo "=== Examining Escrow Milestones Migration File ==="
cat services/supabase/migrations/20250303172116_add_escrow_milestones_table_and_others.sql

# Also look at recent migrations that might have review-related tables
echo -e "\n=== Examining Recent Migrations ==="
cat services/supabase/migrations/20250305185613_create_project_members_table.sql

# Let's also check the API route that uses these tables to understand their expected structure
echo -e "\n=== Examining Escrow Review API Route ==="
cat apps/web/app/api/escrow/review/route.ts
```

Length of output: 11401

---

@AndlerRL I've examined the codebase and confirmed that we need to create the missing review tables. I'll create issues for each needed table.

---

🏁 Script executed:
```
#!/bin/bash
# Create issue for the reviewers table
echo "Creating issue for reviewers table..."
gh issue create \
  --title "Create 'reviewers' table for milestone reviews" \
  --body "## Overview
This issue addresses the need to create a 'reviewers' table to handle authorized KindFi admin users who can review project milestones.

## Background
The review system for project milestones is currently using a 'reviewers' table that doesn't exist in the database schema. The API route at \`apps/web/app/api/escrow/review/route.ts\` expects this table to validate if a reviewer is authorized.

## Requirements
1. Create a migration file to add the 'reviewers' table with appropriate columns:
   - id (UUID, primary key)
   - user_id (UUID, foreign key to auth.users)
   - role (TEXT or ENUM for different reviewer roles if needed)
   - created_at (TIMESTAMP)
   - additional fields as needed

2. Add appropriate Row Level Security (RLS) policies

3. Update database schema TypeScript definitions

## Related PR
This issue was identified in PR #239 (https://github.com/kindfi-org/kindfi/pull/239)" \
  --assignee "AndlerRL"

# Create issue for the review_comments table
echo "Creating issue for review_comments table..."
gh issue create \
  --title "Create 'review_comments' table for project milestone reviews" \
  --body "## Overview
This issue addresses the need to create a 'review_comments' table to store comments from reviewers about project milestones.

## Background
The review system for project milestones is currently using a 'review_comments' table that doesn't exist in the database schema. The API route at \`apps/web/app/api/escrow/review/route.ts\` attempts to insert review comments into this table.

## Requirements
1. Create a migration file to add the 'review_comments' table with appropriate columns:
   - id (UUID, primary key)
   - milestone_id (UUID, foreign key to escrow_milestones.id)
   - reviewer_id (UUID, foreign key to reviewers.id)
   - comments (TEXT)
   - created_at (TIMESTAMP)
   - additional fields as needed

2. Add appropriate Row Level Security (RLS) policies

3. Update database schema TypeScript definitions

## Related PR
This issue was identified in PR #239 (https://github.com/kindfi-org/kindfi/pull/239)" \
  --assignee "AndlerRL"
```

Length of output: 2386

---



</details>

@AndlerRL I've examined the codebase and created the requested issues for the missing review tables:

1. Created issue [#298](https://github.com/kindfi-org/kindfi/issues/298) for the `reviewers` table that will handle the allowed KindFi admin users who can review project milestones.

2. Created issue [#299](https://github.com/kindfi-org/kindfi/issues/299) for the `review_comments` table that will store reviewer feedback on milestones.

I confirmed these tables are currently being referenced in the code (specifically in `apps/web/app/api/escrow/review/route.ts`) but don't exist in the database schema. The PR #239 is attempting to use these tables for milestone review functionality, so creating them will be essential for transparency in project communications as you mentioned.

Both issues include detailed requirements for the necessary columns, foreign key relationships, and RLS policies. Let me know if you'd like any adjustments to these issues!
author_association: CONTRIBUTOR