feat(session)!: persist watch and connect rules - #196
Merged
Merged
Conversation
Register a directed-edge SQLModel table with S2/S3 columns so later slices fill fields without altering schema. Related: #193 AI-Generated: true Generated-At: 2026-09-15T00:38:58Z
Store directed edges in SQLite, restore and re-authorize on startup, and lower the watch floor to 1 second. Extract SessionBridgeState as the live index. BREAKING CHANGE: SessionWatch.expires_at is wall-clock UTC unix seconds and now includes rule_id. MIN_WATCH_TTL_SECONDS is 1. remaining_seconds no longer uses monotonic time. Related: #193 AI-Generated: true Generated-At: 2026-09-15T00:39:47Z
Let creators and same-config operators list and revoke persisted watch/connect edges by stable rule_id. Related: #193 AI-Generated: true Generated-At: 2026-09-15T00:40:08Z
Record wall-clock TTL, SQLite persistence, connect without duration, and IM-only links/unlink in zh and en docs. Fixes #193 AI-Generated: true Generated-At: 2026-09-15T00:40:27Z
Replace SessionBridgeStore protocol ellipsis bodies so CodeQL does not flag ineffectual statements. Type expiry tasks as coroutines for pyright. Check watch/connect limits before deleting an existing edge, skip pair rows on restore, fail closed on invalid restore rows, and hide expired watches from /session links. Related: #193 AI-Generated: true Generated-At: 2026-09-15T00:58:46Z
Replace the empty restore except with a log, keep later rules when authorize raises unexpectedly, refresh stored config ids, skip unavailable listeners, and translate link TTL labels. Related: #193 AI-Generated: true Generated-At: 2026-09-15T01:15:05Z
Update the grouped CLI name test for links/unlink. Store expiry as ceil(now+ttl) so a 1-second watch is not already elapsed. Drop extra connects for the same listener on restore and remove unused state helpers. Related: #193 AI-Generated: true Generated-At: 2026-09-15T01:44:37Z
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
Persist
/session watchand/session connectas directed SQLite edges with stablerule_ids, wall-clock watch TTL (floor 1 second), and IM/session links//session unlinkfor creators and same-config operators.Related issue
Fixes #193
Related: #192
Behavior
rule_idand resets TTL; connect retarget is 1:1; watch↔connect replace each other./session linksand/session unlink <rule_id>are IM-only. Creators see and can revoke their own rules after role loss; current-configinstance_operatorsees/revokes rules touching that config;operator/rootsee and revoke all.SessionWatchnow hasrule_id;expires_atis wall-clock UTC unix seconds;list()still returns only the actor's watches.Non-goals
pair/unpair(#194)/session filter(#195)SessionBridgeCapabilitywithlinks/unlinkImplementation notes
SessionBridgeManagerremains the public owner. Live grants, connect 1:1, and store IO live in privateSessionBridgeState. The newsession_bridge_rulestable includes S2/S3 columns (pair_id,match,except,header) written with S1 defaults. Restore rebuildsSubject.from_idand re-authorizes; lost permission deletes the row. Adapter-unavailable deliveries skip without deleting the rule.This is a plugin SDK semantic break for
SessionWatchandMIN_WATCH_TTL_SECONDS.Validation
Not run:
make check,make test-blocking.Compatibility and risk
Breaking for plugins that assume monotonic
SessionWatch.expires_atorMIN_WATCH_TTL_SECONDS == 60. RestoreAuthContextis reconstructed fromsubject.kindwithout a new column; deny deletes the row (fail closed). No OpenAPI change.Checklist
docs/zh/anddocs/en/.docs/public/openapi.json, and tests change together when routes or schemas change.pyproject.toml,requirements.txt, anduv.locktogether.!and aBREAKING CHANGE:footer.Agent note
Goal: ship #193 S1 of the session-bridge persistence stack. Paths: new
session_bridge_rulesstore,SessionBridgeState, manager restore/lifecycle, IMlinks/unlink, bilingual command/authorization/send-message docs. Checks actually run are listed under Validation;make checkand blocking pytest were not run. Residual risk: reconstructed restore context for rare subject kinds, and the SDK wall-clock/rule_idbreak. Tools: OpenCode / grok-4.6.