Skip to content

Commit cf386df

Browse files
committed
Harden experiment transport and evidence precision
1 parent 3a09db2 commit cf386df

16 files changed

Lines changed: 1915 additions & 35 deletions

.github/workflows/ci.yml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,23 @@ jobs:
6161
--cov=mrma.core.sender
6262
--cov-report=term-missing
6363
--cov-fail-under=85
64-
- name: Runtime dependency audit
65-
run: python -m pip_audit --requirement requirements-audit.txt
64+
65+
runtime-audit:
66+
strategy:
67+
fail-fast: false
68+
matrix:
69+
python-version: ["3.10", "3.13"]
70+
runs-on: ubuntu-latest
71+
steps:
72+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
73+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
74+
with:
75+
python-version: ${{ matrix.python-version }}
76+
cache: pip
77+
- name: Audit published runtime dependency floor
78+
run: |
79+
python -m pip install --upgrade pip pip-audit
80+
python -m pip_audit --requirement requirements-audit.txt
6681
6782
distribution:
6883
runs-on: ubuntu-latest
@@ -93,7 +108,7 @@ jobs:
93108
/tmp/mrma-wheel/bin/python -m pip check
94109
cd /tmp
95110
/tmp/mrma-wheel/bin/mrma --version
96-
/tmp/mrma-wheel/bin/python -c "from importlib.resources import files; root=files('mrma.schemas'); assert all(root.joinpath(f'experiment-v{v}.schema.json').is_file() for v in (2,3,4)); assert 'site-packages' in str(root)"
111+
/tmp/mrma-wheel/bin/python -c "from importlib.resources import files; root=files('mrma.schemas'); assert all(root.joinpath(f'experiment-v{v}.schema.json').is_file() for v in (2,3,4,5)); assert 'site-packages' in str(root)"
97112
98113
container:
99114
runs-on: ubuntu-latest

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,30 @@
33
All notable changes are documented here. MRMA follows semantic versioning for the CLI and uses an
44
independent version in each machine-readable evidence schema.
55

6+
## Unreleased
7+
8+
### Transport Reproducibility
9+
10+
- Experiment transport now disables HTTPX environment trust by default and supports explicit proxy,
11+
CA bundle, and environment opt-in policies. V5 evidence records TLS and proxy provenance without
12+
exposing credentials, environment values, or file paths.
13+
- Research and forensic assurance disable environment trust and reject disabled TLS unless the
14+
researcher supplies a separate explicit exception.
15+
16+
### Evidence Precision
17+
18+
- Missing, malformed, or conflicting `Content-Type` evidence is no longer assumed to be text.
19+
Unequal bodies remain indeterminate unless an explicit weaker assumption is requested.
20+
- Exact target-specific response fields can be made decision-bearing. Results disclose the full
21+
selected header set, omitted-header risk, and a response-header coverage assurance dimension.
22+
- Experiment evidence advances to strict `mrma.experiment/v5`; published v2, v3, and v4 contracts
23+
remain packaged and immutable.
24+
25+
### Verification
26+
27+
- Added transport secrecy, body eligibility, custom-header, schema-negative, and v4 immutability
28+
regressions. Runtime dependency auditing now runs independently on Python 3.10 and 3.13.
29+
630
## 0.3.5 - 2026-07-14
731

832
### Dependency Contract

README.md

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ across a layered HTTP system, then helps reduce that signal to the smallest resp
77
It is not a generic vulnerability scanner and it does not treat a one-off response difference as
88
a finding.
99

10-
> Status: `0.3.5` research preview. `mrma experiment` has a conservative evidence contract;
10+
> Status: `0.3.5` research preview; `main` targets 0.3.6. `mrma experiment` has a conservative evidence contract;
1111
> legacy survey and minimization commands do not yet share this oracle.
1212
1313
## The flagship workflow
@@ -52,8 +52,9 @@ The result includes:
5252
- the effective normalization policy, state and connection modes, response bound, complete retry
5353
policy, negotiated HTTP versions, and stop reason;
5454
- a multidimensional assurance profile for statistical decisiveness, control stability,
55-
connection independence, state isolation, body completeness, normalization risk, and transport
56-
reproducibility, without a scalar confidence label;
55+
connection independence, state isolation, body completeness, normalization risk, transport
56+
reproducibility, transport integrity, and response-header coverage, without a scalar confidence
57+
label;
5758
- structured limitation codes with severity, scope, explanation, and remediation;
5859
- a short run ID and evidence schema version.
5960

