Skip to content
Centriu
Centriu Run

Partial-Update Data-Loss Protection Automation: When Saving Four Fields Used to Erase Twenty

A wide-ranging audit of 13 screens in Centriu Run's infrastructure settings found what its own findings called the most severe defect: two screens that each save only 4 specific fields (a client's monthly value, contract type, contracted scope and expected complexity) were routing through a generic update function that rebuilds a client's ENTIRE record on every save, filling in literal defaults — empty string, empty array, false, null — for every field the caller didn't explicitly touch. Because nested groups like contact info, social accounts and address were unconditionally reconstructed from those defaults rather than left alone, every single save on either screen silently erased a client's contact details, address, social accounts, logos, brand colors and legal name — measured directly against real data: 22 of the organization's 23 active clients had contact information on file, meaning nearly the entire active client base was exposed. The fix replaces the generic update path with one that includes a column in the update only when its own source field was actually present in the request, and reconstructs a nested group of fields only when at least one of its own members was included — closing the exposure without changing how any screen that legitimately edits those fields already works.
22 of 23 clients were exposed
Only what changed gets written
Person working on a laptop with notifications on screen
Four fields saved. Twenty almost erased.

Why a function built for "save everything" is dangerous the moment something only saves a little

A function that assembles a complete database record from a client object is the natural, obvious way to handle a form that genuinely edits every field on that record — and it works perfectly for exactly that case. The danger appears the instant a second, narrower screen reuses that same function to save only a handful of fields it actually cares about: if the function's own logic can't tell the difference between "this field is genuinely empty" and "this field was never mentioned," it has no way to leave anything alone. It either saves everything correctly, or it silently overwrites everything else with a default — and which one happens depends entirely on whether the caller happened to populate every field, not on what the caller actually intended.

How the underlying problem shows up before you fix it

A screen built to save 4 specific fields, when used normally, causes unrelated data elsewhere on the same record — contact info, address, social handles, brand assets — to disappear on the very next page load.

The data loss is silent: no error, no warning, no confirmation dialog — the save reports success, because from the database's point of view, a normal update did happen.

A structured (nested) group of fields is especially vulnerable — even though the missing source fields disappear from the outgoing request in one format, a nested object made of several such fields can still arrive as an empty shape that overwrites what was already stored.

A comment already exists somewhere in the code warning about this exact danger for one specific function — but the same danger remains live and unaddressed in the generic path every other screen actually uses.

The blast radius is proportional to how common the affected field is across the client base, not to how often the buggy screen is used — a field populated for nearly every active record means nearly every active record is one click away from losing it.

Why "build the whole row, then save it" quietly breaks the moment two screens share it

Building an entire row from a client object and writing all of it works fine as long as every caller of that function genuinely means to set every field — which is true for a comprehensive edit form and false for almost anything else. In JavaScript, a field a caller never touched shows up as `undefined`, and `undefined` disappears entirely when the resulting object is serialized to JSON — but a NESTED object built by unconditionally reading several `undefined` source fields into it doesn't disappear at all; it becomes a real, populated (if empty-valued) object, and that object reaches the database as a genuine value to write, overwriting whatever was there before. A function correct for a full-record save becomes actively destructive the moment anything narrower calls it, and nothing about calling it looks obviously wrong at the call site — the bug lives entirely inside the shared function's own assumption about what "no value provided" should mean.

How Centriu Run closed the gap with a save path that only touches what changed

The defect surfaced through a systematic audit of all 13 screens under Run's infrastructure settings — described in the audit's own summary as looking for problems worse than the classic empty-shell pattern (fake data, decorative buttons that do nothing), and finding exactly that: real, working screens with defects that were actively harmful rather than merely incomplete. The most severe of them: a "Save data" button on two specific screens (an org-level strategic overview and a deal-intelligence panel) each save exactly 4 numeric and categorical fields relevant to their own purpose. Neither screen touches a client's contact details, address, social handles, or brand assets at all — but both routed their save through the same shared update function used everywhere else in the client-management area, and that function's existing behavior was to reconstruct the ENTIRE client record from whatever was passed in, filling in defaults for anything missing.

Measured directly against the organization's real client data: 22 of 23 active clients had a populated contact-information field. Because the shared function unconditionally rebuilt that field (along with social accounts and address) from source fields that these two specific screens never populate, every single click of "Save data" on either screen was silently erasing contact info, address, social handles, logos, brand colors and the client's legal name for whichever client was open at the time — regardless of how carefully the person clicking save had filled in the 4 fields the screen actually shows. Notably, the file's own pre-existing code already carried a comment warning about exactly this danger, attached to a different, narrower function — the warning existed in the codebase, but the generic path everything else actually used remained exposed.

The fix replaces that generic path, for updates specifically, with a function that checks — field by field, using a direct existence check rather than inferring intent from a value — whether each source field was actually present in the update request, and includes the corresponding database column only when it was. For the nested groups (contact info, social accounts, address), the same discipline applies at the group level: the group is only reconstructed, and only sent, when at least one of its own component fields was actually present in the request; when none were, the entire group is omitted from the update, leaving whatever the database already holds untouched. The one documented exception, called out directly in the fix's own comment: a caller that intentionally edits only ONE field within a nested group (say, only email inside contact info) will still overwrite that group's sibling fields, which is precisely why the single existing caller that legitimately edits those blocks — the full client-editing form — is confirmed to continue sending the complete object for any group it touches, exactly as it always has.

What is actually built today

