Support can no longer correct votes by erasing intent

Today's work in Ultimate Porra looked spread across unrelated fixes.

The live home view refreshing better.

Knockout cards resolving the right teams more reliably.

Goal-difference rules being corrected.

The backoffice gaining better filters and more precise editing.

Seen separately, that looks like maintenance.

Seen together, a more serious product decision appears:

correcting a pool can no longer mean touching data bluntly and hoping the user's intent survives.

The problem was not only getting the math right

In a real prediction product, three different truths coexist:

Layer What it represents What breaks if it gets mixed with the others
Official result What the tournament ultimately confirmed Recalculating points from unresolved teams or incomplete rules
Saved vote What a person actually meant to submit Losing valid fields through partial saves or over-aggressive auto-correction
Support action The exceptional intervention to fix one case Turning targeted help into a silent overwrite or a bulk reset

The system was getting dangerously close to mixing those layers.

If a partial preview save could overwrite fields that were already valid, if an admin correction could behave like a batch propagation, or if automatic validation could silently clear a choice, the app stopped protecting votes and started “reconstructing” them from the outside.

That is convenient in the short term.

But for a product with leaderboards, bonuses, and dynamic brackets, it is also a way to manufacture distrust.

Correction stopped looking like a reset

The strongest decision from the day was this:

support fixes a case; it does not rewrite the whole system.

That pushed several changes in the same direction:

  • admin corrections now require explicit confirmation;
  • the logic stopped allowing corrections to behave like bulk operations;
  • full vote resets stopped being treated as a valid escape hatch;
  • and preview editing started preserving fields that were already correct when a form does not submit the whole structure.

That combination matters more than it looks.

It is not just “more validation”.

It changes the support model from rebuilding state to preserving original intent and touching only the wrong piece.

Partial saves stopped being a silent threat

There was an interesting tension here.

Ultimate Porra's preview is no longer a tiny form: it now carries champion, runner-up, top scorer, surprise team, and group-level reads that later feed brackets and bonuses.

Once that surface grows, saving from a partial view stops being harmless.

If the system interprets “this form did not send the field” as “this field must be cleared”, the product punishes the user for the shape of the UI rather than for their decision.

That is why saving changed its rule:

  • omitted data is not destroyed by default;
  • invalid data is communicated;
  • and anything that needs human correction is separated from what can be recalculated automatically.

The lesson is not specific to a pool app.

In any product with long forms and derived rules, a partial submit should not behave like system amnesia.

The official tournament had to become an explicit dependency

The way teams, brackets, and point feedback get resolved also changed.

It was no longer enough to have nice cards or live results arriving on the home page.

The app needed a stricter relationship between:

  1. the official standings,
  2. the canonical identity of teams,
  3. the scoring logic,
  4. and the visible explanation of why a prediction is worth what it is.

That is the deeper pattern.

As long as tournament reality enters from one side and the UI explains from another, small lies appear:

  • a bracket shows a team name that is still ambiguous;
  • a goal-difference vote is scored with an incomplete rule;
  • one panel shows the new state while another still carries the previous one.

Today's work pushed the opposite:

if the official tournament moves one piece, team resolution, scoring, and public reading have to move as one chain.

The backoffice stopped being only an emergency door

The other important signal was the change in the admin tool.

It did not grow in order to “do more”.

It grew in order to do less damage per action.

Filters by competition, pool, phase, and country are not visual luxury.

They force a correction to happen with enough context before anything is touched.

Separating preview edits from per-match vote edits points in the same direction: not all predictions live at the same scale, and they should not be corrected with the same gesture.

Once support matures, the question stops being “what permissions does it have”.

It becomes:

how easy is it to correct exactly one thing without accidentally moving three more?

A serious pool product needs memory, not reflexes

The strongest idea from the day is this:

a prediction product does not become trustworthy just because it can calculate points.

It becomes trustworthy when it can distinguish between what happened, what someone meant to vote for, and what an administrator is actually allowed to correct.

If those three layers collapse into each other, the product feels fast but stops being credible.

If they stay separate, support stops behaving like manual reset and starts looking like precision work.

That is where a pool app stops being a form with a leaderboard and starts behaving like a system that respects history, context, and intent.

Part of my product and platform notes. Follow the blog or contact me.