Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
481e581
chore(deps): bump @tiptap/core from 2.27.2 to 3.30.4
dependabot[bot] Sep 3, 2026
6c9db08
build(deps): patch transitive security advisories
seonghobae Sep 4, 2026
a334084
build(deps): migrate TipTap stack to v3
seonghobae Sep 4, 2026
87b5fef
docs: record the editor security migration
seonghobae Sep 4, 2026
870c2c3
fix(ci): preserve Python boundary coverage
seonghobae Sep 4, 2026
93fd077
fix(ci): restore full Python PR matrix
seonghobae Sep 4, 2026
84bc0e2
Merge remote-tracking branch 'origin/main' into codex/security-transi…
seonghobae Sep 4, 2026
d942322
test(ci): cover event-specific Python matrix
seonghobae Sep 4, 2026
ca31a26
test(ci): bind Python matrix to event
seonghobae Sep 4, 2026
6b059f2
fix(deps): repair TipTap React declarations
seonghobae Sep 4, 2026
3d4efaa
repair(ci): keep security lane out of Python policy
seonghobae Sep 4, 2026
378e030
test(office): align Python support contract with event matrix
seonghobae Sep 4, 2026
2f7455d
chore(ci): join security prerequisite for verification
seonghobae Sep 4, 2026
4378877
chore(ci): join TipTap security prerequisite
seonghobae Sep 4, 2026
6207d78
chore(ci): synchronize protected main
seonghobae Sep 4, 2026
85c7765
fix(types): isolate packed declarations from TipTap React
seonghobae Sep 4, 2026
b444332
docs(tiptap): tighten migration evidence
seonghobae Sep 4, 2026
202084d
fix(collaboration): declare v3 runtime binding
seonghobae Sep 4, 2026
d1f2753
fix(collaboration): ship y-tiptap peer runtime
seonghobae Sep 4, 2026
b229572
feat!: version the TipTap 3 migration
seonghobae Sep 4, 2026
6d51f5c
docs: align 0.7 release authority
seonghobae Sep 4, 2026
ac0b7bd
fix: identify TipTap v3 in demo
seonghobae Sep 4, 2026
637b910
test: tighten release contract guards
seonghobae Sep 4, 2026
7a769c7
test(office): reject unsupported CI matrix values
seonghobae Sep 7, 2026
740ffb4
test(office): resolve the CI matrix instead of pinning its syntax
seonghobae Sep 7, 2026
a7f8109
test(ci): resolve the office matrix contract instead of pinning its text
seonghobae Sep 7, 2026
8f39454
Merge remote-tracking branch 'origin/fix/office-python-event-matrix-c…
seonghobae Sep 7, 2026
95b2c63
test(ci): bind Office matrix payloads to the PR event predicate
seonghobae Sep 8, 2026
f44b588
test(office): reject unsupported matrix event predicates
seonghobae Sep 8, 2026
6352283
test(ci): inherit resolved Office matrix contracts
seonghobae Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ${{ github.event_name == 'pull_request' && fromJSON('["3.14"]') || fromJSON('["3.11", "3.12", "3.13", "3.14"]') }}
python-version: ["3.11", "3.12", "3.13", "3.14"]
defaults:
run:
working-directory: office
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Historical release entries from **0.1.0 through 0.5.27** are preserved verbatim
- Restored a visible `:focus-visible` indicator on the editable textbox, mapped it to `CanvasText` in forced-colors mode, and suppresses that interactive focus chrome under `@media print`; dependency-locked Chromium, Firefox, and WebKit acceptance exercises the packed stylesheet on the real `role="textbox"` surface.

### Security
- Patched an editor dependency vulnerability while preserving the existing formatting, collaboration-presence, safe-link, and exact document-restore behavior.
- Raised workspace-wide transitive development-tool overrides for `fast-uri`, `nanoid`, and `postcss` to patched minimums, keeping the lockfile audit clean without changing runtime package authority.
- Normalized isolated package-verifier temporary roots before containment checks on macOS.

