v1.5.0 — API Test Suite, Org Migration & Dependency Hardening
v1.5.0 — API Test Suite, Org Migration & Dependency Hardening
Minor release. Ships the comprehensive Python pytest API test suite (#413, PR #432 — 247 tests across 18 modules covering every documented endpoint), completes the GitHub org migration to risk-sentinel (#430), and absorbs a wave of dependency security patches and bumps.
No breaking changes to SPARC user-visible behavior — existing deployments upgrade in place. No new migrations. No new env vars.
Highlights
- Python pytest API test suite — 247 tests, 18 modules, all 95 endpoints. Lives at
tests/api/, runs viauvper repo convention. (#413, PR #432) - GitHub org migration —
Rebel-Raiders/sparc→risk-sentinel/sparc. Coordinated three-repo migration withrisk-sentinel/sparc-iacandrisk-sentinel/sparc-validate. Workflows, cosign identity regex, cross-repo dispatch, docs, wiki, compliance CDEFs all retargeted. (#430, PR #434) - Security patches:
net-imapSTARTTLS-stripping (GHSA-vcgp-9326-pqcp) + CRLF injection (GHSA-75xq-5h9v-w6px, GHSA-hm49-wcqc-g2xg);erbdefense-in-depth onMarshal-loaded ERB instances. jwtmajor bump — 2.10.2 → 3.1.2. Internally compatible with SPARC's single JWT consumer (audit posted on PR #289); new regression spec covers RS256 happy path + 4 rejection paths against an in-memory JWKS.
#413 / PR #432 — API Documentation Review and Automated Testing
Phase 1 — Documentation (closed)
- API inventory —
docs/api/INVENTORY.mdenumerates every endpoint with auth mode, phase, schema status - 100% endpoint doc coverage — every controller action documented under
docs/api/endpoints/ - Postman collection — all 95 endpoints, organized into 12 folders, with prod + local environments
- Procedure doc —
docs/api/SPARC-API-Review-and-Automated-Testing-Procedure.mddescribes the review-and-testing workflow
Phase 2 — Automated Testing (closed)
- Python pytest suite at
tests/api/:- 247 tests across 18 modules
- Every documented endpoint exercised against a live SPARC instance
- Container-based test runner (
tests/api/Dockerfile) for CI portability uv+uv.lockfor reproducible Python toolchain
- Coverage spans: SSP, SAR, SAP, POAM, CDEF, profile, catalog, control mapping, baseline parameters, KSI, federation peers, authoritative sources, back-matter resources, admin credentials, users, authorization boundaries, discovery
- Auth modes parametrized — local, OIDC, hybrid
Phase 2 deliberately stops at contract-style validation (status codes + envelope shapes). The follow-on content-style layer (pydantic schemas, fixtures, round-trip, audit-log assertions, OSCAL schema validation) is tracked under #433 — Phase 12 P1.
#430 / PR #434 — GitHub Org Migration
Coordinated Rebel-Raiders → risk-sentinel transfer over 5/2-5/3, with sparc-iac and sparc-validate migrating in the same window to keep cross-references coherent.
Pre-cutover sweep — 33 files retargeted with no logic changes:
.github/workflows/build-sign-publish.yml— image source/vendor labels; cosign--certificate-identity-regexpretargeted at 3 call sites (Docker Hub, ECR, README example) so signature verification continues post-transfer.github/workflows/security.yml—repository_dispatchtarget retargeted torisk-sentinel/sparc-iac; payloadsource_repoupdated- App code, views, README, all
docs/cross-repo issue links, all 6 wiki pages (incl.PUSH_TO_WIKI.sh), compliance CDEFs (remarksfields only — no control-status changes), tracker docs
Post-cutover — verified end-to-end:
- CI green on
risk-sentinel/sparcafter transfer - All repo-level secrets and variables carried over (
AWS_ACCOUNT_ID,DOCKERHUB_USERNAME,DOCKERHUB_TOKEN,SPARC_IAC_DISPATCH_TOKEN,AWS_ROLE_ARN,AWS_REGION,COMPLIANCE_S3_BUCKET,ECR_REGISTRY) SPARC_IAC_DISPATCH_TOKENrotated to a fine-grained PAT scoped to the new org's repospublish_for_sparc_iaccross-repo dispatch round-tripped end-to-end (S3 upload +repository_dispatchtorisk-sentinel/sparc-iac)- Wiki re-pushed via
wiki/PUSH_TO_WIKI.sh(10 files, +452/-171)
OSCAL prop namespace https://rebel-raiders.io/sparc-validate/v1 confirmed absent from repo (preserved by absence — issue notes it as a stable identifier, not a URL).
Security
| CVE / advisory | Severity | Fix | PR |
|---|---|---|---|
GHSA-vcgp-9326-pqcp — net-imap STARTTLS stripping |
High | net-imap 0.6.3 → 0.6.4 |
#438 |
GHSA-75xq-5h9v-w6px — net-imap CRLF/command injection via Symbol args |
High | same | #438 |
GHSA-hm49-wcqc-g2xg — net-imap CRLF/command injection via attr / storage_limit / RawData |
High | same | #438 |
erb def_method on marshal-loaded ERB instances |
Defense-in-depth | erb 6.0.2 → 6.0.4 |
#410 |
jwt major-version compatibility audit (#289)
jwt 3.x introduces several breaking changes. SPARC's audit:
- Single JWT consumer in app code —
app/controllers/concerns/api_authentication.rb(oneJWT.decode+ oneJWT::JWK::Set.new) - All 3.0/3.1 breaking changes verified safe against SPARC's call patterns:
- "Require explicit algorithm on JWK verify" — already passes
algorithms: ["RS256"] - "Require RSA keys ≥ 2048 bits" — Okta JWKS already meets this minimum
- "Stricter base64 (RFC 4648)" — Okta tokens are RFC-compliant
- ECDSA strictness — n/a (RS256 only)
- Drop HS512256 — n/a
- Marshal-loaded payload access requires verification — already passes
verify=true
- "Require explicit algorithm on JWK verify" — already passes
- New regression spec at
spec/requests/api/v1/oidc_jwt_decode_spec.rb— generates an in-memory RSA keypair, exposes the public key as a JWKS via stubbed Net::HTTP responses, signs an RS256 JWT, and asserts the full decode path throughapi_authentication.rb. Also covers expired / wrong-aud / wrong-iss / wrong-key / unknown-subject rejection paths.
Dependencies
| Gem | From | To | PR |
|---|---|---|---|
jwt |
2.10.2 | 3.1.2 | #289 |
net-imap |
0.6.3 | 0.6.4 | #438 |
rubyzip |
3.2.2 | 3.3.0 | #437 |
aws-sdk-s3 |
1.219.0 | 1.220.0 | #437 |
aws-sdk-rds |
1.310.0 | 1.311.0 | #437 |
bootsnap |
1.23.0 | 1.24.1 | #437 |
faker |
3.6.1 | 3.8.0 | #437 |
erb |
6.0.2 | 6.0.4 | #410 |
aws-sdk-core |
3.244.0 | 3.246.0 | (transitive via #437) |
aws-sdk-kms |
1.123.0 | 1.124.0 | (transitive via #437) |
rubyzip 3.2.2 → 3.3.0 is in-major. The only behavioral change in 3.3.0 is Zip::InputStream refactored to behave more like Ruby IO. SPARC consumers (app/services/ato_package_export_service.rb for Zip::OutputStream, app/services/cci_refresh_service.rb for Zip::File.open, plus indirect via roo for Excel parsing) are unaffected.
Process / Internal
.github/CODEOWNERSadded — admin review now required for non-admin PRs (#435)- Implementation plan reprioritized — Phase 12 active backlog (post-migration test/CI hardening + federation follow-ups) added with priority-ordered issue list (PR #439)
- Known issue: Path-filtered required checks block config/docs PRs (#436) — Phase 12 P0, lands first in the next sprint to remove the admin-merge requirement on trivial PRs
Verification
bundle exec rspec— 2076 examples, 0 failuresbundle exec rubocop— cleanbundle check— Gemfile.lock satisfies Gemfile- CI green on PR #441 before merge
- Post-merge:
gh release create v1.5.0 --target mainagainst the merge commit
Upgrading
git pull
bundle install
bin/rails db:migrate # no-op for v1.5.0 — no migrations
docker compose up --buildOr pull the prebuilt image:
docker pull risksentinel/sparc:1.5.0Contributors
Generated from PR set: @dependabot, repo owner, and Claude Code.
Full Changelog: v1.4.1...v1.5.0