Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ package/
lambda_package/
*.zip

# Java / Maven
target/
*.class
.mvn/wrapper/maven-wrapper.jar

# Node / frontend
node_modules/
.next/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,380 @@
# Group 1 Notice Board / Trainee Tracker — API Contract

## Purpose

This file defines the shared contract between the React frontend, Java/Spring Boot backend, MongoDB layer, deployment configuration, and CI/CD.

Do not rename shared fields, endpoints, class names, or environment variables without updating this file and notifying the team.

**Status:** this replaces an earlier draft of this contract that assumed a single `Notice` resource. The backend actually implemented (Aaron) is a multi-resource trainee-onboarding tracker, matching the class layout already committed to `feature/backend`. This version documents what's real as of 2026-08-28 so Alena/Danielle/Mark can build against it.

---

## 1. Backend Stack

```text
Language: Java 17
Framework: Spring Boot 3.3.4
Build tool: Maven (pom.xml) — not Gradle
Package root: com.edtech.noticeboard
Database: MongoDB Atlas
```

Build command (from `backend/`):

```bash
mvn clean package
```

Produces:

```text
backend/target/noticeboard-backend-0.0.1-SNAPSHOT.jar
```

Dev startup:

```bash
mvn spring-boot:run
```

Production startup:

```bash
java -jar target/noticeboard-backend-0.0.1-SNAPSHOT.jar
```

Backend port:

```text
8080
```

---

## 2. Resources

Four resources exist as MongoDB `@Document` models. **Only `TrainingPlan` has working CRUD right now** — the other three have models + repositories but empty controllers/services (stubs, not yet implemented). See section 4 for exact implementation status per resource.

| Resource | Owner | Status |
|---|---|---|
| `TrainingPlan` | Aaron | **Implemented** — full CRUD, tested against Atlas |
| `User` | Mark | Model + repository only |
| `Cohort` | Mark | Model + repository only |
| `ProgressLog` | Aaron / Danielle | Model + repository only — **field shape not yet finalized, see section 9** |

---

## 3. Resource Fields

### TrainingPlan (implemented)

```text
id String — generated by MongoDB
title String — required, must not be blank
modules List<String>
milestones List<String>
```

Note: there is no `createdAt` field on `TrainingPlan`. If the frontend needs one, tell Aaron before assuming it exists.

### User (stub — not yet exposed via any endpoint)

```text
id String
name String
email String
passwordHash String
role String — TRAINEE, HR, or MANAGER
```

### Cohort (stub — not yet exposed via any endpoint)

```text
id String
name String
studentIds List<String>
```

### ProgressLog (stub — not yet exposed via any endpoint)

```text
id String
traineeId String
moduleId String
status String — NOT_STARTED, IN_PROGRESS, BLOCKED, or COMPLETED
submissionNote String
updatedAt Instant
```

**This field list is a guess Aaron made early on, not something confirmed with Danielle.** Aaron and Danielle must agree on the real shape before `ProgressController`/`ProgressService` get implemented — do not assume these fields are final.

---

## 4. REST Endpoints

### Curriculum API — `TrainingPlan` (implemented)

Backend class names:

```text
TrainingPlan
CurriculumController
CurriculumService
TrainingPlanRepository
```

| Method | Path | Purpose | Status |
|---|---|---|---|
| POST | `/api/curriculum` | Create a TrainingPlan | 201 Created |
| GET | `/api/curriculum` | List all TrainingPlans | 200 OK |
| GET | `/api/curriculum/{id}` | Read one TrainingPlan | 200 OK / 404 |
| PUT | `/api/curriculum/{id}` | Update a TrainingPlan | 200 OK / 404 |
| DELETE | `/api/curriculum/{id}` | Delete a TrainingPlan | 204 No Content / 404 |

#### Create

```http
POST /api/curriculum
Content-Type: application/json

{
"title": "Onboarding Week 1",
"modules": ["Git", "Java Basics"],
"milestones": ["Setup complete"]
}
```

Do not send `id` — it's generated by MongoDB.

Response — `201 Created`:

```json
{
"id": "6a91c37d76e8582777776f72",
"title": "Onboarding Week 1",
"modules": ["Git", "Java Basics"],
"milestones": ["Setup complete"]
}
```

#### List

```http
GET /api/curriculum
```

Response — `200 OK`, empty array if none exist:

```json
[
{
"id": "6a91c37d76e8582777776f72",
"title": "Onboarding Week 1",
"modules": ["Git", "Java Basics"],
"milestones": ["Setup complete"]
}
]
```

#### Read one

```http
GET /api/curriculum/{id}
```

`200 OK` with the object, or `404 Not Found`:

```json
{ "message": "Training plan not found: <id>" }
```

#### Update

```http
PUT /api/curriculum/{id}
Content-Type: application/json

{
"title": "Onboarding Week 1 (updated)",
"modules": ["Git", "Java Basics", "Spring Boot"],
"milestones": ["Setup complete"]
}
```

`200 OK` with the updated object (same `id`), or `404 Not Found` in the same shape as above.

#### Delete

```http
DELETE /api/curriculum/{id}
```

`204 No Content` on success, or `404 Not Found` in the same shape as above.

### Other resources (not yet implemented)

`AuthController` (`/api/auth`), `CohortController` (`/api/cohorts`), `ProgressController` (`/api/progress`), and `DashboardController` (`/api/dashboard`) exist as empty `@RestController` classes with the base `@RequestMapping` path set, but no methods yet. Calling any of them currently returns `404` (no matching route), not a real response.

---

## 5. Validation & Error Format

All error responses (validation failures, not-found, bad input) come back as:

```json
{ "message": "<description>" }
```

- `400 Bad Request` — bean validation failure, e.g. `{ "message": "title must not be blank" }` (verified live)
- `400 Bad Request` — malformed input MongoDB can't parse (e.g. a non-ObjectId `{id}`), e.g. `{ "message": "Invalid request: ..." }` (defensive — added but not yet verified against a live Atlas call in this session; Aaron should confirm with a real `GET /api/curriculum/not-a-real-id` against a running instance)
- `404 Not Found` — missing resource, e.g. `{ "message": "Training plan not found: <id>" }` (verified live)

This is enforced globally by a `@RestControllerAdvice` (`GlobalExceptionHandler`), so any new controller gets the same error shape for free — no need to hand-roll error handling per controller.

---

## 6. Environment Variables

### Backend

```text
MONGODB_URI
```

Full Atlas connection string **including the database name in the path**, e.g.:

```text
mongodb+srv://<user>:<password>@bankcluster.xxxxx.mongodb.net/noticeboard?retryWrites=true&w=majority
```

There is **no separate `MONGODB_DATABASE` variable** — the db name (`noticeboard`) lives inside `MONGODB_URI`. Don't introduce a second variable for it.

Mail (for Aaron's scheduled notification jobs, optional — defaults exist for local dev):

```text
MAIL_HOST
MAIL_PORT
MAIL_USERNAME
MAIL_PASSWORD
```

### Frontend

```text
VITE_API_URL
```

Local value:

```text
http://localhost:8080
```

Curriculum calls should be built as `${VITE_API_URL}/api/curriculum`.

---

## 7. CORS

Configured in `CorsConfig` (`com.edtech.noticeboard.config`). Currently allows only:

```text
http://localhost:5173
```

for `GET`, `POST`, `PUT`, `DELETE`, `OPTIONS` on `/api/**`. **Mark must get the production frontend URL added here before deployment** — it is not automatic.

---

## 8. Auth Status

`SecurityConfig` currently allows every request unauthenticated (`permitAll()`), with CSRF disabled. This is intentional and temporary — it exists so controllers are testable before real auth is wired up. **Mark owns replacing this with real JWT/session auth and role-based access** (`TRAINEE`/`HR`/`MANAGER`, per the `User.role` field). No endpoint currently requires a token.

---

## 9. Open Items

- **`ProgressLog` field shape** — not finalized. Aaron and Danielle must agree on real fields before `ProgressController`/`ProgressService` are implemented.
- **Danielle's USP** — not yet selected. Once chosen, if it changes any resource's fields or adds endpoints, this file must be updated *before* implementation starts, and Aaron/Alena notified.
- **Auth/JWT** — not started (Mark).
- **Production CORS origin** — pending frontend deployment URL (Mark).
- **Deployment architecture** — the backend is Java/Spring Boot (a persistent server), which is a deliberate deviation from this workshop's default Python/FastAPI/Lambda stack. The assignment's Terraform/Lambda scripts assume a Python zip handler and won't apply to this backend as-is. Mark needs either a Lambda-compatible Java handler wrapper or a non-Lambda compute target (EC2/ECS/Elastic Beanstalk) — not yet decided.

---

## 10. How to Test This

Two layers of testing exist, covering different purposes:

### Automated (JUnit)

`backend/src/test/java/com/edtech/noticeboard/service/CurriculumServiceTest.java` — 5 Mockito-based unit tests covering `CurriculumService`: listing, 404-on-missing-id (read and delete), id-stripping on create, and field updates on PUT. No real MongoDB needed — the repository is mocked, so these run fast and don't touch Atlas.

Run them:

```bash
cd backend
mvn test
```

These are what a grader/CI checks for TDD coverage. New backend logic should get tests here, not just manual Postman checks.

### Manual (Postman)

`backend/postman/NoticeBoardTracker-Curriculum.postman_collection.json` — import this into Postman. Two folders:

- **Happy Path** — Create → List → Get By Id → Update → Delete, run top-to-bottom (or via Collection Runner). Each request has `pm.test()` assertions on status code and response shape, and the Create request auto-captures the generated `id` into a collection variable so the rest of the chain uses it automatically. The Delete step cleans up after itself, so running this doesn't leave junk data in the shared Atlas cluster.
- **Error Cases** — blank-title create (400), get/delete on a non-existent id (404). Demonstrates the `{"message": "..."}` error format from section 5.

Collection variable `baseUrl` defaults to `http://localhost:8080` — change it if testing against a deployed instance instead of local.

Before running either folder, start the backend locally with a real `MONGODB_URI` set (see section 6), or point `baseUrl` at wherever it's already running.

---

## 11. Team Responsibilities

### Aaron — Backend + MongoDB CRUD

Owns `CurriculumController`/`CurriculumService` (done), `ProgressController`/`ProgressService` (pending field sync with Danielle), and `NotificationService` (scheduled email jobs, not started).

### Alena — React CRUD Frontend

Consumes `/api/curriculum` per section 4. Needs: React/Vite setup details, Node version, package manager, frontend build command, build output directory — not yet documented here, Alena to fill in.

### Danielle — USP + UX

Owns `DashboardController`/`DashboardService`, and the USP feature. Must notify Aaron/Alena before changing any resource's fields, per section 9.

### Mark — Deployment + CI/CD + Integration

Owns `AuthController`/`AuthService`, `CohortController`/`CohortService`, `SecurityConfig`, `CorsConfig`, and all deployment/CI-CD. See sections 7, 8, and 9 for what's blocking him.

---

## 12. Change Rules

When a contract change is required:

1. Agree on the change with affected teammates.
2. Update this file.
3. Notify all affected team members.
4. Update backend code.
5. Update frontend code.
6. Update tests/Postman.
7. Update deployment configuration if necessary.

### Change Log

```text
2026-08-28 — Replaced single-Notice draft with the actual multi-resource
(User/Cohort/TrainingPlan/ProgressLog) contract matching
what's implemented on feature/backend, after the team
decided to keep the existing Java/Spring Boot backend
rather than rewrite it to match the original draft.

2026-08-28 — Added section 10 (How to Test This): CurriculumServiceTest
(5 JUnit/Mockito unit tests) and a Postman collection at
backend/postman/NoticeBoardTracker-Curriculum.postman_collection.json.
```
Loading