diff --git a/.env.prod.example b/.env.prod.example index ded8a3e..497635e 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -3,7 +3,7 @@ # Pin deployments to an immutable OpenClockwork release. Do not use `latest` # for production upgrades. -OPENCLOCKWORK_VERSION=2.0.0 +OPENCLOCKWORK_VERSION=2.0.1 # Keep these names unchanged across upgrades. OPENCLOCKWORK_DB_VOLUME=openclockwork-db-data-prod OPENCLOCKWORK_ATTACHMENTS_VOLUME=openclockwork-attachments-prod diff --git a/FEATURES.md b/FEATURES.md index a9ee47f..6cb3c37 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -1,6 +1,6 @@ # OpenClockwork Features -OpenClockwork 2.0.0 provides **Solo** personal work tracking and **Team** time and +OpenClockwork 2.0.1 provides **Solo** personal work tracking and **Team** time and attendance in one responsive, self-hosted application. Both keep deployment, data, and configuration under the operator's control, with German and English UI. diff --git a/README.md b/README.md index 703fd73..18cdf3b 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ country. No proprietary time-clock hardware or hosted subscription is required. **Existing installations remain in Team mode after an upgrade.** A mode change is a separate, authenticated administrator action with a preview and safety checks. Invoice creation, monetary billing, and CAUR coding-agent usage import -are not included in 2.0.0; see the [roadmap](ROADMAP.md). +are not included in 2.0.1; see the [roadmap](ROADMAP.md). ## Choose your mode @@ -310,7 +310,7 @@ repository and enter its directory: ```bash git clone https://github.com/patrickschiller/openclockwork.git cd openclockwork -git switch --detach v2.0.0 +git switch --detach v2.0.1 cp .env.prod.example .env.prod ``` @@ -341,7 +341,7 @@ openssl rand -hex 32 Open `.env.prod` in an editor and replace every `change-me` value: -- Set `OPENCLOCKWORK_VERSION=2.0.0` for this release. Use the same explicit +- Set `OPENCLOCKWORK_VERSION=2.0.1` for this release. Use the same explicit version for the API and web images; never deploy `latest`. - Put the first command's output into `POSTGRES_PASSWORD` and replace `change-me-database-password` inside `DATABASE_URL` with that exact same diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a616f4f..e75aaf1 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,53 @@ +# OpenClockwork v2.0.1 + +## Security fix + +- Fixes read authorization in Team mode for personnel records, time accounts, vacation + balances, leave allowances, absences and working-time violations in + [PR #34](https://github.com/patrickschiller/openclockwork/pull/34), following a + finding from Codex Security Cloud. Employee lists and individual personnel + records now follow the authenticated actor's permitted scope. The related + account, vacation-balance, leave-allowance, absence and violation reads require + authentication and enforce access to the actor's own data, their direct reports + or the HR administrator's permitted scope. Absence lists without an employee + filter are scoped as well; an explicit unauthorized employee filter is rejected. +- Keeps substitute selection and project assignment working through an + authenticated employee directory containing only IDs, first names and last + names. These selectors no longer require the full personnel-record list. +- Updating existing installations to 2.0.1 is recommended. See the + [security advisory](https://github.com/patrickschiller/openclockwork/security/advisories/GHSA-4f2x-4pf8-wwx6) + for affected endpoints and mitigation. + +## Upgrade and compatibility + +- There are no new database migrations when upgrading from 2.0.0. Keep the + existing database, attachment volumes, identities, configuration and working + timezone. Do not seed or reset an existing installation for this update. + When upgrading from an older release, also follow its intervening migration + and upgrade requirements. +- Read the [upgrade guide](https://github.com/patrickschiller/openclockwork/blob/v2.0.1/UPGRADING.md) + and take a consistent backup before updating. Deploy matching API and web + images. If deploying them separately, deploy the API first and wait for + `/api/health` to report `2.0.1`, then deploy the web image. Reopen existing PWA + or browser tabs if they continue using a cached bundle. +- Custom API clients must handle `401` and `403` responses and must not assume + `GET /api/employees` exposes every employee's personnel record. Use + `GET /api/employees/directory` for names and IDs needed by substitute and + project-assignment selectors. Keep personnel, account, vacation-balance, + `GET /api/employees/:employeeId/leave-allowances`, `GET /api/absences` and + `GET /api/violations` reads authenticated and within the actor's permitted + scope. Consult the + [OpenAPI contract](https://github.com/patrickschiller/openclockwork/blob/v2.0.1/apps/api/openapi.json) + for the updated directory response. + +## Docker images + +- `ghcr.io/patrickschiller/openclockwork-api:2.0.1` +- `ghcr.io/patrickschiller/openclockwork-web:2.0.1` + +The release workflow also updates each image's `latest` tag. Pin `2.0.1` or a +verified digest for production and use the same release for both images. + # OpenClockwork v2.0.0 OpenClockwork 2.0 introduces two explicit ways to run the same application: diff --git a/RELEASING.md b/RELEASING.md index bc5d0cf..fbf44b2 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -33,8 +33,8 @@ annotated tag on the exact merge commit and push it: ```bash git switch main git pull --ff-only -git tag -a v2.0.0 -m "OpenClockwork v2.0.0" -git push origin v2.0.0 +git tag -a v2.0.1 -m "OpenClockwork v2.0.1" +git push origin v2.0.1 ``` The release workflow verifies the tag and notes, runs Nx and API end-to-end @@ -50,8 +50,8 @@ pulled anonymously by self-hosted installations. ## Verify the published release ```bash -docker pull ghcr.io/patrickschiller/openclockwork-api:2.0.0 -docker pull ghcr.io/patrickschiller/openclockwork-web:2.0.0 +docker pull ghcr.io/patrickschiller/openclockwork-api:2.0.1 +docker pull ghcr.io/patrickschiller/openclockwork-web:2.0.1 ``` Confirm that the GitHub Release is marked latest, contains the curated upgrade diff --git a/UPGRADING.md b/UPGRADING.md index 7506f8f..20716af 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -25,6 +25,28 @@ Compose from managing their deletion, but this does not protect against manual volume removal, pruning unused volumes, Docker data loss or host failure. Do not replace a populated installation's volume with a new name during an upgrade. +## Required for 2.0.1 + +Version 2.0.1 fixes read access in Team mode to personnel records, time accounts, vacation +balances, leave allowances, absences and working-time violations. Updating +existing installations is recommended. From 2.0.0, +this update adds no database migrations and requires no seed or reset. +Keep the existing data, volumes, configuration and working timezone, take a +consistent backup, and deploy matching 2.0.1 API/web images as described below. + +Custom API clients must handle `401` and `403` responses and the scoped +`GET /api/employees` list. Use the authenticated `GET /api/employees/directory` +names/IDs response for substitute and project-assignment selectors instead +of reading full personnel records. Personnel, account, vacation-balance, +`GET /api/employees/:employeeId/leave-allowances`, `GET /api/absences` and +`GET /api/violations` reads require authentication and remain within the +actor's own data, direct reports or HR administrator scope. Unfiltered absence +lists are scoped too; explicit unauthorized employee filters are rejected. +See the updated [OpenAPI contract](apps/api/openapi.json). + +When upgrading from a version older than 2.0.0, also follow the 2.0.0 +requirements below and the release notes for every skipped version. + ## Required for 2.0.0 ### Existing 1.4.0 installations @@ -313,7 +335,7 @@ runs in a non-production runtime; the API retains its production runtime. ## 2. Select and pull the release Set `OPENCLOCKWORK_VERSION` in `.env.prod` to the exact version from the GitHub -Release, **`2.0.0` for this upgrade**, only after preserving the old configuration +Release, **`2.0.1` for this upgrade**, only after preserving the old configuration in the backup set. Pin matching API/web versions or verified digests. Do not use `latest`, a mutable `:local` image, or a source-build override for an unattended production upgrade. Keep the same PostgreSQL major version; a PostgreSQL major @@ -335,7 +357,7 @@ The API waits for PostgreSQL and runs `prisma migrate deploy` before starting. Prisma records applied migrations in `_prisma_migrations` and skips them on subsequent starts. Production startup never seeds or resets the database. If API/web are deployed independently, deploy the API first, wait for its -health endpoint to report `2.0.0`, then deploy the matching web image. The web +health endpoint to report `2.0.1`, then deploy the matching web image. The web startup version check is not a promise of zero-downtime mixed-version operation; keep additional writers paused until verification completes. @@ -364,7 +386,7 @@ oc exec -T api ./node_modules/.bin/prisma migrate status oc exec -T api wget -qO- http://127.0.0.1:3000/api/health ``` -Confirm `2.0.0` through the public web/proxy health route as well as the +Confirm `2.0.1` through the public web/proxy health route as well as the container check. Sign in and verify the actual deployed mode, a known employee, an existing time entry, historic break totals, leave balances and configured attachment storage. A 1.4.0 upgrade must still be Team unless an administrator diff --git a/apps/api/openapi.json b/apps/api/openapi.json index 1658dc8..37bcbc7 100644 --- a/apps/api/openapi.json +++ b/apps/api/openapi.json @@ -3869,7 +3869,7 @@ "info": { "title": "OpenClockwork API", "description": "Self-hostable working-time tracker — REST + WebSocket surface.", - "version": "2.0.0", + "version": "2.0.1", "contact": {} }, "tags": [], @@ -4690,7 +4690,7 @@ }, "version": { "type": "string", - "example": "2.0.0" + "example": "2.0.1" }, "utcTimestamp": { "type": "string", diff --git a/apps/api/src/app/health/health.controller.ts b/apps/api/src/app/health/health.controller.ts index 3af22ac..a2a0fde 100644 --- a/apps/api/src/app/health/health.controller.ts +++ b/apps/api/src/app/health/health.controller.ts @@ -9,7 +9,7 @@ export class HealthResponseDto { @ApiProperty({ example: 'openclockwork-api' }) service!: string; - @ApiProperty({ example: '2.0.0' }) + @ApiProperty({ example: '2.0.1' }) version!: string; @ApiProperty({ format: 'date-time' }) diff --git a/apps/api/src/generate-openapi.ts b/apps/api/src/generate-openapi.ts index 59a9007..1410b80 100644 --- a/apps/api/src/generate-openapi.ts +++ b/apps/api/src/generate-openapi.ts @@ -33,7 +33,7 @@ async function main() { .setDescription( 'Self-hostable working-time tracker — REST + WebSocket surface.', ) - .setVersion('2.0.0') + .setVersion('2.0.1') .addBearerAuth() .build(); const document = SwaggerModule.createDocument(app, config); diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index ee73829..059f3ba 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -38,7 +38,7 @@ async function bootstrap() { .setDescription( 'Self-hostable working-time tracker — REST + WebSocket surface.', ) - .setVersion('2.0.0') + .setVersion('2.0.1') .addBearerAuth() .build(); const document = SwaggerModule.createDocument(app, swaggerConfig); diff --git a/apps/web/src/api/generated.ts b/apps/web/src/api/generated.ts index ea7a5e3..b56a80e 100644 --- a/apps/web/src/api/generated.ts +++ b/apps/web/src/api/generated.ts @@ -1710,7 +1710,7 @@ export interface components { status: string; /** @example openclockwork-api */ service: string; - /** @example 2.0.0 */ + /** @example 2.0.1 */ version: string; /** Format: date-time */ utcTimestamp: string; diff --git a/docs/SOLO_MODE.md b/docs/SOLO_MODE.md index 26c584f..cee58d7 100644 --- a/docs/SOLO_MODE.md +++ b/docs/SOLO_MODE.md @@ -1,6 +1,6 @@ # Solo mode -Solo mode in OpenClockwork 2.0.0 is for one person managing their own work: +Solo mode in OpenClockwork 2.0.1 is for one person managing their own work: freelancers, independent consultants, and owner-operated businesses. It provides time capture, customers, projects, service orders, personal calendar entries, and timesheets without manager approvals or a fictional HR department. @@ -31,11 +31,11 @@ are **not implemented** in this release. See the [roadmap](../ROADMAP.md). Use the [production installation guide](../README.md#production-installation-step-by-step) for host requirements, independent secrets, TLS, persistent volumes, and backups. -For 2.0.0, check out the `v2.0.0` tag and set the following in your private +For 2.0.1, check out the `v2.0.1` tag and set the following in your private `.env.prod`: ```dotenv -OPENCLOCKWORK_VERSION=2.0.0 +OPENCLOCKWORK_VERSION=2.0.1 TZ=UTC ``` diff --git a/docs/TEAM_MODE.md b/docs/TEAM_MODE.md index 90e87af..7ec538a 100644 --- a/docs/TEAM_MODE.md +++ b/docs/TEAM_MODE.md @@ -13,8 +13,8 @@ employee, manager, kiosk, or approval setup has to be replaced by Solo. Choose ## Install and bootstrap Follow the [production installation guide](../README.md#production-installation-step-by-step). -For this release, use the `v2.0.0` source tag and set -`OPENCLOCKWORK_VERSION=2.0.0` in the private `.env.prod` file. Configure all +For this release, use the `v2.0.1` source tag and set +`OPENCLOCKWORK_VERSION=2.0.1` in the private `.env.prod` file. Configure all required independent secrets, browser origins, the installation's IANA working timezone (`TZ`), stable volume names, and TLS before using real personal data. @@ -82,7 +82,7 @@ switch succeeds. 3. **Create employees and reporting relationships.** Enter start dates, weekly hours, roles, managers, holiday calendars, and actual leave entitlements. Employee creation is administrator-managed; email invitation/onboarding is - not part of 2.0.0. + not part of 2.0.1. 4. **Review accounts.** Configure opening time balances, annual leave, carry-over, expiry, and reasoned adjustments as applicable. Check calculations against representative contractual cases before operational use. diff --git a/package.json b/package.json index 93808fb..f8cb2fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openclockwork", - "version": "2.0.0", + "version": "2.0.1", "license": "Apache-2.0", "private": true, "description": "OpenClockwork — self-hosted time and attendance with configurable work rules for organisations worldwide",