Skip to content

fix: value resolver 403, CamundaTask modify action, and register the freemarker plugins (v12) - #906

Open
Klaas-Ritense wants to merge 4 commits into
rc/12.43.0from
bugfix/v12-plugin-di-and-config-fixes
Open

fix: value resolver 403, CamundaTask modify action, and register the freemarker plugins (v12)#906
Klaas-Ritense wants to merge 4 commits into
rc/12.43.0from
bugfix/v12-plugin-di-and-config-fixes

Conversation

@Klaas-Ritense

@Klaas-Ritense Klaas-Ritense commented Aug 13, 2026

Copy link
Copy Markdown
Member

Ports the applicable fixes from #903 to v12 on top of rc/12.43.0, and fixes the reason no v12 image could show the
freemarker plugin screens at all. What from #903 does not apply here is listed at the bottom.

Value resolver management endpoints returned 403 for administrators

GET /api/management/v1/value-resolver and the document-definition key endpoints returned 403 for a ROLE_ADMIN
token, leaving the Value resolver input mode without options. The key endpoints resolve through
JsonSchemaDocumentDefinitionService.findLatestByName / findByNameAndVersion, which require the VIEW permission on
JsonSchemaDocumentDefinition, so entity-level authorization applied on top of the administrator check that already
guards all five endpoints in ValueResolverHttpSecurityConfigurer. They are now annotated @RunWithoutAuthorization.
Access remains restricted to administrators.

:backend:authorization is declared compileOnly rather than implementation. Only the annotation symbol is
needed here; the aspect that acts on it lives in the authorization module, core already exposes that module to every
app as an api dependency, and a @Retention(RUNTIME) annotation whose class is absent is simply skipped by the JVM.
An implementation dependency would instead put AuthorizationAutoConfiguration on the runtime classpath of every
value-resolver consumer — it needs a UserManagementService, a ChangelogService and the authorization tables, none of
which the module's own integration test context provides (liquibase.enabled: false, ddl-auto: none), so the context
fails to load. That is the DefaultCacheAwareContextLoaderDelegate failure ValueResolverResourceIT hit on #903; the
same one-word change fixes it there.

modify action for CamundaTask

CamundaTaskService.setDueDate and removeDueDate both call requirePermission(task, MODIFY), but
CamundaTaskActionProvider did not list MODIFY, so the action was not discoverable through
AuthorizationService.getAvailableActionsForResource when granting permissions on the CamundaTask resource type.

No released v12 frontend registered the external plugins

