migrator(v4): P0-5 — v3.x → v4 GA non-destructive payload migrator (Python + TypeScript)#45
Merged
Merged
Conversation
…ython + TypeScript) Adds the R4-P0-5 normative migrator surface in both reference SDKs: - `docs/spec/MIGRATION_V3_TO_V4.md` (NORMATIVE) — wire-envelope contract unchanged (`klickd_version="3.0"`, payload moves to v4 GA fields), 10-rule transform table, idempotency, manual-review conditions, error handling. - Python: `klickd.migrate_payload`, `klickd.migrate_payload_iter_warnings`, `klickd.needs_migration` (pure / non-destructive / idempotent). Stamps `payload_schema_version="4.0"`, defaults `profile_kind="learner"`, records RFC-004 v1 `migration` block. Preserves every v3 field verbatim (SPEC.md §33.7). Never invents safety surface. - TypeScript: `migratePayload`, `migratePayloadIterWarnings`, `needsMigration` — cross-impl parity with Python (same rules, same warnings). - Cross-impl tests: 36 new pytest cases + 30 new jest cases covering detection, stamping, pointer refs, non-mutation, default/explicit profile_kind, verbatim block preservation, no-synthesis invariant, envelope-key untouched, idempotency on v3 and v4 inputs, unknown version refusal, warning surface, secret-key non-synthesis, plus strict v4 schema validation across all six v3 example files. No release, no tag, no package version bump. Wire envelope contract preserved: encrypted v3 files round-trip bit-for-bit under the same passphrase after payload-only migration.
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
.klickdv3.x → v4 GA, in both reference SDKs and as a docs-normative spec. Non-destructive, pure, idempotent — operates on the decrypted payload only, never touches the encrypted wire envelope.klickd_versionstays"3.0"on disk; only the inner payload advertisespayload_schema_version: "4.0"(matches the preview-track invariant already documented inCONTRIBUTING.md).What ships
docs/spec/MIGRATION_V3_TO_V4.mdpackages/pypi/klickd/src/klickd/migrate.py(re-exported viaklickd.__init__)packages/@klickd/core/src/migrate.ts(re-exported via@klickd/coreindex)packages/pypi/klickd/tests/test_migrate_v3_to_v4.py(36 cases)packages/@klickd/core/src/__tests__/migrate-v3-to-v4.test.ts(30 cases)Migrator contract (summary — see spec for full rules)
needs_migration(payload)/needsMigration(payload)— boolean detector.migrate_payload(payload, *, source_version=None, migrated_at=None, profile_kind="learner", migration_report_ref=None, backup_ref=None)— returns a new dict (Python) / object (TypeScript).migrate_payload_iter_warnings(payload)/migratePayloadIterWarnings(payload)— non-throwing warning surface for manual-review conditions (overlongdecisions_locked, non-reservedprofile_kind,human_veto_policy↔ethics.locked_actionsoverlap, missing source-version metadata).Transform rules (R1–R10) covered by the spec § 3.3:
payload_schema_version = "4.0".profile_kind = "learner"when absent.domain_schema_versionverbatim.migrationblock (source_version,migrated_at, optional pointer refs).verification_gates,human_veto_policy,claim_sources,media_profile, …).ethics.locked_actions,context.decisions_locked) never mutated.What is intentionally NOT in scope
validate(..., strict=True)separately).vectors/v4-ga-strict-p0-6).Testing
Local results on this branch:
python verify_vectors.py→ 59/59 pass (v2.5 + v3.0 + adversarial + v4.0-preview), 0 fail, 0 skipnode verify_vectors.mjs→ 42/42 pass (with hash-wasm), 0 fail, 0 skippython scripts/validate_v4_schemas.py→ strict v4 schema validations all pass (positive + negative)python -m pytest packages/pypi/klickd/tests/ -q→ 98 passed, 1 skipped (skip is the pre-existing R4-P0-2 wizard-deferred case)cd packages/@klickd/core && npm test→ 96 passed (4 suites, includes the 30 new migrator cases)cd packages/@klickd/core && npm run build→ clean ESM + CJS + DTSTest plan
full_v34.klickdwhose v3-eralearning_goal.stakes="critical"is tightened by the v4 GA enum — surfaced via warnings, not rewritten, per spec § 3.4).klickd_version,kdf,cipher,created_at,domain,encrypted), NOT introduce any secret-looking keys.decisions_locked, ethics ↔ veto overlap, non-reservedprofile_kind.Follow-up
vectors/v4-ga-strict-p0-6. Not included here.