Skip to content

v1.5.0 — API Test Suite, Org Migration & Dependency Hardening

Choose a tag to compare

@clem-field clem-field released this 05 May 00:06

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 via uv per repo convention. (#413, PR #432)
  • GitHub org migrationRebel-Raiders/sparcrisk-sentinel/sparc. Coordinated three-repo migration with risk-sentinel/sparc-iac and risk-sentinel/sparc-validate. Workflows, cosign identity regex, cross-repo dispatch, docs, wiki, compliance CDEFs all retargeted. (#430, PR #434)
  • Security patches: net-imap STARTTLS-stripping (GHSA-vcgp-9326-pqcp) + CRLF injection (GHSA-75xq-5h9v-w6px, GHSA-hm49-wcqc-g2xg); erb defense-in-depth on Marshal-loaded ERB instances.
  • jwt major 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 inventorydocs/api/INVENTORY.md enumerates 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 docdocs/api/SPARC-API-Review-and-Automated-Testing-Procedure.md describes 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.lock for 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-Raidersrisk-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-regexp retargeted at 3 call sites (Docker Hub, ECR, README example) so signature verification continues post-transfer
  • .github/workflows/security.ymlrepository_dispatch target retargeted to risk-sentinel/sparc-iac; payload source_repo updated
  • App code, views, README, all docs/ cross-repo issue links, all 6 wiki pages (incl. PUSH_TO_WIKI.sh), compliance CDEFs (remarks fields only — no control-status changes), tracker docs

Post-cutover — verified end-to-end:

  • CI green on risk-sentinel/sparc after 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_TOKEN rotated to a fine-grained PAT scoped to the new org's repos
  • publish_for_sparc_iac cross-repo dispatch round-tripped end-to-end (S3 upload + repository_dispatch to risk-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-pqcpnet-imap STARTTLS stripping High net-imap 0.6.3 → 0.6.4 #438
GHSA-75xq-5h9v-w6pxnet-imap CRLF/command injection via Symbol args High same #438
GHSA-hm49-wcqc-g2xgnet-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 (one JWT.decode + one JWT::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
  • 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 through api_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/CODEOWNERS added — 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 rspec2076 examples, 0 failures
  • bundle exec rubocop — clean
  • bundle check — Gemfile.lock satisfies Gemfile
  • CI green on PR #441 before merge
  • Post-merge: gh release create v1.5.0 --target main against the merge commit

Upgrading

git pull
bundle install
bin/rails db:migrate    # no-op for v1.5.0 — no migrations
docker compose up --build

Or pull the prebuilt image:

docker pull risksentinel/sparc:1.5.0

Contributors

Generated from PR set: @dependabot, repo owner, and Claude Code.

Full Changelog: v1.4.1...v1.5.0