@valkyrianlabs/payload-markdown-docs 0.1.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +195 -0
  2. package/dist/admin/DocsSetManager.d.ts +2 -0
  3. package/dist/admin/DocsSetManager.js +298 -0
  4. package/dist/admin/DocsSetManager.js.map +1 -0
  5. package/dist/admin/docsSetManagerData.d.ts +25 -0
  6. package/dist/admin/docsSetManagerData.js +266 -0
  7. package/dist/admin/docsSetManagerData.js.map +1 -0
  8. package/dist/admin/docsSetManagerTypes.d.ts +103 -0
  9. package/dist/admin/docsSetManagerTypes.js +3 -0
  10. package/dist/admin/docsSetManagerTypes.js.map +1 -0
  11. package/dist/admin/index.d.ts +3 -0
  12. package/dist/admin/index.js +4 -0
  13. package/dist/admin/index.js.map +1 -0
  14. package/dist/cli/commands/install.d.ts +2 -0
  15. package/dist/cli/commands/install.js +211 -0
  16. package/dist/cli/commands/install.js.map +1 -0
  17. package/dist/cli/commands/keygen.d.ts +2 -0
  18. package/dist/cli/commands/keygen.js +89 -0
  19. package/dist/cli/commands/keygen.js.map +1 -0
  20. package/dist/cli/commands/manifest.d.ts +2 -0
  21. package/dist/cli/commands/manifest.js +50 -0
  22. package/dist/cli/commands/manifest.js.map +1 -0
  23. package/dist/cli/commands/plan.d.ts +2 -0
  24. package/dist/cli/commands/plan.js +110 -0
  25. package/dist/cli/commands/plan.js.map +1 -0
  26. package/dist/cli/commands/push.d.ts +3 -0
  27. package/dist/cli/commands/push.js +308 -0
  28. package/dist/cli/commands/push.js.map +1 -0
  29. package/dist/cli/commands/validate.d.ts +3 -0
  30. package/dist/cli/commands/validate.js +109 -0
  31. package/dist/cli/commands/validate.js.map +1 -0
  32. package/dist/cli/filesystem.d.ts +20 -0
  33. package/dist/cli/filesystem.js +96 -0
  34. package/dist/cli/filesystem.js.map +1 -0
  35. package/dist/cli/format.d.ts +35 -0
  36. package/dist/cli/format.js +76 -0
  37. package/dist/cli/format.js.map +1 -0
  38. package/dist/cli/http.d.ts +19 -0
  39. package/dist/cli/http.js +39 -0
  40. package/dist/cli/http.js.map +1 -0
  41. package/dist/cli/index.d.ts +3 -0
  42. package/dist/cli/index.js +214 -0
  43. package/dist/cli/index.js.map +1 -0
  44. package/dist/cli/parseArgs.d.ts +5 -0
  45. package/dist/cli/parseArgs.js +219 -0
  46. package/dist/cli/parseArgs.js.map +1 -0
  47. package/dist/cli/types.d.ts +51 -0
  48. package/dist/cli/types.js +3 -0
  49. package/dist/cli/types.js.map +1 -0
  50. package/dist/collections/docs.d.ts +9 -0
  51. package/dist/collections/docs.js +168 -0
  52. package/dist/collections/docs.js.map +1 -0
  53. package/dist/collections/docsGroups.d.ts +5 -0
  54. package/dist/collections/docsGroups.js +57 -0
  55. package/dist/collections/docsGroups.js.map +1 -0
  56. package/dist/collections/docsSets.d.ts +8 -0
  57. package/dist/collections/docsSets.js +158 -0
  58. package/dist/collections/docsSets.js.map +1 -0
  59. package/dist/collections/index.d.ts +10 -0
  60. package/dist/collections/index.js +7 -0
  61. package/dist/collections/index.js.map +1 -0
  62. package/dist/collections/nonces.d.ts +6 -0
  63. package/dist/collections/nonces.js +57 -0
  64. package/dist/collections/nonces.js.map +1 -0
  65. package/dist/collections/syncRuns.d.ts +5 -0
  66. package/dist/collections/syncRuns.js +139 -0
  67. package/dist/collections/syncRuns.js.map +1 -0
  68. package/dist/constants.d.ts +21 -0
  69. package/dist/constants.js +23 -0
  70. package/dist/constants.js.map +1 -0
  71. package/dist/endpoints/index.d.ts +2 -0
  72. package/dist/endpoints/index.js +3 -0
  73. package/dist/endpoints/index.js.map +1 -0
  74. package/dist/endpoints/sync.d.ts +47 -0
  75. package/dist/endpoints/sync.js +616 -0
  76. package/dist/endpoints/sync.js.map +1 -0
  77. package/dist/index.d.ts +9 -0
  78. package/dist/index.js +7 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/next/PayloadMarkdownDocsPage.d.ts +7 -0
  81. package/dist/next/PayloadMarkdownDocsPage.js +142 -0
  82. package/dist/next/PayloadMarkdownDocsPage.js.map +1 -0
  83. package/dist/next/index.d.ts +9 -0
  84. package/dist/next/index.js +7 -0
  85. package/dist/next/index.js.map +1 -0
  86. package/dist/next/markdown.d.ts +14 -0
  87. package/dist/next/markdown.js +232 -0
  88. package/dist/next/markdown.js.map +1 -0
  89. package/dist/next/metadata.d.ts +3 -0
  90. package/dist/next/metadata.js +33 -0
  91. package/dist/next/metadata.js.map +1 -0
  92. package/dist/next/records.d.ts +14 -0
  93. package/dist/next/records.js +146 -0
  94. package/dist/next/records.js.map +1 -0
  95. package/dist/next/route.d.ts +6 -0
  96. package/dist/next/route.js +271 -0
  97. package/dist/next/route.js.map +1 -0
  98. package/dist/next/sidebar.d.ts +15 -0
  99. package/dist/next/sidebar.js +137 -0
  100. package/dist/next/sidebar.js.map +1 -0
  101. package/dist/next/types.d.ts +117 -0
  102. package/dist/next/types.js +3 -0
  103. package/dist/next/types.js.map +1 -0
  104. package/dist/payload/applyDocsSync.d.ts +54 -0
  105. package/dist/payload/applyDocsSync.js +176 -0
  106. package/dist/payload/applyDocsSync.js.map +1 -0
  107. package/dist/payload/docsConflicts.d.ts +12 -0
  108. package/dist/payload/docsConflicts.js +34 -0
  109. package/dist/payload/docsConflicts.js.map +1 -0
  110. package/dist/payload/docsData.d.ts +23 -0
  111. package/dist/payload/docsData.js +59 -0
  112. package/dist/payload/docsData.js.map +1 -0
  113. package/dist/payload/docsSets.d.ts +38 -0
  114. package/dist/payload/docsSets.js +57 -0
  115. package/dist/payload/docsSets.js.map +1 -0
  116. package/dist/payload/existingDocs.d.ts +43 -0
  117. package/dist/payload/existingDocs.js +97 -0
  118. package/dist/payload/existingDocs.js.map +1 -0
  119. package/dist/payload/index.d.ts +15 -0
  120. package/dist/payload/index.js +10 -0
  121. package/dist/payload/index.js.map +1 -0
  122. package/dist/payload/routeCollisions.d.ts +31 -0
  123. package/dist/payload/routeCollisions.js +104 -0
  124. package/dist/payload/routeCollisions.js.map +1 -0
  125. package/dist/payload/syncRuns.d.ts +60 -0
  126. package/dist/payload/syncRuns.js +53 -0
  127. package/dist/payload/syncRuns.js.map +1 -0
  128. package/dist/plugin.d.ts +3 -0
  129. package/dist/plugin.js +165 -0
  130. package/dist/plugin.js.map +1 -0
  131. package/dist/routing/index.d.ts +3 -0
  132. package/dist/routing/index.js +4 -0
  133. package/dist/routing/index.js.map +1 -0
  134. package/dist/routing/paths.d.ts +7 -0
  135. package/dist/routing/paths.js +23 -0
  136. package/dist/routing/paths.js.map +1 -0
  137. package/dist/routing/reservations.d.ts +37 -0
  138. package/dist/routing/reservations.js +79 -0
  139. package/dist/routing/reservations.js.map +1 -0
  140. package/dist/security/canonical.d.ts +12 -0
  141. package/dist/security/canonical.js +24 -0
  142. package/dist/security/canonical.js.map +1 -0
  143. package/dist/security/githubOidc.d.ts +45 -0
  144. package/dist/security/githubOidc.js +177 -0
  145. package/dist/security/githubOidc.js.map +1 -0
  146. package/dist/security/headers.d.ts +22 -0
  147. package/dist/security/headers.js +44 -0
  148. package/dist/security/headers.js.map +1 -0
  149. package/dist/security/index.d.ts +15 -0
  150. package/dist/security/index.js +9 -0
  151. package/dist/security/index.js.map +1 -0
  152. package/dist/security/jwks.d.ts +20 -0
  153. package/dist/security/jwks.js +40 -0
  154. package/dist/security/jwks.js.map +1 -0
  155. package/dist/security/jwt.d.ts +10 -0
  156. package/dist/security/jwt.js +42 -0
  157. package/dist/security/jwt.js.map +1 -0
  158. package/dist/security/nonce.d.ts +34 -0
  159. package/dist/security/nonce.js +43 -0
  160. package/dist/security/nonce.js.map +1 -0
  161. package/dist/security/sign.d.ts +13 -0
  162. package/dist/security/sign.js +39 -0
  163. package/dist/security/sign.js.map +1 -0
  164. package/dist/security/verify.d.ts +28 -0
  165. package/dist/security/verify.js +54 -0
  166. package/dist/security/verify.js.map +1 -0
  167. package/dist/skills/codex/SKILL.md +173 -0
  168. package/dist/skills/codex/examples/docs-page.md +42 -0
  169. package/dist/skills/codex/examples/github-actions.md +64 -0
  170. package/dist/skills/codex/reference/admin.md +28 -0
  171. package/dist/skills/codex/reference/frontmatter.md +39 -0
  172. package/dist/skills/codex/reference/payload-markdown-directives.md +77 -0
  173. package/dist/skills/codex/reference/routing.md +35 -0
  174. package/dist/skills/codex/reference/sync.md +35 -0
  175. package/dist/skills/codex/reference/troubleshooting.md +53 -0
  176. package/dist/skills/codex/reference/workflow.md +39 -0
  177. package/dist/sync/aiExportManifest.d.ts +58 -0
  178. package/dist/sync/aiExportManifest.js +430 -0
  179. package/dist/sync/aiExportManifest.js.map +1 -0
  180. package/dist/sync/frontmatter.d.ts +28 -0
  181. package/dist/sync/frontmatter.js +210 -0
  182. package/dist/sync/frontmatter.js.map +1 -0
  183. package/dist/sync/hash.d.ts +1 -0
  184. package/dist/sync/hash.js +8 -0
  185. package/dist/sync/hash.js.map +1 -0
  186. package/dist/sync/index.d.ts +12 -0
  187. package/dist/sync/index.js +9 -0
  188. package/dist/sync/index.js.map +1 -0
  189. package/dist/sync/manifest.d.ts +58 -0
  190. package/dist/sync/manifest.js +21 -0
  191. package/dist/sync/manifest.js.map +1 -0
  192. package/dist/sync/paths.d.ts +16 -0
  193. package/dist/sync/paths.js +116 -0
  194. package/dist/sync/paths.js.map +1 -0
  195. package/dist/sync/plan.d.ts +29 -0
  196. package/dist/sync/plan.js +72 -0
  197. package/dist/sync/plan.js.map +1 -0
  198. package/dist/sync/validate.d.ts +26 -0
  199. package/dist/sync/validate.js +308 -0
  200. package/dist/sync/validate.js.map +1 -0
  201. package/dist/types.d.ts +84 -0
  202. package/dist/types.js +3 -0
  203. package/dist/types.js.map +1 -0
  204. package/package.json +143 -0
