dotCMS / dotCMS/core

Add 'VTL Viewtool Contract Change' rollback category (H-8, HIGH) to ROLLBACK_UNSAFE_CATEGORIES.md

Open Beginner friendly
#36,117 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

QA : Not Needed Release : 26.06.11-01 stale Team : Scout Type : Documentation
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Description

docs/core/ROLLBACK_UNSAFE_CATEGORIES.md is the canonical reference that the automatic PR rollback-safety check (.github/workflows/ai_claude-rollback-safety.yml) reads at runtime (cat docs/core/ROLLBACK_UNSAFE_CATEGORIES.md, prompt STEP 1, line 98) to classify every PR as AI: Safe To Rollback / AI: Not Safe To Rollback.

The document currently has no category covering changes to the contract of a VTL Viewtool (Velocity ViewTool methods exposed to templates via toolbox.xml, e.g. $estool, $dotcontent). This is a genuine blind spot in the reference, surfaced while reviewing an ES→OS migration change.

Motivating example

As part of the ES→OpenSearch migration, ESContentTool.raw(String) (the $estool.raw() viewtool) changed its return type:

// before
public SearchResponse raw(String esQuery) { ... }            // org.elasticsearch type
// after
public ContentSearchResponse raw(final String esQuery) { ... } // vendor-neutral DTO

SearchResponse and ContentSearchResponse expose different accessors (e.g. the new record exposes aggregationTree() / aggregations()). Customer VTL templates migrated to the new accessors are a persistent artifact stored outside the application binary (in the DB / theme filesystem). If the binary is rolled back to N-1 without reverting those templates, N-1's raw() returns the old SearchResponse, the template calls a method that no longer exists, and Velocity fails at render time — i.e. N-1 cannot "serve requests correctly."

Why it belongs in this document

The document's scope is not limited to DB/index state. The rule of thumb (line 5) includes "serve requests correctly", and M-3 explicitly states "This risk exists entirely outside the DB layer". The unifying principle is:

A change is rollback-unsafe if it leaves a persistent artifact outside the application binary — DB, index, file, queued bundle, deployed client (M-3), compiled OSGi plugin (M-4) — that survives a rollback and breaks N-1.

A VTL template is structurally identical to an OSGi plugin in this model: an external consumer written against the binary's contract that survives a rollback.

VTL template : viewtool method   ≡   OSGi plugin : exported interface

Since M-3 (REST/GraphQL) and M-4 (OSGi) already capture code-contract risks where the persistent artifact is a deployed consumer, VTL viewtool contracts fit the same class and belong here.

Proposed category

Add M-5 — VTL Viewtool Contract Change with a scaled severity (precedent: H-7 already uses "escalates to MEDIUM/HIGH if…"):

Condition Risk
Viewtool method used in scope-limited templates (specific page/detail type) 🟡 MEDIUM (base) — few pages affected; recovery = edit that template
Viewtool method invoked from shared/global templates (layouts, headers, footers, widely-reused containers) 🟠 HIGH — one change breaks many pages at once; matches "core features broken for affected users"

Rationale for not flat-HIGH or CRITICAL: no data loss, N-1 starts normally, recovery is a content/template edit (no backup/reindex). Flat-HIGH would also rank it above M-4 (OSGi, which can destabilize the container yet is rated MEDIUM), breaking the document's internal calibration. The trigger is conditional (only breaks if templates were co-migrated to the new contract) — same conditionality the document states for M-3.

The new section must follow the existing convention: Context · Why it is unsafe · Example (the raw()ContentSearchResponse case above) · Signals to watch for in code review · Safer alternative — plus a line in the Decision Card (lines ~24–46).

Acceptance Criteria

  • A new category M-5 — VTL Viewtool Contract Change is added to docs/core/ROLLBACK_UNSAFE_CATEGORIES.md in the 🟡 MEDIUM section, following the exact structural convention of existing categories (Context, Why it is unsafe, Example, Signals to watch for in code review, Safer alternative).
  • The category documents scaled severity: 🟡 MEDIUM base, escalating to 🟠 HIGH when the viewtool method is reachable from shared/global templates (layouts, headers, footers, widely-reused containers), with the escalation worded in the style of H-7.
  • The category includes the real-world example: ESContentTool.raw(String) return type change SearchResponseContentSearchResponse and the render-time failure scenario on rollback.
  • Signals to watch for include: return-type or signature change on a class implementing ViewTool; the class is registered in toolbox.xml (or equivalent); the new return type exposes different accessor methods than the old one.
  • Safer alternative documents the additive pattern: keep the old accessors on the new return type (or keep the old method overload) for one release so co-migrated templates and rolled-back binaries both resolve — i.e. a two-phase contract change.
  • A corresponding entry is added to the Decision Card (VTL viewtool contract change? → 🟡 MEDIUM / 🟠 HIGH (M-5)).
  • The document remains internally consistent: M-5 is not ranked above M-4 (OSGi) as a flat level, and the new entry does not introduce a new GitHub label type (it reuses the existing Safe / Not Safe To Rollback labels — no change required to categorize.ts or the check-release-rollback skill).
  • No change to ai_claude-rollback-safety.yml is required (the workflow reads the doc dynamically by exact path); confirm this explicitly in the PR.

Priority

Medium

Additional Context

  • Consumer/pipeline analysis confirming how the doc is wired:
    • Dynamic read by ai_claude-rollback-safety.yml (prompt STEP 1, line 98; allowedTools restricts to that exact path, line 128) — so new categories added inside the file are picked up automatically on the next PR, with no workflow change.
    • Hardcoded labels (AI: Not Safe To Rollback, etc.) live in .github/scripts/gather-release-data/src/categorize.ts (lines 10–14) and the check-release-rollback skill — unaffected because M-5 reuses the existing labels.
  • The allowedTools allow-list (Bash(cat docs/core/ROLLBACK_UNSAFE_CATEGORIES.md)) is why a separate new .md file would NOT be picked up — it would be denied by the sandbox. Hence this change must go into the existing file.
  • Defining class of the example: dotCMS/src/main/java/com/dotcms/rendering/velocity/viewtools/ESContentTool.java; new DTO: dotCMS/src/main/java/com/dotcms/content/index/domain/ContentSearchResponse.java; viewtool registration: dotCMS/src/main/webapp/WEB-INF/toolbox.xml (estool). Related migration work: PR #36026 (VTL aggregation backward-compat).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read docs/core/ROLLBACK_UNSAFE_CATEGORIES.md, especially the Decision Card and existing H-7 and M-4 sections, then review .github/workflows/ai_claude-rollback-safety.yml to confirm the document is read dynamically. Add the M-5 section and Decision Card entry with the specified severity, ESContentTool.raw example, signals, and safer alternative; done means the existing file fully captures the acceptance criteria without workflow changes.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.