client: carry the non-secret identity the wire has been sending all along - #52
Merged
ualtinok merged 1 commit intoSep 18, 2026
Merged
Conversation
Verified: 19 client tests; hermetic suite 223 pass, 0 fail, 871 expectations. Both decoder mutations reached named RED tests and were restored byte-identically. scripts/gate.sh was not green locally: crates/credentials-module/src/bin/cli_support/opencode_files.rs failed malformed_diagnostic_owner_fields_are_tolerated_and_evictable_once_stale (assertion result.is_ok(), load [12.93, 8.43, 6.32]) and reclaim_failure_does_not_fail_acquisition (assertion quarantine.exists(), load [15.02, 11.22, 7.87]).
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.
decodeCredentialhas been dropping five of the eight fieldsGetResultsends, including the one a consumer needs to verify it is holding the right account's handle.Why now
cortexkit/openai-authhas a served-identity fence written and skipped: it compares the vault'saccount_idagainst the JWT claim in the served token, which is what catches a handle bound to the wrong ChatGPT account. It cannot run, because the vendored client discards the field. They are holding their main-account enrollment until that branch is armed.Worth naming the shape of the defect, because it is not "a field is missing". My own OpenCode plugin logs the manifest's
credential_idbeside the vault'srecord_versionas though the pair corroborated identity. It does not — the vault'scredential_idnever reaches the consumer, so the plugin is comparing a local value against a local value and rendering it as agreement.What it does
Five optional fields on
ServedCredential, populated indecodeCredential. All five areskip_serializing_if = "Option::is_none"on the server, so absence is the common case and must not throw.The TSDoc carries forward the distinction the Rust doc comments make, because the client is where a consumer will actually read it:
credential_idis a binding-verification value, not a routing key. Account-scoped routing joins onaccount_id+record_version— the version bumps on every replace, so a re-pointed handle forces the router to re-resolve.Validation is fail-closed: a non-string where a string is expected throws
invalid_responserather than silently becomingundefined. A silent drop would hand the identity fence an absent value and let it pass by default, which inverts the whole point.CredentialStatusis deliberately untouched — this is the get path only.Mutations
Two from the implementer, one I ran myself on the validator because it guards the fail-closed property:
Verification
bash scripts/gate.shexit 0,workspace floor 626 >= origin/master 626 at 539ffd3. Hermetic 223 pass / 0 fail / 871 expectations. Two files, 115 insertions, no deletions;Cargo.lockuntouched; two-way revert sweep clean.One caveat on the gate, stated rather than hidden: the implementer's runs went red twice on
manifest_lockmembers under load[12.93, …]and[15.02, …]—reclaim_failure_does_not_fail_acquisitionandmalformed_diagnostic_owner_fields_are_tolerated_and_evictable_once_stale, in a file this diff does not touch. Mine passed at load ~7, and the isolated suite ran 15/15 five times. That is the class from #51; the two surviving members look different from each other (one pinsnow_override_ms, one reads system time directly) and I have not established a mechanism. Following up separately rather than guessing at it here.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Exposes the non-secret identity fields
GetResultalready sends, socortexkit/openai-authcan arm its served-identity fence that compares the vault'saccount_idagainst the served JWT claim.Behavior changes
ServedCredentialgains optionalcredentialId,projectId,accountId,email, andorgName, all populated indecodeCredential.undefined; a present non-string identity value throwsinvalid_responserather than silently passing the fence.credentialIdas a binding-verification value, not a routing key; account-scoped routing joinsaccountIdwithrecordVersion.CredentialStatusis untouched; only the get path changes.Caveat
scripts/gate.shwent red twice onmanifest_lockmembers (reclaim_failure_does_not_fail_acquisition,malformed_diagnostic_owner_fields_are_tolerated_and_evictable_once_stale) in a file this diff does not touch; mechanism not established.Written for commit c4ae1d8. Summary will update on new commits.