@@ -0,0 +1,54 @@
1
+ import { createPublicKey, verify } from 'node:crypto';
2
+ import { sha256Hex } from '../sync/index.js';
3
+ export const verifyBodySha256 = ({ body, expectedHash })=>{
4
+ const computedHash = sha256Hex(body);
5
+ if (!/^[a-f0-9]{64}$/i.test(expectedHash)) {
6
+ return {
7
+ computedHash,
8
+ ok: false
9
+ };
10
+ }
11
+ return {
12
+ computedHash,
13
+ ok: computedHash === expectedHash.toLowerCase()
14
+ };
15
+ };
16
+ export const validateTimestampSkew = ({ maxSkewSeconds, now = new Date(), timestamp })=>{
17
+ const date = new Date(timestamp);
18
+ if (Number.isNaN(date.getTime())) {
19
+ return {
20
+ message: 'Sync request timestamp is invalid.',
21
+ ok: false
22
+ };
23
+ }
24
+ const skewMs = Math.abs(now.getTime() - date.getTime());
25
+ if (skewMs > maxSkewSeconds * 1000) {
26
+ return {
27
+ message: 'Sync request timestamp is outside the allowed skew.',
28
+ ok: false
29
+ };
30
+ }
31
+ return {
32
+ date,
33
+ ok: true
34
+ };
35
+ };
36
+ const getPublicKeyInput = (publicKey)=>{
37
+ if (publicKey.includes('BEGIN PUBLIC KEY')) {
38
+ return publicKey;
39
+ }
40
+ return createPublicKey({
41
+ type: 'spki',
42
+ format: 'der',
43
+ key: Buffer.from(publicKey, 'base64')
44
+ });
45
+ };
46
+ export const verifyEd25519Signature = ({ canonicalString, publicKey, signature })=>{
47
+ try {
48
+ return verify(null, Buffer.from(canonicalString, 'utf8'), getPublicKeyInput(publicKey), Buffer.from(signature, 'base64'));
49
+ } catch {
50
+ return false;
51
+ }
52
+ };
53
+
54
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/security/verify.ts"],"sourcesContent":["import { createPublicKey, verify } from 'node:crypto'\n\nimport { sha256Hex } from '../sync/index.js'\n\nexport type VerifyBodyHashResult =\n | {\n computedHash: string\n ok: false\n }\n | {\n computedHash: string\n ok: true\n }\n\nexport type ValidateTimestampResult =\n | {\n date: Date\n ok: true\n }\n | {\n message: string\n ok: false\n }\n\nexport const verifyBodySha256 = ({\n body,\n expectedHash,\n}: {\n body: string\n expectedHash: string\n}): VerifyBodyHashResult => {\n const computedHash = sha256Hex(body)\n\n if (!/^[a-f0-9]{64}$/i.test(expectedHash)) {\n return {\n computedHash,\n ok: false,\n }\n }\n\n return {\n computedHash,\n ok: computedHash === expectedHash.toLowerCase(),\n }\n}\n\nexport const validateTimestampSkew = ({\n maxSkewSeconds,\n now = new Date(),\n timestamp,\n}: {\n maxSkewSeconds: number\n now?: Date\n timestamp: string\n}): ValidateTimestampResult => {\n const date = new Date(timestamp)\n\n if (Number.isNaN(date.getTime())) {\n return {\n message: 'Sync request timestamp is invalid.',\n ok: false,\n }\n }\n\n const skewMs = Math.abs(now.getTime() - date.getTime())\n\n if (skewMs > maxSkewSeconds * 1000) {\n return {\n message: 'Sync request timestamp is outside the allowed skew.',\n ok: false,\n }\n }\n\n return {\n date,\n ok: true,\n }\n}\n\nconst getPublicKeyInput = (publicKey: string) => {\n if (publicKey.includes('BEGIN PUBLIC KEY')) {\n return publicKey\n }\n\n return createPublicKey({\n type: 'spki',\n format: 'der',\n key: Buffer.from(publicKey, 'base64'),\n })\n}\n\nexport const verifyEd25519Signature = ({\n canonicalString,\n publicKey,\n signature,\n}: {\n canonicalString: string\n publicKey: string\n signature: string\n}): boolean => {\n try {\n return verify(\n null,\n Buffer.from(canonicalString, 'utf8'),\n getPublicKeyInput(publicKey),\n Buffer.from(signature, 'base64'),\n )\n } catch {\n return false\n }\n}\n\n"],"names":["createPublicKey","verify","sha256Hex","verifyBodySha256","body","expectedHash","computedHash","test","ok","toLowerCase","validateTimestampSkew","maxSkewSeconds","now","Date","timestamp","date","Number","isNaN","getTime","message","skewMs","Math","abs","getPublicKeyInput","publicKey","includes","type","format","key","Buffer","from","verifyEd25519Signature","canonicalString","signature"],"mappings":"AAAA,SAASA,eAAe,EAAEC,MAAM,QAAQ,cAAa;AAErD,SAASC,SAAS,QAAQ,mBAAkB;AAsB5C,OAAO,MAAMC,mBAAmB,CAAC,EAC/BC,IAAI,EACJC,YAAY,EAIb;IACC,MAAMC,eAAeJ,UAAUE;IAE/B,IAAI,CAAC,kBAAkBG,IAAI,CAACF,eAAe;QACzC,OAAO;YACLC;YACAE,IAAI;QACN;IACF;IAEA,OAAO;QACLF;QACAE,IAAIF,iBAAiBD,aAAaI,WAAW;IAC/C;AACF,EAAC;AAED,OAAO,MAAMC,wBAAwB,CAAC,EACpCC,cAAc,EACdC,MAAM,IAAIC,MAAM,EAChBC,SAAS,EAKV;IACC,MAAMC,OAAO,IAAIF,KAAKC;IAEtB,IAAIE,OAAOC,KAAK,CAACF,KAAKG,OAAO,KAAK;QAChC,OAAO;YACLC,SAAS;YACTX,IAAI;QACN;IACF;IAEA,MAAMY,SAASC,KAAKC,GAAG,CAACV,IAAIM,OAAO,KAAKH,KAAKG,OAAO;IAEpD,IAAIE,SAAST,iBAAiB,MAAM;QAClC,OAAO;YACLQ,SAAS;YACTX,IAAI;QACN;IACF;IAEA,OAAO;QACLO;QACAP,IAAI;IACN;AACF,EAAC;AAED,MAAMe,oBAAoB,CAACC;IACzB,IAAIA,UAAUC,QAAQ,CAAC,qBAAqB;QAC1C,OAAOD;IACT;IAEA,OAAOxB,gBAAgB;QACrB0B,MAAM;QACNC,QAAQ;QACRC,KAAKC,OAAOC,IAAI,CAACN,WAAW;IAC9B;AACF;AAEA,OAAO,MAAMO,yBAAyB,CAAC,EACrCC,eAAe,EACfR,SAAS,EACTS,SAAS,EAKV;IACC,IAAI;QACF,OAAOhC,OACL,MACA4B,OAAOC,IAAI,CAACE,iBAAiB,SAC7BT,kBAAkBC,YAClBK,OAAOC,IAAI,CAACG,WAAW;IAE3B,EAAE,OAAM;QACN,OAAO;IACT;AACF,EAAC"}
@@ -0,0 +1,173 @@
1
+ # Payload Markdown Docs Skill
2
+
3
+ Use this skill when maintaining Git-backed documentation for a project that uses `@valkyrianlabs/payload-markdown-docs`.
4
+
5
+ The docs source lives in `{{docsRoot}}` unless the user says otherwise. Edit Markdown source files first. Do not directly mutate generated Payload docs records unless the user explicitly asks for an admin-side override change.
6
+
7
+ ## Core Rules
8
+
9
+ - Keep docs in repo-local Markdown files.
10
+ - Use `.md` files only. Do not introduce MDX unless the project explicitly enables it in a future version.
11
+ - Use supported frontmatter only.
12
+ - Keep internal docs links root-relative inside the docs set, such as `/getting-started/quick-start`.
13
+ - Use `payload-markdown` directives only when they are supported.
14
+ - Do not invent directives, frontmatter fields, CLI flags, sync modes, or runtime features.
15
+ - Do not describe unsupported features as implemented.
16
+ - Run validation before finishing docs edits.
17
+ - Treat sync and publishing as server-owned. The request may ask; the Payload plugin decides.
18
+
19
+ ## AI Markdown Export Manifest
20
+
21
+ Treat `{{docsRoot}}/index.ai.yml` as part of the standard docs package.
22
+ When creating, scaffolding, migrating, or updating Payload Markdown docs, create or
23
+ update this file automatically. Do not wait for the user to request it.
24
+
25
+ The manifest is source-controlled alongside the docs. It controls the generated
26
+ AI-facing raw Markdown route, usually `/plugins/<docs-package>.md`, while the
27
+ human docs continue to render at `/plugins/<docs-package>`.
28
+
29
+ Rules for `index.ai.yml`:
30
+
31
+ - Prefer `index.ai.yml`; `index.ai.yaml` is supported when already present.
32
+ - Generate `order` from the actual Markdown files present under `{{docsRoot}}`.
33
+ - Update `order` in the same change when docs pages are added, renamed, moved, or removed.
34
+ - Do not invent page names just to fill the manifest.
35
+ - Do not show the manifest in human docs navigation.
36
+ - Do not render the manifest as a normal docs page.
37
+ - Use it as the canonical ordering source for the `.md` export.
38
+ - Avoid backend hand-sorting unless the project already has a docs sort field.
39
+
40
+ Ordering source preference:
41
+
42
+ 1. `{{docsRoot}}/index.ai.yml`
43
+ 2. `{{docsRoot}}/index.ai.yaml`
44
+ 3. existing docs/nav order field
45
+ 4. deterministic fallback order: title, slug/path, id
46
+
47
+ Default ordering pattern when applicable:
48
+
49
+ 1. `index.md`
50
+ 2. installation/setup docs
51
+ 3. basic usage docs
52
+ 4. rendering docs
53
+ 5. blocks/component docs
54
+ 6. styling/theming docs
55
+ 7. configuration docs
56
+ 8. advanced docs
57
+ 9. examples
58
+ 10. troubleshooting/reference
59
+
60
+ Supported first-pass values:
61
+
62
+ - `orphans: append`
63
+ - `orphans: ignore`
64
+ - `headingMode: normalize`
65
+ - `headingMode: preserve`
66
+
67
+ Defaults are `orphans: append` and `headingMode: normalize`.
68
+
69
+ Example manifest:
70
+
71
+ ```yaml
72
+ version: 1
73
+
74
+ title: Payload Markdown Documentation
75
+ canonical: /plugins/payload-markdown
76
+ output: /plugins/payload-markdown.md
77
+
78
+ description: >
79
+ Consolidated AI-facing documentation export for Payload Markdown.
80
+
81
+ preamble: |
82
+ This file is intended for AI agents, editor tooling, Codex, ChatGPT,
83
+ and offline reference.
84
+
85
+ Read the documents in the listed order. Installation and basic usage
86
+ should be treated as prerequisite context before rendering, styling,
87
+ configuration, or advanced examples.
88
+
89
+ order:
90
+ - ./index.md
91
+ - ./install.md
92
+ - ./usage.md
93
+ - ./rendering.md
94
+ - ./blocks.md
95
+ - ./styling.md
96
+ - ./configuration.md
97
+ - ./examples.md
98
+
99
+ exclude:
100
+ - ./drafts/**
101
+ - ./internal.md
102
+
103
+ orphans: append
104
+ headingMode: normalize
105
+ ```
106
+
107
+ Manifest fields:
108
+
109
+ - `version`: manifest format version.
110
+ - `title`: title of the generated Markdown export.
111
+ - `canonical`: canonical human-facing docs URL.
112
+ - `output`: canonical AI-facing Markdown export URL.
113
+ - `description`: short summary included near the top of the export.
114
+ - `preamble`: AI-facing usage note included before page content.
115
+ - `order`: ordered list of docs files to include first.
116
+ - `exclude`: glob/path list of docs to omit from the AI export.
117
+ - `orphans`: behavior for docs not listed in `order`.
118
+ - `headingMode`: heading normalization behavior.
119
+
120
+ ## Default Workflow
121
+
122
+ ```bash
123
+ {{packageManager}} exec payload-markdown-docs validate {{docsRoot}} --source main-docs
124
+ {{packageManager}} exec payload-markdown-docs plan {{docsRoot}} --source main-docs
125
+ ```
126
+
127
+ Only push when the user asks for an upload and provides endpoint/auth context. Prefer GitHub OIDC in GitHub Actions:
128
+
129
+ ```bash
130
+ {{packageManager}} exec payload-markdown-docs push {{docsRoot}} \
131
+ --endpoint "$DOCS_SYNC_ENDPOINT" \
132
+ --source main-docs \
133
+ --github-oidc \
134
+ --oidc-audience payload-markdown-docs \
135
+ --dry-run
136
+ ```
137
+
138
+ Ed25519 signed sync is still supported for non-GitHub CI or local workflows:
139
+
140
+ ```bash
141
+ {{packageManager}} exec payload-markdown-docs push {{docsRoot}} \
142
+ --endpoint "$DOCS_SYNC_ENDPOINT" \
143
+ --source main-docs \
144
+ --key-id github-actions-main \
145
+ --private-key-env DOCS_SYNC_PRIVATE_KEY \
146
+ --sync
147
+ ```
148
+
149
+ Sync writes require `sync.allowWrites: true`. Publishing additionally requires `sync.allowPublish: true` and a draft-enabled docs collection.
150
+
151
+ ## References
152
+
153
+ - `reference/payload-markdown-directives.md`
154
+ - `reference/frontmatter.md`
155
+ - `reference/workflow.md`
156
+ - `reference/sync.md`
157
+ - `reference/routing.md`
158
+ - `reference/admin.md`
159
+ - `reference/troubleshooting.md`
160
+ - `examples/docs-page.md`
161
+ - `examples/github-actions.md`
162
+
163
+ ## Safety Checklist
164
+
165
+ Before finishing:
166
+
167
+ 1. Confirm changed docs have valid frontmatter.
168
+ 2. Confirm `index.ai.yml` matches the current docs files.
169
+ 3. Confirm internal links are root-relative.
170
+ 4. Confirm directives match the reference.
171
+ 5. Run validate.
172
+ 6. Run plan when sync behavior matters.
173
+ 7. Report any validation failures instead of guessing.
@@ -0,0 +1,42 @@
1
+ # Example Docs Page
2
+
3
+ ```markdown
4
+ ---
5
+ title: Signed Push
6
+ navTitle: Signed Push
7
+ description: Upload docs with signed requests.
8
+ order: 30
9
+ status: published
10
+ tags:
11
+ - workflow
12
+ ---
13
+
14
+ # Signed Push
15
+
16
+ :::toc {title="On this page" depth="3" theme="compact"}
17
+ :::
18
+
19
+ Use signed push to validate and upload docs.
20
+
21
+ :::callout {variant="warning" title="Server-owned authority"}
22
+ The request may ask. The Payload plugin decides.
23
+ :::
24
+
25
+ :::steps {variant="cards" layout="stack" numbered stepTheme="glass"}
26
+
27
+ ### Validate
28
+
29
+ Run `payload-markdown-docs validate`.
30
+
31
+ ### Dry-run
32
+
33
+ Run `payload-markdown-docs push --dry-run`.
34
+
35
+ ### Sync
36
+
37
+ Run `payload-markdown-docs push --sync` only when the server allows writes.
38
+
39
+ :::
40
+
41
+ Read [Publishing](/workflow/publishing) next.
42
+ ```
@@ -0,0 +1,64 @@
1
+ # GitHub Actions Example
2
+
3
+ ```yaml
4
+ name: Publish docs
5
+
6
+ on:
7
+ pull_request:
8
+ paths:
9
+ - 'docs/**'
10
+ push:
11
+ branches: [main]
12
+ paths:
13
+ - 'docs/**'
14
+
15
+ permissions:
16
+ id-token: write
17
+ contents: read
18
+
19
+ jobs:
20
+ docs:
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+
26
+ - uses: pnpm/action-setup@v4
27
+ with:
28
+ version: 10
29
+
30
+ - uses: actions/setup-node@v4
31
+ with:
32
+ node-version: 22
33
+ cache: pnpm
34
+
35
+ - run: pnpm install --frozen-lockfile
36
+
37
+ - name: Validate docs
38
+ run: pnpm exec payload-markdown-docs validate ./docs --source main-docs
39
+
40
+ - name: Dry-run docs sync
41
+ if: github.event_name == 'pull_request'
42
+ run: |
43
+ pnpm exec payload-markdown-docs push ./docs \
44
+ --endpoint "$DOCS_SYNC_ENDPOINT" \
45
+ --source main-docs \
46
+ --github-oidc \
47
+ --oidc-audience payload-markdown-docs \
48
+ --dry-run
49
+ env:
50
+ DOCS_SYNC_ENDPOINT: ${{ secrets.DOCS_SYNC_ENDPOINT }}
51
+
52
+ - name: Publish docs
53
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
54
+ run: |
55
+ pnpm exec payload-markdown-docs push ./docs \
56
+ --endpoint "$DOCS_SYNC_ENDPOINT" \
57
+ --source main-docs \
58
+ --github-oidc \
59
+ --oidc-audience payload-markdown-docs \
60
+ --sync \
61
+ --publish
62
+ env:
63
+ DOCS_SYNC_ENDPOINT: ${{ secrets.DOCS_SYNC_ENDPOINT }}
64
+ ```
@@ -0,0 +1,28 @@
1
+ # Admin Manager
2
+
3
+ The Docs Set Admin Manager is a read-only overview on the docs set edit view.
4
+
5
+ It shows:
6
+
7
+ - route base
8
+ - sync metadata
9
+ - total generated docs
10
+ - archived docs
11
+ - draft and published docs
12
+ - hidden-from-nav docs
13
+ - docs with overrides
14
+ - generated docs grouped by source path
15
+ - links to generated docs records
16
+
17
+ Per-doc overrides live on generated docs records:
18
+
19
+ - `navTitle`
20
+ - `hideFromNav`
21
+ - `theme`
22
+ - `heroEyebrow`
23
+ - `heroTitle`
24
+ - `heroDescription`
25
+ - `seoTitle`
26
+ - `seoDescription`
27
+
28
+ Inline override editing from the manager is not implemented yet. Open the generated docs record to edit overrides.
@@ -0,0 +1,39 @@
1
+ # Frontmatter
2
+
3
+ Use only this supported frontmatter subset.
4
+
5
+ ```yaml
6
+ ---
7
+ title: Installation
8
+ navTitle: Install
9
+ description: Install and configure docs sync.
10
+ order: 10
11
+ status: published
12
+ tags:
13
+ - getting-started
14
+ redirectFrom:
15
+ - /docs/install
16
+ ---
17
+ ```
18
+
19
+ Supported fields:
20
+
21
+ - `title`
22
+ - `navTitle`
23
+ - `description`
24
+ - `order`
25
+ - `status`
26
+ - `slug`
27
+ - `tags`
28
+ - `redirectFrom`
29
+ - `draft`
30
+
31
+ Rules:
32
+
33
+ - `status` must be `draft` or `published`.
34
+ - `order` must be a number.
35
+ - `tags` and `redirectFrom` must use list item syntax.
36
+ - `slug` may contain letters, numbers, and hyphens.
37
+ - Avoid arbitrary nested YAML objects.
38
+ - Avoid unsupported fields unless the user accepts validation warnings.
39
+ - Explicit `title` is preferred even though title fallback exists.
@@ -0,0 +1,77 @@
1
+ # Payload Markdown Directives
2
+
3
+ Use directives to make docs clearer while keeping Markdown readable in Git.
4
+
5
+ ## Table Of Contents
6
+
7
+ ```markdown
8
+ :::toc {title="On this page" depth="3" theme="compact"}
9
+ :::
10
+ ```
11
+
12
+ Use near the top of long reference or configuration pages.
13
+
14
+ ## Callout
15
+
16
+ ```markdown
17
+ :::callout {variant="warning" title="Server-owned authority"}
18
+ The request may ask. The Payload plugin decides.
19
+ :::
20
+ ```
21
+
22
+ Use for warnings, notes, tips, and important constraints.
23
+
24
+ ## Details
25
+
26
+ ```markdown
27
+ :::details {title="Advanced notes"}
28
+ Optional deeper explanation.
29
+ :::
30
+ ```
31
+
32
+ Use for advanced or secondary material.
33
+
34
+ ## Steps
35
+
36
+ ```markdown
37
+ :::steps {variant="cards" layout="stack" numbered stepTheme="glass"}
38
+
39
+ ### Generate keys
40
+
41
+ Run keygen.
42
+
43
+ ### Configure Payload
44
+
45
+ Add the public key.
46
+
47
+ :::
48
+ ```
49
+
50
+ Use for ordered procedures.
51
+
52
+ ## Cards
53
+
54
+ ```markdown
55
+ :::cards {columns="3" cardTheme="glass"}
56
+
57
+ :::card {title="Signed sync" href="/workflow/signed-push"}
58
+ Upload docs with signed requests.
59
+ :::
60
+
61
+ :::card {title="Route adapter" href="/frontend/route-adapter"}
62
+ Render docs without turning them into Pages.
63
+ :::
64
+
65
+ :::
66
+ ```
67
+
68
+ Use cards for overview pages and choice sets.
69
+
70
+ ## Gotchas
71
+
72
+ - Do not invent directive names.
73
+ - Keep blank lines around nested directive content.
74
+ - Use `:::steps` for procedures.
75
+ - Use `:::cards` for overview grids.
76
+ - Use `:::callout` for warnings, tips, and notes.
77
+ - Prefer root-relative docs links in directive attributes, such as `href="/workflow/signed-push"`.
@@ -0,0 +1,35 @@
1
+ # Routing
2
+
3
+ Docs are managed as docs sets, not as one Page per Markdown file.
4
+
5
+ ## Docs Groups
6
+
7
+ Docs groups reserve namespaces such as `/plugins` or `/internal/tools`.
8
+
9
+ ## Docs Sets
10
+
11
+ Docs sets represent one documentation site. They map a `sourceId` to a server-owned `routeBase`, such as:
12
+
13
+ ```text
14
+ /plugins/payload-markdown-docs
15
+ ```
16
+
17
+ ## Generated Docs
18
+
19
+ Generated docs records are internal storage for routing, search, sync correctness, and per-doc overrides.
20
+
21
+ `index.md` routes to the docs set route base. Nested files route below it.
22
+
23
+ ## Links
24
+
25
+ Use root-relative links inside the docs set:
26
+
27
+ ```markdown
28
+ [Quick start](/getting-started/quick-start)
29
+ ```
30
+
31
+ Do not hardcode production docs domains for internal navigation.
32
+
33
+ ## Route Adapter
34
+
35
+ The `/next` export can resolve docs routes and let an app fall back to normal Pages rendering when no docs route matches. It does not mutate Pages.
@@ -0,0 +1,35 @@
1
+ # Sync Safety Model
2
+
3
+ The sync workflow is authenticated and server-owned.
4
+
5
+ Important concepts:
6
+
7
+ - `source.id` maps to a configured docs set or allowed source.
8
+ - The docs set owns the route base.
9
+ - The manifest does not choose target collections or fields.
10
+ - `sync.allowWrites: true` is required for `mode: "sync"`.
11
+ - `sync.allowPublish: true` and `target.enableDrafts: true` are required for publishing.
12
+ - `sync.allowHardDelete: true` is required for hard delete.
13
+ - Archive is safer than delete.
14
+ - Manual edit conflicts abort before writes.
15
+
16
+ Ed25519 signed pushes verify:
17
+
18
+ - key id
19
+ - timestamp skew
20
+ - nonce replay
21
+ - body SHA-256
22
+ - Ed25519 signature
23
+ - manifest validity
24
+
25
+ GitHub OIDC pushes verify:
26
+
27
+ - bearer JWT signature through GitHub JWKS
28
+ - issuer and audience
29
+ - repository, owner, ref, workflow, and environment allowlists when configured
30
+ - pull request policy
31
+ - JWT `jti` replay protection
32
+ - body SHA-256
33
+ - manifest validity
34
+
35
+ Do not bypass failed auth or body verification. Fix the key, endpoint, source id, body, or server config.
@@ -0,0 +1,53 @@
1
+ # Troubleshooting
2
+
3
+ ## Invalid signature
4
+
5
+ Check key id, private key, endpoint pathname, timestamp, nonce, and exact body string.
6
+
7
+ ## OIDC invalid token
8
+
9
+ Check that the workflow uses `--github-oidc`, grants `id-token: write`, and requests the configured audience.
10
+
11
+ ## OIDC repository or ref not allowed
12
+
13
+ Check server OIDC allowlists. The request may ask; the server decides which repository and ref are trusted.
14
+
15
+ ## OIDC replay
16
+
17
+ Rerun the workflow so GitHub issues a fresh OIDC token with a new `jti`.
18
+
19
+ ## Body hash mismatch
20
+
21
+ The signed body is not the body that was sent. Sign and send the exact same JSON string.
22
+
23
+ ## Nonce replay
24
+
25
+ Generate a fresh request. Do not reuse signed headers.
26
+
27
+ ## Source not allowed
28
+
29
+ Create or update a docs set with the expected `sourceId`, or update server fallback sources.
30
+
31
+ ## Publish disabled
32
+
33
+ The server needs `sync.allowPublish: true` and a draft-enabled docs collection.
34
+
35
+ ## Hard delete disabled
36
+
37
+ Hard delete requires `sync.allowHardDelete: true`. Prefer archive unless the user explicitly needs deletion.
38
+
39
+ ## Route collision
40
+
41
+ A generated docs route overlaps another docs route or an opt-in Pages collision check.
42
+
43
+ ## Manual edit conflict
44
+
45
+ A generated docs record was edited outside the docs sync workflow. The sync aborts before writes.
46
+
47
+ ## Invalid frontmatter
48
+
49
+ Use only supported fields and simple YAML.
50
+
51
+ ## Non-root-relative link
52
+
53
+ Internal docs links should look like `/workflow/signed-push`, not `workflow/signed-push` or a production URL.
@@ -0,0 +1,39 @@
1
+ # Agent Docs Workflow
2
+
3
+ Use this workflow when editing docs source files.
4
+
5
+ 1. Inspect the docs tree, usually `{{docsRoot}}`.
6
+ 2. Edit Markdown files in place.
7
+ 3. Keep frontmatter valid and simple.
8
+ 4. Keep internal docs links root-relative.
9
+ 5. Use only supported `payload-markdown` directives.
10
+ 6. Run validation.
11
+ 7. Run plan when sync impact matters.
12
+ 8. Only push when the user asks for upload/sync and provides endpoint/auth context.
13
+
14
+ Validation:
15
+
16
+ ```bash
17
+ {{packageManager}} exec payload-markdown-docs validate {{docsRoot}} --source main-docs
18
+ ```
19
+
20
+ Plan:
21
+
22
+ ```bash
23
+ {{packageManager}} exec payload-markdown-docs plan {{docsRoot}} --source main-docs
24
+ ```
25
+
26
+ Dry-run upload with GitHub OIDC:
27
+
28
+ ```bash
29
+ {{packageManager}} exec payload-markdown-docs push {{docsRoot}} \
30
+ --endpoint "$DOCS_SYNC_ENDPOINT" \
31
+ --source main-docs \
32
+ --github-oidc \
33
+ --oidc-audience payload-markdown-docs \
34
+ --dry-run
35
+ ```
36
+
37
+ Use Ed25519 key flags only when the project is not using GitHub OIDC.
38
+
39
+ Do not directly edit generated Payload docs records unless the user specifically asks for Payload-side overrides.