Skip to content

fix(data-integrity): keep controlled value synchronization document-atomic #200

Description

@seonghobae

Buyer-visible data-integrity boundary

Protected shipped truth is exact main@3b38ead2d00f44eb578d0689087b9293b3dabe1e. The original defect was that controlled value synchronization could call TipTap setContent(..., false) without first proving the requested complete replacement survives the active ProseMirror transaction policy unchanged. A deterministic appendTransaction transformation or a later live-only/stateful divergence could therefore leave the editor on a third document rather than the previous local document or requested controlled document.

This is Inkspan-local controlled-document integrity only. Hosts/plugins may enforce editor-local transaction policy; Inkspan must not bypass that policy or report an unapplied controlled value as ordinary onChange success. No transport, persistence, authn/authz, tenancy, credentials, model/provider, network, migration, retention, deployment, durable-audit, Yjs, or durable PDF authority moves into Inkspan.

Canonical owner and implemented contract

Draft PR #201 / branch fix/atomic-controlled-sync-200 is the sole active writer for src/components/CwlEditor.tsx and this controlled-value synchronization boundary. Protected shipped truth and the frozen v0.6.0 source candidate remain main@3b38ead2d00f44eb578d0689087b9293b3dabe1e; current exact Draft head is f582e7cfd423cc2f55b2a2adc36a6201186b31ba. Fresh canonical comparison resolves protected main as the merge base, 19 ahead / 0 behind, across exactly eight standalone-editor source/test paths:

  • src/components/CwlEditor.controlledValueComposition.test.tsx
  • src/components/CwlEditor.editabilityComposition.test.tsx
  • src/components/CwlEditor.runtimeEditable.test.tsx
  • src/components/CwlEditor.runtimeToolbarVisibility.test.tsx
  • src/components/CwlEditor.tsx
  • src/components/CwlEditorControlledValuePolicy.test.tsx
  • src/components/editorControlledValueSync.ts
  • src/components/editorDocumentValue.runtime.test.tsx

Prior issue snapshots naming 43d4f00c7cae657c54f8fd9c97d41a315bfbb350 or 343d4132574f4cb20eb561928df034154609bab7 as current are predecessor prose and their workflow/review evidence does not transfer.

Current production parses the requested serialized value once, constructs the complete replacement against captured editor state, preflights it through current ProseMirror transaction application, and refuses deterministic filtering/transformation before live mutation. A structural postcondition remains defense in depth. If a stateful/non-deterministic policy diverges only during live dispatch or an observer throws after local mutation, Inkspan attempts best-effort restoration of the captured local editor state and keeps the failure local/payload-redacted. Accepted controlled updates, Markdown/HTML mode-aware parsing, read-only host-control semantics, selection/editor lifecycle, SSR/hydration, native-form behavior, and package consumers remain preserved.

The same canonical #201 lane also owns the adjacent finite runtime contracts for editable (#252), hideToolbar (#263), value / defaultValue (#267), and formResetValue (#271). Its current head additionally contains two composition-boundary repairs: when local composition is active and edit authority is revoked, the editor drains compositionend before setEditable(false) so composition state is not stranded; and when a controlled host value changes during composition, Inkspan defers replacement and applies the latest host value after composition ends. Those lifecycle repairs do not broaden or weaken the controlled-value atomicity contract. Native form-reset policy atomicity remains separately owned by Draft #199; #380 remains the stacked browser-harness/test owner. Do not create overlapping source writers.

Test-first / exact-current evidence

  • Controlled-value RED 9bb0f03112e5d616a08cad81b80aaf953ac7ccc3: CI 31482959890 failed at the intended real ProseMirror appendTransaction transformation regression while Security 31482959919 and SAST 31482959928 passed.
  • Current exact fix(data-integrity): keep controlled value sync atomic #201 head f582e7cfd423cc2f55b2a2adc36a6201186b31ba carries the complete controlled-value repair, adjacent standalone runtime-boundary fixes, editability/composition transition repair, and controlled-value-during-composition deferral; predecessor workflow/review evidence does not transfer.
  • CI 32654492013 is completed / success for this exact source head. Its build/test job checked out f582e7cfd423cc2f55b2a2adc36a6201186b31ba, passed 150 test files / 843 tests, reported 100% aggregate instrumented statement/branch/function/line coverage, passed packed-package verification, and completed the demo build.
  • Security Scan 32654492010 is aggregate status-success but non-passing for merge/release acceptance: security jobs consumed synthetic PR-merge source 4ffa57cd216d7b1ec7212fad297f86fa863d0909, and Dependency Review was skipped. The existing foreign owner repair is ContextualWisdomLab/.github PR #897.
  • SAST Semgrep 32654492044 is aggregate status-success but non-passing for merge/release acceptance: Semgrep reported zero findings while scanning synthetic PR-merge source 4ffa57cd216d7b1ec7212fad297f86fa863d0909 rather than the submitted source head. The existing foreign exact-source repair is ContextualWisdomLab/.github PR #941.
  • Formal submitted review state remains one predecessor-head Cursor COMMENTED review on 9fd9a281073da390409ed368fcc9311c8d501411, explicitly non-approving; qualifying exact-head approving reviews are 0.
  • Unresolved inline review threads are 0; GitHub reports the Draft mechanically mergeable.
  • Stacked browser-assurance PR test(input): add multilingual browser input baseline #380 is non-destructively stacked on this exact parent; its current exact head is e807c522df71886d8a5c13360d99aea41bd8a1c3, 24 commits ahead / 0 behind relative to fix(data-integrity): keep controlled value sync atomic #201 with the exact parent as merge base and a net seven-file browser harness/spec/config delta. The child now makes all committed *.browser.spec.ts journeys discoverable by each desktop engine project and fails closed on non-loopback requests in the newly discovered native-form/composition assurance. Exact child-head workflows remain absent, so child evidence is non-passing.

Repository CI success is not qualifying independent approval and cannot cure wrong-checkout, skipped, absent, synthetic-source, predecessor, or otherwise non-current evidence. Pending, queued, skipped, cancelled, absent, neutral, failed, stale, predecessor, status-only, synthetic-source, or model-only evidence remains non-passing.

Integration boundary

The controlled-value defect is active-PR repaired behavior only and is not protected-main shipped truth. Keep this issue open until #201 integrates under then-live governance. Keep #201 Draft/unmerged while #118 owns exact protected v0.6.0 tag/publication/provenance/digest operational acceptance and while qualifying independent latest-push approval plus every applicable live exact-source workflow/governance gate remain incomplete. Before any lifecycle transition refetch exact #201 head/live base, ancestry/mergeability, live rules/permissions, formal reviews/threads, and every applicable repository/central workflow. Do not self-approve, transfer predecessor evidence, weaken gates, move protected main, create a competing CwlEditor.tsx writer, or fabricate release identity.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: apiAPI, protocol, event, or external contractarea: ci-cdCI, GitHub Actions, checks, release, or supply chainarea: securitySecurity boundary, hardening, or vulnerability preventionpriority: mediumNormal-priority or P2 workstatus: triagedOpen issue has an organization taxonomy assignmenttype: bugDefect or incorrect behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions