docs(dev): add iteration 1 setup and reports

This commit is contained in:
sechmachine
2026-08-15 11:02:27 +07:00
parent 039fe25c7c
commit 4212e9cbc2
8 changed files with 711 additions and 22 deletions
+14
View File
@@ -0,0 +1,14 @@
# Copy to .env, replace every placeholder, then load it into the IDE or shell.
SPRING_PROFILES_ACTIVE=dev
LAB_SERVER_PORT=8080
LAB_FORWARD_HEADERS_STRATEGY=NONE
LAB_DB_URL=jdbc:postgresql://localhost:55432/labtimesheet
LAB_DB_USERNAME=labtimesheet
LAB_DB_PASSWORD=replace-with-local-database-password
LAB_SMTP_HOST=localhost
LAB_SMTP_PORT=1025
LAB_PUBLIC_ORIGIN=http://localhost:8080
LAB_SECURITY_MASTER_KEY=replace-with-base64-encoded-32-byte-key
+1
View File
@@ -29,6 +29,7 @@ build/
!**/src/main/**/build/ !**/src/main/**/build/
!**/src/test/**/build/ !**/src/test/**/build/
node_modules/ node_modules/
/.env
### VS Code ### ### VS Code ###
.vscode/ .vscode/
+233
View File
@@ -0,0 +1,233 @@
# Development Guide
This guide explains how to prepare and run Lab Timesheet on a developer
computer. The application runs from Java. PostgreSQL and Mailpit run in Docker
containers.
Application containerization and Docker Compose are planned for a later
iteration, so they are not required for Iteration 1 development.
## 1. Install the required tools
Install:
- Java 25
- Docker Desktop or OrbStack
- Node.js 24 and npm 11
- Git
- IntelliJ IDEA, if you want to run the application from the IDE
Confirm the tools are available:
```bash
java -version
docker version
node --version
npm --version
```
On macOS, select an installed Java 25 JDK with:
```bash
export JAVA_HOME=$(/usr/libexec/java_home -v 25)
export PATH="$JAVA_HOME/bin:/opt/homebrew/opt/node@24/bin:$PATH"
```
Java 25 is the supported project baseline. A newer local JDK can compile the
project but is not the shared team baseline.
## 2. Prepare the project
Clone the repository, open a terminal in its root directory, then create your
local environment file:
```bash
cp .env.example .env
```
Edit `.env` and replace the database password placeholder. Generate the
encryption master key with:
```bash
openssl rand -base64 32
```
Copy that output into `LAB_SECURITY_MASTER_KEY`. Never commit `.env` or share a
real key in chat, screenshots, test evidence, or documentation.
Install and build the local frontend assets:
```bash
npm ci
npm run build
```
## 3. Start the development containers
### PostgreSQL 18.4
Create a named volume once. The volume keeps your development data when the
container is stopped or replaced.
```bash
docker volume create labtimesheet-postgres-data
```
Start PostgreSQL:
```bash
docker run -d \
--name labtimesheet-postgres \
--restart unless-stopped \
-e POSTGRES_DB=labtimesheet \
-e POSTGRES_USER=labtimesheet \
-e POSTGRES_PASSWORD=replace-with-same-password-as-env \
-p 127.0.0.1:55432:5432 \
-v labtimesheet-postgres-data:/var/lib/postgresql \
postgres:18.4
```
Use the same password for `POSTGRES_PASSWORD` and `LAB_DB_PASSWORD` in `.env`.
PostgreSQL stores the original password in the volume. Changing only `.env`
later will not change the database password.
### Mailpit
Mailpit receives development email without sending it to real people.
```bash
docker run -d \
--name labtimesheet-mailpit \
--restart unless-stopped \
-p 127.0.0.1:1025:1025 \
-p 127.0.0.1:8025:8025 \
axllent/mailpit:v1.27.4
```
Confirm both containers are running:
```bash
docker ps
```
Useful container commands:
```bash
docker logs labtimesheet-postgres
docker logs labtimesheet-mailpit
docker stop labtimesheet-postgres labtimesheet-mailpit
docker start labtimesheet-postgres labtimesheet-mailpit
```
Stopping the containers keeps the database volume. Do not remove the volume
unless you intentionally want to discard your local development data.
## 4. Run from a terminal
Load the environment file in the same terminal that will run Spring Boot:
```bash
set -a
source .env
set +a
./mvnw spring-boot:run
```
Open:
- First-Admin setup: `http://localhost:8080/bootstrap`
- Login: `http://localhost:8080/login`
- Mailpit inbox: `http://localhost:8025`
At first setup, configure SMTP through the Admin console with:
| Setting | Development value |
|---|---|
| Host | `localhost` |
| Port | `1025` |
| Security | `NONE` |
| Username | leave empty |
| Password | leave empty |
| From address | a local address such as `labtimesheet@example.test` |
| From name | `Lab Timesheet` |
Test the draft before activating it. Mailpit's web inbox shows activation and
other development messages.
Stop the application with `Control+C`.
## 5. Run with IntelliJ IDEA
### Open the project
1. Open IntelliJ IDEA.
2. Choose **Open** and select the repository root.
3. Allow IntelliJ to import the Maven project.
4. Open **File > Project Structure > Project**.
5. Select a Java 25 SDK. Add the JDK installation if it is not listed.
### Create the run configuration
1. Open **Run > Edit Configurations**.
2. Select **+**, then **Spring Boot**.
3. Use the name `Lab Timesheet (dev)`.
4. Set **Main class** to
`com.lab.labtimesheet.LabtimesheetApplication`.
5. Set **Use classpath of module** to the main `labtimesheet` module.
6. Set **JRE** to Java 25.
7. Set **Active profiles** to `dev`.
8. Set **Working directory** to the repository root.
9. Open the **Environment variables** editor and add every variable from your
local `.env` file.
10. Apply the configuration and run it.
Some IntelliJ editions can load variables from an environment file directly.
If that option is available, select the local `.env`; otherwise use the
environment-variable table. Do not store real secrets in a shared or committed
run configuration.
Run `npm ci` and `npm run build` in IntelliJ's terminal before the first launch
and after changing Tailwind or icon sources.
## 6. Common problems
### The application cannot connect to PostgreSQL
Run:
```bash
docker ps
docker logs labtimesheet-postgres
```
Check that `.env` uses port `55432`, database `labtimesheet`, user
`labtimesheet`, and the password used when the PostgreSQL volume was first
created.
### Port 8080, 55432, 1025, or 8025 is already in use
Stop the other program or container using that port. Keep `.env` and the Docker
port mapping consistent if you intentionally select another development port.
### Mail does not appear in Mailpit
Check that Mailpit is running and that the active Admin SMTP configuration uses
host `localhost`, port `1025`, and security `NONE`. A container health warning
does not by itself prove that SMTP is unavailable; use the Admin SMTP test.
### IntelliJ uses the wrong Java version
Check both **Project SDK** and the run configuration's **JRE**. They should both
be Java 25.
### Styles or icons are missing
Run:
```bash
npm ci
npm run build
```
For test setup, commands, TDD, and test evidence rules, read
[TESTING.md](TESTING.md).
+117 -9
View File
@@ -1,24 +1,132 @@
# Lab Timesheet # Lab Timesheet
Server-rendered Spring Boot application for managing laboratory internships,
Projects, Tasks, and attendance. Iteration 1 is complete and was verified on
15 August 2026.
## Iteration 1: working now
### Accounts and onboarding
- Atomic first-Admin bootstrap that remains closed after initialization and restart.
- Optional SMTP onboarding with five distinct deferral warnings and a persistent restricted-state notice.
- Admin SMTP draft, connection test, and activation against Mailpit or another configured server.
- Admin creation of Admin, Mentor, and Intern accounts through single-use email activation.
- Password setup, form login, logout, global roles, and role-protected Admin routes.
### Projects
- Owning Mentors create `PLANNED` Projects with an eligible initial Leader.
- Mentor-controlled direct membership with historical membership and leadership intervals.
- Leader reassignment and guarded `PLANNED` to `ACTIVE` activation.
- Role-correct Project lists, details, member views, and guessed-ID concealment.
### Tasks
- One current assignee per Task.
- Active members create self-assigned Tasks; the current Leader may assign another active member.
- Due dates are checked against Project dates and current global days off.
- The fixed `TODO`, `IN_PROGRESS`, `BLOCKED`, and `DONE` transition graph is enforced.
- Authorized comments, Task lists/details, assignee display, status counts, and completion progress.
### Attendance and calendar
- Effective attendance-policy resolution with Vietnam business time, configured workdays, and separate 30-minute check-in and checkout grace defaults.
- Admin-managed manual global calendar days off.
- Server-time check-in and checkout with duplicate, off-day, leave-day, lifecycle, and cutoff rejection.
- `MISSING_CHECKOUT` classification without a second early-departure violation.
- Intern history plus authorized Mentor/Admin attendance inspection using the historical applied policy.
### Desktop UI
- Shared Thymeleaf/Tailwind shell with role-aware navigation and dashboards.
- Light, dark, and system themes applied before paint.
- Collapsible desktop sidebar, accessible forms/errors, tables, badges, empty states, and local Lucide icons.
- Bootstrap, authentication, SMTP, Project, Task, calendar, and attendance pages integrated into the same shell.
## Deliberately not implemented yet
The baseline schema includes later-workflow tables; table presence does not mean
the corresponding feature is complete.
- Iteration 2: Project invitations and approved membership exits, broader Project lifecycle transfers, Task edit/delete/reassignment and work logs, leave, missed-checkout corrections, notifications, schedulers, and complete metrics.
- Iteration 3: HTML/XLSX/PDF report parity, Chart.js trends, production security hardening, application containers, Compose, Gitea CI publication, and deployment scaffolding.
- Mobile layouts are best-effort. Desktop is the supported interface target.
## Architecture and versions
- Java 25, Spring Boot 4.1.0, Maven, Spring MVC/Security/Data JPA/Validation, Thymeleaf, Flyway, and PostgreSQL 18.4.
- Node 24/npm 11, Tailwind CSS 4.3.3, and `lucide-static` 1.27.0 for local assets.
- Package-by-feature modular monolith under `com.lab.labtimesheet.feature`.
- Cross-feature access through public services and DTOs; no cross-feature repositories, shadow entities, or business SQL.
- Flyway owns the schema; Hibernate validates it with `ddl-auto=validate`.
## Local development ## Local development
The application targets Java 25 and expects PostgreSQL on Follow [DEVELOPMENT.md](DEVELOPMENT.md) for the complete beginner-friendly
`localhost:55432` when the default `dev` profile is active. Override any local setup, PostgreSQL and Mailpit container commands, terminal launch steps, and an
value with `LAB_DB_URL`, `LAB_DB_USERNAME`, `LAB_DB_PASSWORD`, IntelliJ IDEA run-configuration walkthrough.
`LAB_SMTP_HOST`, or `LAB_SMTP_PORT`.
The committed [`.env.example`](.env.example) contains placeholders only. Real
database passwords and the AES-256 master key belong in an untracked `.env`.
Product SMTP and HolidayAPI credentials are configured through the Admin
console, not environment variables.
```bash ```bash
cp .env.example .env
# Edit .env. Generate LAB_SECURITY_MASTER_KEY with: openssl rand -base64 32
set -a
source .env
set +a
export JAVA_HOME=/opt/homebrew/opt/openjdk@25 export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="$JAVA_HOME/bin:$PATH" export PATH="/opt/homebrew/opt/node@24/bin:$JAVA_HOME/bin:$PATH"
npm ci
npm run build
./mvnw spring-boot:run ./mvnw spring-boot:run
``` ```
Tests use PostgreSQL 18.4 through Testcontainers and do not use the developer Development defaults to the application on port `8080`, PostgreSQL on `55432`,
database: and Mailpit SMTP on `1025`. The exact Spring settings are in
[`application-dev.properties`](src/main/resources/application-dev.properties).
On first launch, open `http://localhost:8080/bootstrap`, create the first Admin,
then configure and test SMTP or complete all five explicit deferral warnings.
## Verification status
The final Iteration 1 integration gate recorded:
- 197 Maven tests passed with PostgreSQL 18.4 Testcontainers.
- Flyway replay produced exactly 23 application tables and 56 foreign keys.
- Java compilation and full Javadoc/doclint passed.
- Two consecutive Node/Tailwind/Lucide builds produced identical assets.
- A real Java process completed bootstrap, login, SMTP deferral, persistent warning recovery, and a separate Mailpit draft/test/activate flow with health `UP`.
- Independent reviews of all five work branches closed with no remaining Critical, Important, or Minor findings.
Tests require Docker for PostgreSQL Testcontainers:
```bash ```bash
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export DOCKER_HOST=unix:///Users/your-name/.orbstack/run/docker.sock # only when using OrbStack
./mvnw test ./mvnw test
``` ```
Every feature test must have a companion Markdown evidence record under See [TESTING.md](TESTING.md) for setup, test commands, the required TDD cycle,
[`docs/tests`](docs/tests/README.md). evidence records, best practices, and common fixes. Every behavior test has a
companion record under [`docs/tests`](docs/tests/README.md).
## Branch ownership
| Branch | Primary area |
|---|---|
| `work/platform` | Application baseline, schema, accounts, security, integrations |
| `work/projects` | Projects, membership, leadership, lifecycle |
| `work/tasks` | Tasks, comments, status, progress |
| `work/attendance` | Policy, calendar, attendance workflows |
| `work/reports-ui` | Shared UI, dashboards, reporting presentation |
Iteration 2 work must start from the merged Iteration 1 `main`, continue with
strict RED-to-GREEN TDD, add Javadoc during implementation, and update the
matching Markdown evidence record before each milestone commit.
+243
View File
@@ -0,0 +1,243 @@
# Testing Guide
This guide explains how to prepare the test environment, run each type of test,
and follow the project's required test-driven development workflow.
## 1. What you need
Install these tools before running tests:
- Java 25
- Docker Desktop or OrbStack
- Node.js 24 and npm 11
- Git
Confirm the tools are available:
```bash
java -version
docker version
node --version
npm --version
```
On macOS with Homebrew, the project normally uses:
```bash
export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="/opt/homebrew/opt/node@24/bin:$JAVA_HOME/bin:$PATH"
```
If you use OrbStack and Testcontainers cannot find Docker, set:
```bash
export DOCKER_HOST=unix:///Users/your-name/.orbstack/run/docker.sock
```
Replace `your-name` with your macOS account name. Docker Desktop users normally
do not need this setting.
Tests use temporary PostgreSQL 18.4 containers. They do not use the development
database, Mailpit, or the local `.env` file.
## 2. First test run
From the repository root, run:
```bash
./mvnw test
```
The first run may take longer because Docker downloads PostgreSQL and
Testcontainers support images. A successful run ends with `BUILD SUCCESS`.
Frontend assets have a separate check:
```bash
npm ci
npm run build
```
## 3. Test types used by this project
### Unit tests
Unit tests check a small rule or calculation without starting the full
application. Examples include Task status transitions and progress calculations.
Run one class:
```bash
./mvnw -Dtest=TaskDomainRulesTest test
```
### Integration tests
Integration tests check real Spring services, Flyway migrations, JPA mappings,
transactions, and PostgreSQL constraints. Docker must be running.
Run one integration class:
```bash
./mvnw -Dtest=AttendancePersistenceIntegrationTest test
```
### Web tests
Web tests send requests through Spring MVC and check security, validation,
Thymeleaf pages, redirects, and error messages without opening a browser.
```bash
./mvnw -Dtest=TaskControllerTest test
```
### End-to-end checks
End-to-end checks use the running application in a real desktop browser. They
cover complete journeys such as bootstrap, login, SMTP setup, Projects, Tasks,
and attendance.
Current end-to-end checks are guided manual checks:
1. Prepare `.env` by following the main README.
2. Start PostgreSQL 18.4 and Mailpit.
3. Run `./mvnw spring-boot:run`.
4. Follow the scenario written in `docs/tests/e2e/`.
5. Record the browser, viewport, result, and any boundary that was not tested.
Do not record a real browser journey as a web test. Use `docs/tests/e2e/`.
### Structure and configuration checks
Structure tests protect package boundaries and prevent one feature from reading
another feature's repositories or database entities.
```bash
./mvnw -Dtest=LayerStructureTest test
```
Simple configuration or documentation changes use the smallest useful shell
check, followed by the affected Maven suite. Do not create an artificial Java
test only to check that a text file exists.
## 4. Useful commands
Run one test method:
```bash
./mvnw '-Dtest=TaskControllerTest#validCreateFormUsesAuthenticatedIdentityAndRedirectsToCreatedTask' test
```
Run tests for one feature by name:
```bash
./mvnw -Dtest='*Attendance*Test' test
```
Run the complete backend suite:
```bash
./mvnw test
```
Check compilation and Javadoc:
```bash
./mvnw -DskipTests compile
./mvnw -DskipTests -Ddoclint=all javadoc:javadoc
```
Check whitespace and patch formatting:
```bash
git diff --check
```
Maven test reports are written to `target/surefire-reports/`.
## 5. Required TDD workflow
TDD means writing the test before writing the production behavior.
1. Choose the requirement and acceptance-scenario IDs.
2. Copy the matching template from `docs/tests/unit`, `integration`, `web`, or `e2e`.
3. Write the smallest test that proves the missing behavior.
4. Run that test and confirm it fails for the expected reason. This is **RED**.
5. Record the exact command and useful failure output in the evidence file.
6. Write the minimum production code and its Javadoc. Do not add unrelated work.
7. Run the same test again. It must pass. This is **GREEN**.
8. Run the affected feature tests, then the full suite when the milestone is complete.
9. Refactor only while the tests stay green.
10. Update the evidence file and commit the complete milestone.
If the first test fails because Docker is stopped, a class name is wrong, or the
test setup is broken, that is not a valid RED. Fix the environment or test first.
## 6. Evidence records
Every behavior test needs one Markdown record in the matching directory:
```text
docs/tests/unit/
docs/tests/integration/
docs/tests/web/
docs/tests/e2e/
```
Keep every heading from `_TEMPLATE.md`. Record:
- requirement and scenario IDs;
- the behavior being protected;
- how the expected result was calculated;
- exact RED and GREEN commands and results;
- the affected-suite result;
- anything the test did not prove.
One record may cover a closely related parameterized scenario set. A written
claim never replaces a test command and result.
## 7. Testing best practices
- Test user-visible behavior and stored results, not private method details.
- Use PostgreSQL 18.4 for persistence tests. Do not replace it with H2.
- Test allowed actions and denied actions, including guessed IDs and wrong roles.
- Include boundary values for dates, times, grace periods, passwords, and status transitions.
- Use the project's injectable `Clock`; do not make tests depend on the real current time.
- Keep each test independent. Do not rely on another test running first.
- Use real Spring and database components at the boundary being tested. Mock only external services such as SMTP or HolidayAPI when appropriate.
- Never put real passwords, API keys, activation links, or reset links in test code or evidence.
- Do not remove assertions, catch errors, or disable security simply to make a test pass.
- Run the focused test first so feedback is fast, then run the broader suite before committing.
- Give tests names that describe the rule and expected result.
- Clean up temporary browser data, application processes, and manually started containers after end-to-end work.
## 8. Common problems
### Testcontainers cannot find Docker
Start Docker Desktop or OrbStack. Run `docker version`. OrbStack users should
also check the `DOCKER_HOST` command shown in Section 1.
### The wrong Java version is used
Run `java -version` and `./mvnw -version`. Both should report Java 25. Set
`JAVA_HOME` again if Maven uses another JDK.
### The application cannot start for a manual browser check
Confirm `.env` was loaded, PostgreSQL is reachable, and
`LAB_SECURITY_MASTER_KEY` decodes from Base64 to 32 bytes. Automated tests do
not need this local file.
### A test passes alone but fails in the full suite
Check for shared state, fixed ports, assumptions about test order, or data that
was not created by the test itself. Do not hide the failure with retries.
### Build output looks stale
Use this only after confirming the ordinary command is using stale compiled output:
```bash
./mvnw clean test
```
@@ -0,0 +1,68 @@
# Test Evidence: Development environment configuration
- **Test type:** Integration
- **Requirement IDs:** `OPS-001`, `OPS-004`, `SEC-013`
- **Scenario IDs:** `AC-OPS-001`, `AC-SEC-005`
- **Test class/method:** Shell configuration contract plus the full Spring Boot Maven suite
- **Implementation commit:** `pending`
## Protected behavior
Development starts from environment-backed datasource, encryption, public-origin, server, proxy, and local Mailpit settings without committing a real `.env` or weakening application security controls.
## Test method
A shell contract verifies that the committed placeholder and development properties exist, the superseded YAML is absent, the real `.env` is ignored, every required environment key is represented, and every application placeholder resolves after loading the local file. The full Maven suite then exercises Spring configuration binding, Flyway, JPA validation, security, and PostgreSQL behavior.
## Hand-derived expected result
The committed tree contains `.env.example` and `application-dev.properties`, never tracks `.env`, and exposes exactly the environment inputs needed by the current application. Loading the local file gives Spring a `dev` profile, PostgreSQL connection, 32-byte Base64 encryption key, public origin, local Mailpit endpoint, server port, and explicit no-forwarded-header policy.
## RED
**Command**
```text
required_files=(.env.example src/main/resources/application-dev.properties); failed=0; for file in $required_files; do if [ ! -f "$file" ]; then echo "MISSING $file"; failed=1; fi; done; if [ -f src/main/resources/application-dev.yaml ]; then echo 'STALE src/main/resources/application-dev.yaml'; failed=1; fi; if ! grep -qx '/.env' .gitignore; then echo 'MISSING /.env ignore rule'; failed=1; fi; exit "$failed"
```
**Observed result**
```text
MISSING .env.example
MISSING src/main/resources/application-dev.properties
STALE src/main/resources/application-dev.yaml
MISSING /.env ignore rule
exit 1
```
## GREEN
**Command**
```text
required_files=(.env.example src/main/resources/application-dev.properties); required_env=(SPRING_PROFILES_ACTIVE LAB_SERVER_PORT LAB_FORWARD_HEADERS_STRATEGY LAB_DB_URL LAB_DB_USERNAME LAB_DB_PASSWORD LAB_SMTP_HOST LAB_SMTP_PORT LAB_PUBLIC_ORIGIN LAB_SECURITY_MASTER_KEY); required_props=(server.port server.forward-headers-strategy spring.datasource.url spring.datasource.username spring.datasource.password spring.jpa.hibernate.ddl-auto spring.jpa.open-in-view spring.flyway.enabled spring.mail.host spring.mail.port lab.public-origin lab.security.master-key); failed=0; for file in $required_files; do if [ ! -f "$file" ]; then echo "MISSING $file"; failed=1; fi; done; if [ -f src/main/resources/application-dev.yaml ]; then echo 'STALE src/main/resources/application-dev.yaml'; failed=1; fi; if ! grep -qx '/.env' .gitignore; then echo 'MISSING /.env ignore rule'; failed=1; fi; for key in $required_env; do if ! grep -q "^${key}=" .env.example; then echo "MISSING example $key"; failed=1; fi; if ! grep -q "^${key}=" .env; then echo "MISSING local $key"; failed=1; fi; done; for property in $required_props; do if ! grep -q "^${property}=" src/main/resources/application-dev.properties; then echo "MISSING property $property"; failed=1; fi; done; set -a; source .env; set +a; decoded_bytes=$(printf '%s' "$LAB_SECURITY_MASTER_KEY" | base64 -d | wc -c | tr -d ' '); if [ "$decoded_bytes" != 32 ]; then echo "INVALID master key bytes=$decoded_bytes"; failed=1; fi; if ! git check-ignore -q .env; then echo 'LOCAL .env is not ignored'; failed=1; fi; if git ls-files --error-unmatch .env >/dev/null 2>&1; then echo 'LOCAL .env is tracked'; failed=1; fi; if [ "$failed" -eq 0 ]; then echo 'development configuration contract: PASS'; fi; exit "$failed"
```
**Observed result**
```text
development configuration contract: PASS
A real Java 25 process loaded `.env` and `application-dev.properties`, connected to PostgreSQL 18.4, validated Flyway/JPA, and started on the environment-overridden port 18081. With temporary Mailpit on the configured SMTP port, `/actuator/health` returned HTTP 200 with `UP`, and `/login` returned HTTP 200. The process shut down and the temporary Mailpit container was removed.
```
## Affected suite
**Command and result**
```text
env -u SPRING_PROFILES_ACTIVE -u LAB_SERVER_PORT -u LAB_FORWARD_HEADERS_STRATEGY -u LAB_DB_URL -u LAB_DB_USERNAME -u LAB_DB_PASSWORD -u LAB_SMTP_HOST -u LAB_SMTP_PORT -u LAB_PUBLIC_ORIGIN -u LAB_SECURITY_MASTER_KEY /bin/zsh -lc 'export JAVA_HOME=/opt/homebrew/opt/openjdk@25; export PATH=/opt/homebrew/opt/node@24/bin:$JAVA_HOME/bin:$PATH; export DOCKER_HOST=unix:///Users/sechmachine/.orbstack/run/docker.sock; ./mvnw test'
Tests run: 197, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS in 01:33 using PostgreSQL 18.4 Testcontainers. No development environment value was present.
```
## External-test boundaries
The committed example cannot prove another developer's local credentials. Product SMTP and HolidayAPI revisions remain Admin-console configuration and are intentionally absent from `.env`.
@@ -0,0 +1,35 @@
# Development profile. Values that differ between machines come from an untracked .env file.
server.port=${LAB_SERVER_PORT}
server.forward-headers-strategy=${LAB_FORWARD_HEADERS_STRATEGY}
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=false
server.servlet.session.cookie.same-site=lax
server.error.include-message=never
server.error.include-stacktrace=never
spring.datasource.url=${LAB_DB_URL}
spring.datasource.username=${LAB_DB_USERNAME}
spring.datasource.password=${LAB_DB_PASSWORD}
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.open-in-view=false
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
spring.docker.compose.enabled=false
# Mailpit keeps Spring's mail health check local. User-facing SMTP credentials remain Admin-console data.
spring.mail.host=${LAB_SMTP_HOST}
spring.mail.port=${LAB_SMTP_PORT}
spring.mail.protocol=smtp
spring.mail.test-connection=false
spring.mail.properties.mail.smtp.auth=false
spring.mail.properties.mail.smtp.starttls.enable=false
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000
management.endpoints.web.exposure.include=health,info
management.endpoint.health.show-details=when_authorized
lab.public-origin=${LAB_PUBLIC_ORIGIN}
lab.security.master-key=${LAB_SECURITY_MASTER_KEY}
-13
View File
@@ -1,13 +0,0 @@
spring:
datasource:
url: ${LAB_DB_URL:jdbc:postgresql://localhost:55432/labtimesheet}
username: ${LAB_DB_USERNAME:labtimesheet}
password: ${LAB_DB_PASSWORD:labtimesheet_dev}
mail:
host: ${LAB_SMTP_HOST:localhost}
port: ${LAB_SMTP_PORT:1025}
lab:
public-origin: ${LAB_PUBLIC_ORIGIN:http://localhost:8080}
security:
# Explicit non-production key; production must supply its own 256-bit key.
master-key: AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=