@@ -74,9 +75,9 @@ mrma experiment \
7475
--fail-on any-signal
7576
```
7677

77-
The output declares `mrma.experiment/v4`; exit code `10` means influence and `11` means
78-
inconclusive when selected by `--fail-on`. The strict v4 JSON Schema defines every nested evidence
79-
object and cross-field assurance invariant. Published v2 and v3 schemas remain packaged and
78+
The output declares `mrma.experiment/v5`; exit code `10` means influence and `11` means
79+
inconclusive when selected by `--fail-on`. The strict v5 JSON Schema defines every nested evidence
80+
object and cross-field assurance invariant. Published v2, v3, and v4 schemas remain packaged and
8081
immutable for compatibility. The default exit code remains zero for all verdicts.
8182
The transport is labeled `semantic-http`; MRMA uses `httpx` and does not claim byte-for-byte HTTP/1
8283
wire reproduction.
@@ -85,6 +86,9 @@ Responses are streamed with a default 1 MiB read bound. `--body-storage sample`
8586
KiB per observation. When full normalization cannot be performed, unequal digests are marked
8687
`INDETERMINATE`; they are never silently treated as equivalent. Encoded and non-text bodies use
8788
exact transfer-digest equality only until bounded, content-aware decoders are implemented.
89+
Responses without one unambiguous, well-formed `Content-Type` also use digest-only evidence by
90+
default. `--assume-text-without-content-type` is an explicit weaker assumption and emits a
91+
structured limitation.
8892

8993
Retries are disabled by default. When enabled, every intermediate attempt, outcome class,
9094
error subtype, retry-triggering status, backoff, and final result is recorded. Stable error-subtype
@@ -99,7 +103,10 @@ fingerprint. Response fields use explicit semantics for `Vary`, `Allow`, CORS to
99103
`Cache-Control`, `Location`, and `Content-Location`. HTTP method tokens remain case-sensitive even
100104
when their list order is irrelevant. Duplicate directives or malformed `Cache-Control` syntax
101105
preserve ordered evidence and emit `AMBIGUOUS_CACHE_CONTROL`; captured fields without a registry
102-
rule and `Set-Cookie` remain conservative ordered evidence.
106+
rule and `Set-Cookie` remain conservative ordered evidence. The registry is intentionally
107+
selective: exact target-specific fields can be made decision-bearing with repeatable
108+
`--include-response-header`; the evidence records the complete selected set and an explicit
109+
coverage limitation.
103110

104111
Connection scope is explicit: `reuse` (default), `per-arm`, `per-round`, or `fresh-observation`.
105112
Cookie state remains a separate policy. Wilson intervals assume repeated observations are suitably
@@ -108,8 +115,13 @@ authentication, HTTP/2 state, throttling, or WAF scoring could violate that assu
108115

109116
For publication-oriented work, `--assurance research` authoritatively selects fresh connections,
110117
isolated response state, disabled retries, a 20-round bracketed design, standard privacy, and full
111-
body retention within the configured response bound. `exploratory` preserves efficient pooled
112-
behavior; `forensic` uses research isolation while intentionally retaining exact metadata.
118+
body retention within the configured response bound. It also disables HTTPX environment trust.
119+
Experiment transport ignores proxy and CA environment variables by default; opt in with
120+
`--trust-environment`, or use explicit `--proxy` and `--ca-bundle` inputs. Evidence stores only
121+
keyed proxy/environment fingerprints and the CA bundle digest, never proxy credentials, environment
122+
values, or file paths. Research and forensic presets reject `--insecure` unless the separate
123+
`--allow-insecure-research` exception is supplied and recorded. `exploratory` preserves efficient
124+
pooled behavior; `forensic` uses research isolation while intentionally retaining exact metadata.
113125

114126
JSON output uses atomic replacement. Add `--evidence-write durable` to flush and synchronize the
115127
temporary file before replacement and synchronize the parent directory on platforms that support

RELEASE_CHECKLIST.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
- [ ] `python -m compileall mrma` passes
99
- [ ] wheel and sdist pass `twine check`
1010
- [ ] clean virtualenv installs the built wheel and passes `pip check`
11-
- [ ] `pip-audit` reports no known vulnerable runtime dependency
11+
- [ ] `pip-audit` reports no known vulnerable runtime dependency on Python 3.10 and 3.13
1212
- [ ] CI passes on Python 3.10 and 3.13 across Linux, Windows, and macOS
1313

1414
## Versioning
@@ -20,15 +20,19 @@
2020
- [ ] `mrma config --json` works
2121
- [ ] `mrma run --url https://example.com --follow-redirects` works
2222
- [ ] `mrma experiment` detects a deterministic local mutation
23-
- [ ] `mrma experiment --json` emits schema-valid `mrma.experiment/v4` without decoration
23+
- [ ] `mrma experiment --json` emits schema-valid `mrma.experiment/v5` without decoration
2424
- [ ] cookie state does not cross observations in default isolated mode
2525
- [ ] response limits and transport failures produce typed evidence instead of crashes
2626
- [ ] redirect and retry traces affect verdicts when final responses are identical
2727
- [ ] equivalent redirect targets and parsed response headers do not create false signals
2828
- [ ] method-token case and ambiguous cache-directive order remain decision-bearing
2929
- [ ] ambiguous cache syntax emits `AMBIGUOUS_CACHE_CONTROL`
3030
- [ ] retry error subtypes are decision-bearing while timing remains quantitative context
31-
- [ ] assurance presets, profiles, and structured limitations satisfy v4 cross-field constraints
31+
- [ ] assurance presets, profiles, and structured limitations satisfy v5 cross-field constraints
32+
- [ ] experiment transport ignores environment proxy/CA settings unless explicitly enabled
33+
- [ ] transport evidence fingerprints proxy/CA configuration without exposing values or paths
34+
- [ ] absent or ambiguous `Content-Type` remains digest-only unless explicitly overridden
35+
- [ ] exact included response headers affect decisions and selected scope is machine-readable
3236
- [ ] durable evidence mode syncs the file and the parent directory where supported
3337
- [ ] every connection mode passes its state and pool-isolation tests
3438
- [ ] exit codes `10` and `11` match the documented `--fail-on` policy

