Repository navigation
Sidebar page tree - #4
Merged
Merged
Conversation
* frontend and backend implementation
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jun 20, 2026
…o an admin field Convert the htmlEmbed node from same-origin raw-HTML execution to a sandboxed iframe (sandbox="allow-scripts allow-popups allow-forms", no allow-same-origin, srcdoc) with postMessage auto-resize (validated by event.source) and an optional manual height attr. The block now runs in an opaque origin and cannot reach the viewer's cookies/session/API, so it is safe for any member. Because the block is now harmless, remove the entire admin/role gating apparatus: drop htmlEmbedAllowed/canAuthorHtmlEmbed/stripDisallowedHtmlEmbedNodes/ collectHtmlEmbedSources and every role-based strip on the write paths (collab REST/MCP + socket, page create/duplicate, import x2, transclusion unsync), along with the now-unused WorkspaceRepo/UserRepo injections and the PageService.create callerRole param. Keep one strip: prepareContentForShare still removes htmlEmbed on the anonymous public-share read path when the workspace master toggle is OFF. The workspace settings.htmlEmbed toggle is now a plain feature switch (gates the slash-menu and share rendering); when ON the block is available to all members. Add settings.trackerHead: an admin-only raw HTML/JS analytics snippet injected verbatim into the <head> of public share pages only (ShareSeoController), for trackers that genuinely need same-origin. Admin-gated via the existing CASL Manage/Settings ability; never injected into the authenticated app shell. Closes security-review findings #1, #2, docmost#4, docmost#5, docmost#10 (and docmost#3 as a security issue). Co-Authored-By: Claude Opus 4.8 <[email protected]>
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jun 24, 2026
…ocmost#151 review) Review of docmost#158 (Request changes) — core logic verified correct; addressed the test-coverage + localization items: 1. i18n pluralization: the token-count keys were called with {count} but had one form, so ru-RU always rendered the genitive ("1 токенов"). Added _one/_other (en) and _one/_few/_many (ru: токен/токена/токенов) for both "Thinking… · {{count}} tokens" and "Thinking · {{count}} tokens"; de-duped the PR-added duplicate "Thinking" key. Call sites unchanged. 2. ReasoningBlock: new reasoning-block.test.tsx (4 branches: authoritative count wins / estimate fallback / header-only when count-but-no-text / body render). 3. Reasoning-token attribution: extracted the docmost#151 anti-double-count rule into a pure `reasoningTokensForPart(message)` (single reasoning part -> authoritative turn total; multiple/none -> undefined so each estimates). message-item uses it; removed the now-dead lastReasoningIndex reduce (review docmost#5). Unit-tested. 6. adopt-chat-id.ts: refreshed 3 stale `chatStreamStartMetadata` -> `chatStreamMetadata` comment references. 7. chat-markdown.test.ts: assert the export footer's `reasoning: N` line appears when reasoningTokens>0 and is absent at 0/undefined. Skipped optional docmost#4 (mantine useThrottledCallback): the manual throttle has two distinct exit paths (turn-end revert-to-null + the captured-total trailing emit) with no guarding test; remapping risks the streaming behavior — non-blocking. Client tsc clean; ai-chat suite green (171 tests). Co-Authored-By: Claude Opus 4.8 <[email protected]>
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jun 25, 2026
…he right one (docmost#159) The client sends the "current page" as { id, title } in the request body and the server echoed BOTH verbatim into the system prompt context and the getCurrentPage tool. id and title are independently attacker/desync-controllable (two tabs, stale navigation), so openPage.id could point at page B while openPage.title said "Page A" — the model then reported "updated Page A" while it actually edited page B (CASL still allowed it; the user has access). Red-team finding docmost#4. Resolve the open page ONCE against the DB via a new `resolveOpenPageContext`: workspace-scoped lookup + access check, returning the AUTHORITATIVE { id, title } (title from the DB row, never the client) or null (fail-closed) for a missing / foreign / inaccessible page. That validated value now feeds the system prompt, the getCurrentPage tool, AND the new-chat history origin (which previously did this validation inline, for the id only — now shared, and the title is fixed too). Tests: resolveOpenPageContext covers no-id, not-found, foreign-workspace, Forbidden, non-Forbidden-fault (fail-closed), the DB-title-wins-over-client case, and null-title coercion. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jun 27, 2026
…calize only page write paths (docmost#228) Must-fix (REAL DATA LOSS): - markdownToProseMirror is reused for COMMENT bodies (createComment/updateComment). It unconditionally canonicalized, so a comment carrying a standalone footnote definition ([^1]: text with no matching reference) had its whole footnotesList stripped (referenceIds.length===0 -> stripFootnotesListsDeep) — the text vanished. Fix: markdownToProseMirror no longer canonicalizes (content-preserving primitive); a new markdownToProseMirrorCanonical wraps it for the PAGE write paths (markdown import via importPageMarkdown, update_page markdown via updatePageContentRealtime). Comment callers keep the non-canonicalizing primitive. Updated the now-false header comment and added create/update-comment inline notes. Added collaboration tests: comment path PRESERVES a reference-less definition; page path still drops it AND still reorders real footnotes. Updated the page-import canonicalization test to use the canonical variant. Suggestions / architecture: - #2: collapsed transforms.footnoteDefinition onto the shared makeFootnoteDefinition factory (adds only the inner paragraph block id); kept the dependency direction transforms -> footnote-authoring (no circular import, mirror stays pure). - docmost#3: confirmed docmost_transform auto-canonicalization is documented (inline comment, tool description, CHANGELOG) — no code change. - docmost#4: copyPageContent is a FULL-document write (replacePageContent of a type:"doc"); added a defensive canonicalizeFootnotes pass (no-op on already-canonical source). - CHANGELOG entry refined to list the FULL-document write paths (incl. copy_page_content) and to state canonicalization is NOT applied to comment bodies. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jul 4, 2026
…ocmost#293 canon docmost#9) Move paragraph/heading textAlign off the HTML-wrapper form (<p style="text-align:…"> / <hN style=…>) onto a trailing attached HTML comment on the block line: `text <!--attrs {"textAlign":"center"}-->`. This keeps the readable markdown block form (plain `text` / `## Title`) while preserving alignment losslessly. "left"/null stay bare (no churn). Adds a reusable attached-comment primitive (attached-comment.ts) that docmost#4 (image) and docmost#8 (media) will reuse: - attachedCommentFor(name, json) -> `<!--name {compact-json}-->`, escaping any `--` pair inside the JSON as -- so the payload can never close the comment early; - parseAttachedComment(data) with grammar `^\s*([A-Za-z][\w-]*)(?:\s+({…}))?\s*$` whose name excludes `:`, so envelope comments (docmost:meta / docmost:comments) never match — fail-open on anything malformed. On import, applyAttachedComments runs AFTER marked.parse but BEFORE generateJSON (parse5 drops comments), re-expressing the attrs comment as an inline text-align style on the parent block, then removing the comment node. Guards: emit only when there is a visible element to attach to — paragraph requires non-empty text, heading requires non-empty headingText (symmetry: an empty aligned heading stays bare `##`, no orphan comment). Goldens in markdown-converter-golden/gaps updated deliberately to the attached-comment form (assertions stay strict: exact output + lossless round-trip). New textalign.test.ts (19 tests) covers center/right/justify on paragraph and heading, byte-stable re-export, and fail-open branches. Raw-HTML containers (columns/cells/callout via blockToHtml) keep the inline text-align form intentionally — comments are dropped inside raw HTML. package vitest: 462 passed | 1 expected-fail; tsc clean. git-sync: 268 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jul 4, 2026
…ent (docmost#293 canon docmost#4) Every image now serializes as ``; non-default layout/identity attrs that markdown cannot express ride along in an attached `<!--img {…}-->` comment on the same line, replacing the prior "image-with-attrs -> raw <img>" split for the top-level path:  <!--img {"width":"420","align":"left","attachmentId":"…"}--> Keys (emitted only when non-default, stable order): width, height, align, size, aspectRatio, attachmentId, caption, title. Numeric sizing attrs are stringified in the payload (the import side reads DOM attributes back as strings), so a numeric `width:420` round-trips byte-stably instead of churning `420 -> "420"`. attachedCommentFor defuses any `--` in a value (e.g. a caption containing the comment-closing `-->`) so the payload can never close the comment early. Align default unified to "center" (docmost#293 canon docmost#4): editor-ext declares image.align default "center" while this package's schema declared null — keeping null would make the clean `` form dead code (every editor image is "center"). Now the schema default is "center" (docmost-schema image align, with explicit parseHTML/renderHTML), canonicalize KNOWN_DEFAULTS drops align=="center" for image, and the serializer omits align when it is null OR "center". A null align collapses to "center" on re-import (a null align is not a distinct editor state) — stable, no ping-pong. Only left/right emit a comment. Import: applyCommentDirectives gains an `img` handler that targets the comment's previousElementSibling <img> and writes each decoded key to the DOM attribute the schema reads (align, width, height, data-size, data-aspect-ratio, data-attachment-id, data-caption, title), then removes the comment. Attached only: a standalone `<!--img-->` with no adjacent image is inert. Fail-open on malformed JSON / unknown keys. Raw-HTML path unchanged in spirit: images inside columns/cells keep the `<img …>` form (comments are dropped by the DOM parse stage); imageToHtml now omits a redundant align="center" to match the unified default. Tests: new image-comment.test.ts (21 cases incl. caption == `-->`, numeric-size byte-stability, image-in-column <img> form, fail-open). Goldens updated deliberately: markdown-roundtrip-spoiler-caption (captioned image -> comment form), markdown-converter-gaps spec 14/15 (title now round-trips via comment; column image drops redundant align), canonicalize-extra (center+null dropped, left kept). package vitest: 498 passed | 1 expected-fail; tsc clean. git-sync (rebuilt build): 268 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jul 4, 2026
…tizers + tidy (docmost#333 review F1-F4) F1 [critical, data-loss] — escape the image alt in ``. Canon docmost#4 moved the top-level image off the lossless <img> form onto markdown ``, but the alt was inserted raw; the importer re-parses the `![alt]` label as CommonMark inline, so a markdown-active char in a realistic description ("Figure [1]", "the *new* logo", "a]b[c") broke the round-trip — the image node vanished or emphasis collapsed. Now `escapeLinkText(imgAttrs.alt ?? "")`, exactly as the link-form media (attachment/pdf/embed) already escape their visible text. Regression test added: six active-punctuation alts round-trip byte-stable with the node intact. F2 [drift] — re-export `clampCalloutType` / `sanitizeCssColor` from the package barrel and drop the verbatim copies in the mcp schema shim. The copies had already drifted (the mcp `clampCalloutType` lost the callout-type alias mapping the package applies), which is exactly the schema drift docmost#293 exists to kill. The sanitizers now live only in the package; mcp `schema.test.mjs` exercises the single alias-aware implementation. F3 [docs] — AGENTS.md:296 said `packages/mcp/build/` is committed; this branch gitignored it (git-sync/prosemirror-markdown convention). Updated the line to say it is gitignored and rebuilt in CI/Docker via `pnpm build`. F4 [cleanup] — removed the dead `test.typecheck` block from the package vitest.config.ts and deleted tsconfig.vitest.json. Both were copied verbatim from git-sync; this package has zero `*.test-d.ts` files, and the ported comments referenced git-sync-only entities. Kept the `docmost-client` resolve alias (22 tests use it) and the runtime include/environment. package vitest: 658 passed (+1 F1 regression); tsc clean. git-sync: 268 passed. mcp: node --test 454 passed; tsc clean. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jul 12, 2026
… чистки (docmost#491) Ребейз на обновлённый feat/490 (PR docmost#510, Option-A): стек docmost#491 перенесён с 6e872f2d на 6e42752a; run-fsm.ts/chat-thread.tsx приехали из develop-версии (W1/S4: RUN_ALREADY_ACTIVE несёт activeRunId + supersede-CAS адопция) — мои docmost#491-правки легли сверху без конфликтов, W1 НЕ откачен (run-fsm.ts == develop байт-в-байт; RUN_ALREADY_ACTIVE диспатчит activeRunId). 1. [CI-fidelity] Дельта-курсор спек падал в CI unit-лейне: `.spec.ts` дефолтил на НЕмигрированный docmost → 5/6 ERROR relation does not exist (skip-гард ловит только connection-fail). Переименован в `*.int-spec.ts` (исключается из unit- regex `.spec.ts$`, гоняется в test:int, чей global-setup мигрирует docmost_test) + DSN по умолчанию → docmost_test. Теперь 6/6 реально исполняются в CI-верном окружении; overlap-мутация роняет RACE-тесты (не вакуумен). 2. [regression docmost#137/docmost#161] attach: отсутствие `n` схлопывалось в frontier 0 → finished-неротированный ран (coverageFloor 0) отдавал ВЕСЬ tail вместо 204; парамслесс/легаси-вкладка допишет полный replay → дубль. Различаем ОТСУТСТВИЕ `n` (null — не tail-aware) от `n=0` (tail-aware): контроллер шлёт null при missing/invalid; registry.attach(n: number|null) 204-ит finished-ран при n===null (старый `finished && !expectLive` гейт), n=0 по-прежнему отдаёт хвост. Тесты (registry + controller) + mutation-verify: нейтрализация гейта роняет их. 4. [conventions] Ring-кап env-var переименован RUN_STREAM_MAX_BUFFER_BYTES → AI_CHAT_RUN_STREAM_MAX_BUFFER_BYTES (префикс как у сиблингов) + запись в .env.example (дефолт 4MB, 0/invalid→дефолт, subscriber-cap=2×). 5. [docs] run-fsm.spec.md: item4 переписан («реализовано в docmost#491 — дельта несёт run:{id,status}|null; клиент run-поле ещё не потребляет») + добавлена строка перехода POLL_IDLE_CAP stopping→idle (Review docmost#4, редьюсер это делает). 6. [simplification] Удалена мёртвая цепочка reconstructRunParts / reconstructPartsFromRow (ноль прод-вызовов) + опц. messageRepo-инъекция в AiChatRunService + спек-блоки; вернётся с первым реальным вызывателем. Маркер metadata.stepsPersisted (реально используемый) сохранён. DROP-пункты ревьюера (осиротевший import, DELTA_POLL_MAX_ROWS) не трогаю. Прогон: server tsc 0, ai-chat unit 202, delta-int 6/6 (int-lane), int attach 6/6, client vitest 403, tsc client 0 ai-chat, mcp 834/0. FSM-инварианты docmost#488 сохранены. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
vvzvlad
pushed a commit
to vvzvlad/gitmost
that referenced
this pull request
Jul 17, 2026
…rf flake Two failures surfaced after the round-1 e2e baseHash fix unblocked the mcp e2e: - editor-ext table schema: TableCell/TableHeader did not declare an `align` attribute, so the docmost#647/docmost#672 server-side guarded-replace write path (jsonToNode -> Node.fromJSON(getSchema(editor-ext exts))) stripped GFM column alignment on persist — the old client-side collab write went through the converter schema (which HAS align), masking the drift. Mirror the converter's docmost-schema align onto editor-ext so the authoritative editor/collab schema preserves it (round-trips |:--|:-:|--:|). Invariants docmost#7/docmost#4. - drawio-layout benchmark (docmost#486): the `dt < 5000` sanity bound compared TOTAL round-trip time (worker startup + elkjs load + IPC + the internal 5000ms ELK budget) against the internal budget, flaking on loaded CI runners. Loosen to 10000ms; the event-loop-responsive / layout-applied guarantees are unchanged. Verified: editor-ext + prosemirror-markdown build; converter tests green (895); runtime proof that Node.fromJSON now preserves tableCell/tableHeader align; drawio-layout perf test green locally. Follow-up: add a CI parity check for node-attribute drift between editor-ext and prosemirror-markdown/docmost-schema (the gap that let `align` diverge).
PMQ9
referenced
this pull request
in cccvu/docmost
Aug 29, 2026
Docmost's OSS ships a NoopAuditService (real audit is EE-only). Rebind the AUDIT_SERVICE token to a fork-owned, platform-forwarding implementation so the ~70-event catalog is captured by the wiki-v2 platform's central, tamper-evident sink instead of being swallowed. - authz/audit/platform-audit.client.ts: a fire-and-forget forwarder to the platform's POST /audit/ingest (mirrors PlatformAuthzClient, but NEVER throws or blocks a request — drops + warns on platform-down). - authz/audit/platform-audit.service.ts: PlatformAuditService implements IAuditService; maps the upstream AuditLogPayload + CLS actor context onto the ingest contract; setActorId/Type write through to the CLS context. - authz/audit/audit.module.ts: @global PlatformAuditModule binds AUDIT_SERVICE with the same shape as NoopAuditModule (drop-in for the ~45 injectors). Upstream seam (documented, UPSTREAM_MODIFICATIONS.md #4): app.module.ts swaps NoopAuditModule -> PlatformAuditModule (one import line, in an already-listed seam file — no new seam file). All audit logic lives in authz/audit/ + the platform; this only changes which module provides the token. Co-Authored-By: Claude Opus 4.8 <[email protected]>
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.
Sidebar page tree implementation.