Skip to content

feat: add strict gRPC contracts - #1

Merged
intel352 merged 2 commits into
mainfrom
feat/strict-grpc-contracts
Apr 27, 2026
Merged

intel352 merged 2 commits into
mainfrom
feat/strict-grpc-contracts

Conversation

@intel352

Copy link
Copy Markdown
Contributor

Summary

  • add protobuf-backed strict contracts for audit modules, steps, and service methods
  • expose typed providers and runtime contract registry
  • add strict typed query/export/annotate adapters with effective-merge validation and optional zero-preserving limit semantics
  • package plugin.contracts.json for install/release and wire local build version ldflags

Verification

  • GOWORK=off go test ./... -count=1
  • make test
  • GOWORK=off go vet ./...
  • GOWORK=off go mod tidy -diff
  • git diff --check
  • jq empty plugin.json plugin.contracts.json
  • GOWORK=off go run github.com/GoCodeAlone/workflow/cmd/wfctl@v0.19.0 plugin validate -file plugin.json
  • make build

Review

  • local code-review agent verdict: SHIP-IT

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds protobuf-backed “strict” contracts for audit modules/steps/service methods and wires typed providers + a runtime contract registry so the plugin can be validated/consumed via gRPC/typed adapters.

Changes:

  • Introduce plugin.contracts.json + protobuf definitions for strict module/step/service contracts.
  • Add typed module/step creation + contract registry exposure in the plugin implementation.
  • Update build/release/CI plumbing (ldflags versioning, goreleaser packaging, GOWORK=off CI) and bump dependencies/engine minimum.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
plugin.json Bumps version/minEngineVersion; adds download artifacts + declares service methods capability.
plugin.contracts.json Declares strict contract manifest for modules/steps/service methods.
internal/typed.go Implements typed step handlers and typed service method invocation + proto↔map adapters.
internal/plugin_contracts_test.go Adds tests validating strict contracts, registry, and typed behavior.
internal/plugin.go Adds typed providers and contract registry; makes type lists defensive; returns errors for unknown types.
internal/contracts/audit.proto Defines protobuf message contracts for configs/inputs/outputs and service request/response types.
internal/contracts/audit.pb.go Generated Go code for the protobuf contracts.
go.mod Bumps workflow engine dependency and adds/upgrades related deps.
go.sum Updates checksums for upgraded dependencies.
Makefile Adds build/test/install targets with ldflags version wiring and contracts install packaging.
.goreleaser.yaml Updates plugin.json sed to rewrite download URLs; includes plugin.contracts.json in archives.
.github/workflows/ci.yml Forces GOWORK=off for build/test/vet in CI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/typed.go Outdated
}
events = append(events, auditEvent)
}
raw, _ := json.Marshal(events)

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exportInputToMap ignores the json.Marshal error when encoding events (raw, _ := json.Marshal(events)). If marshaling fails, this currently returns an empty/partial map without surfacing the failure, which can make typed export behave incorrectly and hide data-loss bugs. Return the marshal error to the caller instead of discarding it.

Suggested change
raw, _ := json.Marshal(events)
raw, err := json.Marshal(events)
if err != nil {
return nil, err
}

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in e1d51b8 by returning the json.Marshal error from exportInputToMap instead of discarding it.

Comment thread internal/typed.go Outdated
Comment on lines +149 to +162
func protoMessageToMap(msg proto.Message) map[string]any {
if msg == nil {
return nil
}
raw, err := (protojson.MarshalOptions{UseProtoNames: true}).Marshal(msg)
if err != nil {
return nil
}
values := map[string]any{}
if err := json.Unmarshal(raw, &values); err != nil {
return nil
}
return values
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protoMessageToMap is currently unused in this package, and it also swallows marshal/unmarshal errors by returning nil. Consider removing it if it’s dead code, or changing it to return (map[string]any, error) so callers can distinguish a real empty map from a conversion failure.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in e1d51b8 by removing the unused protoMessageToMap helper entirely.

Comment thread internal/typed.go
Comment on lines +272 to +280
func parseOptionalQueryTimestamp(name, raw string) (*time.Time, error) {
if raw == "" {
return nil, nil
}
parsed, err := time.Parse(time.RFC3339Nano, raw)
if err != nil {
return nil, fmt.Errorf("%s timestamp %q: %w", name, raw, err)
}
return &parsed, nil

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseOptionalQueryTimestamp validates query timestamps using time.RFC3339Nano, but the runtime query parsing in AuditQueryStep / CollectorModule uses time.RFC3339. This can accept timestamps with fractional seconds during typed validation that will later be ignored by the runtime parser, leading to inconsistent query behavior. Align both sides to the same layout (either switch validation to RFC3339, or update the runtime parsers to RFC3339Nano) and add/adjust a test to cover fractional-second timestamps.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in e1d51b8 by aligning runtime query parsing to RFC3339Nano and adding a typed fractional-second bounds regression test.

@intel352
intel352 merged commit a720577 into main Apr 27, 2026
4 checks passed
@intel352
intel352 deleted the feat/strict-grpc-contracts branch April 27, 2026 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants