TWX Code Analyzer is a local tool for the static analysis of IBM Business Process Manager / Business Automation Workflow (BAW, CP4BA) process applications exported as .twx packages. It reads the export directly (no BPM database, no server connection), runs 156 rules over services, processes, coach views, business objects, scripts, toolkits and configuration, and presents ranked findings with the full artifact path, the offending code line, remediation guidance and diagrams that show where each finding sits.
It also answers the everyday questions about an export: which toolkit artifacts does the application really use, what changed between two snapshots, where is a variable or a service referenced, and what does a business object look like once its nested types are resolved.
Everything runs on your machine with the desktop app. Nothing is uploaded anywhere.
Live demo: https://twxca.com - the web application (version 1.3) running as a public demo. Without an account each browser gets a private, temporary workspace (purged after 30 days, rule settings read-only). Create an account to keep your analyses, define quality gates and policies, accept findings, import from your Process Center or Studio, and use the API with a personal access token; you can purge your data or delete the account at any time. Do not upload exports you are not allowed to store on a third-party server.
License: Apache-2.0 (attribution required, see License). Part of the open-source BAW tooling of Dosvak.
- Parse
.twxprocess applications with their bundled toolkits (recursively). - 156 static-analysis rules in 15 categories: application structure, dependencies, services, processes (BPDs), scripts (pattern and syntax-tree based), coach views, business objects, data, naming, documentation, performance, security, configuration, migration, quality.
- Findings ranked by a weighted score, each with the artifact path (application > type > artifact > step or script), line and column, the source line, the reason it matters and how to fix it; "needs review" findings are marked separately from confirmed ones.
- Health score per snapshot and analysis history; comparison of two snapshots of the same application (added, removed, changed artifacts; new and fixed findings).
- Service and process diagrams rendered from the coordinates stored in the export, with the flagged steps highlighted and a "show in diagram" jump from every finding.
- Toolkit Usage report with evidence tiers (used, possible usage, no detected usage), duplicate snapshots merged, toolkit-to-toolkit references, exportable as HTML or PDF.
- Artifact browser: variables, steps or flow objects with lanes and assignments, scripts, coach view options and resources, business object schema with nested types (circular and unresolved types flagged), managed asset content, references both ways, raw XML.
- TWX search: text or regular expression over names, scripts, conditions, mappings, documentation and raw XML, with artifact type and toolkit filters.
- Exports: CSV, self-contained HTML and PDF reports of the findings (respecting the current filter) and of the toolkit usage.
- Rule settings: enable or disable every rule, change its severity and impact, the severity weights behind the score and the numeric thresholds of the size and complexity rules; export the settings as a JSON file and import them elsewhere (browser, command line, embedded engine).
- Analysis coverage and diagnostics: product version of the export, scripts skipped because of syntax errors, missing object files, unreadable toolkits.
- A command line for batch use (JSON output), a JSON facade to embed the engine in other Java or BAW deliveries, and a deployable web application (WAR) for a shared server: accounts or single sign-on, personal and team workspaces, central rule policies with quality gates and verdicts, accepted findings, an analysis queue, Process Center and Business Automation Studio import, notifications, dashboard, executive PDF, audit, metrics, an OpenAPI description with Swagger UI for pipelines, and a built-in help (see docs/WEB-APPLICATION.md).
The browser UI has the pages Analyze, History, Compare, Rules and Settings, and per report the tabs Findings, Overview, Objects & Diagrams, Toolkit Usage and TWX Search.
Requirements: Java 8 or newer to run (the packaged builds ship their own runtime), JDK 17 or newer to build.
# build
JAVA_HOME=/path/to/jdk17 ./build.sh # -> build/twx-code-analyzer.jar, build/twx-code-analyzer.war, build/twx-code-analyzer-jakarta.war
# local web app (listens on 127.0.0.1 only, opens the browser)
java -jar build/twx-code-analyzer.jar serve 8765 data
# command line
java -jar build/twx-code-analyzer.jar analyze MyApp.twx report.json # findings, summary, toolkit usage, coverage as JSON
java -jar build/twx-code-analyzer.jar analyze MyApp.twx report.json --settings my-rules.json --toolkits # with customised rule settings, toolkits included
java -jar build/twx-code-analyzer.jar settings my-rules.json # settings template (every rule with its defaults) to edit
java -jar build/twx-code-analyzer.jar inventory MyApp.twx # what the loader sees
java -jar build/twx-code-analyzer.jar rules docs/RULES.md # rule catalogue as markdown
run.sh / run.bat start the packaged app; package.sh builds the Linux and Windows distributions with a trimmed Java runtime (see docs/BUILD-AND-SIGNING.md). The WAR files deploy the same application on WebSphere Liberty, WebSphere traditional or Tomcat for a team (see docs/DEPLOYMENT.md).
A .twx file is a ZIP archive with an IBM-defined structure:
application.twx
├── META-INF/
│ ├── package.xml manifest: project, branch, snapshot, buildVersion, dependencies, object list
│ └── metadata.xml
├── objects/
│ └── <objectId>.xml one XML document per artifact
├── toolkits/
│ └── <snapshot>.zip every bundled toolkit, same layout (recursively)
└── files/
└── <assetId>/<name> content of the managed assets (server files, web files, images ...)
Loading happens in four stages (tca.parse.TwxLoader):
META-INF/package.xmlprovides the package identity (name, acronym, snapshot, branch, the product version that produced the export) and the dependency list (toolkit snapshots, system or not).- Every
<object>entry of the manifest (id, versionId, name, type) is joined with itsobjects/<id>.xmldocument. Missing documents are recorded as diagnostics instead of failing the load. toolkits/*.zipare loaded the same way and attached to the model by snapshot id; embedded subprocess BPDs (exported with their GUID as name) are relabelled after the activity that embeds them.files/members are listed; JavaScript managed assets are kept in memory so the script rules know the functions defined by server files and web files.
The object type comes from the manifest. The numeric prefix of an object id identifies the artifact family:
| Prefix | Type in the manifest | Shown as |
|---|---|---|
| 1 | process |
Service, grouped by its kind (see below) |
| 25 | bpd |
Process (BPD) |
| 64 | coachView |
Coach View |
| 12 | twClass |
Business Object |
| 61 | managedAsset |
Managed Asset (server file, web file, design file) |
| 21 | epv |
Exposed Process Value |
| 24 | participant |
Team |
| 4 | underCoverAgent |
Undercover Agent |
| 7 | webService |
Web Service |
| 14 | trackingGroup |
Tracking Group |
| 62 | environmentVariableSet |
Environment Variables |
| 51 | userAttributeDefinition |
User Attribute |
| 63 | projectDefaults |
Project Defaults |
| 2064 | SmartFolder |
Saved Search |
A service (process) is classified by its processType code: 1 decision service, 2 Ajax service, 3 heritage human service, 4 integration service, 6 general system service, 7 advanced integration service, 10 client-side human service (CSHS), 11 external service, 12 service flow, 13 deployment service flow. The Objects tab groups services by this kind, so client-side human services, Ajax services and integration services are separate groups.
Type-specific parsers (ServiceParser, BpdParser, CoachViewParser, BusinessObjectParser) turn the XML into models: steps with their component, coordinates, scripts, mappings and pre/post assignments; lanes, flow objects, flows and boundary events; coach view options, event handlers, inline scripts, AMD dependencies and included resources; business object properties with type references. Scripts collects every executable snippet of an artifact (step scripts, text templates, link conditions, mappings, default values, coach view handlers and inline scripts) with a human-readable location.
tca.engine.Analyzer runs every rule of tca.rules.RuleSet over a RuleContext that lazily parses and caches the models, keeps a reverse reference index (which artifact references which), and exposes the thresholds from the settings.
Rules produce findings. Each finding carries:
| Field | Meaning |
|---|---|
ruleId, title, category, severity |
The rule (see docs/RULES.md) |
score |
Severity weight (Critical 100, Major 40, Minor 10, Info 2) x rule impact (1..3); the ranking key |
confidence |
high = certain from the export; medium = heuristic match, shown as "needs review" |
path |
Application (acronym) / artifact type / artifact / step or script |
line, column, snippet |
Position and source line inside the script or template when known |
message, evidence, remediation, reference |
What was found, the proof, what to do, the source of the rule |
Three kinds of rules exist:
- Structural rules read the models: unconnected steps, gateways without a default path, services without error handling, coaches after long chains of steps, teams with static member lists, toolkit cycles, unused artifacts, missing references, business objects with too many properties, naming and documentation conventions, size thresholds.
- Pattern rules run over comment- and string-stripped script text: string-built SQL, hard-coded credentials and URLs, debug output,
toString()of business objects in mappings, synchronous browser calls, ES6 syntax in server scripts, and the JavaScript syntax check itself. - Syntax-tree rules parse each script with the Rhino parser (bundled, no runtime dependency) into an abstract syntax tree and reason on it: undefined identifiers with scope resolution (server-side scripts know the BAW API objects, the functions of the application's and toolkits' server files; coach view scripts know the browser and coach globals, AMD dependency arguments, the view's own scripts and the web assets the view includes); undeclared
tw.localvariables checked against the parameters and private variables of the service or process (embedded subprocesses inherit the parent's variables); definite division by zero and null or undefined property access by straight-line constant tracking;evalon process data; loops without an exit; activedebugger;parseIntwithout radix; hard-coded business constants; dynamic SQL construction. IBM template syntax (<#= tw.env.NAME #>) is handled as template content, not as a JavaScript error.
Scripts with syntax errors are reported once (rule TCA-JS-021) and skipped by the syntax-tree rules; the report's coverage block lists them and marks the analysis as partial.
Findings are ranked by score, then severity, then artifact. The health score is 100 x exp(-density / 40) where density is the total score per application artifact: 100 is clean, a typical legacy application scores between 10 and 30.
Static analysis is advisory. Confirm a finding in the application context before changing production logic.
The rules come from three places, documented in docs/:
- the rule table of a legacy, database-backed code analyzer that ran on Process Center (176 rules, 129 of them re-implemented statically; the mapping is in docs/LEGACY-RULES.md),
- IBM's published checkstyle rules for BAW and CP4BA best practices (docs/RESEARCH-RULE-SOURCES.md),
- JavaScript static analysis (scope analysis, constant propagation, dangerous constructs).
The complete catalogue with description and remediation for every rule is generated from the code: docs/RULES.md.
The Toolkit Usage tab answers where the application uses each bundled toolkit. Duplicate snapshots of the same toolkit (a common situation after upgrades) are shown as one logical toolkit. Every toolkit is listed, including those with no detected usage.
| Status | Evidence |
|---|---|
| Used | An application artifact references the toolkit artifact's id in its XML: a service call, a coach view in a layout, a business object as a variable type, an included asset, a team, an EPV. Certain. |
| Possible usage | An application script instantiates a business object with new tw.object.Name() and exactly one toolkit declares that name (the application itself none). Inferred. |
| No detected usage | Neither. This is not proof that the toolkit can be removed: lookups by name at runtime (tw.system.model.findProcessByName, service names in configuration) are invisible to static analysis. |
Ambiguous constructor names (several toolkits declare the same business object) are reported as diagnostics, not counted as usage. References from other toolkits are listed per toolkit, because a toolkit that only another toolkit needs is still required.
Expand a toolkit to see its used artifacts grouped by type and the application artifacts that use each of them (clickable). Select toolkits and export the report as self-contained HTML (print to PDF from the browser) or as a PDF rendered by the engine.
The artifact tree groups the application (and, optionally, every bundled toolkit) by artifact kind and shows the number of findings per artifact. Selecting an artifact shows:
- the diagram of a service or process drawn from the Process Designer coordinates (steps with findings outlined in red, click a step for its scripts, mappings and findings),
- its findings,
- variables (parameters and private variables with type, default and documentation),
- steps or flow objects as a flat list (kind, implementation with a link to the called artifact, lane, pre/post assignments, mapping count, script size, error handling),
- scripts with their location,
- coach view configuration options, binding and included resources,
- business object properties with the nested structure of complex types resolved in place (circular references and types missing from the export are flagged),
- managed asset type, size and content for JavaScript files,
- references and referenced-by lists (both clickable),
- the raw XML on request.
| Export | Where | Content |
|---|---|---|
| CSV | Findings tab | The filtered findings with path, message, evidence and remediation |
| HTML | Findings tab, Toolkit Usage tab | Self-contained page (summary, rules, findings or toolkit usage), print to PDF from the browser |
| Findings tab, Toolkit Usage tab | Rendered by the engine (tca.engine.Pdf, no external library), A4 landscape, page breaks with repeated table headers; the findings PDF respects the current filter and sort |
|
| JSON | analyze command, /api/report/<id> |
The full report (inventory, summary, coverage, diagnostics, toolkit usage, rules, findings) |
Every analysis is stored under data/<id>/ as the uploaded file, the report JSON and a small metadata file (no database). The History page lists them; the trash button there and the Delete button on the report remove the analysis permanently (uploaded file, report and metadata are deleted from disk). Compare takes two analyses of the same application and reports added, removed and changed artifacts, toolkit version changes, and the findings that are new (regressions) or fixed.
The Settings page customises the rule set; the settings are stored by the server in the data directory (settings.json) and apply to every analysis made from the browser, the command line (--settings) or the embedded engine.
| What | Where | Effect |
|---|---|---|
| Enabled | per rule | A disabled rule does not run; it stays in the catalogue and in reports as disabled with 0 findings |
| Severity | per rule | Replaces the rule's severity (Critical, Major, Minor, Info) on every finding of the rule, including the ones the rule would have escalated itself |
| Impact | per rule | Multiplier 1..3 of the severity weight (business criticality of the rule) |
| Severity weights | global | Points per severity (defaults Critical 100, Major 40, Minor 10, Info 2); score = weight x impact, the weighted total drives the ranking and the health score |
| Thresholds | global | Limits of the size and complexity rules (script length, steps per service, parameters, private variables, flow objects, controls per coach, toolkit count and depth, asset sizes ...) |
| Analyze toolkits | global | Default of the "also analyze the bundled toolkits" option |
The page has a filter (id, title, category, customised only) and bulk buttons (enable, disable or reset the shown rules). Export downloads the complete settings as a JSON file (twx-code-analyzer-settings.json, every rule with its effective and default values); Import loads such a file, full or partial (only the rules that change), validates it and reports what was ignored (unknown rules or thresholds, invalid severities or impacts); Reset to defaults removes every customisation. Every report records the settings it was produced with (settings in the JSON, a note on the Overview tab), and the Rules page shows the effective values with disabled and customized badges.
Settings file format (partial documents are accepted; values equal to the defaults are dropped when stored):
{ "format": "twx-code-analyzer-settings", "version": 1,
"includeToolkits": false,
"severityWeights": { "CRITICAL": 100, "MAJOR": 40, "MINOR": 10, "INFO": 2 },
"thresholds": { "scriptLinesMedium": 100, "serviceSteps": 40 },
"rules": { "TCA-JS-001": { "enabled": false }, "TCA-JS-020": { "severity": "MINOR", "impact": 2 } } }java -jar twx-code-analyzer.jar settings template.json writes the full template with every rule; analyze ... --settings file.json applies a file on the command line. A settings file exported from the web app or from the process application can be imported anywhere.
flowchart LR
User["Browser or CLI"] --> Main["tca.Main"]
Main -->|serve| Web["tca.web.WebServer (JDK HTTP server, desktop app)"]
Container["Servlet container (WAR)"] --> Servlet["tca.web.AnalyzerServlet"]
Web --> Api["tca.web.Api (JSON API shared by both)"]
Servlet --> Api
Main -->|analyze / inventory / rules / settings| Loader
Api -->|POST /api/analyze| Loader["tca.parse.TwxLoader"]
Loader --> Model["tca.model (packages, objects, services, BPDs, coach views, business objects, scripts)"]
Settings["tca.rules.RuleSettings (enabled, severity, impact, weights, thresholds)"] --> Context
Model --> Context["tca.rules.RuleContext (cached models, reference index, thresholds)"]
Context --> Rules["tca.rules.* (156 rules)"]
Rules --> Report["tca.engine.Report (findings, summary, coverage, diagnostics)"]
Context --> Usage["tca.engine.ToolkitUsage"]
Usage --> Report
Report --> Store["tca.web.Store (data/<id>/, settings.json)"]
Report --> Pdf["tca.engine.PdfReport"]
Context --> Views["tca.engine.ObjectViews, tca.diagram.DiagramBuilder, tca.search.Searcher"]
Views --> UI["static/app.js"]
Report --> UI
Facade["tca.baw.Facade (JSON in / JSON out)"] --> Loader
Facade --> Views
Java 8 bytecode, no framework, one runtime dependency (Mozilla Rhino, shaded into the jar for the JavaScript parser); the servlet API jars in lib/ are compile-time only. The web UI is plain HTML and JavaScript with Bootstrap, Font Awesome and Chart.js served from the static/ folder (packaged into the WAR); it uses relative URLs only, so it runs at any context root. See docs/ARCHITECTURE.md for the package layout, the TWX facts the parsers rely on, and the ranking formulas; docs/EMBEDDING.md for the JSON facade used to embed the engine in other deliveries.
Paths are relative to the application root (http://127.0.0.1:8765/ for the desktop app, https://server/twx-code-analyzer/ for the WAR).
| Endpoint | Purpose |
|---|---|
| `POST /api/analyze?toolkits=0 | 1&name=&settings=` |
GET /api/info |
Engine version and deployment options (workspaces, retentionDays, settingsReadOnly) |
GET /api/settings · GET /api/settings?download=1 |
Full rule settings document (the export file; download sets a file name) |
PUT /api/settings · DELETE /api/settings |
Import a settings document (full or partial, validated; returns warnings and the stored settings) / reset to the defaults |
GET /api/report/<id> · DELETE /api/report/<id> |
Stored report / delete an analysis permanently (report, metadata and uploaded TWX) |
GET /api/report/<id>/pdf?sev=&cat=&rule=&type=&conf=&q=&sort= |
Findings PDF with the same filter as the UI |
GET /api/history |
Analyses list |
GET /api/objects/<id>?toolkits=1 · GET /api/object/<id>/<objectId>?xml=1 · GET /api/diagram/<id>/<objectId> |
Artifact tree, artifact detail, diagram geometry |
GET /api/toolkit-usage/<id> · `GET /api/toolkit-usage//pdf?keys=k1 |
k2` |
GET /api/search/<id>?q=®ex=&case=&scope=&types=&toolkits= |
TWX search |
GET /api/compare?a=<id>&b=<id> |
Snapshot comparison |
GET /api/rules |
Rule catalogue with the effective severity, impact and enabled state |
The desktop app parses files locally and listens on 127.0.0.1 only (serve ... --host 0.0.0.0 opens it deliberately, for example inside a container). On a server the application isolates visitors in workspaces: each browser receives a random token in an HttpOnly cookie and sees only its own analyses and rule settings (stored under <dataDir>/ws/<token>/); a report id of another workspace answers 404. Uploads can be deleted permanently at any time and an optional retention purges old analyses. The WAR has no authentication of its own, so for a private deployment add the container's security (a security constraint, the reverse proxy or the enterprise single sign-on, see docs/DEPLOYMENT.md). The tool makes no network calls of its own; the only outbound connection is the optional Process Center export of the embedding facade, which happens only when a caller supplies a server URL and credentials. No telemetry, no external scripts or fonts in the UI.
- docs/RULES.md - the 156 rules with description and remediation (generated)
- docs/LEGACY-RULES.md - mapping of the legacy analyzer's 176 rules to the static rules
- docs/RESEARCH-RULE-SOURCES.md - public sources of the best-practice rules
- docs/ARCHITECTURE.md - packages, TWX facts, ranking, diagrams, deliveries
- docs/EMBEDDING.md - the JSON facade for embedding the engine (Java, BAW)
- docs/WEB-APPLICATION.md - the web application (WAR) enterprise edition: features, configuration, identity, API and pipeline recipes, repositories, data layout
- docs/SECURITY-REVIEW-WAR.md - security review of the web application
- docs/TEST-REPORT-1.3.md - functional test results of the web application
- docs/SECURITY-SCAN-REPORT-1.3.1.md - SAST / SCA / DAST scan results (CodeQL, Semgrep, SpotBugs + FindSecBugs, Trivy, Retire.js, gitleaks, OWASP ZAP) with dispositions
- docs/DEPLOYMENT.md - deploying the WAR (Liberty, WebSphere, Tomcat; Docker; the layout of the live demo)
- docs/CHANGELOG.md - what changed in each version
- docs/BUILD-AND-SIGNING.md - reproducible build, packaging, signed Windows launcher
- process-app/README.md - the analyzer as a BAW process application (TWX Code Analyzer 1.2,
TWXCA): the engine embedded as a managed server file, analyses as process instances, dashboard with findings, explorer, diagrams, search, history, comparison and rules
Apache License 2.0 - see LICENSE and NOTICE. You may use, copy, modify and redistribute the software, including commercially, provided the copyright notice, the license and the NOTICE file are kept with every copy (attribution to Dosvak LLC). Versions up to 1.3.1 were published under the MIT license; that license continues to apply to those copies.
Third-party components: Mozilla Rhino (MPL 2.0), Bootstrap (MIT), Font Awesome Free (CC BY 4.0 / SIL OFL 1.1 / MIT), Chart.js (MIT), Swagger UI (Apache 2.0).
Published by Dosvak LLC, an IBM Business Partner (Silver, IBM Partner Plus). IBM, IBM Business Automation Workflow, IBM Business Process Manager and IBM Cloud Pak are trademarks or registered trademarks of International Business Machines Corporation; this project is not affiliated with, endorsed by or supported by IBM.