Skip to content

Follow the v1.1 correction through the docs and the Python binding - #59

Merged
blocksifrdev merged 1 commit into
mainfrom
fix/aggregation-v1.1-followthrough
Sep 15, 2026
Merged

blocksifrdev merged 1 commit into
mainfrom
fix/aggregation-v1.1-followthrough

Conversation

@blocksifrdev

Copy link
Copy Markdown
Collaborator

Three things a normative change isn't finished without. Follows #58.

1. The security doc was making a promise the algorithm didn't keep

docs/security.md §3, as a mitigation against a compromised high-volume issuer:

Even if one issuer submits 1000 receipts, it cannot exceed 40% of the aggregate weight.

That was not true of v1.0. Fifty receipts from one issuer reached roughly 87%. Anyone who read that section got an assurance the algorithm did not provide, and §1.1 item 9 ("Single-issuer resistance") rested on the same claim.

Now: the guarantees name the version they hold from, the residual-risk note is corrected (a compromised issuer key could reach ~87%, not 40%), and a dated correction explains what was wrong and points at agg-009, the vector that pins the fixed behaviour.

A security guarantee that silently starts being true is worse than one that says when it started — anyone who deployed on v1.0 and relied on the 40% bound needs to know to re-evaluate.

2. Python carries the normative algorithm too

sdk/python/aggregate.py implements v1.1 step for step. All eleven vectors run against it, plus the property tests. Both bindings now implement the normative algorithm rather than just the JavaScript side.

3. The parity gate covers aggregation

59 checks across both languages now — AGT bridge and trust aggregation, including the capped-issuer case that v1.0 got wrong.

Verified it bites: moving the Python max_issuer_weight to 0.45 fails with

aggregation.dominant-issuer-capped
    js:     [0.52,3]
    python: [0.56,3]

CI compiles and tests the new module.

194 JS tests, 25 Python tests, 59 parity checks.

🤖 Generated with Claude Code

Three things a normative change is not finished without.

1. docs/security.md stated, as a mitigation against a compromised
   high-volume issuer: "Even if one issuer submits 1000 receipts, it
   cannot exceed 40% of the aggregate weight." That was not true of v1.0
   — 50 receipts reached roughly 87% — so anyone who read that section
   received an assurance the algorithm did not provide. The claims now
   name the version they hold from, the residual-risk note is corrected,
   and a dated correction explains what was wrong and points at the
   vector that pins the fixed behaviour. A security guarantee that
   silently starts being true is worse than one that says when it
   started.

2. sdk/python/aggregate.py implements the same algorithm, so both
   bindings carry the normative one rather than only the JavaScript side.
   All eleven vectors run against it.

3. The parity gate now covers aggregation as well as the AGT bridge: 59
   checks across both languages, including the capped-issuer case.
   Verified it catches drift — moving the Python cap to 0.45 fails with
   the divergence named.

CI compiles and tests the new module.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@blocksifrdev
blocksifrdev deployed to protected-execution September 15, 2026 16:17 — with GitHub Actions Active
@blocksifrdev
blocksifrdev merged commit 65ef7a6 into main Sep 15, 2026
4 checks passed
@blocksifrdev
blocksifrdev deleted the fix/aggregation-v1.1-followthrough branch September 15, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant