From a05a7d3dad2598e532d08374c502057eaf1b2a0e Mon Sep 17 00:00:00 2001 From: shankar0123 Date: Sun, 3 May 2026 13:31:35 +0000 Subject: [PATCH] ci: fix Phase 1b post-push CI failures (3 guards) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1b push (commit 44a85d6) failed three CI guards. None were caught by `make verify` locally because they're CI-only guards that aren't part of the Makefile target. This commit fixes all three. 1. go.mod tidy diff. The go-jose v4 dep was added with `// indirect` in go.mod after the initial `go get`, but the codebase imports it directly from internal/api/acme/jws.go + service/acme.go + handler/acme.go. CI's `go mod tidy && git diff --exit-code go.mod go.sum` flagged the staleness. Promoted to a direct require in the same `require (...)` block as github.com/aws/aws-sdk-go-v2 etc. 2. G-3-env-docs-drift.sh. The guard greps `\bCERTCTL_[A-Z_]+\b` in docs/ and complains when the bare-prefix forms don't match anything defined in config.go. Phase 1a + 1b's docs/acme-server.md intro and migration header use bare-prefix forms `CERTCTL_ACME_*` and `CERTCTL_ACME_SERVER_*` to describe namespace separation (consumer-side ACMEConfig vs server-side ACMEServerConfig). Same precedent as the existing CERTCTL_SCEP_ + CERTCTL_TLS_ + CERTCTL_QA_* prefix entries already in the guard's ALLOWED list. Added CERTCTL_ACME_ + CERTCTL_ACME_SERVER_ to the ALLOWED list with a justification comment block matching the existing integration-surface allowlist convention. 3. openapi-handler-parity.sh. Distinct from internal/api/router/openapi_parity_test.go (which runs at `go test` time and has its own SpecParityExceptions map I extended in 1a + 1b) — this is a separate CI-only guard that reads api/openapi-handler-exceptions.yaml. The 6 Phase-1a routes + 4 Phase-1b routes (10 ACME endpoints total) were never added to that yaml. Same rationale as the SCEP/SCEP-mTLS entries already in the file: ACME is a JWS-signed-JSON wire protocol per RFC 8555 + RFC 9773, not an OpenAPI-shape REST surface. Documenting every endpoint in openapi.yaml would duplicate the RFC. The canonical reference is docs/acme-server.md. Phases 2-4 will add their routes to this yaml in lockstep with router.go. Verified locally: - bash scripts/ci-guards/G-3-env-docs-drift.sh → clean. - bash scripts/ci-guards/openapi-handler-parity.sh → clean (152 router routes, 136 OpenAPI ops, 18 documented exceptions). - All other ci-guards/*.sh → clean. - go.mod diff after `go mod tidy` is empty. --- api/openapi-handler-exceptions.yaml | 29 +++++++++++++++++++++++++ go.mod | 1 + scripts/ci-guards/G-3-env-docs-drift.sh | 14 +++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/api/openapi-handler-exceptions.yaml b/api/openapi-handler-exceptions.yaml index 6c5e86c..ed8a604 100644 --- a/api/openapi-handler-exceptions.yaml +++ b/api/openapi-handler-exceptions.yaml @@ -25,3 +25,32 @@ documented_exceptions: why: "SCEP-mTLS sibling endpoint, trailing-slash variant." - route: "POST /scep-mtls/" why: "SCEP-mTLS sibling endpoint, trailing-slash POST variant." + + # ACME server (RFC 8555 + RFC 9773 ARI) — wire-protocol surface. + # Like SCEP/EST, ACME is a JWS-signed-JSON wire protocol whose + # semantics are dictated by the RFC, not by an OpenAPI schema. + # Documenting every endpoint in openapi.yaml would duplicate + # RFC 8555 §7.1 + §7.2 + §7.3 with no information gain. The + # canonical operator-facing reference is docs/acme-server.md. + # Phases 2-4 will extend this list as new-order, finalize, authz, + # challenge, cert, key-change, revoke-cert, renewal-info routes land. + - route: "GET /acme/profile/{id}/directory" + why: "ACME server RFC 8555 §7.1.1 directory; documented in docs/acme-server.md." + - route: "HEAD /acme/profile/{id}/new-nonce" + why: "ACME server RFC 8555 §7.2 new-nonce; documented in docs/acme-server.md." + - route: "GET /acme/profile/{id}/new-nonce" + why: "ACME server RFC 8555 §7.2 new-nonce GET form; documented in docs/acme-server.md." + - route: "POST /acme/profile/{id}/new-account" + why: "ACME server RFC 8555 §7.3 new-account (JWS jwk); documented in docs/acme-server.md." + - route: "POST /acme/profile/{id}/account/{acc_id}" + why: "ACME server RFC 8555 §7.3.2 + §7.3.6 (JWS kid) account update + deactivation; documented in docs/acme-server.md." + - route: "GET /acme/directory" + why: "ACME server default-profile shorthand; mirrors per-profile when CERTCTL_ACME_SERVER_DEFAULT_PROFILE_ID is set." + - route: "HEAD /acme/new-nonce" + why: "ACME server default-profile shorthand for new-nonce HEAD." + - route: "GET /acme/new-nonce" + why: "ACME server default-profile shorthand for new-nonce GET." + - route: "POST /acme/new-account" + why: "ACME server default-profile shorthand for new-account." + - route: "POST /acme/account/{acc_id}" + why: "ACME server default-profile shorthand for account update + deactivation." diff --git a/go.mod b/go.mod index 1c3c7e9..b19a20a 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.41.7 github.com/aws/aws-sdk-go-v2/config v1.32.17 github.com/aws/aws-sdk-go-v2/service/acmpca v1.46.14 + github.com/go-jose/go-jose/v4 v4.0.4 github.com/leanovate/gopter v0.2.11 github.com/masterzen/winrm v0.0.0-20250927112105-5f8e6c707321 github.com/pkg/sftp v1.13.10 diff --git a/scripts/ci-guards/G-3-env-docs-drift.sh b/scripts/ci-guards/G-3-env-docs-drift.sh index b629006..233f371 100755 --- a/scripts/ci-guards/G-3-env-docs-drift.sh +++ b/scripts/ci-guards/G-3-env-docs-drift.sh @@ -61,7 +61,9 @@ CERTCTL_TLS_INSECURE_SKIP_VERIFY| CERTCTL_SCEP_| CERTCTL_SERVER_CA_BUNDLE_PATH| CERTCTL_SERVER_TLS_INSECURE_SKIP_VERIFY| -CERTCTL_QA_[A-Z_]+ +CERTCTL_QA_[A-Z_]+| +CERTCTL_ACME_| +CERTCTL_ACME_SERVER_ )$' # ^ The CERTCTL_OPENSSL_* / CERTCTL_STEPCA_* / CERTCTL_WEBHOOK_* / # CERTCTL_ACME_EAB_* / CERTCTL_ACME_DNS_PROPAGATION_WAIT / @@ -70,6 +72,16 @@ CERTCTL_QA_[A-Z_]+ # (script invocations, per-issuer config-blob field names, # per-notifier config-blob field names, demo-stack overrides, # test fixtures) — not server-side env vars in config.go. +# +# CERTCTL_ACME_ + CERTCTL_ACME_SERVER_ are bare-prefix forms +# operator docs use to describe namespace separation between the +# consumer-side ACMEConfig (full names like CERTCTL_ACME_DIRECTORY_URL +# defined in config.go) and the ACME server's CERTCTL_ACME_SERVER_* +# prefix (full names like CERTCTL_ACME_SERVER_ENABLED defined in +# config.go::ACMEServerConfig). The bare prefixes themselves are +# never read by config.go — they're only doc prose — so they +# allowlist alongside the existing CERTCTL_SCEP_ + CERTCTL_TLS_ +# bare-prefix entries. # The audit's "37 docs-only" count over-flagged these; the # closure narrows the gate to the specific drift sites # (renewal-interval rename + 6 config-only) and allowlists