Skip to content

About

De-risking SAP S/4HANA custom-code transitions — grade your custom ABAP for readiness, Clean-Core posture, migration effort and risk. In-system cockpit + CLI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

caern

De-risking SAP S/4HANA custom-code transitions.

Every S/4HANA migration hits the same wall: the custom Z-code — how much exists, what breaks on S/4HANA, what fights the Clean Core model, what is dead weight, and what it costs to fix. caern turns that unknown into graded, evidence-backed analysis a project lead can act on.

This repo holds the whole product:

Where What
src/core shared in-system ABAP extractor base — the caern.export/v0 contract + the reused ATC / where-used / usage-harvest helpers (object table below)
src/{lens,plumb,atlas,sweep,compass,caliper} the six wedges — one ABAP extractor each (ZCL_CAERN_<TOOL>), each a subpackage of the caern umbrella package
caern-cli the host CLI (caern <command>) that drives extraction and renders customer-ready reports — usage: caern-cli/README.md
assets the single-page cockpit CSS/JS (served as MIME repository objects — see Cockpit below)

Approach. Each wedge reads one signal from a live SAP system and emits the one normalised contract (caern.export/v0); core owns that contract plus the shared source-harvest and stays wedge-agnostic (the cockpit dispatches wedges by name, so core keeps no static dependency on them). caern's main application is the in-system cockpit (ZCL_CAERN_ICF) — a single-page analysis & reporting workbench served from the SAP ICM; the caern CLI is a companion for scripting, CI gates and client decks. Both render the same data through the same contract.

Handling — two ways to run it, stated up front. caern's main application is an in-system product: the ABAP classes, the DDIC tables, the ICF cockpit node, the cockpit assets (MIME objects) and the ZCAERN authorization object install into the SAP system by transport or abapGit, and it runs there natively — the cockpit is opened from transaction ZCAERN. Built and proven on AS ABAP 7.52 SP04; the frameworks it uses are accessed dynamically, so it also activates on classic 7.40/7.50 ECC and reports, in-system, which checks the release supports (Check-content tab). The repo is serialised with abapGit PREFIX folder logic, so the package name is chosen at install time: pull into ZCAERN (or your own registered namespace) and the subpackages follow (ZCAERN_CORE, ZCAERN_LENS, …) — the repo bakes in no fixed package prefix.

Installing: INSTALL.md. Two steps are not optional and not automatic — activate the ICF node (the pull installs the service but leaves it inactive) and build the ZCAERN role (the authorization object ships, a PFCG role cannot, so on day 1 nobody holds it — not even SAP_ALL). The cockpit fails closed and tells you which step is missing.

The caern host CLI is a companion, not the product: it drives the same in-system extractors over ADT for scripting, CI gates and generating client decks off a laptop. For that mode you need X.509 cert auth to an ADT-reachable system (ADT_BASE / ADT_CERT / ADT_KEY in a gitignored caern-cli/.env, see caern-cli/.env.example) and Node ≥ 20.

The extractor core (src/core)

The core package (ZCAERN_CORE under the caern umbrella) — the reuse boundary every wedge builds on (no wedge duplicates it):

