diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a58aab..5c883fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ permissions: jobs: pr-title: + name: pr-title if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: @@ -26,6 +27,7 @@ jobs: PR_TITLE: ${{ github.event.pull_request.title }} run: make pr-title-check test: + name: test (${{ matrix.go-version }}) runs-on: ubuntu-latest env: GOTOOLCHAIN: local @@ -136,6 +138,7 @@ jobs: GOWORK: off run: go build ./... postgres-contract: + name: postgres-contract runs-on: ubuntu-latest env: API_TOOLKIT_TEST_POSTGRES: "1" @@ -164,6 +167,7 @@ jobs: - name: Real PostgreSQL harness run: make test-postgres redis-contract: + name: redis-contract runs-on: ubuntu-latest env: API_TOOLKIT_TEST_REDIS: "1" @@ -190,6 +194,7 @@ jobs: make test-redis make supported-adapter-check lint: + name: lint runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout v7.0.0 @@ -200,6 +205,7 @@ jobs: - name: Lint run: make lint governance: + name: governance runs-on: ubuntu-latest env: GOTOOLCHAIN: local @@ -229,6 +235,7 @@ jobs: API_BASE_REF: origin/${{ github.base_ref }} run: make contrib-api-drift-report api-check: + name: api-check (${{ matrix.go-version }}) runs-on: ubuntu-latest env: GOTOOLCHAIN: local @@ -274,6 +281,7 @@ jobs: UPGRADE_SMOKE_BASE_REF: v3.1.2 run: make upgrade-smoke-check fuzz: + name: fuzz runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout v7.0.0 @@ -300,6 +308,7 @@ jobs: if-no-files-found: warn retention-days: 7 mutation: + name: mutation runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout v7.0.0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 385d02f..26dd058 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,6 +17,7 @@ jobs: actions: read contents: read security-events: write + name: analyze runs-on: ubuntu-latest steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout v7.0.0 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 2262411..fb7f566 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -9,6 +9,7 @@ permissions: jobs: dependency-review: + name: dependency-review runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 271c977..9e105be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -68,6 +68,7 @@ jobs: attestations: write contents: write id-token: write + name: release-preflight needs: [toolchain-compatibility, redis-contract] env: TOOLCHAIN_MATRIX_RESULT: passed diff --git a/Makefile b/Makefile index 7d9a1d1..374e5c1 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ export endif GITHUB_AUTH_TOKEN ?= $(GITHUB_TOKEN) # GitHub PAT. -.PHONY: help tools api-check release-api-check api-check-contract api-inventory api-inventory-check api-additions-check api-additions-check-contract docs-site docs-site-check dead-code-todo-check dead-code-todo-contract contrib-api-drift-report contrib-release-notes-check dependency-report dependency-boundary-check full-profile-scaffold-check generated-integration-check generated-integration-check-minio generated-integration-contract generated-soak-check generated-soak-contract generated-failure-check generated-failure-contract generated-upgrade-compat-check generated-upgrade-compat-contract upgrade-smoke-check upgrade-smoke-contract reference-service-check reference-service-coverage reference-service-load reference-service-load-contract reference-service-evidence reference-service-evidence-contract test-postgres test-redis supported-adapter-check v3-readiness-check contrib-review-contract actions-audit actions-audit-contract sbom-license-report-contract release-artifact-verify-contract release-evidence-parser-contract release-tag-consistency-check release-tag-consistency-contract release-quality-baseline-contract version-consistency-check version-consistency-contract pr-title-check pr-title-check-contract docs-check fmt lint vuln gosec tidy test example-compile-check coverage coverage-check coverage-trend-record coverage-trend-check benchmark-baseline-check fast-check test-race timeout-determinism-check fuzz fuzz-contract mutation-smoke benchmark-smoke clean finalize audit-check reviewer-gate release-check release-evidence release-review-summary release-artifact-verify release-artifact-verify-fixture ci-build-smoke codeql-local .codeql-local-build scorecard-local sbom-local github-governance-check +.PHONY: help tools api-check release-api-check api-check-contract api-inventory api-inventory-check api-additions-check api-additions-check-contract docs-site docs-site-check dead-code-todo-check dead-code-todo-contract contrib-api-drift-report contrib-release-notes-check dependency-report dependency-boundary-check full-profile-scaffold-check generated-integration-check generated-integration-check-minio generated-integration-contract generated-soak-check generated-soak-contract generated-failure-check generated-failure-contract generated-upgrade-compat-check generated-upgrade-compat-contract upgrade-smoke-check upgrade-smoke-contract reference-service-check reference-service-coverage reference-service-load reference-service-load-contract reference-service-evidence reference-service-evidence-contract test-postgres test-redis supported-adapter-check v3-readiness-check contrib-review-contract actions-audit actions-audit-contract sbom-license-report-contract release-artifact-verify-contract release-evidence-parser-contract release-tag-consistency-check release-tag-consistency-contract release-quality-baseline-contract version-consistency-check version-consistency-contract pr-title-check pr-title-check-contract required-checks-verify required-checks-verify-contract docs-check fmt lint vuln gosec tidy test example-compile-check coverage coverage-check coverage-trend-record coverage-trend-check benchmark-baseline-check fast-check test-race timeout-determinism-check fuzz fuzz-contract mutation-smoke mutation-check benchmark-smoke clean finalize audit-check reviewer-gate release-check release-evidence release-review-summary release-artifact-verify release-artifact-verify-fixture ci-build-smoke codeql-local .codeql-local-build scorecard-local sbom-local github-governance-check help: ## Show help @awk 'BEGIN {FS=":.*## "}; \ @@ -177,6 +177,12 @@ supported-adapter-check: ## Verify supported PostgreSQL and Redis real-service e github-governance-check: ## Optional authenticated GitHub branch/tag protection verification @scripts/github_governance_check.sh +required-checks-verify: ## Verify the required-check manifest against stable workflow job identities + @scripts/required_checks_verify.sh + +required-checks-verify-contract: ## Exercise required-check manifest and branch-protection failure modes + @bash scripts/required_checks_verify_contract_test.sh + v3-readiness-check: ## Run compatibility-sensitive v3 readiness guardrails @$(GO) test ./docscheck -count=1 -run 'TestCompatibilitySensitivePortsManifestIsCurrent|TestContribPackageClassificationAndCompatibilityPolicy|TestCompatibilityShimLifecycleRoadmap|TestIdempotencyCompatibilityMetricDocsStayBounded|TestResponseWriterInventoryMatchesCurrentImports|TestPublicExamplesDoNotTeachLegacyCompatibilitySurfaces|TestV3RemovalMatrixHasExecutableEvidence|TestV3DebtChecklistRowsStayExecutable|TestCompatibilityRoadmapCoversDocumentedSensitiveSurfaces|TestCompatibilitySensitivePortsGovernanceDocs|TestCompatibilitySensitivePackageDocsPointToReplacements|TestExamplesAndGuidesPreferCompatibilityReplacements|TestReleaseNotesIncludeStableSurfaceChecklist|TestDeprecatedBillingPortsPointToCompatPackage|TestDeprecatedBillingPortsStayInCompatibilitySource|TestDatabaseStatsStayInCompatibilityOrAdapterSource|TestAdapterLegacyRecoveryTelemetryRedactsKeysByDefault|TestIdempotencyCaptureDoesNotUseLegacyResponseWriter' @@ -194,6 +200,8 @@ sbom-license-report-contract: ## Run SPDX dependency license report contract tes docs-check: ## Run documentation contract checks @$(GO) test ./docscheck -count=1 + @$(MAKE) required-checks-verify + @$(MAKE) required-checks-verify-contract @$(MAKE) version-consistency-check @$(MAKE) version-consistency-contract @$(MAKE) coverage-trend-check @@ -363,6 +371,7 @@ release-check: ## Run release readiness checks; requires explicit API_BASE_REF $(MAKE) vuln $(MAKE) gosec $(MAKE) ci-build-smoke + $(MAKE) required-checks-verify $(MAKE) release-api-check $(MAKE) contrib-api-drift-report $(MAKE) contrib-release-notes-check @@ -376,6 +385,7 @@ release-check: ## Run release readiness checks; requires explicit API_BASE_REF $(MAKE) test $(MAKE) test-race $(MAKE) fuzz + $(MAKE) mutation-check $(MAKE) clean release-evidence: ## Run release readiness and write release-check-summary.json diff --git a/docs/README.md b/docs/README.md index ec15193..9a70afd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -203,6 +203,7 @@ identifies the installed generator and contract tool. | [Reproducible build status](reproducible-builds.md) | Release consumers and maintainers | Distinguish unsupported binary reproducibility from the checksums, signatures, and provenance verified for release assets. | | [Release review checklist](release-review.md) | Release reviewers | Short path through summary fields, manifests, dirty-tree decisions, artifacts, and release notes. | | [Governance](governance.md) | Maintainers | Branch protection, CODEOWNERS, tag protection, required checks, and release approval expectations. | +| `docs/required-checks.json` | Maintainers and automation | Canonical check names, workflow/job identities, GitHub App bindings, owners, and PR/release classifications for protected quality gates. | | [Changelog](../CHANGELOG.md) | Release consumers | Concise user-facing history for published releases. | | [Release notes](release-notes.md) | Release consumers and maintainers | Dated behavior changes, upgrade notes, and package-tied contrib drift acknowledgements. | | [Release manifests](release-manifests.md) | Release reviewers and maintainers | Human guide for package classification, contrib drift, contrib dispositions, and vulnerability dispositions. | diff --git a/docs/governance.md b/docs/governance.md index 3e5b82e..0a8d814 100644 --- a/docs/governance.md +++ b/docs/governance.md @@ -19,24 +19,26 @@ and `docs/stable-core.md`. eligible maintainer is added. - Require the CodeQL `code_scanning` ruleset on `master` with Errors and Warnings plus High-or-higher security alerts blocking merges. -- Require the CI jobs that apply to the change: - - `ci / test`, including `make coverage-check`, `make test-race`, and - `make vuln`. - - `ci / lint`, including `make lint`. - - `ci / governance`, including `make docs-check`, - `make v3-readiness-check`, and pull-request contrib drift/release-note - checks. - - `ci / api-check`, including `make release-api-check` against the pull - request base or push predecessor. - - `ci / fuzz`, including `make fuzz` and a failure-only upload of minimized - synthetic fuzz corpus files. - - `ci / mutation`, including `make mutation-check` with its documented - assertion-based kill-rate threshold. - - `dependency-review / dependency-review`, which fails pull requests that - introduce high or critical vulnerable dependencies or dependencies outside - the configured license policy. - - `codeql` and `scorecard` workflow results when those workflows are enabled - for the repository. +- Require every pull-request identity in `docs/required-checks.json`, with the + exact check name and GitHub App binding recorded there. The manifest groups + the stable gates as follows: + - `test (1.25.x)` and `test (1.26.x)` cover unit tests, + `make coverage-check`, `make test-race`, `make vuln`, builds, examples, and + dependency-footprint evidence. + - The four `platform-core (...)` identities cover Linux amd64, native Linux + arm64, macOS arm64, and Windows amd64 portability. + - `lint`, `governance`, both `api-check (...)` identities, `fuzz`, and + `mutation` run `make lint`, `make docs-check`, `make v3-readiness-check`, + `make release-api-check`, `make fuzz`, and `make mutation-check` across + static quality, documentation and dependency boundaries, API compatibility, + malformed-input smoke, and assertion-sensitive testing. + - `postgres-contract` and `redis-contract` cover supported real-service + integration contracts. + - `analyze`, `CodeQL`, and `dependency-review` cover workflow analysis, + code-scanning publication, and dependency policy. `dependency-review` + rejects high or critical vulnerable dependencies and dependencies outside + the configured license policy. `pr-title` enforces the one-ticket + Conventional Commit identity at review time. - Enable GitHub Secret Scanning and push protection for supported secret patterns. Treat them as required merge-prevention controls, not as a replacement for review or safe configuration design. @@ -58,13 +60,22 @@ state. Maintainers should verify them with the GitHub UI or `make github-governance-check` before publication review, and attach the output when repository settings are accessible. +`make required-checks-verify` validates the manifest schema, canonical workflow +paths, explicit workflow job names, owners, release classification, and unique +check identities. It runs through `docs-check` and `release-check`; changing a +required job ID or displayed job name therefore requires a matching manifest +change. Release evidence records the verifier and required mutation gate as +ordinary release-check results. + Maintainers can run the optional authenticated verifier with `make github-governance-check`. The command uses `gh api` when available to -check branch protection, required status checks, the sole-maintainer PR and -no-bypass rulesets, CodeQL merge protection, force-push/deletion protection, -and tag rulesets for both `refs/tags/v*` and `refs/tags/contrib/v*`. It skips -cleanly when `gh` is not installed or authenticated, and it is not part of `finalize` -or required PR CI. +compare the manifest with the exact strict, app-bound branch-protection set and +to check the sole-maintainer PR and no-bypass rulesets, CodeQL merge protection, +force-push/deletion protection, and tag rulesets for both `refs/tags/v*` and +`refs/tags/contrib/v*`. It skips cleanly only when `gh` is absent or +unauthenticated; an authenticated API failure, malformed response, missing +check, stale check, or wrong App binding fails closed. The authenticated command +is not part of `finalize` or required PR CI. ## PR Review Discipline diff --git a/docs/release-notes.md b/docs/release-notes.md index e8a8ff5..c8949c7 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -81,6 +81,17 @@ source of truth is `docs/release-runbook.md`. policy does not claim macOS amd64 or Windows arm64 without matching required workflow evidence. +### Stable required quality-gate identities + +- `docs/required-checks.json` now records every protected pull-request check, + its GitHub App binding, workflow/job identity, owner, and PR/release role. +- Workflow jobs have explicit displayed names, and local documentation plus + release gates fail when a job identity drifts from the manifest. +- The authenticated governance audit compares branch protection with the exact + manifest set and fails on missing, stale, unbound, or wrong-App checks. +- Release evidence now records required-check manifest verification and the + blocking mutation gate as named results. + ### Real Redis contract foundation - `make test-redis` now provides an isolated Redis 7 harness and real-service diff --git a/docs/release-runbook.md b/docs/release-runbook.md index 9cbd286..4a2a1cf 100644 --- a/docs/release-runbook.md +++ b/docs/release-runbook.md @@ -134,7 +134,8 @@ after the final stable `vX.Y.0` release is published. | `GOTOOLCHAIN=local make reference-service-coverage` | Optional checked-in reference service coverage diagnostic. | Writes `.ci-result/coverage/reference-service.func` and `.ci-result/coverage/reference-service-summary.md` without folding generated app code into root/contrib aggregate coverage thresholds. Not part of `finalize`. | | `GOTOOLCHAIN=local make reference-service-load` | Optional checked-in reference service load-smoke baseline. | Runs the reference-service router in-process, writes `.ci-result/reference-service-load/status`, `summary.json`, `summary.md`, and `load-smoke.log`, and records latency, throughput, memory, allocations, and expected missing-API-key failure behavior. Not part of `finalize`. | | `GOTOOLCHAIN=local make reference-service-evidence` | Optional recorded reference service evidence. | Runs `reference-service-check`, writes `.ci-result/reference-service/status`, `.ci-result/reference-service/summary.json`, and logs. Set `REFERENCE_SERVICE_DOCKER=1` to also run the service-owned Docker `integration-check`; set `REFERENCE_SERVICE_MINIO=1` only when object-storage integration evidence is in scope. Not part of `finalize`. | -| `make github-governance-check` | Optional authenticated GitHub repository settings verification. | Uses `gh api` to verify branch protection, required checks, the sole-maintainer PR/no-bypass rulesets, CodeQL merge protection, force-push/deletion protection, and root `v*` plus contrib `contrib/v*` tag rulesets when `gh` is installed and authenticated; skips cleanly otherwise. | +| `make required-checks-verify` | Local required-check identity contract. | Validates `docs/required-checks.json` against explicit workflow job IDs and names. It is part of `docs-check` and `release-check`, so release evidence records its result. | +| `make github-governance-check` | Optional authenticated GitHub repository settings verification. | Uses `gh api` to compare the manifest with the exact strict, app-bound branch-protection set and verify the sole-maintainer PR/no-bypass rulesets, CodeQL merge protection, force-push/deletion protection, and root `v*` plus contrib `contrib/v*` tag rulesets. It skips when `gh` is absent or unauthenticated and fails closed after authentication. | | `RELEASE_TAG=vX.Y.Z GOTOOLCHAIN=local make release-tag-consistency-check` | Paired root/contrib release identity gate. | Fails if matching root/contrib tags, branch ancestry, module-major paths, changelog, release notes, support policy, or the release-workflow baseline are incoherent. | | `RELEASE_TAG=vX.Y.Z API_BASE_REF=v4.0.1 GOTOOLCHAIN=local make release-evidence` | Clean-tree tag-binding preflight. | Requires the supported tag to point at `HEAD` and records tag/commit/tree/default-branch/module identity in `release-check-summary.json` schema v2, plus checks and retained logs. Local evidence is useful preflight only; the tag-driven GitHub workflow is the trusted publication producer. | | `ALLOW_DIRTY_RELEASE_EVIDENCE=1 API_BASE_REF=v4.0.1 GOTOOLCHAIN=local make release-evidence` | Local dirty-tree audit evidence. | Writes the same evidence files but records `publication_eligible=false` and `provenance_policy.mode=local_audit`; not acceptable before publishing. | @@ -242,6 +243,9 @@ Local release evidence is the developer/auditor tier. It contains: - `release-check-summary.json` schema v2. - One check record per `make release-check` subtarget. +- Required-check manifest verification and the blocking mutation result are + retained as named check records, so release reviewers can see whether stable + workflow identities and the assertion-sensitive gate passed. - Command lines, exit codes, durations, log availability, log paths, tool versions, commit, branch or detached state, dirty flag, staged/unstaged/ untracked/deleted counts, and `API_BASE_REF`. diff --git a/docs/required-checks.json b/docs/required-checks.json new file mode 100644 index 0000000..7daeb8a --- /dev/null +++ b/docs/required-checks.json @@ -0,0 +1,192 @@ +[ + { + "check_name": "pr-title", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "pr-title", + "job_name": "pr-title", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": false, + "owner": "maintainers" + }, + { + "check_name": "test (1.25.x)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "test", + "job_name": "test (${{ matrix.go-version }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "test-engineering" + }, + { + "check_name": "test (1.26.x)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "test", + "job_name": "test (${{ matrix.go-version }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "test-engineering" + }, + { + "check_name": "platform-core (linux-amd64)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "platform-core", + "job_name": "platform-core (${{ matrix.platform }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "build-engineering" + }, + { + "check_name": "platform-core (linux-arm64)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "platform-core", + "job_name": "platform-core (${{ matrix.platform }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "build-engineering" + }, + { + "check_name": "platform-core (macos-arm64)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "platform-core", + "job_name": "platform-core (${{ matrix.platform }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "build-engineering" + }, + { + "check_name": "platform-core (windows-amd64)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "platform-core", + "job_name": "platform-core (${{ matrix.platform }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "build-engineering" + }, + { + "check_name": "postgres-contract", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "postgres-contract", + "job_name": "postgres-contract", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": false, + "owner": "integration-test-team" + }, + { + "check_name": "redis-contract", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "redis-contract", + "job_name": "redis-contract", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "integration-test-team" + }, + { + "check_name": "lint", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "lint", + "job_name": "lint", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "build-engineering" + }, + { + "check_name": "governance", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "governance", + "job_name": "governance", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "maintainers" + }, + { + "check_name": "api-check (1.25.x)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "api-check", + "job_name": "api-check (${{ matrix.go-version }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "api-review" + }, + { + "check_name": "api-check (1.26.x)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "api-check", + "job_name": "api-check (${{ matrix.go-version }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "api-review" + }, + { + "check_name": "fuzz", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "fuzz", + "job_name": "fuzz", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "test-engineering" + }, + { + "check_name": "mutation", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "mutation", + "job_name": "mutation", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "test-engineering" + }, + { + "check_name": "analyze", + "workflow_file": ".github/workflows/codeql.yml", + "job_id": "analyze", + "job_name": "analyze", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": false, + "owner": "security" + }, + { + "check_name": "CodeQL", + "workflow_file": ".github/workflows/codeql.yml", + "job_id": "analyze", + "job_name": "analyze", + "app_id": 57789, + "required_for_pr": true, + "required_for_release": false, + "owner": "security" + }, + { + "check_name": "dependency-review", + "workflow_file": ".github/workflows/dependency-review.yml", + "job_id": "dependency-review", + "job_name": "dependency-review", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": false, + "owner": "security" + }, + { + "check_name": "release-preflight", + "workflow_file": ".github/workflows/release.yml", + "job_id": "release-preflight", + "job_name": "release-preflight", + "app_id": 15368, + "required_for_pr": false, + "required_for_release": true, + "owner": "release-engineering" + } +] diff --git a/docs/site/search-index.json b/docs/site/search-index.json index 25cb90b..8426471 100644 --- a/docs/site/search-index.json +++ b/docs/site/search-index.json @@ -321,7 +321,7 @@ "title": "Release Notes", "category": "migration", "url": "https://github.com/aatuh/api-toolkit/blob/master/docs/release-notes.md", - "text": "docs/release-notes.md Release Notes Audience: release consumers and maintainers who need dated behavior changes upgrade notes and package-tied compatibility acknowledgements. Current release guidance Need Current guidance Exact release commands and Release Notes Audience: release consumers and maintainers who need dated behavior changes upgrade notes and package-tied compatibility acknowledgements. Current release guidance Need Current guidance Exact release commands and supported `API_BASE_REF` Use `docs/release-runbook.md` do not maintain a second baseline table here. Concise user-facing summary by published version Use `CHANGELOG.md` update it with every release tag. User-visible behavior migration notes and compatibility acknowledgements Add dated entries in this file. Keep historical entries historical unless later guidance would otherwise mislead readers. Stable surface changes Update `VERSIONING.md` package docs compatibility docs release notes and docscheck coverage together. Supported-adapter or selected contrib drift Run the contrib drift and release-note review gates with the release baseline from the runbook. Root/contrib release identity Create matching root and `contrib/` tags at one commit then run `make release-tag-consistency-check` before release evidence. Generated service upgrade compatibility `make generated-upgrade-compat-check` defaults to `v3.0.0 v3.1.2` the script `docs/reference-service.md` and `docs/release-runbook.md` are the checked sources. Release Note Categories Every dated release entry should use one or more of these categories when the change is present: Category Use when the release includes Breaking Source-incompatible API module config generated-file or runtime contract changes. Behavior User-visible runtime behavior response shape validation persistence or default changes. Security Security fixes hardening bypass removal vulnerability disposition or sensitive default changes. Docs Documentation-only changes that affect adoption upgrade release or operations guidance. Dependencies Dependency upgrades removals replacements vulnerability-driven changes or imported-only risk dispositions. Generated scaffold Generator CLI behavior templates scaffold runtime assets generated Makefile targets or reference-service compatibility. Migration Upgrade steps compatibility notes deprecations replacement paths or required operator action. Release checklist For stable surface changes deprecations or compatibility-sensitive updates keep this file focused on user-visible behavior and upgrade notes. The command source of truth is `docs/release-runbook.md`. - Choose one or more release note categories from the taxonomy above before adding the dated entry do not bury breaking behavior security dependency generated scaffold or migration impact under generic prose. - Update `VERSIONING.md` public docs and package docs that describe the affected stability contract. - Update `scripts/apicheck.sh` and docscheck coverage when the stable package list or compatibility-sensitive manifest changes. - Update `docs/ports-surface.md` `docs/v3-compatibility-roadmap.md` release notes and upgrade notes when compatibility-sensitive ports or legacy stable surfaces change. - Add release notes and upgrade notes that describe user-visible behavior migration paths and compatibility impact. - Run release evidence through the runbook path `docs/release-runbook.md` owns the current supported `API_BASE_REF` baseline and exact commands while `make finalize` and `make audit-check` are local/reviewer gates. - Run `make contrib-api-drift-report` with the same release baseline when selected contrib adapters or integrations change exported APIs selected packages come from `docs/contrib-api-drift-packages.txt` supported-adapter incompatible drift is gate-enforced and this does not make contrib stable. - Run `make contrib-release-notes-check` with the same release baseline when supported contrib adapter integration middleware bootstrap telemetry production generator CLI behavior files or runtime assets change. - Supported-adapter contrib packages remain outside the stable core API promise but incompatible public API drift in that tier must be treated as gate-enforced and resolved with compatibility reclassification or a major-release policy decision. - If there is incompatible report-only contrib drift add an explicit release note or upgrade note acknowledgement tied to the affected package. This does not make contrib stable. - Update `docs/vulnerability-dispositions.tsv` when imported-only vulnerability IDs change expire or receive upgraded dependencies. - Update `docs/contrib-api-drift-dispositions.tsv` when current contrib drift packages or incompatible drift status changes. - Use clean publication evidence with the explicit baseline command from `docs/release-runbook.md` reserve `ALLOW_DIRTY_RELEASE_EVIDENCE 1` for local dirty-tree audit evidence that is not acceptable before publishing. First v3 major-release evidence may use `API_BASE_REF v2.1.0` only as documented v2-to-v3 transition evidence. - Use `docs/release-manifests.md` when interpreting `docs/package-classification.tsv` `docs/contrib-api-drift-dispositions.tsv` and `docs/vulnerability-dispositions.tsv`. 2026-08-22 Cross-platform core verification - Root-module verification builds tests examples and a generated `saas-api` service build now gate Linux amd64 Linux arm64 macOS arm64 and Windows amd64 pull requests on fixed GitHub-hosted runner labels. - Repository-owned text is normalized to LF on every checkout and generated service dependencies are resolved before the isolated build gate runs. - The generator now validates canonical slash-form manifest paths before converting them to host separators allowing nested templates on Windows without weakening rooted traversal protection. - Full contrib and race verification remain Linux amd64 gates. The support policy does not claim macOS amd64 or Windows arm64 without matching required workflow evidence. Real Redis contract foundation - `make test-redis` now provides an isolated Redis 7 harness and real-service contracts for supported cache idempotency and rate-limit adapters plus the generated reference-service Redis paths. It covers TTL empty and oversized values atomic concurrency Lua release/token handling malformed state isolation cancellation dependency failure connection interruption and reconnect behavior. - The harness requires explicit test-only opt-in accepts only credential-free local/service endpoints on database 15 cleans only its random key prefix and sanitizes connection failures. CI and release tags run the same `redis-contract` miniredis remains fast unit evidence not equivalent release evidence. Real PostgreSQL contract foundation - `make test-postgres` now provides an isolated PostgreSQL 18 harness for contrib integration tests. It uses an explicit test-only loopback or CI service-container DSN creates a database and schema per test supports rollback migration cancellation and connection-loss checks and never reads application `DATABASE_URL` configuration. - The harness now directly validates supported PostgreSQL adapters migrations scheduler storage and generated reference-service persistence paths on every pull request `make supported-adapter-check` is the explicit verification alias. Internal response-writing behavior - Root-module internals now use checked response writers. Terminal paths stop after a failed write existing application-facing void writer APIs remain compatibility wrappers. Contrib and generated scaffolds will adopt these APIs with the next paired verified v4 root release so standalone builds retain a published dependency. Security and generated scaffold - `github.com/aatuh/api-toolkit/v4/binding.PublicError` and `binding.PublicError.PublicMessage` permit an application to opt a validation detail into a client response. Other validation errors now use the generic `validation failed` detail. - `github.com/aatuh/api-toolkit/v4/fielderrors.FieldError.Public` must be set for a field message to be eligible for client disclosure. - `github.com/aatuh/api-toolkit/v4/fielderrors.FieldErrors.AllPublic` requires every field message to be explicitly classified before a Provider s fields are added to a validation response. - Generated `saas-api` services log only a validation error s type at the default application logger they never log the raw rejected error string. Request binding behavior and future v5 migration - `github.com/aatuh/api-toolkit/v4/binding.RequiredMode` `binding.RequiredModeNonZero` and `binding.RequiredModePresent` let a handler choose non-zero or source-presence validation for `required: true ` fields. - `binding.JSONConfig.RequiredMode` `binding.QueryConfig.RequiredMode` and `binding.PathConfig.RequiredMode` preserve v4-compatible defaults unless a caller explicitly selects presence validation. `binding.PathConfig.HasParam` lets a router distinguish an absent path parameter from a present empty one. - A v5 major release is planned to make presence-aware validation the default. Applications that require a non-zero or non-null value should state that semantic rule separately before migrating. Health manager construction and v5 migration - `github.com/aatuh/api-toolkit/v4/endpoints/health.DefaultConfig` `health.Config.Clock` and `health.Config.Validate` provide an explicit testable startup-time configuration baseline for health managers. - `health.NewManager` returns a concrete manager and fails invalid timeout cache and probe configuration. `health.Manager.RegisterCheckerChecked` rejects nil empty-name and duplicate checkers instead of replacing a configured probe silently. - `health.NewManagerWithConfig` and `health.NewWithConfig` remain v4 compatibility wrappers. Migrate startup wiring to `NewManager` and checked registration before v5 removes the inconsistent unchecked constructors. Rate-limit decisions and bounded cleanup - `github.com/aatuh/api-toolkit/v4/middleware/ratelimit.DecisionLimiter` and `ratelimit.DecisionLimiter.Allow` let a shared rate-limit adapter return a complete `ratelimit.Decision` including `ratelimit.Decision.Limit` `ratelimit.Decision.Remaining` and `ratelimit.Decision.Reset` for standard response headers on both allowed and denied requests. - `ratelimit.Options.DecisionLimiter` cannot be combined with the existing `ratelimit.Limiter` the latter remains a v4-compatible adapter for allow/deny and retry-after decisions. - In-memory state expiry now uses a bounded expiry heap and removes at most 64 expired buckets per request. It starts no background goroutine. Blank key results share an anonymous bucket rather than bypassing rate limiting dangerous skip headers remain opt-in and restricted to trusted proxies. Timeout routing and hard-response limits - `github.com/aatuh/api-toolkit/v4/middleware/timeout.RouteCapabilities` `timeout.RouteCapabilities.Streaming` `timeout.RouteCapabilities.ServerSentEvents` `timeout.RouteCapabilities.WebSocketUpgrade` `timeout.RouteCapabilities.LargeDownload` `timeout.RouteCapabilities.Flusher` `timeout.RouteCapabilities.Hijacker` `timeout.RouteCapabilities.Pusher` and `timeout.RouteCapabilities.ReaderFrom` declare response behavior that hard-timeout buffering cannot preserve. - `timeout.RouteCapabilities.ValidateHardTimeout` and `timeout.HardTimeout.WrapRoute` reject unsafe route declarations before a hard timeout is applied. Generated bootstrap profiles and examples use cooperative `NewPropagator` middleware globally finite JSON routes opt in to hard response timeouts explicitly. - `timeout.HardTimeout.Middleware` and `securityprofile.WithHardTimeout` are deprecated v4 compatibility paths. `timeout.HardTimeoutEventHooks.OnHandlerContinuesAfterTimeout` provides a bounded low-level signal when a timeout response wins while the handler continues to run. 2026-08-15 HTTP response writer behavior - `github.com/aatuh/api-toolkit/v4/httpx` adds `httpx.WriteJSONChecked` and `httpx.WriteProblemChecked`. Their typed errors are `httpx.ResponseWriteError` `httpx.ResponseWriteError.Err` `httpx.ResponseWriteError.Error` `httpx.ResponseWriteError.Stage` `httpx.ResponseWriteError.Unwrap` `httpx.ResponseWriteStage` `httpx.ResponseWriteStageEncode` `httpx.ResponseWriteStageHeader` and `httpx.ResponseWriteStageBody`. Existing `httpx.WriteJSON` and `httpx.WriteProblem` remain compatibility wrappers callers that need write failures should use the checked APIs. Release integrity and migration - The v4 release-identity review verifies root `v4.0.1` as the sole root-module baseline. Use `API_BASE_REF v4.0.1` for v4 root release checks. - `v4.0.0` `contrib/v4.0.0` and `contrib/v4.0.1` are withdrawn. Contrib consumers must wait for a new paired repair release do not substitute the root tag for the withdrawn contrib module. Security and migration - `contrib/adapters/chi.Middleware.RealIP` now ignores untrusted forwarding headers and leaves `http.Request.RemoteAddr` intact. This removes the spoofable `middleware.RealIP` behavior identified by the updated chi dependency. - Reverse-proxy deployments must obtain the resolved client address through `middleware.GetClientIP r.Context ` and apply `chi.ClientIPFromXFF trustedCIDRs... `. The helper trusts only the configured proxy CIDRs and never mutates `RemoteAddr`. 2026-07-11 V4 migration release - Published the v4 root and contrib module paths with the mechanical import replacements documented in [migration/v4.md] migration/v4.md . - Reduced root `ports` to generic logger clock and identifier contracts endpoint middleware authorization HTTP and platform contracts now have package-local or contrib-owned v4 destinations. - Moved JWT/JWK middleware shared auth internals OAuth2 helpers and auth test support into contrib. Root v4 has no direct JWT/JWK requirements issuer audience algorithm JWKS and trusted-proxy bypass validation behavior is unchanged. - Added workspace root/contrib module generated-scaffold reference-service root-port ledger API transition dependency coverage race fuzz lint vulnerability and `gosec` release evidence. Migration - Added package-local endpoint aliases for `health.Checker` `health.ManagerContract` `health.DetailedManager` `health.CachedManager` `health.RouteRegistrar` `docs.Provider` `docs.ManagerContract` `docs.HTMLModeProvider` and `docs.RouteRegistrar`. They preserve exact v3 source compatibility with their root `ports` counterparts while giving new health and documentation integrations a consuming-package import path. - Added package-local idempotency store aliases: `idempotency.Store` `idempotency.ReservationReleaser` and `idempotency.ReleasableStore`. New integrations can adopt them after updating to a root version that contains these aliases they retain exact v3 source compatibility with the root contracts. - Added package-local authorization aliases: `authorization.Authorizer` `authorization.AuthorizerFunc` `authorization.PolicyEngine` `authorization.PolicyRequest` and `authorization.PolicyDecision`. They do not change default-deny owner tenant or policy-engine behavior and remain source-compatible with the v3 root contracts. - Deprecated the broad root `ports` contracts that now have package-local aliases: rate limiting idempotency stores authorization and policy health endpoint interfaces and docs endpoint interfaces. They remain available throughout v3 `docs/deprecations.md` records each replacement and the v4 removal horizon. - Published an accountable v4 scope ledger in `docs/v4-plan.md`. Each keep narrow split and removal decision now names an owner replacement direction and migration evidence required before a v4 API change. - Assessed provider extension-module candidates using ownership dependency contract realism and drift evidence. No family is approved for extraction without independent adoption or family-specific release-cadence evidence. - Clarified that CLI and scaffold behavior releases through contrib tooling ownership and release-note review never through the root stable API promise. - Published an AST-verified root-port migration ledger with all current exports consumers implementation evidence deprecation state and v4 dispositions. v3 cleanup branch Security and dependencies - Updated contrib `github.com/jackc/pgx/v5` from `v5.9.0` to `v5.9.2` and `github.com/yuin/goldmark` from `v1.7.16` to `v1.7.17` to remove the called `govulncheck` findings `GO-2026-5004` and `GO-2026-5320`. The update does not change api-toolkit s public API `adapters/pgxpool` remains a supported contrib adapter and `email/markdown` remains experimental. Breaking cleanup - The module paths are now `github.com/aatuh/api-toolkit/v4` and `github.com/aatuh/api-toolkit/contrib/v4`. - Provider-shaped billing exports were removed from root `ports` use `github.com/aatuh/api-toolkit/v4/compat/billing` for the hosted-checkout compatibility model or define app-owned billing ports. - `ports.DatabasePool.Stat` `ports.DatabaseStats` `ports.SnapshotDatabaseStats` and the public `response_writer` package were removed. Use `ports.DatabasePoolSnapshotProvider` `ports.SnapshotDatabasePoolStats` adapter `StatSnapshot ` methods and `httpx`. - Idempotency middleware now requires token-aware release through `ports.IdempotencyReservationReleaser`. - `authz.NewRequireRoleMiddleware` now validates at construction time and returns ` RequireRoleMiddleware error `. - List endpoint helpers keep the checked parser APIs: `ParseListQueryChecked` `DefaultFilterParserChecked` and `DefaultSortParserChecked`. 2026-06-07 Migration - Added `middleware/ratelimit.Limiter` as a package-local v3 migration shim over `ports.RateLimiter`. Existing `ports.RateLimiter` users remain source-compatible while new rate-limit adapters can move imports toward the consuming middleware package before v4 shrinks broad root ports. - Updated `docs/deprecations.md` so the active register covers the existing source-deprecated `middleware/timeout.New` and `middleware/trace.Use` shims with replacements removal horizon snippets and release-note pointers. 2026-06-06 Test evidence and compatibility - Added experimental `github.com/aatuh/api-toolkit/v4/compatkit` downstream compatibility test support. Services can run readiness version Problem Details OpenAPI compatibility and custom HTTP checks against an in-process handler or explicit base URL without promoting the package to the stable API surface. 2026-05-21 Release baseline maintenance - Published `v3.1.2` from the current `master` release tag evidence and advanced the v3 patch/minor release baseline examples to `v3.1.2`. - Added the paired `contrib/v3.1.2` module tag because the contrib module changed in the release. - `make generated-upgrade-compat-check` now defaults to the published baseline matrix `v3.0.0 v3.1.2` `GENERATOR_REF` remains as the single-ref compatibility alias. 2026-05-20 Test evidence and coverage reporting - Added focused behavior tests for `endpoints/docs` `httpx/identity` `httpx/recover` `middleware/json` `middleware/maxbody` `middleware/querylimits` and `securityprofile` then added package-specific coverage floors for those stable HTTP/security surfaces. - Added direct response-recorder behavior tests for `contrib/middleware/metrics` `contrib/middleware/oteltrace` and `contrib/middleware/requestlog` including informational statuses committed-state behavior optional response-writer interface forwarding and unsupported interface fallbacks. Coverage floors now protect those observability middleware packages. - Replaced direct sleep-based assertions in timeout security-profile outbound HTTP retry and transaction cleanup tests with context deadlines or channel synchronization so the same behavior is checked with less timing risk. - Hardened the hard-timeout capture path so handler writes are rejected as soon as the request deadline channel is closed then added `make timeout-determinism-check` for repeated normal and race evidence around late-write rejection. - Added `docs/supported-adapter-test-realism.tsv` and docscheck coverage so every supported adapter declares default PR evidence scheduled/manual evidence and whether that evidence is direct-unit fake DB miniredis hermetic fixture or real-service-backed. - `make coverage-check` now writes `.ci-result/coverage/summary.md` so CI can append root/contrib coverage totals to the GitHub job summary without making aggregate coverage the test-quality score. - Added `make reference-service-coverage` as non-Docker generated-service coverage evidence. It writes `.ci-result/coverage/reference-service.func` and `.ci-result/coverage/reference-service-summary.md` separately from toolkit root/contrib coverage thresholds. - Docscheck now keeps the checked-in reference service package test inventory explicit including package-level rationales for generated or entrypoint packages that intentionally do not carry direct tests. End-game hardening - `make generated-upgrade-compat-check` now accepts `GENERATED_UPGRADE_COMPAT_REFS` and defaults to checking both `v3.0.0` and `v3.1.2` `GENERATOR_REF` remains as a source-compatible single-ref alias. - Generated upgrade compatibility evidence now writes one log per generator ref plus `.ci-result/generated-upgrade-compat/status.tsv`. - Full-profile resource generation tests now prove the generated `project` replacement path with required/default/enum fields filters deterministic sorts OpenAPI/client checks contract checks and `resource-check` evidence. - Full-profile docs and generated READMEs now state that sample `widgets` are app-owned starter domain code meant to be replaced or complemented by product resources. - Added `make reference-service-evidence` which records non-blocking reference-service proof under `.ci-result/reference-service/` with optional `REFERENCE_SERVICE_DOCKER 1` and `REFERENCE_SERVICE_MINIO 1` runtime evidence. - Added a reference-service adoption evidence template for setup time upgrade results OpenAPI/client checks tenant isolation idempotency backup/restore load-smoke notes and known pain points. Release proof and reference service - Removed the temporary `.next_steps.md` release checklist after publishing `v3.1.0` future release baseline guidance now lives in the release runbook. - Added `examples/reference-saas-api` as a checked-in `saas-api-full` adoption proof service with local workspace replacements typed client output OpenAPI/contract assets Docker integration assets deployment starters and observability assets. - Added `make reference-service-check` as optional non-Docker evidence for the checked-in reference service. It stays outside default `finalize`. - Generated `saas-api-full` `.gitignore` files no longer ignore `internal/client/apiclient` so the checked-in typed Go client can be tracked by generated services. Contrib validation adapter - `contrib/adapters/validation` now uses `github.com/aatuh/validate/v3@v3.0.7` instead of `github.com/go-playground/validator/v10`. - Validation tags in toolkit examples now use the validate v3 grammar such as `validate: string required email ` and `validate: int min 1 `. - Field errors now preserve validate v3 JSON field paths and stable error codes while continuing to avoid raw submitted values in error strings. The deprecated `ValidationError.Value` field is retained for source compatibility but is no longer populated by the adapter. - `NewPlaygroundValidator` remains as a deprecated source-compatible alias but it no longer constructs a go-playground-backed validator. Use `NewValidateValidator` for new code. 2026-05-19 Maturity evidence - Added `make generated-upgrade-compat-check` an opt-in generated-service upgrade compatibility signal that generates `saas-api-full` from the prior v3 baseline replaces toolkit dependencies with the workspace and runs generated tests OpenAPI client and contract checks. This stays outside `finalize`. - Raised the JWT middleware package coverage floor after adding behavior tests for valid subject propagation skip-header enforcement nil/disabled handler behavior safe close behavior and JWKS health checks. - Raised the health endpoints package coverage floor after adding behavior tests for public liveness/readiness separation dependency state transitions timeout mapping public detail redaction admin-only detailed health access dependency checker options and scheduler callbacks. - Raised the OpenAPI validation middleware coverage floor after adding behavior tests for option constructors OpenAPI file loading route failure Problem Details request validation field mapping response validation error hooks streaming opt-outs large-response bypasses and response buffering limits. - Raised webhook delivery and Postgres webhook delivery adapter coverage floors after adding behavior tests for signing endpoint policy retry classification safe error surfaces tenant mismatch rejection replay safety attempt recording secret resolution and readiness health. - Raised the pgxpool adapter coverage floor after adding behavior tests for constructor validation bounded startup contexts database readiness mapping plain-value snapshots legacy stats wrappers acquire failures and close idempotence. - Added a docscheck gate that every `supported-adapter` contrib package has direct tests package docs a behavior-contract row and release drift coverage before it can retain the supported-adapter classification. - Added a manifest-driven adapter maturity review to the production-readiness docs so supported adapters are visible as evidence-complete and experimental packages are clearly not promoted. - Updated the release workflow provenance attestation action from the older `actions/attest-build-provenance` generation to a pinned v4.1.0 commit while preserving release artifact verification semantics. - Updated generated lean and full scaffold GitHub Actions templates to pinned `actions/checkout` v6.0.2 and `actions/setup-go` v6.4.0 commits. - Added `make actions-audit` and contract coverage for pinned GitHub Actions workflow refs stale action comments and generated workflow template versions it runs in `make audit-check` and remains non-mutating. - Tightened README and production-readiness positioning so api-toolkit is explicitly scoped to conventional HTTP/JSON API infrastructure not a universal backend platform and generated code is app-owned. - Aligned the release runbook with end-game proof targets by making `actions-audit` `coverage-check` generated upgrade compatibility generated integration and reference-service evidence visible to release reviewers while keeping Docker-backed checks opt-in. - Tightened the optional GitHub governance verifier so release tag protection covers both root `v ` tags and contrib module `contrib/v ` tags. - Removed the local root-module `replace` directive from `contrib/go.mod` so the contrib CLI can be installed with `go run github.com/aatuh/api-toolkit/contrib/v4/cmd/api-toolkit@vX.Y.Z`. - Added `docs/coverage-hardening-backlog.md` to make the next JWT health pgxpool OpenAPI middleware and webhook delivery coverage floor increases conditional on behavior-test evidence rather than numeric threshold churn. - Raised maturity evidence for high-risk v3 surfaces with additional JWT OpenAPI validation and bootstrap tests. The package coverage gate now keeps the OpenAPI validation middleware and bootstrap floors aligned with the new observed coverage. - Promoted production-relevant contrib packages to `supported-adapter` after direct tests package docs behavior-contract rows and drift coverage were confirmed: `contrib/adapters/httpclient` `contrib/adapters/envvar` `contrib/config` `contrib/adapters/validation` `contrib/adapters/migrate` `contrib/migrator` and `contrib/scheduler/postgres`. - OPA and Cedar policy adapters now use a shared policy-engine contract for provider-neutral request mapping allow/deny decisions malformed input failures and safe error surfaces and are promoted to `supported-adapter`. Upgrade notes - Contrib packages promoted to `supported-adapter` remain outside the stable root SemVer promise. Incompatible supported-adapter drift is now release-gated and must be release-noted. 2026-05-02 Correctness security and release governance - `docs/full-service-scaffold.md` now defines the planned `saas-api-full` production profile contract including Postgres Redis defaults tenant resources durable async/outbox behavior audit events webhook delivery OpenAPI 3.1 typed Go client output opt-in Docker integration checks and base Kubernetes assets. - `scripts/contrib_release_notes_check.sh` and its contract tests now require release-note coverage for future `saas-api-full` full-profile runtime assets under `contrib/cmd/api-toolkit` including generated Kubernetes YAML and other scaffold templates. - `api-toolkit new service` now supports an initial `--profile saas-api-full` scaffold with API-key auth hexagonal `internal/domain` `internal/app` `internal/adapters/postgres` and `internal/httpapi` boundaries Postgres migrations for tenant/platform tables Docker Compose Postgres/Redis assets with optional MinIO Kubernetes starter manifests OpenAPI golden checks contract lint/diff/client-check targets checked-in Go client output and generated HTTP smoke tests for readiness OpenAPI auth failure validation failure idempotent create replay and ETag conflicts. - `api-toolkit new service --profile saas-api-full` now accepts repeatable `--with stripe-billing resend-email clerk-webhooks` flags. Selected provider workflows generate app-owned `internal/providers` starter packages provider docs env examples manifest entries fake-provider tests tenant-scoped audit behavior and webhook/signature verification boundaries without adding provider-specific imports to the toolkit root module. - The async audit cache objectstore webhookdelivery OIDC middleware OIDC integration and their Postgres/Redis/S3 adapters now have supported-adapter classification package contract rows drift-gate coverage and release-note requirements. Postgres audit operation outbox and webhook delivery stores also expose readiness health checkers and `contrib/async/asynctest` adds a reusable async store contract suite for adapter implementations. - `api-toolkit --help` `api-toolkit -h` `api-toolkit help` and equivalent subcommand help forms now return usage with exit code `0` unknown commands continue to exit `2`. - `api-toolkit clients typescript --style fetch` now generates a browser/stdlib `fetch` TypeScript package for the same supported OpenAPI subset as the typed Go client: JSON bodies path/query/header params API-key and bearer auth Problem Details errors nullable fields enums and raw response access. `api-toolkit new service --profile saas-api-full --client typescript` adds the checked-in TypeScript client package and `client-ts-check` target while keeping the existing generated Go client path source-compatible. Generated TypeScript configs include DOM iterable fetch types and `client-ts-check` runs a local TypeScript build when `node_modules` is already present. - `api-toolkit ops observability --profile saas-api-full` now emits a bounded label Grafana/Prometheus/runbook bundle for the full scaffold and `api-toolkit deploy helm` plus `api-toolkit deploy terraform --cloud aws` generate deployment starters for API worker migration admin service dependency references and AWS Postgres/Redis/S3 primitives. Generated full services now include `cmd/assetcheck` plus `make observability-check` `make deploy-check` and `make asset-check` so those starter assets are validated offline without Helm Terraform jq or network access. Release evidence now records those generated asset checks in `full_profile_scaffold_evidence.asset_validation`. - Generated `saas-api-full` migrator commands now include `plan` `verify` and a guarded `down` command. Down migrations require both `--allow-dangerous-down` and `ALLOW_DANGEROUS_MIGRATION_DOWN true` and remain documented as local/schema-teardown only. When both guards are present the generated command now delegates to `bootstrap.RunDown` and reverts one latest applied migration through the contrib migrator. - `api-toolkit generate resource` now accepts the v2 field and route-shaping flags `--field` `--filter` `--sort` `--admin` `--relationship` and `--object-field` validating the field DSL before mutating generated projects. Generated resources now wire exact-match list filters and allow-listed deterministic sorts through HTTP query parsing application services parameterized Postgres queries OpenAPI parameters generated typed clients and partial Postgres indexes. Relationship flags add ` name _id` fields and object-backed fields must end in `_key` and expose only object keys not payloads. `--admin` now mounts a generated admin-list endpoint under `/admin/ plural ` on the admin router only protected by `X-Admin-Key` and an explicit tenant selector. - Provider workflow scaffolds now include `cmd/provider-replay` and generated provider-check runs package tests plus deterministic replay validation for checked-in Stripe Resend and Clerk fake fixtures. Live provider checks remain gated by `RUN_PROVIDER_LIVE_CHECKS true`. - `api-toolkit contracts changelog` and `api-toolkit contracts impact` now report OpenAPI operation additions/removals and machine-readable breaking client impact for release review. Contract lint and impact checks now also cover OpenAPI 3.1 composition review metadata streaming and binary response metadata callback/webhook metadata schema default changes enum widening and narrowing and oneOf/anyOf/allOf composition changes. - `api-toolkit new service --profile saas-web --auth session oidc-session` now emits a separate browser/session starter so API-first profiles stay unchanged. The generated profile includes cookie security defaults memory and Redis session-store boundaries guarded production startup validation CSRF middleware OIDC callback state validation browser-safe CORS and session fixation tests without adding session dependencies to the root module. - `api-toolkit new service --profile saas-api-full --with entitlements` now emits provider-neutral generated app code for plans features quotas usage counters OpenAPI entitlement routes Postgres `tenant_entitlements` and `billing_mappings` persistence and billing-provider composition guidance. The workflow composes with `--with stripe-billing` by updating app-owned billing mappings before entitlement changes without adding Stripe-shaped ports to core. - `github.com/aatuh/api-toolkit/contrib/v4/entitlements` now provides provider-neutral feature and quota contracts low-cardinality decisions reusable store contract tests and HTTP enforcement middleware that avoids exposing tenant or billing identifiers in Problem Details responses. - Release evidence now expands `full_profile_scaffold_evidence` with explicit fields for OpenAPI 3.1 full scaffold output typed client generation resource generator checks provider-flag generation worker wiring generated integration workflow assets and opt-in Docker integration status. The focused `full-profile-scaffold-check` target now covers provider workflow generation and resource generation in addition to the full scaffold auth modes. - Generated `saas-api-full` services now include tenant domain and application services for organizations memberships invitations role checks and invitation acceptance. The generated service hashes invitation tokens before storage returns the raw invitation token only from the create-invitation use case and includes generated unit tests for owner membership role failures wrong-token failures and single-use invitation acceptance. - Generated `saas-api-full` HTTP routers now expose organization create/list member list invitation create and invitation accept routes with OpenAPI contracts generated Go client methods idempotency metadata tenant policy metadata and generated HTTP tests for role failures and token replay. - Generated `saas-api-full` services now include API-key lifecycle management for organization-scoped create/list/revoke scoped permissions one-time raw secret return non-secret key prefixes peppered SHA-256 hash storage last-used tracking on verification and generated OpenAPI/client coverage. - `api-toolkit new service --profile saas-api-full --auth jwt clerk oidc` now emits matching bearer-auth runtime wiring generated auth tests tenant claim checks scope checks and BearerAuth OpenAPI security instead of falling back to API-key-shaped full-profile router code. - Generated `saas-api-full` services now include an async widget import workflow using `202 Accepted` `Location`/`Retry-After` tenant-scoped operation polling at `GET /operations/ id ` replay-safe idempotency a generated worker service over the contrib async store/handler contracts and OpenAPI/client coverage for `createWidgetImport` and `getOperation`. - Generated `saas-api-full` services now wire optional Postgres runtime startup checks: when `DATABASE_URL` is set generated code opens a pgx pool pings it verifies required platform tables closes the pool on shutdown and reflects database failures through public readiness and admin detailed health. - Generated `saas-api-full` services now use `bootstrap.NewAPIService` as the composition root for public/admin listeners strict SaaS middleware order validation safe system endpoint mounting graceful shutdown and async worker lifecycle. The full profile now exposes `/livez` separately from `/readyz` keeps liveness process-only moves detailed health/metrics/pprof to the admin listener when `ADMIN_ADDR` is set and enables runtime OpenAPI request validation by default with response validation enabled in development/test or by `OPENAPI_RESPONSE_VALIDATION true`. - Generated `saas-api-full` services now include an in-process audit recorder and write-route hooks for organization invitation API-key widget and async import actions with generated tests proving audit metadata redaction and no raw API-key secret leakage. - Generated `saas-api-full` services now include outbound webhook event catalog endpoint create/list delivery list and delivery replay routes widget writes enqueue tenant-scoped pending deliveries for subscribed endpoints generated OpenAPI/client output covers those operations and tests prove webhook signing secrets are returned only at endpoint creation. - Generated `saas-api-full` OpenAPI documents now opt into OpenAPI 3.1 through `specs.NewRegistryWithOptions ... OpenAPIVersion31 ` while the lean `saas-api` scaffold keeps the existing OpenAPI 3.0 default. - Generated `saas-api-full` services now include a generated cache service in-memory local cache store Redis cache adapter `CACHE_STORE` configuration cache readiness composition and cached webhook event catalog responses with generated tests for TTL cloning Redis address validation and cache hits. - Generated `saas-api-full` services now include tenant-scoped object storage routes and application services with strict key content-type and size validation OpenAPI/client coverage audit hooks and tests proving object payloads are not exposed in list/create responses or validation problems. - Release evidence now records `full_profile_scaffold_evidence` and `make release-check` includes a focused `make full-profile-scaffold-check` target so the generated `saas-api-full` service OpenAPI/contract workflow and generated Go client are explicit release signals. Generated Docker integration checks remain opt-in and are reported separately through the non-blocking integration evidence status. - Generated `saas-api-full` `integration-check` now uses a dedicated script that starts Postgres and Redis applies the generated migration runs generated unit tests starts the API on localhost and performs HTTP smoke checks for readiness OpenAPI authentication failure tenant membership managed API-key authentication idempotent widget writes ETag conflict handling async operation polling outbox completion/retry behavior webhook delivery/replay object write/readback audit writes admin detailed health admin metrics admin pprof and public admin-route isolation before tearing Docker volumes down. Set `INTEGRATION_OBJECT_STORE s3` to have the script start the optional MinIO profile initialize the generated `api-objects` bucket and run the same object checks through the S3-compatible adapter. Fresh generated checkouts now materialize `.env` from `.env.example` before invoking Docker Compose and the generated Postgres volume mount uses the PostgreSQL 18-compatible `/var/lib/postgresql` parent directory. Generated full-profile Makefile Dockerfile and integration checks now hydrate module sums with `go mod tidy` before build or test commands and generated `go.mod` files use the installed toolkit release version instead of pinning the stale v2.1.0 baseline when the CLI is installed from a SemVer tag. The generated integration script now feeds SQL through stdin so psql variables are expanded isolates generated auth tests from integration actor environment variables uses current-compatible MinIO `mc mb --ignore-existing` flags and tears down Compose with the objectstore profile enabled so optional MinIO resources do not remain running after S3 checks. - Postgres audit and outbox adapters now exercise real-SQL failure paths more closely: audit SQL no longer includes Go comment text and outbox retry scheduling casts the retry base timestamp before adding interval backoff. - Generated `saas-api-full` widget services now use an application storage port and the generated runtime switches to a Postgres widget store when `DATABASE_URL` is configured. The store persists widget create/update/delete state in the generated `widgets` table while preserving the local in-memory default for tests and lightweight development. - Generated `saas-api-full` API-key services now switch to a generated Postgres API-key store when `DATABASE_URL` is configured. The store persists only keyed hash bytes display prefixes scopes expiry revocation and last-used timestamps raw API-key secrets are still returned once and are not durable data. - Generated `saas-api-full` tenancy services now switch to a generated Postgres tenancy store when `DATABASE_URL` is configured. The store persists organizations owner memberships role checks invitation token hashes invitation acceptance and member listing while keeping raw invitation tokens return-once only. - Generated `saas-api-full` async widget imports now switch to generated Postgres operation/outbox wiring when `DATABASE_URL` is configured. The app service writes tenant-scoped pollable operation rows enqueues outbox work and the generated outbox store leases work through contrib async while keeping failure problems sanitized. - Generated `saas-api-full` Postgres runtimes now route the shared outbox through `contrib/async` s handler mux dispatching `widgets.import` to the widget importer and `webhook.delivery` to the outbound webhook deliverer. Webhook attempts are recorded through the generated app/Postgres store boundary with sanitized errors and low-cardinality delivery metrics. - Generated `saas-api-full` services now include a dedicated `cmd/worker` binary for background jobs an `ASYNC_WORKER_ENABLED` switch for API processes Docker Compose worker service wiring a Kubernetes worker Deployment and integration-check startup that exercises the worker separately from the public API process. - Generated `saas-api-full` integration checks now run a local webhook receiver prove successful outbound delivery and replay reach it verify failing webhook endpoints record retryable delivery state force a poison outbox row into `dead_letter` and check receiver/delivery output does not expose the generated signing secret. - Generated `saas-api-full` services now emit contrib migrator-compatible ` .up.sql` migrations plus a generated `cmd/migrate up status check` binary. Docker Compose runs a dedicated `/migrate -dir /migrations up` service before API/worker startup the integration script applies and checks migrations through `cmd/migrate` and the Docker image now includes `/migrate` plus `/migrations`. - Generated `saas-api-full` Kubernetes assets now include ConfigMap Secret placeholder migration Job worker Deployment internal-only admin Service PodDisruptionBudget HPA NetworkPolicy resource requests/limits non-root security contexts and `/livez`/`/readyz` probes. The generated integration workflow is opt-in through `workflow_dispatch` and scheduled runs instead of default PR CI. - Generated `saas-api-full` services now include an `api-toolkit.yaml` manifest and `resource-check` target and `api-toolkit generate resource` now supports manifest-gated tenant-scoped CRUD generation inside full-profile projects. The generator adds domain/app/Postgres/httpapi files a contrib-migrator ` .up.sql` migration route/OpenAPI contracts audit hooks webhook event hooks OpenAPI golden regeneration typed Go client regeneration and fails closed when expected generated anchors are missing. - Generated `saas-api-full` object routes now support `OBJECT_STORE s3` via a generated blob-store port and S3-compatible adapter wrapper. Tenant and role checks remain in the app service object bytes are written read and deleted through the contrib S3 adapter with bounded size and content-type policy. - Generated `saas-api-full` S3 object routes now use a generated Postgres object metadata store when `DATABASE_URL` is configured so tenant-scoped list/get/delete state survives process restarts while payload bytes remain in the object store. - Generated `saas-api-full` webhook routes now switch to a generated Postgres webhook store when `DATABASE_URL` is configured. Endpoint signing secrets are encrypted with `WEBHOOK_SECRET_KEY` delivery history is tenant-scoped and replay updates the delivery row while requeueing the matching outbox job. - Generated `saas-api-full` unsafe write routes now use the core idempotency middleware with tenant-aware hashed storage keys. Local scaffolds default to in-memory replay `IDEMPOTENCY_STORE redis` wires the generated Redis adapter for cross-instance replay state. - Generated `saas-api-full` protected routes now use the core rate-limit middleware. Local scaffolds default to in-process buckets production defaults require `RATE_LIMIT_STORE redis` and wire a generated Redis limiter with hashed actor/tenant/route keys. - Generated `saas-api-full` services now create a contrib Prometheus recorder wrap public `net/http` routes with HTTP metrics middleware and serve the standard Prometheus handler only behind admin authentication. Generated tests assert request metrics use route-pattern labels and do not expose tenants actors API keys admin keys or idempotency keys. - Generated `saas-api-full` admin routers now mount real Go pprof handlers via `pprof.RegisterAdminRoutes` instead of returning a placeholder response. Generated tests assert pprof is absent from the public handler and requires `X-Admin-Key` on the admin handler. - Generated `saas-api-full` API-key auth mode now verifies generated API keys through the generated API-key service when the static bootstrap `API_KEY` does not match. Managed keys enforce route scopes bind requests to their organization update last-used state fail after revocation and keep raw key secrets out of Problem Details. - Generated `saas-api-full` audit recording now delegates to the contrib Postgres audit store when `DATABASE_URL` is configured after the generated service has produced event IDs timestamps and redaction-safe metadata. Local development keeps the existing in-memory audit recorder. - `specs.NewRegistryWithOptions` now supports explicit OpenAPI 3.1 output via `specs.RegistryOptions OpenAPIVersion: specs.OpenAPIVersion31 ` while preserving the existing `specs.NewRegistry` OpenAPI 3.0 default. - `specs` now includes additive schema helpers for reusable refs nullable schemas examples enum values struct-tag examples/enums/nullable fields request/response media examples and reusable HTTP Problem Details response components. - `api-toolkit clients go` now generates a stdlib-only Go client package from OpenAPI operations including operation methods path/query/header request options JSON request bodies API-key and bearer auth helpers and Problem Details error decoding. - `api-toolkit clients go --style typed` now generates component schema structs typed request/response operation methods typed Problem Details error handling and raw method escape hatches while preserving the existing `raw` client style as the default. - `api-toolkit new service --profile saas-api-full` now checks in typed Go client output and its generated `client-check` target regenerates with `api-toolkit clients go --style typed`. - `api-toolkit contracts lint` `contracts diff` and `clients go --style typed` now normalize OpenAPI 3.1 schema `type` arrays containing `null` and schema-level `examples` before parser validation. Contract linting also rejects Go client method schema type and parameter identifier collisions that would make typed client output unstable or unbuildable. - `specs.Operation` now includes `OperationID` and emits OpenAPI `operationId` values so route contracts can carry stable client-visible operation identity. - `routepolicy` now includes typed metadata helpers for auth deprecation sunset tenant idempotency rate-limit admin-policy and Problem Details response contracts plus operation linting for missing production policy metadata. - `routepolicy` now exposes typed metadata readers for auth deprecation tenant idempotency rate-limit admin-policy and Problem Details response contracts. Contract linting now requires unsafe-write tenant and idempotency metadata to be explicitly marked `required: true` instead of accepting any extension value. - `routepolicy.LintOperations` and `api-toolkit contracts lint` now fail non-public operations without security metadata and unsafe write operations without tenant idempotency rate-limit and Problem Details policy metadata while allowing known public readiness liveness docs and version routes. - `api-toolkit contracts lint` now accepts repeatable `--public-path` and `--admin-path` flags so applications can extend the default public and operator-only path sets without weakening the built-in production checks. - `routepolicy` `contracttest` and `api-toolkit contracts lint` now enforce unique OpenAPI `operationId` values so generated clients and compatibility reviews can rely on stable operation identity. - `routepolicy.LintOperations` and `api-toolkit contracts lint` now require non-public operations including safe reads to document Problem Details error responses. - `routepolicy.LintOperations` and `api-toolkit contracts lint` now fail unsafe write operations that omit request body metadata for POST/PUT/PATCH or omit a documented 2xx success response. - `contracttest` now includes assertions for operation IDs Problem Details error responses tenant/idempotency/rate-limit/admin policy metadata registry-wide operation ID coverage and conservative OpenAPI compatibility findings. - `contracttest` now includes stricter generated-OpenAPI assertions for expected security scopes tenant policy source idempotency header named admin policy and sets of Problem Details response statuses. - `contracttest.OpenAPICompatibilityFindings` now reports tenant idempotency rate-limit admin-policy and deprecation/sunset route policy drift matching the stricter `api-toolkit contracts diff` behavior. - CI now runs `make docs-check` explicitly and runs `make contrib-release-notes-check` on pull requests against the fetched PR base ref keeping documentation and supported-contrib release-note governance visible before merge. - CI pull-request governance now also runs `make contrib-api-drift-report` against the fetched PR base ref so supported-adapter incompatible drift fails before merge without making contrib part of the stable core API promise. - `make contrib-release-notes-check` now reviews `github.com/aatuh/api-toolkit/contrib/v4/cmd/api-toolkit` behavior files in addition to supported adapters integrations middleware bootstrap and telemetry so scaffold and contract-tooling behavior changes require release-note coverage. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap` now exposes `APIService` and `APIServiceConfig` as a supported composition root for generated services with safe admin-wrapper system endpoint mounting and startup checks. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap.APIServiceConfig` now accepts `AdminAddr` and `AdminRouter` for a separate admin listener and `APIService.AdminHandler ` exposes the composed admin handler for tests and custom server wiring. - `github.com/aatuh/api-toolkit/contrib/v4/cache` and `github.com/aatuh/api-toolkit/contrib/v4/adapters/cacheredis` add supported contrib cache contracts and a Redis-backed cache adapter with TTL delete health-check and reusable adapter-contract coverage. - `github.com/aatuh/api-toolkit/contrib/v4/audit` and `github.com/aatuh/api-toolkit/contrib/v4/adapters/auditpostgres` add supported contrib audit-event contracts reusable recorder-contract tests and a transaction-aware Postgres audit recorder that stores actor type tenant action resource result request ID and redaction-checked metadata. The generated `saas-api-full` audit migration now includes `actor_type`. - `github.com/aatuh/api-toolkit/v4/operations` adds additive write-side repository contracts plus lifecycle helpers for validating operation states terminal states and pending/running/succeeded/failed/canceled transitions. - `github.com/aatuh/api-toolkit/contrib/v4/async` adds a supported contrib durable async worker runner with lease/complete/fail store contracts bounded concurrency graceful shutdown low-cardinality metric hooks and logs that avoid job payloads and raw handler errors. - `github.com/aatuh/api-toolkit/contrib/v4/async` now includes an fail-closed handler mux for routing leased jobs by sanitized low-cardinality kind allowing one durable queue or outbox to back multiple worker concerns without inspecting job payloads. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/operationpostgres` adds an supported Postgres-backed operation repository for pollable async operations including tenant-scoped context helpers JSON result/problem storage create/update support and fail-closed tenant validation. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/outboxpostgres` adds an supported Postgres transactional outbox adapter with enqueue due-event leasing using `FOR UPDATE SKIP LOCKED` lease-owner completion retry backoff dead-letter transition and `contrib/async.Store` compatibility. - `github.com/aatuh/api-toolkit/contrib/v4/objectstore` and `github.com/aatuh/api-toolkit/contrib/v4/adapters/objectstores3` add supported contrib object storage contracts reusable contract-test helpers and a raw HTTP S3-compatible adapter with SigV4 request signing presigned URL hooks content-type and object-size policy checks metadata secret-shape rejection not-found mapping and a bucket health checker. - `github.com/aatuh/api-toolkit/contrib/v4/webhookdelivery` adds supported contrib outbound webhook delivery contracts with a fail-closed event catalog tenant-scoped endpoint matching HMAC-signed HTTP delivery bounded retry backoff helpers replay commands sanitized attempt results and `contrib/async` worker integration that keeps endpoint signing secrets out of durable job payloads. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/webhookdeliverypostgres` adds a supported Postgres adapter for outbound webhook endpoint lookup delivery enqueue outbox job creation attempt recording and operator replay. Endpoint signing secrets are loaded through an application-owned `SecretResolver` instead of raw secret storage in the webhook endpoint table generated `saas-api-full` migrations now include `event_id` and `last_status_code` on webhook delivery rows. The adapter also accepts the shared `webhookdelivery.EndpointPolicy` so generated development and integration services can allow localhost HTTP webhook targets without weakening production HTTPS defaults. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` and `github.com/aatuh/api-toolkit/contrib/v4/middleware/requestlog` now expose outbound webhook delivery observation hooks with bounded event type outcome and status-class labels that omit tenants endpoint IDs delivery IDs URLs payloads secrets and raw error strings. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/auth/oidc` and `github.com/aatuh/api-toolkit/contrib/v4/integrations/auth/oidc` add supported provider-neutral OIDC/JWKS bearer-token middleware with optional discovery issuer/audience and algorithm validation tenant and scope claim mapping JWKS health checks env loading and generated `saas-api-full` `--auth oidc` wiring. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap.APIServiceConfig` now accepts named shutdown hooks so composed services can close auth telemetry or adapter background resources after the HTTP server stops. - `middleware/auth/tenant.Options.RequireAllSources` now lets services require every configured tenant source to be present and equal before a handler runs which supports authenticated-tenant-to-header mismatch checks. - `github.com/aatuh/api-toolkit/contrib/v4/cmd/api-toolkit` adds the developer CLI with `new service` `contracts lint` `contracts diff` and `version` commands. The generated `saas-api` service uses chi-backed bootstrap defaults code-first route contracts OpenAPI output public readiness admin-protected metrics/pprof/detailed health core API-key and tenant middleware and idempotent write behavior plus a checked-in OpenAPI golden workflow. - Generated `saas-api` services now fail startup under `ENV production` unless `API_KEY` and `ADMIN_KEY` are explicitly set so local fallback credentials cannot be deployed accidentally. - Generated `saas-api` services now include a `.dockerignore` and a hardened multi-stage Dockerfile that runs tests during build compiles a static binary and runs it from a non-root distroless runtime image instead of `go run` in a full Go toolchain image. - Generated `saas-api` services now include a `.gitignore` that excludes local `.env` files coverage output temporary directories test binaries and the built service binary while keeping `.env.example` tracked. - Generated `saas-api` Makefiles now include `contracts-lint` and `contracts-diff` targets backed by the api-toolkit CLI and generated `finalize` runs those contract checks alongside tests and OpenAPI golden verification. - Generated `saas-api` Makefiles now make `coverage-check` enforce `COVERAGE_MIN` instead of only writing a coverage profile so generated CI fails closed when test coverage drops below the configured floor. - Generated `saas-api` Makefiles now install `govulncheck` under `.tools/bin` by default and invoke it through the overridable `GOVULNCHECK` variable so scaffold checks do not require globally mutating the developer Go bin. - Generated `saas-api` services now keep memory idempotency storage as the local default but reject it under `ENV production` production defaults to the Redis idempotency adapter and requires `REDIS_ADDR` before startup. - `api-toolkit new service` now supports `--auth jwt` and `--auth clerk` for the `saas-api` profile. Generated bearer-token services validate tokens through JWKS require issuer and audience configuration extract tenant scope from validated token claims enforce route scopes close auth middleware through bootstrap shutdown hooks and keep generated contract tests and OpenAPI goldens aligned. Development-header and unknown modes still fail closed. - `api-toolkit new service` now supports the explicit `dev-api` profile with `--auth dev-headers`. The generated development service requires explicit dangerous-bypass environment settings separates debug user tenant and scope headers keeps tenant mismatch and idempotent write tests and refuses to start with dev-header auth when `ENV production`. - Generated services now wire `bootstrap.NewDefaultRouterWithConfig` to the contrib Prometheus recorder so protected `/metrics` exposes bounded HTTP request counters and histograms instead of only runtime collector output. - `contrib/middleware/auth/clerk.Subject` now exposes tenant and scope strings derived from validated JWT claims while preserving subject comparability so applications and generated services can enforce tenant and route-scope policy from Clerk tokens. - `middleware/idempotency.Options.OnOutcome` now emits bounded request-path idempotency outcome events and `OutcomeEvent.MetricLabels ` exposes only method store class outcome and status class for metrics. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now records bounded `idempotency_outcomes_total` Prometheus counters through `IdempotencyOutcomeHook` and `github.com/aatuh/api-toolkit/contrib/v4/middleware/requestlog` now provides `IdempotencyOutcomeLogHook` with the same low-cardinality outcome shape. Generated `saas-api` services wire both hooks by default. - `middleware/idempotency` now supports `Options.StorageKeyFunc` plus `TenantScopedStorageKeyFunc ` so multi-tenant services can hash client-supplied idempotency keys with tenant and actor scope before shared storage access. Generated `saas-api` services opt into the helper while preserving the original `Idempotency-Key` response header on replay. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now records bounded `health_status_changes_total` Prometheus counters through `HealthStatusChangeHook` using only `from` and `to` health-status labels for scheduler transitions. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now treats `net/http.ServeMux` request patterns as route labels when chi route context is unavailable preserving low-cardinality HTTP metrics for stdlib routers. - Routes registered through `routecontracts` now attach bounded `routepolicy` observability labels. Contrib metrics records them through `http_route_policy_requests_total` and contrib request logging emits `policy_ ` fields without raw scopes tenant sources rate-limit policy names or admin policy names. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now exposes `RoutePolicyLabels` so custom recorders can reuse the same bounded route-policy label normalization as the Prometheus recorder. - `middleware/idempotency.Options` now includes additive `RequireKey` support. Generated SaaS services enable it so unsafe writes without `Idempotency-Key` fail closed with Problem Details 400 instead of executing untracked. - Generated service READMEs and security guidance now document that unsafe writes without `Idempotency-Key` fail with Problem Details 400 and that generated idempotency storage keys are tenant and actor scoped. - Generated services now load bootstrap router env controls for `TRUSTED_PROXIES` and rate-limit skip headers failing startup on malformed proxy CIDRs or unsafe bypass settings. - Generated services now register a shutdown hook for Redis idempotency clients so production stores are closed through the `bootstrap.APIService` lifecycle. - Generated services now support `RATE_LIMIT_STORE redis` and default to Redis rate limiting in production including startup validation and Redis client shutdown hooks. - Generated scaffold documentation now describes the local memory and production Redis rate-limit store defaults. - Generated services now initialize contrib OpenTelemetry tracing from `OTEL_ ` environment variables fail startup when tracing is enabled without an OTLP endpoint and close the tracer provider during service shutdown. - Generated compose files now include a Redis service healthcheck persistent volume and container-safe Redis address overrides for idempotency and rate limiting. - `github.com/aatuh/api-toolkit/contrib/v4/telemetry.InitTracing` now returns an error when tracing is explicitly enabled without an OTLP endpoint instead of silently installing a noop exporter. - `api-toolkit version` now prints Go runtime main module core module contrib module build commit and build date metadata for release evidence. - `api-toolkit version --json` now emits the same installed tool metadata in a stable machine-readable shape for release evidence and automation. - Generated services now stamp `/version` from `appVersion` `buildCommit` and `buildDate` and the generated Makefile/Dockerfile pass those fields through build flags with local `dev`/`unknown` defaults. - `make v3-readiness-check` now runs focused compatibility-sensitive cleanup guardrails and is included in `make release-check` and release evidence logs keeping major-version removal planning tied to roadmap replacement guidance and release-note requirements. - CI governance now runs `make v3-readiness-check` explicitly alongside docs-check and contrib release-note/drift gates. - `api-toolkit new service` now emits a pinned GitHub Actions workflow that runs `make finalize` keeping generated services on the same test build OpenAPI golden and contract lint path documented by the scaffold. - The getting-started guide is now scaffold-first and verifies the generated service OpenAPI golden and contract lint/diff workflow instead of teaching a hand-written minimal starter as the primary path. - Generated service Makefiles now include `fast-check` `audit-check` `coverage-check` `test-race` `vuln` and `clean` targets so scaffold CI runs race tests and govulncheck in addition to build and contract checks. - Generated service Makefiles now include optional `sbom-local` output through Syft writing SPDX JSON to `.ci-result/sbom/sbom.spdx.json` without adding Syft to the default finalize path. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap.APIServiceConfig` now supports named `BackgroundTasks` that run with the service context fail the service on unexpected task errors and stop during graceful shutdown. Generated `saas-api` services use this to run health refreshes with bounded health-status metrics. - `make release-check` now runs `contrib-api-drift-report` as a first-class release-readiness subcheck and release evidence reuses that log for the structured contrib drift summary instead of leaving supported-adapter API drift only in the evidence-only path. - `api-toolkit contracts diff` now performs compatibility review over parsed OpenAPI operations. Additive operations pass while removed operations changed operation IDs removed documented parameters added required parameters removed documented responses request-body tightening or content removal response content removal and changed security requirements fail with deterministic findings. - `api-toolkit contracts diff` now also fails closed when existing operations drift in tenant idempotency rate-limit admin-policy or deprecation/sunset route policy metadata. - `api-toolkit contracts diff` and `contracttest.OpenAPICompatibilityFindings` now also flag removed or changed `components.securitySchemes` so auth header bearer OAuth or OIDC contract drift is caught even when operation-level security requirements keep the same scheme name. - `api-toolkit contracts lint` `api-toolkit contracts diff` and `contracttest.OpenAPICompatibilityFindings` now honor top-level OpenAPI `security` as inherited operation security and report `global_security_changed` when release-review specs change that default. - `api-toolkit contracts lint` now emits a stable `GLOBAL` `security_scheme_undefined` finding when top-level OpenAPI security references a scheme missing from `components.securitySchemes`. - `specs.Registry` now exposes `SetSecurity` for code-first top-level OpenAPI `security` and `contracttest.SecuritySchemeDefinitionFindings` verifies those global requirements against `components.securitySchemes`. - Generated `api-toolkit new service` scaffolds now use `specs.Registry` top-level OpenAPI security defaults in runtime docs and golden files while keeping protected write operation scopes explicit. - Generated service READMEs now list admin-protected detailed health and pprof routes and scaffold tests assert detailed health metrics and pprof all require `X-Admin-Key`. - `api-toolkit contracts diff` now also reviews OpenAPI component schemas and reports removed schemas added required properties removed object properties type/ref changes and enum value removals as compatibility findings. - `api-toolkit contracts diff` now applies those conservative schema compatibility checks to inline request and response media schemas on existing operations so handler-local contract narrowing is caught before release. - `api-toolkit contracts lint` now fails when an operation references a security requirement that is not defined in `components.securitySchemes` preventing reviewed specs from declaring unenforceable auth. - `contracttest` now exposes `SecuritySchemeDefinitionFindings` and `AssertSecuritySchemesDefined` so service tests can catch the same undefined OpenAPI security-scheme references as CLI contract linting. - `contracttest.OpenAPICompatibilityFindings` now reports the same conservative OpenAPI component and inline request/response schema drift findings so library tests and CLI release review stay aligned. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap` now exposes middleware stage identifiers strict/dev middleware order helpers and startup validation for custom APIService middleware order declarations. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap` now exposes `StrictSaaSAPIMiddlewareOrder` for services that require the full production policy sequence of auth tenant and idempotency after the transport middleware stack and generated `saas-api` services declare that order during startup validation. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now canonicalizes Prometheus HTTP metric labels so methods stay within standard HTTP verbs plus `OTHER`/`UNKNOWN` invalid statuses collapse to `0` and route labels are trimmed before series creation. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/openapi` response validation now accepts `ResponseValidationOptions.ShouldValidate` so services can skip response buffering for streaming upgrade or large-download routes while keeping request validation enabled. - `middleware/timeout.NewHard` now accepts `Options.EventHooks` emitting bounded operator metadata for timeout panic and response-capture overflow outcomes without exposing panic values paths query strings headers or bodies. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now exposes `HardTimeoutEventHook` and records bounded hard-timeout outcomes in `http_hard_timeout_events_total` request logging now exposes `HardTimeoutEventLogHook` with the same bounded event shape. - `securityprofile.StreamingRouteOverride` now provides an explicit route-level opt-out for streaming SSE websocket or large-download routes that must avoid hard-timeout response buffering and preserve optional writer interfaces. - `contrib/adapters/idempotencyredis.ReleaseReservation` now performs atomic token-aware compare-and-delete cleanup so stale releasers cannot delete newer in-flight reservations after expiry or replacement. - `middleware/timeout.NewHard` now contains handler panics inside the hard-timeout goroutine. Panics before timeout return deterministic Problem Details responses while panics after timeout are contained after the 504 response has already won. - `securityprofile.WithHardTimeoutMaxCaptureBytes` and `RouteOverride.HardTimeoutMaxCaptureBytes` expose hard-timeout response capture limits through global and per-route profile configuration. - Memory and Redis idempotency adapter legacy recovery events now hash keys by default and expose raw keys only through explicit raw-key opt-in fields for short incident-review windows. - The contrib release-note review gate now scopes behavior-change release-note requirements to packages classified as `supported-adapter` preserving supported-adapter governance without over-requiring notes for experimental or wrapper-only contrib internals. - The contrib release-note review gate now includes package-owned runtime assets such as JSON YAML SQL template and policy files under supported contrib package directories. - `docs/supported-adapter-contracts.tsv` now defines behavior contracts and direct-test/release-drift evidence for every `supported-adapter` contrib package. The chi router adapter and zap logger adapter are promoted to `supported-adapter` and included in the contrib drift gate. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/ratelimittest` adds reusable rate limiter adapter contract coverage and `ratelimitredis` now runs it to prove empty-key bypass per-key isolation retry-after and refill behavior. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/healthchecktest` adds reusable health checker adapter contract coverage for supported Stripe Resend and Clerk readiness checks. Stable core API additions - Added stable core packages `binding` and `middleware/auth/apikey` for typed request binding Problem Details-compatible validation errors API key authentication optional auth context principals and scope enforcement. - `endpoints/list` now includes signed HMAC cursor pagination helpers alongside the existing limit/offset APIs. - `specs.Operation` now supports route contract metadata for parameters security requirements scopes deprecation sunset metadata request bodies responses and deterministic OpenAPI extensions. - `contrib/examples/api-key` demonstrates local-only HMAC-backed API key verification and scoped routes. - Added stable core package `httpcache` for ETag and Last-Modified conditional request helpers including `304 Not Modified` and `412 Precondition Failed` response paths. - Added stable core package `middleware/deprecation` for runtime `Deprecation` `Sunset` and deprecation-policy `Link` headers. - Added stable core package `webhooks` for raw-body-preserving HMAC webhook verification JSON event decoding accepted-event handling and Problem Details failures. - `specs` now supports reusable OpenAPI schemas responses security schemes and schema refs for request and response content. - Added stable core package `routecontracts` for registering handlers and matching OpenAPI operations together. - Added stable core package `negotiation` for `Accept` and `Content-Type` negotiation including `406` and `415` Problem Details responses. - `specs` now generates deterministic OpenAPI schemas from Go structs for route contract components. - `httpx` now includes a typed Problem Details catalog for stable machine-readable error codes and catalog-backed error mapping. - Added stable core package `queryparams` for collection sorting filtering sparse fieldsets and include parameter parsing without storage coupling. - Added stable core package `operations` for `202 Accepted` responses and pollable asynchronous operation resources. - `webhooks` now includes outbound HMAC-SHA256 signing helpers for JSON event requests that remain compatible with the existing receiver verifier. - Added stable core package `contracttest` for route contract OpenAPI generated contract and problem catalog assertion helpers. - Added stable core package `routepolicy` and opt-in `routecontracts` policy hooks for deriving deprecation headers content negotiation auth idempotency and rate-limit middleware from route operation metadata. - `specs` can now register reusable Problem Details and validation problem components from an `httpx.ProblemCatalog` while preserving unchanged OpenAPI output until the catalog helper is used. - `middleware/ratelimit` can now emit standard `RateLimit-Limit` `RateLimit-Remaining` `RateLimit-Reset` and `Retry-After` headers when header emission is explicitly enabled. - Added stable core package `idempotent` for idempotency-key requirements deterministic request hashes conflict/replay Problem Details accepted replay responses and OpenAPI operation extensions. - `webhooks` now includes replay-window checks required event-id contracts timestamp/event-id header constants and delivery attempt/result contract types without adding retry persistence or provider-specific schemas. - Added stable core package `upload` for multipart form decoding required file checks per-file and aggregate size limits content-type allowlists and Problem Details-compatible field errors. - Added stable core package `oauth2` for provider-neutral bearer token claims validators scope checks JWKS configuration values OpenAPI security scheme registration and `authorization.Actor`/scope mapping. - Added stable core package `apitest` for deterministic HTTP API assertions over Problem Details validation fields headers pagination operation-accepted responses webhook signatures and OpenAPI golden output. - Added stable core package `apiclient` for client-side Problem Details decoding cursor iteration `Retry-After` parsing precondition headers API key transports webhook signing transports and JSON request/response helpers. Dependency and release evidence updates - Contrib dependencies were upgraded to burn down the imported-only `govulncheck` findings from v39: `github.com/jackc/pgx/v5` is now on `v5.9.0` and `google.golang.org/grpc` is now on `v1.79.3`. - `docs/dependency-risk.md` now records the v39 advisory ownership map for `GO-2026-4762` `GO-2026-4771` and `GO-2026-4772` the active `docs/vulnerability-dispositions.tsv` manifest is header-only while current imported-only vulnerability evidence is zero. - The release evidence parser contract now includes a mixed same-package contrib drift fixture where one package has both `Incompatible changes:` and `Compatible changes:` and must summarize as incompatible. - Runtime use of the legacy `response_writer` package was removed from `httpx/recover` and maintained contrib HTTP middleware. Those packages now use package-local response wrappers while the public `response_writer` package remains source-compatible for v2 callers. - `make release-artifact-verify-fixture` now builds a synthetic local release asset bundle and runs the local verifier path. This is only local fixture coverage publication verification still requires downloaded GitHub draft release assets `RELEASE_ARTIFACT_VERIFY_MODE publication` `RELEASE_TAG` `GITHUB_REPOSITORY` real Sigstore material and online attestation checks. - The release workflow now prints `make release-review-summary` output after clean evidence is generated and before release artifact verification steps. Contrib behavior and compatibility notes - `github.com/aatuh/api-toolkit/contrib/v4/middleware/auth/devheaders` now requires explicit dangerous-bypass opt-in and trusted-proxy configuration when enabled while keeping exported config and middleware values comparable for v2 source compatibility. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now keeps the existing `NewPrometheusRecorder` signature for v2 source compatibility and adds `NewPrometheusRecorderChecked` for callers that want collector registration conflicts returned as errors. - Idempotency mixed-version compatibility metrics now expose only bounded `method` `store_class` and `outcome` labels. Raw paths idempotency keys key hashes and error strings remain available only on structured events for logs or traces. - `middleware/timeout.NewHard` now enforces a bounded response capture size with a 1 MiB default. Oversized captured responses return Problem Details instead of silently truncating successful responses. - Admin endpoint docs now steer new pprof and detailed-health mounts toward fail-closed registration helpers while preserving legacy source-compatible helpers for v2 callers. - `endpoints/health.Handler.RegisterPublicRoutesTo` and `contrib/bootstrap.MountSystemEndpointsToWithAdmin` now give new system endpoint wiring a source-compatible path that keeps public probes separate from admin-only detailed health metrics and pprof routes. - `webhooks.Receiver` now returns a generic verifier failure detail by default so custom verifier errors are not echoed to clients. Use `ReceiverConfig.VerificationErrorDetail` only for explicitly safe text. Upgrade notes - If you treated maintained contrib middleware or adapters as semver-stable review `API_BASE_REF v2.1.0 GOTOOLCHAIN local make contrib-api-drift-report` before upgrading and check `docs/contrib-api-drift-dispositions.tsv` for the current package-tied disposition. Contrib drift remains report-only this guidance helps migration review but does not extend the stable v2 API promise to contrib. - For `github.com/aatuh/api-toolkit/contrib/v4/middleware/auth/devheaders` set `AllowDangerousDevBypasses` and `TrustedProxies` explicitly when enabling debug-header auth. `TrustedProxies` is a comma-separated CIDR list. - V3 preparation guidance is now consolidated in `docs/v3-compatibility-roadmap.md`: use `compat/billing` or app-owned billing ports database stats snapshots `httpx` or package-local response helpers and token-aware idempotency release before the major-version compatibility removals. 2026-05-01 - Release evidence now writes `release-check-summary.json` schema v2 with per-check command lines exit codes durations log paths tool versions and local-vs-GitHub artifact tier metadata. - `make release-evidence` now runs the release-readiness subchecks through the evidence writer so local summaries have detailed provenance instead of a fixed pass list. - `docs/package-classification.tsv` now documents API and test quality tiers and docscheck mechanically validates direct-test wrapper-smoke example generated tooling test-support excluded and needs-tests classifications. - `docs/v3-compatibility-roadmap.md` now contains one removal matrix for provider-shaped billing ports pgx-shaped database stats `response_writer` tokenless idempotency release unchecked authz construction and checked list parser shims. - `make contrib-api-drift-report` adds a report-only API drift signal for selected high-use contrib adapters and integrations without changing the contrib compatibility policy. - `make contrib-release-notes-check` adds a lightweight review gate requiring release-note coverage when contrib adapter or integration behavior files change. - Release evidence now records `git_state` with branch/detached state dirty flag staged/unstaged/untracked/deleted counts and the commit checked. - Release evidence now records top-level `publication_eligible` automation must require it to be `true` along with passed status clean provenance and clean git state before accepting publication evidence. - Release evidence now fails publication mode on dirty worktrees unless `ALLOW_DIRTY_RELEASE_EVIDENCE 1` explicitly marks the output as local dirty-tree audit evidence. - Release evidence now archives `.ci-result/release-evidence/logs` as `.ci-result/release-evidence/release-evidence-logs.tgz` and records `publication_artifact_expectations` for draft-release asset review. - `make release-artifact-verify` now verifies downloaded draft release asset names `release-asset-manifest.tsv` checksums retained release logs SBOM signatures/certificates and expected provenance subjects before publishing. - The tag-driven release workflow now verifies keyless SBOM signatures against the GitHub OIDC certificate identity and issuer before uploading draft release assets. - Release evidence now records `vulnerability_evidence` from govulncheck logs so imported-but-not-called vulnerability IDs and counts have reviewer disposition in `docs/dependency-risk.md` and `docs/vulnerability-dispositions.tsv`. - Release evidence now dynamically compares imported-only vulnerability IDs with `docs/vulnerability-dispositions.tsv` and fails when dispositions are missing incomplete or expired on the release review date. - `make release-evidence` now archives report-only contrib drift at `.ci-result/release-evidence/logs/contrib-api-drift-report.log` and summarizes drift skipped compatible and incompatible counts in `release-check-summary.json`. - Release evidence now records current contrib drift packages and status compares them with `docs/contrib-api-drift-dispositions.tsv` and fails when current drift has missing or expired disposition coverage. - Current contrib drift disposition is recorded in `docs/contrib-api-drift-dispositions.tsv` including the incompatible report-only `contrib/middleware/auth/devheaders` drift. - `make release-check` and `make release-evidence` now include `contrib-release-notes-check` while `contrib-api-drift-report` reads selected report-only packages from `docs/contrib-api-drift-packages.txt`. - Incompatible report-only contrib drift is acknowledged for this release: `contrib/middleware/auth/devheaders` changed exported struct comparability because middleware/config types now include non-comparable lifecycle fields. This remains a review signal and does not make contrib stable. - `make contrib-release-notes-check` now requires incompatible report-only contrib drift acknowledgement to mention the affected package not only a generic incompatible-contrib phrase. - Docscheck now blocks new production source usage of deprecated billing ports outside `ports`/`compat/billing` and direct database-stat usage outside compatibility or adapter paths. - Idempotency middleware response capture now uses a package-local helper instead of importing the legacy `response_writer` compatibility package. - `docs/release-review.md` gives release reviewers a shorter path through the runbook release notes stability policy package classification compatibility roadmap and evidence artifacts. - Wrapper and example coverage policy now distinguishes wrapper smoke minimums from build-smoke-only example coverage. - Package docs for `ports` `compat/billing` and the legacy response helper package now identify v2 compatibility-sensitive surfaces and preferred replacements for new code. - `contrib/middleware/requestlog` expands header redaction defaults for broader authentication/session families and adds payload field redaction helpers for non-header custom fields. - `contrib/adapters/httpclient` retry defaults are now conservative: `GET` and `HEAD` only other methods such as `PUT` and `DELETE` now require explicit opt-in through `RetryableMethods`. - `contrib/bootstrap` pprof mounting now defaults to opt-in behavior and requires explicit profile intent to enable `Pprof` routes in production-like defaults. - Idempotency in-flight reservations now carry `ReservationToken` and require tokenized releases for healthy non-legacy records while legacy tokenless records are recovered during mixed-version rollouts when stale past `InFlightTTL`. - Idempotency memory and Redis adapters now expose optional legacy-recovery telemetry callbacks for tokenless record migrations `legacy_in_flight_recovered` and `legacy_in_flight_token_mismatch` . - Idempotency middleware now emits compatibility telemetry for mixed-version fallback attempts `legacy_in_flight_fallback_entered` `legacy_in_flight_fallback_recovered` `legacy_in_flight_fallback_rejected` `legacy_in_flight_fallback_unknown` and validates cross-service `InFlightTTL` alignment via `KnownInFlightTTLs`/`FailOnInFlightTTLMismatch`. - `ports.ErrLegacyInFlightReservationMissingToken` has been added for migration-time observability of legacy in-flight record recovery. - `middleware/auth/authz` keeps the v2-compatible single-return constructor and adds `NewRequireRoleMiddlewareChecked` plus bootstrap validation for explicit role requirements and nil resolver detection at route setup. - `endpoints/list` keeps the v2-compatible single-return parser helpers and adds checked variants `ParseListQueryChecked` `DefaultFilterParserChecked` `DefaultSortParserChecked` for callers that need field-level validation errors. - `contrib/middleware/requestlog` documents and supports deep payload redaction for common typed container shapes `map[string]string` `[]map[string]string` while preserving legacy shallow behavior. - Idempotency middleware now emits mixed-version fallback telemetry by default when no `OnLegacyInFlightCompatibility` callback is configured defaults legacy compatibility keys to stable SHA-256 redaction and supports explicit raw-key opt-in through `LegacyInFlightCompatibilityRawKey`. - Idempotency startup rollout governance now includes optional strict clock-preflight checks `FailOnInFlightClockSkewPreflight` for mixed-version safety emitting `ErrLegacyInFlightClockSkewPreflightRisk` in strict mode and advisory deprecation-risk warnings in default mode. - `contrib/adapters/chi` now ships a route bootstrap helper that maps chi route registration context into authz role specs and validates role coverage in one startup call including actionable `ANY`/method route context. - `contrib/middleware/requestlog` normalizes panic observability by always logging recovered panics at error level with failure classification including committed- response panics and preserving committed status for optional downstream analytics. - Release readiness now has a fail-closed `make release-check` path that requires `API_BASE_REF v2.1.0` keeps local `make api-check` fallback behavior separate and publishes `release-check-summary.json` with release SBOM assets. - Root idempotency adapter contract coverage moved to contrib-owned reusable contract tests so root `go.mod` no longer carries contrib Redis or miniredis requirements for core middleware tests. Upgrade notes - If your system endpoint wiring relied on implicit pprof exposure in production profiles use an explicit profile-aware mount helper to re-enable it intentionally. - If you require retries for non-idempotent methods add them explicitly to `RetryableMethods` and confirm the target API contract is idempotent. - If you are rolling out idempotency migration with shared Redis across mixed binary versions ensure all services agree on `InFlightTTL`. Legacy tokenless in-flight entries will be auto-cleared only when stale and mixed-version cleanup can be delayed by that TTL when no newer version processes the key first. - Legacy idempotency cleanup requires aligned timing: set `InFlightTTL` consistently across services and storage layers including matching `InFlightTTL` and key TTL behavior keep `SystemClock` sources synchronized and ensure record `CreatedAt` monotonic assumptions match your deploy latency. Checklist during rollout: 1 run `ValidateRequireRoleMiddleware`-style startup checks for route wiring on all roles-protected endpoints 2 verify `InFlightTTL` parity and shared store key prefixes across all deploy units 3 monitor middleware telemetry outcomes `legacy_in_flight_fallback_entered` `..._recovered` `..._rejected` `..._unknown` while mixed binaries run and 4 remove tokenless-compatibility behavior only after mixed-version fallback suppression reaches zero. - Recommended rollout telemetry contract: - Labels: `method` `path` `store_type` `outcome` `key` optional and `error`. - For metric collectors prefer `LegacyInFlightCompatibilityMetricSink` and `LegacyInFlightCompatibilitySampleEvery` during large rollout waves. - Use `LegacyInFlightCompatibilityAsync` when callback latency must not affect request latency. Keep `Logger`/compatibility sink diagnostics during initial rollout windows for deterministic evidence. - Default warning thresholds: - `legacy_in_flight_fallback_unknown 0` for 5 minutes indicates release risk and should page. - `legacy_in_flight_fallback_rejected / legacy_in_flight_fallback_entered` above `0.5 ` over 10 minutes indicates high key-level contention and should be investigated. - `legacy_in_flight_fallback_recovered / fallback_entered` dropping below `99 ` indicates likely TTL/clock contract mismatch. - Dashboard query examples: - Backpressure behavior: - Synchronous sinks execute in the request path if a custom sink is slow or blocking requests can back up at startup and during mixed-version load. - Enable async emission for high-volume migrations and confirm callback exceptions are tracked by tests or sink-specific observability since they are intentionally recovered and must not abort request handling. - If you rely on zero-config retry behavior in `contrib/adapters/httpclient` review all non-GET/HEAD consumers and update to explicit `RetryableMethods` only for confirmed replay-safe routes and clients. - `NewRequireRoleMiddleware` keeps the v2-compatible single-return constructor. Invalid wiring is still fail-closed at runtime until fixed and will return `401` no actor or `403` actor without role as applicable. For startup validation use `NewRequireRoleMiddlewareChecked` or run `ValidateRequireRoleMiddleware method route mw ` for each protected route. - If you need startup authz migration validation prefer registry-level validation via `ValidateRequireRoleMiddlewareRoutes` during bootstrap and fail startup on the first startup pass when any route fails this check. - Rollout symptoms of misconfigured authz route wiring are usually a startup failure in CI or process init `invalid role middleware for route ...` then runtime `401` for unauthenticated requests and `403` for missing-role users. Rollback sequence when migration checks block startup: 1 restore previous middleware wiring 2 temporarily disable strict constructor checks only as a temporary guardrail 3 reapply the startup check after role/route registration is repaired and 4 rerun staged rollout. - `requestlog` payload redaction assumes redaction-sensitive names based on canonical field patterns `token` `secret` `password` common aliases before any deep traversal. For typed payloads normalize unsupported custom shapes to map/slice-of-map shapes before calling `requestlog.RedactPayloadFieldsDeep` see `contrib/middleware/requestlog/doc.go` . - For mixed-version idempotency rollouts run startup with `FailOnInFlightTTLMismatch` and `FailOnInFlightClockSkewPreflight` only after you have parity checks and rollback strategy in place. Keep both off during the first boot of a migration wave if you need warning-only discovery. - `ports.IdempotencyReleaser.Release ctx key ` remains the v2 compatibility contract for existing custom stores. New stores should also implement `ports.IdempotencyReservationReleaser.ReleaseReservation ctx key token ` so middleware can release only the current tokened in-flight reservation. - To upgrade authz checks with chi either build explicit `[]authz.RequireRoleRouteSpec` and validate via `authz.ValidateRequireRoleMiddlewareRoutes` or use `chi.ValidateRequireRoleMiddlewareRoutes` with a route method resolver closure to map protected handlers. 2026-04-24 - `contrib/telemetry.WrapHTTPClient nil ` now creates an instrumented client with a 10 second timeout instead of an unbounded zero-timeout client. - `contrib/migrator.Options.LockTimeout` can now override the advisory lock wait timeout zero keeps the previous 10 minute default. - `contrib/migrator.Options.UnlockFailureHandler` and the existing migrator logger can now surface advisory unlock failures without replacing the primary migration result. Upgrade notes - If you intentionally need no client-level timeout for a telemetry-wrapped `net/http` client pass an explicit ` http.Client ` to `WrapHTTPClient` prefer request contexts with deadlines for long-running calls. 2026-04-23 - Billing contracts in `ports/billing.go` are now formally deprecated for new code. The same Stripe-shaped v2 model is available through the new compatibility package `github.com/aatuh/api-toolkit/v4/compat/billing`. - `contrib/adapters/pgxpool.Adapter.StatSnapshot ` now copies plain-value pool stats directly from pgxpool instead of routing through the legacy `DatabaseStats` wrapper path. Upgrade notes - Existing code that imports billing contracts from `ports` keeps working for the rest of v2 but new code should migrate to `github.com/aatuh/api-toolkit/v4/compat/billing` so the provider-shaped dependency is explicit before v3 extraction. - If your health or observability code still reads `DatabasePool.Stat ` or depends on `DatabaseStats` move it to `DatabasePoolSnapshotProvider` `SnapshotDatabasePoolStats` or adapter `StatSnapshot ` methods. The legacy counter interface remains for compatibility adapters not as the preferred generic path. 2026-04-19 - `contrib/middleware/auth/devheaders` now requires explicit dangerous-bypass opt-in and trusted-proxy configuration before it will honor debug auth headers. - Health endpoints now fail closed on empty or miswired liveness/readiness probe sets and HTTP handlers only expose detailed dependency output when `ports.HealthCheckConfig.EnableDetailed` is explicitly enabled. - `contrib/adapters/txpostgres.WithinTx` now attempts deferred rollback with a bounded cleanup context even when the caller context is already canceled or timed out. - `contrib/adapters/txpostgres` now fails closed with `ErrPoolNotConfigured` when callers forget to wire a database pool instead of panicking on nil-pool use. - `endpoints/docs.New ` and `NewDefaultHandler ` now default to the first-party static docs surface callers must opt into the CDN-backed Swagger UI mode with `docs.NewSwaggerUI ` or `DocsConfig.HTMLMode`. - `contrib/migrator` now records commit-acknowledgement failures as `uncertain` and blocks later runs when a prior migration record is still `started` or `uncertain`. - `scheduler.Runner` now persists final run records through a bounded cleanup context so graceful shutdown does not drop `LastFinished` updates for jobs that already completed. - `scheduler.Runner` now surfaces recorder persistence failures through structured logs and optional `SetRecorderFailureHandler` callbacks without changing the completed job result or schedule cadence. - JWT and Clerk middleware now share internal auth/JWKS validation primitives with no intended public API or configuration change. Upgrade notes - If you previously enabled `devheaders` without explicitly opting into dangerous bypasses or without trusted-proxy configuration startup will now fail fast until you set both intentionally. - If you had tests or thin wiring paths that called `txpostgres.New nil ` or `txpostgres.FromCtx ... nil ` they now return `ErrPoolNotConfigured` instead of panicking. - If you relied on `docs.New ` or `NewDefaultHandler ` to serve Swagger UI with CDN assets switch to `docs.NewSwaggerUI ` or set `DocsConfig.HTMLMode ports.DocsHTMLModeSwaggerUI` explicitly. - If a deployment previously canceled scheduler job contexts during graceful shutdown completed jobs now get a short recorder-persistence window before exit so restart-time suppression remains accurate. - If operators previously relied on `/health` or equivalent routes exposing dependency-level detail by default set `EnableDetailed` explicitly during wiring otherwise only basic probes should remain visible. - If your deployment workflow retried migrations automatically after commit errors stop doing that. Inspect the database state and reconcile `schema_migrations` before rerunning when a migration is recorded as `started` or `uncertain`. - If you need alerting when scheduler run history cannot be persisted wire `SetRecorderFailureHandler` or monitor the new recorder-failure log events job completion alone no longer implies recorder persistence succeeded. - JWT and Clerk integrations should be behaviorally equivalent to their prior public APIs but custom wrappers that depended on edge-case differences in bearer parsing claim requirements or skip-header handling should be revalidated. 2026-04-15 - Idempotency middleware now releases failed reservations after downstream `5xx` responses and panics so retries with the same payload and `Idempotency-Key` are not blocked behind a stale in-flight record. - Idempotency middleware now fails closed with `503 Service Unavailable` when it cannot persist a completed replay record and it stores an ambiguous state for that key instead of reopening it for another execution. - Idempotency middleware now includes authenticated actor and tenant scope in the default request hash preventing cross-principal or cross-tenant replays from reusing the same key and payload. - Idempotency middleware now caps buffered replay bodies at `1 MiB` by default and returns `503 Service Unavailable` plus an ambiguous key state when a handled response exceeds the replay buffer limit. - `scheduler.Runner` now recovers scheduled-job panics logs and records them as failed runs and keeps future intervals alive instead of letting one bad job crash the process. - `scheduler.Runner` now prevents the same job name from overlapping with itself across duplicate `Start` calls or duplicate scheduling of the same job. - `bootstrap.ProfileStrictAPI` no longer enables wildcard CORS by default browser-facing cross-origin access now requires an explicit `WithCORSOptions ... ` allowlist. - `contrib/config.LoadFromEnv` now treats invalid present bool and int values as startup errors instead of silently falling back to defaults. - Docs endpoints now return `404` when the HTML docs surface is disabled or when no authoritative OpenAPI document is available. - `DocsConfig.EnableJSON` and `DocsConfig.EnableYAML` now control which discovered OpenAPI formats may be served on the configured docs path. - Multi-source migrator loading now documents its actual contract: duplicate version direction pairs are rejected. - The pagination example now returns one field-level validation shape for invalid `limit` inputs even when `querylimits` rejects the request before the handler. Upgrade notes - If clients previously saw `409 Conflict` after a failed idempotent write retry behavior has changed: the same payload and `Idempotency-Key` can now be retried immediately after downstream `5xx` and panic paths but not after completed-response persistence failures or replay-buffer overflows. - If clients previously received the original success response even though completion persistence failed they now receive `503 Service Unavailable` and the key remains blocked in an ambiguous state until it expires or is reconciled. - If authenticated middleware previously ran after idempotency default caller scoping will not apply. Move auth and tenant middleware earlier in the stack to keep replay protection scoped per caller. - If a route can stream hijack upgrade or return large bodies exclude it with `ShouldHandle` or raise `MaxResponseBytes` otherwise oversized handled responses now fail closed with `503 Service Unavailable` and block same-key retries for the key lifetime. - If a scheduled job panic previously terminated the process that failure is now contained and surfaced through scheduler logging and run recording instead. - If application code called `scheduler.Runner.Start` more than once or reused the same job name across duplicate schedules those executions no longer overlap. Validate any workload that previously relied on concurrent execution of the same named job. - If browser clients previously relied on `ProfileStrictAPI` to emit `Access-Control-Allow-Origin: ` they must now set an explicit allowlist with `WithCORSOptions ... ` during bootstrap. - If deployment environments previously contained malformed bool or int values such as `MIGRATE_ON_START maybe` startup now fails fast instead of silently using defaults. Validate env files and secrets before rollout. - If deployment environments used undocumented semantic values such as `ENV qa` `ENV prod` `LOG_LEVEL verbose` or `LOG_LEVEL warning` startup now fails fast. Use `development staging production` for `ENV` and `debug info warn error` for `LOG_LEVEL`. - Docs handlers no longer return a synthetic OpenAPI document when no authoritative spec exists. Expect `404` for disabled docs surfaces and for missing OpenAPI files unless a real document is configured. - `DocsConfig.EnableJSON` and `DocsConfig.EnableYAML` now control which discovered OpenAPI formats can be served. Verify custom docs paths and any YAML-based docs setup during upgrade." + "text": "docs/release-notes.md Release Notes Audience: release consumers and maintainers who need dated behavior changes upgrade notes and package-tied compatibility acknowledgements. Current release guidance Need Current guidance Exact release commands and Release Notes Audience: release consumers and maintainers who need dated behavior changes upgrade notes and package-tied compatibility acknowledgements. Current release guidance Need Current guidance Exact release commands and supported `API_BASE_REF` Use `docs/release-runbook.md` do not maintain a second baseline table here. Concise user-facing summary by published version Use `CHANGELOG.md` update it with every release tag. User-visible behavior migration notes and compatibility acknowledgements Add dated entries in this file. Keep historical entries historical unless later guidance would otherwise mislead readers. Stable surface changes Update `VERSIONING.md` package docs compatibility docs release notes and docscheck coverage together. Supported-adapter or selected contrib drift Run the contrib drift and release-note review gates with the release baseline from the runbook. Root/contrib release identity Create matching root and `contrib/` tags at one commit then run `make release-tag-consistency-check` before release evidence. Generated service upgrade compatibility `make generated-upgrade-compat-check` defaults to `v3.0.0 v3.1.2` the script `docs/reference-service.md` and `docs/release-runbook.md` are the checked sources. Release Note Categories Every dated release entry should use one or more of these categories when the change is present: Category Use when the release includes Breaking Source-incompatible API module config generated-file or runtime contract changes. Behavior User-visible runtime behavior response shape validation persistence or default changes. Security Security fixes hardening bypass removal vulnerability disposition or sensitive default changes. Docs Documentation-only changes that affect adoption upgrade release or operations guidance. Dependencies Dependency upgrades removals replacements vulnerability-driven changes or imported-only risk dispositions. Generated scaffold Generator CLI behavior templates scaffold runtime assets generated Makefile targets or reference-service compatibility. Migration Upgrade steps compatibility notes deprecations replacement paths or required operator action. Release checklist For stable surface changes deprecations or compatibility-sensitive updates keep this file focused on user-visible behavior and upgrade notes. The command source of truth is `docs/release-runbook.md`. - Choose one or more release note categories from the taxonomy above before adding the dated entry do not bury breaking behavior security dependency generated scaffold or migration impact under generic prose. - Update `VERSIONING.md` public docs and package docs that describe the affected stability contract. - Update `scripts/apicheck.sh` and docscheck coverage when the stable package list or compatibility-sensitive manifest changes. - Update `docs/ports-surface.md` `docs/v3-compatibility-roadmap.md` release notes and upgrade notes when compatibility-sensitive ports or legacy stable surfaces change. - Add release notes and upgrade notes that describe user-visible behavior migration paths and compatibility impact. - Run release evidence through the runbook path `docs/release-runbook.md` owns the current supported `API_BASE_REF` baseline and exact commands while `make finalize` and `make audit-check` are local/reviewer gates. - Run `make contrib-api-drift-report` with the same release baseline when selected contrib adapters or integrations change exported APIs selected packages come from `docs/contrib-api-drift-packages.txt` supported-adapter incompatible drift is gate-enforced and this does not make contrib stable. - Run `make contrib-release-notes-check` with the same release baseline when supported contrib adapter integration middleware bootstrap telemetry production generator CLI behavior files or runtime assets change. - Supported-adapter contrib packages remain outside the stable core API promise but incompatible public API drift in that tier must be treated as gate-enforced and resolved with compatibility reclassification or a major-release policy decision. - If there is incompatible report-only contrib drift add an explicit release note or upgrade note acknowledgement tied to the affected package. This does not make contrib stable. - Update `docs/vulnerability-dispositions.tsv` when imported-only vulnerability IDs change expire or receive upgraded dependencies. - Update `docs/contrib-api-drift-dispositions.tsv` when current contrib drift packages or incompatible drift status changes. - Use clean publication evidence with the explicit baseline command from `docs/release-runbook.md` reserve `ALLOW_DIRTY_RELEASE_EVIDENCE 1` for local dirty-tree audit evidence that is not acceptable before publishing. First v3 major-release evidence may use `API_BASE_REF v2.1.0` only as documented v2-to-v3 transition evidence. - Use `docs/release-manifests.md` when interpreting `docs/package-classification.tsv` `docs/contrib-api-drift-dispositions.tsv` and `docs/vulnerability-dispositions.tsv`. 2026-08-22 Cross-platform core verification - Root-module verification builds tests examples and a generated `saas-api` service build now gate Linux amd64 Linux arm64 macOS arm64 and Windows amd64 pull requests on fixed GitHub-hosted runner labels. - Repository-owned text is normalized to LF on every checkout and generated service dependencies are resolved before the isolated build gate runs. - The generator now validates canonical slash-form manifest paths before converting them to host separators allowing nested templates on Windows without weakening rooted traversal protection. - Full contrib and race verification remain Linux amd64 gates. The support policy does not claim macOS amd64 or Windows arm64 without matching required workflow evidence. Stable required quality-gate identities - `docs/required-checks.json` now records every protected pull-request check its GitHub App binding workflow/job identity owner and PR/release role. - Workflow jobs have explicit displayed names and local documentation plus release gates fail when a job identity drifts from the manifest. - The authenticated governance audit compares branch protection with the exact manifest set and fails on missing stale unbound or wrong-App checks. - Release evidence now records required-check manifest verification and the blocking mutation gate as named results. Real Redis contract foundation - `make test-redis` now provides an isolated Redis 7 harness and real-service contracts for supported cache idempotency and rate-limit adapters plus the generated reference-service Redis paths. It covers TTL empty and oversized values atomic concurrency Lua release/token handling malformed state isolation cancellation dependency failure connection interruption and reconnect behavior. - The harness requires explicit test-only opt-in accepts only credential-free local/service endpoints on database 15 cleans only its random key prefix and sanitizes connection failures. CI and release tags run the same `redis-contract` miniredis remains fast unit evidence not equivalent release evidence. Real PostgreSQL contract foundation - `make test-postgres` now provides an isolated PostgreSQL 18 harness for contrib integration tests. It uses an explicit test-only loopback or CI service-container DSN creates a database and schema per test supports rollback migration cancellation and connection-loss checks and never reads application `DATABASE_URL` configuration. - The harness now directly validates supported PostgreSQL adapters migrations scheduler storage and generated reference-service persistence paths on every pull request `make supported-adapter-check` is the explicit verification alias. Internal response-writing behavior - Root-module internals now use checked response writers. Terminal paths stop after a failed write existing application-facing void writer APIs remain compatibility wrappers. Contrib and generated scaffolds will adopt these APIs with the next paired verified v4 root release so standalone builds retain a published dependency. Security and generated scaffold - `github.com/aatuh/api-toolkit/v4/binding.PublicError` and `binding.PublicError.PublicMessage` permit an application to opt a validation detail into a client response. Other validation errors now use the generic `validation failed` detail. - `github.com/aatuh/api-toolkit/v4/fielderrors.FieldError.Public` must be set for a field message to be eligible for client disclosure. - `github.com/aatuh/api-toolkit/v4/fielderrors.FieldErrors.AllPublic` requires every field message to be explicitly classified before a Provider s fields are added to a validation response. - Generated `saas-api` services log only a validation error s type at the default application logger they never log the raw rejected error string. Request binding behavior and future v5 migration - `github.com/aatuh/api-toolkit/v4/binding.RequiredMode` `binding.RequiredModeNonZero` and `binding.RequiredModePresent` let a handler choose non-zero or source-presence validation for `required: true ` fields. - `binding.JSONConfig.RequiredMode` `binding.QueryConfig.RequiredMode` and `binding.PathConfig.RequiredMode` preserve v4-compatible defaults unless a caller explicitly selects presence validation. `binding.PathConfig.HasParam` lets a router distinguish an absent path parameter from a present empty one. - A v5 major release is planned to make presence-aware validation the default. Applications that require a non-zero or non-null value should state that semantic rule separately before migrating. Health manager construction and v5 migration - `github.com/aatuh/api-toolkit/v4/endpoints/health.DefaultConfig` `health.Config.Clock` and `health.Config.Validate` provide an explicit testable startup-time configuration baseline for health managers. - `health.NewManager` returns a concrete manager and fails invalid timeout cache and probe configuration. `health.Manager.RegisterCheckerChecked` rejects nil empty-name and duplicate checkers instead of replacing a configured probe silently. - `health.NewManagerWithConfig` and `health.NewWithConfig` remain v4 compatibility wrappers. Migrate startup wiring to `NewManager` and checked registration before v5 removes the inconsistent unchecked constructors. Rate-limit decisions and bounded cleanup - `github.com/aatuh/api-toolkit/v4/middleware/ratelimit.DecisionLimiter` and `ratelimit.DecisionLimiter.Allow` let a shared rate-limit adapter return a complete `ratelimit.Decision` including `ratelimit.Decision.Limit` `ratelimit.Decision.Remaining` and `ratelimit.Decision.Reset` for standard response headers on both allowed and denied requests. - `ratelimit.Options.DecisionLimiter` cannot be combined with the existing `ratelimit.Limiter` the latter remains a v4-compatible adapter for allow/deny and retry-after decisions. - In-memory state expiry now uses a bounded expiry heap and removes at most 64 expired buckets per request. It starts no background goroutine. Blank key results share an anonymous bucket rather than bypassing rate limiting dangerous skip headers remain opt-in and restricted to trusted proxies. Timeout routing and hard-response limits - `github.com/aatuh/api-toolkit/v4/middleware/timeout.RouteCapabilities` `timeout.RouteCapabilities.Streaming` `timeout.RouteCapabilities.ServerSentEvents` `timeout.RouteCapabilities.WebSocketUpgrade` `timeout.RouteCapabilities.LargeDownload` `timeout.RouteCapabilities.Flusher` `timeout.RouteCapabilities.Hijacker` `timeout.RouteCapabilities.Pusher` and `timeout.RouteCapabilities.ReaderFrom` declare response behavior that hard-timeout buffering cannot preserve. - `timeout.RouteCapabilities.ValidateHardTimeout` and `timeout.HardTimeout.WrapRoute` reject unsafe route declarations before a hard timeout is applied. Generated bootstrap profiles and examples use cooperative `NewPropagator` middleware globally finite JSON routes opt in to hard response timeouts explicitly. - `timeout.HardTimeout.Middleware` and `securityprofile.WithHardTimeout` are deprecated v4 compatibility paths. `timeout.HardTimeoutEventHooks.OnHandlerContinuesAfterTimeout` provides a bounded low-level signal when a timeout response wins while the handler continues to run. 2026-08-15 HTTP response writer behavior - `github.com/aatuh/api-toolkit/v4/httpx` adds `httpx.WriteJSONChecked` and `httpx.WriteProblemChecked`. Their typed errors are `httpx.ResponseWriteError` `httpx.ResponseWriteError.Err` `httpx.ResponseWriteError.Error` `httpx.ResponseWriteError.Stage` `httpx.ResponseWriteError.Unwrap` `httpx.ResponseWriteStage` `httpx.ResponseWriteStageEncode` `httpx.ResponseWriteStageHeader` and `httpx.ResponseWriteStageBody`. Existing `httpx.WriteJSON` and `httpx.WriteProblem` remain compatibility wrappers callers that need write failures should use the checked APIs. Release integrity and migration - The v4 release-identity review verifies root `v4.0.1` as the sole root-module baseline. Use `API_BASE_REF v4.0.1` for v4 root release checks. - `v4.0.0` `contrib/v4.0.0` and `contrib/v4.0.1` are withdrawn. Contrib consumers must wait for a new paired repair release do not substitute the root tag for the withdrawn contrib module. Security and migration - `contrib/adapters/chi.Middleware.RealIP` now ignores untrusted forwarding headers and leaves `http.Request.RemoteAddr` intact. This removes the spoofable `middleware.RealIP` behavior identified by the updated chi dependency. - Reverse-proxy deployments must obtain the resolved client address through `middleware.GetClientIP r.Context ` and apply `chi.ClientIPFromXFF trustedCIDRs... `. The helper trusts only the configured proxy CIDRs and never mutates `RemoteAddr`. 2026-07-11 V4 migration release - Published the v4 root and contrib module paths with the mechanical import replacements documented in [migration/v4.md] migration/v4.md . - Reduced root `ports` to generic logger clock and identifier contracts endpoint middleware authorization HTTP and platform contracts now have package-local or contrib-owned v4 destinations. - Moved JWT/JWK middleware shared auth internals OAuth2 helpers and auth test support into contrib. Root v4 has no direct JWT/JWK requirements issuer audience algorithm JWKS and trusted-proxy bypass validation behavior is unchanged. - Added workspace root/contrib module generated-scaffold reference-service root-port ledger API transition dependency coverage race fuzz lint vulnerability and `gosec` release evidence. Migration - Added package-local endpoint aliases for `health.Checker` `health.ManagerContract` `health.DetailedManager` `health.CachedManager` `health.RouteRegistrar` `docs.Provider` `docs.ManagerContract` `docs.HTMLModeProvider` and `docs.RouteRegistrar`. They preserve exact v3 source compatibility with their root `ports` counterparts while giving new health and documentation integrations a consuming-package import path. - Added package-local idempotency store aliases: `idempotency.Store` `idempotency.ReservationReleaser` and `idempotency.ReleasableStore`. New integrations can adopt them after updating to a root version that contains these aliases they retain exact v3 source compatibility with the root contracts. - Added package-local authorization aliases: `authorization.Authorizer` `authorization.AuthorizerFunc` `authorization.PolicyEngine` `authorization.PolicyRequest` and `authorization.PolicyDecision`. They do not change default-deny owner tenant or policy-engine behavior and remain source-compatible with the v3 root contracts. - Deprecated the broad root `ports` contracts that now have package-local aliases: rate limiting idempotency stores authorization and policy health endpoint interfaces and docs endpoint interfaces. They remain available throughout v3 `docs/deprecations.md` records each replacement and the v4 removal horizon. - Published an accountable v4 scope ledger in `docs/v4-plan.md`. Each keep narrow split and removal decision now names an owner replacement direction and migration evidence required before a v4 API change. - Assessed provider extension-module candidates using ownership dependency contract realism and drift evidence. No family is approved for extraction without independent adoption or family-specific release-cadence evidence. - Clarified that CLI and scaffold behavior releases through contrib tooling ownership and release-note review never through the root stable API promise. - Published an AST-verified root-port migration ledger with all current exports consumers implementation evidence deprecation state and v4 dispositions. v3 cleanup branch Security and dependencies - Updated contrib `github.com/jackc/pgx/v5` from `v5.9.0` to `v5.9.2` and `github.com/yuin/goldmark` from `v1.7.16` to `v1.7.17` to remove the called `govulncheck` findings `GO-2026-5004` and `GO-2026-5320`. The update does not change api-toolkit s public API `adapters/pgxpool` remains a supported contrib adapter and `email/markdown` remains experimental. Breaking cleanup - The module paths are now `github.com/aatuh/api-toolkit/v4` and `github.com/aatuh/api-toolkit/contrib/v4`. - Provider-shaped billing exports were removed from root `ports` use `github.com/aatuh/api-toolkit/v4/compat/billing` for the hosted-checkout compatibility model or define app-owned billing ports. - `ports.DatabasePool.Stat` `ports.DatabaseStats` `ports.SnapshotDatabaseStats` and the public `response_writer` package were removed. Use `ports.DatabasePoolSnapshotProvider` `ports.SnapshotDatabasePoolStats` adapter `StatSnapshot ` methods and `httpx`. - Idempotency middleware now requires token-aware release through `ports.IdempotencyReservationReleaser`. - `authz.NewRequireRoleMiddleware` now validates at construction time and returns ` RequireRoleMiddleware error `. - List endpoint helpers keep the checked parser APIs: `ParseListQueryChecked` `DefaultFilterParserChecked` and `DefaultSortParserChecked`. 2026-06-07 Migration - Added `middleware/ratelimit.Limiter` as a package-local v3 migration shim over `ports.RateLimiter`. Existing `ports.RateLimiter` users remain source-compatible while new rate-limit adapters can move imports toward the consuming middleware package before v4 shrinks broad root ports. - Updated `docs/deprecations.md` so the active register covers the existing source-deprecated `middleware/timeout.New` and `middleware/trace.Use` shims with replacements removal horizon snippets and release-note pointers. 2026-06-06 Test evidence and compatibility - Added experimental `github.com/aatuh/api-toolkit/v4/compatkit` downstream compatibility test support. Services can run readiness version Problem Details OpenAPI compatibility and custom HTTP checks against an in-process handler or explicit base URL without promoting the package to the stable API surface. 2026-05-21 Release baseline maintenance - Published `v3.1.2` from the current `master` release tag evidence and advanced the v3 patch/minor release baseline examples to `v3.1.2`. - Added the paired `contrib/v3.1.2` module tag because the contrib module changed in the release. - `make generated-upgrade-compat-check` now defaults to the published baseline matrix `v3.0.0 v3.1.2` `GENERATOR_REF` remains as the single-ref compatibility alias. 2026-05-20 Test evidence and coverage reporting - Added focused behavior tests for `endpoints/docs` `httpx/identity` `httpx/recover` `middleware/json` `middleware/maxbody` `middleware/querylimits` and `securityprofile` then added package-specific coverage floors for those stable HTTP/security surfaces. - Added direct response-recorder behavior tests for `contrib/middleware/metrics` `contrib/middleware/oteltrace` and `contrib/middleware/requestlog` including informational statuses committed-state behavior optional response-writer interface forwarding and unsupported interface fallbacks. Coverage floors now protect those observability middleware packages. - Replaced direct sleep-based assertions in timeout security-profile outbound HTTP retry and transaction cleanup tests with context deadlines or channel synchronization so the same behavior is checked with less timing risk. - Hardened the hard-timeout capture path so handler writes are rejected as soon as the request deadline channel is closed then added `make timeout-determinism-check` for repeated normal and race evidence around late-write rejection. - Added `docs/supported-adapter-test-realism.tsv` and docscheck coverage so every supported adapter declares default PR evidence scheduled/manual evidence and whether that evidence is direct-unit fake DB miniredis hermetic fixture or real-service-backed. - `make coverage-check` now writes `.ci-result/coverage/summary.md` so CI can append root/contrib coverage totals to the GitHub job summary without making aggregate coverage the test-quality score. - Added `make reference-service-coverage` as non-Docker generated-service coverage evidence. It writes `.ci-result/coverage/reference-service.func` and `.ci-result/coverage/reference-service-summary.md` separately from toolkit root/contrib coverage thresholds. - Docscheck now keeps the checked-in reference service package test inventory explicit including package-level rationales for generated or entrypoint packages that intentionally do not carry direct tests. End-game hardening - `make generated-upgrade-compat-check` now accepts `GENERATED_UPGRADE_COMPAT_REFS` and defaults to checking both `v3.0.0` and `v3.1.2` `GENERATOR_REF` remains as a source-compatible single-ref alias. - Generated upgrade compatibility evidence now writes one log per generator ref plus `.ci-result/generated-upgrade-compat/status.tsv`. - Full-profile resource generation tests now prove the generated `project` replacement path with required/default/enum fields filters deterministic sorts OpenAPI/client checks contract checks and `resource-check` evidence. - Full-profile docs and generated READMEs now state that sample `widgets` are app-owned starter domain code meant to be replaced or complemented by product resources. - Added `make reference-service-evidence` which records non-blocking reference-service proof under `.ci-result/reference-service/` with optional `REFERENCE_SERVICE_DOCKER 1` and `REFERENCE_SERVICE_MINIO 1` runtime evidence. - Added a reference-service adoption evidence template for setup time upgrade results OpenAPI/client checks tenant isolation idempotency backup/restore load-smoke notes and known pain points. Release proof and reference service - Removed the temporary `.next_steps.md` release checklist after publishing `v3.1.0` future release baseline guidance now lives in the release runbook. - Added `examples/reference-saas-api` as a checked-in `saas-api-full` adoption proof service with local workspace replacements typed client output OpenAPI/contract assets Docker integration assets deployment starters and observability assets. - Added `make reference-service-check` as optional non-Docker evidence for the checked-in reference service. It stays outside default `finalize`. - Generated `saas-api-full` `.gitignore` files no longer ignore `internal/client/apiclient` so the checked-in typed Go client can be tracked by generated services. Contrib validation adapter - `contrib/adapters/validation` now uses `github.com/aatuh/validate/v3@v3.0.7` instead of `github.com/go-playground/validator/v10`. - Validation tags in toolkit examples now use the validate v3 grammar such as `validate: string required email ` and `validate: int min 1 `. - Field errors now preserve validate v3 JSON field paths and stable error codes while continuing to avoid raw submitted values in error strings. The deprecated `ValidationError.Value` field is retained for source compatibility but is no longer populated by the adapter. - `NewPlaygroundValidator` remains as a deprecated source-compatible alias but it no longer constructs a go-playground-backed validator. Use `NewValidateValidator` for new code. 2026-05-19 Maturity evidence - Added `make generated-upgrade-compat-check` an opt-in generated-service upgrade compatibility signal that generates `saas-api-full` from the prior v3 baseline replaces toolkit dependencies with the workspace and runs generated tests OpenAPI client and contract checks. This stays outside `finalize`. - Raised the JWT middleware package coverage floor after adding behavior tests for valid subject propagation skip-header enforcement nil/disabled handler behavior safe close behavior and JWKS health checks. - Raised the health endpoints package coverage floor after adding behavior tests for public liveness/readiness separation dependency state transitions timeout mapping public detail redaction admin-only detailed health access dependency checker options and scheduler callbacks. - Raised the OpenAPI validation middleware coverage floor after adding behavior tests for option constructors OpenAPI file loading route failure Problem Details request validation field mapping response validation error hooks streaming opt-outs large-response bypasses and response buffering limits. - Raised webhook delivery and Postgres webhook delivery adapter coverage floors after adding behavior tests for signing endpoint policy retry classification safe error surfaces tenant mismatch rejection replay safety attempt recording secret resolution and readiness health. - Raised the pgxpool adapter coverage floor after adding behavior tests for constructor validation bounded startup contexts database readiness mapping plain-value snapshots legacy stats wrappers acquire failures and close idempotence. - Added a docscheck gate that every `supported-adapter` contrib package has direct tests package docs a behavior-contract row and release drift coverage before it can retain the supported-adapter classification. - Added a manifest-driven adapter maturity review to the production-readiness docs so supported adapters are visible as evidence-complete and experimental packages are clearly not promoted. - Updated the release workflow provenance attestation action from the older `actions/attest-build-provenance` generation to a pinned v4.1.0 commit while preserving release artifact verification semantics. - Updated generated lean and full scaffold GitHub Actions templates to pinned `actions/checkout` v6.0.2 and `actions/setup-go` v6.4.0 commits. - Added `make actions-audit` and contract coverage for pinned GitHub Actions workflow refs stale action comments and generated workflow template versions it runs in `make audit-check` and remains non-mutating. - Tightened README and production-readiness positioning so api-toolkit is explicitly scoped to conventional HTTP/JSON API infrastructure not a universal backend platform and generated code is app-owned. - Aligned the release runbook with end-game proof targets by making `actions-audit` `coverage-check` generated upgrade compatibility generated integration and reference-service evidence visible to release reviewers while keeping Docker-backed checks opt-in. - Tightened the optional GitHub governance verifier so release tag protection covers both root `v ` tags and contrib module `contrib/v ` tags. - Removed the local root-module `replace` directive from `contrib/go.mod` so the contrib CLI can be installed with `go run github.com/aatuh/api-toolkit/contrib/v4/cmd/api-toolkit@vX.Y.Z`. - Added `docs/coverage-hardening-backlog.md` to make the next JWT health pgxpool OpenAPI middleware and webhook delivery coverage floor increases conditional on behavior-test evidence rather than numeric threshold churn. - Raised maturity evidence for high-risk v3 surfaces with additional JWT OpenAPI validation and bootstrap tests. The package coverage gate now keeps the OpenAPI validation middleware and bootstrap floors aligned with the new observed coverage. - Promoted production-relevant contrib packages to `supported-adapter` after direct tests package docs behavior-contract rows and drift coverage were confirmed: `contrib/adapters/httpclient` `contrib/adapters/envvar` `contrib/config` `contrib/adapters/validation` `contrib/adapters/migrate` `contrib/migrator` and `contrib/scheduler/postgres`. - OPA and Cedar policy adapters now use a shared policy-engine contract for provider-neutral request mapping allow/deny decisions malformed input failures and safe error surfaces and are promoted to `supported-adapter`. Upgrade notes - Contrib packages promoted to `supported-adapter` remain outside the stable root SemVer promise. Incompatible supported-adapter drift is now release-gated and must be release-noted. 2026-05-02 Correctness security and release governance - `docs/full-service-scaffold.md` now defines the planned `saas-api-full` production profile contract including Postgres Redis defaults tenant resources durable async/outbox behavior audit events webhook delivery OpenAPI 3.1 typed Go client output opt-in Docker integration checks and base Kubernetes assets. - `scripts/contrib_release_notes_check.sh` and its contract tests now require release-note coverage for future `saas-api-full` full-profile runtime assets under `contrib/cmd/api-toolkit` including generated Kubernetes YAML and other scaffold templates. - `api-toolkit new service` now supports an initial `--profile saas-api-full` scaffold with API-key auth hexagonal `internal/domain` `internal/app` `internal/adapters/postgres` and `internal/httpapi` boundaries Postgres migrations for tenant/platform tables Docker Compose Postgres/Redis assets with optional MinIO Kubernetes starter manifests OpenAPI golden checks contract lint/diff/client-check targets checked-in Go client output and generated HTTP smoke tests for readiness OpenAPI auth failure validation failure idempotent create replay and ETag conflicts. - `api-toolkit new service --profile saas-api-full` now accepts repeatable `--with stripe-billing resend-email clerk-webhooks` flags. Selected provider workflows generate app-owned `internal/providers` starter packages provider docs env examples manifest entries fake-provider tests tenant-scoped audit behavior and webhook/signature verification boundaries without adding provider-specific imports to the toolkit root module. - The async audit cache objectstore webhookdelivery OIDC middleware OIDC integration and their Postgres/Redis/S3 adapters now have supported-adapter classification package contract rows drift-gate coverage and release-note requirements. Postgres audit operation outbox and webhook delivery stores also expose readiness health checkers and `contrib/async/asynctest` adds a reusable async store contract suite for adapter implementations. - `api-toolkit --help` `api-toolkit -h` `api-toolkit help` and equivalent subcommand help forms now return usage with exit code `0` unknown commands continue to exit `2`. - `api-toolkit clients typescript --style fetch` now generates a browser/stdlib `fetch` TypeScript package for the same supported OpenAPI subset as the typed Go client: JSON bodies path/query/header params API-key and bearer auth Problem Details errors nullable fields enums and raw response access. `api-toolkit new service --profile saas-api-full --client typescript` adds the checked-in TypeScript client package and `client-ts-check` target while keeping the existing generated Go client path source-compatible. Generated TypeScript configs include DOM iterable fetch types and `client-ts-check` runs a local TypeScript build when `node_modules` is already present. - `api-toolkit ops observability --profile saas-api-full` now emits a bounded label Grafana/Prometheus/runbook bundle for the full scaffold and `api-toolkit deploy helm` plus `api-toolkit deploy terraform --cloud aws` generate deployment starters for API worker migration admin service dependency references and AWS Postgres/Redis/S3 primitives. Generated full services now include `cmd/assetcheck` plus `make observability-check` `make deploy-check` and `make asset-check` so those starter assets are validated offline without Helm Terraform jq or network access. Release evidence now records those generated asset checks in `full_profile_scaffold_evidence.asset_validation`. - Generated `saas-api-full` migrator commands now include `plan` `verify` and a guarded `down` command. Down migrations require both `--allow-dangerous-down` and `ALLOW_DANGEROUS_MIGRATION_DOWN true` and remain documented as local/schema-teardown only. When both guards are present the generated command now delegates to `bootstrap.RunDown` and reverts one latest applied migration through the contrib migrator. - `api-toolkit generate resource` now accepts the v2 field and route-shaping flags `--field` `--filter` `--sort` `--admin` `--relationship` and `--object-field` validating the field DSL before mutating generated projects. Generated resources now wire exact-match list filters and allow-listed deterministic sorts through HTTP query parsing application services parameterized Postgres queries OpenAPI parameters generated typed clients and partial Postgres indexes. Relationship flags add ` name _id` fields and object-backed fields must end in `_key` and expose only object keys not payloads. `--admin` now mounts a generated admin-list endpoint under `/admin/ plural ` on the admin router only protected by `X-Admin-Key` and an explicit tenant selector. - Provider workflow scaffolds now include `cmd/provider-replay` and generated provider-check runs package tests plus deterministic replay validation for checked-in Stripe Resend and Clerk fake fixtures. Live provider checks remain gated by `RUN_PROVIDER_LIVE_CHECKS true`. - `api-toolkit contracts changelog` and `api-toolkit contracts impact` now report OpenAPI operation additions/removals and machine-readable breaking client impact for release review. Contract lint and impact checks now also cover OpenAPI 3.1 composition review metadata streaming and binary response metadata callback/webhook metadata schema default changes enum widening and narrowing and oneOf/anyOf/allOf composition changes. - `api-toolkit new service --profile saas-web --auth session oidc-session` now emits a separate browser/session starter so API-first profiles stay unchanged. The generated profile includes cookie security defaults memory and Redis session-store boundaries guarded production startup validation CSRF middleware OIDC callback state validation browser-safe CORS and session fixation tests without adding session dependencies to the root module. - `api-toolkit new service --profile saas-api-full --with entitlements` now emits provider-neutral generated app code for plans features quotas usage counters OpenAPI entitlement routes Postgres `tenant_entitlements` and `billing_mappings` persistence and billing-provider composition guidance. The workflow composes with `--with stripe-billing` by updating app-owned billing mappings before entitlement changes without adding Stripe-shaped ports to core. - `github.com/aatuh/api-toolkit/contrib/v4/entitlements` now provides provider-neutral feature and quota contracts low-cardinality decisions reusable store contract tests and HTTP enforcement middleware that avoids exposing tenant or billing identifiers in Problem Details responses. - Release evidence now expands `full_profile_scaffold_evidence` with explicit fields for OpenAPI 3.1 full scaffold output typed client generation resource generator checks provider-flag generation worker wiring generated integration workflow assets and opt-in Docker integration status. The focused `full-profile-scaffold-check` target now covers provider workflow generation and resource generation in addition to the full scaffold auth modes. - Generated `saas-api-full` services now include tenant domain and application services for organizations memberships invitations role checks and invitation acceptance. The generated service hashes invitation tokens before storage returns the raw invitation token only from the create-invitation use case and includes generated unit tests for owner membership role failures wrong-token failures and single-use invitation acceptance. - Generated `saas-api-full` HTTP routers now expose organization create/list member list invitation create and invitation accept routes with OpenAPI contracts generated Go client methods idempotency metadata tenant policy metadata and generated HTTP tests for role failures and token replay. - Generated `saas-api-full` services now include API-key lifecycle management for organization-scoped create/list/revoke scoped permissions one-time raw secret return non-secret key prefixes peppered SHA-256 hash storage last-used tracking on verification and generated OpenAPI/client coverage. - `api-toolkit new service --profile saas-api-full --auth jwt clerk oidc` now emits matching bearer-auth runtime wiring generated auth tests tenant claim checks scope checks and BearerAuth OpenAPI security instead of falling back to API-key-shaped full-profile router code. - Generated `saas-api-full` services now include an async widget import workflow using `202 Accepted` `Location`/`Retry-After` tenant-scoped operation polling at `GET /operations/ id ` replay-safe idempotency a generated worker service over the contrib async store/handler contracts and OpenAPI/client coverage for `createWidgetImport` and `getOperation`. - Generated `saas-api-full` services now wire optional Postgres runtime startup checks: when `DATABASE_URL` is set generated code opens a pgx pool pings it verifies required platform tables closes the pool on shutdown and reflects database failures through public readiness and admin detailed health. - Generated `saas-api-full` services now use `bootstrap.NewAPIService` as the composition root for public/admin listeners strict SaaS middleware order validation safe system endpoint mounting graceful shutdown and async worker lifecycle. The full profile now exposes `/livez` separately from `/readyz` keeps liveness process-only moves detailed health/metrics/pprof to the admin listener when `ADMIN_ADDR` is set and enables runtime OpenAPI request validation by default with response validation enabled in development/test or by `OPENAPI_RESPONSE_VALIDATION true`. - Generated `saas-api-full` services now include an in-process audit recorder and write-route hooks for organization invitation API-key widget and async import actions with generated tests proving audit metadata redaction and no raw API-key secret leakage. - Generated `saas-api-full` services now include outbound webhook event catalog endpoint create/list delivery list and delivery replay routes widget writes enqueue tenant-scoped pending deliveries for subscribed endpoints generated OpenAPI/client output covers those operations and tests prove webhook signing secrets are returned only at endpoint creation. - Generated `saas-api-full` OpenAPI documents now opt into OpenAPI 3.1 through `specs.NewRegistryWithOptions ... OpenAPIVersion31 ` while the lean `saas-api` scaffold keeps the existing OpenAPI 3.0 default. - Generated `saas-api-full` services now include a generated cache service in-memory local cache store Redis cache adapter `CACHE_STORE` configuration cache readiness composition and cached webhook event catalog responses with generated tests for TTL cloning Redis address validation and cache hits. - Generated `saas-api-full` services now include tenant-scoped object storage routes and application services with strict key content-type and size validation OpenAPI/client coverage audit hooks and tests proving object payloads are not exposed in list/create responses or validation problems. - Release evidence now records `full_profile_scaffold_evidence` and `make release-check` includes a focused `make full-profile-scaffold-check` target so the generated `saas-api-full` service OpenAPI/contract workflow and generated Go client are explicit release signals. Generated Docker integration checks remain opt-in and are reported separately through the non-blocking integration evidence status. - Generated `saas-api-full` `integration-check` now uses a dedicated script that starts Postgres and Redis applies the generated migration runs generated unit tests starts the API on localhost and performs HTTP smoke checks for readiness OpenAPI authentication failure tenant membership managed API-key authentication idempotent widget writes ETag conflict handling async operation polling outbox completion/retry behavior webhook delivery/replay object write/readback audit writes admin detailed health admin metrics admin pprof and public admin-route isolation before tearing Docker volumes down. Set `INTEGRATION_OBJECT_STORE s3` to have the script start the optional MinIO profile initialize the generated `api-objects` bucket and run the same object checks through the S3-compatible adapter. Fresh generated checkouts now materialize `.env` from `.env.example` before invoking Docker Compose and the generated Postgres volume mount uses the PostgreSQL 18-compatible `/var/lib/postgresql` parent directory. Generated full-profile Makefile Dockerfile and integration checks now hydrate module sums with `go mod tidy` before build or test commands and generated `go.mod` files use the installed toolkit release version instead of pinning the stale v2.1.0 baseline when the CLI is installed from a SemVer tag. The generated integration script now feeds SQL through stdin so psql variables are expanded isolates generated auth tests from integration actor environment variables uses current-compatible MinIO `mc mb --ignore-existing` flags and tears down Compose with the objectstore profile enabled so optional MinIO resources do not remain running after S3 checks. - Postgres audit and outbox adapters now exercise real-SQL failure paths more closely: audit SQL no longer includes Go comment text and outbox retry scheduling casts the retry base timestamp before adding interval backoff. - Generated `saas-api-full` widget services now use an application storage port and the generated runtime switches to a Postgres widget store when `DATABASE_URL` is configured. The store persists widget create/update/delete state in the generated `widgets` table while preserving the local in-memory default for tests and lightweight development. - Generated `saas-api-full` API-key services now switch to a generated Postgres API-key store when `DATABASE_URL` is configured. The store persists only keyed hash bytes display prefixes scopes expiry revocation and last-used timestamps raw API-key secrets are still returned once and are not durable data. - Generated `saas-api-full` tenancy services now switch to a generated Postgres tenancy store when `DATABASE_URL` is configured. The store persists organizations owner memberships role checks invitation token hashes invitation acceptance and member listing while keeping raw invitation tokens return-once only. - Generated `saas-api-full` async widget imports now switch to generated Postgres operation/outbox wiring when `DATABASE_URL` is configured. The app service writes tenant-scoped pollable operation rows enqueues outbox work and the generated outbox store leases work through contrib async while keeping failure problems sanitized. - Generated `saas-api-full` Postgres runtimes now route the shared outbox through `contrib/async` s handler mux dispatching `widgets.import` to the widget importer and `webhook.delivery` to the outbound webhook deliverer. Webhook attempts are recorded through the generated app/Postgres store boundary with sanitized errors and low-cardinality delivery metrics. - Generated `saas-api-full` services now include a dedicated `cmd/worker` binary for background jobs an `ASYNC_WORKER_ENABLED` switch for API processes Docker Compose worker service wiring a Kubernetes worker Deployment and integration-check startup that exercises the worker separately from the public API process. - Generated `saas-api-full` integration checks now run a local webhook receiver prove successful outbound delivery and replay reach it verify failing webhook endpoints record retryable delivery state force a poison outbox row into `dead_letter` and check receiver/delivery output does not expose the generated signing secret. - Generated `saas-api-full` services now emit contrib migrator-compatible ` .up.sql` migrations plus a generated `cmd/migrate up status check` binary. Docker Compose runs a dedicated `/migrate -dir /migrations up` service before API/worker startup the integration script applies and checks migrations through `cmd/migrate` and the Docker image now includes `/migrate` plus `/migrations`. - Generated `saas-api-full` Kubernetes assets now include ConfigMap Secret placeholder migration Job worker Deployment internal-only admin Service PodDisruptionBudget HPA NetworkPolicy resource requests/limits non-root security contexts and `/livez`/`/readyz` probes. The generated integration workflow is opt-in through `workflow_dispatch` and scheduled runs instead of default PR CI. - Generated `saas-api-full` services now include an `api-toolkit.yaml` manifest and `resource-check` target and `api-toolkit generate resource` now supports manifest-gated tenant-scoped CRUD generation inside full-profile projects. The generator adds domain/app/Postgres/httpapi files a contrib-migrator ` .up.sql` migration route/OpenAPI contracts audit hooks webhook event hooks OpenAPI golden regeneration typed Go client regeneration and fails closed when expected generated anchors are missing. - Generated `saas-api-full` object routes now support `OBJECT_STORE s3` via a generated blob-store port and S3-compatible adapter wrapper. Tenant and role checks remain in the app service object bytes are written read and deleted through the contrib S3 adapter with bounded size and content-type policy. - Generated `saas-api-full` S3 object routes now use a generated Postgres object metadata store when `DATABASE_URL` is configured so tenant-scoped list/get/delete state survives process restarts while payload bytes remain in the object store. - Generated `saas-api-full` webhook routes now switch to a generated Postgres webhook store when `DATABASE_URL` is configured. Endpoint signing secrets are encrypted with `WEBHOOK_SECRET_KEY` delivery history is tenant-scoped and replay updates the delivery row while requeueing the matching outbox job. - Generated `saas-api-full` unsafe write routes now use the core idempotency middleware with tenant-aware hashed storage keys. Local scaffolds default to in-memory replay `IDEMPOTENCY_STORE redis` wires the generated Redis adapter for cross-instance replay state. - Generated `saas-api-full` protected routes now use the core rate-limit middleware. Local scaffolds default to in-process buckets production defaults require `RATE_LIMIT_STORE redis` and wire a generated Redis limiter with hashed actor/tenant/route keys. - Generated `saas-api-full` services now create a contrib Prometheus recorder wrap public `net/http` routes with HTTP metrics middleware and serve the standard Prometheus handler only behind admin authentication. Generated tests assert request metrics use route-pattern labels and do not expose tenants actors API keys admin keys or idempotency keys. - Generated `saas-api-full` admin routers now mount real Go pprof handlers via `pprof.RegisterAdminRoutes` instead of returning a placeholder response. Generated tests assert pprof is absent from the public handler and requires `X-Admin-Key` on the admin handler. - Generated `saas-api-full` API-key auth mode now verifies generated API keys through the generated API-key service when the static bootstrap `API_KEY` does not match. Managed keys enforce route scopes bind requests to their organization update last-used state fail after revocation and keep raw key secrets out of Problem Details. - Generated `saas-api-full` audit recording now delegates to the contrib Postgres audit store when `DATABASE_URL` is configured after the generated service has produced event IDs timestamps and redaction-safe metadata. Local development keeps the existing in-memory audit recorder. - `specs.NewRegistryWithOptions` now supports explicit OpenAPI 3.1 output via `specs.RegistryOptions OpenAPIVersion: specs.OpenAPIVersion31 ` while preserving the existing `specs.NewRegistry` OpenAPI 3.0 default. - `specs` now includes additive schema helpers for reusable refs nullable schemas examples enum values struct-tag examples/enums/nullable fields request/response media examples and reusable HTTP Problem Details response components. - `api-toolkit clients go` now generates a stdlib-only Go client package from OpenAPI operations including operation methods path/query/header request options JSON request bodies API-key and bearer auth helpers and Problem Details error decoding. - `api-toolkit clients go --style typed` now generates component schema structs typed request/response operation methods typed Problem Details error handling and raw method escape hatches while preserving the existing `raw` client style as the default. - `api-toolkit new service --profile saas-api-full` now checks in typed Go client output and its generated `client-check` target regenerates with `api-toolkit clients go --style typed`. - `api-toolkit contracts lint` `contracts diff` and `clients go --style typed` now normalize OpenAPI 3.1 schema `type` arrays containing `null` and schema-level `examples` before parser validation. Contract linting also rejects Go client method schema type and parameter identifier collisions that would make typed client output unstable or unbuildable. - `specs.Operation` now includes `OperationID` and emits OpenAPI `operationId` values so route contracts can carry stable client-visible operation identity. - `routepolicy` now includes typed metadata helpers for auth deprecation sunset tenant idempotency rate-limit admin-policy and Problem Details response contracts plus operation linting for missing production policy metadata. - `routepolicy` now exposes typed metadata readers for auth deprecation tenant idempotency rate-limit admin-policy and Problem Details response contracts. Contract linting now requires unsafe-write tenant and idempotency metadata to be explicitly marked `required: true` instead of accepting any extension value. - `routepolicy.LintOperations` and `api-toolkit contracts lint` now fail non-public operations without security metadata and unsafe write operations without tenant idempotency rate-limit and Problem Details policy metadata while allowing known public readiness liveness docs and version routes. - `api-toolkit contracts lint` now accepts repeatable `--public-path` and `--admin-path` flags so applications can extend the default public and operator-only path sets without weakening the built-in production checks. - `routepolicy` `contracttest` and `api-toolkit contracts lint` now enforce unique OpenAPI `operationId` values so generated clients and compatibility reviews can rely on stable operation identity. - `routepolicy.LintOperations` and `api-toolkit contracts lint` now require non-public operations including safe reads to document Problem Details error responses. - `routepolicy.LintOperations` and `api-toolkit contracts lint` now fail unsafe write operations that omit request body metadata for POST/PUT/PATCH or omit a documented 2xx success response. - `contracttest` now includes assertions for operation IDs Problem Details error responses tenant/idempotency/rate-limit/admin policy metadata registry-wide operation ID coverage and conservative OpenAPI compatibility findings. - `contracttest` now includes stricter generated-OpenAPI assertions for expected security scopes tenant policy source idempotency header named admin policy and sets of Problem Details response statuses. - `contracttest.OpenAPICompatibilityFindings` now reports tenant idempotency rate-limit admin-policy and deprecation/sunset route policy drift matching the stricter `api-toolkit contracts diff` behavior. - CI now runs `make docs-check` explicitly and runs `make contrib-release-notes-check` on pull requests against the fetched PR base ref keeping documentation and supported-contrib release-note governance visible before merge. - CI pull-request governance now also runs `make contrib-api-drift-report` against the fetched PR base ref so supported-adapter incompatible drift fails before merge without making contrib part of the stable core API promise. - `make contrib-release-notes-check` now reviews `github.com/aatuh/api-toolkit/contrib/v4/cmd/api-toolkit` behavior files in addition to supported adapters integrations middleware bootstrap and telemetry so scaffold and contract-tooling behavior changes require release-note coverage. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap` now exposes `APIService` and `APIServiceConfig` as a supported composition root for generated services with safe admin-wrapper system endpoint mounting and startup checks. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap.APIServiceConfig` now accepts `AdminAddr` and `AdminRouter` for a separate admin listener and `APIService.AdminHandler ` exposes the composed admin handler for tests and custom server wiring. - `github.com/aatuh/api-toolkit/contrib/v4/cache` and `github.com/aatuh/api-toolkit/contrib/v4/adapters/cacheredis` add supported contrib cache contracts and a Redis-backed cache adapter with TTL delete health-check and reusable adapter-contract coverage. - `github.com/aatuh/api-toolkit/contrib/v4/audit` and `github.com/aatuh/api-toolkit/contrib/v4/adapters/auditpostgres` add supported contrib audit-event contracts reusable recorder-contract tests and a transaction-aware Postgres audit recorder that stores actor type tenant action resource result request ID and redaction-checked metadata. The generated `saas-api-full` audit migration now includes `actor_type`. - `github.com/aatuh/api-toolkit/v4/operations` adds additive write-side repository contracts plus lifecycle helpers for validating operation states terminal states and pending/running/succeeded/failed/canceled transitions. - `github.com/aatuh/api-toolkit/contrib/v4/async` adds a supported contrib durable async worker runner with lease/complete/fail store contracts bounded concurrency graceful shutdown low-cardinality metric hooks and logs that avoid job payloads and raw handler errors. - `github.com/aatuh/api-toolkit/contrib/v4/async` now includes an fail-closed handler mux for routing leased jobs by sanitized low-cardinality kind allowing one durable queue or outbox to back multiple worker concerns without inspecting job payloads. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/operationpostgres` adds an supported Postgres-backed operation repository for pollable async operations including tenant-scoped context helpers JSON result/problem storage create/update support and fail-closed tenant validation. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/outboxpostgres` adds an supported Postgres transactional outbox adapter with enqueue due-event leasing using `FOR UPDATE SKIP LOCKED` lease-owner completion retry backoff dead-letter transition and `contrib/async.Store` compatibility. - `github.com/aatuh/api-toolkit/contrib/v4/objectstore` and `github.com/aatuh/api-toolkit/contrib/v4/adapters/objectstores3` add supported contrib object storage contracts reusable contract-test helpers and a raw HTTP S3-compatible adapter with SigV4 request signing presigned URL hooks content-type and object-size policy checks metadata secret-shape rejection not-found mapping and a bucket health checker. - `github.com/aatuh/api-toolkit/contrib/v4/webhookdelivery` adds supported contrib outbound webhook delivery contracts with a fail-closed event catalog tenant-scoped endpoint matching HMAC-signed HTTP delivery bounded retry backoff helpers replay commands sanitized attempt results and `contrib/async` worker integration that keeps endpoint signing secrets out of durable job payloads. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/webhookdeliverypostgres` adds a supported Postgres adapter for outbound webhook endpoint lookup delivery enqueue outbox job creation attempt recording and operator replay. Endpoint signing secrets are loaded through an application-owned `SecretResolver` instead of raw secret storage in the webhook endpoint table generated `saas-api-full` migrations now include `event_id` and `last_status_code` on webhook delivery rows. The adapter also accepts the shared `webhookdelivery.EndpointPolicy` so generated development and integration services can allow localhost HTTP webhook targets without weakening production HTTPS defaults. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` and `github.com/aatuh/api-toolkit/contrib/v4/middleware/requestlog` now expose outbound webhook delivery observation hooks with bounded event type outcome and status-class labels that omit tenants endpoint IDs delivery IDs URLs payloads secrets and raw error strings. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/auth/oidc` and `github.com/aatuh/api-toolkit/contrib/v4/integrations/auth/oidc` add supported provider-neutral OIDC/JWKS bearer-token middleware with optional discovery issuer/audience and algorithm validation tenant and scope claim mapping JWKS health checks env loading and generated `saas-api-full` `--auth oidc` wiring. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap.APIServiceConfig` now accepts named shutdown hooks so composed services can close auth telemetry or adapter background resources after the HTTP server stops. - `middleware/auth/tenant.Options.RequireAllSources` now lets services require every configured tenant source to be present and equal before a handler runs which supports authenticated-tenant-to-header mismatch checks. - `github.com/aatuh/api-toolkit/contrib/v4/cmd/api-toolkit` adds the developer CLI with `new service` `contracts lint` `contracts diff` and `version` commands. The generated `saas-api` service uses chi-backed bootstrap defaults code-first route contracts OpenAPI output public readiness admin-protected metrics/pprof/detailed health core API-key and tenant middleware and idempotent write behavior plus a checked-in OpenAPI golden workflow. - Generated `saas-api` services now fail startup under `ENV production` unless `API_KEY` and `ADMIN_KEY` are explicitly set so local fallback credentials cannot be deployed accidentally. - Generated `saas-api` services now include a `.dockerignore` and a hardened multi-stage Dockerfile that runs tests during build compiles a static binary and runs it from a non-root distroless runtime image instead of `go run` in a full Go toolchain image. - Generated `saas-api` services now include a `.gitignore` that excludes local `.env` files coverage output temporary directories test binaries and the built service binary while keeping `.env.example` tracked. - Generated `saas-api` Makefiles now include `contracts-lint` and `contracts-diff` targets backed by the api-toolkit CLI and generated `finalize` runs those contract checks alongside tests and OpenAPI golden verification. - Generated `saas-api` Makefiles now make `coverage-check` enforce `COVERAGE_MIN` instead of only writing a coverage profile so generated CI fails closed when test coverage drops below the configured floor. - Generated `saas-api` Makefiles now install `govulncheck` under `.tools/bin` by default and invoke it through the overridable `GOVULNCHECK` variable so scaffold checks do not require globally mutating the developer Go bin. - Generated `saas-api` services now keep memory idempotency storage as the local default but reject it under `ENV production` production defaults to the Redis idempotency adapter and requires `REDIS_ADDR` before startup. - `api-toolkit new service` now supports `--auth jwt` and `--auth clerk` for the `saas-api` profile. Generated bearer-token services validate tokens through JWKS require issuer and audience configuration extract tenant scope from validated token claims enforce route scopes close auth middleware through bootstrap shutdown hooks and keep generated contract tests and OpenAPI goldens aligned. Development-header and unknown modes still fail closed. - `api-toolkit new service` now supports the explicit `dev-api` profile with `--auth dev-headers`. The generated development service requires explicit dangerous-bypass environment settings separates debug user tenant and scope headers keeps tenant mismatch and idempotent write tests and refuses to start with dev-header auth when `ENV production`. - Generated services now wire `bootstrap.NewDefaultRouterWithConfig` to the contrib Prometheus recorder so protected `/metrics` exposes bounded HTTP request counters and histograms instead of only runtime collector output. - `contrib/middleware/auth/clerk.Subject` now exposes tenant and scope strings derived from validated JWT claims while preserving subject comparability so applications and generated services can enforce tenant and route-scope policy from Clerk tokens. - `middleware/idempotency.Options.OnOutcome` now emits bounded request-path idempotency outcome events and `OutcomeEvent.MetricLabels ` exposes only method store class outcome and status class for metrics. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now records bounded `idempotency_outcomes_total` Prometheus counters through `IdempotencyOutcomeHook` and `github.com/aatuh/api-toolkit/contrib/v4/middleware/requestlog` now provides `IdempotencyOutcomeLogHook` with the same low-cardinality outcome shape. Generated `saas-api` services wire both hooks by default. - `middleware/idempotency` now supports `Options.StorageKeyFunc` plus `TenantScopedStorageKeyFunc ` so multi-tenant services can hash client-supplied idempotency keys with tenant and actor scope before shared storage access. Generated `saas-api` services opt into the helper while preserving the original `Idempotency-Key` response header on replay. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now records bounded `health_status_changes_total` Prometheus counters through `HealthStatusChangeHook` using only `from` and `to` health-status labels for scheduler transitions. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now treats `net/http.ServeMux` request patterns as route labels when chi route context is unavailable preserving low-cardinality HTTP metrics for stdlib routers. - Routes registered through `routecontracts` now attach bounded `routepolicy` observability labels. Contrib metrics records them through `http_route_policy_requests_total` and contrib request logging emits `policy_ ` fields without raw scopes tenant sources rate-limit policy names or admin policy names. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now exposes `RoutePolicyLabels` so custom recorders can reuse the same bounded route-policy label normalization as the Prometheus recorder. - `middleware/idempotency.Options` now includes additive `RequireKey` support. Generated SaaS services enable it so unsafe writes without `Idempotency-Key` fail closed with Problem Details 400 instead of executing untracked. - Generated service READMEs and security guidance now document that unsafe writes without `Idempotency-Key` fail with Problem Details 400 and that generated idempotency storage keys are tenant and actor scoped. - Generated services now load bootstrap router env controls for `TRUSTED_PROXIES` and rate-limit skip headers failing startup on malformed proxy CIDRs or unsafe bypass settings. - Generated services now register a shutdown hook for Redis idempotency clients so production stores are closed through the `bootstrap.APIService` lifecycle. - Generated services now support `RATE_LIMIT_STORE redis` and default to Redis rate limiting in production including startup validation and Redis client shutdown hooks. - Generated scaffold documentation now describes the local memory and production Redis rate-limit store defaults. - Generated services now initialize contrib OpenTelemetry tracing from `OTEL_ ` environment variables fail startup when tracing is enabled without an OTLP endpoint and close the tracer provider during service shutdown. - Generated compose files now include a Redis service healthcheck persistent volume and container-safe Redis address overrides for idempotency and rate limiting. - `github.com/aatuh/api-toolkit/contrib/v4/telemetry.InitTracing` now returns an error when tracing is explicitly enabled without an OTLP endpoint instead of silently installing a noop exporter. - `api-toolkit version` now prints Go runtime main module core module contrib module build commit and build date metadata for release evidence. - `api-toolkit version --json` now emits the same installed tool metadata in a stable machine-readable shape for release evidence and automation. - Generated services now stamp `/version` from `appVersion` `buildCommit` and `buildDate` and the generated Makefile/Dockerfile pass those fields through build flags with local `dev`/`unknown` defaults. - `make v3-readiness-check` now runs focused compatibility-sensitive cleanup guardrails and is included in `make release-check` and release evidence logs keeping major-version removal planning tied to roadmap replacement guidance and release-note requirements. - CI governance now runs `make v3-readiness-check` explicitly alongside docs-check and contrib release-note/drift gates. - `api-toolkit new service` now emits a pinned GitHub Actions workflow that runs `make finalize` keeping generated services on the same test build OpenAPI golden and contract lint path documented by the scaffold. - The getting-started guide is now scaffold-first and verifies the generated service OpenAPI golden and contract lint/diff workflow instead of teaching a hand-written minimal starter as the primary path. - Generated service Makefiles now include `fast-check` `audit-check` `coverage-check` `test-race` `vuln` and `clean` targets so scaffold CI runs race tests and govulncheck in addition to build and contract checks. - Generated service Makefiles now include optional `sbom-local` output through Syft writing SPDX JSON to `.ci-result/sbom/sbom.spdx.json` without adding Syft to the default finalize path. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap.APIServiceConfig` now supports named `BackgroundTasks` that run with the service context fail the service on unexpected task errors and stop during graceful shutdown. Generated `saas-api` services use this to run health refreshes with bounded health-status metrics. - `make release-check` now runs `contrib-api-drift-report` as a first-class release-readiness subcheck and release evidence reuses that log for the structured contrib drift summary instead of leaving supported-adapter API drift only in the evidence-only path. - `api-toolkit contracts diff` now performs compatibility review over parsed OpenAPI operations. Additive operations pass while removed operations changed operation IDs removed documented parameters added required parameters removed documented responses request-body tightening or content removal response content removal and changed security requirements fail with deterministic findings. - `api-toolkit contracts diff` now also fails closed when existing operations drift in tenant idempotency rate-limit admin-policy or deprecation/sunset route policy metadata. - `api-toolkit contracts diff` and `contracttest.OpenAPICompatibilityFindings` now also flag removed or changed `components.securitySchemes` so auth header bearer OAuth or OIDC contract drift is caught even when operation-level security requirements keep the same scheme name. - `api-toolkit contracts lint` `api-toolkit contracts diff` and `contracttest.OpenAPICompatibilityFindings` now honor top-level OpenAPI `security` as inherited operation security and report `global_security_changed` when release-review specs change that default. - `api-toolkit contracts lint` now emits a stable `GLOBAL` `security_scheme_undefined` finding when top-level OpenAPI security references a scheme missing from `components.securitySchemes`. - `specs.Registry` now exposes `SetSecurity` for code-first top-level OpenAPI `security` and `contracttest.SecuritySchemeDefinitionFindings` verifies those global requirements against `components.securitySchemes`. - Generated `api-toolkit new service` scaffolds now use `specs.Registry` top-level OpenAPI security defaults in runtime docs and golden files while keeping protected write operation scopes explicit. - Generated service READMEs now list admin-protected detailed health and pprof routes and scaffold tests assert detailed health metrics and pprof all require `X-Admin-Key`. - `api-toolkit contracts diff` now also reviews OpenAPI component schemas and reports removed schemas added required properties removed object properties type/ref changes and enum value removals as compatibility findings. - `api-toolkit contracts diff` now applies those conservative schema compatibility checks to inline request and response media schemas on existing operations so handler-local contract narrowing is caught before release. - `api-toolkit contracts lint` now fails when an operation references a security requirement that is not defined in `components.securitySchemes` preventing reviewed specs from declaring unenforceable auth. - `contracttest` now exposes `SecuritySchemeDefinitionFindings` and `AssertSecuritySchemesDefined` so service tests can catch the same undefined OpenAPI security-scheme references as CLI contract linting. - `contracttest.OpenAPICompatibilityFindings` now reports the same conservative OpenAPI component and inline request/response schema drift findings so library tests and CLI release review stay aligned. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap` now exposes middleware stage identifiers strict/dev middleware order helpers and startup validation for custom APIService middleware order declarations. - `github.com/aatuh/api-toolkit/contrib/v4/bootstrap` now exposes `StrictSaaSAPIMiddlewareOrder` for services that require the full production policy sequence of auth tenant and idempotency after the transport middleware stack and generated `saas-api` services declare that order during startup validation. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now canonicalizes Prometheus HTTP metric labels so methods stay within standard HTTP verbs plus `OTHER`/`UNKNOWN` invalid statuses collapse to `0` and route labels are trimmed before series creation. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/openapi` response validation now accepts `ResponseValidationOptions.ShouldValidate` so services can skip response buffering for streaming upgrade or large-download routes while keeping request validation enabled. - `middleware/timeout.NewHard` now accepts `Options.EventHooks` emitting bounded operator metadata for timeout panic and response-capture overflow outcomes without exposing panic values paths query strings headers or bodies. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now exposes `HardTimeoutEventHook` and records bounded hard-timeout outcomes in `http_hard_timeout_events_total` request logging now exposes `HardTimeoutEventLogHook` with the same bounded event shape. - `securityprofile.StreamingRouteOverride` now provides an explicit route-level opt-out for streaming SSE websocket or large-download routes that must avoid hard-timeout response buffering and preserve optional writer interfaces. - `contrib/adapters/idempotencyredis.ReleaseReservation` now performs atomic token-aware compare-and-delete cleanup so stale releasers cannot delete newer in-flight reservations after expiry or replacement. - `middleware/timeout.NewHard` now contains handler panics inside the hard-timeout goroutine. Panics before timeout return deterministic Problem Details responses while panics after timeout are contained after the 504 response has already won. - `securityprofile.WithHardTimeoutMaxCaptureBytes` and `RouteOverride.HardTimeoutMaxCaptureBytes` expose hard-timeout response capture limits through global and per-route profile configuration. - Memory and Redis idempotency adapter legacy recovery events now hash keys by default and expose raw keys only through explicit raw-key opt-in fields for short incident-review windows. - The contrib release-note review gate now scopes behavior-change release-note requirements to packages classified as `supported-adapter` preserving supported-adapter governance without over-requiring notes for experimental or wrapper-only contrib internals. - The contrib release-note review gate now includes package-owned runtime assets such as JSON YAML SQL template and policy files under supported contrib package directories. - `docs/supported-adapter-contracts.tsv` now defines behavior contracts and direct-test/release-drift evidence for every `supported-adapter` contrib package. The chi router adapter and zap logger adapter are promoted to `supported-adapter` and included in the contrib drift gate. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/ratelimittest` adds reusable rate limiter adapter contract coverage and `ratelimitredis` now runs it to prove empty-key bypass per-key isolation retry-after and refill behavior. - `github.com/aatuh/api-toolkit/contrib/v4/adapters/healthchecktest` adds reusable health checker adapter contract coverage for supported Stripe Resend and Clerk readiness checks. Stable core API additions - Added stable core packages `binding` and `middleware/auth/apikey` for typed request binding Problem Details-compatible validation errors API key authentication optional auth context principals and scope enforcement. - `endpoints/list` now includes signed HMAC cursor pagination helpers alongside the existing limit/offset APIs. - `specs.Operation` now supports route contract metadata for parameters security requirements scopes deprecation sunset metadata request bodies responses and deterministic OpenAPI extensions. - `contrib/examples/api-key` demonstrates local-only HMAC-backed API key verification and scoped routes. - Added stable core package `httpcache` for ETag and Last-Modified conditional request helpers including `304 Not Modified` and `412 Precondition Failed` response paths. - Added stable core package `middleware/deprecation` for runtime `Deprecation` `Sunset` and deprecation-policy `Link` headers. - Added stable core package `webhooks` for raw-body-preserving HMAC webhook verification JSON event decoding accepted-event handling and Problem Details failures. - `specs` now supports reusable OpenAPI schemas responses security schemes and schema refs for request and response content. - Added stable core package `routecontracts` for registering handlers and matching OpenAPI operations together. - Added stable core package `negotiation` for `Accept` and `Content-Type` negotiation including `406` and `415` Problem Details responses. - `specs` now generates deterministic OpenAPI schemas from Go structs for route contract components. - `httpx` now includes a typed Problem Details catalog for stable machine-readable error codes and catalog-backed error mapping. - Added stable core package `queryparams` for collection sorting filtering sparse fieldsets and include parameter parsing without storage coupling. - Added stable core package `operations` for `202 Accepted` responses and pollable asynchronous operation resources. - `webhooks` now includes outbound HMAC-SHA256 signing helpers for JSON event requests that remain compatible with the existing receiver verifier. - Added stable core package `contracttest` for route contract OpenAPI generated contract and problem catalog assertion helpers. - Added stable core package `routepolicy` and opt-in `routecontracts` policy hooks for deriving deprecation headers content negotiation auth idempotency and rate-limit middleware from route operation metadata. - `specs` can now register reusable Problem Details and validation problem components from an `httpx.ProblemCatalog` while preserving unchanged OpenAPI output until the catalog helper is used. - `middleware/ratelimit` can now emit standard `RateLimit-Limit` `RateLimit-Remaining` `RateLimit-Reset` and `Retry-After` headers when header emission is explicitly enabled. - Added stable core package `idempotent` for idempotency-key requirements deterministic request hashes conflict/replay Problem Details accepted replay responses and OpenAPI operation extensions. - `webhooks` now includes replay-window checks required event-id contracts timestamp/event-id header constants and delivery attempt/result contract types without adding retry persistence or provider-specific schemas. - Added stable core package `upload` for multipart form decoding required file checks per-file and aggregate size limits content-type allowlists and Problem Details-compatible field errors. - Added stable core package `oauth2` for provider-neutral bearer token claims validators scope checks JWKS configuration values OpenAPI security scheme registration and `authorization.Actor`/scope mapping. - Added stable core package `apitest` for deterministic HTTP API assertions over Problem Details validation fields headers pagination operation-accepted responses webhook signatures and OpenAPI golden output. - Added stable core package `apiclient` for client-side Problem Details decoding cursor iteration `Retry-After` parsing precondition headers API key transports webhook signing transports and JSON request/response helpers. Dependency and release evidence updates - Contrib dependencies were upgraded to burn down the imported-only `govulncheck` findings from v39: `github.com/jackc/pgx/v5` is now on `v5.9.0` and `google.golang.org/grpc` is now on `v1.79.3`. - `docs/dependency-risk.md` now records the v39 advisory ownership map for `GO-2026-4762` `GO-2026-4771` and `GO-2026-4772` the active `docs/vulnerability-dispositions.tsv` manifest is header-only while current imported-only vulnerability evidence is zero. - The release evidence parser contract now includes a mixed same-package contrib drift fixture where one package has both `Incompatible changes:` and `Compatible changes:` and must summarize as incompatible. - Runtime use of the legacy `response_writer` package was removed from `httpx/recover` and maintained contrib HTTP middleware. Those packages now use package-local response wrappers while the public `response_writer` package remains source-compatible for v2 callers. - `make release-artifact-verify-fixture` now builds a synthetic local release asset bundle and runs the local verifier path. This is only local fixture coverage publication verification still requires downloaded GitHub draft release assets `RELEASE_ARTIFACT_VERIFY_MODE publication` `RELEASE_TAG` `GITHUB_REPOSITORY` real Sigstore material and online attestation checks. - The release workflow now prints `make release-review-summary` output after clean evidence is generated and before release artifact verification steps. Contrib behavior and compatibility notes - `github.com/aatuh/api-toolkit/contrib/v4/middleware/auth/devheaders` now requires explicit dangerous-bypass opt-in and trusted-proxy configuration when enabled while keeping exported config and middleware values comparable for v2 source compatibility. - `github.com/aatuh/api-toolkit/contrib/v4/middleware/metrics` now keeps the existing `NewPrometheusRecorder` signature for v2 source compatibility and adds `NewPrometheusRecorderChecked` for callers that want collector registration conflicts returned as errors. - Idempotency mixed-version compatibility metrics now expose only bounded `method` `store_class` and `outcome` labels. Raw paths idempotency keys key hashes and error strings remain available only on structured events for logs or traces. - `middleware/timeout.NewHard` now enforces a bounded response capture size with a 1 MiB default. Oversized captured responses return Problem Details instead of silently truncating successful responses. - Admin endpoint docs now steer new pprof and detailed-health mounts toward fail-closed registration helpers while preserving legacy source-compatible helpers for v2 callers. - `endpoints/health.Handler.RegisterPublicRoutesTo` and `contrib/bootstrap.MountSystemEndpointsToWithAdmin` now give new system endpoint wiring a source-compatible path that keeps public probes separate from admin-only detailed health metrics and pprof routes. - `webhooks.Receiver` now returns a generic verifier failure detail by default so custom verifier errors are not echoed to clients. Use `ReceiverConfig.VerificationErrorDetail` only for explicitly safe text. Upgrade notes - If you treated maintained contrib middleware or adapters as semver-stable review `API_BASE_REF v2.1.0 GOTOOLCHAIN local make contrib-api-drift-report` before upgrading and check `docs/contrib-api-drift-dispositions.tsv` for the current package-tied disposition. Contrib drift remains report-only this guidance helps migration review but does not extend the stable v2 API promise to contrib. - For `github.com/aatuh/api-toolkit/contrib/v4/middleware/auth/devheaders` set `AllowDangerousDevBypasses` and `TrustedProxies` explicitly when enabling debug-header auth. `TrustedProxies` is a comma-separated CIDR list. - V3 preparation guidance is now consolidated in `docs/v3-compatibility-roadmap.md`: use `compat/billing` or app-owned billing ports database stats snapshots `httpx` or package-local response helpers and token-aware idempotency release before the major-version compatibility removals. 2026-05-01 - Release evidence now writes `release-check-summary.json` schema v2 with per-check command lines exit codes durations log paths tool versions and local-vs-GitHub artifact tier metadata. - `make release-evidence` now runs the release-readiness subchecks through the evidence writer so local summaries have detailed provenance instead of a fixed pass list. - `docs/package-classification.tsv` now documents API and test quality tiers and docscheck mechanically validates direct-test wrapper-smoke example generated tooling test-support excluded and needs-tests classifications. - `docs/v3-compatibility-roadmap.md` now contains one removal matrix for provider-shaped billing ports pgx-shaped database stats `response_writer` tokenless idempotency release unchecked authz construction and checked list parser shims. - `make contrib-api-drift-report` adds a report-only API drift signal for selected high-use contrib adapters and integrations without changing the contrib compatibility policy. - `make contrib-release-notes-check` adds a lightweight review gate requiring release-note coverage when contrib adapter or integration behavior files change. - Release evidence now records `git_state` with branch/detached state dirty flag staged/unstaged/untracked/deleted counts and the commit checked. - Release evidence now records top-level `publication_eligible` automation must require it to be `true` along with passed status clean provenance and clean git state before accepting publication evidence. - Release evidence now fails publication mode on dirty worktrees unless `ALLOW_DIRTY_RELEASE_EVIDENCE 1` explicitly marks the output as local dirty-tree audit evidence. - Release evidence now archives `.ci-result/release-evidence/logs` as `.ci-result/release-evidence/release-evidence-logs.tgz` and records `publication_artifact_expectations` for draft-release asset review. - `make release-artifact-verify` now verifies downloaded draft release asset names `release-asset-manifest.tsv` checksums retained release logs SBOM signatures/certificates and expected provenance subjects before publishing. - The tag-driven release workflow now verifies keyless SBOM signatures against the GitHub OIDC certificate identity and issuer before uploading draft release assets. - Release evidence now records `vulnerability_evidence` from govulncheck logs so imported-but-not-called vulnerability IDs and counts have reviewer disposition in `docs/dependency-risk.md` and `docs/vulnerability-dispositions.tsv`. - Release evidence now dynamically compares imported-only vulnerability IDs with `docs/vulnerability-dispositions.tsv` and fails when dispositions are missing incomplete or expired on the release review date. - `make release-evidence` now archives report-only contrib drift at `.ci-result/release-evidence/logs/contrib-api-drift-report.log` and summarizes drift skipped compatible and incompatible counts in `release-check-summary.json`. - Release evidence now records current contrib drift packages and status compares them with `docs/contrib-api-drift-dispositions.tsv` and fails when current drift has missing or expired disposition coverage. - Current contrib drift disposition is recorded in `docs/contrib-api-drift-dispositions.tsv` including the incompatible report-only `contrib/middleware/auth/devheaders` drift. - `make release-check` and `make release-evidence` now include `contrib-release-notes-check` while `contrib-api-drift-report` reads selected report-only packages from `docs/contrib-api-drift-packages.txt`. - Incompatible report-only contrib drift is acknowledged for this release: `contrib/middleware/auth/devheaders` changed exported struct comparability because middleware/config types now include non-comparable lifecycle fields. This remains a review signal and does not make contrib stable. - `make contrib-release-notes-check` now requires incompatible report-only contrib drift acknowledgement to mention the affected package not only a generic incompatible-contrib phrase. - Docscheck now blocks new production source usage of deprecated billing ports outside `ports`/`compat/billing` and direct database-stat usage outside compatibility or adapter paths. - Idempotency middleware response capture now uses a package-local helper instead of importing the legacy `response_writer` compatibility package. - `docs/release-review.md` gives release reviewers a shorter path through the runbook release notes stability policy package classification compatibility roadmap and evidence artifacts. - Wrapper and example coverage policy now distinguishes wrapper smoke minimums from build-smoke-only example coverage. - Package docs for `ports` `compat/billing` and the legacy response helper package now identify v2 compatibility-sensitive surfaces and preferred replacements for new code. - `contrib/middleware/requestlog` expands header redaction defaults for broader authentication/session families and adds payload field redaction helpers for non-header custom fields. - `contrib/adapters/httpclient` retry defaults are now conservative: `GET` and `HEAD` only other methods such as `PUT` and `DELETE` now require explicit opt-in through `RetryableMethods`. - `contrib/bootstrap` pprof mounting now defaults to opt-in behavior and requires explicit profile intent to enable `Pprof` routes in production-like defaults. - Idempotency in-flight reservations now carry `ReservationToken` and require tokenized releases for healthy non-legacy records while legacy tokenless records are recovered during mixed-version rollouts when stale past `InFlightTTL`. - Idempotency memory and Redis adapters now expose optional legacy-recovery telemetry callbacks for tokenless record migrations `legacy_in_flight_recovered` and `legacy_in_flight_token_mismatch` . - Idempotency middleware now emits compatibility telemetry for mixed-version fallback attempts `legacy_in_flight_fallback_entered` `legacy_in_flight_fallback_recovered` `legacy_in_flight_fallback_rejected` `legacy_in_flight_fallback_unknown` and validates cross-service `InFlightTTL` alignment via `KnownInFlightTTLs`/`FailOnInFlightTTLMismatch`. - `ports.ErrLegacyInFlightReservationMissingToken` has been added for migration-time observability of legacy in-flight record recovery. - `middleware/auth/authz` keeps the v2-compatible single-return constructor and adds `NewRequireRoleMiddlewareChecked` plus bootstrap validation for explicit role requirements and nil resolver detection at route setup. - `endpoints/list` keeps the v2-compatible single-return parser helpers and adds checked variants `ParseListQueryChecked` `DefaultFilterParserChecked` `DefaultSortParserChecked` for callers that need field-level validation errors. - `contrib/middleware/requestlog` documents and supports deep payload redaction for common typed container shapes `map[string]string` `[]map[string]string` while preserving legacy shallow behavior. - Idempotency middleware now emits mixed-version fallback telemetry by default when no `OnLegacyInFlightCompatibility` callback is configured defaults legacy compatibility keys to stable SHA-256 redaction and supports explicit raw-key opt-in through `LegacyInFlightCompatibilityRawKey`. - Idempotency startup rollout governance now includes optional strict clock-preflight checks `FailOnInFlightClockSkewPreflight` for mixed-version safety emitting `ErrLegacyInFlightClockSkewPreflightRisk` in strict mode and advisory deprecation-risk warnings in default mode. - `contrib/adapters/chi` now ships a route bootstrap helper that maps chi route registration context into authz role specs and validates role coverage in one startup call including actionable `ANY`/method route context. - `contrib/middleware/requestlog` normalizes panic observability by always logging recovered panics at error level with failure classification including committed- response panics and preserving committed status for optional downstream analytics. - Release readiness now has a fail-closed `make release-check` path that requires `API_BASE_REF v2.1.0` keeps local `make api-check` fallback behavior separate and publishes `release-check-summary.json` with release SBOM assets. - Root idempotency adapter contract coverage moved to contrib-owned reusable contract tests so root `go.mod` no longer carries contrib Redis or miniredis requirements for core middleware tests. Upgrade notes - If your system endpoint wiring relied on implicit pprof exposure in production profiles use an explicit profile-aware mount helper to re-enable it intentionally. - If you require retries for non-idempotent methods add them explicitly to `RetryableMethods` and confirm the target API contract is idempotent. - If you are rolling out idempotency migration with shared Redis across mixed binary versions ensure all services agree on `InFlightTTL`. Legacy tokenless in-flight entries will be auto-cleared only when stale and mixed-version cleanup can be delayed by that TTL when no newer version processes the key first. - Legacy idempotency cleanup requires aligned timing: set `InFlightTTL` consistently across services and storage layers including matching `InFlightTTL` and key TTL behavior keep `SystemClock` sources synchronized and ensure record `CreatedAt` monotonic assumptions match your deploy latency. Checklist during rollout: 1 run `ValidateRequireRoleMiddleware`-style startup checks for route wiring on all roles-protected endpoints 2 verify `InFlightTTL` parity and shared store key prefixes across all deploy units 3 monitor middleware telemetry outcomes `legacy_in_flight_fallback_entered` `..._recovered` `..._rejected` `..._unknown` while mixed binaries run and 4 remove tokenless-compatibility behavior only after mixed-version fallback suppression reaches zero. - Recommended rollout telemetry contract: - Labels: `method` `path` `store_type` `outcome` `key` optional and `error`. - For metric collectors prefer `LegacyInFlightCompatibilityMetricSink` and `LegacyInFlightCompatibilitySampleEvery` during large rollout waves. - Use `LegacyInFlightCompatibilityAsync` when callback latency must not affect request latency. Keep `Logger`/compatibility sink diagnostics during initial rollout windows for deterministic evidence. - Default warning thresholds: - `legacy_in_flight_fallback_unknown 0` for 5 minutes indicates release risk and should page. - `legacy_in_flight_fallback_rejected / legacy_in_flight_fallback_entered` above `0.5 ` over 10 minutes indicates high key-level contention and should be investigated. - `legacy_in_flight_fallback_recovered / fallback_entered` dropping below `99 ` indicates likely TTL/clock contract mismatch. - Dashboard query examples: - Backpressure behavior: - Synchronous sinks execute in the request path if a custom sink is slow or blocking requests can back up at startup and during mixed-version load. - Enable async emission for high-volume migrations and confirm callback exceptions are tracked by tests or sink-specific observability since they are intentionally recovered and must not abort request handling. - If you rely on zero-config retry behavior in `contrib/adapters/httpclient` review all non-GET/HEAD consumers and update to explicit `RetryableMethods` only for confirmed replay-safe routes and clients. - `NewRequireRoleMiddleware` keeps the v2-compatible single-return constructor. Invalid wiring is still fail-closed at runtime until fixed and will return `401` no actor or `403` actor without role as applicable. For startup validation use `NewRequireRoleMiddlewareChecked` or run `ValidateRequireRoleMiddleware method route mw ` for each protected route. - If you need startup authz migration validation prefer registry-level validation via `ValidateRequireRoleMiddlewareRoutes` during bootstrap and fail startup on the first startup pass when any route fails this check. - Rollout symptoms of misconfigured authz route wiring are usually a startup failure in CI or process init `invalid role middleware for route ...` then runtime `401` for unauthenticated requests and `403` for missing-role users. Rollback sequence when migration checks block startup: 1 restore previous middleware wiring 2 temporarily disable strict constructor checks only as a temporary guardrail 3 reapply the startup check after role/route registration is repaired and 4 rerun staged rollout. - `requestlog` payload redaction assumes redaction-sensitive names based on canonical field patterns `token` `secret` `password` common aliases before any deep traversal. For typed payloads normalize unsupported custom shapes to map/slice-of-map shapes before calling `requestlog.RedactPayloadFieldsDeep` see `contrib/middleware/requestlog/doc.go` . - For mixed-version idempotency rollouts run startup with `FailOnInFlightTTLMismatch` and `FailOnInFlightClockSkewPreflight` only after you have parity checks and rollback strategy in place. Keep both off during the first boot of a migration wave if you need warning-only discovery. - `ports.IdempotencyReleaser.Release ctx key ` remains the v2 compatibility contract for existing custom stores. New stores should also implement `ports.IdempotencyReservationReleaser.ReleaseReservation ctx key token ` so middleware can release only the current tokened in-flight reservation. - To upgrade authz checks with chi either build explicit `[]authz.RequireRoleRouteSpec` and validate via `authz.ValidateRequireRoleMiddlewareRoutes` or use `chi.ValidateRequireRoleMiddlewareRoutes` with a route method resolver closure to map protected handlers. 2026-04-24 - `contrib/telemetry.WrapHTTPClient nil ` now creates an instrumented client with a 10 second timeout instead of an unbounded zero-timeout client. - `contrib/migrator.Options.LockTimeout` can now override the advisory lock wait timeout zero keeps the previous 10 minute default. - `contrib/migrator.Options.UnlockFailureHandler` and the existing migrator logger can now surface advisory unlock failures without replacing the primary migration result. Upgrade notes - If you intentionally need no client-level timeout for a telemetry-wrapped `net/http` client pass an explicit ` http.Client ` to `WrapHTTPClient` prefer request contexts with deadlines for long-running calls. 2026-04-23 - Billing contracts in `ports/billing.go` are now formally deprecated for new code. The same Stripe-shaped v2 model is available through the new compatibility package `github.com/aatuh/api-toolkit/v4/compat/billing`. - `contrib/adapters/pgxpool.Adapter.StatSnapshot ` now copies plain-value pool stats directly from pgxpool instead of routing through the legacy `DatabaseStats` wrapper path. Upgrade notes - Existing code that imports billing contracts from `ports` keeps working for the rest of v2 but new code should migrate to `github.com/aatuh/api-toolkit/v4/compat/billing` so the provider-shaped dependency is explicit before v3 extraction. - If your health or observability code still reads `DatabasePool.Stat ` or depends on `DatabaseStats` move it to `DatabasePoolSnapshotProvider` `SnapshotDatabasePoolStats` or adapter `StatSnapshot ` methods. The legacy counter interface remains for compatibility adapters not as the preferred generic path. 2026-04-19 - `contrib/middleware/auth/devheaders` now requires explicit dangerous-bypass opt-in and trusted-proxy configuration before it will honor debug auth headers. - Health endpoints now fail closed on empty or miswired liveness/readiness probe sets and HTTP handlers only expose detailed dependency output when `ports.HealthCheckConfig.EnableDetailed` is explicitly enabled. - `contrib/adapters/txpostgres.WithinTx` now attempts deferred rollback with a bounded cleanup context even when the caller context is already canceled or timed out. - `contrib/adapters/txpostgres` now fails closed with `ErrPoolNotConfigured` when callers forget to wire a database pool instead of panicking on nil-pool use. - `endpoints/docs.New ` and `NewDefaultHandler ` now default to the first-party static docs surface callers must opt into the CDN-backed Swagger UI mode with `docs.NewSwaggerUI ` or `DocsConfig.HTMLMode`. - `contrib/migrator` now records commit-acknowledgement failures as `uncertain` and blocks later runs when a prior migration record is still `started` or `uncertain`. - `scheduler.Runner` now persists final run records through a bounded cleanup context so graceful shutdown does not drop `LastFinished` updates for jobs that already completed. - `scheduler.Runner` now surfaces recorder persistence failures through structured logs and optional `SetRecorderFailureHandler` callbacks without changing the completed job result or schedule cadence. - JWT and Clerk middleware now share internal auth/JWKS validation primitives with no intended public API or configuration change. Upgrade notes - If you previously enabled `devheaders` without explicitly opting into dangerous bypasses or without trusted-proxy configuration startup will now fail fast until you set both intentionally. - If you had tests or thin wiring paths that called `txpostgres.New nil ` or `txpostgres.FromCtx ... nil ` they now return `ErrPoolNotConfigured` instead of panicking. - If you relied on `docs.New ` or `NewDefaultHandler ` to serve Swagger UI with CDN assets switch to `docs.NewSwaggerUI ` or set `DocsConfig.HTMLMode ports.DocsHTMLModeSwaggerUI` explicitly. - If a deployment previously canceled scheduler job contexts during graceful shutdown completed jobs now get a short recorder-persistence window before exit so restart-time suppression remains accurate. - If operators previously relied on `/health` or equivalent routes exposing dependency-level detail by default set `EnableDetailed` explicitly during wiring otherwise only basic probes should remain visible. - If your deployment workflow retried migrations automatically after commit errors stop doing that. Inspect the database state and reconcile `schema_migrations` before rerunning when a migration is recorded as `started` or `uncertain`. - If you need alerting when scheduler run history cannot be persisted wire `SetRecorderFailureHandler` or monitor the new recorder-failure log events job completion alone no longer implies recorder persistence succeeded. - JWT and Clerk integrations should be behaviorally equivalent to their prior public APIs but custom wrappers that depended on edge-case differences in bearer parsing claim requirements or skip-header handling should be revalidated. 2026-04-15 - Idempotency middleware now releases failed reservations after downstream `5xx` responses and panics so retries with the same payload and `Idempotency-Key` are not blocked behind a stale in-flight record. - Idempotency middleware now fails closed with `503 Service Unavailable` when it cannot persist a completed replay record and it stores an ambiguous state for that key instead of reopening it for another execution. - Idempotency middleware now includes authenticated actor and tenant scope in the default request hash preventing cross-principal or cross-tenant replays from reusing the same key and payload. - Idempotency middleware now caps buffered replay bodies at `1 MiB` by default and returns `503 Service Unavailable` plus an ambiguous key state when a handled response exceeds the replay buffer limit. - `scheduler.Runner` now recovers scheduled-job panics logs and records them as failed runs and keeps future intervals alive instead of letting one bad job crash the process. - `scheduler.Runner` now prevents the same job name from overlapping with itself across duplicate `Start` calls or duplicate scheduling of the same job. - `bootstrap.ProfileStrictAPI` no longer enables wildcard CORS by default browser-facing cross-origin access now requires an explicit `WithCORSOptions ... ` allowlist. - `contrib/config.LoadFromEnv` now treats invalid present bool and int values as startup errors instead of silently falling back to defaults. - Docs endpoints now return `404` when the HTML docs surface is disabled or when no authoritative OpenAPI document is available. - `DocsConfig.EnableJSON` and `DocsConfig.EnableYAML` now control which discovered OpenAPI formats may be served on the configured docs path. - Multi-source migrator loading now documents its actual contract: duplicate version direction pairs are rejected. - The pagination example now returns one field-level validation shape for invalid `limit` inputs even when `querylimits` rejects the request before the handler. Upgrade notes - If clients previously saw `409 Conflict` after a failed idempotent write retry behavior has changed: the same payload and `Idempotency-Key` can now be retried immediately after downstream `5xx` and panic paths but not after completed-response persistence failures or replay-buffer overflows. - If clients previously received the original success response even though completion persistence failed they now receive `503 Service Unavailable` and the key remains blocked in an ambiguous state until it expires or is reconciled. - If authenticated middleware previously ran after idempotency default caller scoping will not apply. Move auth and tenant middleware earlier in the stack to keep replay protection scoped per caller. - If a route can stream hijack upgrade or return large bodies exclude it with `ShouldHandle` or raise `MaxResponseBytes` otherwise oversized handled responses now fail closed with `503 Service Unavailable` and block same-key retries for the key lifetime. - If a scheduled job panic previously terminated the process that failure is now contained and surfaced through scheduler logging and run recording instead. - If application code called `scheduler.Runner.Start` more than once or reused the same job name across duplicate schedules those executions no longer overlap. Validate any workload that previously relied on concurrent execution of the same named job. - If browser clients previously relied on `ProfileStrictAPI` to emit `Access-Control-Allow-Origin: ` they must now set an explicit allowlist with `WithCORSOptions ... ` during bootstrap. - If deployment environments previously contained malformed bool or int values such as `MIGRATE_ON_START maybe` startup now fails fast instead of silently using defaults. Validate env files and secrets before rollout. - If deployment environments used undocumented semantic values such as `ENV qa` `ENV prod` `LOG_LEVEL verbose` or `LOG_LEVEL warning` startup now fails fast. Use `development staging production` for `ENV` and `debug info warn error` for `LOG_LEVEL`. - Docs handlers no longer return a synthetic OpenAPI document when no authoritative spec exists. Expect `404` for disabled docs surfaces and for missing OpenAPI files unless a real document is configured. - `DocsConfig.EnableJSON` and `DocsConfig.EnableYAML` now control which discovered OpenAPI formats can be served. Verify custom docs paths and any YAML-based docs setup during upgrade." }, { "title": "V3 Migration Guide", @@ -333,7 +333,7 @@ "title": "Documentation", "category": "navigation", "url": "https://github.com/aatuh/api-toolkit/blob/master/docs/README.md", - "text": "docs/README.md Documentation Audience: readers who need the fastest path to the right api-toolkit document without scanning the root README. Current Release Identity The verified current root baseline is `v4.0.1`. Documentation Audience: readers who need the fastest path to the right api-toolkit document without scanning the root README. Current Release Identity The verified current root baseline is `v4.0.1`. `v4.0.0` `contrib/v4.0.0` and `contrib/v4.0.1` are withdrawn use the [v4 release-identity incident] release-incident-v4-release-identity.md for the immutable evidence and required paired-contrib recovery path. New users and application developers Document Audience Purpose [Library-first path] library-first.md Existing-service users Add the smallest useful root package set to a `net/http` chi or app-owned router service. [Minimal core path] minimal-core.md Existing-service users Use only `httpx` `binding` `middleware/maxbody` and `middleware/timeout` without contrib or generators. [Core package decision guide] core-package-guide.md Adopters and reviewers Choose packages by use case when-not-to-use guidance stability tier dependency note and example link. [Scaffold-first path] scaffold-first.md New service teams Generate app-owned service code and understand what the toolkit owns versus what the generated app owns. [Contrib adapter path] contrib-adapters.md Adapter adopters Decide when to add supported contrib adapters integrations examples or generator tooling. [CLI and scaffold identity] cli-scaffold-identity.md Adopters and maintainers Decide how CLI scaffold generated-service and library-first identities stay separate. [Stable core charter] stable-core.md New users and maintainers Decide which root packages are the recommended small-core dependency surface and what evidence stable packages need. [Roadmap and non-goals] ../ROADMAP.md Adopters and contributors See current direction candidate work explicit non-goals and proposal rules. [Core readiness matrix] core-readiness.md API consumers and release reviewers Review docs examples tests fuzz benchmark compatibility security review and production caveats for each stable package. [Alternatives] alternatives.md Evaluators Decide when to use `api-toolkit` instead of `net/http` chi oapi-codegen Goa Connect or app-owned helpers. [Getting started] getting-started.md Scaffold users Generate run and verify the production-oriented app-owned service scaffold. [Full service scaffold] full-service-scaffold.md Application teams Understand the `saas-api-full` production foundation support tier and integration-test policy. [Reference service] reference-service.md Maintainers and release reviewers Verify the checked-in `saas-api-full` adoption proof and know which evidence is local Docker-backed or deployment-owned. [Adopter story] adopters.md Evaluators and maintainers Read the maintainer-owned reference-service outcome friction changes and evidence limits without treating it as a customer case study. [Production readiness] production-readiness.md Technical leads and platform owners Decide which surfaces are production-ready supported-adapter experimental caveated or part of the adapter maturity review. [V3 migration guide] migration/v3.md Application teams upgrading dependencies Upgrade root contrib and generated-service adoption paths within the v3 line. [V4 migration guide] migration/v4.md Application teams upgrading major versions Update module paths and replace removed root-port contracts. [Troubleshooting] troubleshooting.md Application developers and maintainers Diagnose Go version contrib tier timeout buffering health idempotency auth and generated-service issues. [Test coverage evidence] test-coverage.md Maintainers and release reviewers Read the coverage gate outputs package-level floor summary and release-evidence relationship. [Package coverage trend] coverage-trend.md Maintainers and release reviewers Compare root and selected contrib package coverage across published releases. [Benchmark baselines] performance.md Maintainers and release reviewers Run and interpret package-level benchmark baselines before performance-sensitive changes or releases. [Coverage hardening backlog] coverage-hardening-backlog.md Maintainers Track behavior-test prerequisites before raising high-risk package coverage floors. [Cookbook] cookbook.md Application developers Complete common API tasks with commands requests expected responses and caveats. [Examples catalog] ../contrib/examples/README.md Developers copying runnable patterns Find each contrib example its command endpoint expected result required env and safety note. [Architecture] architecture.md Developers and maintainers Understand the hexagonal boundary between stable core ports and contrib adapters. The contrib CLI can scaffold the fuller reusable service baseline: Use `--auth jwt` or `--auth clerk` when the generated service should validate bearer tokens via JWKS instead of local API keys. Bearer scaffolds require the matching issuer audience and JWKS URL environment variables extract tenant scope from validated token claims and keep the same tenant mismatch idempotency OpenAPI and admin-route defaults. Generated services wire the default router to the contrib Prometheus recorder so protected `/metrics` includes bounded HTTP request counters and histograms using method route pattern and status labels. Generated services also expose `/version` with build metadata. The generated Makefile `build` target stamps the binary with `VERSION` `BUILD_COMMIT` and `BUILD_DATE` the Dockerfile accepts matching build args and uses `dev`/`unknown` defaults for local builds. Use `--profile dev-api --auth dev-headers` only for local development services that need debug-header authentication. The generated service requires explicit dev-bypass environment variables trusts only configured loopback proxies by default uses separate debug tenant and scope headers and refuses to start with dev-header auth when `ENV production`. The `saas-api-full` profile keeps the lean `saas-api` default intact and starts the heavier Postgres Redis production foundation described in [full-service-scaffold.md] full-service-scaffold.md . The full profile is wired through `bootstrap.NewAPIService` exposes `/livez` separately from `/readyz` keeps detailed health/metrics/pprof on admin routes and enables runtime OpenAPI request validation by default. Reference-service evidence starts at [reference-service.md] reference-service.md and then follows the app-owned docs under `examples/reference-saas-api` including its README deployment starter docs observability runbook and provider workflow runbook. Read the [adopter story] adopters.md for the maintainer-owned outcome and its explicit evidence limits. The same CLI can review OpenAPI artifacts before release. `contracts lint` checks operation IDs non-public security requirements unsafe-write tenant idempotency rate-limit metadata request body metadata documented 2xx success responses Problem Details responses and protected operator paths. `contracts diff` allows additive operations and fails closed on removed operations changed operation IDs removed documented parameters added required parameters removed documented responses request-body tightening or content removal response content removal changed operation or inherited global security requirements component and inline schema removals obvious schema type/required/property/enum narrowing or drift in tenant idempotency rate-limit admin and deprecation route policy metadata: `clients go` emits a stdlib-only Go client package for the supported OpenAPI subset: JSON request bodies path/query/header options API-key auth bearer auth and Problem Details error decoding. The default `raw` style preserves the original operation helpers `--style typed` also generates component schema structs typed request/response methods and raw method escape hatches. The contract and client commands accept OpenAPI 3.1 schema `type` arrays that include `null` and schema-level `examples` normalizing them to the toolkit s compatibility model before validation. `api-toolkit version` prints the tool version Go runtime main module core module version contrib module version and optional build commit/date fields. Use `api-toolkit version --json` for machine-readable release evidence that identifies the installed generator and contract tool. Security operations and runtime behavior Document Audience Purpose [Security posture] security.md Developers and operators Configure secure defaults dangerous bypasses trusted proxies health detail and docs surfaces. [Security threat model] threat-model.md Maintainers application teams and security reviewers Review protected assets assumptions threats mitigations and verification evidence for security-sensitive surfaces. [Package security review] security-review.md Maintainers and reviewers Record threat input secret authorization DoS data-leakage and observability review evidence for each affected package. [Auth production guide] auth.md Developers and operators Configure API-key JWT tenant role JWK rotation clock skew failure modes and auth tests. [Idempotency production guide] idempotency.md Developers and operators Configure storage locking TTL replay semantics request hashes tenant scoping conflicts and Redis/Postgres ownership. [Health and admin operations] operations.md Operators and developers Split public probes from detailed health metrics pprof admin auth network policy and fail-closed checks. [OpenAPI contract workflow] openapi-workflow.md Maintainers and application teams Run route metadata golden diff contract tests generated docs validation and drift handling. [Runtime configuration] configuration.md Operators and developers Review required production env vars defaults unsafe dev defaults and startup validation. [Observability] observability.md Operators and developers Keep metrics logs traces correlation IDs and dashboards useful and redaction-safe. [Scaffold support matrix] scaffold-support.md Generated service teams Understand what generated code is supported app-owned fragile on regeneration and migration-owned. [Adapter maturity matrix] adapter-maturity.md Contrib adopters Review supported/tested/experimental posture for Postgres Redis Stripe Resend Clerk OpenTelemetry CORS validation and related adapters. [Safe defaults audit] safe-defaults.md Developers and reviewers Check fail-open and fail-closed behavior for root and contrib middleware before broad rollout. [Middleware safety matrix] middleware-safety.md Developers and reviewers Decide which middleware is safe globally route-specific forbidden for streaming or requires opt-outs. [Input-size threat review] input-size-threat-review.md Developers reviewers and operators Review header body JSON query multipart replay-capture and timeout-capture size limits before changing route contracts. [Negative-path test matrix] negative-path-test-matrix.tsv Maintainers and release reviewers Verify stable-package tests for malformed input missing headers bad content types invalid auth invalid tenant oversized bodies and invalid query limits. [Testing policy] testing.md Maintainers and release reviewers Keep tests deterministic with fake clocks injected sleep bounded retries and documented deadlock guards. [Security policy] ../SECURITY.md Security reporters and release consumers Report vulnerabilities and understand supported release security handling. [Security advisory drill] security-advisory-drill.md Maintainers and security reviewers Review the completed fictional private-advisory drill and disclosure process. [Code of conduct] ../CODE_OF_CONDUCT.md Contributors and maintainers Set expectations for respectful project participation and conduct reporting. [Panic policy] ../PANIC_POLICY.md Maintainers and API designers Decide when panics are allowed and how HTTP recovery behaves. [Metrics] metrics.md Operators and developers Use low-cardinality HTTP metric names and labels. [Support policy] support-policy.md Adopters and maintainers Understand the supported Go line platform gate and generated-service ownership limits. [Dependency boundary] dependency-boundary.md Maintainers Keep root stable code free of contrib adapter dependencies. [Auth dependency split decision] auth-dependency-split.md Adopters and maintainers Understand the v3-era JWT/JWK module graph cost and the v4 target for auth-heavy packages. [Provider adapter split decision] provider-adapter-split.md Adopters and maintainers Keep Postgres Redis Stripe Resend OpenTelemetry router and provider adapters out of stable core. [Extension module assessment] extension-module-assessment.md Maintainers and release reviewers Reject speculative provider-module splits until adoption ownership dependency and release-cadence evidence supports one. [Dependency policy] dependency-policy.md Maintainers Review allowed dependency classes banned patterns update SLA and security-sensitive review gates. [License policy] license-policy.md Maintainers Review allowed dependency licenses dependency-review enforcement and exception handling. [Dependency risk] dependency-risk.md Release reviewers and security maintainers Review imported-but-not-called vulnerability disposition and ownership. [Dependency footprint] dependency-footprint.md Adopters and release reviewers Run and interpret root/contrib dependency footprint and base-ref diff reports. Stability compatibility and package docs Document Audience Purpose [Versioning] ../VERSIONING.md API consumers and maintainers Define the stable core API surface and contrib compatibility policy. [Public API inventory] api-inventory.md API consumers and maintainers Review generated exported symbols grouped by package stability tier added version and deprecation status. [API reference index] api-reference.md API consumers Jump from each stable or compatibility-only root package to pkg.go.dev and its compile-checked example. [Generated API docs site] site/index.html API consumers Search package status examples compatibility docs and migration guides from a static generated site. [Downstream compatibility kit] downstream-compatibility.md API consumers Run experimental `compatkit` service checks against an in-process handler or explicit base URL. [API review checklist] api-review-checklist.md Maintainers Review naming zero values context cancellation errors concurrency options return types and interface necessity. [Governance] governance.md Maintainers Review stable API review board process branch protection CODEOWNERS required checks release approval and maintainer succession policy. [API addition example exceptions] api-addition-exceptions.tsv Maintainers Record exact symbol exceptions when a new stable exported identifier has a doc comment and release note but a compile-checked example would mislead. [Deprecation policy] deprecations.md Maintainers and release reviewers Track deprecation format replacements removal horizon migration snippets and release-note requirements. [Interface ownership] interface-ownership.md Maintainers Document whether exported interfaces are user-implemented adapter-owned test-only or compatibility-sensitive. [Options struct audit] options-structs.md Maintainers Review defaults validation behavior zero-value behavior and example evidence for stable exported options structs. [Global state audit] global-state-audit.md Maintainers Review package-level globals in stable packages and the limited mutable-state exceptions. [Context and cancellation] context-cancellation.md Maintainers and adopters Apply context propagation and bounded cleanup rules across HTTP auth idempotency scheduler and client APIs. [Error taxonomy] errors.md Maintainers and API consumers Match sentinel typed field wrapped configuration and Problem Details errors safely. [Concurrency safety] concurrency.md API consumers and maintainers Decide which values are immutable request-scoped synchronized or implementation-owned. [Resource lifecycle] resource-lifecycle.md Maintainers and adopters Track ownership for close shutdown timers goroutines stores adapters and generated service resources. [Ports surface] ports-surface.md Maintainers and advanced API consumers Identify compatibility-sensitive port history and preferred replacements. [Ports export exceptions] ports-export-exceptions.tsv Maintainers Review the accepted ADR required for any new root `ports` export. [V3 compatibility record] v3-compatibility-roadmap.md Maintainers Track completed v3 cleanup decisions and remaining compatibility-sensitive guardrails. [V4 scope cleanup plan] v4-plan.md Maintainers and advanced adopters Plan which root surfaces to keep stable demote split or remove only in a future major release. [Ports v4 migration ledger] ports-v4-migration-ledger.tsv Maintainers and advanced adopters Record every current root-port export consumer packages implementation evidence v3 deprecation status and v4 disposition. [Package doc standard] package-doc-standard.md Maintainers Apply the minimum package-doc template and see the placeholder inventory remediated in this pass. [Package classification guide] package-classification.md Maintainers and adopters Read the rendered status glossary before using the TSV source of truth. [Core readiness matrix] core-readiness.md API consumers and release reviewers Review stable package readiness by docs examples tests fuzz benchmark compatibility security review and production caveat. [Module-boundary ADR] adr/0001-module-boundaries.md Maintainers Record the v3 decision to keep root and contrib modules while deferring deeper splits to v4 planning. `docs/package-classification.tsv` Maintainers and automation Machine-readable API and test-status classification for every package. `docs/package-owners.tsv` Maintainers and automation Machine-readable maintainer owner test owner stability tier and release-blocker status for every package. `docs/supported-adapter-contracts.tsv` Maintainers and automation Machine-readable behavior contracts and evidence paths for supported contrib adapters. `docs/supported-adapter-test-realism.tsv` Maintainers and automation Machine-readable default and scheduled/manual test-realism evidence for each supported contrib adapter. Release and evidence Document Audience Purpose [Production-grade 9/10 roadmap] roadmap/production-grade-9x.md Maintainers and program owners Track the prioritized remediation program its dependencies acceptance criteria and closure rules. [Production-grade scorecard] roadmap/scorecard.tsv Maintainers and reviewers Track evidence-based baseline target owner and review status for the eight production-readiness areas. [Audit and scratch archive policy] audits.md Maintainers and release reviewers Keep local `.audits` and `.trash` scratch material out of tracked release evidence. [OpenSSF Best Practices gap review] openssf-best-practices.md Maintainers and release reviewers Track Best Practices badge readiness unclaimed status and remaining gaps before publishing a badge. [V4 release-identity incident] release-incident-v4-release-identity.md V4 consumers and release reviewers Follow the current safe action while the v4 tag history and checksum mismatch are reconciled. [Release runbook] release-runbook.md Release operators Command source of truth for local checks release evidence artifact verification and baseline policy. [Release provenance] provenance.md Release consumers and reviewers Verify GitHub artifact provenance understand the attested asset scope and apply the documented trust limits. [Reproducible build status] reproducible-builds.md Release consumers and maintainers Distinguish unsupported binary reproducibility from the checksums signatures and provenance verified for release assets. [Release review checklist] release-review.md Release reviewers Short path through summary fields manifests dirty-tree decisions artifacts and release notes. [Governance] governance.md Maintainers Branch protection CODEOWNERS tag protection required checks and release approval expectations. [Changelog] ../CHANGELOG.md Release consumers Concise user-facing history for published releases. [Release notes] release-notes.md Release consumers and maintainers Dated behavior changes upgrade notes and package-tied contrib drift acknowledgements. [Release manifests] release-manifests.md Release reviewers and maintainers Human guide for package classification contrib drift contrib dispositions and vulnerability dispositions. `docs/contrib-api-drift-packages.txt` Maintainers and automation Selected contrib packages reviewed by drift checks supported-adapter incompatible drift is gate-enforced. `docs/supported-adapter-contracts.tsv` Maintainers and automation Required supported-adapter behavior contracts with direct-test and release-drift evidence. `docs/supported-adapter-test-realism.tsv` Maintainers and automation Required supported-adapter realism rows that distinguish direct-unit fake DB miniredis hermetic fixture and scheduled/manual real-service evidence. `docs/contrib-api-drift-dispositions.tsv` Release reviewers and automation Owner status review date expiry and acknowledgement for current contrib drift. `docs/vulnerability-dispositions.tsv` Release reviewers and automation Owner review expiry and upgrade trigger rows for imported-only vulnerability IDs when present. `release-check-summary.json` Release reviewers Generated local release evidence summary only clean publication evidence is publishable. Documentation quality workflow Use the narrowest check that matches the change: Change type Preferred command Notes Documentation-only edits `GOTOOLCHAIN local make docs-check` Runs documentation contracts generated docs-site drift checks getting-started build extraction API/docs policy checks and release evidence parser contracts. Architecture or dependency-boundary edits `GOTOOLCHAIN local make dependency-boundary-check` Runs the stable-core import boundary check before the broader docs gate. V3 cleanup readiness `GOTOOLCHAIN local make v3-readiness-check` Runs focused compatibility-sensitive surface guardrails for major-version cleanup planning and release-note requirements. Docs plus ordinary code changes `GOTOOLCHAIN local make fast-check` Runs `docs-check` and unit tests without rewriting files. Reference service coverage `GOTOOLCHAIN local make reference-service-coverage` Records non-Docker generated-service coverage under `.ci-result/coverage/` without folding app-owned code into toolkit coverage thresholds. Reference service load `GOTOOLCHAIN local make reference-service-load` Records non-Docker generated-service latency throughput memory allocation and expected auth-failure evidence under `.ci-result/reference-service-load/`. Generated full-profile soak `GOTOOLCHAIN local make generated-soak-check` Records nightly-style generated `saas-api-full` race/goroutine soak evidence and repeated Docker integration-cycle logs under `.ci-result/generated-soak/`. Generated full-profile failure `GOTOOLCHAIN local make generated-failure-check` Records generated `saas-api-full` Redis-down Postgres-down expired API-key bad JWKS and slow downstream timeout evidence under `.ci-result/generated-failure/`. Timeout determinism `GOTOOLCHAIN local make timeout-determinism-check` Repeats the hard-timeout late-write test under normal and race runs then runs the root timeout/idempotency/rate-limit/scheduler race subset. Reviewer or audit pass `GOTOOLCHAIN local make audit-check` Non-mutating reviewer gate with lint vuln gosec build smoke GitHub Actions pin audit docs contracts tests race and fuzz smoke. Generated files examples scripts package docs or repo-wide contracts `GOTOOLCHAIN local make finalize` when practical Installs tools and may rewrite Go formatting and module files through `fmt` and `tidy` avoid it in shared dirty worktrees unless that mutation is intended. Do not treat `make finalize` as release evidence. Release publication evidence is owned by [release-runbook.md] release-runbook.md . If the local Go version is older than Go 1.25.x `GOTOOLCHAIN local` failures are expected. Use Go 1.25.x for the minimum line or Go 1.26.x for the current tested line before running root and contrib gates. Canonical high-centrality paths These literal paths are kept here so docs index coverage checks can detect when important public docs disappear from navigation: `README.md` `ROADMAP.md` `docs/library-first.md` `docs/minimal-core.md` `docs/core-package-guide.md` `docs/scaffold-first.md` `docs/cli-scaffold-identity.md` `docs/contrib-adapters.md` `docs/getting-started.md` `docs/cookbook.md` `docs/architecture.md` `docs/migration/v3.md` `docs/troubleshooting.md` `docs/security.md` `docs/threat-model.md` `docs/security-review.md` `docs/auth.md` `docs/idempotency.md` `docs/operations.md` `docs/openapi-workflow.md` `docs/configuration.md` `docs/observability.md` `docs/scaffold-support.md` `docs/adapter-maturity.md` `docs/safe-defaults.md` `docs/middleware-safety.md` `docs/input-size-threat-review.md` `docs/testing.md` `docs/site/index.html` `docs/downstream-compatibility.md` `SECURITY.md` `CODE_OF_CONDUCT.md` `docs/metrics.md` `docs/support-policy.md` `docs/dependency-policy.md` `docs/license-policy.md` `docs/dependency-footprint.md` `docs/adr/0001-module-boundaries.md` `VERSIONING.md` `docs/api-inventory.md` `docs/api-review-checklist.md` `docs/api-reference.md` `docs/core-readiness.md` `docs/deprecations.md` `docs/interface-ownership.md` `docs/context-cancellation.md` `docs/errors.md` `docs/concurrency.md` `docs/resource-lifecycle.md` `docs/release-runbook.md` `docs/release-review.md` `docs/audits.md` `docs/openssf-best-practices.md` `docs/release-notes.md` `docs/release-manifests.md` `docs/ports-surface.md` `docs/v3-compatibility-roadmap.md` `docs/production-readiness.md` `docs/governance.md` `docs/performance.md` `docs/dependency-boundary.md` `docs/dependency-risk.md` `docs/package-doc-standard.md` `docs/full-service-scaffold.md` `docs/package-classification.tsv` `docs/supported-adapter-contracts.tsv` `docs/supported-adapter-test-realism.tsv` `docs/contrib-api-drift-packages.txt` `docs/contrib-api-drift-dispositions.tsv` `docs/vulnerability-dispositions.tsv` `contrib/examples/README.md` `examples/reference-saas-api/README.md` `examples/reference-saas-api/deploy/helm/README.md` `examples/reference-saas-api/deploy/kubernetes/README.md` `examples/reference-saas-api/deploy/terraform/aws/README.md` `examples/reference-saas-api/observability/runbooks/observability.md` `examples/reference-saas-api/docs/providers/provider-runbook.md` `PANIC_POLICY.md` and `release-check-summary.json`." + "text": "docs/README.md Documentation Audience: readers who need the fastest path to the right api-toolkit document without scanning the root README. Current Release Identity The verified current root baseline is `v4.0.1`. Documentation Audience: readers who need the fastest path to the right api-toolkit document without scanning the root README. Current Release Identity The verified current root baseline is `v4.0.1`. `v4.0.0` `contrib/v4.0.0` and `contrib/v4.0.1` are withdrawn use the [v4 release-identity incident] release-incident-v4-release-identity.md for the immutable evidence and required paired-contrib recovery path. New users and application developers Document Audience Purpose [Library-first path] library-first.md Existing-service users Add the smallest useful root package set to a `net/http` chi or app-owned router service. [Minimal core path] minimal-core.md Existing-service users Use only `httpx` `binding` `middleware/maxbody` and `middleware/timeout` without contrib or generators. [Core package decision guide] core-package-guide.md Adopters and reviewers Choose packages by use case when-not-to-use guidance stability tier dependency note and example link. [Scaffold-first path] scaffold-first.md New service teams Generate app-owned service code and understand what the toolkit owns versus what the generated app owns. [Contrib adapter path] contrib-adapters.md Adapter adopters Decide when to add supported contrib adapters integrations examples or generator tooling. [CLI and scaffold identity] cli-scaffold-identity.md Adopters and maintainers Decide how CLI scaffold generated-service and library-first identities stay separate. [Stable core charter] stable-core.md New users and maintainers Decide which root packages are the recommended small-core dependency surface and what evidence stable packages need. [Roadmap and non-goals] ../ROADMAP.md Adopters and contributors See current direction candidate work explicit non-goals and proposal rules. [Core readiness matrix] core-readiness.md API consumers and release reviewers Review docs examples tests fuzz benchmark compatibility security review and production caveats for each stable package. [Alternatives] alternatives.md Evaluators Decide when to use `api-toolkit` instead of `net/http` chi oapi-codegen Goa Connect or app-owned helpers. [Getting started] getting-started.md Scaffold users Generate run and verify the production-oriented app-owned service scaffold. [Full service scaffold] full-service-scaffold.md Application teams Understand the `saas-api-full` production foundation support tier and integration-test policy. [Reference service] reference-service.md Maintainers and release reviewers Verify the checked-in `saas-api-full` adoption proof and know which evidence is local Docker-backed or deployment-owned. [Adopter story] adopters.md Evaluators and maintainers Read the maintainer-owned reference-service outcome friction changes and evidence limits without treating it as a customer case study. [Production readiness] production-readiness.md Technical leads and platform owners Decide which surfaces are production-ready supported-adapter experimental caveated or part of the adapter maturity review. [V3 migration guide] migration/v3.md Application teams upgrading dependencies Upgrade root contrib and generated-service adoption paths within the v3 line. [V4 migration guide] migration/v4.md Application teams upgrading major versions Update module paths and replace removed root-port contracts. [Troubleshooting] troubleshooting.md Application developers and maintainers Diagnose Go version contrib tier timeout buffering health idempotency auth and generated-service issues. [Test coverage evidence] test-coverage.md Maintainers and release reviewers Read the coverage gate outputs package-level floor summary and release-evidence relationship. [Package coverage trend] coverage-trend.md Maintainers and release reviewers Compare root and selected contrib package coverage across published releases. [Benchmark baselines] performance.md Maintainers and release reviewers Run and interpret package-level benchmark baselines before performance-sensitive changes or releases. [Coverage hardening backlog] coverage-hardening-backlog.md Maintainers Track behavior-test prerequisites before raising high-risk package coverage floors. [Cookbook] cookbook.md Application developers Complete common API tasks with commands requests expected responses and caveats. [Examples catalog] ../contrib/examples/README.md Developers copying runnable patterns Find each contrib example its command endpoint expected result required env and safety note. [Architecture] architecture.md Developers and maintainers Understand the hexagonal boundary between stable core ports and contrib adapters. The contrib CLI can scaffold the fuller reusable service baseline: Use `--auth jwt` or `--auth clerk` when the generated service should validate bearer tokens via JWKS instead of local API keys. Bearer scaffolds require the matching issuer audience and JWKS URL environment variables extract tenant scope from validated token claims and keep the same tenant mismatch idempotency OpenAPI and admin-route defaults. Generated services wire the default router to the contrib Prometheus recorder so protected `/metrics` includes bounded HTTP request counters and histograms using method route pattern and status labels. Generated services also expose `/version` with build metadata. The generated Makefile `build` target stamps the binary with `VERSION` `BUILD_COMMIT` and `BUILD_DATE` the Dockerfile accepts matching build args and uses `dev`/`unknown` defaults for local builds. Use `--profile dev-api --auth dev-headers` only for local development services that need debug-header authentication. The generated service requires explicit dev-bypass environment variables trusts only configured loopback proxies by default uses separate debug tenant and scope headers and refuses to start with dev-header auth when `ENV production`. The `saas-api-full` profile keeps the lean `saas-api` default intact and starts the heavier Postgres Redis production foundation described in [full-service-scaffold.md] full-service-scaffold.md . The full profile is wired through `bootstrap.NewAPIService` exposes `/livez` separately from `/readyz` keeps detailed health/metrics/pprof on admin routes and enables runtime OpenAPI request validation by default. Reference-service evidence starts at [reference-service.md] reference-service.md and then follows the app-owned docs under `examples/reference-saas-api` including its README deployment starter docs observability runbook and provider workflow runbook. Read the [adopter story] adopters.md for the maintainer-owned outcome and its explicit evidence limits. The same CLI can review OpenAPI artifacts before release. `contracts lint` checks operation IDs non-public security requirements unsafe-write tenant idempotency rate-limit metadata request body metadata documented 2xx success responses Problem Details responses and protected operator paths. `contracts diff` allows additive operations and fails closed on removed operations changed operation IDs removed documented parameters added required parameters removed documented responses request-body tightening or content removal response content removal changed operation or inherited global security requirements component and inline schema removals obvious schema type/required/property/enum narrowing or drift in tenant idempotency rate-limit admin and deprecation route policy metadata: `clients go` emits a stdlib-only Go client package for the supported OpenAPI subset: JSON request bodies path/query/header options API-key auth bearer auth and Problem Details error decoding. The default `raw` style preserves the original operation helpers `--style typed` also generates component schema structs typed request/response methods and raw method escape hatches. The contract and client commands accept OpenAPI 3.1 schema `type` arrays that include `null` and schema-level `examples` normalizing them to the toolkit s compatibility model before validation. `api-toolkit version` prints the tool version Go runtime main module core module version contrib module version and optional build commit/date fields. Use `api-toolkit version --json` for machine-readable release evidence that identifies the installed generator and contract tool. Security operations and runtime behavior Document Audience Purpose [Security posture] security.md Developers and operators Configure secure defaults dangerous bypasses trusted proxies health detail and docs surfaces. [Security threat model] threat-model.md Maintainers application teams and security reviewers Review protected assets assumptions threats mitigations and verification evidence for security-sensitive surfaces. [Package security review] security-review.md Maintainers and reviewers Record threat input secret authorization DoS data-leakage and observability review evidence for each affected package. [Auth production guide] auth.md Developers and operators Configure API-key JWT tenant role JWK rotation clock skew failure modes and auth tests. [Idempotency production guide] idempotency.md Developers and operators Configure storage locking TTL replay semantics request hashes tenant scoping conflicts and Redis/Postgres ownership. [Health and admin operations] operations.md Operators and developers Split public probes from detailed health metrics pprof admin auth network policy and fail-closed checks. [OpenAPI contract workflow] openapi-workflow.md Maintainers and application teams Run route metadata golden diff contract tests generated docs validation and drift handling. [Runtime configuration] configuration.md Operators and developers Review required production env vars defaults unsafe dev defaults and startup validation. [Observability] observability.md Operators and developers Keep metrics logs traces correlation IDs and dashboards useful and redaction-safe. [Scaffold support matrix] scaffold-support.md Generated service teams Understand what generated code is supported app-owned fragile on regeneration and migration-owned. [Adapter maturity matrix] adapter-maturity.md Contrib adopters Review supported/tested/experimental posture for Postgres Redis Stripe Resend Clerk OpenTelemetry CORS validation and related adapters. [Safe defaults audit] safe-defaults.md Developers and reviewers Check fail-open and fail-closed behavior for root and contrib middleware before broad rollout. [Middleware safety matrix] middleware-safety.md Developers and reviewers Decide which middleware is safe globally route-specific forbidden for streaming or requires opt-outs. [Input-size threat review] input-size-threat-review.md Developers reviewers and operators Review header body JSON query multipart replay-capture and timeout-capture size limits before changing route contracts. [Negative-path test matrix] negative-path-test-matrix.tsv Maintainers and release reviewers Verify stable-package tests for malformed input missing headers bad content types invalid auth invalid tenant oversized bodies and invalid query limits. [Testing policy] testing.md Maintainers and release reviewers Keep tests deterministic with fake clocks injected sleep bounded retries and documented deadlock guards. [Security policy] ../SECURITY.md Security reporters and release consumers Report vulnerabilities and understand supported release security handling. [Security advisory drill] security-advisory-drill.md Maintainers and security reviewers Review the completed fictional private-advisory drill and disclosure process. [Code of conduct] ../CODE_OF_CONDUCT.md Contributors and maintainers Set expectations for respectful project participation and conduct reporting. [Panic policy] ../PANIC_POLICY.md Maintainers and API designers Decide when panics are allowed and how HTTP recovery behaves. [Metrics] metrics.md Operators and developers Use low-cardinality HTTP metric names and labels. [Support policy] support-policy.md Adopters and maintainers Understand the supported Go line platform gate and generated-service ownership limits. [Dependency boundary] dependency-boundary.md Maintainers Keep root stable code free of contrib adapter dependencies. [Auth dependency split decision] auth-dependency-split.md Adopters and maintainers Understand the v3-era JWT/JWK module graph cost and the v4 target for auth-heavy packages. [Provider adapter split decision] provider-adapter-split.md Adopters and maintainers Keep Postgres Redis Stripe Resend OpenTelemetry router and provider adapters out of stable core. [Extension module assessment] extension-module-assessment.md Maintainers and release reviewers Reject speculative provider-module splits until adoption ownership dependency and release-cadence evidence supports one. [Dependency policy] dependency-policy.md Maintainers Review allowed dependency classes banned patterns update SLA and security-sensitive review gates. [License policy] license-policy.md Maintainers Review allowed dependency licenses dependency-review enforcement and exception handling. [Dependency risk] dependency-risk.md Release reviewers and security maintainers Review imported-but-not-called vulnerability disposition and ownership. [Dependency footprint] dependency-footprint.md Adopters and release reviewers Run and interpret root/contrib dependency footprint and base-ref diff reports. Stability compatibility and package docs Document Audience Purpose [Versioning] ../VERSIONING.md API consumers and maintainers Define the stable core API surface and contrib compatibility policy. [Public API inventory] api-inventory.md API consumers and maintainers Review generated exported symbols grouped by package stability tier added version and deprecation status. [API reference index] api-reference.md API consumers Jump from each stable or compatibility-only root package to pkg.go.dev and its compile-checked example. [Generated API docs site] site/index.html API consumers Search package status examples compatibility docs and migration guides from a static generated site. [Downstream compatibility kit] downstream-compatibility.md API consumers Run experimental `compatkit` service checks against an in-process handler or explicit base URL. [API review checklist] api-review-checklist.md Maintainers Review naming zero values context cancellation errors concurrency options return types and interface necessity. [Governance] governance.md Maintainers Review stable API review board process branch protection CODEOWNERS required checks release approval and maintainer succession policy. [API addition example exceptions] api-addition-exceptions.tsv Maintainers Record exact symbol exceptions when a new stable exported identifier has a doc comment and release note but a compile-checked example would mislead. [Deprecation policy] deprecations.md Maintainers and release reviewers Track deprecation format replacements removal horizon migration snippets and release-note requirements. [Interface ownership] interface-ownership.md Maintainers Document whether exported interfaces are user-implemented adapter-owned test-only or compatibility-sensitive. [Options struct audit] options-structs.md Maintainers Review defaults validation behavior zero-value behavior and example evidence for stable exported options structs. [Global state audit] global-state-audit.md Maintainers Review package-level globals in stable packages and the limited mutable-state exceptions. [Context and cancellation] context-cancellation.md Maintainers and adopters Apply context propagation and bounded cleanup rules across HTTP auth idempotency scheduler and client APIs. [Error taxonomy] errors.md Maintainers and API consumers Match sentinel typed field wrapped configuration and Problem Details errors safely. [Concurrency safety] concurrency.md API consumers and maintainers Decide which values are immutable request-scoped synchronized or implementation-owned. [Resource lifecycle] resource-lifecycle.md Maintainers and adopters Track ownership for close shutdown timers goroutines stores adapters and generated service resources. [Ports surface] ports-surface.md Maintainers and advanced API consumers Identify compatibility-sensitive port history and preferred replacements. [Ports export exceptions] ports-export-exceptions.tsv Maintainers Review the accepted ADR required for any new root `ports` export. [V3 compatibility record] v3-compatibility-roadmap.md Maintainers Track completed v3 cleanup decisions and remaining compatibility-sensitive guardrails. [V4 scope cleanup plan] v4-plan.md Maintainers and advanced adopters Plan which root surfaces to keep stable demote split or remove only in a future major release. [Ports v4 migration ledger] ports-v4-migration-ledger.tsv Maintainers and advanced adopters Record every current root-port export consumer packages implementation evidence v3 deprecation status and v4 disposition. [Package doc standard] package-doc-standard.md Maintainers Apply the minimum package-doc template and see the placeholder inventory remediated in this pass. [Package classification guide] package-classification.md Maintainers and adopters Read the rendered status glossary before using the TSV source of truth. [Core readiness matrix] core-readiness.md API consumers and release reviewers Review stable package readiness by docs examples tests fuzz benchmark compatibility security review and production caveat. [Module-boundary ADR] adr/0001-module-boundaries.md Maintainers Record the v3 decision to keep root and contrib modules while deferring deeper splits to v4 planning. `docs/package-classification.tsv` Maintainers and automation Machine-readable API and test-status classification for every package. `docs/package-owners.tsv` Maintainers and automation Machine-readable maintainer owner test owner stability tier and release-blocker status for every package. `docs/supported-adapter-contracts.tsv` Maintainers and automation Machine-readable behavior contracts and evidence paths for supported contrib adapters. `docs/supported-adapter-test-realism.tsv` Maintainers and automation Machine-readable default and scheduled/manual test-realism evidence for each supported contrib adapter. Release and evidence Document Audience Purpose [Production-grade 9/10 roadmap] roadmap/production-grade-9x.md Maintainers and program owners Track the prioritized remediation program its dependencies acceptance criteria and closure rules. [Production-grade scorecard] roadmap/scorecard.tsv Maintainers and reviewers Track evidence-based baseline target owner and review status for the eight production-readiness areas. [Audit and scratch archive policy] audits.md Maintainers and release reviewers Keep local `.audits` and `.trash` scratch material out of tracked release evidence. [OpenSSF Best Practices gap review] openssf-best-practices.md Maintainers and release reviewers Track Best Practices badge readiness unclaimed status and remaining gaps before publishing a badge. [V4 release-identity incident] release-incident-v4-release-identity.md V4 consumers and release reviewers Follow the current safe action while the v4 tag history and checksum mismatch are reconciled. [Release runbook] release-runbook.md Release operators Command source of truth for local checks release evidence artifact verification and baseline policy. [Release provenance] provenance.md Release consumers and reviewers Verify GitHub artifact provenance understand the attested asset scope and apply the documented trust limits. [Reproducible build status] reproducible-builds.md Release consumers and maintainers Distinguish unsupported binary reproducibility from the checksums signatures and provenance verified for release assets. [Release review checklist] release-review.md Release reviewers Short path through summary fields manifests dirty-tree decisions artifacts and release notes. [Governance] governance.md Maintainers Branch protection CODEOWNERS tag protection required checks and release approval expectations. `docs/required-checks.json` Maintainers and automation Canonical check names workflow/job identities GitHub App bindings owners and PR/release classifications for protected quality gates. [Changelog] ../CHANGELOG.md Release consumers Concise user-facing history for published releases. [Release notes] release-notes.md Release consumers and maintainers Dated behavior changes upgrade notes and package-tied contrib drift acknowledgements. [Release manifests] release-manifests.md Release reviewers and maintainers Human guide for package classification contrib drift contrib dispositions and vulnerability dispositions. `docs/contrib-api-drift-packages.txt` Maintainers and automation Selected contrib packages reviewed by drift checks supported-adapter incompatible drift is gate-enforced. `docs/supported-adapter-contracts.tsv` Maintainers and automation Required supported-adapter behavior contracts with direct-test and release-drift evidence. `docs/supported-adapter-test-realism.tsv` Maintainers and automation Required supported-adapter realism rows that distinguish direct-unit fake DB miniredis hermetic fixture and scheduled/manual real-service evidence. `docs/contrib-api-drift-dispositions.tsv` Release reviewers and automation Owner status review date expiry and acknowledgement for current contrib drift. `docs/vulnerability-dispositions.tsv` Release reviewers and automation Owner review expiry and upgrade trigger rows for imported-only vulnerability IDs when present. `release-check-summary.json` Release reviewers Generated local release evidence summary only clean publication evidence is publishable. Documentation quality workflow Use the narrowest check that matches the change: Change type Preferred command Notes Documentation-only edits `GOTOOLCHAIN local make docs-check` Runs documentation contracts generated docs-site drift checks getting-started build extraction API/docs policy checks and release evidence parser contracts. Architecture or dependency-boundary edits `GOTOOLCHAIN local make dependency-boundary-check` Runs the stable-core import boundary check before the broader docs gate. V3 cleanup readiness `GOTOOLCHAIN local make v3-readiness-check` Runs focused compatibility-sensitive surface guardrails for major-version cleanup planning and release-note requirements. Docs plus ordinary code changes `GOTOOLCHAIN local make fast-check` Runs `docs-check` and unit tests without rewriting files. Reference service coverage `GOTOOLCHAIN local make reference-service-coverage` Records non-Docker generated-service coverage under `.ci-result/coverage/` without folding app-owned code into toolkit coverage thresholds. Reference service load `GOTOOLCHAIN local make reference-service-load` Records non-Docker generated-service latency throughput memory allocation and expected auth-failure evidence under `.ci-result/reference-service-load/`. Generated full-profile soak `GOTOOLCHAIN local make generated-soak-check` Records nightly-style generated `saas-api-full` race/goroutine soak evidence and repeated Docker integration-cycle logs under `.ci-result/generated-soak/`. Generated full-profile failure `GOTOOLCHAIN local make generated-failure-check` Records generated `saas-api-full` Redis-down Postgres-down expired API-key bad JWKS and slow downstream timeout evidence under `.ci-result/generated-failure/`. Timeout determinism `GOTOOLCHAIN local make timeout-determinism-check` Repeats the hard-timeout late-write test under normal and race runs then runs the root timeout/idempotency/rate-limit/scheduler race subset. Reviewer or audit pass `GOTOOLCHAIN local make audit-check` Non-mutating reviewer gate with lint vuln gosec build smoke GitHub Actions pin audit docs contracts tests race and fuzz smoke. Generated files examples scripts package docs or repo-wide contracts `GOTOOLCHAIN local make finalize` when practical Installs tools and may rewrite Go formatting and module files through `fmt` and `tidy` avoid it in shared dirty worktrees unless that mutation is intended. Do not treat `make finalize` as release evidence. Release publication evidence is owned by [release-runbook.md] release-runbook.md . If the local Go version is older than Go 1.25.x `GOTOOLCHAIN local` failures are expected. Use Go 1.25.x for the minimum line or Go 1.26.x for the current tested line before running root and contrib gates. Canonical high-centrality paths These literal paths are kept here so docs index coverage checks can detect when important public docs disappear from navigation: `README.md` `ROADMAP.md` `docs/library-first.md` `docs/minimal-core.md` `docs/core-package-guide.md` `docs/scaffold-first.md` `docs/cli-scaffold-identity.md` `docs/contrib-adapters.md` `docs/getting-started.md` `docs/cookbook.md` `docs/architecture.md` `docs/migration/v3.md` `docs/troubleshooting.md` `docs/security.md` `docs/threat-model.md` `docs/security-review.md` `docs/auth.md` `docs/idempotency.md` `docs/operations.md` `docs/openapi-workflow.md` `docs/configuration.md` `docs/observability.md` `docs/scaffold-support.md` `docs/adapter-maturity.md` `docs/safe-defaults.md` `docs/middleware-safety.md` `docs/input-size-threat-review.md` `docs/testing.md` `docs/site/index.html` `docs/downstream-compatibility.md` `SECURITY.md` `CODE_OF_CONDUCT.md` `docs/metrics.md` `docs/support-policy.md` `docs/dependency-policy.md` `docs/license-policy.md` `docs/dependency-footprint.md` `docs/adr/0001-module-boundaries.md` `VERSIONING.md` `docs/api-inventory.md` `docs/api-review-checklist.md` `docs/api-reference.md` `docs/core-readiness.md` `docs/deprecations.md` `docs/interface-ownership.md` `docs/context-cancellation.md` `docs/errors.md` `docs/concurrency.md` `docs/resource-lifecycle.md` `docs/release-runbook.md` `docs/release-review.md` `docs/audits.md` `docs/openssf-best-practices.md` `docs/release-notes.md` `docs/release-manifests.md` `docs/ports-surface.md` `docs/v3-compatibility-roadmap.md` `docs/production-readiness.md` `docs/governance.md` `docs/performance.md` `docs/dependency-boundary.md` `docs/dependency-risk.md` `docs/package-doc-standard.md` `docs/full-service-scaffold.md` `docs/package-classification.tsv` `docs/supported-adapter-contracts.tsv` `docs/supported-adapter-test-realism.tsv` `docs/contrib-api-drift-packages.txt` `docs/contrib-api-drift-dispositions.tsv` `docs/vulnerability-dispositions.tsv` `contrib/examples/README.md` `examples/reference-saas-api/README.md` `examples/reference-saas-api/deploy/helm/README.md` `examples/reference-saas-api/deploy/kubernetes/README.md` `examples/reference-saas-api/deploy/terraform/aws/README.md` `examples/reference-saas-api/observability/runbooks/observability.md` `examples/reference-saas-api/docs/providers/provider-runbook.md` `PANIC_POLICY.md` and `release-check-summary.json`." }, { "title": "api-toolkit", diff --git a/docscheck/contract_test.go b/docscheck/contract_test.go index ac5c678..9545f52 100644 --- a/docscheck/contract_test.go +++ b/docscheck/contract_test.go @@ -3313,7 +3313,7 @@ func TestDependencyReviewWorkflowEnforcesSupplyChainPolicy(t *testing.T) { } } for _, required := range []string{ - "dependency-review / dependency-review", + "`dependency-review`", "high or critical vulnerable dependencies", "configured license policy", } { @@ -7264,18 +7264,19 @@ func TestQualityAuditP0EvidenceAndProcessDocs(t *testing.T) { governance := readText(t, filepath.Join(repoRoot, "docs", "governance.md")) for _, required := range []string{ - "ci / test", + "test (1.25.x)", + "test (1.26.x)", "make coverage-check", "make test-race", "make vuln", - "ci / lint", - "ci / governance", + "`lint`", + "`governance`", "make docs-check", "make v3-readiness-check", - "ci / api-check", + "`api-check (...)`", "make release-api-check", - "ci / fuzz", - "dependency-review / dependency-review", + "`fuzz`", + "`dependency-review`", "sole-maintainer repository", "CodeQL `code_scanning` ruleset", "codeql", diff --git a/scripts/github_governance_check.sh b/scripts/github_governance_check.sh index e5a796e..4f0e1b9 100755 --- a/scripts/github_governance_check.sh +++ b/scripts/github_governance_check.sh @@ -3,6 +3,7 @@ set -euo pipefail repo="${GITHUB_REPOSITORY:-aatuh/api-toolkit}" branch="${GITHUB_DEFAULT_BRANCH:-master}" +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if ! command -v gh >/dev/null 2>&1; then echo "github-governance-check: gh is not installed; skipping optional governance verification" @@ -12,15 +13,51 @@ if ! gh auth status >/dev/null 2>&1; then echo "github-governance-check: gh is not authenticated; skipping optional governance verification" exit 0 fi +if ! command -v jq >/dev/null 2>&1; then + echo "github-governance-check: jq is required when gh is authenticated" >&2 + exit 2 +fi +if ! command -v git >/dev/null 2>&1; then + echo "github-governance-check: git is required when gh is authenticated" >&2 + exit 2 +fi -fail=0 -require_jq() { - if ! command -v jq >/dev/null 2>&1; then - echo "github-governance-check: jq is required when gh is authenticated" >&2 - exit 2 +if [[ ! "$repo" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]]; then + echo "github-governance-check: GITHUB_REPOSITORY must be an owner/repository pair" >&2 + exit 2 +fi +repo_owner="${repo%%/*}" +repo_name="${repo#*/}" +if [[ "$repo_owner" == "." || "$repo_owner" == ".." || "$repo_name" == "." || "$repo_name" == ".." ]]; then + echo "github-governance-check: GITHUB_REPOSITORY contains an invalid path segment" >&2 + exit 2 +fi +if [ "${#branch}" -gt 255 ] || ! git check-ref-format --branch "$branch" >/dev/null 2>&1; then + echo "github-governance-check: GITHUB_DEFAULT_BRANCH is not a valid branch name" >&2 + exit 2 +fi +branch_encoded="$(jq -nr --arg value "$branch" '$value | @uri')" + +fetch_json() { + local endpoint="$1" + local description="$2" + local response + if ! response="$(gh api --method GET "$endpoint" 2>/dev/null)"; then + echo "FAIL $description: authenticated GitHub API request failed" >&2 + return 1 + fi + if [ "${#response}" -gt 1048576 ]; then + echo "FAIL $description: GitHub API response exceeds 1 MiB" >&2 + return 1 + fi + if ! printf '%s' "$response" | jq -e . >/dev/null 2>&1; then + echo "FAIL $description: GitHub API returned malformed JSON" >&2 + return 1 fi + printf '%s' "$response" } +fail=0 check_true() { local name="$1" local value="$2" @@ -32,36 +69,47 @@ check_true() { fi } -require_jq +"$script_dir/required_checks_verify.sh" -branch_json="$(gh api "repos/$repo/branches/$branch" 2>/dev/null || true)" -if [ -z "$branch_json" ]; then - echo "FAIL branch protection: unable to read repos/$repo/branches/$branch" >&2 +branch_json="$(fetch_json "repos/$repo_owner/$repo_name/branches/$branch_encoded" "branch protection")" || exit 1 +if ! printf '%s' "$branch_json" | jq -e 'type == "object" and (.protected | type == "boolean")' >/dev/null; then + echo "FAIL branch protection: response shape is invalid" >&2 exit 1 fi - check_true "branch protected" "$(printf '%s' "$branch_json" | jq -r '.protected == true')" -protection_json="$(gh api "repos/$repo/branches/$branch/protection" 2>/dev/null || true)" -if [ -z "$protection_json" ]; then - echo "FAIL branch protection details" >&2 - exit 1 +protection_json="$(fetch_json "repos/$repo_owner/$repo_name/branches/$branch_encoded/protection" "branch protection details")" || exit 1 +if ! printf '%s' "$protection_json" | "$script_dir/required_checks_verify.sh" --branch-protection -; then + fail=1 fi - check_true "required status checks enabled" "$(printf '%s' "$protection_json" | jq -r '.required_status_checks != null')" +check_true "required status checks use strict branch updates" "$(printf '%s' "$protection_json" | jq -r '.required_status_checks.strict == true')" check_true "admin enforcement enabled" "$(printf '%s' "$protection_json" | jq -r '.enforce_admins.enabled == true')" check_true "linear history enabled" "$(printf '%s' "$protection_json" | jq -r '.required_linear_history.enabled == true')" check_true "force pushes disabled" "$(printf '%s' "$protection_json" | jq -r '.allow_force_pushes.enabled == false')" check_true "deletions disabled" "$(printf '%s' "$protection_json" | jq -r '.allow_deletions.enabled == false')" -rulesets_json="$(gh api "repos/$repo/rulesets?includes_parents=true" 2>/dev/null || printf '[]')" -rulesets_detail="$( +rulesets_json="$(fetch_json "repos/$repo_owner/$repo_name/rulesets?includes_parents=true&per_page=100" "repository rulesets")" || exit 1 +if ! printf '%s' "$rulesets_json" | jq -e ' + type == "array" and + length > 0 and + length <= 100 and + all(.[]; (.id | type == "number" and floor == . and . > 0)) and + ([.[].id] | unique | length) == length +' >/dev/null; then + echo "FAIL repository rulesets: response shape is invalid" >&2 + exit 1 +fi + +rulesets_detail="$({ printf '[' first=1 while IFS= read -r ruleset_id; do - [ -n "$ruleset_id" ] || continue - detail="$(gh api "repos/$repo/rulesets/$ruleset_id" 2>/dev/null || true)" - [ -n "$detail" ] || continue + detail="$(fetch_json "repos/$repo_owner/$repo_name/rulesets/$ruleset_id" "ruleset detail")" || exit 1 + if ! printf '%s' "$detail" | jq -e 'type == "object"' >/dev/null; then + echo "FAIL ruleset detail: response shape is invalid" >&2 + exit 1 + fi if [ "$first" -eq 0 ]; then printf ',' fi @@ -69,7 +117,8 @@ rulesets_detail="$( printf '%s' "$detail" done < <(printf '%s' "$rulesets_json" | jq -r '.[].id') printf ']' -)" +})" || exit 1 + master_ref="refs/heads/$branch" check_true "sole-maintainer pull request gate configured" "$(printf '%s' "$rulesets_detail" | jq -r --arg ref "$master_ref" '[.[] | select(.target == "branch" and (.conditions.ref_name.include | index($ref))) | .rules[]? | select(.type == "pull_request") | select(.parameters.required_approving_review_count == 0 and .parameters.require_code_owner_review == false and .parameters.require_last_push_approval == false and .parameters.required_review_thread_resolution == true)] | length > 0')" check_true "master rulesets have no bypass actors" "$(printf '%s' "$rulesets_detail" | jq -r --arg ref "$master_ref" '[.[] | select(.target == "branch" and (.conditions.ref_name.include | index($ref)))] | length > 0 and all(.[]; (.bypass_actors | length) == 0)')" diff --git a/scripts/release_check_summary.sh b/scripts/release_check_summary.sh index 049681b..565606f 100755 --- a/scripts/release_check_summary.sh +++ b/scripts/release_check_summary.sh @@ -103,6 +103,7 @@ check_names=( "vuln" "gosec" "ci-build-smoke" + "required-checks-verify" "release-api-check" "contrib-api-drift-report" "contrib-release-notes-check" @@ -116,6 +117,7 @@ check_names=( "test" "test-race" "fuzz" + "mutation-check" "clean" ) check_commands=( @@ -124,6 +126,7 @@ check_commands=( "make vuln" "make gosec" "make ci-build-smoke" + "make required-checks-verify" "make release-api-check" "make contrib-api-drift-report" "make contrib-release-notes-check" @@ -137,6 +140,7 @@ check_commands=( "make test" "make test-race" "make fuzz" + "make mutation-check" "make clean" ) diff --git a/scripts/required_checks_verify.sh b/scripts/required_checks_verify.sh new file mode 100755 index 0000000..6bc315e --- /dev/null +++ b/scripts/required_checks_verify.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env bash +set -euo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repo_root="$(cd "$script_dir/.." && pwd)" +manifest="$repo_root/docs/required-checks.json" + +usage() { + echo "usage: required_checks_verify.sh [--branch-protection -]" >&2 + exit 2 +} + +branch_mode=false +case "$#" in + 0) + ;; + 2) + if [ "$1" != "--branch-protection" ] || [ "$2" != "-" ]; then + usage + fi + branch_mode=true + ;; + *) + usage + ;; +esac + +if ! command -v jq >/dev/null 2>&1; then + echo "required-checks: jq is required" >&2 + exit 2 +fi +if [ ! -f "$manifest" ]; then + echo "required-checks: manifest is missing: docs/required-checks.json" >&2 + exit 1 +fi + +if ! jq -e ' + def bounded_text($maximum): + . as $value | + ($value | type) == "string" and + ($value | length) > 0 and + ($value | length) <= $maximum and + ($value | explode | all(. >= 32 and . != 127)) and + $value == ($value | sub("^\\s+"; "") | sub("\\s+$"; "")); + type == "array" and + length > 0 and + all(.[ ]; + keys == [ + "app_id", + "check_name", + "job_id", + "job_name", + "owner", + "required_for_pr", + "required_for_release", + "workflow_file" + ] and + (.check_name | bounded_text(200)) and + (.workflow_file | type == "string" and test("^\\.github/workflows/[A-Za-z0-9][A-Za-z0-9._-]*\\.ya?ml$")) and + (.job_id | type == "string" and test("^[A-Za-z0-9][A-Za-z0-9_-]*$")) and + (.job_name | bounded_text(200)) and + (.app_id | type == "number" and floor == . and . > 0) and + (.required_for_pr | type == "boolean") and + (.required_for_release | type == "boolean") and + (.required_for_pr or .required_for_release) and + (.owner | type == "string" and test("^[a-z0-9][a-z0-9-]*$")) + ) and + (map(.check_name) | unique | length) == length and + any(.[ ]; .required_for_pr) and + any(.[ ]; .required_for_release) +' "$manifest" >/dev/null; then + echo "required-checks: manifest schema, path, identity, or ownership validation failed" >&2 + exit 1 +fi + +workflow_job_name() { + local workflow_path="$1" + local job_id="$2" + awk -v wanted="$job_id" ' + $0 == " " wanted ":" { + in_job = 1 + next + } + in_job && $0 ~ /^ [A-Za-z0-9][A-Za-z0-9_-]*:[[:space:]]*$/ { + exit + } + in_job && $0 ~ /^ name:[[:space:]]*/ { + sub(/^ name:[[:space:]]*/, "") + print + exit + } + ' "$workflow_path" +} + +while IFS=$'\t' read -r workflow job_id expected_job_name; do + workflow_path="$repo_root/$workflow" + if [ ! -f "$workflow_path" ]; then + echo "required-checks: workflow is missing: $workflow" >&2 + exit 1 + fi + actual_job_name="$(workflow_job_name "$workflow_path" "$job_id")" + if [ -z "$actual_job_name" ]; then + echo "required-checks: $workflow is missing explicit job $job_id with a stable name" >&2 + exit 1 + fi + if [ "$actual_job_name" != "$expected_job_name" ]; then + echo "required-checks: $workflow job $job_id name is '$actual_job_name'; manifest expects '$expected_job_name'" >&2 + exit 1 + fi +done < <(jq -r 'unique_by(.workflow_file + "\u0000" + .job_id + "\u0000" + .job_name)[] | [.workflow_file, .job_id, .job_name] | @tsv' "$manifest") + +manifest_count="$(jq 'length' "$manifest")" +echo "required-checks: verified $manifest_count manifest identities and workflow job names" + +if [ "$branch_mode" != true ]; then + exit 0 +fi + +protection_json="$(cat)" +if [ "${#protection_json}" -gt 1048576 ]; then + echo "required-checks: branch-protection response exceeds 1 MiB" >&2 + exit 1 +fi +if ! printf '%s' "$protection_json" | jq -e ' + def safe_context: + . as $value | + ($value | type) == "string" and + ($value | length) > 0 and + ($value | length) <= 200 and + ($value | explode | all(. >= 32 and . != 127)); + type == "object" and + (.required_status_checks | type == "object") and + (.required_status_checks.strict | type == "boolean") and + (.required_status_checks.checks | type == "array") and + all(.required_status_checks.checks[]; + type == "object" and + (.context | safe_context) and + (.app_id | type == "number" and floor == . and . > 0) + ) +' >/dev/null 2>&1; then + echo "required-checks: malformed or unbound branch-protection response" >&2 + exit 1 +fi +if [ "$(printf '%s' "$protection_json" | jq -r '.required_status_checks.strict')" != true ]; then + echo "required-checks: branch protection must require an up-to-date branch" >&2 + exit 1 +fi + +comparison="$(printf '%s' "$protection_json" | jq -c --slurpfile manifest "$manifest" ' + ([$manifest[0][] | select(.required_for_pr) | {context: .check_name, app_id}] | sort_by(.context, .app_id)) as $expected | + ([.required_status_checks.checks[] | {context, app_id}] | sort_by(.context, .app_id)) as $actual | + { + matches: ($expected == $actual), + actual_has_duplicates: (($actual | unique_by(.context, .app_id) | length) != ($actual | length)), + missing: ($expected - $actual), + unexpected: ($actual - $expected), + expected_count: ($expected | length) + } +')" + +if [ "$(printf '%s' "$comparison" | jq -r '.matches and (.actual_has_duplicates | not)')" != true ]; then + printf '%s' "$comparison" | jq -r '.missing[] | "FAIL missing required check \(.context) (app_id=\(.app_id))"' >&2 + printf '%s' "$comparison" | jq -r '.unexpected[] | "FAIL unmanifested required check \(.context) (app_id=\(.app_id))"' >&2 + if [ "$(printf '%s' "$comparison" | jq -r '.actual_has_duplicates')" = true ]; then + echo "FAIL branch protection contains duplicate required-check identities" >&2 + fi + exit 1 +fi + +expected_count="$(printf '%s' "$comparison" | jq -r '.expected_count')" +echo "required-checks: branch protection exactly matches $expected_count app-bound pull-request checks" diff --git a/scripts/required_checks_verify_contract_test.sh b/scripts/required_checks_verify_contract_test.sh new file mode 100755 index 0000000..7c54967 --- /dev/null +++ b/scripts/required_checks_verify_contract_test.sh @@ -0,0 +1,249 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +subject="$repo_root/scripts/required_checks_verify.sh" +governance_subject="$repo_root/scripts/github_governance_check.sh" + +if [ ! -x "$subject" ] || [ ! -x "$governance_subject" ]; then + echo "required-checks contract: executable verifier or governance audit is missing" >&2 + exit 1 +fi + +fixture_root="$(mktemp -d)" +trap 'rm -rf "$fixture_root"' EXIT +mkdir -p "$fixture_root/scripts" "$fixture_root/docs" "$fixture_root/.github/workflows" "$fixture_root/bin" +cp "$subject" "$fixture_root/scripts/required_checks_verify.sh" +cp "$governance_subject" "$fixture_root/scripts/github_governance_check.sh" + +write_workflow() { + cat >"$fixture_root/.github/workflows/ci.yml" <<'YAML' +name: ci +jobs: + test: + name: test (${{ matrix.go-version }}) + runs-on: ubuntu-latest + lint: + name: lint + runs-on: ubuntu-latest + release-preflight: + name: release-preflight + runs-on: ubuntu-latest +YAML +} + +write_renamed_workflow() { + cat >"$fixture_root/.github/workflows/ci.yml" <<'YAML' +name: ci +jobs: + renamed-test: + name: test (${{ matrix.go-version }}) + runs-on: ubuntu-latest + lint: + name: lint + runs-on: ubuntu-latest + release-preflight: + name: release-preflight + runs-on: ubuntu-latest +YAML +} + +write_manifest() { + cat >"$fixture_root/docs/required-checks.json" <<'JSON' +[ + { + "check_name": "test (1.26.x)", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "test", + "job_name": "test (${{ matrix.go-version }})", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "test-engineering" + }, + { + "check_name": "lint", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "lint", + "job_name": "lint", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "build-engineering" + }, + { + "check_name": "release-preflight", + "workflow_file": ".github/workflows/ci.yml", + "job_id": "release-preflight", + "job_name": "release-preflight", + "app_id": 15368, + "required_for_pr": false, + "required_for_release": true, + "owner": "release-engineering" + } +] +JSON +} + +write_protection() { + cat >"$fixture_root/protection.json" <<'JSON' +{ + "required_status_checks": { + "strict": true, + "checks": [ + {"context": "lint", "app_id": 15368}, + {"context": "test (1.26.x)", "app_id": 15368} + ] + } +} +JSON +} + +expect_pass() { + local description="$1" + shift + if ! "$@" >"$fixture_root/stdout" 2>"$fixture_root/stderr"; then + echo "required-checks contract: expected pass: $description" >&2 + cat "$fixture_root/stdout" >&2 + cat "$fixture_root/stderr" >&2 + exit 1 + fi +} + +expect_fail() { + local description="$1" + shift + if "$@" >"$fixture_root/stdout" 2>"$fixture_root/stderr"; then + echo "required-checks contract: expected failure: $description" >&2 + cat "$fixture_root/stdout" >&2 + exit 1 + fi +} + +verify_branch_fixture() { + "$fixture_root/scripts/required_checks_verify.sh" --branch-protection - <"$fixture_root/protection.json" +} + +write_workflow +write_manifest +write_protection +expect_pass "valid local manifest" "$fixture_root/scripts/required_checks_verify.sh" +expect_pass "exact app-bound branch protection" verify_branch_fixture + +write_renamed_workflow +expect_fail "renamed workflow job" "$fixture_root/scripts/required_checks_verify.sh" +write_workflow + +cat >"$fixture_root/docs/required-checks.json" <<'JSON' +[ + { + "check_name": "lint", + "workflow_file": "../ci.yml", + "job_id": "lint", + "job_name": "lint", + "app_id": 15368, + "required_for_pr": true, + "required_for_release": true, + "owner": "build-engineering" + } +] +JSON +expect_fail "non-canonical workflow path" "$fixture_root/scripts/required_checks_verify.sh" + +write_manifest +cat >"$fixture_root/protection.json" <<'JSON' +{"required_status_checks":{"strict":true,"checks":[{"context":"lint","app_id":15368}]}} +JSON +expect_fail "missing required branch check" verify_branch_fixture + +cat >"$fixture_root/protection.json" <<'JSON' +{"required_status_checks":{"strict":true,"checks":[{"context":"lint","app_id":15368},{"context":"test (1.26.x)","app_id":15368},{"context":"stale-check","app_id":15368}]}} +JSON +expect_fail "unmanifested branch check" verify_branch_fixture + +cat >"$fixture_root/protection.json" <<'JSON' +{"required_status_checks":{"strict":true,"checks":[{"context":"lint","app_id":1},{"context":"test (1.26.x)","app_id":15368}]}} +JSON +expect_fail "wrong check app binding" verify_branch_fixture + +cat >"$fixture_root/protection.json" <<'JSON' +{"required_status_checks":{"strict":false,"checks":[{"context":"lint","app_id":15368},{"context":"test (1.26.x)","app_id":15368}]}} +JSON +expect_fail "non-strict branch checks" verify_branch_fixture + +printf '{not-json' >"$fixture_root/protection.json" +expect_fail "malformed provider response" verify_branch_fixture + +expect_fail "unsupported verifier argument" "$fixture_root/scripts/required_checks_verify.sh" --manifest "$fixture_root/docs/required-checks.json" + +cat >"$fixture_root/bin/gh" <<'SH' +#!/usr/bin/env bash +set -euo pipefail + +mode="${GH_FAKE_MODE:-success}" +if [ "${1:-}" = auth ] && [ "${2:-}" = status ]; then + exit 0 +fi +if [ "${1:-}" != api ] || [ "${2:-}" != --method ] || [ "${3:-}" != GET ] || [ "$#" -ne 4 ]; then + exit 2 +fi +if [ "$mode" = unavailable ]; then + exit 1 +fi + +case "$4" in + repos/example/repo/branches/master) + printf '%s' '{"protected":true}' + ;; + repos/example/repo/branches/master/protection) + if [ "$mode" = malformed ]; then + printf '%s' '{"private":"super-secret-provider-payload"' + else + printf '%s' '{"required_status_checks":{"strict":true,"checks":[{"context":"lint","app_id":15368},{"context":"test (1.26.x)","app_id":15368}]},"enforce_admins":{"enabled":true},"required_linear_history":{"enabled":true},"allow_force_pushes":{"enabled":false},"allow_deletions":{"enabled":false}}' + fi + ;; + 'repos/example/repo/rulesets?includes_parents=true&per_page=100') + printf '%s' '[{"id":1},{"id":2}]' + ;; + repos/example/repo/rulesets/1) + printf '%s' '{"id":1,"target":"branch","conditions":{"ref_name":{"include":["refs/heads/master"]}},"bypass_actors":[],"rules":[{"type":"pull_request","parameters":{"required_approving_review_count":0,"require_code_owner_review":false,"require_last_push_approval":false,"required_review_thread_resolution":true}},{"type":"code_scanning","parameters":{"code_scanning_tools":[{"tool":"CodeQL","alerts_threshold":"errors_and_warnings","security_alerts_threshold":"high_or_higher"}]}}]}' + ;; + repos/example/repo/rulesets/2) + printf '%s' '{"id":2,"target":"tag","conditions":{"ref_name":{"include":["refs/tags/v*","refs/tags/contrib/v*"]}},"bypass_actors":[],"rules":[]}' + ;; + *) + exit 1 + ;; +esac +SH +chmod +x "$fixture_root/bin/gh" + +verify_governance_fixture() { + local mode="$1" + GH_FAKE_MODE="$mode" \ + GITHUB_REPOSITORY=example/repo \ + GITHUB_DEFAULT_BRANCH=master \ + PATH="$fixture_root/bin:$PATH" \ + "$fixture_root/scripts/github_governance_check.sh" +} + +verify_invalid_repository() { + GH_FAKE_MODE=success \ + GITHUB_REPOSITORY=../example/repo \ + GITHUB_DEFAULT_BRANCH=master \ + PATH="$fixture_root/bin:$PATH" \ + "$fixture_root/scripts/github_governance_check.sh" +} + +write_workflow +write_manifest +expect_pass "authenticated provider fixture" verify_governance_fixture success +expect_fail "authenticated provider unavailable" verify_governance_fixture unavailable +expect_fail "authenticated provider malformed response" verify_governance_fixture malformed +if grep -Fq 'super-secret-provider-payload' "$fixture_root/stdout" "$fixture_root/stderr"; then + echo "required-checks contract: governance audit disclosed a raw provider payload" >&2 + exit 1 +fi +expect_fail "invalid repository input" verify_invalid_repository + +echo "required-checks contract tests passed"