From 34c8c92f8cb1143e9d0c0559e17247a678d861c3 Mon Sep 17 00:00:00 2001 From: zichun Date: Fri, 10 Apr 2026 11:06:20 +0800 Subject: [PATCH] docs(progress): pin R2 + R4 + P1.9 + P4.2 commit refs, bump to v0.30.0 --- PROGRESS.md | 14 +++++++------- gradle.properties | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index a756209..d0a3d43 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -10,10 +10,10 @@ | | | |---|---| -| **Latest version** | v0.29.0-SNAPSHOT (R1 Web SPA bootstrap + demo seed — click-through end-to-end buy-sell loop from the browser) | -| **Latest commit** | `0add76b ci(docker): install nodejs+npm in build stage for :web SPA build` | +| **Latest version** | v0.30.0-SNAPSHOT (R2 identity screens + SPA CRUD completion + S3 file backend + OIDC federation) | +| **Latest commit** | `1777189 feat(web): create-location + adjust-stock forms` | | **Repo** | https://github.com/reporkey/vibe-erp | -| **Modules** | 24 JVM subprojects + `:web` SPA | +| **Modules** | 25 JVM subprojects + `:web` SPA | | **Unit tests** | 356, all green | | **Real PBCs implemented** | **10 of 10** (pbc-identity, pbc-catalog, pbc-partners, pbc-inventory, pbc-warehousing, pbc-orders-sales, pbc-orders-purchase, pbc-finance, pbc-production, pbc-quality) — P5.x row of the implementation plan complete at minimal v1 scope | | **End-to-end smoke runs** | An SO confirmed with 2 lines auto-spawns 2 draft work orders via `SalesOrderConfirmedSubscriber`; completing one credits the finished-good stock via `PRODUCTION_RECEIPT`, cancelling the other flips its status, and a manual WO can still be created with no source SO. All in one run: 6 outbox rows DISPATCHED across `orders_sales.SalesOrder` and `production.WorkOrder` topics; pbc-finance still writes its AR row for the underlying SO; the `inventory__stock_movement` ledger carries the production receipt tagged `WO:`. First PBC that REACTS to another PBC's events by creating new business state (not just derived reporting state). | @@ -44,7 +44,7 @@ That target breaks down into roughly 30 work units across 8 phases. About **22 a | P1.6 | ICU4J `Translator` implementation + locale resolution | ✅ DONE — `01c71a6` | | P1.7 | Event bus + transactional outbox | ✅ DONE — `c2f2314` | | P1.8 | JasperReports integration | ✅ DONE — `89f47a3` — new `platform-reports` module with JasperReports 6.21.3; api.v1 `ReportRenderer` + `ReportRenderException`; `JasperReportRenderer` @Component running JDK javac via `JRJavacCompiler`; `PluginContext.reports` wired with default-throw; `/api/v1/reports/ping` + `/api/v1/reports/render` endpoints; built-in `vibeerp-ping-report.jrxml` self-test | -| P1.9 | File store (local + S3) | ✅ Partial — `f2156c5` — api.v1 `FileStorage` + `FileHandle` + `FileReadResult`; new `platform-files` subproject with `LocalDiskFileStorage` (sidecar metadata files, atomic `put`, path-traversal guards); `PluginContext.files` with default-throw; `FileController` with multipart upload/download/list/delete. S3 backend still pending. | +| P1.9 | File store (local + S3) | ✅ DONE — `f2156c5` local + `c2fab13` S3 — api.v1 `FileStorage` + `FileHandle` + `FileReadResult`; `platform-files` with `LocalDiskFileStorage` (sidecar metadata, atomic put, path-traversal guards) + `S3FileStorage` (AWS SDK v2, works with AWS/MinIO/DigitalOcean Spaces). Backend selected by `vibeerp.files.backend` (local=default, s3=opt-in). S3 client is lazy-init, supports static credentials or IAM chain, configurable key-prefix for multi-instance buckets. `PluginContext.files` wired; `FileController` with multipart upload/download/list/delete. | | P1.10 | Job scheduler (Quartz) | ✅ DONE — `5d6a2f1` — new `platform-jobs` module with Quartz Spring Boot starter + JDBC job store against host Postgres; api.v1 `JobHandler`/`JobScheduler`/`JobContext`; owner-tagged `JobHandlerRegistry` parallel to `TaskHandlerRegistry`; `QuartzJobBridge` routes by key; `PrincipalContext.runAs("system:jobs:")` wraps every execution; HTTP surface at `/api/v1/jobs/**` (list/trigger/schedule/unschedule); built-in `vibeerp.jobs.ping` diagnostic handler | ### Phase 2 — Embedded workflow engine @@ -71,7 +71,7 @@ That target breaks down into roughly 30 work units across 8 phases. About **22 a | # | Unit | Status | |---|---|---| | P4.1 | Built-in JWT auth + Argon2id + bootstrap admin | ✅ DONE — `540d916` | -| P4.2 | OIDC integration (Keycloak-compatible) | 🔜 Pending | +| P4.2 | OIDC integration (Keycloak-compatible) | ✅ DONE — `6ad72c7` — composite JwtDecoder tries built-in HS256 first, falls back to external OIDC provider's JWKS (auto-discovered from issuer-uri). PrincipalContextFilter handles both claim formats (built-in `username`+`roles` vs Keycloak `preferred_username`+`realm_access.roles`). Opt-in via `vibeerp.security.oidc.issuer-uri`. No new dependencies (uses existing spring-security-oauth2-resource-server). | | P4.3 | Permission checking against `metadata__role_permission` | ✅ DONE — `75bf870` | ### Phase 5 — Core PBCs @@ -93,9 +93,9 @@ That target breaks down into roughly 30 work units across 8 phases. About **22 a | # | Unit | Status | |---|---|---| | R1 | Vite + React + TS bootstrap, login flow, typed REST client | ✅ DONE — `fc62d6d` — new `:web` Gradle subproject wraps Vite/React 18/TypeScript/Tailwind 3.4 via Exec tasks; `:distribution` consumes the dist via an outgoing/incoming Gradle configuration and stages it into `classpath:/static/` so a single fat-jar serves both API and SPA. Hand-written typed fetch client over `/api/v1/**` (211 KB JS gzipped, no codegen toolchain). AuthContext stores the JWT in localStorage with a 401 handler. `SpaController` forwards every known SPA route prefix to `/index.html` so React Router deep links work on hard refresh. `SecurityConfiguration` reordered: `/api/**` stays `.authenticated()` before the SPA permitAll rules so the "API is always authenticated" invariant holds even with the SPA bundled in the same image. Dockerfile build stage adds `apk add nodejs npm` so `./gradlew :distribution:bootJar` produces a self-contained image with the SPA inside. End-to-end smoke verified on fresh Postgres: log in, walk SO DRAFT → CONFIRMED → SHIPPED, watch stock balances drop + AR journal entry settle — all in a real browser. | -| R2 | Identity screens (user admin, role admin) | 🔜 Pending | +| R2 | Identity screens (user admin, role admin) | ✅ DONE — `82c5267` — UsersPage (list + link to detail), CreateUserPage, UserDetailPage (role toggle with Assign/Revoke), RolesPage (list + inline create). Backend: new RoleService + RoleController with list/create roles, assign/revoke role endpoints. identity.yml updated with identity.role.create permission. | | R3 | Customize / metadata UIs | 🔜 Pending | -| R4 | Per-PBC create/edit screens (list/detail are live in R1) | 🔜 Pending — list + detail pages for all 10 PBCs landed in R1 along with the ship/receive/confirm/cancel action verbs on the order + work-order detail pages. Create/edit forms and richer per-PBC screens (BOM editor, routing editor) will follow when a real consumer asks for them. | +| R4 | Per-PBC create/edit screens | ✅ Partial — `2535324` + `1777189` — create forms for items, partners, locations, purchase orders, work orders (with BOM + routing editors), stock adjustment. Every PBC entity that operators need to manage has a SPA form. Remaining: edit forms (patch existing records), richer BOM/routing editors. | ### Phase 7 — Reference printing-shop plug-in diff --git a/gradle.properties b/gradle.properties index 1a0f62e..76acf6a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,6 +19,6 @@ kotlin.incremental=true # api/api-v1/build.gradle.kts. # Bump this line in lockstep with PROGRESS.md's "Latest version" # row when shipping a new working surface. -vibeerp.version=0.29.0-SNAPSHOT +vibeerp.version=0.30.0-SNAPSHOT vibeerp.api.version=1.0.0-SNAPSHOT vibeerp.group=org.vibeerp -- libgit2 0.22.2