docs/superpowers/plans/2026-08-10-frontend-x509-review-remediation.md
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Resolve the actionable lint, CodeRabbit, and SonarCloud findings on PR 6028 without changing the approved authentication semantics.
Architecture: Keep certificate evidence immutable for a physical frontend connection, but isolate ASN.1 URI extraction and policy subchecks into small helpers. Keep certificate generation in TAP code while replacing shell command construction with argument-vector process execution. Refactor only the large test flows and policy evaluator flagged on new code.
Tech Stack: C++17, OpenSSL X.509 APIs, nlohmann JSON, RE2, ProxySQL TAP, wexecvp, Python groups.json lint.
require_x509 production behavior remains compiled only under PROXYSQL31 and therefore PROXYSQL40.require_x509.COM_CHANGE_USER reuses immutable evidence from the original TLS handshake and never renegotiates TLS.Files:
test/tap/tests/test_frontend_x509_auth-t.cpptest/tap/tests/test_frontend_x509_passthrough-t.cpptest/tap/groups/groups.jsonInterfaces:
Consumes: existing certificate fixture and isolated TAP runner.
Produces: failing coverage for first-SPIFFE-SAN selection and the trusted-fixture fallback assertion count.
Add a SPIFFE certificate fixture containing two URI SANs and assert that the first SPIFFE URI is the identity used for authentication.
Run the focused PROXYSQL31 TAP against the current implementation and record the expected failure caused by last-match overwrite.
Run python3 test/tap/groups/lint_groups_json.py and record the expected unsorted-key failure.
Exercise the pass-through test with trusted certificate signing unavailable and record the plan mismatch caused by 11 fallback skips.
Files:
include/MySQL_Data_Stream.hlib/mysql_data_stream.cpptest/tap/tests/test_frontend_x509_auth-t.cppInterfaces:
Produces: reset_frontend_certificate_evidence() and bounded first-match SPIFFE URI extraction from ASN1_STRING.
Replace strstr/strdup over ASN.1 storage with ASN1_STRING_get0_data, ASN1_STRING_length, bounded prefix comparison, exact allocation/copy, and explicit NUL termination.
Stop after the first matching SPIFFE URI and reject embedded-NUL URI values.
Reset/free SAN and PROXYSQL31 evidence at data-stream initialization so any future stream reuse cannot retain prior-client evidence.
Rebuild and rerun the focused X.509 TAP until the new first-SAN regression is GREEN.
Files:
lib/MySQL_Protocol.cpptest/tap/tests/test_frontend_x509_auth-t.cpptest/tap/tests/reg_test_3504-change_user-t.cppInterfaces:
Produces: small require_x509 and SPIFFE evaluation helpers used by evaluate_frontend_certificate_policy.
Extract the require_x509 type/evidence check without changing fail-closed results or diagnostics.
Extract the context/type/regex SPIFFE check without changing exact/regex matching.
Replace the new direct free(password) rejection cleanup with cleanse_and_free_password(password); leave pre-existing packet-buffer ownership unchanged.
Clean-build and run the X.509 and COM_CHANGE_USER TAPs in PROXYSQL31.
Files:
test/tap/tests/frontend_x509_test_utils.htest/tap/tests/test_frontend_x509_auth-t.cpptest/tap/tests/test_frontend_x509_passthrough-t.cppInterfaces:
Produces: non-copyable temporary_certificate_directory rooted below REGULAR_INFRA_DATADIR; run_openssl(const std::vector<std::string>&) using wexecvp.
Delete copy and move construction/assignment for the owning temporary-directory class and rename its header guard to a non-reserved identifier.
Build the mkdtemp template beneath the isolated infra data directory passed by the callers.
Replace shell quoting and system() with explicit OpenSSL argument vectors passed to wexecvp, capturing stdout/stderr for diagnostics.
Rebuild and run both X.509 TAP binaries to prove certificate generation and cleanup remain functional.
Files:
test/tap/tests/test_frontend_x509_auth-t.cpptest/tap/tests/test_frontend_x509_passthrough-t.cppInterfaces:
Produces: focused setup/behavior/cleanup helper functions; explicit lambda captures.
Split each flagged main() into setup, behavior-matrix, and cleanup helpers while retaining literal TAP expectations and ordering.
Explicitly capture only the admin connection and command-line object in the two pass-through lambdas.
Change the trusted-fixture fallback from 11 skips to 10 and keep plan(40).
Rerun normal and unavailable-trusted-fixture paths and verify both emit exactly 40 TAP results.
Files:
test/tap/groups/groups.jsondocs/superpowers/plans/2026-08-10-frontend-x509-authentication.mddocs/superpowers/specs/2026-08-10-frontend-x509-proxysql31-gating-design.md if its lint output requires it.Interfaces:
Produces: sorted group keys and valid fenced examples.
Run the groups lint fixer, inspect that it only sorts keys, then rerun lint.
Indent fenced preprocessor examples consistently within their list items and add any missing language tags.
Run the repository Markdown lint command used by CI or the closest locally available equivalent.
Files:
Interfaces:
Produces: fresh Stable and PROXYSQL31 build/test evidence suitable for pushing to PR 6028.
Run git diff --check, groups lint, focused test compilation, and static checks for banned system()/unbounded ASN.1 operations.
Clean-build Stable DEBUG, run the tier-gate and COM_CHANGE_USER regressions, and verify feature symbols remain absent.
Clean-build PROXYSQL31 DEBUG and run frontend X.509, X.509/pass-through, COM_CHANGE_USER, and tier-gate TAPs.
Commit the scoped remediation, push only after verification, and rerun/recheck PR checks; rerun the unrelated Aurora job without modifying cluster code.