core+net: stamp session onto register/attach/assign/deregister envelopes; fix control-byte JSON escaping in 3 writers - #75
Merged
Conversation
Yaraslaut
force-pushed
the
issue-cluster-f-session-auth
branch
from
August 12, 2026 06:19
aeb721f to
922f7d7
Compare
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Yaraslaut
force-pushed
the
issue-cluster-f-session-auth
branch
2 times, most recently
from
August 12, 2026 13:37
482a491 to
ef139b2
Compare
…ster envelopes Add IBackend::setSession(session::Context), mirroring the setReconnectHandler/setConnectHandler/setDisconnectHandler no-op-default pattern. Bridge pushes the current default session to the active backend from its constructor, from setDefaultSession(), and to the incoming backend in switchBackend() (before phase 1's re-registration loop runs, so re-registered handlers' control envelopes carry it too). SimulatedRemoteBackend, SocketBackend, and QtWebSocketBackend override setSession to store the session and stamp it onto every register, registerShared, attach, assign, and deregister envelope they build. LocalBackend needs no change -- the local path never serialises a Context onto a wire envelope. Previously these control envelopes always carried a default-constructed, unauthenticated session::Context regardless of Bridge::setDefaultSession(), so RemoteServer::authorizeRegister could never see a caller's identity and the owner principal recorded at register time was always empty -- degrading authorizeInstance's ownership check to allow-all for every Bridge-registered instance. Updated docs/spec/core/backend.md, docs/spec/core/bridge.md, and docs/spec/session/session.md to document the new hook and its call sites. Note: SocketBackend's fix (include/morph/net/socket_backend.hpp) could not be compile-tested on this Windows machine -- morph::net is POSIX-only and MORPH_BUILD_NET is ignored on Windows -- but mirrors the verified SimulatedRemoteBackend fix exactly. Same for QtWebSocketBackend, fixed for consistency though not explicitly required by the issue's hint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ters Apply the same control-byte escaping option morph::wire::encode already uses (morph::wire::detail::EscapingWriteOpts) to the three writers on caller-supplied strings that never got the fix: - morph::journal::toJson(LogEntry) (journal/action_log.hpp) - morph::offline::detail::toJson(FileQueueRecord) (offline/file_offline_queue.hpp) - morph::session::TokenIssuer::issue(SessionToken) (session/session_auth.hpp) glaze 7.4 leaves ASCII control bytes (0x00-0x1F) unescaped by default: RFC 8259 requires them escaped, so a raw control byte in any of these writers' string fields produced JSON the sibling reader either failed to decode outright, or -- when the same string also held an escaped `\`/`"` -- silently corrupted via glaze's chunked writer path before the payload ever reached disk or was signed. Each file gets its own local EscapingWriteOpts (duplicated, not shared, to avoid a new core/ dependency from journal/offline/session -- these stay independently includable, e.g. under MORPH_CLIENT_ONLY). Also routes TokenIssuer::issue's previously-discarded (void)glz::write_json(...) through a new throwOnGlazeError-style helper (mirroring the other two writers already had), adding a TokenIssuanceError type. Not realistically reachable for SessionToken's flat shape, but keeps the writer consistent with its siblings instead of silently serialising a claims blob that could later fail to verify. Updated docs/spec/journal/journal.md, docs/spec/offline/offline.md, and docs/spec/security.md to document the escaping and the new error type. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ol_characters members Doxygen's WARN_AS_ERROR=FAIL_ON_WARNINGS gate flagged the two of these three duplicated structs it happened to reach as undocumented (journal and session; the offline-queue copy has the identical gap, fixed here too for consistency). Matches the @brief already present on the original in core/wire.hpp that these three deliberately mirror. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…Entry literals Both structs gained fields (roles on SessionToken; outcome, error, principal, timestampMs, idempotencyKey on LogEntry) at various points in their history, and this branch's new test files built designated initializers against the earlier, shorter field lists. MSVC doesn't warn on this; Linux clang-debug's strict -Werror, -Wmissing-designated-field-initializers does. List every field explicitly at each call site. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Yaraslaut
force-pushed
the
issue-cluster-f-session-auth
branch
from
August 12, 2026 16:11
ef139b2 to
1e5dd5a
Compare
Comments should describe the present implementation and its rationale, not narrate what a fix changed — once merged, that framing has no context to anchor to. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…not history
docs/spec/core/backend.md, docs/spec/session/session.md,
include/morph/core/backend.hpp, and two test file headers/comments
narrated the pre-fix state ('before IBackend::setSession existed',
'was always empty', 'reproduces and verifies the fix for #63') instead
of describing the current design. Rewritten to state only present-tense
facts and their rationale — once merged, 'before the fix' framing has
no context to anchor to.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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
Closes #63, closes #62.
IBackend::setSession(session::Context), mirroringsetConnectHandler/setDisconnectHandler.Bridgepushes the session to the active backend from its constructor,setDefaultSession(), andswitchBackend().SimulatedRemoteBackend,SocketBackend, andQtWebSocketBackendnow stamp it onto every control envelope, fixingauthorizeRegister(previously always denied on a verifying authorizer) and owner-principal recording at register time (previously always empty).EscapingWriteOptscontrol-byte-escaping fix to the three sibling writers that never got it:journal::LogEntry,offline::FileQueueRecord,session::SessionToken. Also routed the session-token writer's error through athrowOnGlazeError-style helper instead of discarding it.Review
Ran
contour-workflows:cpp-reviewagainst the branch diff (real skill invocation). No findings — lock discipline for the new_sessionMtxverified leaf-only (no lock-order inversion), the three new escaping structs are deliberate duplicates (avoiding a newcore/dependency in headers meant to stay independently includable underMORPH_CLIENT_ONLY).Caveat
The
SocketBackendfix (include/morph/net/socket_backend.hpp) could not be compile-tested —morph::netis POSIX-only and ignored on this Windows build machine. It mirrors the verifiedSimulatedRemoteBackendfix exactly but is unverified by a build here; worth a CI check on Linux before merging.Test plan
Full suite: 854/854 passing (excluding the two known pre-existing unrelated environment issues).
🤖 Generated with Claude Code