The hook for them existed only in apps/valtimo (app-plugins.ts / app-plugins.prod.ts) and angular.json had no
app-plugins.ts -> app-plugins.prod.ts fileReplacement for any app, so every build compiled the empty stub and the
@valtimo-plugins/* packages CI installed from release-plugins.json were never imported by anything. Meanwhile the
backend freemarker plugin ships in the dev, gzac and evenementenvergunning apps but not in valtimo — the one app
carrying the frontend hook had no backend counterpart.

The gzac app now imports the plugin modules and specifications directly: SmtpMailPluginModule,
MailTemplatePluginModule, TextTemplatePluginModule and DocumentGeneratorPluginModule. The packages are plain
package.json dependencies, pinned there instead of in release-plugins.json.

No app-plugins split is needed on this branch. That indirection exists on next-minor because its package.json
declares @valtimo/* as npm workspaces pointing at uncompiled projects/valtimo/* source, which breaks Vite's
pre-bundling of the plugin packages' transitive @valtimo/* imports — hence keeping them out of package.json and
swapping the module list at build time. v12 has no workspaces at all: all 37 @valtimo/* are already declared as
file:dist/valtimo/*, so node resolution lands on the compiled libraries locally exactly as it does in CI, and the
builder is webpack rather than esbuild/Vite. node_modules/@valtimo/plugin is a symlink to ../../dist/valtimo/plugin
either way.

Consequently release-plugins.json and the workflow step that applied its pins are removed, as are the now-unused
apps/valtimo stubs. Dropping the stub from apps/valtimo/app.module.ts changes nothing there: it spread two empty
arrays.

Freemarker plugin -> 8.5.3-V12

Latest v12 release, for the backend artifact (com.ritense.valtimoplugins:freemarker, gradle.properties) and the
frontend packages (now frontend/package.json).

Not ported from #903

  • tsconfig.app.prod.json + angular.json production tsConfig. The duplicate-library DI defect does not exist on
    v12, for the same reason the app-plugins split is unnecessary: both resolution routes land on dist/valtimo/*.
    Confirmed on a v12 gzac-frontend built from this branch — the bundle contains the plugin config InjectionToken
    exactly once.
  • The Stamp frontend version change in frontend_build_push_docker_image.yml. Not needed on v12. The step only
    patches projects/valtimo's versions.ts, which this branch's app does not bundle — but the libraries workflow
    already stamps versions.ts and rebuilds @valtimo/config before uploading the dist artifact this job consumes, and
    skips its content-keyed lib cache whenever an explicit project_version is given. ritense/gzac-frontend:12.42.0
    does report 12.42.0. The stamp step is a harmless no-op here, so its logic is left untouched.
  • BuildingBlockValueResolverResource. No building-block module on v12.
  • Moving the evenementenvergunning permissions and roles to the global importer. v12 has no
    GlobalPermissionImporter / GlobalRoleImporter and no config/global support. Adding the CamundaTask modify
    grant under a bumped changeset was considered and rejected: the app does not set
    valtimo.changelog.pbac.clear-tables, and PermissionDeployer.deploy only calls saveAll with freshly built
    entities, so a new changeset would duplicate all 41 existing rows. The file is untouched, which also means v12 keeps
    the non-reconciling behaviour — a permission removed from the file stays active.

Verification

Backend:

  • ./gradlew :backend:value-resolver:integrationTestingPostgresql — green, including all nine ValueResolverResourceIT
    tests, which is what confirms the compileOnly choice.
  • ./gradlew :backend:value-resolver:test :backend:core:test :backend:exact-plugin:test — green (exact-plugin is the
    only module depending on value-resolver).
  • ./gradlew :backend:apps:gzac:bootJar — green, and :backend:authorization still resolves on the runtimeClasspath
    of all four apps through core's api dependency.

Frontend:

  • npm run build:gzac and npm run build:valtimo — both succeed. npx ng build gzac without the production
    configuration also succeeds, which is the case the app-plugins split was meant to protect.
  • Bundles: gzac carries the freemarker and smtpmail code and the plugin config token exactly once; the valtimo bundle
    contains neither, unchanged from before.

Against a running stack — released ritense/gzac-backend:12.42.0 and a gzac image built from this branch, side by
side on the same database, with the gzac app's own roles (it ships no permission file, so ROLE_ADMIN holds no entity
permissions):

call 12.42.0 this PR
GET /api/management/v1/value-resolver 200 200
POST /api/management/v1/value-resolver/document-definition/mail-test/keys 403 200
POST /api/management/v2/value-resolver/document-definition/mail-test/keys 403 200

The GET never returned 403 on v12 — it resolves no entity — so the annotation there is preventive rather than a fix.

End-to-end through the UI of the gzac-frontend image built from this branch: the plugin picker offers all 17 plugins
including Document generator, Mail sjablonen, Text sjablonen and SMTP Mail; a Mail sjablonen plugin
configuration and a plugin process link on the Genereer Mailinhoud action were created without a single console error
(no NullInjectorError on either the plugin configuration or the action configuration step); every request returned 200,
including the POST /api/management/v2/value-resolver/document-definition/mail-test/keys that the Value-resolver veld
input mode issues. Running the process rendered the mail into the mailContent process variable:

<p>Beste Klaas Schuijtemaker,</p>
<p>Uw aanvraag is ontvangen. Deze mail is gegenereerd met Freemarker.</p>

Known, pre-existing

The published -V12 plugin packages declare @angular/core: ^19.2.8 peers while this branch is on 17.3.12 — true for
8.5.1-V12 as well. frontend/.npmrc sets legacy-peer-deps=true, so installs are unaffected and both apps build, but
the peer range is wrong in the plugin repo.

GET /api/management/v1/value-resolver and the document-definition key
endpoints returned 403 for a ROLE_ADMIN token, leaving the *Value
resolver* input mode without options. The key endpoints resolve through
JsonSchemaDocumentDefinitionService.findLatestByName /
findByNameAndVersion, which require the VIEW permission on
JsonSchemaDocumentDefinition, so entity-level authorization applied on
top of the administrator check that already guards all five endpoints in
ValueResolverHttpSecurityConfigurer. They are now annotated with
@RunWithoutAuthorization. Access remains restricted to administrators.

The authorization module is declared compileOnly rather than
implementation: only the annotation symbol is needed here, the aspect
that acts on it lives in :backend:authorization and is present in every
application, and an annotation whose class is absent at runtime is
skipped by the JVM. An implementation dependency would put
AuthorizationAutoConfiguration on the runtime classpath of every
value-resolver consumer — it needs a UserManagementService, a
ChangelogService and the authorization tables, none of which the
module's own integration test context provides, so the context would
fail to load.

Verified with ./gradlew :backend:value-resolver:integrationTestingPostgresql
— green, including all nine ValueResolverResourceIT tests.
CamundaTaskService.setDueDate and removeDueDate both call
requirePermission(task, MODIFY), but CamundaTaskActionProvider did not
list MODIFY among its available actions, so the action was not
discoverable through AuthorizationService.getAvailableActionsForResource
when granting permissions on the CamundaTask resource type.
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e29a3c6a-228e-478f-9d4d-6a59b1627e41

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Klaas-Ritense
Klaas-Ritense force-pushed the bugfix/v12-plugin-di-and-config-fixes branch from f5f14ee to 79cdbfc Compare August 13, 2026 13:08
Picks up the latest v12 release of the plugin, for both the backend
artifact (com.ritense.valtimoplugins:freemarker) and the frontend
package (@valtimo-plugins/freemarker) that release builds pin.
@Klaas-Ritense
Klaas-Ritense force-pushed the bugfix/v12-plugin-di-and-config-fixes branch from 79cdbfc to 1b8df3c Compare August 13, 2026 13:46
@Klaas-Ritense Klaas-Ritense changed the title fix: value resolver 403, CamundaTask modify action, frontend version stamp (v12 port of #903) fix: value resolver 403 and CamundaTask modify action (v12 port of #903) Aug 13, 2026
No released v12 frontend registered the external plugins. The hook for
them existed only in apps/valtimo (app-plugins.ts / app-plugins.prod.ts)
and angular.json had no app-plugins.ts -> app-plugins.prod.ts
fileReplacement for any app, so every build compiled the empty stub and
the @valtimo-plugins/* packages CI installed from release-plugins.json
were never imported by anything. Meanwhile the backend freemarker plugin
ships in the dev, gzac and evenementenvergunning apps but not in valtimo,
so the one app carrying the frontend hook had no backend counterpart.

The gzac app now imports the plugin modules and specifications directly:
SmtpMailPluginModule, MailTemplatePluginModule, TextTemplatePluginModule
and DocumentGeneratorPluginModule. The packages are plain package.json
dependencies, pinned there instead of in release-plugins.json.

No app-plugins split is needed on this branch. That indirection exists on
next-minor because its package.json declares @valtimo/* as npm workspaces
pointing at uncompiled projects/valtimo/* source, which breaks Vite's
pre-bundling of the plugin packages' transitive @valtimo/* imports — hence
keeping them out of package.json and swapping the module list at build
time. v12 has no workspaces at all: all 37 @valtimo/* are already declared
as file:dist/valtimo/*, so node resolution lands on the compiled libraries
locally exactly as it does in CI, and the builder is webpack rather than
esbuild/Vite. node_modules/@valtimo/plugin is a symlink to
../../dist/valtimo/plugin either way.

Consequently release-plugins.json and the workflow step that applied its
pins are removed, as are the now-unused apps/valtimo stubs. Dropping the
stub from apps/valtimo/app.module.ts changes nothing there: it spread two
empty arrays.

Verified: `npm run build:gzac` and `npm run build:valtimo` both succeed,
and `npx ng build gzac` without the production configuration succeeds too
— the case the split was meant to protect. The gzac bundle contains the
plugin config InjectionToken exactly once and carries the freemarker and
smtpmail code; the valtimo bundle contains neither, as before. Against a
running stack the plugin picker offers all 17 plugins, including Document
generator, Mail sjablonen, Text sjablonen and SMTP Mail, and a process
link on the Genereer Mailinhoud action rendered a mail into a process
variable.
@Klaas-Ritense Klaas-Ritense changed the title fix: value resolver 403 and CamundaTask modify action (v12 port of #903) fix: value resolver 403, CamundaTask modify action, and register the freemarker plugins (v12) Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant