feat(editor): /trajects/:id/docs read-only docs route (stubbed; depends on #632 + #626)#653
Draft
humanintheloop25 wants to merge 3 commits into
Draft
feat(editor): /trajects/:id/docs read-only docs route (stubbed; depends on #632 + #626)#653humanintheloop25 wants to merge 3 commits into
humanintheloop25 wants to merge 3 commits into
Conversation
Adds a markdown-rendered docs view that lives inside the traject concept from #632. URL shape: /trajects/:trajectId/docs → landing (sidebar only) /trajects/:trajectId/docs/:sourceId → source root /trajects/:trajectId/docs/:sourceId/<path> → specific .md page Frontend additions: - `frontend/src/TrajectDocsApp.vue` — root view (parallel to EditorApp / LibraryApp), two-pane layout: DocsSidebar + DocsContent. - `frontend/src/components/docs/DocsSidebar.vue` — lists each source attached to the traject, grouped by top-level directory. - `frontend/src/components/docs/DocsContent.vue` — renders markdown via the shared `useArticleMarkdown` pipeline (marked + DOMPurify, same as ArticleText) and post-processes ` ```mermaid ` code blocks into SVG via `mermaid.run`. - `frontend/src/composables/useDocs.js` — `useDocsTree` + `useDocsPage` with cookie-credentialed fetches; route-driven, so refresh/back/forward keep working. - `frontend/src/router.js` — new `traject-docs` route, `requiresAuth` identical to the editor route. - `mermaid@^11.4.1` added to frontend deps. Lazy-loaded via the TrajectDocsApp route bundle (visible in `npm run build` chunk listing). Backend additions (`packages/editor-api/`): - `traject_docs.rs` with `tree` + `page` handlers, registered in `main.rs` behind the existing `require_session_auth` middleware. - Returns canned data for `source=dummy` paths today. ## Stub status & upstream dependencies The backend handlers serve **canned data** while waiting on two of @tdjager's PRs in review: - **#632 (trajects)** brings the `trajects`, `traject_members`, `accounts`, and `traject_corpus_sources` tables. Once merged, this module switches to: 1. resolving `session.person_sub` → `accounts.id` via one query, 2. asserting membership in `traject_members` (non-member → 403), 3. selecting the traject's sources and walking the `docs/` subdir of each source's on-disk clone (the same clones the writable-own flow already uses). - **#626 (layered RBAC)** introduces `editor-reader` realm-role gating. Docs routes will be raised to `editor-reader` (explicit) instead of the implicit `require_session_auth` that's wired today. The handler signatures + response shapes are stable across the stub→real transition, so the frontend doesn't need to change when the backend is rewired. ## Verification - `just editor-api-fmt` — clean - `just editor-api-lint` (clippy) — clean - `just editor-api-check` (cargo check) — clean - `frontend/`: `npm run build` — passes; mermaid lazy-loaded into the TrajectDocsApp chunk (~600 KB raw, ~140 KB gzipped per diagram variant). Local smoke-test (with the editor-api running and the existing require_session_auth bypassed in non-OIDC dev mode): curl /api/trajects/test/docs/tree curl '/api/trajects/test/docs/page?source=dummy&path=diagrams/fietsval-flow-2025-04-01.md' ## Not in this PR (follow-ups, scoped out) - Real DB queries (blocked on #632) - Explicit `editor-reader` role gate (blocked on #626) - Annotations on docs pages — RFC-018 covers law-text annotations; whether/how to extend that pattern to free-text markdown is a separate decision after these merges land. - Source-cross-link resolution (relative `.md` → in-app router-link) - Build-pipeline integration of corpus sources into editor image
3 tasks
Preview Deployment — editor — editorYour changes have been deployed to a preview environment: URL: https://editor.pr653.rig.prd1.gn2.quattro.rijksapps.nl This deployment will be automatically cleaned up when the PR is closed. |
Drop the hand-rolled `<aside>` + `<article>` + custom-CSS shell in favour of the same NLDD web-components the rest of the editor uses. Three concrete swaps: - `TrajectDocsApp.vue`: layout now follows LibraryApp — `nldd-app-view` → `nldd-navigation-split-view` with a navigation pane and a content pane. Empty/loading/error states use `nldd-inline-dialog` instead of div+classname fragments. - `DocsSidebar.vue`: per-source group is now `nldd-simple-section` (keeps the heading-styling consistent with EditSheet's sections); per-folder file lists use `nldd-list variant="simple"` with `nldd-list-item type="button" :selected` — same pattern as LibraryApp's sidebar. File labels render through `nldd-text-cell`. - `DocsContent.vue`: drops the `<article>` + ~50 lines of typography CSS in favour of `nldd-rich-text`, the same primitive ArticleText and AnnotatedText already use. Effect: docs and law-text share identical typography, spacing, code-block treatment, link styles. Mermaid post-render still works — `nldd-rich-text` keeps its slot content in the light DOM so `richTextEl.querySelectorAll(...)` reaches it (AnnotatedText relies on the same property). ~125 lines net deleted; visual consistency with the rest of the editor is now structural rather than hex-fallback-based.
The NLDD refactor wired the panes wrong, producing first a white screen and then a sidebar-only view where clicking a nav item showed nothing: - sidebar pane used slot="navigation"; nldd-navigation-split-view expects slot="sidebar" (confirmed against LibraryApp's nested split-view). Wrong slot name → component never mounted → white screen. - main content pane had no slot and no has-content. The split-view only reveals the main pane when it carries slot="main" + has-content, so the pane stayed collapsed (0px) — the sidebar rendered but the content area was empty, and mermaid threw "Could not find a suitable point for the given distance" because it rendered into a zero-size box. With slot="main" + has-content the content pane gets real dimensions: text pages render and mermaid diagrams draw correctly.
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.
Summary
Adds a markdown-rendered, per-traject docs view to the editor. The route renders documentation files (
docs/*.md) from the corpus-sources attached to a traject, behind the usual session-auth + an upcoming expliciteditor-readerrole gate.The backend handlers in
packages/editor-api/src/traject_docs.rscurrently return canned data so the frontend can be reviewed end-to-end while two upstream PRs are still in flight:trajects,traject_members,accounts, andtraject_corpus_sourcestables. Without those we can't do the real authz check ("is this account a member of this traject?") nor list the traject's sources from the DB.editor-reader / editor-writer / editor-adminrealm-roles. Our docs routes will be raised toeditor-reader(explicit) instead of the implicitrequire_session_authwired today.Once both land,
traject_docs.rsswitches to:session.person_sub→accounts.idvia one query.traject_membersfor the requested:trajectId. Not a member → 403.traject_corpus_sourcesrows for the traject and walk each source's on-disk clone (the same clones feat: introduce traject concept for grouped law edits #632 uses for the writable-own flow). Thedocs/subdir of each clone is the docs tree.The handler signatures and response shapes are stable across the stub→real transition, so the frontend does not need to change when the backend is rewired.
What's in this PR
Frontend
frontend/src/TrajectDocsApp.vue— root view (parallel to EditorApp / LibraryApp). Two-pane layout: DocsSidebar + DocsContent.frontend/src/components/docs/DocsSidebar.vue— lists each source attached to the traject, grouped by top-level directory.frontend/src/components/docs/DocsContent.vue— renders markdown via the shareduseArticleMarkdownpipeline (marked + DOMPurify, identical toArticleText.vue) and post-processes\``mermaidcode blocks into SVG viamermaid.run`.frontend/src/composables/useDocs.js—useDocsTree+useDocsPagecomposables with cookie-credentialed fetches. Route-driven so refresh/back/forward keep working.frontend/src/router.js— newtraject-docsroute,meta.requiresAuth: trueidentical to the editor route.mermaid@^11.4.1added tofrontend/package.json. Lazy-loaded — only fetched when navigating to the docs route.Backend
packages/editor-api/src/traject_docs.rs—tree+pagehandlers, stub-only for now.packages/editor-api/src/main.rs— module registered, two routes added inside the existingprotected_api_routesblock (which carriesrequire_session_auth).Test plan
just editor-api-fmt— cleanjust editor-api-lint(clippy) — cleanjust editor-api-check(cargo check) — cleancd frontend && npm run build— passes; mermaid + sub-renderers chunked separately, lazy-loaded into the TrajectDocsApp bundleeditor-readerroute-layerNot in this PR (follow-ups)
editor-readerrealm-role gate (blocked on feat(admin): layered RBAC with per-app reader/writer/admin roles #626).md→ in-app router-link)Background
Replaces an earlier exploration of a standalone docs platform (
MinBZK/regelrecht-corpus-docs, soon to be archived) that built its own auth-proxy + DB. Integrating into the editor instead reuses auth, session-management, deploy pipeline, and now per-traject permissions from #632 — drastically less infrastructure for the same user-facing capability.