Structured error codes: stable enum through the FFI error callback - #39
Merged
Conversation
Consumers currently detect credential rejection by substring-matching the
free-form SyncError message, which is fragile in both directions. Give the
library an owned, stable code so bindings can react to the action a failure
calls for.
Library:
- New ReplicantErrorCode (#[repr(i32)], explicit stable values) banded by
action: 1xxx credential-rejected, 2xxx transient (incl. clock-skew
timestamp reasons), 3xxx protocol, 4xxx identity drift.
- is_credential_rejection band helper + FFI
replicant_error_is_credential_rejection(i32) -> bool so bindings don't
re-derive the band.
- SyncEvent::SyncError and the internal QueuedEvent carry the code;
ErrorEventCallback ABI becomes (event_type, i32 error_code, message, ctx).
- websocket.rs parses the phoenix join-rejection payload structurally
(error_code_for_join_reject -> error_code_for_reason), mapping the server's
{reason: "<atom>"} to a code; timeouts -> Timeout, other socket/connect
failures -> ConnectionFailed, identity drift -> IdentityDrift.
- Other emit_sync_error sites pass the most specific code (Unknown where
genuinely uncategorized).
- Regenerated include/replicant.h with the pinned cbindgen (=0.26.0);
byte-stable.
Consumers/tests:
- Updated the FFI test callbacks, Rust examples, C++ examples and the JUCE
wrapper (onSyncError now surfaces the code) to the new ABI.
- error_code unit tests (per server reason + band helper); interop
credential test now asserts the derived code is CredentialNotEnrolled.
Callback ABI break; version bump deferred to release.
Claude-Session: https://claude.ai/code/session_01GwMbERgLK4KAuLrz4b4Liw
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.
Consumers currently detect credential rejection by substring-matching the free-form error message — the C++ consumer clears stored credentials off
strstr. The library must own this knowledge.ReplicantErrorCode:#[repr(i32)]enum with explicit stable values, banded by consumer action — 1xxx credential rejected (clear + re-enroll), 2xxx transient (retry, never clear — includes the timestamp/clock-skew reasons), 3xxx protocol, 4xxx identity drift (refuse sync, don't clear), 0 unknown. Exported through the pinned cbindgen; band helperreplicant_error_is_credential_rejection()over FFI so bindings never re-implement band logic.(event_type, int32_t error_code, const char* message, ctx)— code and message together. Breaking; next release is 0.5.0.ChannelJoinError::Rejected { rejection }) via a pure per-reason mapping table, unit-tested per server reason atom. Identity-drift check emitsIdentityDrift.onSyncErrornow(int32_t, const std::string&).Tests: workspace green (55 in replicant-client lib incl. 4 new mapping/band tests); live interop harness 28/28 with the
credential_not_enrollednegative test extended to assert code 1003 through the production extractor.https://claude.ai/code/session_01GwMbERgLK4KAuLrz4b4Liw