docs/ROADMAP.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ adding more mutation families.
5454
- [x] Signed annotated tag verification in every publishing workflow
5555
- [x] Protected release environment and verifiable Python/container provenance
5656

57+
## 0.3.5 - Dependency contract consistency
58+
59+
- [x] Align the Python 3.10 Tomli security floor across package and audit metadata
60+
- [x] Parse and compare published and audited PEP 508 dependency contracts in tests
61+
- [x] Validate Rich 15 and Actions Checkout 7 across the complete quality matrix
62+
63+
## 0.3.6 - Transport and evidence precision
64+
65+
- [x] Disable ambient HTTPX environment configuration for experiments by default
66+
- [x] Record privacy-preserving TLS, CA, proxy, and environment provenance
67+
- [x] Require an explicit exception for disabled TLS under research assurance
68+
- [x] Treat missing or ambiguous `Content-Type` as digest-only evidence by default
69+
- [x] Allow exact target-specific response headers into decision evidence
70+
- [x] Expose selective response-header coverage as a structured limitation and assurance dimension
71+
- [x] Publish strict `mrma.experiment/v5` while preserving v2, v3, and v4 contracts
72+
- [x] Audit runtime dependencies on Python 3.10 and 3.13 independently
73+
5774
## 0.4 - Authorization-first experiment engine
5875

5976
- Enforce an authorization policy before any network operation, including every redirect

0 commit comments

Comments
 (0)