forgeconv

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package forgeconv implements lint rules that enforce forge codegen conventions on proto files. These analyzers exist because forge's codegen is annotation-driven (see internal/cli/orm_entity.go) — it does NOT auto-detect entity / pk / tenant / timestamp semantics by field name. The analyzers here catch the cases that previously failed silently or blew up at generate time, surfacing them as actionable lint findings with explicit remediation messages before `forge generate` runs.

The full list of rules:

forgeconv-one-service-per-file   one service per .proto, full stop
forgeconv-pk-annotation          fields named `id` need `pk: true` (or message must mark some field PK)
forgeconv-timestamps             `*_at` Timestamp fields need entity timestamps:true OR field-level annotation
forgeconv-tenant-annotation      tenant-shaped field names need `tenant: true` when entity is tenant-scoped
forgeconv-method-auth-annotation each RPC declares its auth posture via (forge.v1.method); auth-by-omission is a security hazard

The package exposes a single LintProtoTree entry point that takes a project root (or any directory containing .proto files) and returns a Result. Findings are emitted in deterministic order (file, then byte position) so output is stable across runs.

Index

Constants

View Source
const (
	SeverityError   = finding.SeverityError
	SeverityWarning = finding.SeverityWarning
)

Severity enum values (aliases onto the canonical single-spelling set).

Variables

This section is empty.

Functions

This section is empty.

Types

type Finding

type Finding = finding.Finding

Finding is the shared linter finding shape, re-exported under the historical forgeconv spelling. forgeconv findings populate Rule/Severity/File/Line/Message/Remediation.

type LintOptions

type LintOptions struct {
	// Strict escalates advisory security findings to errors. Today this
	// flips forgeconv-method-auth-annotation from warning to error so a
	// missing `(forge.v1.method)` annotation fails `forge lint --strict`
	// (and, by extension, CI). The default keeps it a warning so the rule
	// can land without breaking existing trees on day one — see
	// FORGE_SHAPE_REDESIGN §7e (auth-by-omission is a security hazard;
	// the long-term intent is default-deny / required annotation).
	Strict bool
}

LintOptions tunes the proto convention analyzers. The zero value is the default (advisory) posture; callers opt into stricter gating.

type Result

type Result struct {
	Findings []Finding `json:"findings"`
}

Result aggregates findings from a single lint run. It is a distinct type (not an alias) so forgeconv can hang its own FormatText rendering on it; the finding vocabulary inside is the shared one.

func LintFrontendHookTests

func LintFrontendHookTests(rootDir string) (Result, error)

LintFrontendHookTests walks rootDir/frontends/*/src/hooks/ for *-hooks.ts files and warns when no sibling test file or starter is present. Returns findings ordered by (file, line) to keep CI logs stable. A missing frontends/ tree is not an error — projects without any frontends produce an empty Result.

func LintFrontendStores

func LintFrontendStores(rootDir string) (Result, error)

LintFrontendStores scans frontends/<name>/src/stores/*.ts and web/src/store/*.ts for files that both spin up a Zustand store AND pull in a generated Connect client. Warnings only. A project with no frontends at all gets an empty result.

Findings are sorted by (file, line, rule) for stable output. Line is the line where reZustandCreate hits (the user's eye goes to the store-factory call, not the import line).

func LintHandlerErrorMapping

func LintHandlerErrorMapping(rootDir string) (Result, error)

LintHandlerErrorMapping walks rootDir for Go files under handlers/ directories and flags hand-rolled service-error → connect.Error helpers. Returns findings in deterministic order.

The walk recognises any directory whose path component is exactly "handlers" as the canonical handler tree (matches the project-template `internal/handlers/<svc>/` shape). Test files (_test.go) are skipped — fixtures and table tests sometimes legitimately construct connect errors for assertions.

func LintHandlerFileSize

func LintHandlerFileSize(rootDir string, threshold int) (Result, error)

LintHandlerFileSize walks rootDir/handlers/ for *.go files and warns on any whose source-LOC count exceeds threshold. Test files (*_test.go) and generated files (*_gen.go) are excluded — they have their own size dynamics (table-driven tests legitimately go long; generated files aren't user-owned). A missing handlers/ directory is not an error (CLI / library projects).

Findings are emitted in deterministic order (file, then rule).

func LintHandlerTests

func LintHandlerTests(rootDir string) (Result, error)

LintHandlerTests walks rootDir/handlers/ for *_test.go files and warns when each looks like the hand-rolled `tests := []struct{name, call}` shape rather than `tdd.RunRPCCases`. Returns findings in deterministic order (file, then line). A missing internal/handlers/ directory is not an error — projects without an internal/handlers/ tree (CLI, library kinds) get an empty result.

func LintOptionalDepMarkerPosition

func LintOptionalDepMarkerPosition(rootDir string) (Result, error)

LintOptionalDepMarkerPosition walks rootDir's internal/handlers/, internal/workers/, and internal/operators/ trees for files whose comments mention the `forge:optional-dep` marker, and emits a finding when the marker is not attached to a `Deps` struct field. Returns findings in deterministic order (file, then line). Missing component dirs are not an error — projects may ship none of them.

func LintProtoTree

func LintProtoTree(rootDir string) (Result, error)

LintProtoTree walks rootDir for .proto files and runs every analyzer in the default (advisory) posture. Thin wrapper over LintProtoTreeOpts kept for the existing call sites + tests.

func LintProtoTreeOpts

func LintProtoTreeOpts(rootDir string, opts LintOptions) (Result, error)

LintProtoTreeOpts walks rootDir for .proto files and runs every analyzer with the supplied options. Files under proto/forge/ (vendored forge annotation protos) are skipped — they're external definitions, not user code. Returns a deterministic Result ordered by (file, line, rule).

func (Result) FormatText

func (r Result) FormatText() string

FormatText renders findings as a human-readable report. Empty result produces an empty string so callers can prefix their own success line.

func (Result) HasErrors

func (r Result) HasErrors() bool

HasErrors returns true if any finding has Severity == SeverityError. Used by `forge lint` to decide exit status.

type Severity

type Severity = finding.Severity

Severity is the shared finding severity vocabulary, re-exported under the historical forgeconv spelling.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL