Skip to content

[CLI] Add semantic application-contract diffing with gowdk changes #688

Description

@cssbruno

[CLI] Add semantic application-contract diffing with gowdk changes

Priority

Medium-high — reviewability, safer upgrades, and deployment planning

Context

GOWDK already exposes rich structured information through routes, endpoints, manifests, compiler inspection, contracts, security audit output, OpenAPI/AsyncAPI, and generated build reports. Security auditing also has focused diff behavior.

What is missing is a single user-facing command that compares two validated application snapshots and explains the operational and compatibility impact of a change before deployment.

A textual source diff cannot reliably answer questions such as:

  • Was a public route removed or only moved between source files?
  • Did an endpoint change method, path, input contract, guard, CSRF, cache, or result policy?
  • Did a page move from static output to request-time rendering?
  • Did a target begin requiring a runtime environment variable?
  • Did an event stop invalidating a query?
  • Must split frontend and backend artifacts be deployed together?

Goal

Add gowdk changes, a semantic diff command that compares normalized validated application plans or versioned build metadata and classifies changes by compatibility, security, runtime, deployment, and informational impact.

Proposed CLI

# Compare the working tree with another Git revision.
gowdk changes --against main

gowdk changes --against HEAD~1 --target site

# Compare two committed build snapshots/reports.
gowdk changes \
  --from dist/previous/gowdk-build-report.json \
  --to dist/current/gowdk-build-report.json

# CI policy.
gowdk changes --against origin/main --fail-on breaking
gowdk changes --against origin/main --fail-on security,breaking

# Machine-readable output.
gowdk changes --against main --json

Git integration should remain an adapter around snapshot materialization. The semantic comparison engine should accept two already-normalized snapshots without requiring Git, making it reusable by tests, release tooling, and editors.

Change classifications

Use stable machine-readable categories and severities. A possible model:

Compatibility

  • breaking: an existing consumer/request/deployment can stop working;
  • potentially_breaking: impact depends on application/runtime behavior;
  • compatible: additive or behavior-preserving;
  • informational: metadata-only or non-contract change.

Domains

  • route;
  • endpoint;
  • page_runtime;
  • component_client;
  • asset;
  • security;
  • cache;
  • environment;
  • contract;
  • realtime;
  • deployment;
  • schema;
  • tooling.

Example human output:

BREAKING  route       Removed GET /customers/{id}
SECURITY  endpoint    POST /account/delete no longer has auth.required
RUNTIME   page        /dashboard changed from static SPA to SSR
CONFIG    environment SESSION_KEY became required at runtime
BREAKING  contract    UserDisabled no longer invalidates CurrentUser
COMPAT    endpoint    Added GET /health/details
INFO      asset       hero.css content hash changed

Every finding should include old/new source locations where available and stable identifiers suitable for editor navigation.

Minimum comparison surface

Routes and pages

  • route add/remove/change;
  • dynamic parameter name/type/rest changes;
  • localized route additions/removals;
  • static/SPA/SSR/hybrid lane changes;
  • guard/public-access changes;
  • route-local error page changes;
  • cache/revalidate changes;
  • page removal or ownership movement.

Endpoints

  • kind, method, path, symbol, package, and binding-status changes;
  • input field/type/required/validation changes;
  • route parameter and query contract changes;
  • result/status/content-type changes when represented;
  • guard, CSRF, rate-limit, body-limit, CORS, and error-policy changes;
  • fragment target/patch behavior changes;
  • missing-handler/stub policy changes.

Environment and runtime

  • required/optional environment variable additions/removals;
  • build-time versus runtime requirement changes;
  • generated runtime import/dependency changes;
  • server timeout/body/header policy changes that affect generated output;
  • lifecycle service additions/removals;
  • target role changes.

Contracts and realtime

  • command/query/event/job add/remove/rename;
  • web exposure and role changes;
  • input/output type changes;
  • event subscriber/owner changes;
  • invalidation edge changes;
  • realtime subscription and audience policy changes;
  • worker/cron target selection changes when supported.

