feat(templates): immutable records disable Edit up front - GET /{id}/mutable pre-check + read-only pages - #6526
Merged
Merged
Conversation
…nt - GET /{id}/mutable pre-check + read-only pages
The immutable/immutableWhen 409 on PUT/DELETE stays the authoritative
guard, but the generated UI used to offer Edit/Save and only fail on
the write. Each generated controller (power/partner/my) now exposes a
GET /{id}/mutable utility endpoint (shared isMutable extracted from
requireMutable; partner/my scoped through requireMine), and every
Harmonia surface consumes it:
- manage form + document pages ask the pre-check on edit load and
force the read-only preview mode with a "Read-only" title badge, so
a directly typed /edit URL opens read-only; the preview footer's
Edit button hides. The pre-check fails OPEN (an outage must not
lock the UI - the server still refuses the write).
- manage list + master browse views hide row-menu Edit/Delete and
disable the details-pane buttons via a baked isRowImmutable(row)
computed from the row's status FK against the generation-time
immutable ids - no per-row API calls, and no drift (generated from
the same model attrs as the server gate).
- partner/my form + document pages disable their controls
(fieldset :disabled), hide Save/Delete/item actions and the chat
composer, and show the same badge.
IntentEmissionCoverageIT asserts both layers: the endpoint + page
tokens, and mutable=false over REST for a POSTED/append-only record
vs mutable=true while DRAFT.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
delchev
force-pushed
the
feat/immutable-ui-precheck
branch
from
August 5, 2026 09:19
05a95f3 to
b8599cf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
immutable:/immutableWhen:entities used to offer Edit → Save in every generated view and only refuse on the write (PUT/DELETE→ 409 "immutable in its current status"). The 409 stays exactly as it was — the authoritative guard — but the generated UI now knows up front:1. Utility API. Each generated controller — power
EntityController,EntityPartnerController,EntityMyController— exposesGET /{id}/mutable→{"mutable": true|false}, backed by a sharedisMutable(entity)extracted fromrequireMutable(single source of truth, no duplicated logic). The partner/my variants resolve the record throughrequireMine(id), so a foreign record stays the same 404. Emitted only when the entity declares immutability.2. All Harmonia templates consume it (not only the document layout):
/editURL is forced into the existing read-only preview mode, a warning Read-only badge appears in the title bar (tooltip: "corrections go through the workflow"), and the preview footer's Edit button hides. The pre-check fails open — an outage must not lock the UI; the server still refuses the write.isRowImmutable(row)computed from the row's status FK against the generation-time immutable status ids — no per-row API calls, and no drift (generated from the same model attrs as the server gate, thevalidationSchemaprecedent). Preview always stays — the record remains readable.fieldset :disabled, hide Save/Delete, item Add/Edit/Delete and the chat composer, and show the same badge.Entities without immutability generate byte-identical output (all additions are Velocity-guarded).
Tests
IntentEmissionCoverageITextended on both layers per the emission-testing contract:/{id}/mutable+isMutable(in the generated controllers, the pre-check inEntryFormPage.js,isRowImmutableinEntryMasterPage.js;mutable=falseover REST for the POSTED entry and the append-only snapshot,mutable=truewhile DRAFT.Docs
engine-intent/CLAUDE.mdimmutability bullet updated with the pre-check contract. A dirigible.io note (help page forimmutableWhen) follows after merge; no intentfile.org change — the DSL grammar is untouched.🤖 Generated with Claude Code