Expand Down
4 changes: 2 additions & 2 deletions docs/atomic-envelope-restore.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Restore performs these operations in order:
4. validate the Inkspan envelope schema identifier and version;
5. detach and deeply freeze the document JSON;
6. reconstruct and recursively check the complete document against the active ProseMirror schema;
7. dispatch one TipTap `setContent(..., false)` replacement;
7. dispatch one TipTap `setContent(..., { emitUpdate: false })` replacement;
8. verify that the resulting active document is structurally equal to the prepared document.

Any failure before step 7 leaves the current document unchanged. A ProseMirror transaction filter may reject a schema-valid replacement at step 7; Inkspan then throws `DocumentEnvelopeRestoreError` and never reports the operation as successful. Inkspan's built-in safe-link and inline-image policies reject unsafe replacements without changing the document.
Expand Down Expand Up @@ -87,7 +87,7 @@ The helper adds no database, credential, environment-variable, transport, provid

## Primary references

- [TipTap v2 `setContent` command](https://v2.tiptap.dev/docs/editor/api/commands/content/set-content)
- [TipTap `setContent` command](https://tiptap.dev/docs/editor/api/commands/content/set-content)
- [ProseMirror `PluginSpec.filterTransaction`](https://prosemirror.net/docs/ref/#state.PluginSpec.filterTransaction)
- [ProseMirror `Schema.nodeFromJSON()` and `Node.check()`](https://prosemirror.net/docs/ref/#model.Schema.nodeFromJSON)
- [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format](https://www.rfc-editor.org/rfc/rfc8259)
Expand Down
4 changes: 2 additions & 2 deletions docs/collaboration.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ editor or coupling its core package to organization infrastructure.

## Primary references

- [TipTap v2 Collaboration](https://v2.tiptap.dev/docs/editor/extensions/functionality/collaboration)
- [TipTap v2 Collaboration Cursor](https://v2.tiptap.dev/docs/editor/extensions/functionality/collaboration-cursor)
- [TipTap Collaboration](https://tiptap.dev/docs/editor/extensions/functionality/collaboration)
- [TipTap Collaboration Caret](https://tiptap.dev/docs/editor/extensions/functionality/collaboration-caret)
- [Yjs Awareness and Presence](https://docs.yjs.dev/getting-started/adding-awareness)
- [WAI-ARIA `status` role](https://www.w3.org/TR/wai-aria-1.2/#status)
- [WCAG relative luminance definition](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html)
22 changes: 14 additions & 8 deletions docs/doctoring/tiptap-v2-prosemirror-paste-adapter.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# TipTap v2 ProseMirror paste adapter
# TipTap ProseMirror paste adapter

## Decision

Inkspan registers SafeClipboard through a TipTap v2 extension whose
Inkspan registers SafeClipboard through a TipTap v3 extension whose
`addProseMirrorPlugins` hook returns a ProseMirror `Plugin` with a
`transformPastedHTML` editor property. That property receives rich clipboard
HTML before ProseMirror parses it into an editor document.
Expand All @@ -16,7 +16,7 @@ retention, migration, and model-use policy.

## Root cause

Inkspan locks `@tiptap/core 2.27.2`. The first implementation placed a
Inkspan previously locked `@tiptap/core 2.27.2`. The first implementation placed a
`transformPastedHTML` field directly on a TipTap extension configuration and its
unit tests invoked that field manually. That appeared consistent with current
TipTap documentation, but it did not prove registration in the installed v2
Expand All @@ -28,7 +28,13 @@ plugins. It does not collect an arbitrary direct extension
`transformPastedHTML` field into editor props. The locked source is authoritative
for the installed runtime, while current mutable documentation is useful design
context but not evidence that an API existed in this historical dependency
version.
version. Inkspan now locks the coherent TipTap 3.30.4 package family; the same
real-pipeline tests prove that the adapter remains registered after migration.
The published `@tiptap/react` 3.30.4 ESM and CommonJS declarations qualify four
`Editor` references through an internal namespace that does not export that
type. The lockfile applies one bounded patch to those declarations, and the
packed strict-TypeScript consumer check prevents the broken public types from
shipping.

The practical result was a false assurance gap: direct sanitizer unit tests were
green, but the real `editor.view` paste pipeline had no SafeClipboard
Expand Down Expand Up @@ -57,7 +63,7 @@ result is not completion evidence for a later exact head.

## Ordering and residual host boundary

TipTap v2.27.2 sorts extension priorities from higher to lower when resolving
TipTap v3.30.4 sorts extension priorities from higher to lower when resolving
extensions and again when assembling ProseMirror plugins. ProseMirror checks
plugin-provided editor properties in plugin order. SafeClipboard therefore uses
a deliberately low priority so ordinary host transforms run first and the
Expand Down Expand Up @@ -107,6 +113,6 @@ TipTap GmbH. (n.d.). *Extension API*. TipTap Editor Docs. Retrieved August 7,
2026, from
https://tiptap.dev/docs/editor/extensions/custom-extensions/create-new/extension

TipTap GmbH. (2025). *ExtensionManager.ts (Version 2.27.2)* [Source code].
GitHub. Retrieved August 7, 2026, from
https://github.com/ueberdosis/tiptap/blob/%40tiptap/core%402.27.2/packages/core/src/ExtensionManager.ts
TipTap GmbH. (2026). *ExtensionManager.ts (Version 3.30.4)* [Source code].
GitHub. Retrieved September 4, 2026, from
https://github.com/ueberdosis/tiptap/blob/%40tiptap/core%403.30.4/packages/core/src/ExtensionManager.ts
Comment thread
seonghobae marked this conversation as resolved.
Outdated
4 changes: 2 additions & 2 deletions docs/imperative-envelope-persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Object and JSON-text inputs use `validateDocumentEnvelope()` and
`...Bytes` methods. Validation is non-mutating. Restore completes duplicate
object-name detection, resource checks, schema/version routing, hostile-value
detachment, and full active ProseMirror schema reconstruction before one
`setContent(..., false)` mutation. A failure leaves the current document
`setContent(..., { emitUpdate: false })` mutation. A failure leaves the current document
unchanged.

Successful restore suppresses normal change callbacks because loading an
Expand Down Expand Up @@ -216,5 +216,5 @@ metadata rather than extending the strict envelope with ad hoc fields.
- [W3C Web Cryptography API Recommendation](https://www.w3.org/TR/2017/REC-WebCryptoAPI-20170126/)
- [WHATWG Encoding Standard: UTF-8](https://encoding.spec.whatwg.org/#utf-8)
- [TipTap persistence guidance](https://tiptap.dev/docs/editor/core-concepts/persistence)
- [TipTap v2 `setContent`](https://v2.tiptap.dev/docs/editor/api/commands/content/set-content)
- [TipTap `setContent`](https://tiptap.dev/docs/editor/api/commands/content/set-content)
- [ProseMirror `Node.fromJSON`](https://prosemirror.net/docs/ref/#model.Node^fromJSON)
2 changes: 1 addition & 1 deletion docs/papers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ GFM table and strikethrough extensions.
as base64, which this module relies on so figures travel with the document and
remain readable by a downstream LLM. <https://datatracker.ietf.org/doc/html/rfc2397>
- **ProseMirror** (Marijn Haverbeke) — the MIT-licensed document model and
editing toolkit that TipTap v2 is built on. <https://prosemirror.net/>
editing toolkit that TipTap is built on. <https://prosemirror.net/>
23 changes: 10 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,16 @@
}
},
"dependencies": {
"@tiptap/core": "^2.27.2",
"@tiptap/extension-collaboration": "^2.27.2",
"@tiptap/extension-collaboration-cursor": "^2.27.2",
"@tiptap/extension-image": "^2.11.5",
"@tiptap/extension-link": "^2.11.5",
"@tiptap/extension-placeholder": "^2.11.5",
"@tiptap/extension-table": "^2.11.5",
"@tiptap/extension-table-cell": "^2.11.5",
"@tiptap/extension-table-header": "^2.11.5",
"@tiptap/extension-table-row": "^2.11.5",
"@tiptap/pm": "^2.11.5",
"@tiptap/react": "^2.11.5",
"@tiptap/starter-kit": "^2.11.5",
"@tiptap/core": "3.30.4",
Comment thread
seonghobae marked this conversation as resolved.
"@tiptap/extension-collaboration": "3.30.4",
"@tiptap/extension-collaboration-caret": "3.30.4",
Comment thread
seonghobae marked this conversation as resolved.
"@tiptap/extension-image": "3.30.4",
"@tiptap/extension-link": "3.30.4",
"@tiptap/extension-table": "3.30.4",
"@tiptap/extensions": "3.30.4",
"@tiptap/pm": "3.30.4",
"@tiptap/react": "3.30.4",
Comment thread
seonghobae marked this conversation as resolved.
"@tiptap/starter-kit": "3.30.4",
"marked": "^15.0.6",
"turndown": "^7.2.0",
"turndown-plugin-gfm": "^1.0.2",
Expand Down
70 changes: 70 additions & 0 deletions patches/@tiptap__react@3.30.4.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
diff --git a/dist/index.d.cts b/dist/index.d.cts
index 331a7a57ec202e68d67e2c692c4b1bedb928c6cc..5fc696b31890d469d3b1cd07bc2f860f5cfc782e 100644
--- a/dist/index.d.cts
+++ b/dist/index.d.cts
@@ -402,7 +402,7 @@ declare function ReactWidgetRenderer<P extends Record<string, any> = object>(com
*/
type TiptapContextType = {
/** The Tiptap editor instance. */
- editor: index_d_exports.Editor;
+ editor: Editor;
};
/**
* React context that stores the current editor instance.
@@ -459,18 +459,18 @@ declare const useTiptap: () => TiptapContextType;
* }
* ```
*/
-declare function useTiptapState<TSelectorResult>(selector: (context: EditorStateSnapshot<index_d_exports.Editor>) => TSelectorResult, equalityFn?: (a: TSelectorResult, b: TSelectorResult | null) => boolean): TSelectorResult;
+declare function useTiptapState<TSelectorResult>(selector: (context: EditorStateSnapshot<Editor>) => TSelectorResult, equalityFn?: (a: TSelectorResult, b: TSelectorResult | null) => boolean): TSelectorResult;
type TiptapWrapperEditorInstanceProps = {
/**
* The editor instance to provide to child components.
* Use `useEditor()` to create this instance.
*/
- editor: index_d_exports.Editor;
+ editor: Editor;
} | {
/**
* @deprecated Use `editor` instead. Will be removed in the next major version.
*/
- instance: index_d_exports.Editor;
+ instance: Editor;
};
/**
* Props for the `Tiptap` root/provider component.
diff --git a/dist/index.d.ts b/dist/index.d.ts
index 1ea46992a97b34957359edd7e70186dfa060fe87..1aeb997fa11b4dfb57604596dded3f54f2c3e270 100644
--- a/dist/index.d.ts
+++ b/dist/index.d.ts
@@ -402,7 +402,7 @@ declare function ReactWidgetRenderer<P extends Record<string, any> = object>(com
*/
type TiptapContextType = {
/** The Tiptap editor instance. */
- editor: index_d_exports.Editor;
+ editor: Editor;
};
/**
* React context that stores the current editor instance.
@@ -459,18 +459,18 @@ declare const useTiptap: () => TiptapContextType;
* }
* ```
*/
-declare function useTiptapState<TSelectorResult>(selector: (context: EditorStateSnapshot<index_d_exports.Editor>) => TSelectorResult, equalityFn?: (a: TSelectorResult, b: TSelectorResult | null) => boolean): TSelectorResult;
+declare function useTiptapState<TSelectorResult>(selector: (context: EditorStateSnapshot<Editor>) => TSelectorResult, equalityFn?: (a: TSelectorResult, b: TSelectorResult | null) => boolean): TSelectorResult;
type TiptapWrapperEditorInstanceProps = {
/**
* The editor instance to provide to child components.
* Use `useEditor()` to create this instance.
*/
- editor: index_d_exports.Editor;
+ editor: Editor;
} | {
/**
* @deprecated Use `editor` instead. Will be removed in the next major version.
*/
- instance: index_d_exports.Editor;
+ instance: Editor;
};
/**
* Props for the `Tiptap` root/provider component.
Loading
Loading