Skip to content

chore(wiki-v2): promote #57 platform-admin entry seam onto the durable branch - #2

Merged
PMQ9 merged 1 commit into
wiki-v2from
feat/issue-57-platform-spaces
Aug 31, 2026
Merged

PMQ9 merged 1 commit into
wiki-v2from
feat/issue-57-platform-spaces

Conversation

@PMQ9

@PMQ9 PMQ9 commented Aug 31, 2026

Copy link
Copy Markdown

What this promotes

Fast-forwards the fork's durable wiki-v2 branch to include the one #57 seam commit 45f8960 — a
fork-owned features/admin-entry/AdminEntryLink + a one-line mount in the authed app-header.tsx.

Why (merge ordering)

The wiki-v2 parent PR cccvu/wiki-v2#65 pins the docmost submodule at 45f8960. A DevOps review flagged
that .gitmodules declares branch = wiki-v2 while that SHA lived only on the feature branch — so this PR
promotes it onto wiki-v2 so the pin is reachable from the branch the parent declares (and survives feature-
branch cleanup). This is a clean fast-forward (parent of 45f8960 is the current wiki-v2 tip). Merge this
before/with the parent PR, exactly as the passwordless work (PR #61) advanced wiki-v2 on merge.

Boundary

The seam is documented in the parent repo's UPSTREAM_MODIFICATIONS.md (#17); features/admin-entry/** is
fork-owned/additive (excluded from the boundary check). Advisory-only visibility gating — grants no Docmost
capability; all authority is re-enforced server-side by the platform PDP.

🤖 Generated with Claude Code

Fork-owned, additive UI: features/admin-entry/AdminEntryLink self-gates on the
platform's /admin/context (same-origin, cookie-auth) and surfaces a link to the
standalone admin console at /console ONLY for a platform workspace admin.
Advisory-only visibility gating — grants no Docmost capability; every console
action is re-enforced server-side by the PDP, and the platform admin stays a
non-privileged Docmost member. One-line seam in the authed app-header mounts it
(documented as seam #17 in UPSTREAM_MODIFICATIONS.md).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@PMQ9
PMQ9 merged commit d313d66 into wiki-v2 Aug 31, 2026
@PMQ9
PMQ9 deleted the feat/issue-57-platform-spaces branch August 31, 2026 18:10
PMQ9 added a commit that referenced this pull request Sep 8, 2026
…ge, DTO validation, keyset hardening

All four round-justifying (non-blocking Level-3) findings from the 7-lens review, plus overlapping Level-2
robustness folded in while in the same files:

- [Testing L3 / DevOps L3] listByPage: give it opt-in {limit,before} keyset paging (consistent with the
  members/ACL reads), and add service-attachment.pg.spec.ts — resolvePage + listByPage now execute on real
  Postgres (a raw-sql column/table typo no longer ships green), and the paging keyset walks a shared-ms tie
  with no skip / no duplicate.
- [Testing L3] Add dto-validation.spec.ts — the new class-validator DTOs (ContentSearchDto, ContentSortDto,
  ContentCursorDto, ContentListDto incl. nested sort) now run through validate(), so dropping a constraint
  (@Max/@IsUUID/@IsIn/@IsNotEmpty/@IsISO8601, …) reds a test.
- [Correctness L3] Add a real-Postgres walk for the generalized TIMESTAMP keyset (only title was walked) and
  for value='' (null-title) as a mid-walk cursor bound.
- [Security F1 / Correctness #1 / Testing P2] A malformed keyset/cursor timestamp now 400s instead of
  500-ing at the ::timestamptz cast: a shared isIsoInstant() guard (rejects Date.parse-lenient-but-PG-invalid
  values like '2026') used by parseSubCollectionQuery and the content keyset builder.
- [Correctness #2] A text sort (title/name) now REQUIRES its cursor `value` (400) instead of silently
  falling back to a timestamp `updatedAt` and paginating on the wrong boundary.
- [DevOps #3] Bump service-bridge.openapi.json version 1.1.1 → 1.2.0 (additive expansion).

Non-blocking Level ≤2 polish is deferred to a follow-up issue. Verified: nest build, 19 service-bridge suites
(179 tests), 3 real-Postgres pg specs (30 tests), eslint, import-boundary — all green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
PMQ9 added a commit that referenced this pull request Sep 17, 2026
… content write when Redis off (docmost#344)

Two pre-existing content-write defects on the collaboration path, both found while
tracing docmost#282 and both able to lose or silently drop a page's content.

docmost#342 — a content `replace` emptied the Yjs fragment BEFORE building the new document
from the request body. If `TiptapTransformer.toYdoc` threw (a body that passed
`jsonToNode` but the Yjs transformer rejects), the connection's closing store persisted
the emptied fragment: the page was WIPED while the request also failed. Build the new
state first, then delete+apply — a conversion failure now aborts before any mutation and
the original content survives. Shared by the ordinary `updatePageContent` handler and the
docmost#282 conditional write.

docmost#344 — custom collab events route only through the RedisSync extension, so with
COLLAB_DISABLE_REDIS (single-node standalone) `handleYjsEvent('updatePageContent')`
returned undefined and `PageService.update` ignored it: a REST/`/v1` content write
returned 200 while persisting nothing. Fail that one un-routable write loudly instead.
Narrowest boundary: the supported standalone mode still boots, interactive editing (direct
Hocuspocus path) is untouched, and the docmost#282 seams keep their fail-closed `undefined`
contract.

Tests: build-before-delete leaves the fragment intact on a throwing toYdoc; the gateway
guard throws for updatePageContent with Redis off, stays quiet for best-effort events, and
routes normally with Redis on. UPSTREAM_MODIFICATIONS.md seams #2/#3 updated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
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