Skip to content

feat: field operations and translation freshness (RFC-0041 step 3) - #96

Merged
Madraka merged 1 commit into
mainfrom
feat/fields-operations
Oct 23, 2026
Merged

Madraka merged 1 commit into
mainfrom
feat/fields-operations

Conversation

@Madraka

@Madraka Madraka commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Step 3 of RFC-0041's rollout (ADR-0043), built on #94 and #95.

Operations (@cloudhal/core-ts, src/fields-operations/)

  • The four operations:
    • rename_field;
    • change_field_type: a closed conversion table in @cloudhal/core-ts/fields; onInvalid: "clear" is required to drop values that do not convert;
    • set_field_localized;
    • remove_field.
  • How each runs:
    1. A dry run builds a report: per locale, with samples, and with the refusal when it would be refused.
    2. A "before" snapshot is taken; its id is the operation id.
    3. Phase A writes the definition with a migration marker.
    4. Phase B rewrites entries in batches of 200. Each entry is a CAS guarded on the marker, and the run resumes within a budget of 2,000 entries or 20 s per call.
    5. Phase C drops the marker behind a NOT EXISTS guard, then takes an "after" snapshot.
  • Only the draft graph changes; tests check that the published snapshot is untouched.
  • While it runs, resolveFields and a person's entry writes read through the marker, so their edit and the operation converge.
  • Revert puts back the earlier definition and the bodies nobody edited since. Edited entries are converted back and listed. Revert needs a finished operation.

Translation freshness (follow-up from #95)

  • When a write changes only non-localized values, translations that were up to date get their recorded source rev and hash moved forward in the same batch (store/source-forward.ts).
  • Node hashes are unchanged, so existing sites stay byte-identical.
  • Translations held by a release, or in other sites, are skipped.

API

  • POST /api/sites/:id/collections/:key/fields/operations (site:settings plus content:write), ?continue=<id>.
  • GET …/:operationId (content:read).
  • POST …/:operationId/revert.
  • Admin equivalents for the CLI's --remote.
  • New codes: operation_in_progress (409), field_values_unconvertible (422, with the report), field_operation_incomplete (409).

CLI: cloudhal fields rename|retype|localize|remove|continue|revert … [--dry-run] [--remote]. --dry-run also lists theme files that read fields.<key>.

Choices where the RFC was open

  • select → text writes option values, not labels.
  • When the old value also fits the new type, an entry a person edited mid-run keeps their value.
  • Operations do not check release holds, like the tags migration.

Tests

  • New operation suites on sqlite, D1 and DO SQLite: 82 in a filtered run.
  • CLI: 171/171.
  • fields-api, admin and route-scopes pass.
  • Typecheck, size check and MCP doc check are clean.
  • Locally the DO SQLite tail fails with EADDRNOTAVAIL (socket exhaustion); CI is the judge.

Changeset: minor (core-ts, api, cli).

🤖 Generated with Claude Code

- rename_field, change_field_type (closed conversion table, onInvalid
  "clear" to drop values), set_field_localized and remove_field: a dry
  run, a "before" snapshot, phase A (definition with a migration
  marker), phase B (entries in CAS-guarded batches of 200, resumable),
  phase C (marker dropped, "after" snapshot). Draft graph only;
  revertible. resolveFields and entry writes read through the marker
  mid-run.
- Changing only non-localized values on an original no longer marks
  its translations stale (store/source-forward.ts); node hashes are
  unchanged.
- API: /collections/:key/fields/operations (run, continue, status,
  revert; site:settings) and the admin equivalents for --remote.
- CLI: cloudhal fields rename|retype|localize|remove|continue|revert
  [--dry-run] [--remote].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
@Madraka
Madraka merged commit dcd6f08 into main Oct 23, 2026
4 checks passed
@Madraka
Madraka deleted the feat/fields-operations branch October 23, 2026 01:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant