feat!: upgrade to ALTCHA v3.2.1 and add a strict-CSP mode - #1
Closed
hleroy wants to merge 1 commit into
Closed
Conversation
Upgrade the bundled JS widget from ALTCHA v2.3.0 to v3.2.1 and move the server side from the v1 Proof-of-Work API to the v2 one, raising the altcha requirement to >=2.1.0,<3.0.0. PR aboutcode-org#48 took the altcha v2 package while staying on the *_v1 compatibility functions; this replaces those with the real v2 API, so the widget and the library speak the same KDF-based Proof-of-Work. Challenges and payloads are not compatible across versions. `get_altcha_challenge()` now takes `algorithm` and `cost` in place of `max_number`, driven by the new ALTCHA_ALGORITHM and ALTCHA_COST settings, and `verify_solution()` returns a result object rather than a tuple. Replay protection keys the cache on the challenge signature, as the v3 payload no longer carries a challenge string. Widget side, the v3 options replace the v2 ones. `challengeurl` and `challengejson` are mapped to the unified `challenge` option with a DeprecationWarning; options the widget does not accept as an HTML attribute are collected into the JSON-encoded `configuration` attribute. Add an ALTCHA_STRICT_CSP setting that switches the widget template and the new form Media to the modular /dist_external build: the stylesheet is served as a separate file and the Proof-of-Work workers are loaded from the static files instead of a blob: URL, removing the need for `style-src 'unsafe-inline'` and `worker-src blob:`. The modular build registers no algorithm on its own, so a small altcha-workers.js module wires $altcha.algorithms to the bundled worker scripts. The new asset settings — ALTCHA_JS_STRICT_CSP_URL, ALTCHA_CSS_URL, ALTCHA_WORKERS_REGISTER_URL and ALTCHA_WORKERS_URL — go through the STATIC_URL resolution added in aboutcode-org#45. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01956qnAS7qztaS7tghEKDta
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrades the bundled ALTCHA widget from v2.3.0 to v3.2.1, moves the server side from the v1 Proof-of-Work API to the v2 one, and adds an opt-in strict Content-Security-Policy mode.
Widget: v2.3.0 → v3.2.1
Assets are vendored from the
v3.2.1tag and verified byte-identical against jsDelivr (sha256 match on all 8 files):.ABOUTfiles updated and added for each vendored group.Server: v1 → v2 Proof-of-Work
ALTCHA v3 replaces the v1 hash-matching PoW with a KDF-based one.
create_challenge(algorithm, cost, …)andverify_solution(payload, hmac_secret)replace the*_v1shims introduced in aboutcode-org#48;verify_solutionreturns a result object rather than a(verified, error)tuple, and challenges serialize viato_dict()rather than__dict__. Thealtcharequirement moves to>=2.1.0,<3.0.0.Replay protection now keys the cache on the challenge signature — an HMAC over parameters that include a random nonce and salt — because the v3 payload no longer carries a
challengestring.Note
aboutcode-org#48 deliberately stayed on the v1 API. That remains a working option: the v3 widget keeps a v1 compatibility path, and I verified a
create_challenge_v1challenge is still solved by the v3.2.1 widget and accepted byverify_solution_v1. The case for moving to v2 anyway is capability, not compatibility — v1 has no memory-hard algorithm at all, so noARGON2IDand noSCRYPT, and its PoW is materially slower.Strict CSP
ALTCHA_STRICT_CSP = Trueswitches the widget template and the newAltchaWidget.mediato the modular build: the stylesheet is served as a separate file and the PoW workers load from static files instead of ablob:URL.ALTCHA_STRICT_CSP = Truestyle-src 'unsafe-inline'; worker-src blob:style-src 'self'; worker-src 'self'The modular build registers no algorithm on its own — without registration it throws
Unsupported algorithm.altcha-workers.jswires$altcha.algorithmsto the bundled workers, resolving their URLs fromimport.meta.url(overridable viaALTCHA_WORKERS_URL). This requires droppingasyncfrom the script tags so module evaluation order holds.Breaking changes
AltchaFieldoptions are the v3 ones.challengeurl/challengejsonmap to the unifiedchallengeoption with aDeprecationWarning; every other removed option (floating,overlay,hidefooter,maxnumber,strings,delay,mockerror, …) raisesTypeError. Options the widget does not accept as an HTML attribute are collected into the JSON-encodedconfigurationattribute.get_altcha_challenge()takesalgorithm/costinstead ofmax_number;AltchaChallengeViewexposesalgorithm/costaccordingly.static/altcha/dist_i18n/all.min.jstostatic/altcha/i18n/all.js, following the upstream v3 layout. ALTCHA v3 publishes no minified combined-translations build. Projects settingALTCHA_JS_TRANSLATIONS_URLare unaffected.New settings
ALTCHA_ALGORITHM("PBKDF2/SHA-256"),ALTCHA_COST(5000),ALTCHA_STRICT_CSP(False),ALTCHA_JS_STRICT_CSP_URL,ALTCHA_CSS_URL,ALTCHA_WORKERS_REGISTER_URL,ALTCHA_WORKERS_URL. The asset settings reuse the_STATIC_ASSET_SETTINGSresolution added in aboutcode-org#45 — relative paths go throughSTATIC_URL, absolute paths and full URLs pass through untouched.ARGON2IDneedsargon2-cffi, available via a newargon2extra.ALTCHA_JS_URLis ignored whenALTCHA_STRICT_CSPis on — the two builds are different artifacts and a standard-build URL would be wrong in strict mode.ALTCHA_JS_STRICT_CSP_URLoverrides it there.Verification
54 tests pass (35 existing + 19 new). Ruff clean; Sphinx builds with
--fail-on-warning; doc8 clean; the wheel packages all new assets.Beyond the unit tests, the widget was driven in Chromium against a live server with the policy actually set as a response header:
PBKDF2/SHA-256challengeURL viaAltchaChallengeViewblob:workers blockedSCRYPTunder strict CSPscript-src 'wasm-unsafe-eval', passes with itThat last row is documented in the README:
ARGON2IDandSCRYPTare WebAssembly and need'wasm-unsafe-eval'; the defaultPBKDF2/SHA-256does not.Not addressed
fetchandverifyFunctiontake JS function values and cannot be expressed from Python; they need$altcha.defaults.set()from your own script.refetchonexpireandcustomfetchhave no v3 equivalent.🤖 Generated with Claude Code
https://claude.ai/code/session_01956qnAS7qztaS7tghEKDta