# Docs Gatekeeper Development Guide Docs Gatekeeper moves `/docs` from "bundle all Markdown into the frontend" to "return catalog and content from the backend according to permissions." Its goal is to keep public manuals, user docs, developer docs, and admin/ops docs in one searchable Docs page while making every protected Markdown body pass through a server-side whitelist and authorization check. For the user workflow, see the Docs section in [Planet Manual](/home/ray/dev/linkong/planet/docs/technical/en/manual.md). ## Authorization Model Docs uses two permission layers: - `users.role`: preserved for console/system permissions. - `users.gatekeeper_groups`: Docs content permission groups. Groups: | Group | Purpose | | --- | --- | | `docs_user` | User-operation docs | | `docs_developer` | Earth, frontend, backend, collector, and AI Provider development docs | | `docs_admin` | Service control, operations, environment, and sensitive-operation docs | Inheritance: - Anonymous users can only read `public`. - `docs_developer` includes `docs_user`. - `docs_admin` includes `docs_developer` and `docs_user`. - `admin` and `super_admin` receive all Docs permissions by default. ## Backend Entry Points Files: - [docs.py](/home/ray/dev/linkong/planet/backend/app/api/v1/docs.py) - [docs_gatekeeper.py](/home/ray/dev/linkong/planet/backend/app/services/docs_gatekeeper.py) - [user.py](/home/ray/dev/linkong/planet/backend/app/models/user.py) - [users.py](/home/ray/dev/linkong/planet/backend/app/api/v1/users.py) APIs: ```http GET /api/v1/docs/catalog GET /api/v1/docs/{lang}/{slug} ``` `catalog` returns only documents visible to the current user. The content endpoint validates language, slug, and file existence through the metadata whitelist before checking access: - Anonymous protected-doc request: `401`. - Authenticated but insufficient permissions: `403`. - Unknown language, unknown slug, or missing file: `404`. Markdown bodies can only come from whitelisted files under `docs/technical/{zh,en}/`; arbitrary path reads are not allowed. ## Metadata Source Server-side metadata lives in [docs_gatekeeper.py](/home/ray/dev/linkong/planet/backend/app/services/docs_gatekeeper.py): ```python DocsMetadata( "manual.md", "manual", "public", "Manual", 2, "Planet 使用手册", "Planet Manual", ) ``` When adding a public technical doc: - Add both Chinese and English Markdown files. - Add filename, slug, access, group, order, and titles to server `DOCS_METADATA`. - Add matching metadata to frontend [docs-content.ts](/home/ray/dev/linkong/planet/frontend/src/pages/Docs/docs-content.ts) so navigation titles and sorting stay aligned. - Update `docs/technical/zh/README.md` and `docs/technical/en/README.md` when the document should be discoverable from the README. ## User Management The `users` table has `gatekeeper_groups JSONB DEFAULT '[]'`. Startup [session.py](/home/ray/dev/linkong/planet/backend/app/db/session.py) applies `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` for existing local databases. The user API: - Writes `gatekeeper_groups` during user creation. - Validates group names on update: only `docs_user`, `docs_developer`, and `docs_admin` are accepted. - Allows only `super_admin` to modify Gatekeeper groups. Frontend [Users.tsx](/home/ray/dev/linkong/planet/frontend/src/pages/Users/Users.tsx) displays group tags and provides a multi-select in the edit form. Non-`super_admin` users see the field disabled, and submission removes `gatekeeper_groups` before sending. ## Frontend Docs Loading Files: - [Docs.tsx](/home/ray/dev/linkong/planet/frontend/src/pages/Docs/Docs.tsx) - [docs-content.ts](/home/ray/dev/linkong/planet/frontend/src/pages/Docs/docs-content.ts) - [docs-search.ts](/home/ray/dev/linkong/planet/frontend/src/pages/Docs/docs-search.ts) Key changes: - Remove `import.meta.glob(...?raw)` as the Markdown content source. - Load `/api/v1/docs/catalog` to build the visible navigation. - Load `/api/v1/docs/{lang}/{slug}` for document bodies. - Index search only across currently visible docs, loading Markdown from the backend as needed. - Show login state for `401`, permission state for `403`, and unavailable-doc state for `404`. ## Test Coverage Relevant tests: - [test_docs_gatekeeper.py](/home/ray/dev/linkong/planet/backend/tests/test_docs_gatekeeper.py) Tests should cover: - Anonymous users only see public docs. - Protected content returns `401` or `403` appropriately. - `docs_developer` can read developer docs but not admin docs. - `admin` and `super_admin` can read admin docs. - Unknown slugs, unknown languages, and path traversal strings cannot read files.