Skip to content

[nightshift] doc-drift: documentation out of sync with code #21

@nightshift-micr

Description

@nightshift-micr

TailStick Documentation Drift Report

Repository: ~/nightshift-workspace/clones/tailstick
Analysis Date: 2026-04-17
Analyzer: nightshift doc-drift (automated)


Summary

Severity Count
P0 Critical 0
P1 High 4
P2 Medium 5
P3 Low 3
Total 12

Findings

DRIFT-001: Go version mismatch between go.mod, docs, and CI

  • Severity: P1 High
  • Files:
    • go.mod line 3: go 1.25.6
    • README.md line 29: Go 1.22+ is required for building from source
    • CONTRIBUTING.md line 7: Go 1.22+ is required
    • .github/workflows/ci.yml line 17: go-version: "1.22"
    • .github/workflows/release.yml line 36: go-version: "1.22"
    • .github/workflows/live-e2e.yml lines 32, 120: go-version: "1.25.6"
  • Description: go.mod declares go 1.25.6, but README and CONTRIBUTING say "Go 1.22+." The CI and release workflows use Go 1.22, while only the live-e2e workflow uses 1.25.6. A go build with Go 1.22 will fail against a go.mod requiring 1.25.6. The docs, CI, and go.mod are all inconsistent with each other.
  • Recommendation: Decide on the minimum Go version. If 1.25.6 is required, update README, CONTRIBUTING, ci.yml, and release.yml to match. If 1.22 is the target, downgrade go.mod. Align all references.

DRIFT-002: Release artifact names and formats in docs don't match CI

  • Severity: P1 High
  • Files:
    • docs/release-runbook.md lines 49-52: lists tailstick-linux-amd64.tar.gz, tailstick-linux-arm64.tar.gz, tailstick-windows-amd64.tar.gz, tailstick-windows-arm64.tar.gz
    • .github/workflows/release.yml lines 41-49: builds tailstick-cli-{os}-{arch} and tailstick-gui-{os}-{arch} as raw binaries
  • Description: The release runbook documents .tar.gz archives (4 total), but release.yml produces 8 individual raw binaries named tailstick-cli-linux-amd64, tailstick-gui-linux-amd64, etc. The names and formats are completely different. Anyone following the runbook to verify releases will not find the documented artifacts.
  • Recommendation: Update the release runbook to reflect the actual artifact naming scheme: tailstick-cli-{os}-{arch} and tailstick-gui-{os}-{arch} (8 binaries total, no tar.gz). Alternatively, modify release.yml to produce the documented tar.gz archives.

DRIFT-003: docs/configuration.md example config link is a local absolute path

  • Severity: P1 High
  • Files:
    • docs/configuration.md line 5: [configs/tailstick.config.example.json](/home/ubuntu/workspace/tailscale-usb/configs/tailstick.config.example.json)
  • Description: The example config link points to /home/ubuntu/workspace/tailscale-usb/configs/... — a developer's local filesystem path from a different machine/project. This link will 404 for anyone else and is not a valid relative path in the repo.
  • Recommendation: Change to a relative path: [configs/tailstick.config.example.json](../configs/tailstick.config.example.json).

DRIFT-004: Go module path doesn't match GitHub repository URL

  • Severity: P1 High
  • Files:
    • go.mod line 1: module github.com/tailstick/tailstick
    • README.md lines 10-11: references github.com/Microck/tailstick
    • CONTRIBUTING.md line 55: references Microck/tailstick
    • .github/workflows/release.yml line 59: gh run list -R Microck/tailstick
  • Description: The Go module path is github.com/tailstick/tailstick, but the actual GitHub repository is github.com/Microck/tailstick. Running go build or go get would attempt to resolve the module from the wrong URL (github.com/tailstick/tailstick), which either doesn't exist or is a different repo.
  • Recommendation: Update go.mod to module github.com/Microck/tailstick and update all Go import paths accordingly, or ensure the github.com/tailstick/tailstick GitHub redirect/mirror exists and works.

DRIFT-005: Makefile build-all only builds amd64; README claims arm64 support

  • Severity: P2 Medium
  • Files:
    • README.md line 49: "release binaries are built for linux/amd64, linux/arm64, windows/amd64, and windows/arm64"
    • README.md lines 183-184: make build-all listed as way to cross-compile all targets
    • Makefile lines 21-25: build-all only builds GOARCH=amd64 for all 4 targets
  • Description: README says make build-all cross-compiles all targets including arm64, but the Makefile's build-all target only builds amd64 variants. The release.yml CI workflow does build arm64, but developers using make build-all locally won't get arm64 binaries.
  • Recommendation: Either add arm64 builds to the Makefile build-all target, or update README to clarify that make build-all only builds amd64 and that arm64 builds are done in CI.

DRIFT-006: Preset creator generates config fields not supported by the Go model

  • Severity: P2 Medium
  • Files:
    • .github/pages/index.html lines 464-478: generates defaultMode, defaultChannel, defaultDays fields in preset objects
    • assets/preset-creator.html lines 385-392: same fields
    • internal/model/types.go lines 39-53: Preset struct has no defaultMode, defaultChannel, or defaultDays fields
  • Description: The preset creator web tool generates JSON with defaultMode, defaultChannel, and defaultDays fields per preset, but the Go Preset struct doesn't define these fields. When the config is loaded, these fields are silently ignored by json.Unmarshal. Users who build configs with the preset creator will have non-functional fields in their JSON.
  • Recommendation: Either add DefaultMode, DefaultChannel, and DefaultDays to the model.Preset struct and implement the corresponding logic, or remove these fields from the preset creator output.

DRIFT-007: --audit default path is relative to config directory, not current directory

  • Severity: P2 Medium
  • Files:
    • README.md line 76: --audit | logs/tailstick-audit.ndjson
    • internal/app/workflow.go lines 56-58: rt.AuditPath = filepath.Join(filepath.Dir(rt.ConfigPath), "logs", "tailstick-audit.ndjson")
  • Description: README documents the default audit path as logs/tailstick-audit.ndjson, implying it's relative to the current working directory. The actual code makes it relative to the config file's directory. In USB deployment (config on the USB drive), this is a meaningful difference — the audit log goes on the USB drive, not in the CWD.
  • Recommendation: Update README to clarify: --audit default is logs/tailstick-audit.ndjson (relative to config file directory). This is consistent with docs/operations.md line 55 which says <config_dir>/logs/tailstick-audit.ndjson.

DRIFT-008: --non-interactive flag documented for run but not available in GUI mode

  • Severity: P2 Medium
  • Files:
    • README.md line 72: --non-interactive documented as a run flag
    • internal/app/gui.go: RunGUI does not accept or pass NonInteractive
    • internal/gui/server.go lines 33-43: enrollRequest has no nonInteractive field
  • Description: The --non-interactive flag is documented as a run flag and implemented in the CLI, but the GUI mode always sets NonInteractive: false. This is not documented. While it makes sense (GUI is inherently interactive), a user reading the docs might expect this flag to work in the GUI binary too, especially since the README lists shared flags for both modes.
  • Recommendation: Add a note in the README GUI flags section clarifying that --non-interactive is CLI-only.

DRIFT-009: --days description in README is misleading about valid values

  • Severity: P2 Medium
  • Files:
    • README.md line 67: --days described generically as "timed lease duration in days"
    • internal/tailscale/client.go lines 253-258: ParseDurationDays validates days must be in {1, 3, 7}
  • Description: The README implies --days accepts any number, but the code only accepts 1, 3, or 7. Users who try --days 5 will get an error: "timed lease requires days in {1,3,7} or custom-days in [1,30]". The README should document this constraint.
  • Recommendation: Change the README --days description to: "timed lease duration in days (allowed: 1, 3, or 7; use --custom-days for other values)".

DRIFT-010: README mentions tailstick.micr.dev preset maker URL; pages.yml deploys from .github/pages/

  • Severity: P3 Low
  • Files:
    • README.md line 35: "use the optional preset maker"
    • .github/workflows/pages.yml: deploys .github/pages/ directory as GitHub Pages
  • Description: The README links to tailstick.micr.dev for the preset maker, which is presumably a custom domain pointing to the GitHub Pages deployment. If the custom domain is not configured in the repo settings, this URL won't work. The internal reference is consistent (.github/pages/index.html is the preset creator), but the external URL depends on DNS configuration outside the repo.
  • Recommendation: Verify the custom domain is configured in GitHub Pages settings. Consider adding a fallback link like [preset maker](https://microck.github.io/tailstick/) or noting the URL may vary.

DRIFT-011: internal/platform/exec.go package doc comment says "Runner interface" but Runner is a concrete struct

  • Severity: P3 Low
  • Files:
    • internal/platform/exec.go line 3: doc comment says "It provides a Runner interface"
    • internal/platform/exec.go line 15: type Runner struct { ... }
  • Description: The package-level doc comment in exec.go says it provides a "Runner interface," but Runner is actually a concrete struct, not a Go interface. This is a minor inaccuracy in the code documentation.
  • Recommendation: Change the doc comment from "It provides a Runner interface" to "It provides a Runner type."

DRIFT-012: CONTRIBUTING.md says go build ./... but Makefile uses targeted builds

  • Severity: P3 Low
  • Files:
    • CONTRIBUTING.md line 10: go build ./...
    • Makefile lines 14-18: build target builds specific ./cmd/* entrypoints
  • Description: CONTRIBUTING.md suggests go build ./... as the development build command. While this works, it differs from the Makefile's targeted build approach. More importantly, go build ./... builds all packages but only leaves binaries for main packages, which is fine but not the canonical approach documented in the Makefile and README.
  • Recommendation: Consider aligning CONTRIBUTING.md with the README's build instructions or the Makefile's build target for consistency.

Methodology

  1. Read all documentation files: README.md, CONTRIBUTING.md, docs/architecture.md, docs/configuration.md, docs/operations.md, docs/testing.md, docs/release-runbook.md
  2. Read all Go source files: go.mod, cmd/*/main.go, internal/app/cli.go, internal/app/gui.go, internal/app/workflow.go, internal/config/config.go, internal/model/types.go, internal/platform/platform.go, internal/platform/exec.go, internal/tailscale/client.go, internal/gui/server.go
  3. Read all CI/CD configs: .github/workflows/ci.yml, .github/workflows/release.yml, .github/workflows/live-e2e.yml, .github/workflows/pages.yml
  4. Read supporting files: Makefile, configs/tailstick.config.example.json, .env.example, .gitignore, .github/pages/index.html, assets/preset-creator.html
  5. Cross-referenced documented CLI flags against actual flag.NewFlagSet definitions
  6. Cross-referenced documented config fields against model.Config and model.Preset structs
  7. Cross-referenced CI workflow configurations against documented build/test procedures
  8. Cross-referenced release artifact naming between runbook and release.yml

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions