guildhouse-spire-plugins/docs/testing.md
Tyler King 420a4e2ea0 Remediate all 17 audit findings from AUDIT.md
Critical fixes:
- F-01: SatScope array form support (single pointer → slice with polymorphic JSON)
- F-02: Add governance-intent@guildhouse.dev as 10th Shellstream extension
- F-06: Replace os.Exit(1) stubs with go-plugin Serve() boilerplate in all cmd/
- F-13: Validate SatScope.ResourcePattern is non-empty

High priority:
- F-03: Add normative Accord policy syntax note to credential-governance.md §8.2
- F-04: Replace OID XXXXX placeholder with explicit PEN reference and IANA TODO
- F-05: Document CredentialComposer hook mapping in spec and plugin-types.md
- F-07/F-08: Commit CI pipeline (.github/workflows/ci.yaml)
- F-09: Add hashicorp/go-plugin v1.6.3 to go.mod

Medium priority:
- F-10: Wire sample-ssh-cert-extensions.json fixture into shellstream tests
- F-11: Cross-reference merkle proof depth limit (256 leaves) in governance spec
- F-12: Add YAML format clarification headers to deploy configs
- F-14: Expand README with project status, docs links, and quick-start

Low priority:
- F-15: Standardize "SSH SVID" → "SSH-SVID" terminology across docs
- F-16: Add GovernanceEpochSeconds to PluginConfig and deploy configs
- F-17: Add troubleshooting section to deployment.md, error handling to OIDC docs

Global: Rename all extension keys from @guildhouse.io to @guildhouse.dev

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:45:33 -05:00

3.5 KiB

Testing Strategy

How to test the Guildhouse SPIRE plugins.

Running Tests

make test       # Run all tests
make lint       # Run go vet

# Verbose output
go test -v ./...

# Single package
go test -v ./pkg/shellstream/...

# With coverage
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

Test Structure

Unit Tests (pkg/)

Each package has *_test.go files with unit tests:

Package Tests Coverage Focus
pkg/shellstream ~28 tests Encode/decode round-trips, validation rules, format constraints, co-occurrence rules
pkg/oidc 2 tests Config validation (scaffolded)
pkg/governance 2 tests Client construction (scaffolded)
pkg/sshcert 3 tests Builder config validation (scaffolded)
pkg/config 2 tests Plugin config validation (scaffolded)

pkg/shellstream Tests (Fully Implemented)

The shellstream package has comprehensive tests covering:

  • Round-trip: Encode → Decode produces identical values (full and minimal)
  • Required fields: Missing tenant-id, missing roles produce validation errors
  • Format validation: Invalid UUID, wrong hex length, uppercase hex, invalid base64
  • Co-occurrence: sat-scope without sat-hash, ceremony-id without ceremony-type, merkle-proof without merkle-root
  • Parsing: JSON sat-scope, comma-separated roles, base64 merkle proof, uint64 governance epoch
  • Edge cases: Epoch value 0, nil extensions, unknown extensions ignored
  • Enum validation: Unknown ceremony-type rejected

Integration Test Approach (Future)

When plugin implementations are complete, integration tests will use mock gRPC servers:

// Example mock GovernanceService
type mockGovernanceServer struct {
    quartermasterv1.UnimplementedGovernanceServiceServer
    intents map[string]*Intent
}

func (s *mockGovernanceServer) CreateIntent(ctx context.Context, req *quartermasterv1.CreateIntentRequest) (*quartermasterv1.CreateIntentResponse, error) {
    // Return predictable responses for testing
}

Integration tests will:

  1. Start mock gRPC servers for GovernanceService, CeremonyService, NotaryService
  2. Create plugin instances pointed at the mock servers
  3. Invoke plugin methods (Attest, Compose, Notify)
  4. Verify the plugin made expected gRPC calls with correct parameters
  5. Verify the plugin handled error conditions (unreachable service, denied intent, ceremony timeout)

Test Fixtures

Test fixture files in test/fixtures/:

File Purpose
sample-oidc-token.json Example OIDC token payload for oidc-attestor testing
sample-sat-scope.json Example SatScope for governance client testing
sample-ssh-cert-extensions.json Example Shellstream extensions map for shellstream package testing
spire-test-config.hcl Example SPIRE plugin configuration for config package testing

Load fixtures in tests:

func loadFixture(t *testing.T, name string) []byte {
    t.Helper()
    data, err := os.ReadFile(filepath.Join("../../test/fixtures", name))
    if err != nil {
        t.Fatalf("load fixture %s: %v", name, err)
    }
    return data
}

CI Pipeline

The CI pipeline is defined in .github/workflows/ci.yaml. It runs on every push and pull request to master:

  1. Checks out the repository
  2. Sets up Go 1.23
  3. Runs make test (all unit tests)
  4. Runs make lint (go vet)
  5. Runs make build (compiles all 4 plugin binaries)

See .github/workflows/ci.yaml for the full workflow definition.