2.12 - #1417
Merged
Merged
Conversation
…ndpoint
Brand-new state-root tenants (e.g. created by MCP tenant_bootstrap) can
not be encrypted for until a key exists in eg_enc_symmetric_keys. The
existing key-generation paths don't cover this case:
- init() and rotateAll() discover tenants via MDMS search under
STATE_LEVEL_TENANT_ID — a brand-new root is not under any existing
root's tenant.tenants list, so it's missed.
- checkIfTenantExists() falls through to the same MDMS-driven generator,
so the first encrypt for a new root throws "Tenant Id not found" 500.
This endpoint lets a provisioning caller (tenant_bootstrap, ansible
deploy, manual ops) explicitly provision a key for a tenantId, the same
way init() does, but for ONE tenant on demand.
Behavior:
- POST /crypto/v1/_generatekey { "tenantId": "..." }
- Returns 200 with { tenantId, created, keyId }
- Idempotent: if tenant has an active key, returns existing keyId
with created=false (no rotation, no duplicate insert)
- Synchronized to prevent race on first-write
- Refreshes KeyStore + KeyIdGenerator caches after generation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
(cherry picked from commit f5d272b)
…s and DTO projection The localization service goes OOM when loaded with production-scale data (~49K messages) because computeMessageList() loads ALL messages for a locale+tenant regardless of the requested module, duplicating data 4-6x in memory during tenant hierarchy merging. Two optimizations: 1. Module-scoped query path (Option B): When a module parameter is present in the search request, only load messages for those modules from the database instead of loading all ~49K and filtering in-memory. Uses separate Redis cache keys that include the module name(s). This reduces loaded records from ~49K to ~5-8K for typical requests. 2. Native query DTO projection (Option C): Replace JPA entity queries with native SQL queries returning a lightweight 5-field interface projection (code, locale, module, message, tenantId). This bypasses the JPA persistence context, avoiding the overhead of loading full 10-field entities with audit fields into Hibernate's first-level cache. Together these reduce peak memory per request from ~88MB to ~8MB for module-scoped requests, making the service stable at 256MB heap. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> (cherry picked from commit 7f5a733)
…tionship search Two bugs in boundary-relationships/_search caused incorrect results: 1. Controller used @ModelAttribute for search criteria, which reads from query params/form data — not the JSON POST body. This meant tenantId, hierarchyType, and all other filter fields were always null, so the query returned ALL boundary relationships across ALL tenants globally. Fix: introduce BoundaryRelationshipSearchRequest wrapper and use @RequestBody to properly deserialize the JSON body. 2. When isSearchForRootNode=true, the query builder appended "parent IS NULL" which returned only root-level nodes. The enricher (BoundaryRelationshipEnricher) needs ALL nodes for the tenant+hierarchy to build the full tree via getSeedBoundaryList(). With only root nodes, the response always had empty children arrays. Fix: remove the parent IS NULL clause so the enricher receives the complete node set for tree assembly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> (cherry picked from commit cfe1923)
EncryptionDecryptionUtil and LocalizationUtil use a hardcoded STATE_LEVEL_TENANT_ID property, preventing multi-state deployments from using the correct encryption key or localization endpoint for non-default state roots. Add new overloaded methods that accept a tenantId parameter and use MultiStateInstanceUtil.getStateLevelTenant() to dynamically derive the state root. Original methods preserved for backward compatibility. Related to PR #1043 (egov-workflow-v2 dynamic state tenant). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> (cherry picked from commit c6f5438)
The `updateWithoutOtpValidation` and `partialUpdate` methods call `requestInfo.getUserInfo().getId()` without null-checking `getUserInfo()`. When the auth token doesn't resolve to a userInfo (e.g. cross-tenant admin operations), this throws NullPointerException. Additionally, `userRepository.update()` takes primitive `long` for userId, so passing null Long causes unboxing NPE. Use 0L as the fallback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> (cherry picked from commit ccc0e13)
…rload The previous commit on this branch added an encryptObject overload that accepts a tenantId and resolves the state root via MultiStateInstanceUtil, but no call sites were updated to use it. With the legacy 3-arg method still in place, every encrypt path silently fell back to the hardcoded STATE_LEVEL_TENANT_ID env var. So flipping STATE_LEVEL_TENANT_ID between deploys still produced key-version drift on encrypted columns and broke logins (the freshly-generated ciphertext prefix mismatches the prefix on existing DB rows; UserNotFoundException -> "Invalid login credentials"). Migrate the 6 UserService.java call sites: - encryptUserSearchCriteria (L154, L205): pass criteria.getTenantId() - createUser (L232): pass user.getTenantId() - updateWithoutOtpValidation (L367): pass user.getTenantId() - partialUpdate (L418): pass user.getTenantId() - updatePassword (L492): pass user.getTenantId() The new overload null-safe-falls-back to stateLevelTenantId, so paths that genuinely lack a request tenant retain today behavior. For single- state deployments (request tenant matches STATE_LEVEL_TENANT_ID), getStateLevelTenant strips the city suffix to the state root - output is identical to today's hardcoded path. No DB compatibility impact. Validated on bomet (ke state): /user/oauth/token, /user/citizen/_create, /user/profile/_update, /user/_search all 200 against pre-existing rows. Refs egovernments/Citizen-Complaint-Resolution-System#622 (cherry picked from commit 884c5e6)
Fixes eGovStack/core-services#1674. Root cause: the ProcessInstance API contract uses the historically misspelled JSON key "assignes" (@JsonProperty). Clients that send the correctly spelled "assignees" key (e.g. integration suites and UI paths) have that field silently dropped during deserialization, because Spring Boot's default ObjectMapper runs with FAIL_ON_UNKNOWN_PROPERTIES disabled. The transition then proceeds with assignes=null: WorkflowValidator has no assignee-presence check, EnrichmentService.enrichUsers only enriches non-empty lists, and the persister's eg_wf_assignee_v2 mapping (jsonPath ProcessInstances.*.assignes.*) extracts zero rows and skips the INSERT entirely while the eg_wf_processinstance_v2 INSERT in the same batch succeeds. Result: the process instance exists but carries no assignee rows, which surfaces as "assignees lost on ASSIGN" since /_search returns the newest (assignee-less) instance per businessId. Fix: add @JsonAlias("assignees") on the assignes field so deserialization accepts both spellings. Serialization still emits "assignes", so the persister jsonPaths, /process/_search responses and all existing consumers are unchanged. Tests: ProcessInstanceTest proves both spellings deserialize into getAssignes() (including via the full ProcessInstanceRequest transition payload) and that serialization keeps emitting "assignes". The two alias tests fail without the one-line fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit 43f925c)
Add build/maven-jdk21/ as a new Dockerfile variant alongside the existing build/maven/ (JDK 17). Services on Spring Boot 3.x are switched to the new Dockerfile; legacy services (Spring Boot 1.5/2.x) remain on JDK 17 unchanged. Why: - JDK 17 has a cgroup v2 CPU detection bug (JDK-8281181) on kernel 6.8+ — the JVM sees all host CPUs instead of the container's CPU limit, spawning 50-60 threads instead of ~15. - JDK 21 fixes this and auto-sizes heap/GC/threads from cgroup limits, eliminating the need for manual JVM tuning flags. - JDK 21 runs Java 17 bytecode natively (no recompilation needed). New files: - build/maven-jdk21/Dockerfile: eclipse-temurin:21-jre-alpine runtime with CDS (Class Data Sharing) pre-dump for faster startup - build/maven-jdk21/start.sh: no default -Xms/-Xmx, CDS loading Updated: build-config.yml - 26 Spring Boot 3.x services → build/maven-jdk21/Dockerfile - 32 legacy/other services → unchanged (build/maven/Dockerfile) - 1 service (egov-user) → unchanged (build/maven-java8/Dockerfile) Validated on docker-compose local-setup (jar-swap approach): - 12 services rebased, all healthy - k6 load test: 100% success (104 transactions, 0 failures) - Memory: ~24% RSS reduction, ~42% thread count reduction Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> (cherry picked from commit 5c861ca)
egov-user is on Spring Boot 1.5 / JDK 8 and cannot be easily migrated to Spring Boot 3.2. This new build variant compiles with JDK 8 but runs on JDK 21, getting cgroup v2 fixes and memory improvements without a framework migration. The hybrid approach: - Build stage: same JDK 8 Maven image (amazoncorretto-8) - Patch stage: injects JAXB API + runtime jars (removed from JDK 11+) - Runtime stage: eclipse-temurin:21-jre-alpine with CDS + --add-opens Measured results (8 vCPU / 16 GB VM): - Memory at idle: 461 MiB → 184 MiB (60% reduction) - Memory under 300 VU load: OOM-killed → 286 MiB (56% of limit) - Threads: 50+ → 34 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> (cherry picked from commit affb45a)
…ening egov-workflow-v2: BusinessServiceRepositoryTest was missing a @MockBean for MultiStateInstanceUtil, causing Spring to fail context initialization when trying to field-inject centralInstanceUtil into BusinessServiceRepository. egov-url-shortening: UrlSorteningApplicationTest hard-coded Jackson's internal deserialization feature bitfield (237020304) which changed to 473998480 in the jackson-databind version pulled by Spring Boot 3.4.5. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit 983e8b2)
[2.12] egov-enc-service: idempotent POST /crypto/v1/_generatekey
[2.12] egov-localization: reduce memory (module-scoped queries + DTO projection)
[2.12] boundary-service: fix tenant filtering + tree assembly in relationship search
[2.12] egov-workflow-v2: persist assignees on self-loop ASSIGN transitions
…date-npe [2.12] egov-user: prevent NPE in _updatenovalidate / profile _update
…-enc [2.12] egov-user: tenant-aware encryption + localization overloads
[2.12][strategic] JDK 21 runtime migration (shared build layer)
Rebase master
Maven jdk21
Merge pull request #1410 from egovernments/master
vinothrallapalli-eGov
requested review from
GhanshyamRawat-eGov and
talele08
as code owners
August 25, 2026 11:29
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.