Object Role
ZIF_CAERN_EXPORT the normalised export contract (caern.export/v0) every wedge emits through
ZCL_CAERN_CORE build_json — assembles findings + summary into the export
ZCL_CAERN_CORE_USED shared source harvest: read_source + scan (SCAN ABAP-SOURCE) + resolve_tables (one batched DD02L query) — the DB tables & called FMs a code object touches. Used by Plumb + Atlas so neither re-implements the scan.
ZCL_CAERN_CORE_SDB on-prem S/4 readiness content: affected(refs) joins the installed Simplification DB (SYCM_*) to the SAP objects a program touches → the simplification item(s) hitting it; target_release() = the S/4 label the content covers. Used by Lens.
ZCL_CAERN_CORE_ATC runs SAP's own Code-Inspector/ATC checks headlessly: cloud_admissibility(objects) drives CL_CI_TEST_ADMISSIBLE_4_CLOUD (object-type ABAP-Cloud admissibility). Used by Lens.
ZCL_CAERN_SDB S/4HANA Simplification-DB currency check (SYCM)
ZCL_CAERN_GRADE the one grading + effort model — assess(dims, errors, cloud, simpl, target) → Clean-Core score/grade + an indicative person-day band. Every surface (cockpit Overview / Effort estimate / Reports, caern estimate, the deck) reads it; nothing re-weights a grade locally.
ZCL_CAERN_ROLLUP estate roll-up over the stored runs (estate(scope) — findings / dims / cloud / simpl / add-ons by custom vs modified-SAP), carrying the grade + effort pre-computed per target (assess_onprem / assess_cloud) by ZCL_CAERN_GRADE. Feeds the cockpit Overview and caern estimate.
ZCL_CAERN_CONFIG (+ table ZCAERN_CONFIG) the calibration behind the model — grade bands, clean prior + pseudo-count, overhead and effort multipliers, benchmark. spec holds the defaults and the form definition; effective( ) overlays the stored overrides. This is the cockpit's Settings tab, with reset-to-defaults.
ZCL_CAERN_CAPS release-capability probe — what this system can actually do (JSON adapter, Simplification DB, ABAP-Cloud check, SCMON, WBCROSSGT, Fiori map) and what a fuller result would need. Rendered as the System capabilities panel so an empty check is never mistaken for a clean one.
ZCL_CAERN_JSON the dynamic JSON adapter around /UI2/CL_JSON. It is called dynamically on purpose: a static reference would fail activation on a system without SAP_UI / SAP_GWFND — this adapter is what lets caern install below its 7.52 build target. available( ) reports the gap honestly instead of dumping.
ZCL_CAERN_REPORT the one renderer: body(json) + css( ) = the fragment + stylesheet the cockpit embeds, tool-aware, with finding-driven next steps. A tool it does not know renders as "no interpretation applied" — never as a clean bill of health.
ZCL_CAERN_STORE (+ ZCAERN_RUN / ZCAERN_FINDING / ZCAERN_STATUS) run persistence + diff_last_two, bounded (each run caps its (package, tool) history to the most-recent keep_per_group runs), plus per-finding triage — set_status keys a status (open / ack / progress / fixed / wontfix) + note by object + check, so it survives a re-run
ZCL_CAERN_PKG package inventory for the cockpit — customer packages (see custom scope below), SAP-standard packages carrying logged modifications (SMODILOG), and the installed third-party add-ons, with object counts
ZCL_CAERN_ICF IF_HTTP_EXTENSION — the single-page cockpit web app (see below)
ZCL_CAERN_ASSETS the cockpit CSS/JS (from assets/app.{css,js}), held as MIME repository objects under /SAP/PUBLIC/caern/ and served by ZCL_CAERN_ICF as `?asset=css

Custom scope is not just Z*/Y*. ZCL_CAERN_PKG=>custom_scope( ) returns the Z*/Y* default namespace plus every namespace this system produces itself — TRNSPACE rows with role = 'P' and sapflag <> 'X'. A customer whose code lives in a registered namespace (/ACME/…) is therefore in scope without configuration; SAP-delivered namespaces are recipient-role and stay out, so the custom estate never fills up with SAP packages. The cockpit browser and the estate roll-up share this one definition, so both agree on what "custom" means.

Sweep's runtime-usage (SCMON) + static where-used (WBCROSSGT) reader lives in the Sweep wedge, not here — one consumer, so it stays out of the reuse boundary until a second wedge needs it.

Cockpit (ICF)

ZCL_CAERN_ICF (an IF_HTTP_EXTENSION handler) serves the single-page workbench directly from the SAP ICM — caern's main application, the analysis & reporting cockpit (caern-cli is the scripting/deck companion). The page loads once with a boot payload (package inventory, portfolio KPIs, the latest-run matrix and recent runs, embedded as JSON) and then never navigates away: browsing, filtering, paginating (50/page) and selecting packages, switching tabs and reading results all happen client-side, so there are no selection→result screen jumps and the browser Back button is never in the critical path. Only an actual analysis hits the server, as a small HTML fragment.

  • Tabs — Overview (portfolio KPIs, worst offenders, never-analyzed), Analyze (the package browser + the six-app palette + the tool pipeline), Result matrix (packages × tools heatmap; click a cell to open its report), Results (the result cards of the current analysis), Effort estimate (the estate roll-up: grade + migration effort for the chosen target) and Reports (the customer-ready deliverable — charts, method cards, print/PDF, PNG and CSV export). Beside them, three admin views: History (every run in a table with a detail-pane + per-run "compare to previous"), Check content (the installed Simplification DB — release coverage, item count and SAP's readiness check set — plus the System capabilities panel; Lens result cards deep-link here) and Settings (the model calibration, ZCL_CAERN_CONFIG).
  • Package browser replaces typing a package name: a searchable, sortable, paginated list of the ZCL_CAERN_PKG sources (custom code and modified-SAP) with checkbox multi-select, run through the selected tools as a pipeline with live progress; each result streams in as a card. A package is analysed as a tree (the package and everything below it in the hierarchy), not as a single node.
  • Whole-estate scan — the pipeline is interactive and suits a handful of packages; a full estate (hundreds of packages) is analysed by the schedulable report ZCAERN_SCAN as an SM36 background job (no HTTP timeout, one commit per run, every failure logged with its reason). The cockpit then browses what it produced. See INSTALL.md step 6.
  • Per-package diff — "compare to previous" surfaces added/fixed findings via diff_last_two.
  • Fragment API (same node, same authenticated + authorized caller): ?frag=run&tool=&pkg= runs one wedge and returns its result card; ?frag=diff&tool=&pkg= the delta; ?frag=view&run=<id> a stored run. A wedge is dispatched by name (CALL METHOD (|ZCL_CAERN_{ tool }|)=>run) so core keeps no static dependency on the wedges; every run is persisted through ZCL_CAERN_STORE; live and stored runs render through the shared ZCL_CAERN_REPORT.

The cockpit node (/sap/bc/caern, handler ZCL_CAERN_ICF) is served straight from the SAP ICM. It is authenticated and authorized — the node challenges for logon and every request runs an AUTHORITY-CHECK on the ZCAERN object (03 display / 16 run / 02 configure), granted through the ZCAERN role; state-changing routes are POST-only with a CSRF marker. For a quick look without the ICM, caern lens … --html > report.html produces a self-contained file you open via file://.

The wedges

Each wedge reads one signal and emits the shared caern.export/v0 contract; the caern CLI and the cockpit render the reports. Command usage + flags: caern-cli/README.md.

Wedge Signal Extractor (src/…) Prio
Lens S/4HANA readiness (real ATC + Simplification-DB) src/lens — ZCL_CAERN_LENS P0
Plumb Clean-Core posture / direct SAP-table access src/plumb — ZCL_CAERN_PLUMB P1
Atlas as-is footprint (tables + FMs a Z-object touches) src/atlas — ZCL_CAERN_ATLAS P1
Caliper dictionary check — custom DDIC against the S/4 data model (hard-typed fields, appends, includes) src/caliper — ZCL_CAERN_CALIPER P1
Sweep dead code (SCMON runtime + WBCROSSGT where-used) src/sweep — ZCL_CAERN_SWEEP P2
Compass transaction → Fiori-successor mapping src/compass — ZCL_CAERN_COMPASS P3

Effort estimate is not a seventh wedge — it is the roll-up. The grade and the migration-effort band come from one ABAP model, ZCL_CAERN_GRADE, served pre-computed per target by ZCL_CAERN_ROLLUP over the stored runs (drivers: Lens, Plumb and Caliper findings; Sweep marks the slice of effort you can avoid by retiring dead code instead of migrating it). It has its own cockpit tab (Effort estimate) and its own calibration (Settings); caern estimate and the caern report deck read that model — they never re-derive a grade or an effort figure of their own.

Honest by construction

The failure mode of a code-analysis tool is not a wrong number — it is a confident empty result. An estate nobody looked at, or a check the release cannot run, must never render as a clean estate. Three mechanisms make that structural rather than a matter of care:

  • caern refuses to grade what it could not measure. ZCL_CAERN_GRADE has an explicit ungraded state ('--', graded = abap_false) with the reason attached: with no analysed objects there is nothing to grade, and the surfaces show that instead of an "A". Likewise, an object whose source could not be read gets its own dimension and never counts as a graded, clean one.
  • The system tells you what it can check. ZCL_CAERN_CAPS probes the release at runtime and the cockpit's System capabilities panel (Check content) names every optional signal — the JSON adapter, the Simplification DB, the ABAP-Cloud check, the call monitor, the where-used index, the Fiori map — and what is missing without it. So when a check comes back empty you can tell whether it found nothing or could not look.
  • Triage reaches the deliverable. Every finding can be given a status (open / ack / progress / fixed / wontfix) and a note; the status is keyed by object + check, not by run, so it survives a re-analysis. A rebuilt export drops what you marked fixed or wontfix — so the report and the client deck reflect the triage instead of re-reporting work you already closed.

Using caern & license

caern is source-available: you may read, download, run, and evaluate it, and adapt it for your own use — including running it against your own or a client's SAP system and handing over the analysis. You do not need permission for that, and you are never in breach merely for using it. Reselling it, redistributing it, offering it as a hosted service, or building a competing product from it needs written permission — that is also the channel for development partnerships and reseller arrangements. Full terms: LICENSE.

If you run caern, the author would genuinely like to hear from you — it is how partnerships and feedback channels open up. A hello at contact@caern.eu is welcome, but it is a request, not a condition: your right to use caern does not depend on it.

About

De-risking SAP S/4HANA custom-code transitions — grade your custom ABAP for readiness, Clean-Core posture, migration effort and risk. In-system cockpit + CLI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages