Files
sherlock/docs/conventions.md
T
amacocian fe71a4e60c
CI / build (push) Successful in 1m5s
Code fixes
2026-05-25 09:51:14 +02:00

3.6 KiB

Conventions

Rules that govern this repo. Anything that becomes load-bearing belongs here, in conventions.md, never in a section appended to another doc.

Repository layout

cmd/                    one subdir per shippable binary; package main only
internal/               every other package; never imported outside this module
internal/agent/profiles built-in TOML profiles, embedded with //go:embed
docs/                   one topic per file (see "Docs" below)
plan.md                 the long-form design doc; source-of-truth for phasing
README.md               TOC only

No top-level pkg/ until we have an external consumer.

Go

  • Module path: gitea.alexandru.macocian.me/Charlie/sherlock.
  • Target Go toolchain: go 1.25 (pinned via go.mod's go directive; CI installs the matching minor).
  • One package main per cmd/<binary>/. No multiple-main-files trickery.
  • Every other package has a top-of-file Package <name> ... doc comment (in the leading .go source file; we drop standalone doc.go files once a real source file exists).
  • Third-party deps are added with a one-line justification. The current set:
    • github.com/zalando/go-keyring — OS keyring for token persistence (Decision #8).
    • github.com/BurntSushi/toml — parse services.d/*.toml and agents.d/*.toml (Decision #4).
    • github.com/coreos/go-oidc/v3 — OIDC discovery + ID-token verification against Authentik.
    • golang.org/x/oauth2 — auth-code + PKCE + refresh against Authentik's token endpoint.
    • golang.org/x/syncsingleflight for collapsing concurrent token refreshes.

Docs

  • README.md is TOC only. One-line description + a bulleted index of docs/*.md.
  • One topic per file under docs/. Never append a new section to an existing doc to cover a new concern; create docs/<new-topic>.md and link it from README.md.
  • plan.md is the long-form design + phasing doc. It is allowed to be long.
  • Cross-link aggressively: every doc should link to the other docs whose concerns it touches.
  • ASCII diagrams over images. Diagrams live next to the prose that explains them.

Naming

  • Binaries are kebab-case (sherlock-broker, gitea-mcp).
  • Built-in agent profiles match the agent's canonical CLI name (copilot, claude, aider).
  • Service registry files match the service's canonical name (gitea.toml, grafana.toml).
  • Env vars are <SERVICE>_TOKEN (e.g. GITEA_TOKEN, GSSH_TOKEN).

Extensibility invariants

  • Agent extensibility: adding a new agent CLI MUST be a TOML drop-in under ~/.config/sherlock/agents.d/. If a code change is required, the design has drifted — fix the abstraction in internal/agent/, don't accept the code change.
  • Service extensibility: adding a new downstream service MUST be a TOML drop-in under ~/.config/sherlock/services.d/ + (optionally) a new cmd/<service>-mcp/ binary. The broker itself does not learn about individual services in Go code.

Commits

  • Conventional-ish: area: short imperative (e.g. broker: persist tokens with age, docs: add gssh-integration).
  • One logical change per commit. CI must pass on every commit on main.

CI

  • .gitea/workflows/ci.yaml runs on every push + PR. It runs gofmt, go vet, errcheck, staticcheck, go test -race, and go build. No other gates.
  • No deploy pipeline — sherlock is operator-installed via go install. Release artifacts (binaries to the gitea registry / releases) land in Phase 5 if at all.

Security

  • No secrets in this repo, ever. Not in tests, not in fixtures, not in comments.
  • The operator's Authentik tokens and (Phase 2+) per-service tokens live in the OS keyring. See storage.md.