Notes

Protected drafts and bulletproof updater

An incomplete JSON from the AI corrupted a draft: a stricter parser and validation

2 min read

A day of fine-grained maintenance: a draft corrupted by an AI response and the decision of how the product will be updated for clients.

An incomplete response corrupted a draft

A response from MiniMax arrived as an incomplete JSON, degenerating at the end. The rewrite fallback accepted it as Markdown and the polisher confirmed the content before validating the next response. Result: a partial draft associated with a failed execution.

The fix is twofold: the parser now rejects incomplete JSON wrappers instead of saving them as content, and the polisher computes and validates rewriting and metadata before applying any changes. Corrupted draft deleted, execution retried successfully, and a Lorem ipsum test article removed from the schedule.

Updates without repository access

The decision of the day: separate panel, API and public frontend so that only the product core can be updated. Releases are distributed as private, immutable images, and a restricted host updater will handle backups, migrations, health checks and rollback without ever replacing the client's data, media or customised frontend.

From document to code

Within hours the decision has a technical foundation: installer target for the client with the base frontend included, updater daemon connected to the API, verification key included in the package, signed update manifest and updater socket mounted on the client's API. Along the way, the usual fixes: seeding the client's initial administrator, idempotent migration of the font validator, resolved compose routes and the GHCR image owner approved for publish.

Fire test: protected updater and cleanup

The evening was spent on end-to-end tests. A new fclean with root and exact domain confirmation: without typing the exact domain, nothing gets deleted. On pilot, the entire chain was verified: backup, migration, restart, rollback and preservation of the client's public website. Meanwhile, five fine-tuning fixes: image owner approved for publish, signed manifest published, socket mounted, compose metadata preserved during updates and GHCR credentials reaching the systemd service. The panel already shows its own version.

The button that wasn't calling anything

The agent added detection, confirmation and progress to the panel summary. The button was visible, but when pressed, no POST went out. It first blamed the native dialog and replaced it with a visible confirmation; still nothing. The real cause: onClick={() => void apply} instead of invoking apply(). Fixed the call and with errors visible in the panel. The lesson is noted: check the actual request and the callback before publishing a UX fix.

The client never sees the repository, but a new version arrives as controlled as a push: signed, verified and with rollback.

Other diary entries