@ihelpee/prumo-plugin-go-gin 0.8.3 → 0.9.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.
package/README.md CHANGED
@@ -9,17 +9,17 @@
9
9
 
10
10
  > Official **Go/Gin** architectural invariant plugin for [Prumo](https://www.npmjs.com/package/@ihelpee/prumo) — the deterministic gatekeeper and business guardrails for AI-assisted engineering.
11
11
 
12
- Em Go, os três modos de falha que IA mais comete são estruturais: **rota de mutação sem auth** (Gin espalha middleware por três camadas — inline, `Group.Use`, `Engine.Use` — e a camada de grupo é onde o falso-negativo mora), **erro engolido** (`_ = err`, `x, _ := f()` — a falha silenciosa nativa da linguagem) e **binding sem validação** (`ShouldBindJSON` numa struct sem tags `binding:"..."`). Este plugin fiscaliza os três com AST estática pura — **sem boot do app, sem `go build` do alvo, sem rede**.
12
+ In Go, the three failure modes AI commits most often are structural: **a mutation route without auth** (Gin spreads middleware across three layers — inline, `Group.Use`, `Engine.Use` — and the group layer is where the false-negative lives), **a swallowed error** (`_ = err`, `x, _ := f()` — the language's native silent failure) and **binding without validation** (`ShouldBindJSON` on a struct without `binding:"..."` tags). This plugin polices all three with pure static AST analysis — **no app boot, no `go build` of the target, no network**.
13
13
 
14
- Go é também a única linguagem do ecossistema Prumo em que a lei do oráculo ("quem gera não especifica a correção") pode ser imposta pelo **próprio compilador**: implementação sob `internal/**` e oráculo num módulo separado (`oracle/go.mod`) tornam o import da implementação um erro de build, não um achado de lint. O plugin recomenda essa topologia como gold standard e tolera a de módulo único (coberta pela regra estática).
14
+ Go is also the only language in the Prumo ecosystem where the oracle law ("whoever generates does not specify correctness") can be enforced by **the compiler itself**: implementation under `internal/**` and the oracle in a separate module (`oracle/go.mod`) turn importing the implementation into a build error, not a lint finding. The plugin recommends this topology as the gold standard and tolerates the single-module one (covered by the static rule).
15
15
 
16
- ## Instalação
16
+ ## Installation
17
17
 
18
18
  ```bash
19
19
  pnpm add -D @ihelpee/prumo-plugin-go-gin @ihelpee/prumo
20
20
  ```
21
21
 
22
- Configure em `prumo.config.ts` (o caminho real é `invariants:`, não `plugins:`):
22
+ Configure it in `prumo.config.ts` (the real key is `invariants:`, not `plugins:`):
23
23
 
24
24
  ```ts
25
25
  import { defineConfig } from '@ihelpee/prumo';
@@ -39,66 +39,73 @@ export default defineConfig({
39
39
  });
40
40
  ```
41
41
 
42
- Ou em `.prumo/invariants/rules.ts` (onde vivem os waivers):
42
+ Or in `.prumo/invariants/rules.ts` (where the waivers live):
43
43
 
44
44
  ```ts
45
45
  import { goGinPreset } from '@ihelpee/prumo-plugin-go-gin';
46
46
  export default goGinPreset;
47
47
  ```
48
48
 
49
- ## Invariantes
49
+ ## Invariants
50
50
 
51
- | id | sev. | o footgun | fronteira honesta (o que NÃO pega) |
51
+ | id | sev. | the footgun | the honest boundary (what it does NOT catch) |
52
52
  |---|---|---|---|
53
- | `mutation-routes-guarded` | error | rota de mutação (`POST`/`PUT`/`PATCH`/`DELETE`) sem auth em **nenhuma** camada — inline, `Group.Use`, `Engine.Use`, com herança **transitiva** de sub-grupos | `Recovery`/`Logger`/`CORS` não contam como auth; `NoAuth()` explícito marca público intencional; rotas de leitura nunca são alvo |
54
- | `error-handling-enforced` | error | erro descartado deliberadamente: `_ = err`, `x, _ := f()` | `if err := f(); err != nil` não é achado |
55
- | `error-handling-unchecked` | warn | chamada que retorna `error` usada como statement puro (`db.Save(o)`) | heurística sem type info: só funções em `knownErrReturning` ou vistas com `err` no mesmo arquivo; por isso `warn`, nunca bloqueia sem `--fail-on-warn` |
56
- | `payload-validation-bound` | error | `ShouldBindJSON`/`Bind` numa struct com campo de dados sem tag `binding:"..."` | tipo não resolvível sintaticamente **não é reportado** (nunca adivinha); `binding:"-"` é ignorado |
57
- | `payload-validation-query` | warn | binding de query/uri sem tag | validação de query é frequentemente opcional — `warn` |
58
- | `oracle-no-src` | error | teste de oráculo importando pacote interno da aplicação (resolvido contra o `module` do `go.mod`) | alias, dot e blank import são todos arestas — burla por alias bloqueada |
59
- | `oracle-whitebox-test` | error | `_test.go` dentro de `internal/**` declarando `package foo` — acessa símbolos não-exportados: espelho branco por construção | `package foo_test` é black-box e não viola |
60
- | `src-no-oracle` | error | produção importando o diretório de oráculo (fixture vazando para produção) | — |
61
- | `oracle-module-couples-app` | error | `oracle/go.mod` com `require`/`replace` do módulo da aplicação: a fronteira do compilador foi desativada de propósito | topologia de módulo único não tem `oracle/go.mod` e é coberta por `oracle-no-src` |
62
- | `no-cross-feature-import` | warn | `internal/<A>/` importando `internal/<B>/` | layouts Go variam — `warn` no MVP |
63
- | `monetary-is-integer` | warn | campo monetário como `float32`/`float64` | `int64` com sufixo `Cents` é limpo |
64
- | `go-toolchain-missing` | warn | `go` ausente no host: invariantes Go **não avaliados** | nunca silencioso; `--fail-on-warn` promove a bloqueio |
65
- | `go-parse-error` | error | arquivo `.go` que não parseia fica invisível às regras | corrigir/excluir o arquivo resolve |
66
-
67
- ## Como funciona (e por que é seguro)
68
-
69
- - **Extrator Go stdlib-only** (`go-extractor/`, módulo `ihelpee.dev/prumo-go-extractor`): `go/parser` + `go/ast` serializando a AST em **JSON canônico v1** no stdout. Zero dependência externa — qualquer `require` no `go.mod` do extrator é falha de build.
70
- - **O extrator é parser, não implementador da lei.** A decisão "isto é violação?" vive 100% no core Node (`rules.ts`). Dois implementadores da mesma lei driftam — auto-refutação para uma ferramenta que caça drift.
71
- - **Nunca executa o código analisado**: só `parser.ParseFile`. O `go run` do extrator roda de dentro do módulo isolado com `GOTOOLCHAIN=local` e `GOPROXY=off` — o grafo de dependências do alvo nunca é tocado, e a ausência de rede é mecânica, não acidental.
72
- - **Timeout** (default 20s) no subprocesso; parse patológico não trava o gate.
73
- - `go` ausente → achado `warn` nomeado, nunca skip mudo.
74
-
75
- ## Opções
53
+ | `mutation-routes-guarded` | error | a mutation route (`POST`/`PUT`/`PATCH`/`DELETE`) without auth in **any** layer — inline, `Group.Use`, `Engine.Use`, with **transitive** inheritance from sub-groups | `Recovery`/`Logger`/`CORS` don't count as auth; an explicit `NoAuth()` marks an intentionally public route; read routes are never targeted |
54
+ | `error-handling-enforced` | error | an error deliberately discarded: `_ = err`, `x, _ := f()` | `if err := f(); err != nil` is not a finding |
55
+ | `error-handling-unchecked` | warn | a call returning `error` used as a bare statement (`db.Save(o)`) | heuristic without type info: only functions in `knownErrReturning` or seen with `err` in the same file; hence `warn`, never blocks without `--fail-on-warn` |
56
+ | `payload-validation-bound` | error | `ShouldBindJSON`/`Bind` on a struct with a data field lacking a `binding:"..."` tag | a type not resolvable syntactically **is not reported** (never guesses); `binding:"-"` is ignored |
57
+ | `payload-validation-query` | warn | query/uri binding without a tag | query validation is frequently optional — `warn` |
58
+ | `oracle-no-src` | error | an oracle test importing an internal application package (resolved against the `module` in `go.mod`) | alias, dot and blank imports are all edge cases — bypass via alias is blocked |
59
+ | `oracle-whitebox-test` | error | a `_test.go` inside `internal/**` declaring `package foo` — accesses unexported symbols: a white-box mirror by construction | `package foo_test` is black-box and does not violate |
60
+ | `src-no-oracle` | error | production importing the oracle directory (a fixture leaking into production) | — |
61
+ | `oracle-module-couples-app` | error | `oracle/go.mod` with a `require`/`replace` of the application module: the compiler boundary was disabled on purpose | the single-module topology has no `oracle/go.mod` and is covered by `oracle-no-src` |
62
+ | `no-cross-feature-import` | warn | `internal/<A>/` importing `internal/<B>/` | Go layouts vary — `warn` in the MVP |
63
+ | `monetary-is-integer` | warn | a monetary field as `float32`/`float64` | `int64` with a `Cents` suffix is clean |
64
+ | `go-toolchain-missing` | warn | `go` absent on the host: Go invariants are **not evaluated** | never silent; `--fail-on-warn` promotes it to a block |
65
+ | `go-parse-error` | error | a `.go` file that fails to parse becomes invisible to the rules | fixing/excluding the file resolves it |
66
+
67
+ ## How it works (and why it's safe)
68
+
69
+ - **Go stdlib-only extractor** (`go-extractor/`, module `ihelpee.dev/prumo-go-extractor`): `go/parser` + `go/ast` serializing the AST into **canonical JSON v1** on stdout. Zero external dependency — any `require` in the extractor's `go.mod` is a build failure.
70
+ - **The extractor is a parser, not an implementer of the law.** The "is this a violation?" decision lives 100% in the Node core (`rules.ts`). Two implementers of the same law drift — self-refutation for a tool that hunts drift.
71
+ - **It never runs the code under analysis**: only `parser.ParseFile`. The extractor's `go run` executes from inside the isolated module with `GOTOOLCHAIN=local` and `GOPROXY=off` — the target's dependency graph is never touched, and the absence of network is mechanical, not accidental.
72
+ - **Timeout** (default 20s) on the subprocess; a pathological parse won't hang the gate.
73
+ - `go` absent → a named `warn` finding, never a silent skip.
74
+
75
+ ## Options
76
76
 
77
77
  ```ts
78
78
  goGinPlugin({
79
79
  authSymbols: ['Auth', 'RequireAuth', 'JWTAuth'], // R3.5
80
80
  publicSymbols: ['NoAuth'], // R3.6
81
81
  knownErrReturning: ['Save', 'Exec', 'Do'], // R3.8
82
- excludePatterns: ['**/gen/**'], // R1.7 (vendor/ e gerados já são default)
82
+ excludePatterns: ['**/gen/**'], // R1.7 (vendor/ and generated are already default)
83
83
  srcDirs: ['internal', 'pkg', 'cmd'], // R2.5/R2.7
84
84
  oracleDirs: ['oracle', 'tests/oracle'], // R2.x
85
85
  timeoutMs: 20_000, // R1.5
86
86
  })
87
87
  ```
88
88
 
89
- ## Gold standard de oráculo em Go
89
+ ## The Go oracle gold standard
90
90
 
91
91
  ```
92
92
  orders/ # go.mod: module github.com/acme/orders
93
- internal/orders/handler.go # implementação — só importável neste módulo
93
+ internal/orders/handler.go # implementation — importable only within this module
94
94
  cmd/server/main.go
95
- oracle/ # módulo SEPARADO: go.mod próprio
96
- go.mod # SEM require/replace do módulo da aplicação
97
- orders_blackbox_test.go # HTTP black-box; expectativa do CONTRATO
95
+ oracle/ # SEPARATE module: its own go.mod
96
+ go.mod # WITHOUT require/replace of the application module
97
+ orders_blackbox_test.go # HTTP black-box; the CONTRACT's expectation
98
98
  ```
99
99
 
100
- Nessa topologia o teste-espelho **não compila** — a lei é física, não opinativa. O Prumo vira verificador de intenção (`oracle-module-couples-app`).
100
+ In this topology the mirror test **does not compile** — the law is physical, not opinionated. Prumo becomes an intent verifier (`oracle-module-couples-app`).
101
101
 
102
- ## License
102
+ ---
103
103
 
104
- Apache-2.0
104
+ ## License & Brand
105
+
106
+ Copyright © 2026 **IHELPEE TECNOLOGIA LTDA** (<https://ihelpee.com>). All rights reserved.
107
+ Created and authored by [Alex Gotardi](https://github.com/alexgotardi).
108
+
109
+ Licensed under the [Apache License, Version 2.0](https://github.com/ihelpee/prumo/blob/main/LICENSE) (the "License"); you may not use this file except in compliance with the License. A copy is available at <http://www.apache.org/licenses/LICENSE-2.0>.
110
+
111
+ The **"Prumo"** name and logo are trademarks of IHELPEE TECNOLOGIA LTDA and are **not** licensed under the Apache 2.0 license.
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EACZ,KAAK,OAAO,EAGb,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAOL,KAAK,YAAY,EAIlB,MAAM,UAAU,CAAC;AA6ElB;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAcnE;AASD,iFAAiF;AACjF,wBAAgB,YAAY,IAAI,OAAO,CAWtC;AAyFD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAkCtE;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,GAAE,YAAiB,GAAG,OAAO,CAyBvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CA+BvE;AAoBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAqChD;AAED,oGAAoG;AACpG,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAoCvE;AA6BD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CA2B5D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAyBnE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CA2B5D;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAgChD;AAwBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CA6BrE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAuB3C;AAUD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,YAAiB,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAyBpF;AAED,qFAAqF;AACrF,eAAO,MAAM,WAAW,EAAE,OAAO,EAAwB,CAAC;AAE1D,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EACZ,KAAK,OAAO,EAGb,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAOL,KAAK,YAAY,EAIlB,MAAM,UAAU,CAAC;AA8ElB;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAcnE;AASD,iFAAiF;AACjF,wBAAgB,YAAY,IAAI,OAAO,CAWtC;AAyFD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAkCtE;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,GAAE,YAAiB,GAAG,OAAO,CAyBvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CA+BvE;AAoBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAqChD;AAED,oGAAoG;AACpG,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAoCvE;AA6BD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CA2B5D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAyBnE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CA2B5D;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAgChD;AAwBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CA6BrE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAuB3C;AAUD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,YAAiB,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAyBpF;AAED,qFAAqF;AACrF,eAAO,MAAM,WAAW,EAAE,OAAO,EAAwB,CAAC;AAE1D,eAAe,WAAW,CAAC"}
package/dist/rules.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { rule, definePlugin, } from '@ihelpee/prumo/invariants';
2
2
  import { startsWithAny } from '@ihelpee/prumo/core';
3
3
  import { runGoExtractor, DEFAULT_AUTH_SYMBOLS, DEFAULT_PUBLIC_SYMBOLS, DEFAULT_KNOWN_ERR_RETURNING, DEFAULT_ORACLE_DIRS, } from './ast.js';
4
+ import pkg from '../package.json' with { type: 'json' };
4
5
  /**
5
6
  * Invariantes Go/Gin (spec `docs/especificacao-prumo-go-gin.md` §2 e §3).
6
7
  *
@@ -690,7 +691,7 @@ function isUnderAny(p, prefixes) {
690
691
  export function goGinPlugin(opts = {}) {
691
692
  return definePlugin({
692
693
  name: 'go-gin',
693
- version: '0.8.3',
694
+ version: pkg.version,
694
695
  description: 'Go/Gin invariants: mutation route guards (inline/Group.Use/Engine.Use transitivo), error-handling enforcement, payload binding validation, oracle isolation nativa de Go (internal/, white-box, módulo separado).',
695
696
  extractors: {
696
697
  go: async (ctx) => ({ result: await runGoExtractor(ctx.root, opts) }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ihelpee/prumo-plugin-go-gin",
3
- "version": "0.8.3",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "description": "Go/Gin plugin for Prumo: mutation route guards (inline/Group.Use/Engine.Use), error-handling enforcement, payload binding validation, and Go-native oracle isolation.",
6
6
  "author": "Alex Gotardi <alexgotardi@gmail.com>",
@@ -33,6 +33,6 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@ihelpee/prumo": "0.8.3"
36
+ "@ihelpee/prumo": "0.9.0"
37
37
  }
38
38
  }