Index: backend/connectionModel.js
===================================================================
--- backend/connectionModel.js	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ backend/connectionModel.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -45,10 +45,10 @@
 
 // Get My vehicles
-const getMyVehicles = async () => {
+const getMyVehicles = async (taxNr) => {
     try {
         return await new Promise(function (resolve, reject) {
             pool.query(
                 "SELECT * from vehicle where tax_nr=$1",
-                ["BM15153"],
+                [taxNr],
                 (error, results) => {
                     if (error) {
@@ -136,5 +136,27 @@
 };
 
-// Get single agreement
+// Register new dealership
+const registerDealership = async (body) => {
+    return new Promise(function (resolve, reject) {
+        const { tax_nr, d_name, brands, email, pass, director, telephones, addres } = body;
+
+        pool.query(
+            "INSERT INTO dealership (Tax_Nr, D_Name, Brands, Email, Pass, Director, Telephones, Addres) values ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *",
+            [tax_nr, d_name, brands, email, pass, director, telephones, addres],
+            (error, results) => {
+                if (error) {
+                    throw(error);
+                }
+                if (results && results.rows) {
+                    resolve(`Dealership account was created.`);
+                } else {
+                    throw(new Error("Not able to make new dealership account."));
+                }
+            }
+        );
+    });
+};
+
+// Get single agreement by VIN
 const getAgreement = async (slug) => {
     console.log(slug);
@@ -142,7 +164,456 @@
         return await new Promise(function (resolve, reject) {
             pool.query(
-                "SELECT * from agreement as a where a.vin=$1",
+                `SELECT a.*, v.make, v.model, v.p_year, v.color,
+                        c.c_name, c.embg, d.d_name
+                 FROM agreement a
+                 JOIN vehicle v ON a.vin = v.vin
+                 JOIN client c ON a.embg = c.embg
+                 JOIN dealership d ON a.tax_nr = d.tax_nr
+                 WHERE a.vin = $1`,
                 [slug],
-
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows) {
+                        resolve(results.rows);
+                    } else {
+                        reject(new Error("No results found"));
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Get single agreement by agreement ID
+const getAgreementById = async (agreementId) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                `SELECT a.*, v.make, v.model, v.p_year, v.color,
+                        c.c_name, c.embg, d.d_name
+                 FROM agreement a
+                 JOIN vehicle v ON a.vin = v.vin
+                 JOIN client c ON a.embg = c.embg
+                 JOIN dealership d ON a.tax_nr = d.tax_nr
+                 WHERE a.a_id = $1`,
+                [agreementId],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows && results.rows.length > 0) {
+                        resolve(results.rows[0]);
+                    } else {
+                        resolve(null);
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Get all agreements with payment status for a dealership
+const getDealershipAgreementsWithPaymentStatus = async (taxNr) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                `SELECT a.*, v.make, v.model, v.p_year, v.color,
+                        c.c_name, c.embg, d.d_name,
+                        CASE WHEN p.p_id IS NOT NULL THEN true ELSE false END as payment_exists,
+                        p.p_id, p.amount as payment_amount, p.bank, p.iban
+                 FROM agreement a
+                 JOIN vehicle v ON a.vin = v.vin
+                 JOIN client c ON a.embg = c.embg
+                 JOIN dealership d ON a.tax_nr = d.tax_nr
+                 LEFT JOIN payment p ON a.a_id = p.a_id
+                 WHERE a.tax_nr = $1
+                 ORDER BY a.datum DESC`,
+                [taxNr],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows) {
+                        resolve(results.rows);
+                    } else {
+                        resolve([]);
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Delete a vehicle
+const deleteVehicle = async (vin, taxNr) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            // First check if the vehicle belongs to the dealership and is not sold
+            pool.query(
+                `SELECT vin, status FROM vehicle WHERE vin = $1 AND tax_nr = $2`,
+                [vin, taxNr],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                        return;
+                    }
+                    
+                    if (!results.rows || results.rows.length === 0) {
+                        reject(new Error("Vehicle not found or you don't have permission to delete it"));
+                        return;
+                    }
+                    
+                    const vehicle = results.rows[0];
+                    if (vehicle.status === false) {
+                        reject(new Error("Cannot delete sold vehicles"));
+                        return;
+                    }
+                    
+                    // Delete the vehicle
+                    pool.query(
+                        `DELETE FROM vehicle WHERE vin = $1 AND tax_nr = $2`,
+                        [vin, taxNr],
+                        (deleteError, deleteResults) => {
+                            if (deleteError) {
+                                reject(deleteError);
+                            } else {
+                                resolve({ success: true, message: "Vehicle deleted successfully" });
+                            }
+                        }
+                    );
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Login dealership
+const loginDealership = async (email, password) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                "SELECT * FROM dealership WHERE email = $1 AND pass = $2",
+                [email, password],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows && results.rows.length > 0) {
+                        resolve(results.rows[0]);
+                    } else {
+                        resolve(null);
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Login client
+const loginClient = async (email, password) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                "SELECT * FROM client WHERE email = $1 AND pass = $2",
+                [email, password],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows && results.rows.length > 0) {
+                        resolve(results.rows[0]);
+                    } else {
+                        resolve(null);
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Create agreement
+const createAgreement = async (body) => {
+    return new Promise(function (resolve, reject) {
+        const {
+            A_Id,
+            Price,
+            Status,
+            Datum,
+            VIN,
+            EMBG,
+            Tax_Nr
+        } = body;
+        
+        pool.query(
+            "INSERT INTO agreement (A_Id, Price, Status, Datum, Tax_Nr, VIN, EMBG) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING *",
+            [A_Id, Price, Status, Datum, Tax_Nr, VIN, EMBG],
+            (error, results) => {
+                if (error) {
+                    reject(new Error("Not able to create agreement."));
+                }
+                if (results && results.rows) {
+                    // Update vehicle status to sold
+                    pool.query(
+                        "UPDATE vehicle SET status = false WHERE vin = $1",
+                        [VIN],
+                        (updateError, updateResults) => {
+                            if (updateError) {
+                                console.error("Error updating vehicle status:", updateError);
+                            }
+                        }
+                    );
+                    resolve(`Agreement created successfully.`);
+                } else {
+                    reject(new Error("Not able to create agreement."));
+                }
+            }
+        );
+    });
+};
+
+// Get client agreements
+const getClientAgreements = async (embg) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                `SELECT a.*, v.make, v.model, v.p_year, v.color, v.price as vehicle_price, 
+                        d.d_name as dealership_name,
+                        CASE WHEN p.p_id IS NOT NULL THEN true ELSE false END as payment_exists
+                 FROM agreement a 
+                 JOIN vehicle v ON a.vin = v.vin 
+                 JOIN dealership d ON a.tax_nr = d.tax_nr 
+                 LEFT JOIN payment p ON a.a_id = p.a_id
+                 WHERE a.embg = $1`,
+                [embg],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows) {
+                        resolve(results.rows);
+                    } else {
+                        reject(new Error("No results found"));
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Create payment
+const createPayment = async (body) => {
+    return new Promise(function (resolve, reject) {
+        const {
+            Bank,
+            IBAN,
+            Amount,
+            A_Id,
+            EMBG
+        } = body;
+        
+        pool.query(
+            "INSERT INTO payment (Bank, IBAN, Amount, EMBG, A_Id) VALUES ($1, $2, $3, $4, $5) RETURNING *",
+            [Bank, IBAN, Amount, EMBG, A_Id],
+            (error, results) => {
+                if (error) {
+                    reject(new Error("Not able to create payment."));
+                }
+                if (results && results.rows) {
+                    resolve(`Payment created successfully.`);
+                } else {
+                    reject(new Error("Not able to create payment."));
+                }
+            }
+        );
+    });
+};
+
+// Check if agreement has payment
+const checkAgreementPayment = async (aId) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                "SELECT * FROM payment WHERE a_id = $1",
+                [aId],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows && results.rows.length > 0) {
+                        resolve(true);
+                    } else {
+                        resolve(false);
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Get payment details for an agreement
+const getPaymentDetails = async (aId) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                `SELECT p.*, a.price as agreement_price, a.datum as agreement_date,
+                        v.vin, v.make, v.model, v.p_year, v.color,
+                        d.d_name as dealership_name,
+                        c.c_name as client_name
+                 FROM payment p
+                 JOIN agreement a ON p.a_id = a.a_id
+                 JOIN vehicle v ON a.vin = v.vin
+                 JOIN dealership d ON a.tax_nr = d.tax_nr
+                 JOIN client c ON a.embg = c.embg
+                 WHERE p.a_id = $1`,
+                [aId],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows && results.rows.length > 0) {
+                        resolve(results.rows[0]);
+                    } else {
+                        resolve(null);
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Get payment details by VIN
+const getPaymentDetailsByVin = async (vin) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                `SELECT p.*, a.price as agreement_price, a.datum as agreement_date,
+                        v.vin, v.make, v.model, v.p_year, v.color,
+                        d.d_name as dealership_name,
+                        c.c_name as client_name
+                 FROM payment p
+                 JOIN agreement a ON p.a_id = a.a_id
+                 JOIN vehicle v ON a.vin = v.vin
+                 JOIN dealership d ON a.tax_nr = d.tax_nr
+                 JOIN client c ON a.embg = c.embg
+                 WHERE v.vin = $1`,
+                [vin],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows && results.rows.length > 0) {
+                        resolve(results.rows[0]);
+                    } else {
+                        resolve(null);
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Get payments for a dealership (all payments for their agreements)
+const getDealershipPayments = async (taxNr) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                `SELECT p.*, a.price as agreement_price, a.datum as agreement_date,
+                        v.make, v.model, v.p_year, v.color,
+                        c.c_name as client_name, c.embg as client_embg
+                 FROM payment p
+                 JOIN agreement a ON p.a_id = a.a_id
+                 JOIN vehicle v ON a.vin = v.vin
+                 JOIN client c ON a.embg = c.embg
+                 WHERE a.tax_nr = $1
+                 ORDER BY p.p_id DESC`,
+                [taxNr],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows) {
+                        resolve(results.rows);
+                    } else {
+                        reject(new Error("No results found"));
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Get all agreements for a dealership
+const getDealershipAgreements = async (taxNr) => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                `SELECT a.*, v.make, v.model, v.p_year, v.color,
+                        c.c_name, c.embg, d.d_name
+                 FROM agreement a
+                 JOIN vehicle v ON a.vin = v.vin
+                 JOIN client c ON a.embg = c.embg
+                 JOIN dealership d ON a.tax_nr = d.tax_nr
+                 WHERE a.tax_nr = $1
+                 ORDER BY a.datum DESC`,
+                [taxNr],
+                (error, results) => {
+                    if (error) {
+                        reject(error);
+                    }
+                    if (results && results.rows) {
+                        resolve(results.rows);
+                    } else {
+                        reject(new Error("No results found"));
+                    }
+                }
+            );
+        });
+    } catch (error_1) {
+        console.error(error_1);
+        throw new Error("Internal server error");
+    }
+};
+
+// Get all dealerships (for debugging)
+const getAllDealerships = async () => {
+    try {
+        return await new Promise(function (resolve, reject) {
+            pool.query(
+                "SELECT tax_nr, d_name, email, pass FROM dealership",
                 (error, results) => {
                     if (error) {
@@ -167,5 +638,20 @@
     getMyVehicles,
     createVehicle,
+    deleteVehicle,
     registerUser,
+    registerDealership,
     getAgreement,
-};
+    getAgreementById,
+    getDealershipAgreementsWithPaymentStatus,
+    loginDealership,
+    loginClient,
+    createAgreement,
+    getClientAgreements,
+    createPayment,
+    checkAgreementPayment,
+    getPaymentDetails,
+    getPaymentDetailsByVin,
+    getDealershipPayments,
+    getDealershipAgreements,
+    getAllDealerships,
+};
Index: backend/cookies.txt
===================================================================
--- backend/cookies.txt	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/cookies.txt	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,5 @@
+# Netscape HTTP Cookie File
+# https://curl.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+#HttpOnly_localhost	FALSE	/	FALSE	1757023108	connect.sid	s%3AOQCKNMOJ-SQyKo3GJdTQmi1mEix0SLWS.HOYY453phBGbtjuYsU6NU7q3spU68OuWNQ0Z6m4zvX4
Index: backend/index.js
===================================================================
--- backend/index.js	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ backend/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -1,11 +1,21 @@
 const express = require("express");
 var cors = require("cors");
+const session = require("express-session");
 const app = express();
 const port = 3001;
 
+// Simple in-memory store for sessions
+const sessions = {};
+
 app.use(express.json());
+app.use(session({
+    secret: 'carzone-secret-key',
+    resave: true,
+    saveUninitialized: true,
+    cookie: { secure: false, maxAge: 24 * 60 * 60 * 1000 } // 24 hours
+}));
 
 app.use(function (req, res, next) {
-    res.setHeader("Access-Control-Allow-Origin", "*");
+    res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
     res.setHeader(
         "Access-Control-Allow-Methods",
@@ -16,4 +26,5 @@
         "Content-Type, Access-Control-Allow-Headers"
     );
+    res.setHeader("Access-Control-Allow-Credentials", "true");
     next();
 });
@@ -22,4 +33,41 @@
 const connection_model = require("./connectionModel");
 
+// Simple authentication middleware
+const requireAuth = (req, res, next) => {
+    const sessionId = req.sessionID;
+    const userSession = sessions[sessionId];
+    
+    if (userSession && userSession.userId && userSession.userType) {
+        req.user = userSession;
+        next();
+    } else {
+        res.status(401).json({ error: 'Unauthorized' });
+    }
+};
+
+const requireDealership = (req, res, next) => {
+    const sessionId = req.sessionID;
+    const userSession = sessions[sessionId];
+    
+    if (userSession && userSession.userType === 'dealership') {
+        req.user = userSession;
+        next();
+    } else {
+        res.status(401).json({ error: 'Unauthorized - Dealership access required' });
+    }
+};
+
+const requireClient = (req, res, next) => {
+    const sessionId = req.sessionID;
+    const userSession = sessions[sessionId];
+    
+    if (userSession && userSession.userType === 'client') {
+        req.user = userSession;
+        next();
+    } else {
+        res.status(401).json({ error: 'Unauthorized - Client access required' });
+    }
+};
+
 //Server requests start here
 
@@ -36,32 +84,149 @@
 });
 
-// For My list
-app.get("/mylist", (req, res) => {
-    connection_model
-        .getMyVehicles()
-        .then((response) => {
-            res.status(200).send(response);
-        })
-        .catch((error) => {
-            res.status(500).send(error);
-        });
-});
-
-// Not implemented
-/* app.post("/agreement", (req, res) => {
-    connection_model
-        .createAgreement(req.body)
-        .then((response) => {
-            res.status(200).send(response);
-        })
-        .catch((error) => {
-            res.status(500).send(error);
-        });
-}); */
-
-// For create vehicle POST method
-app.post("/createvehicle", (req, res) => {
-    connection_model
-        .createVehicle(req.body)
+// Authentication endpoints
+app.post("/login/dealership", (req, res) => {
+    const { email, pass } = req.body;
+
+    connection_model
+        .loginDealership(email, pass)
+        .then((response) => {
+            if (response) {
+                // Store session data in our in-memory store
+                const sessionId = req.sessionID;
+                sessions[sessionId] = {
+                    userId: response.tax_nr,
+                    userType: 'dealership',
+                    userName: response.d_name
+                };
+                
+                res.status(200).json({ success: true, user: response });
+            } else {
+
+                res.status(401).json({ success: false, message: 'Invalid credentials' });
+            }
+        })
+        .catch((error) => {
+            res.status(500).json({ success: false, message: 'Server error' });
+        });
+});
+
+app.post("/login/client", (req, res) => {
+    const { email, pass } = req.body;
+    connection_model
+        .loginClient(email, pass)
+        .then((response) => {
+            if (response) {
+                // Store session data in our in-memory store
+                const sessionId = req.sessionID;
+                sessions[sessionId] = {
+                    userId: response.embg,
+                    userType: 'client',
+                    userName: response.c_name
+                };
+                
+                res.status(200).json({ success: true, user: response });
+            } else {
+                res.status(401).json({ success: false, message: 'Invalid credentials' });
+            }
+        })
+        .catch((error) => {
+            res.status(500).json({ success: false, message: 'Server error' });
+        });
+});
+
+app.post("/logout", (req, res) => {
+    const sessionId = req.sessionID;
+    delete sessions[sessionId];
+    req.session.destroy((err) => {
+        if (err) {
+            res.status(500).json({ success: false, message: 'Could not log out' });
+        } else {
+            res.status(200).json({ success: true, message: 'Logged out successfully' });
+        }
+    });
+});
+
+app.get("/auth/status", (req, res) => {
+    const sessionId = req.sessionID;
+    const userSession = sessions[sessionId];
+    
+    if (userSession && userSession.userId && userSession.userType) {
+        res.status(200).json({
+            loggedIn: true,
+            userId: userSession.userId,
+            userType: userSession.userType,
+            userName: userSession.userName
+        });
+    } else {
+        res.status(200).json({ loggedIn: false });
+    }
+});
+
+
+
+// For My list - now requires dealership authentication
+app.get("/mylist", requireDealership, (req, res) => {
+    connection_model
+        .getMyVehicles(req.user.userId)
+        .then((response) => {
+            res.status(200).send(response);
+        })
+        .catch((error) => {
+            res.status(500).send(error);
+        });
+});
+
+// Create agreement - requires dealership authentication
+app.post("/agreement", requireDealership, (req, res) => {
+    const agreementData = {
+        ...req.body,
+        Tax_Nr: req.user.userId
+    };
+    connection_model
+        .createAgreement(agreementData)
+        .then((response) => {
+            res.status(200).send(response);
+        })
+        .catch((error) => {
+            res.status(500).send(error);
+        });
+});
+
+// Get client agreements - requires client authentication
+app.get("/client/agreements", requireClient, (req, res) => {
+    connection_model
+        .getClientAgreements(req.user.userId)
+        .then((response) => {
+            res.status(200).send(response);
+        })
+        .catch((error) => {
+            res.status(500).send(error);
+        });
+});
+
+// Create payment - requires client authentication
+app.post("/payment", requireClient, (req, res) => {
+    const paymentData = {
+        ...req.body,
+        EMBG: req.user.userId
+    };
+    connection_model
+        .createPayment(paymentData)
+        .then((response) => {
+            res.status(200).send(response);
+        })
+        .catch((error) => {
+            res.status(500).send(error);
+        });
+});
+
+// For create vehicle POST method - requires dealership authentication
+app.post("/createvehicle", requireDealership, (req, res) => {
+    const vehicleData = {
+        ...req.body,
+        tax_nr: req.user.userId
+    };
+    connection_model
+        .createVehicle(vehicleData)
         .then((response) => {
             res.status(200).send(response);
@@ -84,4 +249,101 @@
 });
 
+// For register new dealership POST
+app.post("/registerdealership", (req, res) => {
+    connection_model
+        .registerDealership(req.body)
+        .then((response) => {
+            res.status(200).send(response);
+        })
+        .catch((error) => {
+            res.status(500).send(error);
+        });
+});
+
+// Get payment details for an agreement
+app.get("/payment/:agreementId", (req, res) => {
+    const { agreementId } = req.params;
+    connection_model
+        .getPaymentDetails(agreementId)
+        .then((response) => {
+            if (response) {
+                res.status(200).json(response);
+            } else {
+                res.status(404).json({ error: 'Payment not found' });
+            }
+        })
+        .catch((error) => {
+            res.status(500).json({ error: error.message });
+        });
+});
+
+// Get payment details by VIN
+app.get("/payment/vin/:vin", (req, res) => {
+    const { vin } = req.params;
+    connection_model
+        .getPaymentDetailsByVin(vin)
+        .then((response) => {
+            if (response) {
+                res.status(200).json(response);
+            } else {
+                res.status(404).json({ error: 'Payment not found' });
+            }
+        })
+        .catch((error) => {
+            res.status(500).json({ error: error.message });
+        });
+});
+
+// Get all payments for a dealership
+app.get("/dealership/payments", requireDealership, (req, res) => {
+    connection_model
+        .getDealershipPayments(req.user.userId)
+        .then((response) => {
+            res.status(200).json(response);
+        })
+        .catch((error) => {
+            res.status(500).json({ error: error.message });
+        });
+});
+
+// Get all agreements for a dealership
+app.get("/dealership/agreements", requireDealership, (req, res) => {
+    connection_model
+        .getDealershipAgreements(req.user.userId)
+        .then((response) => {
+            res.status(200).json(response);
+        })
+        .catch((error) => {
+            res.status(500).json({ error: error.message });
+        });
+});
+
+// Get all agreements with payment status for a dealership
+app.get("/dealership/agreements-with-payments", requireDealership, (req, res) => {
+    connection_model
+        .getDealershipAgreementsWithPaymentStatus(req.user.userId)
+        .then((response) => {
+            res.status(200).json(response);
+        })
+        .catch((error) => {
+            res.status(500).json({ error: error.message });
+        });
+});
+
+// Delete a vehicle
+app.delete("/vehicle/:vin", requireDealership, (req, res) => {
+    const { vin } = req.params;
+    const taxNr = req.user.userId;
+    
+    connection_model
+        .deleteVehicle(vin, taxNr)
+        .then((response) => {
+            res.status(200).json(response);
+        })
+        .catch((error) => {
+            res.status(400).json({ error: error.message });
+        });
+});
+
 // To get single agreement based on slug passed
 app.get("/agreement/:slug", (req, res) => {
@@ -96,4 +358,20 @@
 });
 
+// Get agreement by agreement ID
+app.get("/agreement/id/:agreementId", (req, res) => {
+    connection_model
+        .getAgreementById(req.params.agreementId)
+        .then((response) => {
+            if (response) {
+                res.status(200).json(response);
+            } else {
+                res.status(404).json({ error: 'Agreement not found' });
+            }
+        })
+        .catch((error) => {
+            res.status(500).json({ error: error.message });
+        });
+});
+
 app.listen(port, () => {
     console.log(`App running on port ${port}.`);
Index: backend/node_modules/.package-lock.json
===================================================================
--- backend/node_modules/.package-lock.json	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ backend/node_modules/.package-lock.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -333,4 +333,35 @@
       }
     },
+    "node_modules/express-session": {
+      "version": "1.18.2",
+      "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz",
+      "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==",
+      "dependencies": {
+        "cookie": "0.7.2",
+        "cookie-signature": "1.0.7",
+        "debug": "2.6.9",
+        "depd": "~2.0.0",
+        "on-headers": "~1.1.0",
+        "parseurl": "~1.3.3",
+        "safe-buffer": "5.2.1",
+        "uid-safe": "~2.1.5"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/express-session/node_modules/cookie": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+      "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/express-session/node_modules/cookie-signature": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+      "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="
+    },
     "node_modules/fill-range": {
       "version": "7.1.1",
@@ -730,4 +761,12 @@
       }
     },
+    "node_modules/on-headers": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
+      "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/packet-reader": {
       "version": "1.0.0",
@@ -908,4 +947,12 @@
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/random-bytes": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+      "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==",
+      "engines": {
+        "node": ">= 0.8"
       }
     },
@@ -1141,4 +1188,15 @@
       }
     },
+    "node_modules/uid-safe": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
+      "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
+      "dependencies": {
+        "random-bytes": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/undefsafe": {
       "version": "2.0.5",
Index: backend/node_modules/express-session/HISTORY.md
===================================================================
--- backend/node_modules/express-session/HISTORY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/HISTORY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,476 @@
+1.18.2 / 2025-07-17
+==========
+  * deps: mocha@10.8.2
+  * deps: on-headers@~1.1.0
+    - Fix [CVE-2025-7339](https://www.cve.org/CVERecord?id=CVE-2025-7339) ([GHSA-76c9-3jph-rj3q](https://github.com/expressjs/on-headers/security/advisories/GHSA-76c9-3jph-rj3q))
+
+1.18.1 / 2024-10-08
+==========
+
+  * deps: cookie@0.7.2
+    - Fix object assignment of `hasOwnProperty`
+  * deps: cookie@0.7.1
+    - Allow leading dot for domain
+      - Although not permitted in the spec, some users expect this to work and user agents ignore the leading dot according to spec
+    - Add fast path for `serialize` without options, use `obj.hasOwnProperty` when parsing
+  * deps: cookie@0.7.0
+    - perf: parse cookies ~10% faster
+    - fix: narrow the validation of cookies to match RFC6265
+    - fix: add `main` to `package.json` for rspack
+
+1.18.0 / 2024-01-28
+===================
+
+  * Add debug log for pathname mismatch
+  * Add `partitioned` to `cookie` options
+  * Add `priority` to `cookie` options
+  * Fix handling errors from setting cookie
+  * Support any type in `secret` that `crypto.createHmac` supports
+  * deps: cookie@0.6.0
+    - Fix `expires` option to reject invalid dates
+    - perf: improve default decode speed
+    - perf: remove slow string split in parse
+  * deps: cookie-signature@1.0.7
+
+1.17.3 / 2022-05-11
+===================
+
+  * Fix resaving already-saved new session at end of request
+  * deps: cookie@0.4.2
+
+1.17.2 / 2021-05-19
+===================
+
+  * Fix `res.end` patch to always commit headers
+  * deps: cookie@0.4.1
+  * deps: safe-buffer@5.2.1
+
+1.17.1 / 2020-04-16
+===================
+
+  * Fix internal method wrapping error on failed reloads
+
+1.17.0 / 2019-10-10
+===================
+
+  * deps: cookie@0.4.0
+    - Add `SameSite=None` support
+  * deps: safe-buffer@5.2.0
+
+1.16.2 / 2019-06-12
+===================
+
+  * Fix restoring `cookie.originalMaxAge` when store returns `Date`
+  * deps: parseurl@~1.3.3
+
+1.16.1 / 2019-04-11
+===================
+
+  * Fix error passing `data` option to `Cookie` constructor
+  * Fix uncaught error from bad session data
+
+1.16.0 / 2019-04-10
+===================
+
+  * Catch invalid `cookie.maxAge` value earlier
+  * Deprecate setting `cookie.maxAge` to a `Date` object
+  * Fix issue where `resave: false` may not save altered sessions
+  * Remove `utils-merge` dependency
+  * Use `safe-buffer` for improved Buffer API
+  * Use `Set-Cookie` as cookie header name for compatibility
+  * deps: depd@~2.0.0
+    - Replace internal `eval` usage with `Function` constructor
+    - Use instance methods on `process` to check for listeners
+    - perf: remove argument reassignment
+  * deps: on-headers@~1.0.2
+    - Fix `res.writeHead` patch missing return value
+
+1.15.6 / 2017-09-26
+===================
+
+  * deps: debug@2.6.9
+  * deps: parseurl@~1.3.2
+    - perf: reduce overhead for full URLs
+    - perf: unroll the "fast-path" `RegExp`
+  * deps: uid-safe@~2.1.5
+    - perf: remove only trailing `=`
+  * deps: utils-merge@1.0.1
+
+1.15.5 / 2017-08-02
+===================
+
+  * Fix `TypeError` when `req.url` is an empty string
+  * deps: depd@~1.1.1
+    - Remove unnecessary `Buffer` loading
+
+1.15.4 / 2017-07-18
+===================
+
+  * deps: debug@2.6.8
+
+1.15.3 / 2017-05-17
+===================
+
+  * deps: debug@2.6.7
+    - deps: ms@2.0.0
+
+1.15.2 / 2017-03-26
+===================
+
+  * deps: debug@2.6.3
+    - Fix `DEBUG_MAX_ARRAY_LENGTH`
+  * deps: uid-safe@~2.1.4
+    - Remove `base64-url` dependency
+
+1.15.1 / 2017-02-10
+===================
+
+  * deps: debug@2.6.1
+    - Fix deprecation messages in WebStorm and other editors
+    - Undeprecate `DEBUG_FD` set to `1` or `2`
+
+1.15.0 / 2017-01-22
+===================
+
+  * Fix detecting modified session when session contains "cookie" property
+  * Fix resaving already-saved reloaded session at end of request
+  * deps: crc@3.4.4
+    - perf: use `Buffer.from` when available
+  * deps: debug@2.6.0
+    - Allow colors in workers
+    - Deprecated `DEBUG_FD` environment variable
+    - Use same color for same namespace
+    - Fix error when running under React Native
+    - deps: ms@0.7.2
+  * perf: remove unreachable branch in set-cookie method
+
+1.14.2 / 2016-10-30
+===================
+
+  * deps: crc@3.4.1
+    - Fix deprecation warning in Node.js 7.x
+  * deps: uid-safe@~2.1.3
+    - deps: base64-url@1.3.3
+
+1.14.1 / 2016-08-24
+===================
+
+  * Fix not always resetting session max age before session save
+  * Fix the cookie `sameSite` option to actually alter the `Set-Cookie`
+  * deps: uid-safe@~2.1.2
+    - deps: base64-url@1.3.2
+
+1.14.0 / 2016-07-01
+===================
+
+  * Correctly inherit from `EventEmitter` class in `Store` base class
+  * Fix issue where `Set-Cookie` `Expires` was not always updated
+  * Methods are no longer enumerable on `req.session` object
+  * deps: cookie@0.3.1
+    - Add `sameSite` option
+    - Improve error message when `encode` is not a function
+    - Improve error message when `expires` is not a `Date`
+    - perf: enable strict mode
+    - perf: use for loop in parse
+    - perf: use string concatenation for serialization
+  * deps: parseurl@~1.3.1
+    - perf: enable strict mode
+  * deps: uid-safe@~2.1.1
+    - Use `random-bytes` for byte source
+    - deps: base64-url@1.2.2
+  * perf: enable strict mode
+  * perf: remove argument reassignment
+
+1.13.0 / 2016-01-10
+===================
+
+  * Fix `rolling: true` to not set cookie when no session exists
+    - Better `saveUninitialized: false` + `rolling: true` behavior
+  * deps: crc@3.4.0
+
+1.12.1 / 2015-10-29
+===================
+
+  * deps: cookie@0.2.3
+    - Fix cookie `Max-Age` to never be a floating point number
+
+1.12.0 / 2015-10-25
+===================
+
+  * Support the value `'auto'` in the `cookie.secure` option
+  * deps: cookie@0.2.2
+    - Throw on invalid values provided to `serialize`
+  * deps: depd@~1.1.0
+    - Enable strict mode in more places
+    - Support web browser loading
+  * deps: on-headers@~1.0.1
+    - perf: enable strict mode
+
+1.11.3 / 2015-05-22
+===================
+
+  * deps: cookie@0.1.3
+    - Slight optimizations
+  * deps: crc@3.3.0
+
+1.11.2 / 2015-05-10
+===================
+
+  * deps: debug@~2.2.0
+    - deps: ms@0.7.1
+  * deps: uid-safe@~2.0.0
+
+1.11.1 / 2015-04-08
+===================
+
+  * Fix mutating `options.secret` value
+
+1.11.0 / 2015-04-07
+===================
+
+  * Support an array in `secret` option for key rotation
+  * deps: depd@~1.0.1
+
+1.10.4 / 2015-03-15
+===================
+
+  * deps: debug@~2.1.3
+    - Fix high intensity foreground color for bold
+    - deps: ms@0.7.0
+
+1.10.3 / 2015-02-16
+===================
+
+  * deps: cookie-signature@1.0.6
+  * deps: uid-safe@1.1.0
+    - Use `crypto.randomBytes`, if available
+    - deps: base64-url@1.2.1
+
+1.10.2 / 2015-01-31
+===================
+
+  * deps: uid-safe@1.0.3
+    - Fix error branch that would throw
+    - deps: base64-url@1.2.0
+
+1.10.1 / 2015-01-08
+===================
+
+  * deps: uid-safe@1.0.2
+    - Remove dependency on `mz`
+
+1.10.0 / 2015-01-05
+===================
+
+  * Add `store.touch` interface for session stores
+  * Fix `MemoryStore` expiration with `resave: false`
+  * deps: debug@~2.1.1
+
+1.9.3 / 2014-12-02
+==================
+
+  * Fix error when `req.sessionID` contains a non-string value
+
+1.9.2 / 2014-11-22
+==================
+
+  * deps: crc@3.2.1
+    - Minor fixes
+
+1.9.1 / 2014-10-22
+==================
+
+  * Remove unnecessary empty write call
+    - Fixes Node.js 0.11.14 behavior change
+    - Helps work-around Node.js 0.10.1 zlib bug
+
+1.9.0 / 2014-09-16
+==================
+
+  * deps: debug@~2.1.0
+    - Implement `DEBUG_FD` env variable support
+  * deps: depd@~1.0.0
+
+1.8.2 / 2014-09-15
+==================
+
+  * Use `crc` instead of `buffer-crc32` for speed
+  * deps: depd@0.4.5
+
+1.8.1 / 2014-09-08
+==================
+
+  * Keep `req.session.save` non-enumerable
+  * Prevent session prototype methods from being overwritten
+
+1.8.0 / 2014-09-07
+==================
+
+  * Do not resave already-saved session at end of request
+  * deps: cookie-signature@1.0.5
+  * deps: debug@~2.0.0
+
+1.7.6 / 2014-08-18
+==================
+
+  * Fix exception on `res.end(null)` calls
+
+1.7.5 / 2014-08-10
+==================
+
+  * Fix parsing original URL
+  * deps: on-headers@~1.0.0
+  * deps: parseurl@~1.3.0
+
+1.7.4 / 2014-08-05
+==================
+
+  * Fix response end delay for non-chunked responses
+
+1.7.3 / 2014-08-05
+==================
+
+  * Fix `res.end` patch to call correct upstream `res.write`
+
+1.7.2 / 2014-07-27
+==================
+
+  * deps: depd@0.4.4
+    - Work-around v8 generating empty stack traces
+
+1.7.1 / 2014-07-26
+==================
+
+  * deps: depd@0.4.3
+    - Fix exception when global `Error.stackTraceLimit` is too low
+
+1.7.0 / 2014-07-22
+==================
+
+  * Improve session-ending error handling
+    - Errors are passed to `next(err)` instead of `console.error`
+  * deps: debug@1.0.4
+  * deps: depd@0.4.2
+    - Add `TRACE_DEPRECATION` environment variable
+    - Remove non-standard grey color from color output
+    - Support `--no-deprecation` argument
+    - Support `--trace-deprecation` argument
+
+1.6.5 / 2014-07-11
+==================
+
+  * Do not require `req.originalUrl`
+  * deps: debug@1.0.3
+    - Add support for multiple wildcards in namespaces
+
+1.6.4 / 2014-07-07
+==================
+
+  * Fix blank responses for stores with synchronous operations
+
+1.6.3 / 2014-07-04
+==================
+
+  * Fix resave deprecation message
+
+1.6.2 / 2014-07-04
+==================
+
+  * Fix confusing option deprecation messages
+
+1.6.1 / 2014-06-28
+==================
+
+  * Fix saveUninitialized deprecation message
+
+1.6.0 / 2014-06-28
+==================
+
+  * Add deprecation message to undefined `resave` option
+  * Add deprecation message to undefined `saveUninitialized` option
+  * Fix `res.end` patch to return correct value
+  * Fix `res.end` patch to handle multiple `res.end` calls
+  * Reject cookies with missing signatures
+
+1.5.2 / 2014-06-26
+==================
+
+  * deps: cookie-signature@1.0.4
+    - fix for timing attacks
+
+1.5.1 / 2014-06-21
+==================
+
+  * Move hard-to-track-down `req.secret` deprecation message
+
+1.5.0 / 2014-06-19
+==================
+
+  * Debug name is now "express-session"
+  * Deprecate integration with `cookie-parser` middleware
+  * Deprecate looking for secret in `req.secret`
+  * Directly read cookies; `cookie-parser` no longer required
+  * Directly set cookies; `res.cookie` no longer required
+  * Generate session IDs with `uid-safe`, faster and even less collisions
+
+1.4.0 / 2014-06-17
+==================
+
+  * Add `genid` option to generate custom session IDs
+  * Add `saveUninitialized` option to control saving uninitialized sessions
+  * Add `unset` option to control unsetting `req.session`
+  * Generate session IDs with `rand-token` by default; reduce collisions
+  * deps: buffer-crc32@0.2.3
+
+1.3.1 / 2014-06-14
+==================
+
+  * Add description in package for npmjs.org listing
+
+1.3.0 / 2014-06-14
+==================
+
+  * Integrate with express "trust proxy" by default
+  * deps: debug@1.0.2
+
+1.2.1 / 2014-05-27
+==================
+
+  * Fix `resave` such that `resave: true` works
+
+1.2.0 / 2014-05-19
+==================
+
+  * Add `resave` option to control saving unmodified sessions
+
+1.1.0 / 2014-05-12
+==================
+
+  * Add `name` option; replacement for `key` option
+  * Use `setImmediate` in MemoryStore for node.js >= 0.10
+
+1.0.4 / 2014-04-27
+==================
+
+  * deps: debug@0.8.1
+
+1.0.3 / 2014-04-19
+==================
+
+  *  Use `res.cookie()` instead of `res.setHeader()`
+  * deps: cookie@0.1.2
+
+1.0.2 / 2014-02-23
+==================
+
+  * Add missing dependency to `package.json`
+
+1.0.1 / 2014-02-15
+==================
+
+  * Add missing dependencies to `package.json`
+
+1.0.0 / 2014-02-15
+==================
+
+  * Genesis from `connect`
Index: backend/node_modules/express-session/LICENSE
===================================================================
--- backend/node_modules/express-session/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2010 Sencha Inc.
+Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
+Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: backend/node_modules/express-session/README.md
===================================================================
--- backend/node_modules/express-session/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,1032 @@
+# express-session
+
+[![NPM Version][npm-version-image]][npm-url]
+[![NPM Downloads][npm-downloads-image]][node-url]
+[![Build Status][ci-image]][ci-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install express-session
+```
+
+## API
+
+```js
+var session = require('express-session')
+```
+
+### session(options)
+
+Create a session middleware with the given `options`.
+
+**Note** Session data is _not_ saved in the cookie itself, just the session ID.
+Session data is stored server-side.
+
+**Note** Since version 1.5.0, the [`cookie-parser` middleware](https://www.npmjs.com/package/cookie-parser)
+no longer needs to be used for this module to work. This module now directly reads
+and writes cookies on `req`/`res`. Using `cookie-parser` may result in issues
+if the `secret` is not the same between this module and `cookie-parser`.
+
+**Warning** The default server-side session storage, `MemoryStore`, is _purposely_
+not designed for a production environment. It will leak memory under most
+conditions, does not scale past a single process, and is meant for debugging and
+developing.
+
+For a list of stores, see [compatible session stores](#compatible-session-stores).
+
+#### Options
+
+`express-session` accepts these properties in the options object.
+
+##### cookie
+
+Settings object for the session ID cookie. The default value is
+`{ path: '/', httpOnly: true, secure: false, maxAge: null }`.
+
+The following are options that can be set in this object.
+
+##### cookie.domain
+
+Specifies the value for the `Domain` `Set-Cookie` attribute. By default, no domain
+is set, and most clients will consider the cookie to apply to only the current
+domain.
+
+##### cookie.expires
+
+Specifies the `Date` object to be the value for the `Expires` `Set-Cookie` attribute.
+By default, no expiration is set, and most clients will consider this a
+"non-persistent cookie" and will delete it on a condition like exiting a web browser
+application.
+
+**Note** If both `expires` and `maxAge` are set in the options, then the last one
+defined in the object is what is used.
+
+**Note** The `expires` option should not be set directly; instead only use the `maxAge`
+option.
+
+##### cookie.httpOnly
+
+Specifies the `boolean` value for the `HttpOnly` `Set-Cookie` attribute. When truthy,
+the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly`
+attribute is set.
+
+**Note** be careful when setting this to `true`, as compliant clients will not allow
+client-side JavaScript to see the cookie in `document.cookie`.
+
+##### cookie.maxAge
+
+Specifies the `number` (in milliseconds) to use when calculating the `Expires`
+`Set-Cookie` attribute. This is done by taking the current server time and adding
+`maxAge` milliseconds to the value to calculate an `Expires` datetime. By default,
+no maximum age is set.
+
+**Note** If both `expires` and `maxAge` are set in the options, then the last one
+defined in the object is what is used.
+
+##### cookie.partitioned
+
+Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies)
+attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not.
+By default, the `Partitioned` attribute is not set.
+
+**Note** This is an attribute that has not yet been fully standardized, and may
+change in the future. This also means many clients may ignore this attribute until
+they understand it.
+
+More information about can be found in [the proposal](https://github.com/privacycg/CHIPS).
+
+##### cookie.path
+
+Specifies the value for the `Path` `Set-Cookie`. By default, this is set to `'/'`, which
+is the root path of the domain.
+
+##### cookie.priority
+
+Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1].
+
+  - `'low'` will set the `Priority` attribute to `Low`.
+  - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
+  - `'high'` will set the `Priority` attribute to `High`.
+
+More information about the different priority levels can be found in
+[the specification][rfc-west-cookie-priority-00-4.1].
+
+**Note** This is an attribute that has not yet been fully standardized, and may change in the future.
+This also means many clients may ignore this attribute until they understand it.
+
+##### cookie.sameSite
+
+Specifies the `boolean` or `string` to be the value for the `SameSite` `Set-Cookie` attribute.
+By default, this is `false`.
+
+  - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+  - `false` will not set the `SameSite` attribute.
+  - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
+  - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
+  - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+
+More information about the different enforcement levels can be found in
+[the specification][rfc-6265bis-03-4.1.2.7].
+
+**Note** This is an attribute that has not yet been fully standardized, and may change in
+the future. This also means many clients may ignore this attribute until they understand it.
+
+**Note** There is a [draft spec](https://tools.ietf.org/html/draft-west-cookie-incrementalism-01)
+that requires that the `Secure` attribute be set to `true` when the `SameSite` attribute has been
+set to `'none'`. Some web browsers or other clients may be adopting this specification.
+
+##### cookie.secure
+
+Specifies the `boolean` value for the `Secure` `Set-Cookie` attribute. When truthy,
+the `Secure` attribute is set, otherwise it is not. By default, the `Secure`
+attribute is not set.
+
+**Note** be careful when setting this to `true`, as compliant clients will not send
+the cookie back to the server in the future if the browser does not have an HTTPS
+connection.
+
+Please note that `secure: true` is a **recommended** option. However, it requires
+an https-enabled website, i.e., HTTPS is necessary for secure cookies. If `secure`
+is set, and you access your site over HTTP, the cookie will not be set. If you
+have your node.js behind a proxy and are using `secure: true`, you need to set
+"trust proxy" in express:
+
+```js
+var app = express()
+app.set('trust proxy', 1) // trust first proxy
+app.use(session({
+  secret: 'keyboard cat',
+  resave: false,
+  saveUninitialized: true,
+  cookie: { secure: true }
+}))
+```
+
+For using secure cookies in production, but allowing for testing in development,
+the following is an example of enabling this setup based on `NODE_ENV` in express:
+
+```js
+var app = express()
+var sess = {
+  secret: 'keyboard cat',
+  cookie: {}
+}
+
+if (app.get('env') === 'production') {
+  app.set('trust proxy', 1) // trust first proxy
+  sess.cookie.secure = true // serve secure cookies
+}
+
+app.use(session(sess))
+```
+
+The `cookie.secure` option can also be set to the special value `'auto'` to have
+this setting automatically match the determined security of the connection. Be
+careful when using this setting if the site is available both as HTTP and HTTPS,
+as once the cookie is set on HTTPS, it will no longer be visible over HTTP. This
+is useful when the Express `"trust proxy"` setting is properly setup to simplify
+development vs production configuration.
+
+##### genid
+
+Function to call to generate a new session ID. Provide a function that returns
+a string that will be used as a session ID. The function is given `req` as the
+first argument if you want to use some value attached to `req` when generating
+the ID.
+
+The default value is a function which uses the `uid-safe` library to generate IDs.
+
+**NOTE** be careful to generate unique IDs so your sessions do not conflict.
+
+```js
+app.use(session({
+  genid: function(req) {
+    return genuuid() // use UUIDs for session IDs
+  },
+  secret: 'keyboard cat'
+}))
+```
+
+##### name
+
+The name of the session ID cookie to set in the response (and read from in the
+request).
+
+The default value is `'connect.sid'`.
+
+**Note** if you have multiple apps running on the same hostname (this is just
+the name, i.e. `localhost` or `127.0.0.1`; different schemes and ports do not
+name a different hostname), then you need to separate the session cookies from
+each other. The simplest method is to simply set different `name`s per app.
+
+##### proxy
+
+Trust the reverse proxy when setting secure cookies (via the "X-Forwarded-Proto"
+header).
+
+The default value is `undefined`.
+
+  - `true` The "X-Forwarded-Proto" header will be used.
+  - `false` All headers are ignored and the connection is considered secure only
+    if there is a direct TLS/SSL connection.
+  - `undefined` Uses the "trust proxy" setting from express
+
+##### resave
+
+Forces the session to be saved back to the session store, even if the session
+was never modified during the request. Depending on your store this may be
+necessary, but it can also create race conditions where a client makes two
+parallel requests to your server and changes made to the session in one
+request may get overwritten when the other request ends, even if it made no
+changes (this behavior also depends on what store you're using).
+
+The default value is `true`, but using the default has been deprecated,
+as the default will change in the future. Please research into this setting
+and choose what is appropriate to your use-case. Typically, you'll want
+`false`.
+
+How do I know if this is necessary for my store? The best way to know is to
+check with your store if it implements the `touch` method. If it does, then
+you can safely set `resave: false`. If it does not implement the `touch`
+method and your store sets an expiration date on stored sessions, then you
+likely need `resave: true`.
+
+##### rolling
+
+Force the session identifier cookie to be set on every response. The expiration
+is reset to the original [`maxAge`](#cookiemaxage), resetting the expiration
+countdown.
+
+The default value is `false`.
+
+With this enabled, the session identifier cookie will expire in
+[`maxAge`](#cookiemaxage) since the last response was sent instead of in
+[`maxAge`](#cookiemaxage) since the session was last modified by the server.
+
+This is typically used in conjunction with short, non-session-length
+[`maxAge`](#cookiemaxage) values to provide a quick timeout of the session data
+with reduced potential of it occurring during on going server interactions.
+
+**Note** When this option is set to `true` but the `saveUninitialized` option is
+set to `false`, the cookie will not be set on a response with an uninitialized
+session. This option only modifies the behavior when an existing session was
+loaded for the request.
+
+##### saveUninitialized
+
+Forces a session that is "uninitialized" to be saved to the store. A session is
+uninitialized when it is new but not modified. Choosing `false` is useful for
+implementing login sessions, reducing server storage usage, or complying with
+laws that require permission before setting a cookie. Choosing `false` will also
+help with race conditions where a client makes multiple parallel requests
+without a session.
+
+The default value is `true`, but using the default has been deprecated, as the
+default will change in the future. Please research into this setting and
+choose what is appropriate to your use-case.
+
+**Note** if you are using Session in conjunction with PassportJS, Passport
+will add an empty Passport object to the session for use after a user is
+authenticated, which will be treated as a modification to the session, causing
+it to be saved. *This has been fixed in PassportJS 0.3.0*
+
+##### secret
+
+**Required option**
+
+This is the secret used to sign the session ID cookie. The secret can be any type
+of value that is supported by Node.js `crypto.createHmac` (like a string or a
+`Buffer`). This can be either a single secret, or an array of multiple secrets. If
+an array of secrets is provided, only the first element will be used to sign the
+session ID cookie, while all the elements will be considered when verifying the
+signature in requests. The secret itself should be not easily parsed by a human and
+would best be a random set of characters. A best practice may include:
+
+  - The use of environment variables to store the secret, ensuring the secret itself
+    does not exist in your repository.
+  - Periodic updates of the secret, while ensuring the previous secret is in the
+    array.
+
+Using a secret that cannot be guessed will reduce the ability to hijack a session to
+only guessing the session ID (as determined by the `genid` option).
+
+Changing the secret value will invalidate all existing sessions. In order to rotate
+the secret without invalidating sessions, provide an array of secrets, with the new
+secret as first element of the array, and including previous secrets as the later
+elements.
+
+**Note** HMAC-256 is used to sign the session ID. For this reason, the secret should
+contain at least 32 bytes of entropy.
+
+##### store
+
+The session store instance, defaults to a new `MemoryStore` instance.
+
+##### unset
+
+Control the result of unsetting `req.session` (through `delete`, setting to `null`,
+etc.).
+
+The default value is `'keep'`.
+
+  - `'destroy'` The session will be destroyed (deleted) when the response ends.
+  - `'keep'` The session in the store will be kept, but modifications made during
+    the request are ignored and not saved.
+
+### req.session
+
+To store or access session data, simply use the request property `req.session`,
+which is (generally) serialized as JSON by the store, so nested objects
+are typically fine. For example below is a user-specific view counter:
+
+```js
+// Use the session middleware
+app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
+
+// Access the session as req.session
+app.get('/', function(req, res, next) {
+  if (req.session.views) {
+    req.session.views++
+    res.setHeader('Content-Type', 'text/html')
+    res.write('<p>views: ' + req.session.views + '</p>')
+    res.write('<p>expires in: ' + (req.session.cookie.maxAge / 1000) + 's</p>')
+    res.end()
+  } else {
+    req.session.views = 1
+    res.end('welcome to the session demo. refresh!')
+  }
+})
+```
+
+#### Session.regenerate(callback)
+
+To regenerate the session simply invoke the method. Once complete,
+a new SID and `Session` instance will be initialized at `req.session`
+and the `callback` will be invoked.
+
+```js
+req.session.regenerate(function(err) {
+  // will have a new session here
+})
+```
+
+#### Session.destroy(callback)
+
+Destroys the session and will unset the `req.session` property.
+Once complete, the `callback` will be invoked.
+
+```js
+req.session.destroy(function(err) {
+  // cannot access session here
+})
+```
+
+#### Session.reload(callback)
+
+Reloads the session data from the store and re-populates the
+`req.session` object. Once complete, the `callback` will be invoked.
+
+```js
+req.session.reload(function(err) {
+  // session updated
+})
+```
+
+#### Session.save(callback)
+
+Save the session back to the store, replacing the contents on the store with the
+contents in memory (though a store may do something else--consult the store's
+documentation for exact behavior).
+
+This method is automatically called at the end of the HTTP response if the
+session data has been altered (though this behavior can be altered with various
+options in the middleware constructor). Because of this, typically this method
+does not need to be called.
+
+There are some cases where it is useful to call this method, for example,
+redirects, long-lived requests or in WebSockets.
+
+```js
+req.session.save(function(err) {
+  // session saved
+})
+```
+
+#### Session.touch()
+
+Updates the `.maxAge` property. Typically this is
+not necessary to call, as the session middleware does this for you.
+
+### req.session.id
+
+Each session has a unique ID associated with it. This property is an
+alias of [`req.sessionID`](#reqsessionid-1) and cannot be modified.
+It has been added to make the session ID accessible from the `session`
+object.
+
+### req.session.cookie
+
+Each session has a unique cookie object accompany it. This allows
+you to alter the session cookie per visitor. For example we can
+set `req.session.cookie.expires` to `false` to enable the cookie
+to remain for only the duration of the user-agent.
+
+#### Cookie.maxAge
+
+Alternatively `req.session.cookie.maxAge` will return the time
+remaining in milliseconds, which we may also re-assign a new value
+to adjust the `.expires` property appropriately. The following
+are essentially equivalent
+
+```js
+var hour = 3600000
+req.session.cookie.expires = new Date(Date.now() + hour)
+req.session.cookie.maxAge = hour
+```
+
+For example when `maxAge` is set to `60000` (one minute), and 30 seconds
+has elapsed it will return `30000` until the current request has completed,
+at which time `req.session.touch()` is called to reset
+`req.session.cookie.maxAge` to its original value.
+
+```js
+req.session.cookie.maxAge // => 30000
+```
+
+#### Cookie.originalMaxAge
+
+The `req.session.cookie.originalMaxAge` property returns the original
+`maxAge` (time-to-live), in milliseconds, of the session cookie.
+
+### req.sessionID
+
+To get the ID of the loaded session, access the request property
+`req.sessionID`. This is simply a read-only value set when a session
+is loaded/created.
+
+## Session Store Implementation
+
+Every session store _must_ be an `EventEmitter` and implement specific
+methods. The following methods are the list of **required**, **recommended**,
+and **optional**.
+
+  * Required methods are ones that this module will always call on the store.
+  * Recommended methods are ones that this module will call on the store if
+    available.
+  * Optional methods are ones this module does not call at all, but helps
+    present uniform stores to users.
+
+For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo.
+
+### store.all(callback)
+
+**Optional**
+
+This optional method is used to get all sessions in the store as an array. The
+`callback` should be called as `callback(error, sessions)`.
+
+### store.destroy(sid, callback)
+
+**Required**
+
+This required method is used to destroy/delete a session from the store given
+a session ID (`sid`). The `callback` should be called as `callback(error)` once
+the session is destroyed.
+
+### store.clear(callback)
+
+**Optional**
+
+This optional method is used to delete all sessions from the store. The
+`callback` should be called as `callback(error)` once the store is cleared.
+
+### store.length(callback)
+
+**Optional**
+
+This optional method is used to get the count of all sessions in the store.
+The `callback` should be called as `callback(error, len)`.
+
+### store.get(sid, callback)
+
+**Required**
+
+This required method is used to get a session from the store given a session
+ID (`sid`). The `callback` should be called as `callback(error, session)`.
+
+The `session` argument should be a session if found, otherwise `null` or
+`undefined` if the session was not found (and there was no error). A special
+case is made when `error.code === 'ENOENT'` to act like `callback(null, null)`.
+
+### store.set(sid, session, callback)
+
+**Required**
+
+This required method is used to upsert a session into the store given a
+session ID (`sid`) and session (`session`) object. The callback should be
+called as `callback(error)` once the session has been set in the store.
+
+### store.touch(sid, session, callback)
+
+**Recommended**
+
+This recommended method is used to "touch" a given session given a
+session ID (`sid`) and session (`session`) object. The `callback` should be
+called as `callback(error)` once the session has been touched.
+
+This is primarily used when the store will automatically delete idle sessions
+and this method is used to signal to the store the given session is active,
+potentially resetting the idle timer.
+
+## Compatible Session Stores
+
+The following modules implement a session store that is compatible with this
+module. Please make a PR to add additional modules :)
+
+[![★][aerospike-session-store-image] aerospike-session-store][aerospike-session-store-url] A session store using [Aerospike](http://www.aerospike.com/).
+
+[aerospike-session-store-url]: https://www.npmjs.com/package/aerospike-session-store
+[aerospike-session-store-image]: https://badgen.net/github/stars/aerospike/aerospike-session-store-expressjs?label=%E2%98%85
+
+[![★][better-sqlite3-session-store-image] better-sqlite3-session-store][better-sqlite3-session-store-url] A session store based on [better-sqlite3](https://github.com/JoshuaWise/better-sqlite3).
+
+[better-sqlite3-session-store-url]: https://www.npmjs.com/package/better-sqlite3-session-store
+[better-sqlite3-session-store-image]: https://badgen.net/github/stars/timdaub/better-sqlite3-session-store?label=%E2%98%85
+
+[![★][cassandra-store-image] cassandra-store][cassandra-store-url] An Apache Cassandra-based session store.
+
+[cassandra-store-url]: https://www.npmjs.com/package/cassandra-store
+[cassandra-store-image]: https://badgen.net/github/stars/webcc/cassandra-store?label=%E2%98%85
+
+[![★][cluster-store-image] cluster-store][cluster-store-url] A wrapper for using in-process / embedded
+stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2
+and other multi-core embedded devices).
+
+[cluster-store-url]: https://www.npmjs.com/package/cluster-store
+[cluster-store-image]: https://badgen.net/github/stars/coolaj86/cluster-store?label=%E2%98%85
+
+[![★][connect-arango-image] connect-arango][connect-arango-url] An ArangoDB-based session store.
+
+[connect-arango-url]: https://www.npmjs.com/package/connect-arango
+[connect-arango-image]: https://badgen.net/github/stars/AlexanderArvidsson/connect-arango?label=%E2%98%85
+
+[![★][connect-azuretables-image] connect-azuretables][connect-azuretables-url] An [Azure Table Storage](https://azure.microsoft.com/en-gb/services/storage/tables/)-based session store.
+
+[connect-azuretables-url]: https://www.npmjs.com/package/connect-azuretables
+[connect-azuretables-image]: https://badgen.net/github/stars/mike-goodwin/connect-azuretables?label=%E2%98%85
+
+[![★][connect-cloudant-store-image] connect-cloudant-store][connect-cloudant-store-url] An [IBM Cloudant](https://cloudant.com/)-based session store.
+
+[connect-cloudant-store-url]: https://www.npmjs.com/package/connect-cloudant-store
+[connect-cloudant-store-image]: https://badgen.net/github/stars/adriantanasa/connect-cloudant-store?label=%E2%98%85
+
+[![★][connect-cosmosdb-image] connect-cosmosdb][connect-cosmosdb-url] An Azure [Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db/)-based session store.
+
+[connect-cosmosdb-url]: https://www.npmjs.com/package/connect-cosmosdb
+[connect-cosmosdb-image]: https://badgen.net/github/stars/thekillingspree/connect-cosmosdb?label=%E2%98%85
+
+[![★][connect-couchbase-image] connect-couchbase][connect-couchbase-url] A [couchbase](http://www.couchbase.com/)-based session store.
+
+[connect-couchbase-url]: https://www.npmjs.com/package/connect-couchbase
+[connect-couchbase-image]: https://badgen.net/github/stars/christophermina/connect-couchbase?label=%E2%98%85
+
+[![★][connect-datacache-image] connect-datacache][connect-datacache-url] An [IBM Bluemix Data Cache](http://www.ibm.com/cloud-computing/bluemix/)-based session store.
+
+[connect-datacache-url]: https://www.npmjs.com/package/connect-datacache
+[connect-datacache-image]: https://badgen.net/github/stars/adriantanasa/connect-datacache?label=%E2%98%85
+
+[![★][@google-cloud/connect-datastore-image] @google-cloud/connect-datastore][@google-cloud/connect-datastore-url] A [Google Cloud Datastore](https://cloud.google.com/datastore/docs/concepts/overview)-based session store.
+
+[@google-cloud/connect-datastore-url]: https://www.npmjs.com/package/@google-cloud/connect-datastore
+[@google-cloud/connect-datastore-image]: https://badgen.net/github/stars/GoogleCloudPlatform/cloud-datastore-session-node?label=%E2%98%85
+
+[![★][connect-db2-image] connect-db2][connect-db2-url] An IBM DB2-based session store built using [ibm_db](https://www.npmjs.com/package/ibm_db) module.
+
+[connect-db2-url]: https://www.npmjs.com/package/connect-db2
+[connect-db2-image]: https://badgen.net/github/stars/wallali/connect-db2?label=%E2%98%85
+
+[![★][connect-dynamodb-image] connect-dynamodb][connect-dynamodb-url] A DynamoDB-based session store.
+
+[connect-dynamodb-url]: https://www.npmjs.com/package/connect-dynamodb
+[connect-dynamodb-image]: https://badgen.net/github/stars/ca98am79/connect-dynamodb?label=%E2%98%85
+
+[![★][@google-cloud/connect-firestore-image] @google-cloud/connect-firestore][@google-cloud/connect-firestore-url] A [Google Cloud Firestore](https://cloud.google.com/firestore/docs/overview)-based session store.
+
+[@google-cloud/connect-firestore-url]: https://www.npmjs.com/package/@google-cloud/connect-firestore
+[@google-cloud/connect-firestore-image]: https://badgen.net/github/stars/googleapis/nodejs-firestore-session?label=%E2%98%85
+
+[![★][connect-hazelcast-image] connect-hazelcast][connect-hazelcast-url] Hazelcast session store for Connect and Express.
+
+[connect-hazelcast-url]: https://www.npmjs.com/package/connect-hazelcast
+[connect-hazelcast-image]: https://badgen.net/github/stars/huseyinbabal/connect-hazelcast?label=%E2%98%85
+
+[![★][connect-loki-image] connect-loki][connect-loki-url] A Loki.js-based session store.
+
+[connect-loki-url]: https://www.npmjs.com/package/connect-loki
+[connect-loki-image]: https://badgen.net/github/stars/Requarks/connect-loki?label=%E2%98%85
+
+[![★][connect-lowdb-image] connect-lowdb][connect-lowdb-url] A lowdb-based session store.
+
+[connect-lowdb-url]: https://www.npmjs.com/package/connect-lowdb
+[connect-lowdb-image]: https://badgen.net/github/stars/travishorn/connect-lowdb?label=%E2%98%85
+
+[![★][connect-memcached-image] connect-memcached][connect-memcached-url] A memcached-based session store.
+
+[connect-memcached-url]: https://www.npmjs.com/package/connect-memcached
+[connect-memcached-image]: https://badgen.net/github/stars/balor/connect-memcached?label=%E2%98%85
+
+[![★][connect-memjs-image] connect-memjs][connect-memjs-url] A memcached-based session store using
+[memjs](https://www.npmjs.com/package/memjs) as the memcached client.
+
+[connect-memjs-url]: https://www.npmjs.com/package/connect-memjs
+[connect-memjs-image]: https://badgen.net/github/stars/liamdon/connect-memjs?label=%E2%98%85
+
+[![★][connect-ml-image] connect-ml][connect-ml-url] A MarkLogic Server-based session store.
+
+[connect-ml-url]: https://www.npmjs.com/package/connect-ml
+[connect-ml-image]: https://badgen.net/github/stars/bluetorch/connect-ml?label=%E2%98%85
+
+[![★][connect-monetdb-image] connect-monetdb][connect-monetdb-url] A MonetDB-based session store.
+
+[connect-monetdb-url]: https://www.npmjs.com/package/connect-monetdb
+[connect-monetdb-image]: https://badgen.net/github/stars/MonetDB/npm-connect-monetdb?label=%E2%98%85
+
+[![★][connect-mongo-image] connect-mongo][connect-mongo-url] A MongoDB-based session store.
+
+[connect-mongo-url]: https://www.npmjs.com/package/connect-mongo
+[connect-mongo-image]: https://badgen.net/github/stars/kcbanner/connect-mongo?label=%E2%98%85
+
+[![★][connect-mongodb-session-image] connect-mongodb-session][connect-mongodb-session-url] Lightweight MongoDB-based session store built and maintained by MongoDB.
+
+[connect-mongodb-session-url]: https://www.npmjs.com/package/connect-mongodb-session
+[connect-mongodb-session-image]: https://badgen.net/github/stars/mongodb-js/connect-mongodb-session?label=%E2%98%85
+
+[![★][connect-mssql-v2-image] connect-mssql-v2][connect-mssql-v2-url] A Microsoft SQL Server-based session store based on [connect-mssql](https://www.npmjs.com/package/connect-mssql).
+
+[connect-mssql-v2-url]: https://www.npmjs.com/package/connect-mssql-v2
+[connect-mssql-v2-image]: https://badgen.net/github/stars/jluboff/connect-mssql-v2?label=%E2%98%85
+
+[![★][connect-neo4j-image] connect-neo4j][connect-neo4j-url] A [Neo4j](https://neo4j.com)-based session store.
+
+[connect-neo4j-url]: https://www.npmjs.com/package/connect-neo4j
+[connect-neo4j-image]: https://badgen.net/github/stars/MaxAndersson/connect-neo4j?label=%E2%98%85
+
+[![★][connect-ottoman-image] connect-ottoman][connect-ottoman-url] A [couchbase ottoman](http://www.couchbase.com/)-based session store.
+
+[connect-ottoman-url]: https://www.npmjs.com/package/connect-ottoman
+[connect-ottoman-image]: https://badgen.net/github/stars/noiissyboy/connect-ottoman?label=%E2%98%85
+
+[![★][connect-pg-simple-image] connect-pg-simple][connect-pg-simple-url] A PostgreSQL-based session store.
+
+[connect-pg-simple-url]: https://www.npmjs.com/package/connect-pg-simple
+[connect-pg-simple-image]: https://badgen.net/github/stars/voxpelli/node-connect-pg-simple?label=%E2%98%85
+
+[![★][connect-redis-image] connect-redis][connect-redis-url] A Redis-based session store.
+
+[connect-redis-url]: https://www.npmjs.com/package/connect-redis
+[connect-redis-image]: https://badgen.net/github/stars/tj/connect-redis?label=%E2%98%85
+
+[![★][connect-session-firebase-image] connect-session-firebase][connect-session-firebase-url] A session store based on the [Firebase Realtime Database](https://firebase.google.com/docs/database/)
+
+[connect-session-firebase-url]: https://www.npmjs.com/package/connect-session-firebase
+[connect-session-firebase-image]: https://badgen.net/github/stars/benweier/connect-session-firebase?label=%E2%98%85
+
+[![★][connect-session-knex-image] connect-session-knex][connect-session-knex-url] A session store using
+[Knex.js](http://knexjs.org/), which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle.
+
+[connect-session-knex-url]: https://www.npmjs.com/package/connect-session-knex
+[connect-session-knex-image]: https://badgen.net/github/stars/llambda/connect-session-knex?label=%E2%98%85
+
+[![★][connect-session-sequelize-image] connect-session-sequelize][connect-session-sequelize-url] A session store using
+[Sequelize.js](http://sequelizejs.com/), which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL.
+
+[connect-session-sequelize-url]: https://www.npmjs.com/package/connect-session-sequelize
+[connect-session-sequelize-image]: https://badgen.net/github/stars/mweibel/connect-session-sequelize?label=%E2%98%85
+
+[![★][connect-sqlite3-image] connect-sqlite3][connect-sqlite3-url] A [SQLite3](https://github.com/mapbox/node-sqlite3) session store modeled after the TJ's `connect-redis` store.
+
+[connect-sqlite3-url]: https://www.npmjs.com/package/connect-sqlite3
+[connect-sqlite3-image]: https://badgen.net/github/stars/rawberg/connect-sqlite3?label=%E2%98%85
+
+[![★][connect-typeorm-image] connect-typeorm][connect-typeorm-url] A [TypeORM](https://github.com/typeorm/typeorm)-based session store.
+
+[connect-typeorm-url]: https://www.npmjs.com/package/connect-typeorm
+[connect-typeorm-image]: https://badgen.net/github/stars/makepost/connect-typeorm?label=%E2%98%85
+
+[![★][couchdb-expression-image] couchdb-expression][couchdb-expression-url] A [CouchDB](https://couchdb.apache.org/)-based session store.
+
+[couchdb-expression-url]: https://www.npmjs.com/package/couchdb-expression
+[couchdb-expression-image]: https://badgen.net/github/stars/tkshnwesper/couchdb-expression?label=%E2%98%85
+
+[![★][dynamodb-store-image] dynamodb-store][dynamodb-store-url] A DynamoDB-based session store.
+
+[dynamodb-store-url]: https://www.npmjs.com/package/dynamodb-store
+[dynamodb-store-image]: https://badgen.net/github/stars/rafaelrpinto/dynamodb-store?label=%E2%98%85
+
+[![★][dynamodb-store-v3-image] dynamodb-store-v3][dynamodb-store-v3-url] Implementation of a session store using DynamoDB backed by the [AWS SDK for JavaScript v3](https://github.com/aws/aws-sdk-js-v3).
+
+[dynamodb-store-v3-url]: https://www.npmjs.com/package/dynamodb-store-v3
+[dynamodb-store-v3-image]: https://badgen.net/github/stars/FryDay/dynamodb-store-v3?label=%E2%98%85
+
+[![★][express-etcd-image] express-etcd][express-etcd-url] An [etcd](https://github.com/stianeikeland/node-etcd) based session store.
+
+[express-etcd-url]: https://www.npmjs.com/package/express-etcd
+[express-etcd-image]: https://badgen.net/github/stars/gildean/express-etcd?label=%E2%98%85
+
+[![★][express-mysql-session-image] express-mysql-session][express-mysql-session-url] A session store using native
+[MySQL](https://www.mysql.com/) via the [node-mysql](https://github.com/felixge/node-mysql) module.
+
+[express-mysql-session-url]: https://www.npmjs.com/package/express-mysql-session
+[express-mysql-session-image]: https://badgen.net/github/stars/chill117/express-mysql-session?label=%E2%98%85
+
+[![★][express-nedb-session-image] express-nedb-session][express-nedb-session-url] A NeDB-based session store.
+
+[express-nedb-session-url]: https://www.npmjs.com/package/express-nedb-session
+[express-nedb-session-image]: https://badgen.net/github/stars/louischatriot/express-nedb-session?label=%E2%98%85
+
+[![★][express-oracle-session-image] express-oracle-session][express-oracle-session-url] A session store using native
+[oracle](https://www.oracle.com/) via the [node-oracledb](https://www.npmjs.com/package/oracledb) module.
+
+[express-oracle-session-url]: https://www.npmjs.com/package/express-oracle-session
+[express-oracle-session-image]: https://badgen.net/github/stars/slumber86/express-oracle-session?label=%E2%98%85
+
+[![★][express-session-cache-manager-image] express-session-cache-manager][express-session-cache-manager-url]
+A store that implements [cache-manager](https://www.npmjs.com/package/cache-manager), which supports
+a [variety of storage types](https://www.npmjs.com/package/cache-manager#store-engines).
+
+[express-session-cache-manager-url]: https://www.npmjs.com/package/express-session-cache-manager
+[express-session-cache-manager-image]: https://badgen.net/github/stars/theogravity/express-session-cache-manager?label=%E2%98%85
+
+[![★][express-session-etcd3-image] express-session-etcd3][express-session-etcd3-url] An [etcd3](https://github.com/mixer/etcd3) based session store.
+
+[express-session-etcd3-url]: https://www.npmjs.com/package/express-session-etcd3
+[express-session-etcd3-image]: https://badgen.net/github/stars/willgm/express-session-etcd3?label=%E2%98%85
+
+[![★][express-session-level-image] express-session-level][express-session-level-url] A [LevelDB](https://github.com/Level/levelup) based session store.
+
+[express-session-level-url]: https://www.npmjs.com/package/express-session-level
+[express-session-level-image]: https://badgen.net/github/stars/tgohn/express-session-level?label=%E2%98%85
+
+[![★][express-session-rsdb-image] express-session-rsdb][express-session-rsdb-url] Session store based on Rocket-Store: A very simple, super fast and yet powerful, flat file database.
+
+[express-session-rsdb-url]: https://www.npmjs.com/package/express-session-rsdb
+[express-session-rsdb-image]: https://badgen.net/github/stars/paragi/express-session-rsdb?label=%E2%98%85
+
+[![★][express-sessions-image] express-sessions][express-sessions-url] A session store supporting both MongoDB and Redis.
+
+[express-sessions-url]: https://www.npmjs.com/package/express-sessions
+[express-sessions-image]: https://badgen.net/github/stars/konteck/express-sessions?label=%E2%98%85
+
+[![★][firestore-store-image] firestore-store][firestore-store-url] A [Firestore](https://github.com/hendrysadrak/firestore-store)-based session store.
+
+[firestore-store-url]: https://www.npmjs.com/package/firestore-store
+[firestore-store-image]: https://badgen.net/github/stars/hendrysadrak/firestore-store?label=%E2%98%85
+
+[![★][fortune-session-image] fortune-session][fortune-session-url] A [Fortune.js](https://github.com/fortunejs/fortune)
+based session store. Supports all backends supported by Fortune (MongoDB, Redis, Postgres, NeDB).
+
+[fortune-session-url]: https://www.npmjs.com/package/fortune-session
+[fortune-session-image]: https://badgen.net/github/stars/aliceklipper/fortune-session?label=%E2%98%85
+
+[![★][hazelcast-store-image] hazelcast-store][hazelcast-store-url] A Hazelcast-based session store built on the [Hazelcast Node Client](https://www.npmjs.com/package/hazelcast-client).
+
+[hazelcast-store-url]: https://www.npmjs.com/package/hazelcast-store
+[hazelcast-store-image]: https://badgen.net/github/stars/jackspaniel/hazelcast-store?label=%E2%98%85
+
+[![★][level-session-store-image] level-session-store][level-session-store-url] A LevelDB-based session store.
+
+[level-session-store-url]: https://www.npmjs.com/package/level-session-store
+[level-session-store-image]: https://badgen.net/github/stars/toddself/level-session-store?label=%E2%98%85
+
+[![★][lowdb-session-store-image] lowdb-session-store][lowdb-session-store-url] A [lowdb](https://www.npmjs.com/package/lowdb)-based session store.
+
+[lowdb-session-store-url]: https://www.npmjs.com/package/lowdb-session-store
+[lowdb-session-store-image]: https://badgen.net/github/stars/fhellwig/lowdb-session-store?label=%E2%98%85
+
+[![★][medea-session-store-image] medea-session-store][medea-session-store-url] A Medea-based session store.
+
+[medea-session-store-url]: https://www.npmjs.com/package/medea-session-store
+[medea-session-store-image]: https://badgen.net/github/stars/BenjaminVadant/medea-session-store?label=%E2%98%85
+
+[![★][memorystore-image] memorystore][memorystore-url] A memory session store made for production.
+
+[memorystore-url]: https://www.npmjs.com/package/memorystore
+[memorystore-image]: https://badgen.net/github/stars/roccomuso/memorystore?label=%E2%98%85
+
+[![★][mssql-session-store-image] mssql-session-store][mssql-session-store-url] A SQL Server-based session store.
+
+[mssql-session-store-url]: https://www.npmjs.com/package/mssql-session-store
+[mssql-session-store-image]: https://badgen.net/github/stars/jwathen/mssql-session-store?label=%E2%98%85
+
+[![★][nedb-session-store-image] nedb-session-store][nedb-session-store-url] An alternate NeDB-based (either in-memory or file-persisted) session store.
+
+[nedb-session-store-url]: https://www.npmjs.com/package/nedb-session-store
+[nedb-session-store-image]: https://badgen.net/github/stars/JamesMGreene/nedb-session-store?label=%E2%98%85
+
+[![★][@quixo3/prisma-session-store-image] @quixo3/prisma-session-store][@quixo3/prisma-session-store-url] A session store for the [Prisma Framework](https://www.prisma.io).
+
+[@quixo3/prisma-session-store-url]: https://www.npmjs.com/package/@quixo3/prisma-session-store
+[@quixo3/prisma-session-store-image]: https://badgen.net/github/stars/kleydon/prisma-session-store?label=%E2%98%85
+
+[![★][restsession-image] restsession][restsession-url] Store sessions utilizing a RESTful API
+
+[restsession-url]: https://www.npmjs.com/package/restsession
+[restsession-image]: https://badgen.net/github/stars/jankal/restsession?label=%E2%98%85
+
+[![★][sequelstore-connect-image] sequelstore-connect][sequelstore-connect-url] A session store using [Sequelize.js](http://sequelizejs.com/).
+
+[sequelstore-connect-url]: https://www.npmjs.com/package/sequelstore-connect
+[sequelstore-connect-image]: https://badgen.net/github/stars/MattMcFarland/sequelstore-connect?label=%E2%98%85
+
+[![★][session-file-store-image] session-file-store][session-file-store-url] A file system-based session store.
+
+[session-file-store-url]: https://www.npmjs.com/package/session-file-store
+[session-file-store-image]: https://badgen.net/github/stars/valery-barysok/session-file-store?label=%E2%98%85
+
+[![★][session-pouchdb-store-image] session-pouchdb-store][session-pouchdb-store-url] Session store for PouchDB / CouchDB. Accepts embedded, custom, or remote PouchDB instance and realtime synchronization.
+
+[session-pouchdb-store-url]: https://www.npmjs.com/package/session-pouchdb-store
+[session-pouchdb-store-image]: https://badgen.net/github/stars/solzimer/session-pouchdb-store?label=%E2%98%85
+
+[![★][@cyclic.sh/session-store-image] @cyclic.sh/session-store][@cyclic.sh/session-store-url] A DynamoDB-based session store for [Cyclic.sh](https://www.cyclic.sh/) apps.
+
+[@cyclic.sh/session-store-url]: https://www.npmjs.com/package/@cyclic.sh/session-store
+[@cyclic.sh/session-store-image]: https://badgen.net/github/stars/cyclic-software/session-store?label=%E2%98%85
+
+[![★][@databunker/session-store-image] @databunker/session-store][@databunker/session-store-url] A [Databunker](https://databunker.org/)-based encrypted session store.
+
+[@databunker/session-store-url]: https://www.npmjs.com/package/@databunker/session-store
+[@databunker/session-store-image]: https://badgen.net/github/stars/securitybunker/databunker-session-store?label=%E2%98%85
+
+[![★][sessionstore-image] sessionstore][sessionstore-url] A session store that works with various databases.
+
+[sessionstore-url]: https://www.npmjs.com/package/sessionstore
+[sessionstore-image]: https://badgen.net/github/stars/adrai/sessionstore?label=%E2%98%85
+
+[![★][tch-nedb-session-image] tch-nedb-session][tch-nedb-session-url] A file system session store based on NeDB.
+
+[tch-nedb-session-url]: https://www.npmjs.com/package/tch-nedb-session
+[tch-nedb-session-image]: https://badgen.net/github/stars/tomaschyly/NeDBSession?label=%E2%98%85
+
+## Examples
+
+### View counter
+
+A simple example using `express-session` to store page views for a user.
+
+```js
+var express = require('express')
+var parseurl = require('parseurl')
+var session = require('express-session')
+
+var app = express()
+
+app.use(session({
+  secret: 'keyboard cat',
+  resave: false,
+  saveUninitialized: true
+}))
+
+app.use(function (req, res, next) {
+  if (!req.session.views) {
+    req.session.views = {}
+  }
+
+  // get the url pathname
+  var pathname = parseurl(req).pathname
+
+  // count the views
+  req.session.views[pathname] = (req.session.views[pathname] || 0) + 1
+
+  next()
+})
+
+app.get('/foo', function (req, res, next) {
+  res.send('you viewed this page ' + req.session.views['/foo'] + ' times')
+})
+
+app.get('/bar', function (req, res, next) {
+  res.send('you viewed this page ' + req.session.views['/bar'] + ' times')
+})
+
+app.listen(3000)
+```
+
+### User login
+
+A simple example using `express-session` to keep a user log in session.
+
+```js
+var escapeHtml = require('escape-html')
+var express = require('express')
+var session = require('express-session')
+
+var app = express()
+
+app.use(session({
+  secret: 'keyboard cat',
+  resave: false,
+  saveUninitialized: true
+}))
+
+// middleware to test if authenticated
+function isAuthenticated (req, res, next) {
+  if (req.session.user) next()
+  else next('route')
+}
+
+app.get('/', isAuthenticated, function (req, res) {
+  // this is only called when there is an authentication user due to isAuthenticated
+  res.send('hello, ' + escapeHtml(req.session.user) + '!' +
+    ' <a href="/logout">Logout</a>')
+})
+
+app.get('/', function (req, res) {
+  res.send('<form action="/login" method="post">' +
+    'Username: <input name="user"><br>' +
+    'Password: <input name="pass" type="password"><br>' +
+    '<input type="submit" text="Login"></form>')
+})
+
+app.post('/login', express.urlencoded({ extended: false }), function (req, res) {
+  // login logic to validate req.body.user and req.body.pass
+  // would be implemented here. for this example any combo works
+
+  // regenerate the session, which is good practice to help
+  // guard against forms of session fixation
+  req.session.regenerate(function (err) {
+    if (err) next(err)
+
+    // store user information in session, typically a user id
+    req.session.user = req.body.user
+
+    // save the session before redirection to ensure page
+    // load does not happen before session is saved
+    req.session.save(function (err) {
+      if (err) return next(err)
+      res.redirect('/')
+    })
+  })
+})
+
+app.get('/logout', function (req, res, next) {
+  // logout logic
+
+  // clear the user from the session object and save.
+  // this will ensure that re-using the old session id
+  // does not have a logged in user
+  req.session.user = null
+  req.session.save(function (err) {
+    if (err) next(err)
+
+    // regenerate the session, which is good practice to help
+    // guard against forms of session fixation
+    req.session.regenerate(function (err) {
+      if (err) next(err)
+      res.redirect('/')
+    })
+  })
+})
+
+app.listen(3000)
+```
+
+## Debugging
+
+This module uses the [debug](https://www.npmjs.com/package/debug) module
+internally to log information about session operations.
+
+To see all the internal logs, set the `DEBUG` environment variable to
+`express-session` when launching your app (`npm start`, in this example):
+
+```sh
+$ DEBUG=express-session npm start
+```
+
+On Windows, use the corresponding command;
+
+```sh
+> set DEBUG=express-session & npm start
+```
+
+## License
+
+[MIT](LICENSE)
+
+[rfc-6265bis-03-4.1.2.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7
+[rfc-cutler-httpbis-partitioned-cookies]: https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/
+[rfc-west-cookie-priority-00-4.1]: https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1
+[ci-image]: https://badgen.net/github/checks/expressjs/session/master?label=ci
+[ci-url]: https://github.com/expressjs/session/actions?query=workflow%3Aci
+[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/session/master
+[coveralls-url]: https://coveralls.io/r/expressjs/session?branch=master
+[node-url]: https://nodejs.org/en/download
+[npm-downloads-image]: https://badgen.net/npm/dm/express-session
+[npm-url]: https://npmjs.org/package/express-session
+[npm-version-image]: https://badgen.net/npm/v/express-session
Index: backend/node_modules/express-session/index.js
===================================================================
--- backend/node_modules/express-session/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,693 @@
+/*!
+ * express-session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var Buffer = require('safe-buffer').Buffer
+var cookie = require('cookie');
+var crypto = require('crypto')
+var debug = require('debug')('express-session');
+var deprecate = require('depd')('express-session');
+var onHeaders = require('on-headers')
+var parseUrl = require('parseurl');
+var signature = require('cookie-signature')
+var uid = require('uid-safe').sync
+
+var Cookie = require('./session/cookie')
+var MemoryStore = require('./session/memory')
+var Session = require('./session/session')
+var Store = require('./session/store')
+
+// environment
+
+var env = process.env.NODE_ENV;
+
+/**
+ * Expose the middleware.
+ */
+
+exports = module.exports = session;
+
+/**
+ * Expose constructors.
+ */
+
+exports.Store = Store;
+exports.Cookie = Cookie;
+exports.Session = Session;
+exports.MemoryStore = MemoryStore;
+
+/**
+ * Warning message for `MemoryStore` usage in production.
+ * @private
+ */
+
+var warning = 'Warning: connect.session() MemoryStore is not\n'
+  + 'designed for a production environment, as it will leak\n'
+  + 'memory, and will not scale past a single process.';
+
+/**
+ * Node.js 0.8+ async implementation.
+ * @private
+ */
+
+/* istanbul ignore next */
+var defer = typeof setImmediate === 'function'
+  ? setImmediate
+  : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
+
+/**
+ * Setup session store with the given `options`.
+ *
+ * @param {Object} [options]
+ * @param {Object} [options.cookie] Options for cookie
+ * @param {Function} [options.genid]
+ * @param {String} [options.name=connect.sid] Session ID cookie name
+ * @param {Boolean} [options.proxy]
+ * @param {Boolean} [options.resave] Resave unmodified sessions back to the store
+ * @param {Boolean} [options.rolling] Enable/disable rolling session expiration
+ * @param {Boolean} [options.saveUninitialized] Save uninitialized sessions to the store
+ * @param {String|Array} [options.secret] Secret for signing session ID
+ * @param {Object} [options.store=MemoryStore] Session store
+ * @param {String} [options.unset]
+ * @return {Function} middleware
+ * @public
+ */
+
+function session(options) {
+  var opts = options || {}
+
+  // get the cookie options
+  var cookieOptions = opts.cookie || {}
+
+  // get the session id generate function
+  var generateId = opts.genid || generateSessionId
+
+  // get the session cookie name
+  var name = opts.name || opts.key || 'connect.sid'
+
+  // get the session store
+  var store = opts.store || new MemoryStore()
+
+  // get the trust proxy setting
+  var trustProxy = opts.proxy
+
+  // get the resave session option
+  var resaveSession = opts.resave;
+
+  // get the rolling session option
+  var rollingSessions = Boolean(opts.rolling)
+
+  // get the save uninitialized session option
+  var saveUninitializedSession = opts.saveUninitialized
+
+  // get the cookie signing secret
+  var secret = opts.secret
+
+  if (typeof generateId !== 'function') {
+    throw new TypeError('genid option must be a function');
+  }
+
+  if (resaveSession === undefined) {
+    deprecate('undefined resave option; provide resave option');
+    resaveSession = true;
+  }
+
+  if (saveUninitializedSession === undefined) {
+    deprecate('undefined saveUninitialized option; provide saveUninitialized option');
+    saveUninitializedSession = true;
+  }
+
+  if (opts.unset && opts.unset !== 'destroy' && opts.unset !== 'keep') {
+    throw new TypeError('unset option must be "destroy" or "keep"');
+  }
+
+  // TODO: switch to "destroy" on next major
+  var unsetDestroy = opts.unset === 'destroy'
+
+  if (Array.isArray(secret) && secret.length === 0) {
+    throw new TypeError('secret option array must contain one or more strings');
+  }
+
+  if (secret && !Array.isArray(secret)) {
+    secret = [secret];
+  }
+
+  if (!secret) {
+    deprecate('req.secret; provide secret option');
+  }
+
+  // notify user that this store is not
+  // meant for a production environment
+  /* istanbul ignore next: not tested */
+  if (env === 'production' && store instanceof MemoryStore) {
+    console.warn(warning);
+  }
+
+  // generates the new session
+  store.generate = function(req){
+    req.sessionID = generateId(req);
+    req.session = new Session(req);
+    req.session.cookie = new Cookie(cookieOptions);
+
+    if (cookieOptions.secure === 'auto') {
+      req.session.cookie.secure = issecure(req, trustProxy);
+    }
+  };
+
+  var storeImplementsTouch = typeof store.touch === 'function';
+
+  // register event listeners for the store to track readiness
+  var storeReady = true
+  store.on('disconnect', function ondisconnect() {
+    storeReady = false
+  })
+  store.on('connect', function onconnect() {
+    storeReady = true
+  })
+
+  return function session(req, res, next) {
+    // self-awareness
+    if (req.session) {
+      next()
+      return
+    }
+
+    // Handle connection as if there is no session if
+    // the store has temporarily disconnected etc
+    if (!storeReady) {
+      debug('store is disconnected')
+      next()
+      return
+    }
+
+    // pathname mismatch
+    var originalPath = parseUrl.original(req).pathname || '/'
+    if (originalPath.indexOf(cookieOptions.path || '/') !== 0) {
+      debug('pathname mismatch')
+      next()
+      return
+    }
+
+    // ensure a secret is available or bail
+    if (!secret && !req.secret) {
+      next(new Error('secret option required for sessions'));
+      return;
+    }
+
+    // backwards compatibility for signed cookies
+    // req.secret is passed from the cookie parser middleware
+    var secrets = secret || [req.secret];
+
+    var originalHash;
+    var originalId;
+    var savedHash;
+    var touched = false
+
+    // expose store
+    req.sessionStore = store;
+
+    // get the session ID from the cookie
+    var cookieId = req.sessionID = getcookie(req, name, secrets);
+
+    // set-cookie
+    onHeaders(res, function(){
+      if (!req.session) {
+        debug('no session');
+        return;
+      }
+
+      if (!shouldSetCookie(req)) {
+        return;
+      }
+
+      // only send secure cookies via https
+      if (req.session.cookie.secure && !issecure(req, trustProxy)) {
+        debug('not secured');
+        return;
+      }
+
+      if (!touched) {
+        // touch session
+        req.session.touch()
+        touched = true
+      }
+
+      // set cookie
+      try {
+        setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data)
+      } catch (err) {
+        defer(next, err)
+      }
+    });
+
+    // proxy end() to commit the session
+    var _end = res.end;
+    var _write = res.write;
+    var ended = false;
+    res.end = function end(chunk, encoding) {
+      if (ended) {
+        return false;
+      }
+
+      ended = true;
+
+      var ret;
+      var sync = true;
+
+      function writeend() {
+        if (sync) {
+          ret = _end.call(res, chunk, encoding);
+          sync = false;
+          return;
+        }
+
+        _end.call(res);
+      }
+
+      function writetop() {
+        if (!sync) {
+          return ret;
+        }
+
+        if (!res._header) {
+          res._implicitHeader()
+        }
+
+        if (chunk == null) {
+          ret = true;
+          return ret;
+        }
+
+        var contentLength = Number(res.getHeader('Content-Length'));
+
+        if (!isNaN(contentLength) && contentLength > 0) {
+          // measure chunk
+          chunk = !Buffer.isBuffer(chunk)
+            ? Buffer.from(chunk, encoding)
+            : chunk;
+          encoding = undefined;
+
+          if (chunk.length !== 0) {
+            debug('split response');
+            ret = _write.call(res, chunk.slice(0, chunk.length - 1));
+            chunk = chunk.slice(chunk.length - 1, chunk.length);
+            return ret;
+          }
+        }
+
+        ret = _write.call(res, chunk, encoding);
+        sync = false;
+
+        return ret;
+      }
+
+      if (shouldDestroy(req)) {
+        // destroy session
+        debug('destroying');
+        store.destroy(req.sessionID, function ondestroy(err) {
+          if (err) {
+            defer(next, err);
+          }
+
+          debug('destroyed');
+          writeend();
+        });
+
+        return writetop();
+      }
+
+      // no session to save
+      if (!req.session) {
+        debug('no session');
+        return _end.call(res, chunk, encoding);
+      }
+
+      if (!touched) {
+        // touch session
+        req.session.touch()
+        touched = true
+      }
+
+      if (shouldSave(req)) {
+        req.session.save(function onsave(err) {
+          if (err) {
+            defer(next, err);
+          }
+
+          writeend();
+        });
+
+        return writetop();
+      } else if (storeImplementsTouch && shouldTouch(req)) {
+        // store implements touch method
+        debug('touching');
+        store.touch(req.sessionID, req.session, function ontouch(err) {
+          if (err) {
+            defer(next, err);
+          }
+
+          debug('touched');
+          writeend();
+        });
+
+        return writetop();
+      }
+
+      return _end.call(res, chunk, encoding);
+    };
+
+    // generate the session
+    function generate() {
+      store.generate(req);
+      originalId = req.sessionID;
+      originalHash = hash(req.session);
+      wrapmethods(req.session);
+    }
+
+    // inflate the session
+    function inflate (req, sess) {
+      store.createSession(req, sess)
+      originalId = req.sessionID
+      originalHash = hash(sess)
+
+      if (!resaveSession) {
+        savedHash = originalHash
+      }
+
+      wrapmethods(req.session)
+    }
+
+    function rewrapmethods (sess, callback) {
+      return function () {
+        if (req.session !== sess) {
+          wrapmethods(req.session)
+        }
+
+        callback.apply(this, arguments)
+      }
+    }
+
+    // wrap session methods
+    function wrapmethods(sess) {
+      var _reload = sess.reload
+      var _save = sess.save;
+
+      function reload(callback) {
+        debug('reloading %s', this.id)
+        _reload.call(this, rewrapmethods(this, callback))
+      }
+
+      function save() {
+        debug('saving %s', this.id);
+        savedHash = hash(this);
+        _save.apply(this, arguments);
+      }
+
+      Object.defineProperty(sess, 'reload', {
+        configurable: true,
+        enumerable: false,
+        value: reload,
+        writable: true
+      })
+
+      Object.defineProperty(sess, 'save', {
+        configurable: true,
+        enumerable: false,
+        value: save,
+        writable: true
+      });
+    }
+
+    // check if session has been modified
+    function isModified(sess) {
+      return originalId !== sess.id || originalHash !== hash(sess);
+    }
+
+    // check if session has been saved
+    function isSaved(sess) {
+      return originalId === sess.id && savedHash === hash(sess);
+    }
+
+    // determine if session should be destroyed
+    function shouldDestroy(req) {
+      return req.sessionID && unsetDestroy && req.session == null;
+    }
+
+    // determine if session should be saved to store
+    function shouldSave(req) {
+      // cannot set cookie without a session ID
+      if (typeof req.sessionID !== 'string') {
+        debug('session ignored because of bogus req.sessionID %o', req.sessionID);
+        return false;
+      }
+
+      return !saveUninitializedSession && !savedHash && cookieId !== req.sessionID
+        ? isModified(req.session)
+        : !isSaved(req.session)
+    }
+
+    // determine if session should be touched
+    function shouldTouch(req) {
+      // cannot set cookie without a session ID
+      if (typeof req.sessionID !== 'string') {
+        debug('session ignored because of bogus req.sessionID %o', req.sessionID);
+        return false;
+      }
+
+      return cookieId === req.sessionID && !shouldSave(req);
+    }
+
+    // determine if cookie should be set on response
+    function shouldSetCookie(req) {
+      // cannot set cookie without a session ID
+      if (typeof req.sessionID !== 'string') {
+        return false;
+      }
+
+      return cookieId !== req.sessionID
+        ? saveUninitializedSession || isModified(req.session)
+        : rollingSessions || req.session.cookie.expires != null && isModified(req.session);
+    }
+
+    // generate a session if the browser doesn't send a sessionID
+    if (!req.sessionID) {
+      debug('no SID sent, generating session');
+      generate();
+      next();
+      return;
+    }
+
+    // generate the session object
+    debug('fetching %s', req.sessionID);
+    store.get(req.sessionID, function(err, sess){
+      // error handling
+      if (err && err.code !== 'ENOENT') {
+        debug('error %j', err);
+        next(err)
+        return
+      }
+
+      try {
+        if (err || !sess) {
+          debug('no session found')
+          generate()
+        } else {
+          debug('session found')
+          inflate(req, sess)
+        }
+      } catch (e) {
+        next(e)
+        return
+      }
+
+      next()
+    });
+  };
+};
+
+/**
+ * Generate a session ID for a new session.
+ *
+ * @return {String}
+ * @private
+ */
+
+function generateSessionId(sess) {
+  return uid(24);
+}
+
+/**
+ * Get the session ID cookie from request.
+ *
+ * @return {string}
+ * @private
+ */
+
+function getcookie(req, name, secrets) {
+  var header = req.headers.cookie;
+  var raw;
+  var val;
+
+  // read from cookie header
+  if (header) {
+    var cookies = cookie.parse(header);
+
+    raw = cookies[name];
+
+    if (raw) {
+      if (raw.substr(0, 2) === 's:') {
+        val = unsigncookie(raw.slice(2), secrets);
+
+        if (val === false) {
+          debug('cookie signature invalid');
+          val = undefined;
+        }
+      } else {
+        debug('cookie unsigned')
+      }
+    }
+  }
+
+  // back-compat read from cookieParser() signedCookies data
+  if (!val && req.signedCookies) {
+    val = req.signedCookies[name];
+
+    if (val) {
+      deprecate('cookie should be available in req.headers.cookie');
+    }
+  }
+
+  // back-compat read from cookieParser() cookies data
+  if (!val && req.cookies) {
+    raw = req.cookies[name];
+
+    if (raw) {
+      if (raw.substr(0, 2) === 's:') {
+        val = unsigncookie(raw.slice(2), secrets);
+
+        if (val) {
+          deprecate('cookie should be available in req.headers.cookie');
+        }
+
+        if (val === false) {
+          debug('cookie signature invalid');
+          val = undefined;
+        }
+      } else {
+        debug('cookie unsigned')
+      }
+    }
+  }
+
+  return val;
+}
+
+/**
+ * Hash the given `sess` object omitting changes to `.cookie`.
+ *
+ * @param {Object} sess
+ * @return {String}
+ * @private
+ */
+
+function hash(sess) {
+  // serialize
+  var str = JSON.stringify(sess, function (key, val) {
+    // ignore sess.cookie property
+    if (this === sess && key === 'cookie') {
+      return
+    }
+
+    return val
+  })
+
+  // hash
+  return crypto
+    .createHash('sha1')
+    .update(str, 'utf8')
+    .digest('hex')
+}
+
+/**
+ * Determine if request is secure.
+ *
+ * @param {Object} req
+ * @param {Boolean} [trustProxy]
+ * @return {Boolean}
+ * @private
+ */
+
+function issecure(req, trustProxy) {
+  // socket is https server
+  if (req.connection && req.connection.encrypted) {
+    return true;
+  }
+
+  // do not trust proxy
+  if (trustProxy === false) {
+    return false;
+  }
+
+  // no explicit trust; try req.secure from express
+  if (trustProxy !== true) {
+    return req.secure === true
+  }
+
+  // read the proto from x-forwarded-proto header
+  var header = req.headers['x-forwarded-proto'] || '';
+  var index = header.indexOf(',');
+  var proto = index !== -1
+    ? header.substr(0, index).toLowerCase().trim()
+    : header.toLowerCase().trim()
+
+  return proto === 'https';
+}
+
+/**
+ * Set cookie on response.
+ *
+ * @private
+ */
+
+function setcookie(res, name, val, secret, options) {
+  var signed = 's:' + signature.sign(val, secret);
+  var data = cookie.serialize(name, signed, options);
+
+  debug('set-cookie %s', data);
+
+  var prev = res.getHeader('Set-Cookie') || []
+  var header = Array.isArray(prev) ? prev.concat(data) : [prev, data];
+
+  res.setHeader('Set-Cookie', header)
+}
+
+/**
+ * Verify and decode the given `val` with `secrets`.
+ *
+ * @param {String} val
+ * @param {Array} secrets
+ * @returns {String|Boolean}
+ * @private
+ */
+function unsigncookie(val, secrets) {
+  for (var i = 0; i < secrets.length; i++) {
+    var result = signature.unsign(val, secrets[i]);
+
+    if (result !== false) {
+      return result;
+    }
+  }
+
+  return false;
+}
Index: backend/node_modules/express-session/node_modules/cookie-signature/History.md
===================================================================
--- backend/node_modules/express-session/node_modules/cookie-signature/History.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie-signature/History.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,42 @@
+1.0.7 / 2023-04-12
+==================
+
+* backport the buffer support from the 1.2.x release branch (thanks @FadhiliNjagi!)
+
+1.0.6 / 2015-02-03
+==================
+
+* use `npm test` instead of `make test` to run tests
+* clearer assertion messages when checking input
+
+1.0.5 / 2014-09-05
+==================
+
+* add license to package.json
+
+1.0.4 / 2014-06-25
+==================
+
+ * corrected avoidance of timing attacks (thanks @tenbits!)
+
+1.0.3 / 2014-01-28
+==================
+
+ * [incorrect] fix for timing attacks
+
+1.0.2 / 2014-01-28
+==================
+
+ * fix missing repository warning
+ * fix typo in test
+
+1.0.1 / 2013-04-15
+==================
+
+  * Revert "Changed underlying HMAC algo. to sha512."
+  * Revert "Fix for timing attacks on MAC verification."
+
+0.0.1 / 2010-01-03
+==================
+
+  * Initial release
Index: backend/node_modules/express-session/node_modules/cookie-signature/Readme.md
===================================================================
--- backend/node_modules/express-session/node_modules/cookie-signature/Readme.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie-signature/Readme.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,42 @@
+
+# cookie-signature
+
+  Sign and unsign cookies.
+
+## Example
+
+```js
+var cookie = require('cookie-signature');
+
+var val = cookie.sign('hello', 'tobiiscool');
+val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI');
+
+var val = cookie.sign('hello', 'tobiiscool');
+cookie.unsign(val, 'tobiiscool').should.equal('hello');
+cookie.unsign(val, 'luna').should.be.false;
+```
+
+## License 
+
+(The MIT License)
+
+Copyright (c) 2012 LearnBoost &lt;tj@learnboost.com&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: backend/node_modules/express-session/node_modules/cookie-signature/index.js
===================================================================
--- backend/node_modules/express-session/node_modules/cookie-signature/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie-signature/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,51 @@
+/**
+ * Module dependencies.
+ */
+
+var crypto = require('crypto');
+
+/**
+ * Sign the given `val` with `secret`.
+ *
+ * @param {String} val
+ * @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} secret
+ * @return {String}
+ * @api private
+ */
+
+exports.sign = function(val, secret){
+  if ('string' !== typeof val) throw new TypeError("Cookie value must be provided as a string.");
+  if (null == secret) throw new TypeError("Secret key must be provided.");
+  return val + '.' + crypto
+    .createHmac('sha256', secret)
+    .update(val)
+    .digest('base64')
+    .replace(/\=+$/, '');
+};
+
+/**
+ * Unsign and decode the given `val` with `secret`,
+ * returning `false` if the signature is invalid.
+ *
+ * @param {String} val
+ * @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} secret
+ * @return {String|Boolean}
+ * @api private
+ */
+
+exports.unsign = function(val, secret){
+  if ('string' !== typeof val) throw new TypeError("Signed cookie string must be provided.");
+  if (null == secret) throw new TypeError("Secret key must be provided.");
+  var str = val.slice(0, val.lastIndexOf('.'))
+    , mac = exports.sign(str, secret);
+  
+  return sha1(mac) == sha1(val) ? str : false;
+};
+
+/**
+ * Private
+ */
+
+function sha1(str){
+  return crypto.createHash('sha1').update(str).digest('hex');
+}
Index: backend/node_modules/express-session/node_modules/cookie-signature/package.json
===================================================================
--- backend/node_modules/express-session/node_modules/cookie-signature/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie-signature/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,18 @@
+{
+  "name": "cookie-signature",
+  "version": "1.0.7",
+  "description": "Sign and unsign cookies",
+  "keywords": ["cookie", "sign", "unsign"],
+  "author": "TJ Holowaychuk <tj@learnboost.com>",
+  "license": "MIT",
+  "repository": { "type": "git", "url": "https://github.com/visionmedia/node-cookie-signature.git"},
+  "dependencies": {},
+  "devDependencies": {
+    "mocha": "*",
+    "should": "*"
+  },
+  "scripts": {
+    "test": "mocha --require should --reporter spec"
+  },
+  "main": "index"
+}
Index: backend/node_modules/express-session/node_modules/cookie/LICENSE
===================================================================
--- backend/node_modules/express-session/node_modules/cookie/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2012-2014 Roman Shtylman <shtylman@gmail.com>
+Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
Index: backend/node_modules/express-session/node_modules/cookie/README.md
===================================================================
--- backend/node_modules/express-session/node_modules/cookie/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,317 @@
+# cookie
+
+[![NPM Version][npm-version-image]][npm-url]
+[![NPM Downloads][npm-downloads-image]][npm-url]
+[![Node.js Version][node-image]][node-url]
+[![Build Status][ci-image]][ci-url]
+[![Coverage Status][coveralls-image]][coveralls-url]
+
+Basic HTTP cookie parser and serializer for HTTP servers.
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install cookie
+```
+
+## API
+
+```js
+var cookie = require('cookie');
+```
+
+### cookie.parse(str, options)
+
+Parse an HTTP `Cookie` header string and returning an object of all cookie name-value pairs.
+The `str` argument is the string representing a `Cookie` header value and `options` is an
+optional object containing additional parsing options.
+
+```js
+var cookies = cookie.parse('foo=bar; equation=E%3Dmc%5E2');
+// { foo: 'bar', equation: 'E=mc^2' }
+```
+
+#### Options
+
+`cookie.parse` accepts these properties in the options object.
+
+##### decode
+
+Specifies a function that will be used to decode a cookie's value. Since the value of a cookie
+has a limited character set (and must be a simple string), this function can be used to decode
+a previously-encoded cookie value into a JavaScript string or other object.
+
+The default function is the global `decodeURIComponent`, which will decode any URL-encoded
+sequences into their byte representations.
+
+**note** if an error is thrown from this function, the original, non-decoded cookie value will
+be returned as the cookie's value.
+
+### cookie.serialize(name, value, options)
+
+Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the
+name for the cookie, the `value` argument is the value to set the cookie to, and the `options`
+argument is an optional object containing additional serialization options.
+
+```js
+var setCookie = cookie.serialize('foo', 'bar');
+// foo=bar
+```
+
+#### Options
+
+`cookie.serialize` accepts these properties in the options object.
+
+##### domain
+
+Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6265-5.2.3]. By default, no
+domain is set, and most clients will consider the cookie to apply to only the current domain.
+
+##### encode
+
+Specifies a function that will be used to encode a cookie's value. Since value of a cookie
+has a limited character set (and must be a simple string), this function can be used to encode
+a value into a string suited for a cookie's value.
+
+The default function is the global `encodeURIComponent`, which will encode a JavaScript string
+into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range.
+
+##### expires
+
+Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6265-5.2.1].
+By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and
+will delete it on a condition like exiting a web browser application.
+
+**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
+`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
+so if both are set, they should point to the same date and time.
+
+##### httpOnly
+
+Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6265-5.2.6]. When truthy,
+the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set.
+
+**note** be careful when setting this to `true`, as compliant clients will not allow client-side
+JavaScript to see the cookie in `document.cookie`.
+
+##### maxAge
+
+Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6265-5.2.2].
+The given number will be converted to an integer by rounding down. By default, no maximum age is set.
+
+**note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and
+`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
+so if both are set, they should point to the same date and time.
+
+##### partitioned
+
+Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies)
+attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the
+`Partitioned` attribute is not set.
+
+**note** This is an attribute that has not yet been fully standardized, and may change in the future.
+This also means many clients may ignore this attribute until they understand it.
+
+More information about can be found in [the proposal](https://github.com/privacycg/CHIPS).
+
+##### path
+
+Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6265-5.2.4]. By default, the path
+is considered the ["default path"][rfc-6265-5.1.4].
+
+##### priority
+
+Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1].
+
+  - `'low'` will set the `Priority` attribute to `Low`.
+  - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
+  - `'high'` will set the `Priority` attribute to `High`.
+
+More information about the different priority levels can be found in
+[the specification][rfc-west-cookie-priority-00-4.1].
+
+**note** This is an attribute that has not yet been fully standardized, and may change in the future.
+This also means many clients may ignore this attribute until they understand it.
+
+##### sameSite
+
+Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][rfc-6265bis-09-5.4.7].
+
+  - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+  - `false` will not set the `SameSite` attribute.
+  - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
+  - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
+  - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+
+More information about the different enforcement levels can be found in
+[the specification][rfc-6265bis-09-5.4.7].
+
+**note** This is an attribute that has not yet been fully standardized, and may change in the future.
+This also means many clients may ignore this attribute until they understand it.
+
+##### secure
+
+Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6265-5.2.5]. When truthy,
+the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set.
+
+**note** be careful when setting this to `true`, as compliant clients will not send the cookie back to
+the server in the future if the browser does not have an HTTPS connection.
+
+## Example
+
+The following example uses this module in conjunction with the Node.js core HTTP server
+to prompt a user for their name and display it back on future visits.
+
+```js
+var cookie = require('cookie');
+var escapeHtml = require('escape-html');
+var http = require('http');
+var url = require('url');
+
+function onRequest(req, res) {
+  // Parse the query string
+  var query = url.parse(req.url, true, true).query;
+
+  if (query && query.name) {
+    // Set a new cookie with the name
+    res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), {
+      httpOnly: true,
+      maxAge: 60 * 60 * 24 * 7 // 1 week
+    }));
+
+    // Redirect back after setting cookie
+    res.statusCode = 302;
+    res.setHeader('Location', req.headers.referer || '/');
+    res.end();
+    return;
+  }
+
+  // Parse the cookies on the request
+  var cookies = cookie.parse(req.headers.cookie || '');
+
+  // Get the visitor name set in the cookie
+  var name = cookies.name;
+
+  res.setHeader('Content-Type', 'text/html; charset=UTF-8');
+
+  if (name) {
+    res.write('<p>Welcome back, <b>' + escapeHtml(name) + '</b>!</p>');
+  } else {
+    res.write('<p>Hello, new visitor!</p>');
+  }
+
+  res.write('<form method="GET">');
+  res.write('<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">');
+  res.end('</form>');
+}
+
+http.createServer(onRequest).listen(3000);
+```
+
+## Testing
+
+```sh
+$ npm test
+```
+
+## Benchmark
+
+```
+$ npm run bench
+
+> cookie@0.5.0 bench
+> node benchmark/index.js
+
+  node@18.18.2
+  acorn@8.10.0
+  ada@2.6.0
+  ares@1.19.1
+  brotli@1.0.9
+  cldr@43.1
+  icu@73.2
+  llhttp@6.0.11
+  modules@108
+  napi@9
+  nghttp2@1.57.0
+  nghttp3@0.7.0
+  ngtcp2@0.8.1
+  openssl@3.0.10+quic
+  simdutf@3.2.14
+  tz@2023c
+  undici@5.26.3
+  unicode@15.0
+  uv@1.44.2
+  uvwasi@0.0.18
+  v8@10.2.154.26-node.26
+  zlib@1.2.13.1-motley
+
+> node benchmark/parse-top.js
+
+  cookie.parse - top sites
+
+  14 tests completed.
+
+  parse accounts.google.com x 2,588,913 ops/sec ±0.74% (186 runs sampled)
+  parse apple.com           x 2,370,002 ops/sec ±0.69% (186 runs sampled)
+  parse cloudflare.com      x 2,213,102 ops/sec ±0.88% (188 runs sampled)
+  parse docs.google.com     x 2,194,157 ops/sec ±1.03% (184 runs sampled)
+  parse drive.google.com    x 2,265,084 ops/sec ±0.79% (187 runs sampled)
+  parse en.wikipedia.org    x   457,099 ops/sec ±0.81% (186 runs sampled)
+  parse linkedin.com        x   504,407 ops/sec ±0.89% (186 runs sampled)
+  parse maps.google.com     x 1,230,959 ops/sec ±0.98% (186 runs sampled)
+  parse microsoft.com       x   926,294 ops/sec ±0.88% (184 runs sampled)
+  parse play.google.com     x 2,311,338 ops/sec ±0.83% (185 runs sampled)
+  parse support.google.com  x 1,508,850 ops/sec ±0.86% (186 runs sampled)
+  parse www.google.com      x 1,022,582 ops/sec ±1.32% (182 runs sampled)
+  parse youtu.be            x   332,136 ops/sec ±1.02% (185 runs sampled)
+  parse youtube.com         x   323,833 ops/sec ±0.77% (183 runs sampled)
+
+> node benchmark/parse.js
+
+  cookie.parse - generic
+
+  6 tests completed.
+
+  simple      x 3,214,032 ops/sec ±1.61% (183 runs sampled)
+  decode      x   587,237 ops/sec ±1.16% (187 runs sampled)
+  unquote     x 2,954,618 ops/sec ±1.35% (183 runs sampled)
+  duplicates  x   857,008 ops/sec ±0.89% (187 runs sampled)
+  10 cookies  x   292,133 ops/sec ±0.89% (187 runs sampled)
+  100 cookies x    22,610 ops/sec ±0.68% (187 runs sampled)
+```
+
+## References
+
+- [RFC 6265: HTTP State Management Mechanism][rfc-6265]
+- [Same-site Cookies][rfc-6265bis-09-5.4.7]
+
+[rfc-cutler-httpbis-partitioned-cookies]: https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/
+[rfc-west-cookie-priority-00-4.1]: https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1
+[rfc-6265bis-09-5.4.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7
+[rfc-6265]: https://tools.ietf.org/html/rfc6265
+[rfc-6265-5.1.4]: https://tools.ietf.org/html/rfc6265#section-5.1.4
+[rfc-6265-5.2.1]: https://tools.ietf.org/html/rfc6265#section-5.2.1
+[rfc-6265-5.2.2]: https://tools.ietf.org/html/rfc6265#section-5.2.2
+[rfc-6265-5.2.3]: https://tools.ietf.org/html/rfc6265#section-5.2.3
+[rfc-6265-5.2.4]: https://tools.ietf.org/html/rfc6265#section-5.2.4
+[rfc-6265-5.2.5]: https://tools.ietf.org/html/rfc6265#section-5.2.5
+[rfc-6265-5.2.6]: https://tools.ietf.org/html/rfc6265#section-5.2.6
+[rfc-6265-5.3]: https://tools.ietf.org/html/rfc6265#section-5.3
+
+## License
+
+[MIT](LICENSE)
+
+[ci-image]: https://badgen.net/github/checks/jshttp/cookie/master?label=ci
+[ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml
+[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/cookie/master
+[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master
+[node-image]: https://badgen.net/npm/node/cookie
+[node-url]: https://nodejs.org/en/download
+[npm-downloads-image]: https://badgen.net/npm/dm/cookie
+[npm-url]: https://npmjs.org/package/cookie
+[npm-version-image]: https://badgen.net/npm/v/cookie
Index: backend/node_modules/express-session/node_modules/cookie/SECURITY.md
===================================================================
--- backend/node_modules/express-session/node_modules/cookie/SECURITY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie/SECURITY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,25 @@
+# Security Policies and Procedures
+
+## Reporting a Bug
+
+The `cookie` team and community take all security bugs seriously. Thank
+you for improving the security of the project. We appreciate your efforts and
+responsible disclosure and will make every effort to acknowledge your
+contributions.
+
+Report security bugs by emailing the current owner(s) of `cookie`. This
+information can be found in the npm registry using the command
+`npm owner ls cookie`.
+If unsure or unable to get the information from the above, open an issue
+in the [project issue tracker](https://github.com/jshttp/cookie/issues)
+asking for the current contact information.
+
+To ensure the timely response to your report, please ensure that the entirety
+of the report is contained within the email body and not solely behind a web
+link or an attachment.
+
+At least one owner will acknowledge your email within 48 hours, and will send a
+more detailed response within 48 hours indicating the next steps in handling
+your report. After the initial reply to your report, the owners will
+endeavor to keep you informed of the progress towards a fix and full
+announcement, and may ask for additional information or guidance.
Index: backend/node_modules/express-session/node_modules/cookie/index.js
===================================================================
--- backend/node_modules/express-session/node_modules/cookie/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,335 @@
+/*!
+ * cookie
+ * Copyright(c) 2012-2014 Roman Shtylman
+ * Copyright(c) 2015 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module exports.
+ * @public
+ */
+
+exports.parse = parse;
+exports.serialize = serialize;
+
+/**
+ * Module variables.
+ * @private
+ */
+
+var __toString = Object.prototype.toString
+var __hasOwnProperty = Object.prototype.hasOwnProperty
+
+/**
+ * RegExp to match cookie-name in RFC 6265 sec 4.1.1
+ * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2
+ * which has been replaced by the token definition in RFC 7230 appendix B.
+ *
+ * cookie-name       = token
+ * token             = 1*tchar
+ * tchar             = "!" / "#" / "$" / "%" / "&" / "'" /
+ *                     "*" / "+" / "-" / "." / "^" / "_" /
+ *                     "`" / "|" / "~" / DIGIT / ALPHA
+ */
+
+var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
+
+/**
+ * RegExp to match cookie-value in RFC 6265 sec 4.1.1
+ *
+ * cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
+ * cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+ *                     ; US-ASCII characters excluding CTLs,
+ *                     ; whitespace DQUOTE, comma, semicolon,
+ *                     ; and backslash
+ */
+
+var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/;
+
+/**
+ * RegExp to match domain-value in RFC 6265 sec 4.1.1
+ *
+ * domain-value      = <subdomain>
+ *                     ; defined in [RFC1034], Section 3.5, as
+ *                     ; enhanced by [RFC1123], Section 2.1
+ * <subdomain>       = <label> | <subdomain> "." <label>
+ * <label>           = <let-dig> [ [ <ldh-str> ] <let-dig> ]
+ *                     Labels must be 63 characters or less.
+ *                     'let-dig' not 'letter' in the first char, per RFC1123
+ * <ldh-str>         = <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+ * <let-dig-hyp>     = <let-dig> | "-"
+ * <let-dig>         = <letter> | <digit>
+ * <letter>          = any one of the 52 alphabetic characters A through Z in
+ *                     upper case and a through z in lower case
+ * <digit>           = any one of the ten digits 0 through 9
+ *
+ * Keep support for leading dot: https://github.com/jshttp/cookie/issues/173
+ *
+ * > (Note that a leading %x2E ("."), if present, is ignored even though that
+ * character is not permitted, but a trailing %x2E ("."), if present, will
+ * cause the user agent to ignore the attribute.)
+ */
+
+var domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
+
+/**
+ * RegExp to match path-value in RFC 6265 sec 4.1.1
+ *
+ * path-value        = <any CHAR except CTLs or ";">
+ * CHAR              = %x01-7F
+ *                     ; defined in RFC 5234 appendix B.1
+ */
+
+var pathValueRegExp = /^[\u0020-\u003A\u003D-\u007E]*$/;
+
+/**
+ * Parse a cookie header.
+ *
+ * Parse the given cookie header string into an object
+ * The object has the various cookies as keys(names) => values
+ *
+ * @param {string} str
+ * @param {object} [opt]
+ * @return {object}
+ * @public
+ */
+
+function parse(str, opt) {
+  if (typeof str !== 'string') {
+    throw new TypeError('argument str must be a string');
+  }
+
+  var obj = {};
+  var len = str.length;
+  // RFC 6265 sec 4.1.1, RFC 2616 2.2 defines a cookie name consists of one char minimum, plus '='.
+  if (len < 2) return obj;
+
+  var dec = (opt && opt.decode) || decode;
+  var index = 0;
+  var eqIdx = 0;
+  var endIdx = 0;
+
+  do {
+    eqIdx = str.indexOf('=', index);
+    if (eqIdx === -1) break; // No more cookie pairs.
+
+    endIdx = str.indexOf(';', index);
+
+    if (endIdx === -1) {
+      endIdx = len;
+    } else if (eqIdx > endIdx) {
+      // backtrack on prior semicolon
+      index = str.lastIndexOf(';', eqIdx - 1) + 1;
+      continue;
+    }
+
+    var keyStartIdx = startIndex(str, index, eqIdx);
+    var keyEndIdx = endIndex(str, eqIdx, keyStartIdx);
+    var key = str.slice(keyStartIdx, keyEndIdx);
+
+    // only assign once
+    if (!__hasOwnProperty.call(obj, key)) {
+      var valStartIdx = startIndex(str, eqIdx + 1, endIdx);
+      var valEndIdx = endIndex(str, endIdx, valStartIdx);
+
+      if (str.charCodeAt(valStartIdx) === 0x22 /* " */ && str.charCodeAt(valEndIdx - 1) === 0x22 /* " */) {
+        valStartIdx++;
+        valEndIdx--;
+      }
+
+      var val = str.slice(valStartIdx, valEndIdx);
+      obj[key] = tryDecode(val, dec);
+    }
+
+    index = endIdx + 1
+  } while (index < len);
+
+  return obj;
+}
+
+function startIndex(str, index, max) {
+  do {
+    var code = str.charCodeAt(index);
+    if (code !== 0x20 /*   */ && code !== 0x09 /* \t */) return index;
+  } while (++index < max);
+  return max;
+}
+
+function endIndex(str, index, min) {
+  while (index > min) {
+    var code = str.charCodeAt(--index);
+    if (code !== 0x20 /*   */ && code !== 0x09 /* \t */) return index + 1;
+  }
+  return min;
+}
+
+/**
+ * Serialize data into a cookie header.
+ *
+ * Serialize a name value pair into a cookie string suitable for
+ * http headers. An optional options object specifies cookie parameters.
+ *
+ * serialize('foo', 'bar', { httpOnly: true })
+ *   => "foo=bar; httpOnly"
+ *
+ * @param {string} name
+ * @param {string} val
+ * @param {object} [opt]
+ * @return {string}
+ * @public
+ */
+
+function serialize(name, val, opt) {
+  var enc = (opt && opt.encode) || encodeURIComponent;
+
+  if (typeof enc !== 'function') {
+    throw new TypeError('option encode is invalid');
+  }
+
+  if (!cookieNameRegExp.test(name)) {
+    throw new TypeError('argument name is invalid');
+  }
+
+  var value = enc(val);
+
+  if (!cookieValueRegExp.test(value)) {
+    throw new TypeError('argument val is invalid');
+  }
+
+  var str = name + '=' + value;
+  if (!opt) return str;
+
+  if (null != opt.maxAge) {
+    var maxAge = Math.floor(opt.maxAge);
+
+    if (!isFinite(maxAge)) {
+      throw new TypeError('option maxAge is invalid')
+    }
+
+    str += '; Max-Age=' + maxAge;
+  }
+
+  if (opt.domain) {
+    if (!domainValueRegExp.test(opt.domain)) {
+      throw new TypeError('option domain is invalid');
+    }
+
+    str += '; Domain=' + opt.domain;
+  }
+
+  if (opt.path) {
+    if (!pathValueRegExp.test(opt.path)) {
+      throw new TypeError('option path is invalid');
+    }
+
+    str += '; Path=' + opt.path;
+  }
+
+  if (opt.expires) {
+    var expires = opt.expires
+
+    if (!isDate(expires) || isNaN(expires.valueOf())) {
+      throw new TypeError('option expires is invalid');
+    }
+
+    str += '; Expires=' + expires.toUTCString()
+  }
+
+  if (opt.httpOnly) {
+    str += '; HttpOnly';
+  }
+
+  if (opt.secure) {
+    str += '; Secure';
+  }
+
+  if (opt.partitioned) {
+    str += '; Partitioned'
+  }
+
+  if (opt.priority) {
+    var priority = typeof opt.priority === 'string'
+      ? opt.priority.toLowerCase() : opt.priority;
+
+    switch (priority) {
+      case 'low':
+        str += '; Priority=Low'
+        break
+      case 'medium':
+        str += '; Priority=Medium'
+        break
+      case 'high':
+        str += '; Priority=High'
+        break
+      default:
+        throw new TypeError('option priority is invalid')
+    }
+  }
+
+  if (opt.sameSite) {
+    var sameSite = typeof opt.sameSite === 'string'
+      ? opt.sameSite.toLowerCase() : opt.sameSite;
+
+    switch (sameSite) {
+      case true:
+        str += '; SameSite=Strict';
+        break;
+      case 'lax':
+        str += '; SameSite=Lax';
+        break;
+      case 'strict':
+        str += '; SameSite=Strict';
+        break;
+      case 'none':
+        str += '; SameSite=None';
+        break;
+      default:
+        throw new TypeError('option sameSite is invalid');
+    }
+  }
+
+  return str;
+}
+
+/**
+ * URL-decode string value. Optimized to skip native call when no %.
+ *
+ * @param {string} str
+ * @returns {string}
+ */
+
+function decode (str) {
+  return str.indexOf('%') !== -1
+    ? decodeURIComponent(str)
+    : str
+}
+
+/**
+ * Determine if value is a Date.
+ *
+ * @param {*} val
+ * @private
+ */
+
+function isDate (val) {
+  return __toString.call(val) === '[object Date]';
+}
+
+/**
+ * Try decoding a string using a decoding function.
+ *
+ * @param {string} str
+ * @param {function} decode
+ * @private
+ */
+
+function tryDecode(str, decode) {
+  try {
+    return decode(str);
+  } catch (e) {
+    return str;
+  }
+}
Index: backend/node_modules/express-session/node_modules/cookie/package.json
===================================================================
--- backend/node_modules/express-session/node_modules/cookie/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/node_modules/cookie/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,44 @@
+{
+  "name": "cookie",
+  "description": "HTTP server cookie parsing and serialization",
+  "version": "0.7.2",
+  "author": "Roman Shtylman <shtylman@gmail.com>",
+  "contributors": [
+    "Douglas Christopher Wilson <doug@somethingdoug.com>"
+  ],
+  "license": "MIT",
+  "keywords": [
+    "cookie",
+    "cookies"
+  ],
+  "repository": "jshttp/cookie",
+  "devDependencies": {
+    "beautify-benchmark": "0.2.4",
+    "benchmark": "2.1.4",
+    "eslint": "8.53.0",
+    "eslint-plugin-markdown": "3.0.1",
+    "mocha": "10.2.0",
+    "nyc": "15.1.0",
+    "safe-buffer": "5.2.1",
+    "top-sites": "1.1.194"
+  },
+  "files": [
+    "HISTORY.md",
+    "LICENSE",
+    "README.md",
+    "SECURITY.md",
+    "index.js"
+  ],
+  "main": "index.js",
+  "engines": {
+    "node": ">= 0.6"
+  },
+  "scripts": {
+    "bench": "node benchmark/index.js",
+    "lint": "eslint .",
+    "test": "mocha --reporter spec --bail --check-leaks test/",
+    "test-ci": "nyc --reporter=lcov --reporter=text npm test",
+    "test-cov": "nyc --reporter=html --reporter=text npm test",
+    "update-bench": "node scripts/update-benchmark.js"
+  }
+}
Index: backend/node_modules/express-session/package.json
===================================================================
--- backend/node_modules/express-session/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,47 @@
+{
+  "name": "express-session",
+  "version": "1.18.2",
+  "description": "Simple session middleware for Express",
+  "author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
+  "contributors": [
+    "Douglas Christopher Wilson <doug@somethingdoug.com>",
+    "Joe Wagner <njwjs722@gmail.com>"
+  ],
+  "repository": "expressjs/session",
+  "license": "MIT",
+  "dependencies": {
+    "cookie": "0.7.2",
+    "cookie-signature": "1.0.7",
+    "debug": "2.6.9",
+    "depd": "~2.0.0",
+    "on-headers": "~1.1.0",
+    "parseurl": "~1.3.3",
+    "safe-buffer": "5.2.1",
+    "uid-safe": "~2.1.5"
+  },
+  "devDependencies": {
+    "after": "0.8.2",
+    "cookie-parser": "1.4.6",
+    "eslint": "8.56.0",
+    "eslint-plugin-markdown": "3.0.1",
+    "express": "4.17.3",
+    "mocha": "10.8.2",
+    "nyc": "15.1.0",
+    "supertest": "6.3.4"
+  },
+  "files": [
+    "session/",
+    "HISTORY.md",
+    "index.js"
+  ],
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "lint": "eslint . && node ./scripts/lint-readme.js",
+    "test": "./test/support/gencert.sh && mocha --require test/support/env --check-leaks --bail --no-exit --reporter spec test/",
+    "test-ci": "nyc --reporter=lcov --reporter=text npm test",
+    "test-cov": "nyc npm test",
+    "version": "node scripts/version-history.js && git add HISTORY.md"
+  }
+}
Index: backend/node_modules/express-session/session/cookie.js
===================================================================
--- backend/node_modules/express-session/session/cookie.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/session/cookie.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,152 @@
+/*!
+ * Connect - session - Cookie
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module dependencies.
+ */
+
+var cookie = require('cookie')
+var deprecate = require('depd')('express-session')
+
+/**
+ * Initialize a new `Cookie` with the given `options`.
+ *
+ * @param {IncomingMessage} req
+ * @param {Object} options
+ * @api private
+ */
+
+var Cookie = module.exports = function Cookie(options) {
+  this.path = '/';
+  this.maxAge = null;
+  this.httpOnly = true;
+
+  if (options) {
+    if (typeof options !== 'object') {
+      throw new TypeError('argument options must be a object')
+    }
+
+    for (var key in options) {
+      if (key !== 'data') {
+        this[key] = options[key]
+      }
+    }
+  }
+
+  if (this.originalMaxAge === undefined || this.originalMaxAge === null) {
+    this.originalMaxAge = this.maxAge
+  }
+};
+
+/*!
+ * Prototype.
+ */
+
+Cookie.prototype = {
+
+  /**
+   * Set expires `date`.
+   *
+   * @param {Date} date
+   * @api public
+   */
+
+  set expires(date) {
+    this._expires = date;
+    this.originalMaxAge = this.maxAge;
+  },
+
+  /**
+   * Get expires `date`.
+   *
+   * @return {Date}
+   * @api public
+   */
+
+  get expires() {
+    return this._expires;
+  },
+
+  /**
+   * Set expires via max-age in `ms`.
+   *
+   * @param {Number} ms
+   * @api public
+   */
+
+  set maxAge(ms) {
+    if (ms && typeof ms !== 'number' && !(ms instanceof Date)) {
+      throw new TypeError('maxAge must be a number or Date')
+    }
+
+    if (ms instanceof Date) {
+      deprecate('maxAge as Date; pass number of milliseconds instead')
+    }
+
+    this.expires = typeof ms === 'number'
+      ? new Date(Date.now() + ms)
+      : ms;
+  },
+
+  /**
+   * Get expires max-age in `ms`.
+   *
+   * @return {Number}
+   * @api public
+   */
+
+  get maxAge() {
+    return this.expires instanceof Date
+      ? this.expires.valueOf() - Date.now()
+      : this.expires;
+  },
+
+  /**
+   * Return cookie data object.
+   *
+   * @return {Object}
+   * @api private
+   */
+
+  get data() {
+    return {
+      originalMaxAge: this.originalMaxAge,
+      partitioned: this.partitioned,
+      priority: this.priority
+      , expires: this._expires
+      , secure: this.secure
+      , httpOnly: this.httpOnly
+      , domain: this.domain
+      , path: this.path
+      , sameSite: this.sameSite
+    }
+  },
+
+  /**
+   * Return a serialized cookie string.
+   *
+   * @return {String}
+   * @api public
+   */
+
+  serialize: function(name, val){
+    return cookie.serialize(name, val, this.data);
+  },
+
+  /**
+   * Return JSON representation of this cookie.
+   *
+   * @return {Object}
+   * @api private
+   */
+
+  toJSON: function(){
+    return this.data;
+  }
+};
Index: backend/node_modules/express-session/session/memory.js
===================================================================
--- backend/node_modules/express-session/session/memory.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/session/memory.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,187 @@
+/*!
+ * express-session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2015 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var Store = require('./store')
+var util = require('util')
+
+/**
+ * Shim setImmediate for node.js < 0.10
+ * @private
+ */
+
+/* istanbul ignore next */
+var defer = typeof setImmediate === 'function'
+  ? setImmediate
+  : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
+
+/**
+ * Module exports.
+ */
+
+module.exports = MemoryStore
+
+/**
+ * A session store in memory.
+ * @public
+ */
+
+function MemoryStore() {
+  Store.call(this)
+  this.sessions = Object.create(null)
+}
+
+/**
+ * Inherit from Store.
+ */
+
+util.inherits(MemoryStore, Store)
+
+/**
+ * Get all active sessions.
+ *
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.all = function all(callback) {
+  var sessionIds = Object.keys(this.sessions)
+  var sessions = Object.create(null)
+
+  for (var i = 0; i < sessionIds.length; i++) {
+    var sessionId = sessionIds[i]
+    var session = getSession.call(this, sessionId)
+
+    if (session) {
+      sessions[sessionId] = session;
+    }
+  }
+
+  callback && defer(callback, null, sessions)
+}
+
+/**
+ * Clear all sessions.
+ *
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.clear = function clear(callback) {
+  this.sessions = Object.create(null)
+  callback && defer(callback)
+}
+
+/**
+ * Destroy the session associated with the given session ID.
+ *
+ * @param {string} sessionId
+ * @public
+ */
+
+MemoryStore.prototype.destroy = function destroy(sessionId, callback) {
+  delete this.sessions[sessionId]
+  callback && defer(callback)
+}
+
+/**
+ * Fetch session by the given session ID.
+ *
+ * @param {string} sessionId
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.get = function get(sessionId, callback) {
+  defer(callback, null, getSession.call(this, sessionId))
+}
+
+/**
+ * Commit the given session associated with the given sessionId to the store.
+ *
+ * @param {string} sessionId
+ * @param {object} session
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.set = function set(sessionId, session, callback) {
+  this.sessions[sessionId] = JSON.stringify(session)
+  callback && defer(callback)
+}
+
+/**
+ * Get number of active sessions.
+ *
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.length = function length(callback) {
+  this.all(function (err, sessions) {
+    if (err) return callback(err)
+    callback(null, Object.keys(sessions).length)
+  })
+}
+
+/**
+ * Touch the given session object associated with the given session ID.
+ *
+ * @param {string} sessionId
+ * @param {object} session
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.touch = function touch(sessionId, session, callback) {
+  var currentSession = getSession.call(this, sessionId)
+
+  if (currentSession) {
+    // update expiration
+    currentSession.cookie = session.cookie
+    this.sessions[sessionId] = JSON.stringify(currentSession)
+  }
+
+  callback && defer(callback)
+}
+
+/**
+ * Get session from the store.
+ * @private
+ */
+
+function getSession(sessionId) {
+  var sess = this.sessions[sessionId]
+
+  if (!sess) {
+    return
+  }
+
+  // parse
+  sess = JSON.parse(sess)
+
+  if (sess.cookie) {
+    var expires = typeof sess.cookie.expires === 'string'
+      ? new Date(sess.cookie.expires)
+      : sess.cookie.expires
+
+    // destroy expired session
+    if (expires && expires <= Date.now()) {
+      delete this.sessions[sessionId]
+      return
+    }
+  }
+
+  return sess
+}
Index: backend/node_modules/express-session/session/session.js
===================================================================
--- backend/node_modules/express-session/session/session.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/session/session.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,143 @@
+/*!
+ * Connect - session - Session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Expose Session.
+ */
+
+module.exports = Session;
+
+/**
+ * Create a new `Session` with the given request and `data`.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} data
+ * @api private
+ */
+
+function Session(req, data) {
+  Object.defineProperty(this, 'req', { value: req });
+  Object.defineProperty(this, 'id', { value: req.sessionID });
+
+  if (typeof data === 'object' && data !== null) {
+    // merge data into this, ignoring prototype properties
+    for (var prop in data) {
+      if (!(prop in this)) {
+        this[prop] = data[prop]
+      }
+    }
+  }
+}
+
+/**
+ * Update reset `.cookie.maxAge` to prevent
+ * the cookie from expiring when the
+ * session is still active.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'touch', function touch() {
+  return this.resetMaxAge();
+});
+
+/**
+ * Reset `.maxAge` to `.originalMaxAge`.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'resetMaxAge', function resetMaxAge() {
+  this.cookie.maxAge = this.cookie.originalMaxAge;
+  return this;
+});
+
+/**
+ * Save the session data with optional callback `fn(err)`.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'save', function save(fn) {
+  this.req.sessionStore.set(this.id, this, fn || function(){});
+  return this;
+});
+
+/**
+ * Re-loads the session data _without_ altering
+ * the maxAge properties. Invokes the callback `fn(err)`,
+ * after which time if no exception has occurred the
+ * `req.session` property will be a new `Session` object,
+ * although representing the same session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'reload', function reload(fn) {
+  var req = this.req
+  var store = this.req.sessionStore
+
+  store.get(this.id, function(err, sess){
+    if (err) return fn(err);
+    if (!sess) return fn(new Error('failed to load session'));
+    store.createSession(req, sess);
+    fn();
+  });
+  return this;
+});
+
+/**
+ * Destroy `this` session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'destroy', function destroy(fn) {
+  delete this.req.session;
+  this.req.sessionStore.destroy(this.id, fn);
+  return this;
+});
+
+/**
+ * Regenerate this request's session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'regenerate', function regenerate(fn) {
+  this.req.sessionStore.regenerate(this.req, fn);
+  return this;
+});
+
+/**
+ * Helper function for creating a method on a prototype.
+ *
+ * @param {Object} obj
+ * @param {String} name
+ * @param {Function} fn
+ * @private
+ */
+function defineMethod(obj, name, fn) {
+  Object.defineProperty(obj, name, {
+    configurable: true,
+    enumerable: false,
+    value: fn,
+    writable: true
+  });
+};
Index: backend/node_modules/express-session/session/store.js
===================================================================
--- backend/node_modules/express-session/session/store.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/express-session/session/store.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,102 @@
+/*!
+ * Connect - session - Store
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var Cookie = require('./cookie')
+var EventEmitter = require('events').EventEmitter
+var Session = require('./session')
+var util = require('util')
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = Store
+
+/**
+ * Abstract base class for session stores.
+ * @public
+ */
+
+function Store () {
+  EventEmitter.call(this)
+}
+
+/**
+ * Inherit from EventEmitter.
+ */
+
+util.inherits(Store, EventEmitter)
+
+/**
+ * Re-generate the given requests's session.
+ *
+ * @param {IncomingRequest} req
+ * @return {Function} fn
+ * @api public
+ */
+
+Store.prototype.regenerate = function(req, fn){
+  var self = this;
+  this.destroy(req.sessionID, function(err){
+    self.generate(req);
+    fn(err);
+  });
+};
+
+/**
+ * Load a `Session` instance via the given `sid`
+ * and invoke the callback `fn(err, sess)`.
+ *
+ * @param {String} sid
+ * @param {Function} fn
+ * @api public
+ */
+
+Store.prototype.load = function(sid, fn){
+  var self = this;
+  this.get(sid, function(err, sess){
+    if (err) return fn(err);
+    if (!sess) return fn();
+    var req = { sessionID: sid, sessionStore: self };
+    fn(null, self.createSession(req, sess))
+  });
+};
+
+/**
+ * Create session from JSON `sess` data.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} sess
+ * @return {Session}
+ * @api private
+ */
+
+Store.prototype.createSession = function(req, sess){
+  var expires = sess.cookie.expires
+  var originalMaxAge = sess.cookie.originalMaxAge
+
+  sess.cookie = new Cookie(sess.cookie);
+
+  if (typeof expires === 'string') {
+    // convert expires to a Date object
+    sess.cookie.expires = new Date(expires)
+  }
+
+  // keep originalMaxAge intact
+  sess.cookie.originalMaxAge = originalMaxAge
+
+  req.session = new Session(req, sess);
+  return req.session;
+};
Index: backend/node_modules/on-headers/HISTORY.md
===================================================================
--- backend/node_modules/on-headers/HISTORY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/on-headers/HISTORY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,26 @@
+1.1.0 / 2025-07-17
+==================
+  * - Fix [CVE-2025-7339](https://www.cve.org/CVERecord?id=CVE-2025-7339) ([GHSA-76c9-3jph-rj3q](https://github.com/expressjs/multer/security/advisories/GHSA-76c9-3jph-rj3q))
+
+
+1.0.2 / 2019-02-21
+==================
+
+  * Fix `res.writeHead` patch missing return value
+
+1.0.1 / 2015-09-29
+==================
+
+  * perf: enable strict mode
+
+1.0.0 / 2014-08-10
+==================
+
+  * Honor `res.statusCode` change in `listener`
+  * Move to `jshttp` organization
+  * Prevent `arguments`-related de-opt
+
+0.0.0 / 2014-05-13
+==================
+
+  * Initial implementation
Index: backend/node_modules/on-headers/LICENSE
===================================================================
--- backend/node_modules/on-headers/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/on-headers/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2014 Douglas Christopher Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: backend/node_modules/on-headers/README.md
===================================================================
--- backend/node_modules/on-headers/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/on-headers/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,81 @@
+# on-headers
+
+[![NPM Version][npm-version-image]][npm-url]
+[![NPM Downloads][npm-downloads-image]][npm-url]
+[![Node.js Version][node-image]][node-url]
+[![Build Status][ci-image]][ci-url]
+[![Coverage Status][coveralls-image]][coveralls-url]
+
+Execute a listener when a response is about to write headers.
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install on-headers
+```
+
+## API
+
+<!-- eslint-disable no-unused-vars -->
+
+```js
+var onHeaders = require('on-headers')
+```
+
+### onHeaders(res, listener)
+
+This will add the listener `listener` to fire when headers are emitted for `res`.
+The listener is passed the `response` object as it's context (`this`). Headers are
+considered to be emitted only once, right before they are sent to the client.
+
+When this is called multiple times on the same `res`, the `listener`s are fired
+in the reverse order they were added.
+
+## Examples
+
+```js
+var http = require('http')
+var onHeaders = require('on-headers')
+
+http
+  .createServer(onRequest)
+  .listen(3000)
+
+function addPoweredBy () {
+  // set if not set by end of request
+  if (!this.getHeader('X-Powered-By')) {
+    this.setHeader('X-Powered-By', 'Node.js')
+  }
+}
+
+function onRequest (req, res) {
+  onHeaders(res, addPoweredBy)
+
+  res.setHeader('Content-Type', 'text/plain')
+  res.end('hello!')
+}
+```
+
+## Testing
+
+```sh
+$ npm test
+```
+
+## License
+
+[MIT](LICENSE)
+
+[ci-image]: https://badgen.net/github/checks/jshttp/on-headers/master?label=ci
+[ci-url]: https://github.com/jshttp/on-headers/actions/workflows/ci.yml
+[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/on-headers/master
+[coveralls-url]: https://coveralls.io/r/jshttp/on-headers?branch=master
+[node-image]: https://badgen.net/npm/node/on-headers
+[node-url]: https://nodejs.org/en/download
+[npm-downloads-image]: https://badgen.net/npm/dm/on-headers
+[npm-url]: https://npmjs.org/package/on-headers
+[npm-version-image]: https://badgen.net/npm/v/on-headers
Index: backend/node_modules/on-headers/index.js
===================================================================
--- backend/node_modules/on-headers/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/on-headers/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,180 @@
+/*!
+ * on-headers
+ * Copyright(c) 2014 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = onHeaders
+
+var http = require('http')
+
+// older node versions don't have appendHeader
+var isAppendHeaderSupported = typeof http.ServerResponse.prototype.appendHeader === 'function'
+var set1dArray = isAppendHeaderSupported ? set1dArrayWithAppend : set1dArrayWithSet
+
+/**
+ * Create a replacement writeHead method.
+ *
+ * @param {function} prevWriteHead
+ * @param {function} listener
+ * @private
+ */
+
+function createWriteHead (prevWriteHead, listener) {
+  var fired = false
+
+  // return function with core name and argument list
+  return function writeHead (statusCode) {
+    // set headers from arguments
+    var args = setWriteHeadHeaders.apply(this, arguments)
+
+    // fire listener
+    if (!fired) {
+      fired = true
+      listener.call(this)
+
+      // pass-along an updated status code
+      if (typeof args[0] === 'number' && this.statusCode !== args[0]) {
+        args[0] = this.statusCode
+        args.length = 1
+      }
+    }
+
+    return prevWriteHead.apply(this, args)
+  }
+}
+
+/**
+ * Execute a listener when a response is about to write headers.
+ *
+ * @param {object} res
+ * @return {function} listener
+ * @public
+ */
+
+function onHeaders (res, listener) {
+  if (!res) {
+    throw new TypeError('argument res is required')
+  }
+
+  if (typeof listener !== 'function') {
+    throw new TypeError('argument listener must be a function')
+  }
+
+  res.writeHead = createWriteHead(res.writeHead, listener)
+}
+
+/**
+ * Set headers contained in array on the response object.
+ *
+ * @param {object} res
+ * @param {array} headers
+ * @private
+ */
+
+function setHeadersFromArray (res, headers) {
+  if (headers.length && Array.isArray(headers[0])) {
+    // 2D
+    set2dArray(res, headers)
+  } else {
+    // 1D
+    if (headers.length % 2 !== 0) {
+      throw new TypeError('headers array is malformed')
+    }
+
+    set1dArray(res, headers)
+  }
+}
+
+/**
+ * Set headers contained in object on the response object.
+ *
+ * @param {object} res
+ * @param {object} headers
+ * @private
+ */
+
+function setHeadersFromObject (res, headers) {
+  var keys = Object.keys(headers)
+  for (var i = 0; i < keys.length; i++) {
+    var k = keys[i]
+    if (k) res.setHeader(k, headers[k])
+  }
+}
+
+/**
+ * Set headers and other properties on the response object.
+ *
+ * @param {number} statusCode
+ * @private
+ */
+
+function setWriteHeadHeaders (statusCode) {
+  var length = arguments.length
+  var headerIndex = length > 1 && typeof arguments[1] === 'string'
+    ? 2
+    : 1
+
+  var headers = length >= headerIndex + 1
+    ? arguments[headerIndex]
+    : undefined
+
+  this.statusCode = statusCode
+
+  if (Array.isArray(headers)) {
+    // handle array case
+    setHeadersFromArray(this, headers)
+  } else if (headers) {
+    // handle object case
+    setHeadersFromObject(this, headers)
+  }
+
+  // copy leading arguments
+  var args = new Array(Math.min(length, headerIndex))
+  for (var i = 0; i < args.length; i++) {
+    args[i] = arguments[i]
+  }
+
+  return args
+}
+
+function set2dArray (res, headers) {
+  var key
+  for (var i = 0; i < headers.length; i++) {
+    key = headers[i][0]
+    if (key) {
+      res.setHeader(key, headers[i][1])
+    }
+  }
+}
+
+function set1dArrayWithAppend (res, headers) {
+  for (var i = 0; i < headers.length; i += 2) {
+    res.removeHeader(headers[i])
+  }
+
+  var key
+  for (var j = 0; j < headers.length; j += 2) {
+    key = headers[j]
+    if (key) {
+      res.appendHeader(key, headers[j + 1])
+    }
+  }
+}
+
+function set1dArrayWithSet (res, headers) {
+  var key
+  for (var i = 0; i < headers.length; i += 2) {
+    key = headers[i]
+    if (key) {
+      res.setHeader(key, headers[i + 1])
+    }
+  }
+}
Index: backend/node_modules/on-headers/package.json
===================================================================
--- backend/node_modules/on-headers/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/on-headers/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,44 @@
+{
+  "name": "on-headers",
+  "description": "Execute a listener when a response is about to write headers",
+  "version": "1.1.0",
+  "author": "Douglas Christopher Wilson <doug@somethingdoug.com>",
+  "license": "MIT",
+  "keywords": [
+    "event",
+    "headers",
+    "http",
+    "onheaders"
+  ],
+  "repository": "jshttp/on-headers",
+  "devDependencies": {
+    "eslint": "6.8.0",
+    "eslint-config-standard": "14.1.1",
+    "eslint-plugin-import": "2.21.2",
+    "eslint-plugin-markdown": "1.0.2",
+    "eslint-plugin-node": "11.1.0",
+    "eslint-plugin-promise": "4.2.1",
+    "eslint-plugin-standard": "4.0.1",
+    "mocha": "10.2.0",
+    "nyc": "15.1.0",
+    "supertest": "4.0.2"
+  },
+  "files": [
+    "LICENSE",
+    "HISTORY.md",
+    "README.md",
+    "index.js"
+  ],
+  "engines": {
+    "node": ">= 0.8"
+  },
+  "scripts": {
+    "lint": "eslint --plugin markdown --ext js,md .",
+    "test": "mocha --reporter spec --check-leaks test/test.js",
+    "test-ci": "nyc --reporter=lcov --reporter=text npm test",
+    "test-cov": "nyc --reporter=html --reporter=text npm test",
+    "update-upstream-hashes": "node scripts/update-upstream-hashes.js",
+    "upstream": "mocha --reporter spec --check-leaks test/upstream.js",
+    "version": "node scripts/version-history.js && git add HISTORY.md"
+  }
+}
Index: backend/node_modules/random-bytes/HISTORY.md
===================================================================
--- backend/node_modules/random-bytes/HISTORY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/random-bytes/HISTORY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,4 @@
+1.0.0 / 2016-01-17
+==================
+
+  * Initial release
Index: backend/node_modules/random-bytes/LICENSE
===================================================================
--- backend/node_modules/random-bytes/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/random-bytes/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Douglas Christopher Wilson <doug@somethingdoug.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: backend/node_modules/random-bytes/README.md
===================================================================
--- backend/node_modules/random-bytes/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/random-bytes/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,77 @@
+# random-bytes
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Node.js Version][node-version-image]][node-version-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+Generate strong pseudo-random bytes.
+
+This module is a simple wrapper around the Node.js core `crypto.randomBytes` API,
+with the following additions:
+
+  * A `Promise` interface for environments with promises.
+  * For Node.js versions that do not wait for the PRNG to be seeded, this module
+    will wait a bit.
+
+## Installation
+
+```sh
+$ npm install random-bytes
+```
+
+## API
+
+```js
+var randomBytes = require('random-bytes')
+```
+
+### randomBytes(size, callback)
+
+Generates strong pseudo-random bytes. The `size` argument is a number indicating
+the number of bytes to generate.
+
+```js
+randomBytes(12, function (error, bytes) {
+  if (error) throw error
+  // do something with the bytes
+})
+```
+
+### randomBytes(size)
+
+Generates strong pseudo-random bytes and return a `Promise`. The `size` argument is
+a number indicating the number of bytes to generate.
+
+**Note**: To use promises in Node.js _prior to 0.12_, promises must be
+"polyfilled" using `global.Promise = require('bluebird')`.
+
+```js
+randomBytes(18).then(function (string) {
+  // do something with the string
+})
+```
+
+### randomBytes.sync(size)
+
+A synchronous version of above.
+
+```js
+var bytes = randomBytes.sync(18)
+```
+
+## License
+
+[MIT](LICENSE)
+
+[npm-image]: https://img.shields.io/npm/v/random-bytes.svg
+[npm-url]: https://npmjs.org/package/random-bytes
+[node-version-image]: https://img.shields.io/node/v/random-bytes.svg
+[node-version-url]: http://nodejs.org/download/
+[travis-image]: https://img.shields.io/travis/crypto-utils/random-bytes/master.svg
+[travis-url]: https://travis-ci.org/crypto-utils/random-bytes
+[coveralls-image]: https://img.shields.io/coveralls/crypto-utils/random-bytes/master.svg
+[coveralls-url]: https://coveralls.io/r/crypto-utils/random-bytes?branch=master
+[downloads-image]: https://img.shields.io/npm/dm/random-bytes.svg
+[downloads-url]: https://npmjs.org/package/random-bytes
Index: backend/node_modules/random-bytes/index.js
===================================================================
--- backend/node_modules/random-bytes/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/random-bytes/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,101 @@
+/*!
+ * random-bytes
+ * Copyright(c) 2016 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var crypto = require('crypto')
+
+/**
+ * Module variables.
+ * @private
+ */
+
+var generateAttempts = crypto.randomBytes === crypto.pseudoRandomBytes ? 1 : 3
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = randomBytes
+module.exports.sync = randomBytesSync
+
+/**
+ * Generates strong pseudo-random bytes.
+ *
+ * @param {number} size
+ * @param {function} [callback]
+ * @return {Promise}
+ * @public
+ */
+
+function randomBytes(size, callback) {
+  // validate callback is a function, if provided
+  if (callback !== undefined && typeof callback !== 'function') {
+    throw new TypeError('argument callback must be a function')
+  }
+
+  // require the callback without promises
+  if (!callback && !global.Promise) {
+    throw new TypeError('argument callback is required')
+  }
+
+  if (callback) {
+    // classic callback style
+    return generateRandomBytes(size, generateAttempts, callback)
+  }
+
+  return new Promise(function executor(resolve, reject) {
+    generateRandomBytes(size, generateAttempts, function onRandomBytes(err, str) {
+      if (err) return reject(err)
+      resolve(str)
+    })
+  })
+}
+
+/**
+ * Generates strong pseudo-random bytes sync.
+ *
+ * @param {number} size
+ * @return {Buffer}
+ * @public
+ */
+
+function randomBytesSync(size) {
+  var err = null
+
+  for (var i = 0; i < generateAttempts; i++) {
+    try {
+      return crypto.randomBytes(size)
+    } catch (e) {
+      err = e
+    }
+  }
+
+  throw err
+}
+
+/**
+ * Generates strong pseudo-random bytes.
+ *
+ * @param {number} size
+ * @param {number} attempts
+ * @param {function} callback
+ * @private
+ */
+
+function generateRandomBytes(size, attempts, callback) {
+  crypto.randomBytes(size, function onRandomBytes(err, buf) {
+    if (!err) return callback(null, buf)
+    if (!--attempts) return callback(err)
+    setTimeout(generateRandomBytes.bind(null, size, attempts, callback), 10)
+  })
+}
Index: backend/node_modules/random-bytes/package.json
===================================================================
--- backend/node_modules/random-bytes/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/random-bytes/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,36 @@
+{
+  "name": "random-bytes",
+  "description": "URL and cookie safe UIDs",
+  "version": "1.0.0",
+  "contributors": [
+    "Douglas Christopher Wilson <doug@somethingdoug.com>"
+  ],
+  "license": "MIT",
+  "repository": "crypto-utils/random-bytes",
+  "devDependencies": {
+    "bluebird": "3.1.1",
+    "istanbul": "0.4.2",
+    "mocha": "2.3.4",
+    "proxyquire": "1.2.0"
+  },
+  "files": [
+    "LICENSE",
+    "HISTORY.md",
+    "README.md",
+    "index.js"
+  ],
+  "engines": {
+    "node": ">= 0.8"
+  },
+  "scripts": {
+    "test": "mocha --trace-deprecation --reporter spec --bail --check-leaks test/",
+    "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --trace-deprecation --reporter dot --check-leaks test/",
+    "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --trace-deprecation --reporter spec --check-leaks test/"
+  },
+  "keywords": [
+    "bytes",
+    "generator",
+    "random",
+    "safe"
+  ]
+}
Index: backend/node_modules/uid-safe/HISTORY.md
===================================================================
--- backend/node_modules/uid-safe/HISTORY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/uid-safe/HISTORY.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,61 @@
+2.1.5 / 2017-08-02
+==================
+
+  * perf: remove only trailing `=`
+
+2.1.4 / 2017-03-02
+==================
+
+  * Remove `base64-url` dependency
+
+2.1.3 / 2016-10-30
+==================
+
+  * deps: base64-url@1.3.3
+
+2.1.2 / 2016-08-15
+==================
+
+  * deps: base64-url@1.3.2
+
+2.1.1 / 2016-05-04
+==================
+
+  * deps: base64-url@1.2.2
+
+2.1.0 / 2016-01-17
+==================
+
+  * Use `random-bytes` for byte source
+
+2.0.0 / 2015-05-08
+==================
+
+  * Use global `Promise` when returning a promise
+
+1.1.0 / 2015-02-01
+==================
+
+  * Use `crypto.randomBytes`, if available
+  * deps: base64-url@1.2.1
+
+1.0.3 / 2015-01-31
+==================
+
+  * Fix error branch that would throw
+  * deps: base64-url@1.2.0
+
+1.0.2 / 2015-01-08
+==================
+
+  * Remove dependency on `mz`
+
+1.0.1 / 2014-06-18
+==================
+
+  * Remove direct `bluebird` dependency
+
+1.0.0 / 2014-06-18
+==================
+
+  * Initial release
Index: backend/node_modules/uid-safe/LICENSE
===================================================================
--- backend/node_modules/uid-safe/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/uid-safe/LICENSE	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>
+Copyright (c) 2015-2017 Douglas Christopher Wilson <doug@somethingdoug.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
Index: backend/node_modules/uid-safe/README.md
===================================================================
--- backend/node_modules/uid-safe/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/uid-safe/README.md	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,77 @@
+# uid-safe
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Node.js Version][node-version-image]][node-version-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+URL and cookie safe UIDs
+
+Create cryptographically secure UIDs safe for both cookie and URL usage.
+This is in contrast to modules such as [rand-token](https://www.npmjs.com/package/rand-token)
+and [uid2](https://www.npmjs.com/package/uid2) whose UIDs are actually skewed
+due to the use of `%` and unnecessarily truncate the UID.
+Use this if you could still use UIDs with `-` and `_` in them.
+
+## Installation
+
+```sh
+$ npm install uid-safe
+```
+
+## API
+
+```js
+var uid = require('uid-safe')
+```
+
+### uid(byteLength, callback)
+
+Asynchronously create a UID with a specific byte length. Because `base64`
+encoding is used underneath, this is not the string length. For example,
+to create a UID of length 24, you want a byte length of 18.
+
+```js
+uid(18, function (err, string) {
+  if (err) throw err
+  // do something with the string
+})
+```
+
+### uid(byteLength)
+
+Asynchronously create a UID with a specific byte length and return a
+`Promise`.
+
+**Note**: To use promises in Node.js _prior to 0.12_, promises must be
+"polyfilled" using `global.Promise = require('bluebird')`.
+
+```js
+uid(18).then(function (string) {
+  // do something with the string
+})
+```
+
+### uid.sync(byteLength)
+
+A synchronous version of above.
+
+```js
+var string = uid.sync(18)
+```
+
+## License
+
+[MIT](LICENSE)
+
+[npm-image]: https://img.shields.io/npm/v/uid-safe.svg
+[npm-url]: https://npmjs.org/package/uid-safe
+[node-version-image]: https://img.shields.io/node/v/uid-safe.svg
+[node-version-url]: https://nodejs.org/en/download/
+[travis-image]: https://img.shields.io/travis/crypto-utils/uid-safe/master.svg
+[travis-url]: https://travis-ci.org/crypto-utils/uid-safe
+[coveralls-image]: https://img.shields.io/coveralls/crypto-utils/uid-safe/master.svg
+[coveralls-url]: https://coveralls.io/r/crypto-utils/uid-safe?branch=master
+[downloads-image]: https://img.shields.io/npm/dm/uid-safe.svg
+[downloads-url]: https://npmjs.org/package/uid-safe
Index: backend/node_modules/uid-safe/index.js
===================================================================
--- backend/node_modules/uid-safe/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/uid-safe/index.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,107 @@
+/*!
+ * uid-safe
+ * Copyright(c) 2014 Jonathan Ong
+ * Copyright(c) 2015-2017 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var randomBytes = require('random-bytes')
+
+/**
+ * Module variables.
+ * @private
+ */
+
+var EQUAL_END_REGEXP = /=+$/
+var PLUS_GLOBAL_REGEXP = /\+/g
+var SLASH_GLOBAL_REGEXP = /\//g
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = uid
+module.exports.sync = uidSync
+
+/**
+ * Create a unique ID.
+ *
+ * @param {number} length
+ * @param {function} [callback]
+ * @return {Promise}
+ * @public
+ */
+
+function uid (length, callback) {
+  // validate callback is a function, if provided
+  if (callback !== undefined && typeof callback !== 'function') {
+    throw new TypeError('argument callback must be a function')
+  }
+
+  // require the callback without promises
+  if (!callback && !global.Promise) {
+    throw new TypeError('argument callback is required')
+  }
+
+  if (callback) {
+    // classic callback style
+    return generateUid(length, callback)
+  }
+
+  return new Promise(function executor (resolve, reject) {
+    generateUid(length, function onUid (err, str) {
+      if (err) return reject(err)
+      resolve(str)
+    })
+  })
+}
+
+/**
+ * Create a unique ID sync.
+ *
+ * @param {number} length
+ * @return {string}
+ * @public
+ */
+
+function uidSync (length) {
+  return toString(randomBytes.sync(length))
+}
+
+/**
+ * Generate a unique ID string.
+ *
+ * @param {number} length
+ * @param {function} callback
+ * @private
+ */
+
+function generateUid (length, callback) {
+  randomBytes(length, function (err, buf) {
+    if (err) return callback(err)
+    callback(null, toString(buf))
+  })
+}
+
+/**
+ * Change a Buffer into a string.
+ *
+ * @param {Buffer} buf
+ * @return {string}
+ * @private
+ */
+
+function toString (buf) {
+  return buf.toString('base64')
+    .replace(EQUAL_END_REGEXP, '')
+    .replace(PLUS_GLOBAL_REGEXP, '-')
+    .replace(SLASH_GLOBAL_REGEXP, '_')
+}
Index: backend/node_modules/uid-safe/package.json
===================================================================
--- backend/node_modules/uid-safe/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ backend/node_modules/uid-safe/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,46 @@
+{
+  "name": "uid-safe",
+  "description": "URL and cookie safe UIDs",
+  "version": "2.1.5",
+  "contributors": [
+    "Douglas Christopher Wilson <doug@somethingdoug.com>",
+    "Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
+  ],
+  "license": "MIT",
+  "repository": "crypto-utils/uid-safe",
+  "dependencies": {
+    "random-bytes": "~1.0.0"
+  },
+  "devDependencies": {
+    "bluebird": "3.5.0",
+    "eslint": "3.19.0",
+    "eslint-config-standard": "10.2.1",
+    "eslint-plugin-import": "2.7.0",
+    "eslint-plugin-node": "5.1.1",
+    "eslint-plugin-promise": "3.5.0",
+    "eslint-plugin-standard": "3.0.1",
+    "istanbul": "0.4.5",
+    "mocha": "2.5.3"
+  },
+  "files": [
+    "LICENSE",
+    "HISTORY.md",
+    "README.md",
+    "index.js"
+  ],
+  "engines": {
+    "node": ">= 0.8"
+  },
+  "scripts": {
+    "lint": "eslint .",
+    "test": "mocha --trace-deprecation --reporter spec --bail --check-leaks test/",
+    "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --trace-deprecation --reporter dot --check-leaks test/",
+    "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --trace-deprecation --reporter spec --check-leaks test/"
+  },
+  "keywords": [
+    "random",
+    "generator",
+    "uid",
+    "safe"
+  ]
+}
Index: backend/package-lock.json
===================================================================
--- backend/package-lock.json	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ backend/package-lock.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -12,4 +12,5 @@
         "cors": "^2.8.5",
         "express": "^4.18.2",
+        "express-session": "^1.18.2",
         "pg": "^8.11.3"
       },
@@ -346,4 +347,35 @@
       }
     },
+    "node_modules/express-session": {
+      "version": "1.18.2",
+      "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz",
+      "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==",
+      "dependencies": {
+        "cookie": "0.7.2",
+        "cookie-signature": "1.0.7",
+        "debug": "2.6.9",
+        "depd": "~2.0.0",
+        "on-headers": "~1.1.0",
+        "parseurl": "~1.3.3",
+        "safe-buffer": "5.2.1",
+        "uid-safe": "~2.1.5"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/express-session/node_modules/cookie": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+      "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/express-session/node_modules/cookie-signature": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+      "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="
+    },
     "node_modules/fill-range": {
       "version": "7.1.1",
@@ -757,4 +789,12 @@
       }
     },
+    "node_modules/on-headers": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
+      "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/packet-reader": {
       "version": "1.0.0",
@@ -935,4 +975,12 @@
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/random-bytes": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+      "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==",
+      "engines": {
+        "node": ">= 0.8"
       }
     },
@@ -1168,4 +1216,15 @@
       }
     },
+    "node_modules/uid-safe": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
+      "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
+      "dependencies": {
+        "random-bytes": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
     "node_modules/undefsafe": {
       "version": "2.0.5",
Index: backend/package.json
===================================================================
--- backend/package.json	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ backend/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -13,4 +13,5 @@
     "cors": "^2.8.5",
     "express": "^4.18.2",
+    "express-session": "^1.18.2",
     "pg": "^8.11.3"
   },
Index: frontend/package-lock.json
===================================================================
--- frontend/package-lock.json	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ frontend/package-lock.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -9,4 +9,5 @@
       "version": "0.1.0",
       "dependencies": {
+        "@chakra-ui/icons": "^2.2.4",
         "@chakra-ui/react": "^2.8.2",
         "@emotion/react": "^11.11.3",
@@ -2309,4 +2310,13 @@
       }
     },
+    "node_modules/@chakra-ui/icons": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.2.4.tgz",
+      "integrity": "sha512-l5QdBgwrAg3Sc2BRqtNkJpfuLw/pWRDwwT58J6c4PqQT6wzXxyNa8Q0PForu1ltB5qEiFb1kxr/F/HO1EwNa6g==",
+      "peerDependencies": {
+        "@chakra-ui/react": ">=2.0.0",
+        "react": ">=18"
+      }
+    },
     "node_modules/@chakra-ui/image": {
       "version": "2.1.0",
Index: frontend/package.json
===================================================================
--- frontend/package.json	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ frontend/package.json	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -4,4 +4,5 @@
   "private": true,
   "dependencies": {
+    "@chakra-ui/icons": "^2.2.4",
     "@chakra-ui/react": "^2.8.2",
     "@emotion/react": "^11.11.3",
Index: frontend/src/App.js
===================================================================
--- frontend/src/App.js	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ frontend/src/App.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -8,4 +8,16 @@
 import Agreements from "./pages/Agreements";
 import RegisterForm from "./pages/RegisterForm";
+import DealershipLogin from "./pages/DealershipLogin";
+import ClientLogin from "./pages/ClientLogin";
+import Login from "./pages/Login";
+import CreateAgreement from "./pages/CreateAgreement";
+import MyAgreements from "./pages/MyAgreements";
+import CreatePayment from "./pages/CreatePayment";
+import PaymentDetails from "./pages/PaymentDetails";
+import DealershipPayments from "./pages/DealershipPayments";
+import DealershipRegisterForm from "./pages/DealershipRegisterForm";
+import RegisterSelection from "./pages/RegisterSelection";
+import Documents from "./pages/Documents";
+import Reports from "./pages/Reports";
 import { Flex } from "@chakra-ui/react";
 
@@ -21,4 +33,16 @@
                         <Route path='registerform' element={<RegisterForm />} />
                         <Route path='agreement' element={<Agreement />} />
+                        <Route path='dealershiplogin' element={<DealershipLogin />} />
+                        <Route path='clientlogin' element={<ClientLogin />} />
+                        <Route path='login' element={<Login />} />
+                        <Route path='register' element={<RegisterSelection />} />
+                        <Route path='dealershipregister' element={<DealershipRegisterForm />} />
+                        <Route path='createagreement' element={<CreateAgreement />} />
+                        <Route path='myagreements' element={<MyAgreements />} />
+                        <Route path='createpayment' element={<CreatePayment />} />
+                        <Route path='paymentdetails' element={<PaymentDetails />} />
+                        <Route path='dealershippayments' element={<DealershipPayments />} />
+                        <Route path='documents' element={<Documents />} />
+                        <Route path='reports' element={<Reports />} />
                     </Route>
                 </Routes>
Index: frontend/src/components/SoldBlogCard.js
===================================================================
--- frontend/src/components/SoldBlogCard.js	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ frontend/src/components/SoldBlogCard.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -1,4 +1,13 @@
-import { Flex, Text, Button } from "@chakra-ui/react";
-import { Link } from "react-router-dom";
+import { Flex, Text, Button, useToast, useDisclosure } from "@chakra-ui/react";
+import { Link, useNavigate } from "react-router-dom";
+import {
+    AlertDialog,
+    AlertDialogBody,
+    AlertDialogFooter,
+    AlertDialogHeader,
+    AlertDialogContent,
+    AlertDialogOverlay,
+} from "@chakra-ui/react";
+import { useRef, useState } from "react";
 
 const SoldBlogCard = ({
@@ -13,5 +22,70 @@
     price,
     status,
+    onVehicleDeleted,
 }) => {
+    const navigate = useNavigate();
+    const toast = useToast();
+    const { isOpen, onOpen, onClose } = useDisclosure();
+    const cancelRef = useRef();
+    const [isDeleting, setIsDeleting] = useState(false);
+
+    const handleSetAsSold = () => {
+        const vehicleInfo = {
+            vin,
+            make: car_make,
+            model: car_model,
+            p_year: p_year.slice(1, -1),
+            price: price.slice(1, -1)
+        };
+        navigate("/createagreement", { state: { vin, vehicleInfo } });
+    };
+
+    const handleViewDocuments = () => {
+        navigate("/documents", { state: { vin } });
+    };
+
+    const handleDeleteVehicle = async () => {
+        setIsDeleting(true);
+        try {
+            const response = await fetch(`http://localhost:3001/vehicle/${vin}`, {
+                method: "DELETE",
+                credentials: 'include',
+            });
+
+            if (response.ok) {
+                toast({
+                    title: "Vehicle Deleted",
+                    description: "Vehicle has been successfully deleted from your inventory.",
+                    status: "success",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                onClose();
+                // Call the callback to refresh the vehicle list
+                if (onVehicleDeleted) {
+                    onVehicleDeleted();
+                }
+            } else {
+                const errorData = await response.json();
+                toast({
+                    title: "Error",
+                    description: errorData.error || "Failed to delete vehicle",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "An error occurred while deleting the vehicle",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setIsDeleting(false);
+        }
+    };
     return (
         <Flex
@@ -98,25 +172,68 @@
                             _hover={{
                                 background: "#fa5c7c",
-                            }}>
+                            }}
+                            onClick={handleSetAsSold}>
                             Set as Sold
                         </Button>
                     )}
                     {status == "false" ? (
-                        <Link to='../agreement' state={{ vin: vin }}>
-                            <Button
-                                bg='white'
-                                color='black'
-                                borderColor='#160085'
-                                borderWidth='3px'
-                                _hover={{
-                                    background: "#160085",
-                                    color: "white",
-                                }}>
-                                See Agreement
-                            </Button>
-                        </Link>
-                    ) : null}
+                        <Button
+                            bg='blue'
+                            color='white'
+                            _hover={{
+                                background: "#1976d2",
+                            }}
+                            onClick={handleViewDocuments}>
+                            Documents
+                        </Button>
+                    ) : (
+                        <Button
+                            bg='red'
+                            color='white'
+                            _hover={{
+                                background: "#d32f2f",
+                            }}
+                            onClick={onOpen}>
+                            Delete
+                        </Button>
+                    )}
                 </Flex>
             </Flex>
+            
+            {/* Delete Confirmation Dialog */}
+            <AlertDialog
+                isOpen={isOpen}
+                leastDestructiveRef={cancelRef}
+                onClose={onClose}
+            >
+                <AlertDialogOverlay>
+                    <AlertDialogContent>
+                        <AlertDialogHeader fontSize="lg" fontWeight="bold">
+                            Delete Vehicle
+                        </AlertDialogHeader>
+
+                        <AlertDialogBody>
+                            Are you sure you want to delete this vehicle? This action cannot be undone.
+                            <br />
+                            <br />
+                            <strong>{car_make} {car_model} ({p_year.slice(1, -1)})</strong>
+                        </AlertDialogBody>
+
+                        <AlertDialogFooter>
+                            <Button ref={cancelRef} onClick={onClose}>
+                                Cancel
+                            </Button>
+                            <Button 
+                                colorScheme="red" 
+                                onClick={handleDeleteVehicle} 
+                                ml={3}
+                                isLoading={isDeleting}
+                                loadingText="Deleting...">
+                                Delete
+                            </Button>
+                        </AlertDialogFooter>
+                    </AlertDialogContent>
+                </AlertDialogOverlay>
+            </AlertDialog>
         </Flex>
     );
Index: frontend/src/pages/AddVehicle.js
===================================================================
--- frontend/src/pages/AddVehicle.js	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ frontend/src/pages/AddVehicle.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -1,5 +1,8 @@
-import { Formik, Field, Form, ErrorMessage } from "formik";
+import { Formik, Form, Field } from "formik";
+import { Button, Flex, Text, useToast, Box, Select } from "@chakra-ui/react";
+import { Input, InputGroup, InputLeftElement } from "@chakra-ui/react";
+import { InfoIcon } from "@chakra-ui/icons";
+import { useNavigate } from "react-router-dom";
 import * as Yup from "yup";
-import { Button, Text, Flex } from "@chakra-ui/react";
 
 const SignupSchema = Yup.object().shape({
@@ -27,43 +30,63 @@
 
 const AddVehicle = () => {
-    const createVehicle = ({
-        vin,
-        car_body,
-        car_make,
-        car_model,
-        p_year,
-        capacity,
-        power,
-        color,
-        price,
-        tax_nr
-    }) => {
-        fetch("http://localhost:3001/createvehicle", {
-            method: "POST",
-            headers: {
-                "Content-Type": "application/json",
-            },
-            body: JSON.stringify({
-                vin,
-                car_body,
-                car_make,
-                car_model,
-                p_year,
-                capacity,
-                power,
-                color,
-                price,
-                tax_nr,
-            }),
-        }).then((response) => {
-            return response.text();
-        });
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    const handleSubmit = async (values, { setSubmitting }) => {
+        try {
+            const response = await fetch("http://localhost:3001/createvehicle", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                credentials: 'include',
+                body: JSON.stringify(values),
+            });
+
+            if (response.ok) {
+                toast({
+                    title: "Vehicle Added Successfully",
+                    description: "Your vehicle has been added to the listings!",
+                    status: "success",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/mylist");
+            } else if (response.status === 401) {
+                toast({
+                    title: "Unauthorized",
+                    description: "Please log in as a dealership to add vehicles",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/login");
+            } else {
+                throw new Error("Failed to add vehicle");
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "Failed to add vehicle. Please try again.",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setSubmitting(false);
+        }
     };
 
     return (
-        <>
-            <Text marginBottom='50px' fontWeight='bold' fontSize='32px'>
-                Add new vehicle listing
+        <Flex width='100%' flexDir='column' justifyContent='center' maxWidth='500px'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                Add New Vehicle
             </Text>
+            
             <Formik
                 initialValues={{
@@ -76,196 +99,251 @@
                     power: "",
                     color: "",
-                    price: "",
-                    tax_nr: "BM15153"
+                    price: ""
                 }}
                 validationSchema={SignupSchema}
-                onSubmit={async (values) => {
-                    createVehicle(values);
-                    alert("Successfully entered car!");
-                }}>
+                onSubmit={handleSubmit}>
                 {({ isSubmitting, errors, touched }) => (
-                    <Form width='100%'>
-                        <Flex
-                            boxShadow='lg'
-                            hover={{ boxShadow: "xl" }}
-                            borderBottomRadius='10px'
-                            bg='white'
-                            borderRadius='13px'
-                            transition='all 0.4s ease'
-                            direction='column'
-                            padding='20px'
-                            width='100%'>
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='vin'>
-                                        VIN
-                                    </label>
-                                    <Field
-                                        name='vin'
-                                        placeholder='WUZZ1255643'
-                                    />
-                                </Flex>
-                                {errors.vin && touched.vin ? (
-                                    <Flex>{errors.vin}</Flex>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='car_body'>
-                                        Body Type
-                                    </label>
-                                    <Field
-                                        name='car_body'
-                                        placeholder='Car'
-                                        as='select'>
-                                        <option value='Car'>Car</option>
-                                        <option value='Motorcycle'>
-                                            Motorcycle
-                                        </option>
-                                        <option value='Truck'>Truck</option>
-                                        <option value='Van'>Van</option>
-                                    </Field>
-                                </Flex>
-                                {errors.car_body && touched.car_body ? (
-                                    <div>{errors.car_body}</div>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='car_make'>
-                                        Car Make
-                                    </label>
-                                    <Field
-                                        name='car_make'
-                                        placeholder='BMW'
-                                        as='select'>
-                                        <option value='BMW'>BMW</option>
-                                        <option value='MINI'>
-                                            MINI
-                                        </option>
-                                    </Field>
-                                </Flex>
-                                {errors.car_make && touched.car_make ? (
-                                    <div>{errors.car_make}</div>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='car_model'>
-                                        Model
-                                    </label>
-                                    <Field
-                                        name='car_model'
-                                        placeholder='G30 530d'
-                                    />
-                                </Flex>
-                                {errors.car_model && touched.car_model ? (
-                                    <div>{errors.car_model}</div>
-                                ) : null}
-                            </Flex>
-
-                            
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='p_year'>
-                                        Year
-                                    </label>
-                                    <Field name='p_year' placeholder='2017' />
-                                </Flex>
-                                {errors.p_year && touched.p_year ? (
-                                    <Flex maxWidth='500px'>
+                    <Form>
+                        <Flex flexDir='column' gap='4'>
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    VIN (Vehicle Identification Number) *
+                                </Text>
+                                <Field name="vin">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="WUZZ1255643"
+                                                isInvalid={errors.vin && touched.vin}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.vin && touched.vin && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.vin}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Body Type *
+                                </Text>
+                                <Field name="car_body">
+                                    {({ field }) => (
+                                        <Select
+                                            {...field}
+                                            placeholder="Select body type"
+                                            isInvalid={errors.car_body && touched.car_body}>
+                                            <option value='Car'>Car</option>
+                                            <option value='Motorcycle'>Motorcycle</option>
+                                            <option value='Truck'>Truck</option>
+                                            <option value='Van'>Van</option>
+                                        </Select>
+                                    )}
+                                </Field>
+                                {errors.car_body && touched.car_body && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.car_body}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Make *
+                                </Text>
+                                <Field name="car_make">
+                                    {({ field }) => (
+                                        <Select
+                                            {...field}
+                                            placeholder="Select make"
+                                            isInvalid={errors.car_make && touched.car_make}>
+                                            <option value='BMW'>BMW</option>
+                                            <option value='MINI'>MINI</option>
+                                            <option value='Mercedes'>Mercedes</option>
+                                            <option value='Porsche'>Porsche</option>
+                                            <option value='VW'>VW</option>
+                                            <option value='Scania'>Scania</option>
+                                        </Select>
+                                    )}
+                                </Field>
+                                {errors.car_make && touched.car_make && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.car_make}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Model *
+                                </Text>
+                                <Field name="car_model">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="G30 530d"
+                                                isInvalid={errors.car_model && touched.car_model}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.car_model && touched.car_model && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.car_model}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Year *
+                                </Text>
+                                <Field name="p_year">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="2017"
+                                                isInvalid={errors.p_year && touched.p_year}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.p_year && touched.p_year && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
                                         {errors.p_year}
-                                    </Flex>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='capacity'>
-                                        Capacity
-                                    </label>
-                                    <Field name='capacity' placeholder='3000cc' />
-                                </Flex>
-                                {errors.capacity && touched.capacity ? (
-                                    <div>{errors.capacity}</div>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='power'>
-                                        Power (kW)
-                                    </label>
-                                    <Field name='power' placeholder='150' />
-                                </Flex>
-                                {errors.power && touched.power ? (
-                                    <div>{errors.power}</div>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='color'>
-                                        Color
-                                    </label>
-                                    <Field name='color' as='select'>
-                                        <option value='red'>Red</option>
-                                        <option value='green'>Green</option>
-                                        <option value='blue'>Blue</option>
-                                        <option value='black'>Black</option>
-                                        <option value='white'>White</option>
-                                        <option value='yellow'>Yellow</option>
-                                        <option value='orange'>Orange</option>
-                                        <option value='purple'>Purple</option>
-                                        <option value='silver'>Silver</option>
-                                        <option value='grey'>Grey</option>
-                                        <option value='cyan'>Cyan</option>
-                                        <option value='magenta'>Magenta</option>
-                                    </Field>
-                                </Flex>
-                                {errors.color && touched.color ? (
-                                    <div>{errors.color}</div>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='price'>
-                                        Price
-                                    </label>
-                                    <Field name='price' placeholder='35600' />
-                                </Flex>
-                                {errors.price && touched.price ? (
-                                    <div>{errors.price}</div>
-                                ) : null}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Engine Capacity *
+                                </Text>
+                                <Field name="capacity">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="3000cc"
+                                                isInvalid={errors.capacity && touched.capacity}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.capacity && touched.capacity && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.capacity}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Power (kW) *
+                                </Text>
+                                <Field name="power">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="150"
+                                                isInvalid={errors.power && touched.power}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.power && touched.power && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.power}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Color *
+                                </Text>
+                                <Field name="color">
+                                    {({ field }) => (
+                                        <Select
+                                            {...field}
+                                            placeholder="Select color"
+                                            isInvalid={errors.color && touched.color}>
+                                            <option value='red'>Red</option>
+                                            <option value='green'>Green</option>
+                                            <option value='blue'>Blue</option>
+                                            <option value='black'>Black</option>
+                                            <option value='white'>White</option>
+                                            <option value='yellow'>Yellow</option>
+                                            <option value='orange'>Orange</option>
+                                            <option value='purple'>Purple</option>
+                                            <option value='silver'>Silver</option>
+                                            <option value='grey'>Grey</option>
+                                            <option value='cyan'>Cyan</option>
+                                            <option value='magenta'>Magenta</option>
+                                        </Select>
+                                    )}
+                                </Field>
+                                {errors.color && touched.color && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.color}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Price ($) *
+                                </Text>
+                                <Field name="price">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="35600"
+                                                isInvalid={errors.price && touched.price}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.price && touched.price && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.price}
+                                    </Text>
+                                )}
                             </Flex>
 
                             <Button
-                                colorScheme='blue'
-                                type='submit'
-                                disabled={isSubmitting}>
-                                Submit
+                                type="submit"
+                                isLoading={isSubmitting}
+                                loadingText="Adding Vehicle..."
+                                colorScheme="blue"
+                                size="lg"
+                                marginTop="4">
+                                Add Vehicle
                             </Button>
                         </Flex>
@@ -273,5 +351,5 @@
                 )}
             </Formik>
-        </>
+        </Flex>
     );
 };
Index: frontend/src/pages/ClientLogin.js
===================================================================
--- frontend/src/pages/ClientLogin.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/ClientLogin.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,147 @@
+import { Formik, Field, Form } from "formik";
+import * as Yup from "yup";
+import { Button, Text, Flex, useToast } from "@chakra-ui/react";
+import { useNavigate } from "react-router-dom";
+
+const SignupSchema = Yup.object().shape({
+    email: Yup.string()
+        .email("Invalid email")
+        .required("This field is required!"),
+    password: Yup.string()
+        .required("Must enter a password!")
+        .min(1, "Password is required"),
+});
+
+const ClientLogin = () => {
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    const loginClient = async ({ email, password }) => {
+        try {
+            const response = await fetch("http://localhost:3001/login/client", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                credentials: 'include',
+                body: JSON.stringify({ email, password }),
+            });
+
+            const data = await response.json();
+            
+            if (data.success) {
+                toast({
+                    title: "Login successful",
+                    description: `Welcome back, ${data.user.C_Name}!`,
+                    status: "success",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                // Small delay to ensure session is set
+                setTimeout(() => {
+                    navigate("/myagreements");
+                }, 100);
+            } else {
+                toast({
+                    title: "Login failed",
+                    description: data.message || "Invalid credentials",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "An error occurred during login",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        }
+    };
+
+    return (
+        <>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='32px'
+                justifySelf='center'>
+                Client Login
+            </Text>
+            <Formik
+                initialValues={{
+                    email: "",
+                    password: "",
+                }}
+                validationSchema={SignupSchema}
+                onSubmit={async (values) => {
+                    await loginClient(values);
+                }}>
+                {({ isSubmitting, errors, touched }) => (
+                    <Form width='100%'>
+                        <Flex
+                            boxShadow='lg'
+                            hover={{ boxShadow: "xl" }}
+                            borderBottomRadius='10px'
+                            bg='white'
+                            borderRadius='13px'
+                            transition='all 0.4s ease'
+                            direction='column'
+                            padding='20px'
+                            width='100%'>
+                            
+                            <Flex padding='10px' direction='column'>
+                                <Flex>
+                                    <label
+                                        style={{ marginRight: "15px", minWidth: "80px" }}
+                                        htmlFor='email'>
+                                        Email
+                                    </label>
+                                    <Field
+                                        name='email'
+                                        placeholder='client@example.com'
+                                        type='email'
+                                    />
+                                </Flex>
+                                {errors.email && touched.email ? (
+                                    <Flex color='red'>{errors.email}</Flex>
+                                ) : null}
+                            </Flex>
+
+                            <Flex padding='10px' direction='column'>
+                                <Flex>
+                                    <label
+                                        style={{ marginRight: "15px", minWidth: "80px" }}
+                                        htmlFor='password'>
+                                        Password
+                                    </label>
+                                    <Field
+                                        name='password'
+                                        placeholder='Enter password'
+                                        type='password'
+                                    />
+                                </Flex>
+                                {errors.password && touched.password ? (
+                                    <Flex color='red'>{errors.password}</Flex>
+                                ) : null}
+                            </Flex>
+
+                            <Button
+                                colorScheme='green'
+                                type='submit'
+                                disabled={isSubmitting}
+                                marginTop='10px'>
+                                Login as Client
+                            </Button>
+                        </Flex>
+                    </Form>
+                )}
+            </Formik>
+        </>
+    );
+};
+
+export default ClientLogin;
Index: frontend/src/pages/CreateAgreement.js
===================================================================
--- frontend/src/pages/CreateAgreement.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/CreateAgreement.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,231 @@
+import { Formik, Field, Form } from "formik";
+import * as Yup from "yup";
+import { Button, Text, Flex, useToast } from "@chakra-ui/react";
+import { useNavigate, useLocation } from "react-router-dom";
+
+const SignupSchema = Yup.object().shape({
+    A_Id: Yup.string()
+        .required("This field is required!")
+        .min(5, "Agreement ID must be at least 5 characters"),
+    Price: Yup.number()
+        .required("This field is required!")
+        .min(1, "Price must be greater than 0"),
+    EMBG: Yup.string()
+        .min(13, "Must be 13 digits exactly!")
+        .max(13, "Must be 13 digits exactly!")
+        .required("This field is required!")
+        .matches(/^[0-9]*$/, "Must be a number."),
+    Datum: Yup.date()
+        .required("This field is required!"),
+});
+
+const CreateAgreement = () => {
+    const navigate = useNavigate();
+    const location = useLocation();
+    const toast = useToast();
+    
+    // Get VIN from location state
+    const { vin, vehicleInfo } = location.state || {};
+
+    const createAgreement = async ({ A_Id, Price, EMBG, Datum }) => {
+        try {
+            const response = await fetch("http://localhost:3001/agreement", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                credentials: 'include',
+                body: JSON.stringify({
+                    A_Id,
+                    Price,
+                    Status: true,
+                    Datum,
+                    VIN: vin,
+                    EMBG
+                }),
+            });
+
+            const data = await response.text();
+            
+            if (response.ok) {
+                toast({
+                    title: "Agreement created",
+                    description: "Agreement has been created successfully!",
+                    status: "success",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/mylist");
+            } else {
+                toast({
+                    title: "Error",
+                    description: "Failed to create agreement",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "An error occurred while creating agreement",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        }
+    };
+
+    if (!vin) {
+        return (
+            <Flex direction='column' align='center'>
+                <Text fontSize='24px' color='red'>No vehicle selected</Text>
+                <Button onClick={() => navigate("/mylist")} marginTop='20px'>
+                    Back to My Vehicles
+                </Button>
+            </Flex>
+        );
+    }
+
+    return (
+        <>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='32px'
+                justifySelf='center'>
+                Create Agreement
+            </Text>
+            
+            {vehicleInfo && (
+                <Flex
+                    bg='gray.100'
+                    padding='15px'
+                    borderRadius='8px'
+                    marginBottom='20px'
+                    direction='column'>
+                    <Text fontWeight='bold'>Vehicle Information:</Text>
+                    <Text>VIN: {vehicleInfo.vin}</Text>
+                    <Text>Make: {vehicleInfo.make}</Text>
+                    <Text>Model: {vehicleInfo.model}</Text>
+                    <Text>Year: {vehicleInfo.p_year}</Text>
+                    <Text>Price: ${vehicleInfo.price}</Text>
+                </Flex>
+            )}
+
+            <Formik
+                initialValues={{
+                    A_Id: "",
+                    Price: vehicleInfo?.price || "",
+                    EMBG: "",
+                    Datum: new Date().toISOString().split('T')[0],
+                }}
+                validationSchema={SignupSchema}
+                onSubmit={async (values) => {
+                    await createAgreement(values);
+                }}>
+                {({ isSubmitting, errors, touched }) => (
+                    <Form width='100%'>
+                        <Flex
+                            boxShadow='lg'
+                            hover={{ boxShadow: "xl" }}
+                            borderBottomRadius='10px'
+                            bg='white'
+                            borderRadius='13px'
+                            transition='all 0.4s ease'
+                            direction='column'
+                            padding='20px'
+                            width='100%'>
+                            
+                            <Flex padding='10px' direction='column'>
+                                <Flex>
+                                    <label
+                                        style={{ marginRight: "15px", minWidth: "120px" }}
+                                        htmlFor='A_Id'>
+                                        Agreement ID
+                                    </label>
+                                    <Field
+                                        name='A_Id'
+                                        placeholder='AG-2024-001'
+                                    />
+                                </Flex>
+                                {errors.A_Id && touched.A_Id ? (
+                                    <Flex color='red'>{errors.A_Id}</Flex>
+                                ) : null}
+                            </Flex>
+
+                            <Flex padding='10px' direction='column'>
+                                <Flex>
+                                    <label
+                                        style={{ marginRight: "15px", minWidth: "120px" }}
+                                        htmlFor='Price'>
+                                        Agreement Price
+                                    </label>
+                                    <Field
+                                        name='Price'
+                                        placeholder='35000'
+                                        type='number'
+                                    />
+                                </Flex>
+                                {errors.Price && touched.Price ? (
+                                    <Flex color='red'>{errors.Price}</Flex>
+                                ) : null}
+                            </Flex>
+
+                            <Flex padding='10px' direction='column'>
+                                <Flex>
+                                    <label
+                                        style={{ marginRight: "15px", minWidth: "120px" }}
+                                        htmlFor='EMBG'>
+                                        Client EMBG
+                                    </label>
+                                    <Field
+                                        name='EMBG'
+                                        placeholder='1507995410010'
+                                    />
+                                </Flex>
+                                {errors.EMBG && touched.EMBG ? (
+                                    <Flex color='red'>{errors.EMBG}</Flex>
+                                ) : null}
+                            </Flex>
+
+                            <Flex padding='10px' direction='column'>
+                                <Flex>
+                                    <label
+                                        style={{ marginRight: "15px", minWidth: "120px" }}
+                                        htmlFor='Datum'>
+                                        Agreement Date
+                                    </label>
+                                    <Field
+                                        name='Datum'
+                                        type='date'
+                                    />
+                                </Flex>
+                                {errors.Datum && touched.Datum ? (
+                                    <Flex color='red'>{errors.Datum}</Flex>
+                                ) : null}
+                            </Flex>
+
+                            <Flex direction='row' gap='10px' marginTop='20px'>
+                                <Button
+                                    colorScheme='blue'
+                                    type='submit'
+                                    disabled={isSubmitting}>
+                                    Create Agreement
+                                </Button>
+                                <Button
+                                    colorScheme='gray'
+                                    onClick={() => navigate("/mylist")}>
+                                    Cancel
+                                </Button>
+                            </Flex>
+                        </Flex>
+                    </Form>
+                )}
+            </Formik>
+        </>
+    );
+};
+
+export default CreateAgreement;
Index: frontend/src/pages/CreatePayment.js
===================================================================
--- frontend/src/pages/CreatePayment.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/CreatePayment.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,227 @@
+import { Formik, Form, Field } from "formik";
+import { Button, Flex, Text, useToast, Box } from "@chakra-ui/react";
+import { Input, InputGroup, InputLeftElement } from "@chakra-ui/react";
+import { InfoIcon } from "@chakra-ui/icons";
+import { useNavigate, useLocation } from "react-router-dom";
+import * as Yup from "yup";
+
+const SignupSchema = Yup.object().shape({
+    Bank: Yup.string()
+        .required("Bank name is required")
+        .min(2, "Bank name must be at least 2 characters"),
+    IBAN: Yup.string()
+        .required("IBAN is required")
+        .min(15, "IBAN must be at least 15 characters")
+        .matches(/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/, "Invalid IBAN format"),
+});
+
+const CreatePayment = () => {
+    const navigate = useNavigate();
+    const location = useLocation();
+    const toast = useToast();
+    
+    // Get agreement from location state
+    const { agreement } = location.state || {};
+
+    const createPayment = async ({ Bank, IBAN }) => {
+        try {
+            const response = await fetch("http://localhost:3001/payment", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                credentials: 'include',
+                body: JSON.stringify({
+                    Bank,
+                    IBAN,
+                    Amount: agreement.price, // Fixed amount from agreement
+                    A_Id: agreement.a_id
+                }),
+            });
+
+            const data = await response.text();
+            
+            if (response.ok) {
+                toast({
+                    title: "Payment created",
+                    description: "Payment has been processed successfully!",
+                    status: "success",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/myagreements");
+            } else {
+                toast({
+                    title: "Error",
+                    description: "Failed to create payment",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "An error occurred while processing payment",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        }
+    };
+
+    if (!agreement) {
+        return (
+            <Flex direction='column' align='center'>
+                <Text fontSize='24px' color='red'>No agreement selected</Text>
+                <Button onClick={() => navigate("/myagreements")} marginTop='20px'>
+                    Back to My Agreements
+                </Button>
+            </Flex>
+        );
+    }
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center' maxWidth='500px'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                Make Payment
+            </Text>
+            
+            {/* Agreement Information */}
+            <Box
+                borderWidth="1px"
+                borderRadius="lg"
+                overflow="hidden"
+                p="6"
+                bg="blue.50"
+                boxShadow="md"
+                marginBottom="6">
+                
+                <Flex direction="column" gap="2">
+                    <Text fontWeight="bold" fontSize="lg" mb="2">
+                        Agreement Information
+                    </Text>
+                    <Text>Agreement ID: {agreement.a_id}</Text>
+                    <Text>Vehicle: {agreement.make} {agreement.model} ({agreement.p_year})</Text>
+                    <Text>Dealership: {agreement.dealership_name}</Text>
+                    <Text fontWeight="bold" color="green.600" fontSize="lg">
+                        Amount Due: ${agreement.price}
+                    </Text>
+                </Flex>
+            </Box>
+
+            <Formik
+                initialValues={{
+                    Bank: "",
+                    IBAN: "",
+                }}
+                validationSchema={SignupSchema}
+                onSubmit={async (values, { setSubmitting }) => {
+                    await createPayment(values);
+                    setSubmitting(false);
+                }}>
+                {({ isSubmitting, errors, touched }) => (
+                    <Form>
+                        <Flex flexDir='column' gap='4'>
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Bank Name *
+                                </Text>
+                                <Field name="Bank">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="First National Bank"
+                                                isInvalid={errors.Bank && touched.Bank}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.Bank && touched.Bank && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.Bank}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    IBAN *
+                                </Text>
+                                <Field name="IBAN">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="MK07250120000058984"
+                                                isInvalid={errors.IBAN && touched.IBAN}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.IBAN && touched.IBAN && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.IBAN}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Payment Amount
+                                </Text>
+                                <InputGroup>
+                                    <InputLeftElement pointerEvents='none'>
+                                        <InfoIcon color='gray.300' />
+                                    </InputLeftElement>
+                                    <Input
+                                        value={`$${agreement.price}`}
+                                        isReadOnly
+                                        bg="gray.100"
+                                        color="green.600"
+                                        fontWeight="bold"
+                                    />
+                                </InputGroup>
+                                <Text color="gray.500" fontSize="sm" marginTop="1">
+                                    This amount is fixed and cannot be changed
+                                </Text>
+                            </Flex>
+
+                            <Flex direction='row' gap='3' marginTop='4'>
+                                <Button
+                                    type="submit"
+                                    isLoading={isSubmitting}
+                                    loadingText="Processing..."
+                                    colorScheme="green"
+                                    size="lg"
+                                    flex="1">
+                                    Process Payment
+                                </Button>
+                                <Button
+                                    colorScheme="gray"
+                                    size="lg"
+                                    onClick={() => navigate("/myagreements")}>
+                                    Cancel
+                                </Button>
+                            </Flex>
+                        </Flex>
+                    </Form>
+                )}
+            </Formik>
+        </Flex>
+    );
+};
+
+export default CreatePayment;
Index: frontend/src/pages/DealershipLogin.js
===================================================================
--- frontend/src/pages/DealershipLogin.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/DealershipLogin.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,148 @@
+import { Formik, Field, Form } from "formik";
+import * as Yup from "yup";
+import { Button, Text, Flex, useToast } from "@chakra-ui/react";
+import { useNavigate } from "react-router-dom";
+import { useEffect } from "react";
+
+const SignupSchema = Yup.object().shape({
+    email: Yup.string()
+        .email("Invalid email")
+        .required("This field is required!"),
+    password: Yup.string()
+        .required("Must enter a password!")
+        .min(1, "Password is required"),
+});
+
+const DealershipLogin = () => {
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    const loginDealership = async ({ email, password }) => {
+        try {
+            const response = await fetch("http://localhost:3001/login/dealership", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                credentials: 'include',
+                body: JSON.stringify({ email, password }),
+            });
+
+            const data = await response.json();
+            
+            if (data.success) {
+                toast({
+                    title: "Login successful",
+                    description: `Welcome back, ${data.user.D_Name}!`,
+                    status: "success",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                // Small delay to ensure session is set
+                setTimeout(() => {
+                    navigate("/mylist");
+                }, 100);
+            } else {
+                toast({
+                    title: "Login failed",
+                    description: data.message || "Invalid credentials",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "An error occurred during login",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        }
+    };
+
+    return (
+        <>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='32px'
+                justifySelf='center'>
+                Dealership Login
+            </Text>
+            <Formik
+                initialValues={{
+                    email: "",
+                    password: "",
+                }}
+                validationSchema={SignupSchema}
+                onSubmit={async (values) => {
+                    await loginDealership(values);
+                }}>
+                {({ isSubmitting, errors, touched }) => (
+                    <Form width='100%'>
+                        <Flex
+                            boxShadow='lg'
+                            hover={{ boxShadow: "xl" }}
+                            borderBottomRadius='10px'
+                            bg='white'
+                            borderRadius='13px'
+                            transition='all 0.4s ease'
+                            direction='column'
+                            padding='20px'
+                            width='100%'>
+                            
+                            <Flex padding='10px' direction='column'>
+                                <Flex>
+                                    <label
+                                        style={{ marginRight: "15px", minWidth: "80px" }}
+                                        htmlFor='email'>
+                                        Email
+                                    </label>
+                                    <Field
+                                        name='email'
+                                        placeholder='dealership@example.com'
+                                        type='email'
+                                    />
+                                </Flex>
+                                {errors.email && touched.email ? (
+                                    <Flex color='red'>{errors.email}</Flex>
+                                ) : null}
+                            </Flex>
+
+                            <Flex padding='10px' direction='column'>
+                                <Flex>
+                                    <label
+                                        style={{ marginRight: "15px", minWidth: "80px" }}
+                                        htmlFor='password'>
+                                        Password
+                                    </label>
+                                    <Field
+                                        name='password'
+                                        placeholder='Enter password'
+                                        type='password'
+                                    />
+                                </Flex>
+                                {errors.password && touched.password ? (
+                                    <Flex color='red'>{errors.password}</Flex>
+                                ) : null}
+                            </Flex>
+
+                            <Button
+                                colorScheme='blue'
+                                type='submit'
+                                disabled={isSubmitting}
+                                marginTop='10px'>
+                                Login as Dealership
+                            </Button>
+                        </Flex>
+                    </Form>
+                )}
+            </Formik>
+        </>
+    );
+};
+
+export default DealershipLogin;
Index: frontend/src/pages/DealershipPayments.js
===================================================================
--- frontend/src/pages/DealershipPayments.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/DealershipPayments.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,151 @@
+import { useState, useEffect } from "react";
+import { Button, Flex, SimpleGrid, Text, Box, Badge, useToast } from "@chakra-ui/react";
+import { useNavigate } from "react-router-dom";
+
+const DealershipPayments = () => {
+    const [payments, setPayments] = useState([]);
+    const [loading, setLoading] = useState(true);
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    useEffect(() => {
+        fetchPayments();
+    }, []);
+
+    const fetchPayments = async () => {
+        try {
+            const response = await fetch("http://localhost:3001/dealership/payments", {
+                credentials: 'include'
+            });
+
+            if (response.ok) {
+                const data = await response.json();
+                setPayments(data);
+            } else if (response.status === 401) {
+                toast({
+                    title: "Unauthorized",
+                    description: "Please log in as a dealership to view payments",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/dealershiplogin");
+            } else {
+                throw new Error("Failed to fetch payments");
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "Failed to load payments",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    const handleViewPayment = (agreementId) => {
+        navigate("/paymentdetails", { state: { agreementId } });
+    };
+
+    const PaymentCard = ({ payment }) => {
+        return (
+            <Box
+                borderWidth="1px"
+                borderRadius="lg"
+                overflow="hidden"
+                p="4"
+                bg="white"
+                boxShadow="md"
+                _hover={{ boxShadow: "lg" }}
+                transition="all 0.3s">
+                
+                <Flex direction="column" gap="2">
+                    <Flex justify="space-between" align="center">
+                        <Text fontWeight="bold" fontSize="lg">
+                            {payment.make} {payment.model}
+                        </Text>
+                        <Badge colorScheme="green">
+                            Paid
+                        </Badge>
+                    </Flex>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Year: {payment.p_year}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Color: {payment.color}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Client: {payment.client_name}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Agreement ID: {payment.a_id}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Agreement Date: {new Date(payment.agreement_date).toLocaleDateString()}
+                    </Text>
+                    
+                    <Text fontSize="lg" fontWeight="bold" color="green.600">
+                        Amount: ${payment.amount}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Bank: {payment.bank}
+                    </Text>
+                    
+                    <Button
+                        colorScheme="blue"
+                        size="sm"
+                        onClick={() => handleViewPayment(payment.a_id)}
+                        marginTop="2">
+                        View Payment Details
+                    </Button>
+                </Flex>
+            </Box>
+        );
+    };
+
+    if (loading) {
+        return (
+            <Flex justify="center" align="center" height="200px">
+                <Text>Loading payments...</Text>
+            </Flex>
+        );
+    }
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                Received Payments
+            </Text>
+            
+            {payments.length === 0 ? (
+                <Flex justify="center" align="center" height="200px">
+                    <Text fontSize="lg" color="gray.500">
+                        No payments received yet. Payments will appear here when clients make payments for your agreements.
+                    </Text>
+                </Flex>
+            ) : (
+                <SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={6}>
+                    {payments.map((payment, index) => (
+                        <PaymentCard key={payment.p_id || index} payment={payment} />
+                    ))}
+                </SimpleGrid>
+            )}
+        </Flex>
+    );
+};
+
+export default DealershipPayments;
Index: frontend/src/pages/DealershipRegisterForm.js
===================================================================
--- frontend/src/pages/DealershipRegisterForm.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/DealershipRegisterForm.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,333 @@
+import { Formik, Form, Field } from "formik";
+import { Button, Flex, Text, useToast } from "@chakra-ui/react";
+import { Input, InputGroup, InputLeftElement } from "@chakra-ui/react";
+import { EmailIcon, LockIcon, PhoneIcon, InfoIcon } from "@chakra-ui/icons";
+import { useNavigate } from "react-router-dom";
+import * as Yup from "yup";
+
+const DealershipRegisterForm = () => {
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    const validationSchema = Yup.object({
+        tax_nr: Yup.string()
+            .required("Tax Number is required")
+            .min(5, "Tax Number must be at least 5 characters"),
+        d_name: Yup.string()
+            .required("Dealership Name is required")
+            .min(2, "Dealership Name must be at least 2 characters"),
+        brands: Yup.string()
+            .required("Brands are required")
+            .min(2, "Please specify at least one brand"),
+        email: Yup.string()
+            .email("Invalid email format")
+            .required("Email is required"),
+        pass: Yup.string()
+            .required("Password is required")
+            .min(6, "Password must be at least 6 characters"),
+        director: Yup.string()
+            .required("Director name is required")
+            .min(2, "Director name must be at least 2 characters"),
+        telephones: Yup.string()
+            .required("Telephone number is required")
+            .min(8, "Please enter a valid telephone number"),
+        addres: Yup.string()
+            .required("Address is required")
+            .min(5, "Please enter a complete address"),
+    });
+
+    const initialValues = {
+        tax_nr: "",
+        d_name: "",
+        brands: "",
+        email: "",
+        pass: "",
+        director: "",
+        telephones: "",
+        addres: "",
+    };
+
+    const handleSubmit = async (values, { setSubmitting }) => {
+        try {
+            // Convert brands string to array (comma-separated)
+            const brandsArray = values.brands.split(',').map(brand => brand.trim());
+            const telephonesArray = values.telephones.split(',').map(tel => tel.trim());
+
+            const requestData = {
+                ...values,
+                brands: brandsArray,
+                telephones: telephonesArray,
+            };
+
+            const response = await fetch("http://localhost:3001/registerdealership", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                body: JSON.stringify(requestData),
+            });
+
+            if (response.ok) {
+                toast({
+                    title: "Registration Successful",
+                    description: "Your dealership has been registered successfully!",
+                    status: "success",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/dealershiplogin");
+            } else {
+                const errorData = await response.json();
+                throw new Error(errorData.error || "Registration failed");
+            }
+        } catch (error) {
+            toast({
+                title: "Registration Failed",
+                description: error.message,
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setSubmitting(false);
+        }
+    };
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center' maxWidth='500px'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                Register as Dealership
+            </Text>
+            
+            <Formik
+                initialValues={initialValues}
+                validationSchema={validationSchema}
+                onSubmit={handleSubmit}>
+                {({ isSubmitting, errors, touched }) => (
+                    <Form>
+                        <Flex flexDir='column' gap='4'>
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Tax Number *
+                                </Text>
+                                <Field name="tax_nr">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="Enter tax number"
+                                                isInvalid={errors.tax_nr && touched.tax_nr}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.tax_nr && touched.tax_nr && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.tax_nr}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Dealership Name *
+                                </Text>
+                                <Field name="d_name">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="Enter dealership name"
+                                                isInvalid={errors.d_name && touched.d_name}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.d_name && touched.d_name && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.d_name}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Brands (comma-separated) *
+                                </Text>
+                                <Field name="brands">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="e.g., BMW, Mercedes, Audi"
+                                                isInvalid={errors.brands && touched.brands}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.brands && touched.brands && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.brands}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Email *
+                                </Text>
+                                <Field name="email">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <EmailIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                type="email"
+                                                placeholder="Enter email"
+                                                isInvalid={errors.email && touched.email}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.email && touched.email && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.email}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Password *
+                                </Text>
+                                <Field name="pass">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <LockIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                type="password"
+                                                placeholder="Enter password"
+                                                isInvalid={errors.pass && touched.pass}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.pass && touched.pass && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.pass}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Director Name *
+                                </Text>
+                                <Field name="director">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="Enter director name"
+                                                isInvalid={errors.director && touched.director}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.director && touched.director && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.director}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Telephone Numbers (comma-separated) *
+                                </Text>
+                                <Field name="telephones">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <PhoneIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="e.g., +1234567890, +0987654321"
+                                                isInvalid={errors.telephones && touched.telephones}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.telephones && touched.telephones && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.telephones}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Address *
+                                </Text>
+                                <Field name="addres">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="Enter complete address"
+                                                isInvalid={errors.addres && touched.addres}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.addres && touched.addres && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.addres}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Button
+                                type="submit"
+                                isLoading={isSubmitting}
+                                loadingText="Registering..."
+                                colorScheme="blue"
+                                size="lg"
+                                marginTop="4">
+                                Register Dealership
+                            </Button>
+                        </Flex>
+                    </Form>
+                )}
+            </Formik>
+        </Flex>
+    );
+};
+
+export default DealershipRegisterForm;
Index: frontend/src/pages/Documents.js
===================================================================
--- frontend/src/pages/Documents.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/Documents.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,258 @@
+import { useState, useEffect } from "react";
+import { Button, Flex, Box, Text, Badge, useToast, SimpleGrid } from "@chakra-ui/react";
+import { useNavigate, useLocation } from "react-router-dom";
+
+const Documents = () => {
+    const [agreement, setAgreement] = useState(null);
+    const [payment, setPayment] = useState(null);
+    const [loading, setLoading] = useState(true);
+    const navigate = useNavigate();
+    const location = useLocation();
+    const toast = useToast();
+    
+    // Get data from location state - either VIN or full agreement/payment data
+    const { vin, agreementData, paymentData } = location.state || {};
+
+    useEffect(() => {
+        if (vin || agreementData || paymentData) {
+            if (agreementData || paymentData) {
+                // We already have the data, just set it
+                if (agreementData) {
+                    setAgreement(agreementData);
+                    // Check if the agreement data includes payment information
+                    if (agreementData.payment_exists && agreementData.p_id) {
+                        // Payment data is included in the agreement
+                        setPayment({
+                            p_id: agreementData.p_id,
+                            amount: agreementData.payment_amount,
+                            bank: agreementData.bank,
+                            iban: agreementData.iban,
+                            a_id: agreementData.a_id
+                        });
+                    } else if (agreementData.a_id) {
+                        // Check if there's a separate payment for it
+                        fetchPaymentForAgreement(agreementData.a_id);
+                    }
+                }
+                if (paymentData) {
+                    setPayment(paymentData);
+                    // If we have payment data, fetch the corresponding agreement
+                    if (paymentData.a_id) {
+                        fetchAgreementForPayment(paymentData.a_id);
+                    }
+                }
+                setLoading(false);
+            } else if (vin) {
+                // We only have VIN, fetch the data
+                fetchDocuments();
+            }
+        } else {
+            toast({
+                title: "Error",
+                description: "No vehicle data provided",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+            navigate("/reports");
+        }
+    }, [vin, agreementData, paymentData]);
+
+    const fetchDocuments = async () => {
+        try {
+            // Fetch agreement details
+            const agreementResponse = await fetch(`http://localhost:3001/agreement/${vin}`, {
+                credentials: 'include'
+            });
+
+            if (agreementResponse.ok) {
+                const agreementData = await agreementResponse.json();
+                // The backend returns an array, so take the first element
+                if (Array.isArray(agreementData) && agreementData.length > 0) {
+                    const agreement = agreementData[0];
+                    setAgreement(agreement);
+                    // Check if there's a payment for this agreement
+                    if (agreement.a_id) {
+                        fetchPaymentForAgreement(agreement.a_id);
+                    }
+                }
+            }
+
+            // Fetch payment details
+            const paymentResponse = await fetch(`http://localhost:3001/payment/vin/${vin}`, {
+                credentials: 'include'
+            });
+
+            if (paymentResponse.ok) {
+                const paymentData = await paymentResponse.json();
+                setPayment(paymentData);
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "Failed to load documents",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    const fetchPaymentForAgreement = async (agreementId) => {
+        try {
+            const response = await fetch(`http://localhost:3001/payment/${agreementId}`, {
+                credentials: 'include'
+            });
+
+            if (response.ok) {
+                const paymentData = await response.json();
+                setPayment(paymentData);
+            }
+        } catch (error) {
+            // Payment not found is not an error, just means no payment exists yet
+            console.log('No payment found for agreement:', agreementId);
+        }
+    };
+
+    const fetchAgreementForPayment = async (agreementId) => {
+        try {
+            const response = await fetch(`http://localhost:3001/agreement/id/${agreementId}`, {
+                credentials: 'include'
+            });
+
+            if (response.ok) {
+                const agreementData = await response.json();
+                setAgreement(agreementData);
+            }
+        } catch (error) {
+            console.error('Error fetching agreement for payment:', error);
+        }
+    };
+
+    if (loading) {
+        return (
+            <Flex justify="center" align="center" height="200px">
+                <Text>Loading documents...</Text>
+            </Flex>
+        );
+    }
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center' maxWidth='800px'>
+            <Flex justify="space-between" align="center" mb="6">
+                <Text
+                    marginBottom='20px'
+                    textAlign='center'
+                    fontWeight='bold'
+                    fontSize='30px'
+                    justifySelf='center'>
+                    Vehicle Documents
+                </Text>
+                <Button
+                    colorScheme="blue"
+                    onClick={() => navigate("/reports")}>
+                    Back to Reports
+                </Button>
+            </Flex>
+
+            <Box
+                borderWidth="1px"
+                borderRadius="lg"
+                overflow="hidden"
+                p="6"
+                bg="white"
+                boxShadow="lg">
+                
+                <Flex direction="column" gap="6">
+                    {/* Vehicle Information */}
+                    {agreement && (
+                        <Box bg="gray.50" p="4" borderRadius="md">
+                            <Text fontWeight="bold" fontSize="lg" mb="3">Vehicle Information</Text>
+                            <Text>VIN: {agreement.vin}</Text>
+                            <Text>Make: {agreement.make}</Text>
+                            <Text>Model: {agreement.model}</Text>
+                            <Text>Year: {agreement.p_year}</Text>
+                            <Text>Color: {agreement.color}</Text>
+                        </Box>
+                    )}
+                    
+                    {/* Agreement Information */}
+                    {agreement ? (
+                        <Box bg="blue.50" p="4" borderRadius="md">
+                            <Flex justify="space-between" align="center" mb="3">
+                                <Text fontWeight="bold" fontSize="lg">Agreement Details</Text>
+                                <Badge colorScheme="blue" fontSize="md" p="2">
+                                    AGREEMENT
+                                </Badge>
+                            </Flex>
+                            <Text>Agreement ID: {agreement.a_id}</Text>
+                            <Text>Date: {new Date(agreement.datum).toLocaleDateString()}</Text>
+                            <Text>Price: ${agreement.price}</Text>
+                        </Box>
+                    ) : (
+                        <Box bg="red.50" p="4" borderRadius="md">
+                            <Text color="red.600" fontWeight="bold">
+                                Agreement not found
+                            </Text>
+                        </Box>
+                    )}
+                    
+                    {/* Payment Information */}
+                    {payment ? (
+                        <Box bg="green.50" p="4" borderRadius="md">
+                            <Flex justify="space-between" align="center" mb="3">
+                                <Text fontWeight="bold" fontSize="lg">Payment Details</Text>
+                                <Badge colorScheme="green" fontSize="md" p="2">
+                                    PAID
+                                </Badge>
+                            </Flex>
+                            <Text>Payment ID: {payment.p_id}</Text>
+                            <Text>Amount: ${payment.amount}</Text>
+                            <Text>Bank: {payment.bank}</Text>
+                            <Text>IBAN: {payment.iban}</Text>
+                        </Box>
+                    ) : (
+                        <Box bg="yellow.50" p="4" borderRadius="md">
+                            <Flex justify="space-between" align="center" mb="3">
+                                <Text fontWeight="bold" fontSize="lg">Payment Status</Text>
+                                <Badge colorScheme="orange" fontSize="md" p="2">
+                                    PENDING
+                                </Badge>
+                            </Flex>
+                            <Text color="orange.600" fontWeight="bold">
+                                Payment not made yet
+                            </Text>
+                            <Text color="gray.600" mt="2">
+                                This vehicle has been sold but payment has not been received yet.
+                            </Text>
+                        </Box>
+                    )}
+                    
+                    {/* Parties Information */}
+                    {agreement && (
+                        <Box bg="purple.50" p="4" borderRadius="md">
+                            <Text fontWeight="bold" fontSize="lg" mb="3">Parties</Text>
+                            <Text>Dealership: {agreement.d_name}</Text>
+                            <Text>Client: {agreement.c_name}</Text>
+                        </Box>
+                    )}
+                </Flex>
+            </Box>
+            
+            {/* Action Buttons */}
+            <Flex direction="row" gap="3" marginTop="6" justify="center">
+                {payment && (
+                    <Button
+                        colorScheme="gray"
+                        onClick={() => window.print()}>
+                        Print Documents
+                    </Button>
+                )}
+            </Flex>
+        </Flex>
+    );
+};
+
+export default Documents;
Index: frontend/src/pages/Layout.js
===================================================================
--- frontend/src/pages/Layout.js	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ frontend/src/pages/Layout.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -1,19 +1,95 @@
-import { Outlet } from "react-router-dom";
-import { Link } from '@chakra-ui/react'
+import { Outlet, useLocation, useNavigate } from "react-router-dom";
+import { Link, Button, Text, useToast } from '@chakra-ui/react'
 import { Flex } from '@chakra-ui/react'
+import { useState, useEffect } from 'react';
 
 const Layout = () => {
+  const [authState, setAuthState] = useState({ loggedIn: false, userType: null, userName: null });
+  const toast = useToast();
+  const location = useLocation();
+  const navigate = useNavigate();
+
+  useEffect(() => {
+    checkAuthStatus();
+  }, []);
+
+  // Check auth status when route changes (e.g., after login)
+  useEffect(() => {
+    checkAuthStatus();
+  }, [location.pathname]);
+
+  const checkAuthStatus = async () => {
+    try {
+      const response = await fetch("http://localhost:3001/auth/status", {
+        credentials: 'include'
+      });
+      const data = await response.json();
+      console.log('Auth status check result:', data);
+      setAuthState(data);
+    } catch (error) {
+      console.error('Error checking auth status:', error);
+    }
+  };
+
+  const handleLogout = async () => {
+    try {
+      const response = await fetch("http://localhost:3001/logout", {
+        method: "POST",
+        credentials: 'include'
+      });
+      
+      if (response.ok) {
+        setAuthState({ loggedIn: false, userType: null, userName: null });
+        toast({
+          title: "Logged out",
+          description: "You have been logged out successfully",
+          status: "success",
+          duration: 2000,
+          isClosable: true,
+        });
+        // Redirect to home page after logout
+        navigate("/");
+      }
+    } catch (error) {
+      console.error('Error logging out:', error);
+    }
+  };
+
   return (
     <Flex direction='column' justify='center' align='center' alignSelf='center'>
       <Flex marginBottom="50px" borderBottom="4px"
 		borderColor="teal" borderBottomRadius="8px" maxWidth='100%' direction='row' padding='10px'>
-        <Flex fontSize="20px" direction='row' padding='5px'>
+        <Flex fontSize="20px" direction='row' padding='5px' alignItems='center'>
             <Link padding='0px 20px' href="/">CarZone</Link>
           
-            <Link padding='0px 20px' href="/mylist">My Vehicles</Link>
+            {authState.loggedIn && authState.userType === 'dealership' && (
+              <>
+                <Link padding='0px 20px' href="/mylist">My Vehicles</Link>
+                <Link padding='0px 20px' href="/addvehicle">Add Vehicle</Link>
+                <Link padding='0px 20px' href="/reports">Reports</Link>
+              </>
+            )}
 
-            <Link padding='0px 20px' href="/addvehicle">Add Vehicle</Link>
+            {authState.loggedIn && authState.userType === 'client' && (
+              <Link padding='0px 20px' href="/myagreements">My Agreements</Link>
+            )}
 
-            <Link padding='0px 20px' href="/registerform">Register as User</Link>
+                        {!authState.loggedIn && (
+              <>
+                <Link padding='0px 20px' href="/login">Login</Link>
+                <Link padding='0px 20px' href="/register">Register</Link>
+            </>
+            )}
+
+            {authState.loggedIn && (
+              <Flex alignItems='center' marginLeft='20px'>
+                <Text fontSize='16px' marginRight='10px'>
+                  Welcome, {authState.userName}
+                </Text>
+                <Button size='sm' colorScheme='red' onClick={handleLogout}>
+                  Logout
+                </Button>
+              </Flex>
+            )}
         </Flex>
       </Flex>
Index: frontend/src/pages/Login.js
===================================================================
--- frontend/src/pages/Login.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/Login.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,211 @@
+import { useState } from "react";
+import { Formik, Form, Field } from "formik";
+import { Button, Flex, Text, useToast, VStack, HStack, Box, Input, InputGroup, InputLeftElement } from "@chakra-ui/react";
+import { EmailIcon, LockIcon } from "@chakra-ui/icons";
+import { useNavigate } from "react-router-dom";
+import * as Yup from "yup";
+
+const Login = () => {
+    const navigate = useNavigate();
+    const toast = useToast();
+    const [userType, setUserType] = useState(null); // 'client' or 'dealership'
+
+    const validationSchema = Yup.object({
+        email: Yup.string()
+            .email("Invalid email format")
+            .required("Email is required"),
+        pass: Yup.string()
+            .required("Password is required")
+            .min(6, "Password must be at least 6 characters"),
+    });
+
+    const initialValues = {
+        email: "",
+        pass: "",
+    };
+
+    const handleSubmit = async (values, { setSubmitting }) => {
+        if (!userType) {
+            toast({
+                title: "Error",
+                description: "Please select whether you are a client or dealership",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+            setSubmitting(false);
+            return;
+        }
+
+        try {
+            const response = await fetch(`http://localhost:3001/login/${userType}`, {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                credentials: 'include',
+                body: JSON.stringify(values),
+            });
+
+            if (response.ok) {
+                toast({
+                    title: "Login Successful",
+                    description: `Welcome back!`,
+                    status: "success",
+                    duration: 2000,
+                    isClosable: true,
+                });
+                
+                // Navigate based on user type
+                setTimeout(() => {
+                    if (userType === 'dealership') {
+                        navigate("/mylist");
+                    } else {
+                        navigate("/myagreements");
+                    }
+                }, 100);
+            } else {
+                const errorData = await response.json();
+                throw new Error(errorData.error || "Login failed");
+            }
+        } catch (error) {
+            toast({
+                title: "Login Failed",
+                description: error.message,
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setSubmitting(false);
+        }
+    };
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center' maxWidth='500px'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                Login
+            </Text>
+            
+            <Box
+                borderWidth="1px"
+                borderRadius="lg"
+                overflow="hidden"
+                p="8"
+                bg="white"
+                boxShadow="lg">
+                
+                <VStack spacing={6} align="stretch">
+                    {/* User Type Selection */}
+                    <VStack spacing={3} align="stretch">
+                        <Text fontSize="lg" fontWeight="bold" textAlign="center">
+                            I am a:
+                        </Text>
+                        <HStack spacing={4} justify="center">
+                            <Button
+                                colorScheme={userType === 'client' ? 'blue' : 'gray'}
+                                variant={userType === 'client' ? 'solid' : 'outline'}
+                                onClick={() => setUserType('client')}
+                                minW="120px">
+                                Client
+                            </Button>
+                            <Button
+                                colorScheme={userType === 'dealership' ? 'green' : 'gray'}
+                                variant={userType === 'dealership' ? 'solid' : 'outline'}
+                                onClick={() => setUserType('dealership')}
+                                minW="120px">
+                                Dealership
+                            </Button>
+                        </HStack>
+                    </VStack>
+
+                    {/* Login Form */}
+                    <Formik
+                        initialValues={initialValues}
+                        validationSchema={validationSchema}
+                        onSubmit={handleSubmit}>
+                        {({ isSubmitting, errors, touched }) => (
+                            <Form>
+                                <VStack spacing={4} align="stretch">
+                                    <Flex flexDir='column'>
+                                        <Text marginBottom='5px' fontWeight='bold'>
+                                            Email *
+                                        </Text>
+                                        <Field name="email">
+                                            {({ field }) => (
+                                                <InputGroup>
+                                                    <InputLeftElement pointerEvents='none'>
+                                                        <EmailIcon color='gray.300' />
+                                                    </InputLeftElement>
+                                                    <Input
+                                                        {...field}
+                                                        type="email"
+                                                        placeholder="Enter your email"
+                                                        isInvalid={errors.email && touched.email}
+                                                    />
+                                                </InputGroup>
+                                            )}
+                                        </Field>
+                                        {errors.email && touched.email && (
+                                            <Text color="red.500" fontSize="sm" marginTop="1">
+                                                {errors.email}
+                                            </Text>
+                                        )}
+                                    </Flex>
+
+                                    <Flex flexDir='column'>
+                                        <Text marginBottom='5px' fontWeight='bold'>
+                                            Password *
+                                        </Text>
+                                        <Field name="pass">
+                                            {({ field }) => (
+                                                <InputGroup>
+                                                    <InputLeftElement pointerEvents='none'>
+                                                        <LockIcon color='gray.300' />
+                                                    </InputLeftElement>
+                                                    <Input
+                                                        {...field}
+                                                        type="password"
+                                                        placeholder="Enter your password"
+                                                        isInvalid={errors.pass && touched.pass}
+                                                    />
+                                                </InputGroup>
+                                            )}
+                                        </Field>
+                                        {errors.pass && touched.pass && (
+                                            <Text color="red.500" fontSize="sm" marginTop="1">
+                                                {errors.pass}
+                                            </Text>
+                                        )}
+                                    </Flex>
+
+                                    <Button
+                                        type="submit"
+                                        isLoading={isSubmitting}
+                                        loadingText="Logging in..."
+                                        colorScheme={userType === 'dealership' ? 'green' : 'blue'}
+                                        size="lg"
+                                        marginTop="4"
+                                        isDisabled={!userType}>
+                                        Login
+                                    </Button>
+                                </VStack>
+                            </Form>
+                        )}
+                    </Formik>
+                    
+                    <Text fontSize="sm" color="gray.500" textAlign="center" mt="4">
+                        Don't have an account? <Button variant="link" colorScheme="blue" onClick={() => navigate("/register")}>Register here</Button>
+                    </Text>
+                </VStack>
+            </Box>
+        </Flex>
+    );
+};
+
+export default Login;
Index: frontend/src/pages/MyAgreements.js
===================================================================
--- frontend/src/pages/MyAgreements.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/MyAgreements.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,165 @@
+import { useState, useEffect } from "react";
+import { Button, Flex, SimpleGrid, Text, Box, Badge, useToast } from "@chakra-ui/react";
+import { useNavigate } from "react-router-dom";
+
+const MyAgreements = () => {
+    const [agreements, setAgreements] = useState([]);
+    const [loading, setLoading] = useState(true);
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    // Get client agreements
+    const getMyAgreements = async () => {
+        try {
+            const response = await fetch("http://localhost:3001/client/agreements", {
+                method: "GET",
+                credentials: 'include',
+            });
+
+            if (response.ok) {
+                const data = await response.json();
+                setAgreements(data);
+            } else if (response.status === 401) {
+                toast({
+                    title: "Unauthorized",
+                    description: "Please log in as a client to view agreements",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/clientlogin");
+            } else {
+                throw new Error("Failed to fetch agreements");
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "Failed to load agreements",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    useEffect(() => {
+        getMyAgreements();
+    }, []);
+
+    const handleMakePayment = (agreement) => {
+        navigate("/createpayment", { state: { agreement } });
+    };
+
+    const handleViewPayment = (agreementId) => {
+        navigate("/paymentdetails", { state: { agreementId } });
+    };
+
+    const AgreementCard = ({ agreement }) => {
+        const isPaid = agreement.payment_exists; // This would need to be added to the backend query
+        
+        return (
+            <Box
+                borderWidth="1px"
+                borderRadius="lg"
+                overflow="hidden"
+                p="4"
+                bg="white"
+                boxShadow="md"
+                _hover={{ boxShadow: "lg" }}
+                transition="all 0.3s">
+                
+                <Flex direction="column" gap="2">
+                    <Flex justify="space-between" align="center">
+                        <Text fontWeight="bold" fontSize="lg">
+                            {agreement.make} {agreement.model}
+                        </Text>
+                        <Badge colorScheme={isPaid ? "green" : "orange"}>
+                            {isPaid ? "Paid" : "Pending Payment"}
+                        </Badge>
+                    </Flex>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Year: {agreement.p_year}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Color: {agreement.color}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Dealership: {agreement.dealership_name}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Agreement ID: {agreement.a_id}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Agreement Date: {new Date(agreement.datum).toLocaleDateString()}
+                    </Text>
+                    
+                    <Text fontSize="lg" fontWeight="bold" color="blue.600">
+                        Price: ${agreement.price}
+                    </Text>
+                    
+                    {!isPaid ? (
+                        <Button
+                            colorScheme="green"
+                            size="sm"
+                            onClick={() => handleMakePayment(agreement)}
+                            marginTop="2">
+                            Make Payment
+                        </Button>
+                    ) : (
+                        <Button
+                            colorScheme="blue"
+                            size="sm"
+                            onClick={() => handleViewPayment(agreement.a_id)}
+                            marginTop="2">
+                            View Payment
+                        </Button>
+                    )}
+                </Flex>
+            </Box>
+        );
+    };
+
+    if (loading) {
+        return (
+            <Flex justify="center" align="center" height="200px">
+                <Text>Loading agreements...</Text>
+            </Flex>
+        );
+    }
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                My Agreements
+            </Text>
+            
+            {agreements.length === 0 ? (
+                <Flex justify="center" align="center" height="200px">
+                    <Text fontSize="lg" color="gray.500">
+                        No agreements found. Agreements will appear here when dealerships create them for you.
+                    </Text>
+                </Flex>
+            ) : (
+                <SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={6}>
+                    {agreements.map((agreement, index) => (
+                        <AgreementCard key={agreement.a_id || index} agreement={agreement} />
+                    ))}
+                </SimpleGrid>
+            )}
+        </Flex>
+    );
+};
+
+export default MyAgreements;
Index: frontend/src/pages/MyList.js
===================================================================
--- frontend/src/pages/MyList.js	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ frontend/src/pages/MyList.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -40,10 +40,18 @@
     //Call to get cars of one dealership
     function getMyVehicles() {
-        fetch("http://localhost:3001/mylist")
+        fetch("http://localhost:3001/mylist", {
+            credentials: 'include'
+        })
             .then((response) => {
+                if (response.status === 401) {
+                    alert("Please log in as a dealership to view your vehicles");
+                    return null;
+                }
                 return response.text();
             })
             .then((data) => {
-                setMyVehicles(data);
+                if (data) {
+                    setMyVehicles(data);
+                }
             });
     }
@@ -85,4 +93,5 @@
                                         price={holder[30]}
                                         status={holder[32].slice(1, -1)}
+                                        onVehicleDeleted={getMyVehicles}
                                     />
                                 );
Index: frontend/src/pages/PaymentDetails.js
===================================================================
--- frontend/src/pages/PaymentDetails.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/PaymentDetails.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,163 @@
+import { useState, useEffect } from "react";
+import { Button, Flex, Box, Text, Badge, useToast } from "@chakra-ui/react";
+import { useNavigate, useLocation } from "react-router-dom";
+
+const PaymentDetails = () => {
+    const [paymentDetails, setPaymentDetails] = useState(null);
+    const [loading, setLoading] = useState(true);
+    const navigate = useNavigate();
+    const location = useLocation();
+    const toast = useToast();
+    
+    // Get agreement ID or VIN from location state
+    const { agreementId, vin } = location.state || {};
+
+    useEffect(() => {
+        if (agreementId || vin) {
+            fetchPaymentDetails();
+        } else {
+            toast({
+                title: "Error",
+                description: "No agreement ID or VIN provided",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+            navigate(-1);
+        }
+    }, [agreementId, vin]);
+
+    const fetchPaymentDetails = async () => {
+        try {
+            let url;
+            if (agreementId) {
+                url = `http://localhost:3001/payment/${agreementId}`;
+            } else if (vin) {
+                url = `http://localhost:3001/payment/vin/${vin}`;
+            } else {
+                throw new Error("No valid identifier provided");
+            }
+
+            const response = await fetch(url, {
+                credentials: 'include'
+            });
+
+            if (response.ok) {
+                const data = await response.json();
+                setPaymentDetails(data);
+            } else {
+                throw new Error("Failed to fetch payment details");
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "Failed to load payment details",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+            navigate(-1);
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    if (loading) {
+        return (
+            <Flex justify="center" align="center" height="200px">
+                <Text>Loading payment details...</Text>
+            </Flex>
+        );
+    }
+
+    if (!paymentDetails) {
+        return (
+            <Flex justify="center" align="center" height="200px">
+                <Text>Payment details not found</Text>
+            </Flex>
+        );
+    }
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center' maxWidth='800px'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                Payment Details
+            </Text>
+            
+            <Box
+                borderWidth="1px"
+                borderRadius="lg"
+                overflow="hidden"
+                p="6"
+                bg="white"
+                boxShadow="lg">
+                
+                <Flex direction="column" gap="4">
+                    {/* Payment Status */}
+                    <Flex justify="space-between" align="center">
+                        <Text fontWeight="bold" fontSize="xl">
+                            Payment Information
+                        </Text>
+                        <Badge colorScheme="green" fontSize="md" p="2">
+                            PAID
+                        </Badge>
+                    </Flex>
+                    
+                    {/* Vehicle Information */}
+                    <Box bg="gray.50" p="4" borderRadius="md">
+                        <Text fontWeight="bold" mb="2">Vehicle Details:</Text>
+                        <Text>Make: {paymentDetails.make}</Text>
+                        <Text>Model: {paymentDetails.model}</Text>
+                        <Text>Year: {paymentDetails.p_year}</Text>
+                        <Text>Color: {paymentDetails.color}</Text>
+                    </Box>
+                    
+                    {/* Agreement Information */}
+                    <Box bg="blue.50" p="4" borderRadius="md">
+                        <Text fontWeight="bold" mb="2">Agreement Details:</Text>
+                        <Text>Agreement ID: {paymentDetails.a_id}</Text>
+                        <Text>Agreement Date: {new Date(paymentDetails.agreement_date).toLocaleDateString()}</Text>
+                        <Text>Agreement Price: ${paymentDetails.agreement_price}</Text>
+                    </Box>
+                    
+                    {/* Payment Information */}
+                    <Box bg="green.50" p="4" borderRadius="md">
+                        <Text fontWeight="bold" mb="2">Payment Details:</Text>
+                        <Text>Payment ID: {paymentDetails.p_id}</Text>
+                        <Text>Amount Paid: ${paymentDetails.amount}</Text>
+                        <Text>Bank: {paymentDetails.bank}</Text>
+                        <Text>IBAN: {paymentDetails.iban}</Text>
+                    </Box>
+                    
+                    {/* Parties Information */}
+                    <Box bg="purple.50" p="4" borderRadius="md">
+                        <Text fontWeight="bold" mb="2">Parties:</Text>
+                        <Text>Dealership: {paymentDetails.dealership_name}</Text>
+                        <Text>Client: {paymentDetails.client_name}</Text>
+                    </Box>
+                    
+                    {/* Action Buttons */}
+                    <Flex direction="row" gap="3" marginTop="4">
+                        <Button
+                            colorScheme="blue"
+                            onClick={() => navigate(-1)}>
+                            Back
+                        </Button>
+                        <Button
+                            colorScheme="gray"
+                            onClick={() => window.print()}>
+                            Print Receipt
+                        </Button>
+                    </Flex>
+                </Flex>
+            </Box>
+        </Flex>
+    );
+};
+
+export default PaymentDetails;
Index: frontend/src/pages/RegisterForm.js
===================================================================
--- frontend/src/pages/RegisterForm.js	(revision 777b34dd0a3a984ac4252a7fea43c817042047b5)
+++ frontend/src/pages/RegisterForm.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -1,5 +1,8 @@
-import { Formik, Field, Form, ErrorMessage } from "formik";
+import { Formik, Form, Field } from "formik";
+import { Button, Flex, Text, useToast, Box } from "@chakra-ui/react";
+import { Input, InputGroup, InputLeftElement } from "@chakra-ui/react";
+import { EmailIcon, LockIcon, PhoneIcon, InfoIcon } from "@chakra-ui/icons";
+import { useNavigate } from "react-router-dom";
 import * as Yup from "yup";
-import { Button, Text, Flex } from "@chakra-ui/react";
 
 const SignupSchema = Yup.object().shape({
@@ -31,28 +34,54 @@
 
 const RegisterForm = () => {
-    const registerUser = ({ EMBG, C_name, Email, Pass, Telephone }) => {
-        fetch("http://localhost:3001/registeruser", {
-            method: "POST",
-            headers: {
-                "Content-Type": "application/json",
-            },
-            body: JSON.stringify({ EMBG, C_name, Email, Pass, Telephone }),
-        }).then((response) => {
-            return response.text();
-        });
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    const handleSubmit = async (values, { setSubmitting }) => {
+        try {
+            const response = await fetch("http://localhost:3001/registeruser", {
+                method: "POST",
+                headers: {
+                    "Content-Type": "application/json",
+                },
+                body: JSON.stringify(values),
+            });
+
+            if (response.ok) {
+                toast({
+                    title: "Registration Successful",
+                    description: "Your client account has been created successfully!",
+                    status: "success",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/login");
+            } else {
+                const errorData = await response.json();
+                throw new Error(errorData.error || "Registration failed");
+            }
+        } catch (error) {
+            toast({
+                title: "Registration Failed",
+                description: error.message,
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setSubmitting(false);
+        }
     };
 
-    const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
-
     return (
-        <>
+        <Flex width='100%' flexDir='column' justifyContent='center' maxWidth='500px'>
             <Text
                 marginBottom='20px'
                 textAlign='center'
                 fontWeight='bold'
-                fontSize='32px'
+                fontSize='30px'
                 justifySelf='center'>
-                Register Form
+                Register as Client
             </Text>
+            
             <Formik
                 initialValues={{
@@ -64,111 +93,143 @@
                 }}
                 validationSchema={SignupSchema}
-                onSubmit={async (values) => {
-                    registerUser(values);
-                    alert("Successfully created user!");
-                }}>
+                onSubmit={handleSubmit}>
                 {({ isSubmitting, errors, touched }) => (
-                    <Form width='100%'>
-                        <Flex
-                            boxShadow='lg'
-                            hover={{ boxShadow: "xl" }}
-                            borderBottomRadius='10px'
-                            bg='white'
-                            borderRadius='13px'
-                            transition='all 0.4s ease'
-                            direction='column'
-                            padding='20px'
-                            width='100%'>
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='EMBG'>
-                                        EMBG
-                                    </label>
-                                    <Field
-                                        name='EMBG'
-                                        placeholder='1507995410010'
-                                    />
-                                </Flex>
-                                {errors.EMBG && touched.EMBG ? (
-                                    <Flex>{errors.EMBG}</Flex>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='C_name'>
-                                        Name
-                                    </label>
-                                    <Field
-                                        name='C_name'
-                                        placeholder='Jane Doe'
-                                    />
-                                </Flex>
-                                {errors.C_name && touched.C_name ? (
-                                    <div>{errors.C_name}</div>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='Email'>
-                                        Email
-                                    </label>
-                                    <Field
-                                        name='Email'
-                                        placeholder='jane@acme.com'
-                                        type='email'
-                                    />
-                                </Flex>
-                                {errors.Email && touched.Email ? (
-                                    <div>{errors.Email}</div>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='Pass'>
-                                        Password
-                                    </label>
-                                    <Field
-                                        name='Pass'
-                                        placeholder='fDs@d87fsd'
-                                    />
-                                </Flex>
-                                {errors.Pass && touched.Pass ? (
-                                    <Flex maxWidth='500px'>{errors.Pass}</Flex>
-                                ) : null}
-                            </Flex>
-
-                            <Flex padding='10px' direction='column'>
-                                <Flex>
-                                    <label
-                                        style={{ marginRight: "15px" }}
-                                        htmlFor='Telephone'>
-                                        Telephone
-                                    </label>
-                                    <Field
-                                        name='Telephone'
-                                        placeholder='077461321'
-                                    />
-                                </Flex>
-                                {errors.Telephone && touched.Telephone ? (
-                                    <div>{errors.Telephone}</div>
-                                ) : null}
+                    <Form>
+                        <Flex flexDir='column' gap='4'>
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    EMBG (Personal ID) *
+                                </Text>
+                                <Field name="EMBG">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="1507995410010"
+                                                isInvalid={errors.EMBG && touched.EMBG}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.EMBG && touched.EMBG && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.EMBG}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Full Name *
+                                </Text>
+                                <Field name="C_name">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <InfoIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="Jane Doe"
+                                                isInvalid={errors.C_name && touched.C_name}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.C_name && touched.C_name && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.C_name}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Email *
+                                </Text>
+                                <Field name="Email">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <EmailIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                type="email"
+                                                placeholder="jane@acme.com"
+                                                isInvalid={errors.Email && touched.Email}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.Email && touched.Email && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.Email}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Password *
+                                </Text>
+                                <Field name="Pass">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <LockIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                type="password"
+                                                placeholder="Enter secure password"
+                                                isInvalid={errors.Pass && touched.Pass}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.Pass && touched.Pass && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.Pass}
+                                    </Text>
+                                )}
+                            </Flex>
+
+                            <Flex flexDir='column'>
+                                <Text marginBottom='5px' fontWeight='bold'>
+                                    Telephone *
+                                </Text>
+                                <Field name="Telephone">
+                                    {({ field }) => (
+                                        <InputGroup>
+                                            <InputLeftElement pointerEvents='none'>
+                                                <PhoneIcon color='gray.300' />
+                                            </InputLeftElement>
+                                            <Input
+                                                {...field}
+                                                placeholder="077461321"
+                                                isInvalid={errors.Telephone && touched.Telephone}
+                                            />
+                                        </InputGroup>
+                                    )}
+                                </Field>
+                                {errors.Telephone && touched.Telephone && (
+                                    <Text color="red.500" fontSize="sm" marginTop="1">
+                                        {errors.Telephone}
+                                    </Text>
+                                )}
                             </Flex>
 
                             <Button
-                                colorScheme='blue'
-                                type='submit'
-                                disabled={isSubmitting}>
-                                Submit
+                                type="submit"
+                                isLoading={isSubmitting}
+                                loadingText="Registering..."
+                                colorScheme="blue"
+                                size="lg"
+                                marginTop="4">
+                                Register Client
                             </Button>
                         </Flex>
@@ -176,5 +237,5 @@
                 )}
             </Formik>
-        </>
+        </Flex>
     );
 };
Index: frontend/src/pages/RegisterSelection.js
===================================================================
--- frontend/src/pages/RegisterSelection.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/RegisterSelection.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,115 @@
+import { Flex, Text, Button, VStack, HStack, Box, useToast } from "@chakra-ui/react";
+import { useNavigate } from "react-router-dom";
+
+const RegisterSelection = () => {
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    const handleClientRegister = () => {
+        navigate("/registerform");
+    };
+
+    const handleDealershipRegister = () => {
+        navigate("/dealershipregister");
+    };
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center' maxWidth='600px'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                Register Account
+            </Text>
+            
+            <Box
+                borderWidth="1px"
+                borderRadius="lg"
+                overflow="hidden"
+                p="8"
+                bg="white"
+                boxShadow="lg">
+                
+                <VStack spacing={6} align="center">
+                    <Text fontSize="lg" color="gray.600" textAlign="center">
+                        Choose the type of account you want to create:
+                    </Text>
+                    
+                    <HStack spacing={8} align="stretch">
+                        <VStack spacing={4} align="center" minW="200px">
+                            <Box
+                                borderWidth="2px"
+                                borderRadius="lg"
+                                p="6"
+                                bg="blue.50"
+                                borderColor="blue.200"
+                                textAlign="center"
+                                minH="200px"
+                                display="flex"
+                                flexDir="column"
+                                justifyContent="space-between">
+                                
+                                <VStack spacing={3}>
+                                    <Text fontSize="xl" fontWeight="bold" color="blue.700">
+                                        Client Account
+                                    </Text>
+                                    <Text fontSize="sm" color="gray.600" textAlign="center">
+                                        Register as a client to browse vehicles, create agreements, and make payments.
+                                    </Text>
+                                </VStack>
+                                
+                                <Button
+                                    colorScheme="blue"
+                                    size="lg"
+                                    onClick={handleClientRegister}
+                                    width="100%">
+                                    Register as Client
+                                </Button>
+                            </Box>
+                        </VStack>
+                        
+                        <VStack spacing={4} align="center" minW="200px">
+                            <Box
+                                borderWidth="2px"
+                                borderRadius="lg"
+                                p="6"
+                                bg="green.50"
+                                borderColor="green.200"
+                                textAlign="center"
+                                minH="200px"
+                                display="flex"
+                                flexDir="column"
+                                justifyContent="space-between">
+                                
+                                <VStack spacing={3}>
+                                    <Text fontSize="xl" fontWeight="bold" color="green.700">
+                                        Dealership Account
+                                    </Text>
+                                    <Text fontSize="sm" color="gray.600" textAlign="center">
+                                        Register as a dealership to list vehicles, create agreements, and manage sales.
+                                    </Text>
+                                </VStack>
+                                
+                                <Button
+                                    colorScheme="green"
+                                    size="lg"
+                                    onClick={handleDealershipRegister}
+                                    width="100%">
+                                    Register as Dealership
+                                </Button>
+                            </Box>
+                        </VStack>
+                    </HStack>
+                    
+                    <Text fontSize="sm" color="gray.500" textAlign="center" mt="4">
+                        Already have an account? <Button variant="link" colorScheme="blue" onClick={() => navigate("/login")}>Sign in here</Button>
+                    </Text>
+                </VStack>
+            </Box>
+        </Flex>
+    );
+};
+
+export default RegisterSelection;
Index: frontend/src/pages/Reports.js
===================================================================
--- frontend/src/pages/Reports.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
+++ frontend/src/pages/Reports.js	(revision fc040e5bac85c12c8c762fbc148457f7b8e97d42)
@@ -0,0 +1,161 @@
+import { useState, useEffect } from "react";
+import { Button, Flex, SimpleGrid, Text, Box, Badge, useToast } from "@chakra-ui/react";
+import { useNavigate } from "react-router-dom";
+
+const Reports = () => {
+    const [agreements, setAgreements] = useState([]);
+    const [loading, setLoading] = useState(true);
+    const navigate = useNavigate();
+    const toast = useToast();
+
+    useEffect(() => {
+        fetchAllAgreements();
+    }, []);
+
+    const fetchAllAgreements = async () => {
+        setLoading(true);
+        try {
+            const response = await fetch("http://localhost:3001/dealership/agreements-with-payments", {
+                credentials: 'include'
+            });
+
+            if (response.ok) {
+                const data = await response.json();
+                setAgreements(data);
+            } else if (response.status === 401) {
+                toast({
+                    title: "Unauthorized",
+                    description: "Please log in as a dealership to view agreements",
+                    status: "error",
+                    duration: 3000,
+                    isClosable: true,
+                });
+                navigate("/dealershiplogin");
+            } else {
+                throw new Error("Failed to fetch agreements");
+            }
+        } catch (error) {
+            toast({
+                title: "Error",
+                description: "Failed to load agreements",
+                status: "error",
+                duration: 3000,
+                isClosable: true,
+            });
+        } finally {
+            setLoading(false);
+        }
+    };
+
+    const handleViewDocuments = (agreement) => {
+        navigate("/documents", { state: { agreementData: agreement, vin: agreement.vin } });
+    };
+
+    const AgreementCard = ({ agreement }) => {
+        return (
+            <Box
+                borderWidth="1px"
+                borderRadius="lg"
+                overflow="hidden"
+                p="4"
+                bg={agreement.payment_exists ? "green.50" : "white"}
+                boxShadow="md"
+                _hover={{ boxShadow: "lg" }}
+                transition="all 0.3s"
+                borderColor={agreement.payment_exists ? "green.200" : "gray.200"}>
+                
+                <Flex direction="column" gap="2">
+                    <Flex justify="space-between" align="center">
+                        <Text fontWeight="bold" fontSize="lg">
+                            {agreement.make} {agreement.model}
+                        </Text>
+                        <Badge 
+                            colorScheme={agreement.payment_exists ? "green" : "orange"}
+                            fontSize="sm">
+                            {agreement.payment_exists ? "PAID" : "PENDING"}
+                        </Badge>
+                    </Flex>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Year: {agreement.p_year}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Color: {agreement.color}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Client: {agreement.c_name}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Agreement ID: {agreement.a_id}
+                    </Text>
+                    
+                    <Text fontSize="sm" color="gray.600">
+                        Date: {new Date(agreement.datum).toLocaleDateString()}
+                    </Text>
+                    
+                    <Text fontSize="lg" fontWeight="bold" color={agreement.payment_exists ? "green.600" : "blue.600"}>
+                        Price: ${agreement.price}
+                    </Text>
+                    
+                    {agreement.payment_exists && (
+                        <Text fontSize="sm" color="green.600" fontWeight="bold">
+                            Payment Amount: ${agreement.payment_amount}
+                        </Text>
+                    )}
+                    
+                    <Button
+                        colorScheme="blue"
+                        size="sm"
+                        onClick={() => handleViewDocuments(agreement)}
+                        marginTop="2">
+                        View Documents
+                    </Button>
+                </Flex>
+            </Box>
+        );
+    };
+
+    if (loading) {
+        return (
+            <Flex justify="center" align="center" height="200px">
+                <Text>Loading...</Text>
+            </Flex>
+        );
+    }
+
+    return (
+        <Flex width='100%' flexDir='column' justifyContent='center'>
+            <Text
+                marginBottom='20px'
+                textAlign='center'
+                fontWeight='bold'
+                fontSize='30px'
+                justifySelf='center'>
+                All Agreements
+            </Text>
+            
+            <Text fontSize="md" color="gray.600" textAlign="center" mb="6">
+                View all your agreements. Paid agreements are highlighted in green.
+            </Text>
+            
+            {agreements.length === 0 ? (
+                <Flex justify="center" align="center" height="200px">
+                    <Text fontSize="lg" color="gray.500">
+                        No agreements found.
+                    </Text>
+                </Flex>
+            ) : (
+                <SimpleGrid columns={{ base: 1, md: 2, lg: 3 }} spacing={6}>
+                    {agreements.map((agreement, index) => (
+                        <AgreementCard key={agreement.a_id || index} agreement={agreement} />
+                    ))}
+                </SimpleGrid>
+            )}
+        </Flex>
+    );
+};
+
+export default Reports;
