sdk(python,v4): P0-3 — align klickd Python SDK with v4 GA strict schema#43
Merged
Conversation
Adds a v4 schema validation surface to the Python SDK (P0-3) without bumping the package version (`4.0.0a1`) and without touching the v3 envelope crypto contract (SPEC.md §33.10 #2 frozen). What ships: - `klickd.validate(payload, strict=True|False, target="payload"|"unified")` with the strict GA candidate (P0-2) and permissive v4 preview schemas bundled as package data under `klickd/schemas/`. - `klickd.validate_iter_errors(...)` non-raising variant for wizards (R4-P0-1 reload-verification surface area). - Optional `[validate]` extra (`pip install klickd[validate]`) — `jsonschema` stays optional so callers who only need load/save are unaffected. - v4 TypedDicts: `KlickdMediaProfileV1`, `KlickdVerificationGatesV1`, `KlickdGateEntry`, `KlickdHumanVetoPolicy`, `KlickdClaimSources`, `KlickdMigrationV1` (additive to `KlickdPayload`). - README block documenting the new surface + the §33.7 verbatim round-trip guarantee on v4 additive fields. What does NOT ship: - No envelope/version bump, no PyPI publish, no Git tag, no Zenodo DOI — Phase B governance reminder respected. - No SDK alignment of the docs-only R4-P0-2 codes (`KLICKD_E_PASS_MISMATCH`, `KLICKD_E_SAVE_LOCAL`, `KLICKD_E_LEGACY_VERSION`, `KLICKD_E_CORRUPT`, `KLICKD_E_POLICY_LOCKED`, `KLICKD_E_UNSAFE_QR`); R4-P0-2 §4 explicitly defers SDK exposure to a later track. Tests (63 / 63 pass): - 5 R4-P0-3 personas validate against strict payload + unified + preview. - 5 personas round-trip verbatim (single + double round-trip). - Negative cases: unknown gate level, missing media hash, unknown modality, unsupported `payload_schema_version`, encrypted envelope missing kdf/cipher/ciphertext. - Both structured + flat `verification_gates` shapes accepted. - Preview value `"4.0.0-preview.1"` accepted by strict schema (P0-2 design — preview-era files round-trip without rewrite). - v3.x payloads unaffected (no regression). - Unknown top-level fields validate AND round-trip verbatim. - `tests/test_v4_preview_roundtrip.py` and `tests/test_roundtrip.py` unchanged and still green. Repo-level checks: `scripts/validate_v4_schemas.py` ✓ ; `verify_vectors.py` 59/59 ✓ ; JS `verify_vectors.mjs` 29/29 ✓ . Refs: P0-3 in `docs/roadmap/ROAD-TO-V4-GA.md`, depends on P0-1 + P0-2 (merged in #42). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The new tests/test_v4_ga_strict.py suite uses klickd.validate, which is gated on the optional jsonschema dependency. The CI step now installs the [validate] extra so the strict-schema tests execute; the test file also pytest.importorskip()s on jsonschema so a local run without the extra cleanly skips the validation tests instead of erroring. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6 tasks
Davincc77
added a commit
that referenced
this pull request
May 24, 2026
#44) Mirrors PR #43 (Python SDK V4 GA alignment, merged 4136282) on the TypeScript side: - New validate(payload, { strict, target }) and validateIterErrors matching the Python surface (klickd.validate). Throws KlickdError(KLICKD_E_SCHEMA) with the same 8-issue summary format. - Bundles all four v4 schemas (payload+unified x strict+preview) under src/schemas/, byte-identical to the canonical files in schemas/ and schema/. getBundledSchema(key) and listBundledSchemas() mirror Python's _load_schema affordance. - ajv (>=8.12) added as an OPTIONAL peerDependency — callers that do not invoke validate() keep the v3 crypto-only surface. Lazy-loaded through ajv/dist/2020.js for Draft 2020-12 support; missing-ajv raises KLICKD_E_SCHEMA with a clear install hint. - KlickdPayload extended with the additive v4 GA fields (profile_kind, media_profile, verification_gates, human_veto_policy, claim_sources, migration, ...) and the v1-frozen sub-types (KlickdMediaProfileEntry, KlickdGateEntry, KlickdGateLevel, ...) — parity with packages/pypi/klickd/src/klickd/_types.py. - New Jest suite v4-ga-strict.test.ts mirroring the Python pytest matrix: 5 personas validated against strict+preview+unified schemas, double round-trip preservation, negative cases (unknown gate level, missing media hash, bad modality, unsupported schema version, missing envelope kdf), both structured and flat gate forms accepted, preview/GA cross-acceptance, v3.x non-regression, unknown-field preservation (SPEC.md §33.7), validateIterErrors path/message shape, and KlickdError(code/httpStatus) shape. Results: 61/61 Jest, 63/63 Python pytest, 59/59 Python vectors, 42/42 JS vectors, validate_v4_schemas.py all green, package integrity unchanged. No package version bump. No publish. tsup build flagged with --external ajv and --loader .json=copy so the bundled schemas ship in dist/. Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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.
Summary
Wires the Python SDK (
packages/pypi/klickd/) onto the v4 GA strict schema candidate landed by #42, without bumping the package version and without touching the frozen v3 envelope crypto contract (SPEC.md §33.10 #2).klickd.validate(payload, strict=True|False, target=\"payload\"|\"unified\")+ non-raisingklickd.validate_iter_errors(...).klickd/schemas/.jsonschemais an optional extra (pip install klickd[validate]); load/save users are unaffected.Governance — preserved
4.0.0a1).@klickd/corechange.KLICKD_E_PASS_MISMATCH,KLICKD_E_SAVE_LOCAL,KLICKD_E_LEGACY_VERSION,KLICKD_E_CORRUPT,KLICKD_E_POLICY_LOCKED,KLICKD_E_UNSAFE_QR) — R4-P0-2 §4 explicitly defers this to a later track.Strict / preview design
\"4.0\"and\"4.0.0-preview.1\"inpayload_schema_version, by design, so preview-era files round-trip against the strict surface without rewriting.target=\"payload\"validates the inner payload schema (common case afterload_klickd).target=\"unified\"validates an envelope-shaped dict (useful for the wizard's import path).Test plan
python3 -m pytest -qinsidepackages/pypi/klickd/→ 63/63 pass (17 existing + 46 new).payload_schema_version, encrypted envelope missing kdf/cipher/ciphertext).verification_gatesshapes accepted; flat form with invalid level rejected.python3 scripts/validate_v4_schemas.py→ all v4 strict-schema validations pass.python3 verify_vectors.py→ 59/59 pass (v2.5 / v3.0 / adversarial / v4.0-preview).node verify_vectors.mjs→ 29/29 pass, 13 skip (hash-wasm not installed locally; same asmain).python3 -m build --wheelsucceeds; bundled schemas appear exactly once underklickd/schemas/.Impact on next P0 tracks
@klickd/core4.0.0) is now unblocked — Python parity surface isvalidate(payload, strict=...)and the four bundled schemas. JS implementation should mirror the samestrict/preview×payload/unifiedmatrix.klickd.validatedirectly once vectors land.🤖 Generated with Claude Code