Summary
Switching to a new Space can succeed, yet a later query_current_member_revocation fails with Engine error 1387 and hides otherwise valid Space state in consumers.
1387 maps to MEMBER_GROUP_REVOCATION_FAILED_CODE. This is not a join failure: in the observed mobile flow, the new Space and device roster were already available and the new device was visible online to other members.
Suspected Cause
SwitchSpaceUseCase clears encrypted_relationship through RelationshipStateResetPort::clear_all_relationships(), but durable key-epoch and member-revocation data remain in member_revocation_log / space_key_epoch_state.
DefaultSpaceAccessAdapter::current_group_revocation() calls list_incomplete_revocations(), which currently decrypts and validates every incomplete row before selecting the record for the active Space. Therefore an unreadable incomplete record from a previous Space can fail the whole query before the active-Space filter is applied. The operation is surfaced as error 1387.
The exact unreadable-row cause is not yet observable: the current error mapping preserves the stable code but does not record the underlying safe failure reason.
Expected Behavior
A member-removal record from a previous Space must not prevent reading the active Space state or the active Space removal status after a successful switch.
Proposed Direction
- Scope the storage query for incomplete revocations to the active Space lookup token before decrypting rows.
- Review whether old-Space key-epoch / revocation records need explicit lifecycle handling on a Space switch; do not delete security records without a defined retention and recovery policy.
- Add redacted Engine-side diagnostics for failures of
query_current_member_revocation so the underlying reason is captured without recording device IDs, keys, tokens, or payloads.
Acceptance Criteria
- Given an unreadable incomplete revocation record for Space A and an active Space B,
query_current_member_revocation for Space B returns its own status (or no status) instead of error 1387.
- A successful Space switch remains readable even when old-Space revocation data cannot be decoded.
- The affected query emits a redacted failure reason that can distinguish repository, decryption, integrity, and state-transition failures.
- Tests cover the cross-Space case and preserve encrypted-at-rest requirements.
Consumer Impact
Mobile now treats this removal-status query as optional so its failure no longer hides an active Space and its devices. That is a consumer safeguard; the Engine query should still be isolated from unrelated old-Space records.
Summary
Switching to a new Space can succeed, yet a later
query_current_member_revocationfails with Engine error1387and hides otherwise valid Space state in consumers.1387maps toMEMBER_GROUP_REVOCATION_FAILED_CODE. This is not a join failure: in the observed mobile flow, the new Space and device roster were already available and the new device was visible online to other members.Suspected Cause
SwitchSpaceUseCaseclearsencrypted_relationshipthroughRelationshipStateResetPort::clear_all_relationships(), but durable key-epoch and member-revocation data remain inmember_revocation_log/space_key_epoch_state.DefaultSpaceAccessAdapter::current_group_revocation()callslist_incomplete_revocations(), which currently decrypts and validates every incomplete row before selecting the record for the active Space. Therefore an unreadable incomplete record from a previous Space can fail the whole query before the active-Space filter is applied. The operation is surfaced as error1387.The exact unreadable-row cause is not yet observable: the current error mapping preserves the stable code but does not record the underlying safe failure reason.
Expected Behavior
A member-removal record from a previous Space must not prevent reading the active Space state or the active Space removal status after a successful switch.
Proposed Direction
query_current_member_revocationso the underlying reason is captured without recording device IDs, keys, tokens, or payloads.Acceptance Criteria
query_current_member_revocationfor Space B returns its own status (or no status) instead of error1387.Consumer Impact
Mobile now treats this removal-status query as optional so its failure no longer hides an active Space and its devices. That is a consumer safeguard; the Engine query should still be isolated from unrelated old-Space records.