A dedicated partial-update path that includes a database column in a save only when its corresponding source field was actually present in the incoming request — not merely non-empty, but explicitly present.

Nested field groups (contact info, social accounts, address) reconstructed and sent only when at least one of their own component fields was present in the request — otherwise omitted entirely, leaving the stored value untouched.

The narrow, 4-field save screens (the strategic overview and deal-intelligence panel) now genuinely touch only those 4 fields in the database, with zero effect on any other part of the client record.

The one legitimate caller that edits contact info, social accounts or address in full (the complete client-editing form) confirmed unchanged — it already sends the complete object for any group it touches.

The defect measured directly against real production data before the fix (22 of 23 active clients with populated contact information) rather than treated as a purely theoretical risk.

The dangerous, full-record-rebuild function kept in place for the one case it was always correct for — a genuine full-record insert or comprehensive edit — rather than removed outright and rebuilt from scratch.

Updating a deal's expected complexity without touching anything else (illustrative scenario, not a real client)

Someone opens the deal-intelligence panel for an existing client and changes only the expected-complexity field before saving. Before the fix, that single field change would have silently rewritten the client's entire contact block, address and brand assets back to blank defaults the moment the save request reached the database — even though none of those fields were ever shown on that screen. After the fix, the update touches only the one column that actually changed, and everything else on the client's record remains exactly as it was.

What changes operationally

A narrow, purpose-built save screen can no longer silently destroy data it was never designed to touch in the first place — the blast radius of a save is now limited to the fields that screen actually edits, matching what anyone using it would reasonably expect. And because the fix is a shared function used by the update path generically, any future screen built the same way inherits the same protection automatically, rather than needing its own bespoke fix the next time a narrow screen is added.

When this is not the right fit

A team hoping to intentionally clear a single field within a nested group (say, removing only a client's phone number while leaving email and WhatsApp untouched) will find that the current design doesn't support that as a narrow, single-field operation — editing any field within contact info, social accounts or address still goes through the full client-editing form, which sends the complete group. This fix specifically closes an unintended, silent overwrite; it isn't a general-purpose partial-field-clearing feature for nested data.

A record built from a value vs. a record built from what was actually sent

A save function that rebuilds a record entirely from a client object treats "undefined" and "explicitly empty" as if they carry no distinction worth preserving — reasonable for a full-record save, silently destructive for anything narrower that reuses it. Centriu Run's fix draws that distinction explicitly: a field is only ever written when it was actually present in the request, so a screen that only ever meant to touch 4 fields can no longer accidentally rewrite the other twenty just by existing.

Related systems

Main system: Centriu Run.

What it does NOT do

  • Does not let a narrow, purpose-built save screen affect any database column outside the fields it actually edits — the partial-update path includes a column only when its source field was actually present in the request.
  • Does not reconstruct a nested field group (contact info, social accounts, address) unless at least one of its own component fields was present in the request — an untouched group is never sent, and never overwrites what's already stored.
  • Does not remove or replace the full-record-rebuild function outright — it remains in place for the one case it was always correct for, a genuine full-record insert or comprehensive edit.
  • Does not treat this fix as unmeasured or theoretical — the exposure was confirmed directly against real client data (22 of 23 active clients with populated contact information) before and after the change.
  • Does not support clearing a single field within a nested group as an isolated partial operation — editing any field within contact info, social accounts or address still goes through the full client-editing form, which sends the complete group.
  • Does not change the behavior of the one caller that legitimately edits full contact/social/address blocks — that caller already sent, and continues to send, the complete object for any group it touches.

Security and governance

The partial-update discipline reduces the blast radius of any future narrow save screen built the same way, since a column is only ever written when its source field is genuinely present in the request. Any personal or business data referenced in a client record remains subject to Brazil's LGPD (Law No. 13,709/2018). Full detail on access control lives at /governanca and /iso.

Pricing and contracting

Available by monthly subscription, with tiered plans. Values and terms come from the official pricing table at /precos (Centriu's central source — never restated here).

Frequently asked questions

What was the actual measured impact of this defect?

Two screens saving only 4 unrelated fields were, on every save, silently erasing contact info, address, social accounts, logos, brand colors and legal name — measured against real data, 22 of the organization's 23 active clients had populated contact information at risk.

Why didn't this show up as an obvious error?

The save itself succeeded from the database's point of view — a normal update happened, just one that included unintended default values for fields the affected screens never meant to touch.

How does the fix know which fields to actually include in an update?

It checks, field by field, whether the source field was genuinely present in the incoming request — not merely whether it has a value — and includes the corresponding database column only when it was.

What about grouped fields like contact info or address?

A nested group is only reconstructed and sent when at least one of its own component fields was present in the request. If none were, the entire group is omitted, and the stored value is left untouched.

Can I still clear just one field inside a group, like removing only a phone number?

Not as an isolated operation today — editing any field within contact info, social accounts or address goes through the full client-editing form, which sends the complete group for any block it touches.

What does Centriu Run cost?

It is sold by subscription with a published starting price — exact current values are on the central pricing page.

See how Centriu Run protects client data from partial-update overwrites

Reach our commercial team directly, or leave your details below — we'll follow up with guidance for your case.

Sources

  1. Centriu Run — public product page — Centriu, 2026-07-20 · link(primária)
  2. Centriu Run — public factsheet (API, JSON) — Centriu, 2026-07-21 · link
  3. Law No. 13,709/2018 — Brazil’s General Data Protection Law (LGPD) — Presidência da República (Brazil), 2018-08-14 · link

Last material update on .

By · AI-assisted production, with human review