AI cutover checklist for enterprise organizations.
An ERP or commerce cutover is where data moves, rules change, and accountability gets blurry. AI makes that moment higher-stakes. This is what your team can do now — with tools you may already own — so governance stays inside your organization, with or without a systems integrator or an SAP SLA.
Why now
When cutovers fail, the client usually carries the cost — and the evidence of what went wrong has to be rebuilt in court. Two public examples:
AI raises the stakes. When AI agents read and act on data across systems that were never fully integrated — ERP, WMS, commerce, CRM — a gap that once produced a bad report can now trigger actions at machine speed, in every channel at once. An SLA covers uptime and support response; it does not certify your data or govern what AI does with it.
What you can do now
A first pass of each section can be stood up in under an hour on free tiers. None of it waits for the migration program.
1. Signing keys and Git
- Generate organization signing keys. Ed25519 is preferred; RSA (3072-bit or larger) where a partner system requires it. Private keys live in platform secrets or a key manager — never in a repository.
- Sign every commit and protect the branch. Require signed commits and reviewed pull requests on the branches that deploy; nothing reaches production unsigned or unreviewed.
- Publish your public keys. A JWKS endpoint lets partners, auditors and the SAP or AEM team verify your data signatures offline. See it working.
- Rotate on a schedule. Retired keys keep verifying until their end date, so rotation never breaks old evidence.
2. Cloudflare
- Allow list at the edge. Only known origins, partners and agents reach your APIs; everything else stops before it touches a system of record.
- Turn on TLS 1.3 on every hostname; keep the minimum at 1.2 until every client and partner supports 1.3, then raise it. Require encrypted transport between every cloud you connect.
- Run server-side logic in Workers. Signing, redaction and rendering happen at the edge, not in the browser.
- Route AI calls through a gateway for logging, rate limits and caching, so every model call is visible and attributable.
3. Xano as the encrypted system of record
- One record per fact. User, Product, Tags, Category and Attributes live in one place; every channel reads from it instead of keeping copies.
- Encrypt sensitive fields (JWE) and sign tokens (JWS) with Xano’s built-in security functions.
- Check access live. Personalization can use token claims; permission is re-checked against the record on every request.
- Keep an append-only log of every change and every AI action, timestamped in UTC.
4. The Webflow API
- Publish only through the API from approved, validated data — no manual uploads or pasted embeds.
- Use scoped, rotating tokens per site and per job.
- Keep personal data out of the CMS. Pages show bound, non-sensitive fields; personal and health data stays in the encrypted record.
- Localize, then review. Peer and stakeholder approval before anything publishes to a market.
- Webflow components into Fiori. Header, footer, disclosures and the consent banner publish as web components; brand tokens map to Fiori Horizon theme parameters.
- Fiori on the edge. The UI5 build (index.html, Component-preload.js, manifest.json) is served from Cloudflare Workers static assets, and OData calls stay same-origin on your domain.
- AEM linked Edge Functions. AEM Edge Functions — JavaScript on Adobe’s CDN — call the same Worker and Xano checks, so AEM pages and Fiori apps enforce one consent and region rule set.
- Rust reinforces every call. A Rust-to-WebAssembly module in the Worker validates the SAP IAS / XSUAA token, asks Xano for consent and region (no consent, no send), and strips fields the caller is not cleared for.
- No open ports to SAP. Cloudflare Tunnel and Access give an outbound-only link to S/4HANA or the ECC Gateway; the Launchpad tile, OData service and PFCG roles stay in SAP.
5. Shopify apps: public and custom
- Start every new app in the Dev Dashboard. Private apps were retired in 2022 and admin-created custom apps stopped on January 1, 2026; choose public or custom distribution once — it cannot change.
- Keep tokens in the Worker’s vault. Offline and refresh tokens are encrypted per shop, refreshed before expiry, and never reach Webflow or the browser.
- Feed GA4 consent and Merchant channels from the same registry. Consent state comes from the Xano record; product feeds are signed per run.
6. The governance gate
- Test every data release — schema, latency, retries, auth.
- Nothing deploys without human approval, and AI agents act only inside harness restrictions you define.
- Sign the result. Each feed run, QA check, mock load and cutover manifest carries your signature — a chain of custody your organization owns.
Memory safety and nested data loads, in plain terms
Python and Node are memory-safe languages: their garbage collectors prevent these bugs in ordinary code. The risk sits in the C and C++ underneath — native extensions, add-ons and the runtimes themselves — and in loaders written by hand around spreadsheets. The last column is what replaces each pattern in the nested data load model: a JavaScript Worker outside, a Rust → Wasm module inside, and Tokio tasks for concurrent loads.
| Concept | Simple explanation | C++ today | Python today | Node today | Replaced with (nested data load model) |
|---|---|---|---|---|---|
| Use after free | Code keeps using memory after giving it back. The memory is reassigned, and an attacker can place their own data there, so the old code acts on it — a crash becomes a takeover. Like keeping a copy of a hotel key after checkout: the room now belongs to the next guest. | Manual delete, dangling pointers and references; the compiler does not stop it. | Safe in pure Python; possible in C extensions and the interpreter itself. | Safe in JavaScript; possible in native C++ add-ons and engine bugs. | Rust ownership: the compiler refuses code that uses memory after it is freed. Loaders run as Rust → Wasm inside the Worker. |
| Buffer overflow | A buffer is a fixed-size block of memory set aside to hold incoming data, such as a row, a file chunk or a network message. If code writes more than the buffer holds, the extra spills into the memory next to it and overwrites other data — including the addresses that decide what runs next. Like pouring two liters into a one-liter jug on a crowded shelf. | Arrays and memcpy / strcpy with no bounds check; the compiler does not stop it. | Bounds-checked in pure Python; possible in C extensions and file parsers. | Bounds-checked in JavaScript; possible in native add-ons and engine bugs. | Bounds checked on every access: Rust slices and vectors know their length, and the Wasm sandbox confines any fault to the module’s own memory. |
| Double free | The same memory is given back twice, corrupting the allocator — another path to a takeover. | Two delete calls on one pointer, or two owners of one object. | Reference-count mistakes in C extensions (Py_DECREF twice). | Lifetime mistakes in native add-ons. | One owner, freed once: Rust drops each value exactly once; the same struct is validated before any load. |
| Memory safety | A guarantee that code only touches memory it owns. Microsoft and Google attribute about 70% of serious security bugs to its absence. | Not guaranteed; depends on discipline, reviews and sanitizers. | Guaranteed in the language; not in native extensions. | Guaranteed in the language; not in native add-ons. | Guaranteed at compile time for the inner module, plus the Wasm sandbox at run time; native extensions replaced by Rust (PyO3, napi-rs) or Wasm. |
| Firmware | The program stored inside a device — a router, a drive, a scanner, a payment terminal — that runs the hardware. Mostly written in C and shipped as one compiled image with its settings and keys, so it carries the same memory bugs with fewer safeguards and rarer updates. | The norm: C, C++ and assembly with no memory isolation on small chips; one overflow can control the device. | MicroPython on small boards is memory-safe at the script level, but runs on a C interpreter and C drivers. | Node drives devices through native C/C++ bindings; the firmware underneath is still C. | Rust for new firmware (no_std, bounds-checked); images are signed, verified by secure boot and listed in an SBOM, and a device only accepts an update that carries your signature. |
| Restriction rules | Rules that limit what code may touch — which memory, which hosts, which files, which actions — enforced by the compiler, a sandbox or a gate rather than by trust. | None built in; relies on operating-system permissions and code review. | A script can reach anything its process can; a virtual environment is not a sandbox. | Full access by default; the permission model (--permission) is opt-in. | Restricted by default, in layers: the compiler enforces ownership, bounds and Send / Sync; the Wasm module gets no file or network access unless granted; the Worker calls only allow-listed hosts; firmware boots only if signed; nothing deploys without human approval. |
| Remote control | Who may send commands to a system or device from somewhere else — update firmware, change a setting, start a job. If anyone who reaches the network can, so can an attacker. | Device agents and update clients with hard-coded credentials or open debug ports. | Admin scripts and SSH automation running on long-lived keys. | Admin APIs and WebSockets guarded by one shared token. | Signed commands only: each remote action carries a short-lived, scoped signature that the Worker verifies; firmware updates over the air only when signed; every command is written to the register. |
| Data syndication | Sending the same data out to many channels — storefronts, Merchant, marketplaces, partners. Every copy is another place data can leak or go stale. | Batch exporters writing files to FTP. | CSV exports and cron scripts pushing to SFTP or APIs. | ETL scripts posting JSON with copied API keys. | One source, allow-listed destinations: feeds are generated from the system of record, sent only to allow-listed hosts, stripped of fields each channel is not entitled to, and signed on every run. |
| Event-on-change permissions | Permission is checked every time data changes, not once at login. When a record, a consent or an entitlement changes, an event fires and every downstream copy is checked again. | Permissions checked when a connection opens, then cached. | Checked when a job starts; the job keeps running after access is revoked. | Session tokens trusted until they expire. | Signed change events: each feed.updated or consent change re-checks consent and entitlements live before anything is syndicated, so a revoked permission stops the next send, not the next login. |
| Thread channel maps | Work is split across tasks that pass messages over channels, mapped one per sales channel, instead of sharing memory — so no two tasks write the same data at once. | Shared memory with locks; a missed lock is a data race and undefined behavior. | The GIL serialises threads; asyncio queues help, but free-threaded builds bring races back. | One event loop; worker_threads pass messages, but shared buffers can still race. | Tokio channels, one task per channel (web, POS, Merchant, WMS); the compiler’s Send / Sync rules reject data races. |
| AI binding and testing | AI maps data to fields and writes the tests; nothing ships until the tests pass and a person approves. | Hand-written mappings and tests, run when someone remembers. | Ad-hoc scripts and notebooks around CSV files. | Ad-hoc ETL scripts with untyped JSON. | AI binds to the typed struct; schema, latency, retry and auth tests run on every load; the governance gate needs human approval. |
| Nested data load model | Loaders sit inside each other: the outer layer routes and authenticates, the inner layer validates, strips and signs. | One large loader binary with everything in it. | A pandas script reading and writing CSV. | A single Node service doing fetch, transform and write. | Worker (JS) → Rust → Wasm → Tokio tasks, each layer small, typed and tested; every load emits a signed feed.updated event. |
The 70% figure is from public analyses by the Microsoft Security Response Center (2019) and the Google Chromium security team (2020). Free-threaded Python is optional from 3.13.
Offload feeds to GraphQL and the Google Merchant API
Shopify’s Admin API is GraphQL-first, and Google’s Content API for Shopping shut down on August 18, 2026 — product feeds now run on the Merchant API. Instead of exporting spreadsheet-shaped files by hand, generate feeds from the system of record in edge functions:
- JSON in, JSON out. Read from Xano, shape for Shopify GraphQL and the Merchant API, validate before send.
- Memory-safe transforms. Cloudflare Workers run WebAssembly, so data-layer transforms can be compiled from Rust into memory-safe modules at the edge.
- Security as a feature, not a project. Allow lists, TLS 1.3, redaction and a signature on every feed run are part of the pipeline from day one.
- Every domain, one estate. Multi-domain and multi-country storefronts resolve and feed as one estate. See the Merchant API migration calendar.
With or without SAP SLAs, these measures should be in place. Keep the evidence inside your organization — signed, verifiable, and yours.
Case summaries reflect public reporting and court records as cited; settlements were made without findings or admissions of liability. This checklist is technical guidance, not legal advice. Related: channel feed & QA certification · Channel Publish