Assets and client behavior

  • public logical asset URL removal/change;
  • generated client runtime capability changes;
  • component island/WASM ABI changes;
  • persisted store key/shape changes where represented;
  • page preload/prefetch behavior changes;
  • asset cache-policy changes.

Deployment

  • target add/remove/rename;
  • one-binary versus split/backend-only shape changes;
  • frontend/backend compatibility identity changes;
  • Docker/base/runtime-user changes;
  • generated recipe contract changes;
  • runtime feature introduced into a formerly static-only target.

Diff engine design

The engine should compare stable semantic keys rather than array positions or source-file order. It should consume the canonical application plan from #667/#668 and/or a versioned portable snapshot schema.

Suggested internal shape:

type Change struct {
    Code          string
    Severity      Severity
    Compatibility Compatibility
    Domain        Domain
    Subject       SubjectRef
    Before        any
    After         any
    Message       string
    OldLocation   *source.Location
    NewLocation   *source.Location
    Guidance      string
}

Change codes must be stable and documented so CI can waive or target specific rules without parsing messages.

Policy and CI

Support:

  • --fail-on by compatibility class/domain/severity;
  • --allow <change-code> or a reviewed policy file;
  • baseline/waiver expiry similar to audit policy where appropriate;
  • JSON output with a versioned schema;
  • deterministic ordering;
  • exit codes documented for no changes, allowed changes, policy failure, and invalid comparison input.

The default command should report changes without claiming every semantic change is a SemVer break. GOWDK remains 0.x, but users still need precise operational impact.

Snapshot acquisition

Support two sources:

  1. Source snapshots: compile the working tree and another revision into validated plans without publishing output.
  2. Artifact snapshots: compare versioned metadata embedded in prior/current build outputs.

For Git revisions, avoid mutating the user's checkout. Use a temporary worktree/archive or Git object reads, and run through the canonical workspace/compiler pipeline from #671.

External config/build execution for an untrusted revision must be explicit. A safe default may compare static/declarative metadata first and require a flag before executing revision-owned Go configuration or build functions.

Security considerations

  • Do not automatically execute arbitrary code from an untrusted comparison revision without explicit consent and clear output.
  • Redact secret-like config values.
  • Treat guard removal, public exposure, CSRF disablement, relaxed CORS, raw HTML exposure, and role weakening as security-domain changes.
  • Never infer backend resource authorization solely from declarative route metadata.

Editor integration

The JSON output should support a future VS Code view that groups changes and navigates to old/new declarations. Editor integration is not required for the first CLI slice, but source references and stable codes should be designed now.

Test plan

Golden and integration cases should cover:

  • route removal/addition/parameter changes;
  • endpoint method/path/input/result changes;
  • guard and CSRF weakening;
  • static-to-SSR transition;
  • cache and revalidation changes;
  • environment requirement changes;
  • command/query/event/invalidation changes;
  • asset logical URL removal;
  • split target mismatch/deployment-shape changes;
  • equivalent plans with reordered source discovery producing no changes;
  • source move with stable semantic identity;
  • JSON schema validation and deterministic ordering;
  • --fail-on exit behavior;
  • waiver/policy behavior if included;
  • comparison against a Git revision without modifying the checkout;
  • refusal or explicit consent for executable config in an untrusted revision.

Non-goals

  • Replacing git diff for source review.
  • Guaranteeing application-level database or business compatibility.
  • Inferring authorization correctness inside user-owned Go handlers.
  • Automatically generating migration code.
  • Treating all 0.x API changes as forbidden.

Acceptance criteria

  • gowdk changes compares two normalized application snapshots without relying on textual source order.
  • Human and versioned JSON output are supported.
  • Stable change codes, domains, and compatibility classifications are documented.
  • Routes, endpoints, render lanes, guards/security policy, environment requirements, contracts, assets, and deployment targets are included in the first supported matrix.
  • Findings include old/new source references where available.
  • Output ordering is deterministic.
  • CI can fail on selected classes through --fail-on.
  • Git revision comparison does not mutate the current checkout.
  • Executing code from a compared revision is explicit and safely described.
  • Equivalent plans produce no semantic findings despite source discovery or declaration reordering.
  • The command reuses the canonical compilation pipeline and versioned snapshot schemas.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions