Files
kandev/docs/plans/published-docs-preview-reliability/plan.md
T
2026-07-31 21:52:05 +01:00

4.3 KiB

spec, created, status
spec created status
docs/specs/published-docs-preview-reliability/spec.md 2026-07-31 implemented

Implementation Plan: Published Docs Preview Reliability

Overview

The cited preview failed because .github/workflows/notify-docs.yml launches landing without GITHUB_TOKEN; the renderer therefore consumes the hosted runner IP's 60-request unauthenticated quota and rejects any generated fallback community data. The repair first adds a static regression test for the workflow permission boundary, then authenticates the build with a read-only job token and moves preview-comment publication to a separate write-capable job.

Root Cause

  • The preview build step exports KANDEV_DOCS_SOURCE_PATH but not GITHUB_TOKEN, confirmed by the failing log's [github-auth] configured=false diagnostic.
  • Landing fetches repository metrics and contribution activity during static generation. A non-success response produces fallback markup that build-pages.mjs rejects.
  • GitHub's unauthenticated REST quota is IP-scoped and limited to 60 requests per hour, so runner starting quota and concurrent consumption make the result intermittent.
  • The existing preview job also owns issue and pull-request write permissions for its final comment step. Passing that job token directly to the build would make the preview reliable but violate least privilege.

Workflow

Static permission contract

  • Add scripts/notify-docs-workflow.test.mjs to inspect the checked-in workflow and prove the preview build has an explicit token, the preview job is read-only, and preview-link publication is isolated in a write-capable job that does not build pull request content.
  • Add the new test to the workflow's pull-request path filter and validator test command so future workflow changes keep exercising the contract.

Authenticated preview build

  • Restrict jobs.preview.permissions in .github/workflows/notify-docs.yml to contents: read.
  • Export GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} only from the Build preview from pull request docs step. Landing already recognizes this environment variable through its existing githubApiHeaders() contract.
  • Export the Cloudflare-enabled flag, deployment URL, and alias URL as preview job outputs.

Isolated preview comment

  • Move Publish docs preview link into a publish-preview-link job that needs preview, runs only when preview deployment is enabled, and owns issues: write plus pull-requests: write.
  • Pass deployment outputs through needs.preview.outputs and retain the existing idempotent marker-based create-or-update script.

Tests

  • What: the landing build receives an explicit authenticated token while its job cannot write issues or pull requests. File: scripts/notify-docs-workflow.test.mjs. How: extract the checked-in preview job and named build step from the YAML text, then assert the token mapping and permission exclusions.
  • What: preview comment publication retains write permissions without executing the landing build. File: scripts/notify-docs-workflow.test.mjs. How: extract the publication job and assert its dependency, output inputs, permissions, and absence of checkout/build steps.
  • What: public-doc validation and the workflow contract remain green under the exact command used by CI. File: .github/workflows/notify-docs.yml. How: run both Node test files together, then run the public-doc validator.

Implementation Waves And Parallel Candidates

Execution is sequential because the regression test and workflow repair share the same permission and job-output contract.

Documentation Impact

The concise repair spec records CI behavior and permissions. No public CLI, configuration, API, deployment, or UI documentation changes are required.

Risks

  • Job outputs must preserve the exact Cloudflare action output values across the new job boundary.
  • The publication job must remain skipped when Cloudflare is unconfigured or preview fails.
  • Exposing the token at workflow or job scope would unnecessarily widen its availability; the implementation must keep it scoped to the build step.