Repository navigation
v1.9.0 — Schema Drift Detection
Adds runtime detection of mismatch between the codegen baseline schema and the schema currently deployed in SpiceDB. Closes a class of silent production bugs: binary built against schema v1 calling SpiceDB running schema v2 → mis-permission everything with no error path.
The codegen now emits a top-level `/schema.gen.go` with the source `.zed` bytes verbatim plus a `VerifySchema(ctx)` helper that calls SpiceDB's `DiffSchema` RPC, server-side normalises, and partitions typed diffs into severity buckets.
Added
- `authz.SchemaDrift` — drift report with `Added/Removed/Changed/Cosmetic []DriftEntry` and `IsBreaking()` / `IsClean()` predicates.
- `authz.DriftEntry` — `Description string` (human-readable) + `Raw *v1.ReflectionSchemaDiff` (typed wire payload).
- `Engine.DiffSchema(ctx, comparisonSchema)` — new interface method calling SpiceDB's `SchemaService.DiffSchema` RPC.
- Generated `/schema.gen.go` — new top-level file. `SchemaText` + `SchemaDigest` constants, `VerifySchema` helper, internal `bucketDrift` / `describeDrift`. Package name derives from output dir's last segment.
- 4 e2e tests in new `example/authzed/schema_test.go` covering clean / additive / breaking / cosmetic drift.
Caller pattern
```go
import authzed "github.com/danhtran94/authzed-codegen/example/authzed"
drift, err := authzed.VerifySchema(ctx)
if err != nil {
log.Fatalf("schema verification failed: %v", err)
}
if drift.IsBreaking() {
log.Fatalf("schema drift: %d removed, %d changed", len(drift.Removed), len(drift.Changed))
}
if !drift.IsClean() {
log.Warnf("schema is ahead: %d added, %d cosmetic", len(drift.Added), len(drift.Cosmetic))
}
```
Severity buckets (binary's perspective)
- Added — deployed has extras baseline doesn't know about (additive, safe)
- Removed — baseline expects but deployed lacks (breaking)
- Changed — semantic divergence in permission / caveat expressions or caveat parameter types (breaking)
- Cosmetic — doc comment changes only (safe)
Discoveries during implementation
- SPEC A7 was wrong — `example/schema.zed` contains backticks (inline-code in comments). Resolved via `strconv.Quote` instead of a raw string literal.
- DiffSchema RPC direction — SpiceDB returns diffs from the comparison schema's perspective. `_Added` from SpiceDB means "comparison has it, deployed lacks it" (BREAKING from binary view); `_Removed` means "deployed has extra" (ADDITIVE). The bucketing inverts these to match the SchemaDrift API's caller-friendly semantics.
Verified
- All 5 e2e packages pass (added new `example/authzed` package).
- Per-namespace `.gen.go` files byte-identical to v1.8.0 (additive change only).
- Codegen idempotent at the new baseline.
Deferred
- Auto-invoke at engine init — drift policy is opinionated (fail-fast vs log-and-continue). Caller-driven by design.
- CLI verify mode (`authzed-codegen --verify`) — out of scope. Future tool.