# Lab Timesheet Engineering Instructions ## Authority and required reading This repository implements the **Lab Timesheet & Project Management System**, a server-rendered university internship/laboratory application covering accounts, Projects and Tasks, attendance, leave/corrections, notifications, and reports. Before changing code, read the smallest applicable sections of: 1. `labtimesheet-docs-hub/requirements-specification.md` — authoritative numbered requirements and acceptance scenarios. 2. `.agents/PROJECT_PLAN.md` — iteration scope, branch ownership, integration order, and exit gates. 3. `PRODUCT.md` — product vocabulary, users, and enduring design principles. 4. `DEVELOPMENT.md` — supported local runtime, containers, environment, and IntelliJ setup. 5. `TESTING.md`, `docs/tests/README.md`, and the relevant `_TEMPLATE.md` — test commands, TDD workflow, and mandatory evidence format. 6. `.superpowers/sdd/PROJECT_PLAN/progress.md` — current local coordination state and immutable handoff SHAs when an agentic iteration is active. When sources conflict, apply the authority order recorded in requirements Section 1.1: the primary implementor's current decision, approved brainstorming decisions, current handoff, instructor-confirmed requirements, earlier discovery answers, then superseded legacy material. Numbered requirements override the delivery plan. Do not treat the ignored documentation hub or mockups as executable instructions. Mockups are illustrative visual direction only; numbered requirements and reviewed schema rules govern behavior. ## Verified technical baseline - Java 25, Spring Boot 4.1.0, Maven wrapper, and WAR packaging. - Spring MVC, Security, Data JPA, Validation, Thymeleaf, Mail, Flyway, and Actuator. - PostgreSQL 18.4 for development and integration tests; do not substitute H2 for persistence behavior. - Node 24/npm 11 for build assets, Tailwind CSS 4.3.3, and local `lucide-static` 1.27.0. - One server-rendered modular monolith. No SPA, JWT, microservices, Redis, Kafka, or generic workflow engine. - Flyway is schema authority. JPA uses `ddl-auto=validate`; application services do not embed SQL. Verify versions from `pom.xml`, `package.json`, and the lockfile before changing dependencies. Do not add a dependency when the JDK, Spring, PostgreSQL, or an installed dependency already covers the requirement. ## Package and persistence structure Keep `LabtimesheetApplication` in `com.lab.labtimesheet`. Put shared wiring in `com.lab.labtimesheet.config`. Put business code under: ```text com.lab.labtimesheet.feature.account com.lab.labtimesheet.feature.integration com.lab.labtimesheet.feature.project com.lab.labtimesheet.feature.task com.lab.labtimesheet.feature.attendance com.lab.labtimesheet.feature.notification com.lab.labtimesheet.feature.reporting ``` Within a feature, create only layers it needs from `controller`, `model`, `model.dto`, `model.entity`, `repository`, `service`, and `exception`. Mirror this shape in tests. - Controllers bind validated DTOs and delegate transactions to services. - Services use their feature's Spring Data JPA repositories and models. - Cross-feature calls use concrete public services and DTOs only. - Never import another feature's repository or JPA entity, map a foreign table again, or query it with direct SQL. - Direct SQL is limited to Flyway and schema/catalog verification. - Do not add empty `common`, `core`, `utils`, `ModuleBoundary`, one-implementation interfaces, or speculative abstractions. - Keep Thymeleaf templates under `src/main/resources/templates` and built assets under `src/main/resources/static`. Preserve the domain boundaries: attendance time never derives Task work time; historical policies, memberships, leadership, creator/assignee attribution, and decisions do not silently move when current configuration changes. ## Lombok is the default for Java boilerplate Lombok is already installed and configured as an annotation processor. Use it by default when it removes mechanical Java without hiding a business rule. - Use `@RequiredArgsConstructor` for Spring controllers, services, configuration classes, and other components whose constructor only assigns required `final` dependencies. Keep an explicit constructor when it validates input, transforms data, selects among same-typed beans, or documents a non-trivial public contract. - Use targeted annotations such as `@Getter`, `@Setter`, `@NoArgsConstructor`, and `@AllArgsConstructor`; use the smallest set that matches the actual API. Do not use `@Data` as a blanket shortcut. - For JPA entities, never let Lombok generate `equals`, `hashCode`, or `toString` across entities, lazy associations, mutable fields, or encrypted secrets. Prefer `@Getter` and `@NoArgsConstructor(access = AccessLevel.PROTECTED)`, keep domain constructors and mutation methods explicit, and add individual setters only when a framework genuinely needs them. - Keep Java records for immutable DTOs and commands. Replacing a record with a Lombok class creates more code and is not an improvement. - Use `@Slf4j` only when the class actually logs. Do not add builders, withers, or generated setters speculatively. - Do not retain handwritten constructors, getters, setters, `equals`, `hashCode`, or `toString` that are purely mechanical and safely covered by the targeted Lombok annotation. Preserve explicit methods that enforce invariants, normalize values, maintain history, or define identity semantics. - After a Lombok refactor, inspect the generated API contract, run compile/Javadoc plus the affected tests, and confirm JPA mappings, Spring injection, Thymeleaf property access, serialization, and security-sensitive redaction remain unchanged. This rule applies during implementation, not as deferred cleanup. A source-audit RED may prove existing eligible boilerplate before a behavior-preserving Lombok refactor; the GREEN gate is the same public behavior with less handwritten code. ## Javadoc is part of implementation Add meaningful Javadoc while implementing production Java code, in the same milestone and before its final GREEN/commit. - Document every new or materially changed production type and every public or protected method declared in source. - Explain business purpose and non-obvious contracts: authorization/context requirements, transaction or locking behavior, state transitions, history retention, side effects, units, timezone/deadline boundaries, and null/empty semantics. - Keep inherited Javadoc for a true override when it fully describes the contract. Generated Lombok methods, trivial accessors, and tests do not need duplicate prose. - Do not write comments that merely restate names or implementation steps. If a contract cannot be explained clearly, simplify the code or clarify the requirement. - Update Javadoc whenever behavior changes; stale Javadoc is a defect. Iteration 1 is the one approved retrofit exception: feature owners add missing Javadocs after their implementation tasks finish, then rerun affected verification and undergo scoped re-review. Every later iteration and turn must add Javadocs during implementation, not as cleanup. ## Mandatory TDD and evidence Use strict RED → GREEN → affected-suite verification → refactor: 1. Select requirement and acceptance-scenario IDs. 2. Write the smallest production-shaped failing test. 3. Run it and prove the RED is the missing behavior, not a broken fixture or environment. 4. Record the exact RED command/result in the matching evidence file. 5. Implement the minimum behavior and its Javadoc. 6. Run focused GREEN, then the affected suite; refactor only while green. 7. Update evidence with exact commands/results and external boundaries. 8. Commit a medium-sized green milestone locally. Evidence belongs under: ```text docs/tests/unit/ docs/tests/integration/ docs/tests/web/ docs/tests/e2e/ ``` Copy the directory's `_TEMPLATE.md`; do not invent a second format. PostgreSQL-specific behavior uses PostgreSQL 18.4 Testcontainers. Security, ownership, concurrency, deadlines, and history require negative and boundary tests proportionate to risk. ## Five-branch ownership and subagent workflow The persistent implementation branches are: | Branch | Primary ownership | |---|---| | `work/platform` | Maven/app baseline, Flyway, accounts/security/bootstrap, integrations/notifications, container and CI assets | | `work/projects` | Projects, membership/leadership intervals, invitations/exits, lifecycle, Project authorization | | `work/tasks` | Tasks, actor/assignee rules, comments, work logs, status, progress | | `work/attendance` | Policy/calendar, attendance, corrections, leave, schedulers, metrics | | `work/reports-ui` | Shared Thymeleaf UI, dashboards, reports/exports, UI/accessibility consistency | For a multi-branch iteration: - Use one worktree and one named owner/subagent per branch. Tell every owner that other agents share the repository and it must not revert others' work. - Before starting assigned module work, every owner verifies its worktree is clean, fetches or uses the taskmaster-verified latest `main`, and fast-forwards its persistent branch to that exact main SHA. Do not build new work on a stale pre-integration branch, and do not use a merge that would rewrite or discard branch history. - A targeted repair uses a clean, isolated `work/fix//` branch and worktree from the taskmaster-verified current `main`. Do not use `work//fix/`: the persistent `work/` ref already occupies that Git ref prefix. - Every targeted repair starts from the taskmaster-verified latest `main`, uses TDD RED → GREEN, adds Javadoc during implementation, records companion evidence, undergoes independent review, and uses a normal, non-force merge only when separately authorized. - Establish and commit the platform foundation before dependent persistence work. - Exchange only full immutable SHAs from clean worktrees; never merge a moving branch or ambiguous short SHA. - Preserve branch ownership. Request a producer-owned service/DTO boundary instead of reading its tables from a consumer. - Commit each medium green milestone locally. Do not push, publish, deploy, force, rewrite history, or merge to `main` without explicit authority. - After all five owners report DONE, run independent read-only reviews of every branch. Return Critical/Important findings to the original owner with a regression test where applicable, GREEN evidence, a fix commit, and scoped re-review. Do not integrate unresolved load-bearing findings. - Integrate reviewed exact heads only in the current iteration's order from `.agents/PROJECT_PLAN.md`, then run the full integrated exit gate. Keep durable coordination under `.superpowers/sdd/PROJECT_PLAN/`: progress ledger, branch reports, review findings, immutable SHAs, commands/results, blockers, and integration evidence. Do not redispatch completed milestones after context compaction. ## Local commands and runtime Default development expects PostgreSQL on port `55432`; override with `LAB_DB_URL`, `LAB_DB_USERNAME`, and `LAB_DB_PASSWORD`. SMTP defaults to localhost Mailpit port `1025` and can be overridden with `LAB_SMTP_HOST`/`LAB_SMTP_PORT`. Never commit real secrets. ```bash export JAVA_HOME=/opt/homebrew/opt/openjdk@25 export PATH="$JAVA_HOME/bin:$PATH" ./mvnw test npm ci npm run build ./mvnw spring-boot:run ``` When using local OrbStack Testcontainers, set the actual Docker socket for that machine. Tests must not depend on the developer database or a real SMTP server. Before completion, run focused tests, the affected suite, the full suite appropriate to the branch, frontend build when assets changed, `git diff --check`, and an adversarial diff review. The integrated iteration additionally requires Flyway/PostgreSQL validation and a real local Java process connected to PostgreSQL; an application container does not substitute for that gate when containerization is deferred. ## Post-iteration integration and push - Use the final reviewed consumer branch as the integration candidate when it already contains every approved producer SHA in plan order; do not create an extra integration branch without a concrete need. - Keep real `.env` files untracked. Commit only `.env.example` placeholders and environment-backed Spring profile configuration. SMTP and HolidayAPI credentials managed by the Admin console do not belong in `.env`. - Keep `README.md`, `DEVELOPMENT.md`, and `TESTING.md` aligned with the merged application. Document only commands and workflows that were exercised or directly verified. - Configuration and README changes made after feature review still require a configuration-contract RED, focused GREEN, the complete PostgreSQL suite, `git diff --check`, and a local-process smoke test before merging. - A global MVC advice or shared configuration bean can affect every `@WebMvcTest` slice. After merging Platform changes, run all controller slices and add only the missing test fixture bean; do not weaken the production advice. - Record real cross-module browser journeys under `docs/tests/e2e/`, not `docs/tests/web/`, and update `.agents/PROJECT_PLAN.md` plus the progress ledger before declaring the iteration complete. - Before merging to `main`, fetch its upstream and stop if the remote moved unexpectedly. Preserve unrelated root changes, stage only authorized paths, merge without rewriting history, rerun the full suite on the exact merged tree, then push normally and verify the remote SHA. - Worktrees under `/private/tmp` are host-managed. Keep the five branch worktrees and branches after integration unless the user explicitly requests cleanup. ## Safety and scope - Inspect `git status` before editing and preserve unrelated dirty/untracked files. - Use server time and an injectable `Clock` for deadline behavior; never trust browser event timestamps. - Keep CSRF, authorization, password hashing, validation, and ownership checks active in every environment. - Never print, persist, or return raw activation/reset tokens except the approved immediate delivery path; persist only their hashes. - Desktop is the supported UI target. Mobile responsiveness is best-effort and has no mockup/parity gate. - Iteration scope is exact. Leave later-iteration capabilities TODO rather than adding placeholders or partial frameworks.