feat(protocol): enforce the engines.protocol handshake (ADR-0087 P0)#2650
Merged
Conversation
Turn a protocol/consumer version mismatch from an arbitrary downstream crash into a structured, machine-actionable load-time refusal, and pay down a standing ADR-0078 violation: engines.protocol (ADR-0025 §3.2, protocol-first per §3.10 #3) was declared, documented, and checked by no loader or installer. - spec: export PROTOCOL_VERSION / PROTOCOL_MAJOR from /kernel — the single source of truth the handshake checks against; a drift test keeps it in lockstep with the package major. - metadata-core: checkProtocolCompat() (pure, major-grained range check supporting ^/~/>=/</ranges/wildcards), assertProtocolCompat(), and the structured ProtocolIncompatibleError (OS_PROTOCOL_INCOMPATIBLE, carrying both versions and the 'migrate meta --from N' command). Refuses only on a positive mismatch; absent ranges are grandfathered (warn), unrecognized ranges never cause a false rejection. - metadata-protocol: installPackage runs the handshake before the registry write — incompatible packages are refused with a diagnostic, not a crash. Additive and backward compatible; api-surface snapshot regenerated (2 added, 0 breaking). Part of #2643; resolves #2644. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HjDghc79qFSJkJt2zvBxtU
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 93 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
11 tasks
…838) The comparator match (`^(<=|>=|<|>)\s*(.+)$`) and the hyphen-range match (`^(.+?)\s+-\s+(.+)$`) had whitespace/any-char overlap — polynomial-ReDoS shapes on the externally-authored engines string. - comparator: peel the operator by fixed prefix + trim, no backtracking match - hyphen range: split on the whitespace-delimited hyphen (fixed anchor), not a lazy (.+?)…(.+) match - bound the range string to 128 chars up front (a real SemVer range is short; overlong input is unrecognized = admit-with-warning, never a slow scan) Behavior unchanged (100 tests green); adds a ReDoS-regression test asserting pathological inputs resolve to null in well under 50ms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HjDghc79qFSJkJt2zvBxtU
os-zhuang
marked this pull request as ready for review
July 6, 2026 00:28
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.
Implements P0 of the ADR-0087 epic (#2643) — resolves #2644. First real code change of the metadata-protocol upgrade contract.
What & why
PluginEnginesSchema.protocol(packages/spec/src/kernel/manifest.zod.ts, ADR-0025 §3.2, protocol-first per §3.10 #3) was declared, documented, and checked by no loader or installer — an ADR-0078 "declarable-but-inert" violation, and the root cause of "a version mismatch crashes the app": a package built against an incompatible protocol major failed deep in a schema.parse()or renderer contract instead of at the boundary.This turns that into a structured, machine-actionable load-time refusal.
Changes
@objectstack/spec— exportsPROTOCOL_VERSION/PROTOCOL_MAJORfrom/kernel, the single source of truth the handshake checks against. A drift test (protocol-version.test.ts) asserts it againstpackage.jsonso the protocol major and the published package major can never diverge.@objectstack/metadata-core— the pure logic core:checkProtocolCompat(manifest, runtimeVersion?)— major-grained range check supporting^,~,>=/</>/<=, compound (>=11 <13), hyphen, and wildcard forms. Returns a discriminated result (ok/no-range/unparsed-range/incompatible).assertProtocolCompat()+ProtocolIncompatibleError(code: OS_PROTOCOL_INCOMPATIBLE) carrying both versions and the exactobjectstack migrate meta --from Ncommand (wired end-to-end in P2).@objectstack/metadata-protocol—installPackageruns the handshake before the registry write, so an incompatible package is refused with a diagnostic instead of crashing later.Design notes (from ADR-0087 D1)
migrate meta --from N(P2) does not exist yet; P0's value is the diagnosable refusal, and the diagnostic already carries the command string for when P2 lands.engines.protocolreal) #2644): the boot-time load-path handshake (AppPlugin.start()+ durable rehydration), theobjectstack lintnudge for a missing range, and scaffold stamping (create-objectstack/defineStacktemplates) — the ratchet that closes grandfathering. This PR delivers the enforcement core + the primary install seam.Verification
@objectstack/spec— full suite green (incl. the drift test);check:api-surfaceshows 2 added, 0 breaking, snapshot regenerated per ADR-0059 §4.@objectstack/metadata-core— 99 tests green (exhaustive range-logic coverage incl. the<13.0.0boundary and the bare->Nnpm-desugaring case).@objectstack/metadata-protocol— 15 tests green: new install-seam tests prove reject-before-registry-write + structured diagnostic + compatible-installs + grandfathering; pre-existing durable-package tests still pass.🤖 Generated with Claude Code
https://claude.ai/code/session_01HjDghc79qFSJkJt2zvBxtU
Generated by Claude Code