Changelog
From CHANGELOG.md in the repository root.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
[0.3.1] - 2026-05-22¶
Added¶
- GitHub Pages documentation site (MkDocs Material) at https://tsjnsn.github.io/scpz/.
- Container images published on each GitHub release to GHCR (
ghcr.io/tsjnsn/scpz) and Docker Hub (tsjnsn/scpz), plus a rootDockerfilefor local builds.
Changed¶
- CLI commands renamed to match the v0.3.0 design:
optimize-cmd→optimize,schema→print-schema. - Richer
--help/--versionmessaging, command epilog, and option help text across all commands.
Fixed¶
check-equivalenceaction pattern matching uses case-insensitivefnmatchwith*and?wildcards anywhere in the pattern (IAM semantics).ActionCatalog.iter_full_actions()andall_full_actions()normalize service prefixes to lowercase for consistent catalog-backed checks.
[0.3.0] - 2026-05-22¶
Added¶
- Public documentation site built with MkDocs Material, deployed to GitHub Pages via
.github/workflows/pages.yml(enable Settings → Pages → GitHub Actions on first use). - Official Docker Hub image
tsjnsn/scpz: release workflow pushes tags on each GitHub release (<release tag>pluslatestfor stable releases). - CI job Equivalence golden regression runs
tests/test_golden_regression.py: everyexamples/*.jsonand the NotAction fixtures in that module are optimized then checked withcheck_permission_equivalenceso merges block on accidental permission broadening. scpz check-equivalence before.json after.json— catalog-backed check that the optimized (or other) policy did not broaden permissions versus a baseline:Denycoverage must not shrink andAllowcarve-outs must not grow, grouped by effect, condition fingerprint, and resources.split_if_needed(..., catalog=...)expands oversizedDeny+NotActionstatements using the action catalog: denied atoms are re-encoded as chunkedDeny+Actionlists so split output is permission-equivalent (no list partitioning of exemptions, which would broaden denies).- Opt-in
redundancyEliminatepass: when a non-empty action catalog is configured, wholly redundantDeny+NotActionstatements are removed using the same catalog-backed exemption model asNotActioncompression (exempt(B) ⊆ exempt(A) in the catalog universe). spec.validationinscpz.yamlwith per-rule severities (error,warn,ignore) for wildcard actions, broadResource: "*", missingSid, and unknown service prefixes. Wildcard actions useonWildcardAction: the service-specific part after:must contain*or?to match; the bare action*is excluded. The optimizer andscpz validatehonour these settings from the discovered config file.scpz validate(and pre-optimize validation) cross-checks literalAction/NotActionstrings against the configured AWS action catalog. Unknown actions for a catalogued service usespec.validation.onUnknownCatalogAction(defaultwarn; set toerrorfor strict mode, orignoreto skip).actionCompressapplies catalog-safe wildcard compression toNotActionlists when a non-empty action catalog is configured (same conservative trie andcatalog.coversproofs asAction; aggressive shortening is not used forNotActionbecause wildcards would exempt additional APIs).
Changed¶
- CLI redesign (breaking): flat verb-first commands with hyphenated multi-word names.
optimize-cmd→optimizeschema→print-schemavalidateandcheck-equivalenceunchanged- No backward-compatibility aliases for removed command names
- Normalized
--help/--versionmessaging and option help text --outputis deterministic: only paths ending in.jsonname a single file (existing directories always use directory semantics); otherwise--outputis a directory (<output>/<input>or split shards); when PATH is a directory,--outputmust be a directoryoptimizeapplies the same validation rules asvalidate, checks the optimized document (and each split shard) before any write, exits non-zero when any issue is elevated toerror, and skips backups, in-place writes,--output, and split file writes in that case.validateloads project config per file so it honoursspec.validation(invalidscpz.yamlprints a config error and counts as failure for that path without aborting the whole command).
[0.2.7] - 2026-05-16¶
Fixed¶
- Resolved ruff lint violations (UP037, SIM109, E501) in
actions.pyand tests introduced in v0.2.6.
[0.2.6] - 2026-05-16¶
Changed¶
- Refactored
actions.pyinternals: extracted_bare_prefixhelper, improved_try_shorten_across_verbswith incremental LCP narrowing, hoistedhas_catalogguard, fixed type narrowing for mypy/pyright strict mode. - Fixed inaccurate docstring example in
_shorten_verb_prefix.
[0.2.5] - 2026-05-16¶
Added¶
actionCompressaggressive mode now performs shortest-prefix trimming when a catalog is provided. Each verb-level wildcard is shortened to the minimum prefix at which the catalog confirms no other verb families exist (e.g.guardduty:Delete*→guardduty:Del*,iam:Update*→iam:Upd*). A second cross-verb pass then collapses adjacent shortened wildcards when the catalog confirms the merged prefix is still safe (e.g.svc:Del*+svc:Det*→svc:De*).
Fixed¶
scpz validatewas emitting every constraint warning (statement count, size) twice becausevalidate_filealready runsvalidate_documentinternally, butvalidate_cmdcalled it a second time.
[0.2.3] - 2026-05-16¶
Fixed¶
scpz --versionnow reports the correct installed version; previously always showed0.1.0due to a hardcoded string in__init__.py
[0.2.2] - 2026-05-16¶
Changed¶
- README: fix installation instructions to show
pip install scpz/uv tool install scpzfor consumers - README: add Python 3.13+ requirements section
- README: clarify
.bakbackup filename in optimize comment - README: move developer-only commands (
uv sync --dev, schema regeneration) to Development section