Context
Today every plugin repo carries a duplicated `plugin.json.version` field that must be kept in sync with the git tag. The `sync-plugin-version.yml` workflow opens a PR after each tag to bump the field, but those PRs accumulate (13 stale in `workflow-plugin-digitalocean` alone before sweep 2026-05-23). The whole class of drift is preventable by not committing the version at all.
Proposed direction
Adopt an architecture where:
- Plugin binary version comes from build-time `-ldflags` at release time. The `version` field is removed from committed `plugin.json`. Plugin contract requires every plugin binary expose its version via a standard symbol (e.g. `pluginsdk.Version()` backed by an `-X` linker var).
- Registry-side validation rejects publish of any plugin whose version string does not match strict semver (`vN.N.N` or `vN.N.N-prerelease`). Branch-tagged or dirty builds (e.g. `v0.1.0-feat-foo.dirty`) are allowed locally and in test installs but rejected from public registry publish.
- wfctl grows a publish-gate validation (e.g. `wfctl plugin validate --for-publish`) that performs the same semver check before push to the registry. Local installs / test branches do not trigger the gate.
- All plugin repos audited to adopt the new approach: drop `plugin.json.version`, ensure goreleaser `-ldflags -X` is wired, ensure plugin binary surfaces version via the contract symbol.
- `sync-plugin-version.yml` workflow removed from every repo where it currently exists.
Affected surfaces
- workflow (this repo): wfctl validation + plugin contract symbol definition
- workflow-registry: publish-time semver gate
- workflow-plugin-{admin, agent, auth, authz, authz-ui, aws, azure, bento, ci-generator, cloud-ui, compute, cms, data-protection, digitalocean, edge-compute, edge-risk, gcp, github, payments, sandbox, security, supply-chain, tofu, waf, ...}: audit + drop committed version + verify ldflags wiring
- Any plugin repo running `sync-plugin-version.yml`: workflow removal
Why now
Surfaced 2026-05-23 by user when 13 stale sync-PRs piled up in workflow-plugin-digitalocean. Closing those was a sweep; this issue eliminates the root cause.
Acceptance criteria
Out of scope here
Refer to workflow-plugin-digitalocean#159 for unrelated true-blue/green deploy work.
Context
Today every plugin repo carries a duplicated `plugin.json.version` field that must be kept in sync with the git tag. The `sync-plugin-version.yml` workflow opens a PR after each tag to bump the field, but those PRs accumulate (13 stale in `workflow-plugin-digitalocean` alone before sweep 2026-05-23). The whole class of drift is preventable by not committing the version at all.
Proposed direction
Adopt an architecture where:
Affected surfaces
Why now
Surfaced 2026-05-23 by user when 13 stale sync-PRs piled up in workflow-plugin-digitalocean. Closing those was a sweep; this issue eliminates the root cause.
Acceptance criteria
Out of scope here
Refer to workflow-plugin-digitalocean#159 for unrelated true-blue/green deploy work.