contacts: contacts, users, blocking and the resolver on the registry - #10
Merged
Conversation
The three shapes that carry provenance rather than a verdict: UserStatus keeps by_me so a coarse last-seen bucket is never reported as the peer hiding; ContactAdded keeps both imported and retry so an empty import is not read as 'no such number'; DialogStatus stays three-valued, with has_dialog null whenever resolved is false.
…p deleted
The address book, one person's profile, blocking, and the resolver every
other group already leans on. Three semantics carry over verbatim because
AGENT.md freezes them: dialog-status stays three-valued, hide-stories stays
idempotent and silent, and contact rename still writes only our own view of
a name (empty first name still becomes '.').
Two shapes are new. A result can now be marked indeterminate, so
dialog-status returns its body AND exits 13 — an error envelope would have
thrown away the reason a caller needs. And 'resolve link' classifies without
acting: it names the command that would act in delegated_to.
Deletes tlgr/cli/legacy/{contact,user}.py, the eight contact/user IPC routes
and the eight ClientWrapper methods behind them; every v1 path stays
invocable through legacy_paths.
The fake grows a contact world — the list, the two blocklists, top peers, birthdays, the phonebook, saved music, profile photos — so a test asserts that adding a contact really flipped user.contact and that a second hide-stories pass sent nothing at all. The two frozen contracts get the coverage they earned: dialog-status is checked in all three outcomes including the capped scan that must exit 13, and the v1 paths (contact list/add/rename/remove/search, user get/ dialog-status/hide-stories, and the bare 'contacts') are asserted to still resolve and still be invocable. Replaces tests/test_dialog_status.py and tests/test_stories_hidden.py, whose ClientWrapper methods this PR deleted.
… owners The domain-wide waiver is gone. The 22 required ids still uncovered in it each name the group that does own them — privacy keys to PR-12, People Nearby to the location group, live presence to the event bus — which is what makes 'the contact group is done' checkable rather than asserted. P0 floor 53 -> 73, covered floor 350 -> 472, with the 20 new P0 ids named rather than counted so a swap cannot pass silently.
AGENT.md gains the whole group with the two ambiguities spelled out where an agent will read them: an empty contact import is not 'no such user', and by_me on a coarse last-seen bucket is our own privacy, not theirs. The resolve section is new and says plainly that classification never acts. CHANGELOG rows 10-12 cover the three shape changes (contact list/search became Page envelopes, contact add and user get gained keys, --field is gone in favour of the global --select), and DECISIONS records the ten calls this PR had to make.
Each classified kind gets its follow-up read exercised against a real reply shape — an invite preview, a sticker set, a boost status, a gift code, a private post reached through the peer cache — and the assertion is that no acting request was sent alongside it. Also covers the three paths that were assumed rather than checked: --with-stories against real read marks, --translate-bio, and a min user addressed through inputUserFromMessage, which Telethon builds for nobody.
Three assertions were written against a tree where `media`, the sticker sets and the wallpapers were still v1's. On `main` they are not: - `test_sandbox` picked `media download` as its example of a still-hand-written group. PR-6 generated it, and `profile` is now the only one left. - the fake grew a stub `messages.getStickerSet` / `account.getWallPaper` / `stories.getStoriesByID` beside PR-6's world-backed handlers. Python keeps the last definition, so the stubs were dead and the reads came back empty. The stubs are deleted and the address book seeds the two worlds instead, which is the stronger test: `resolve link --open` now reads the same replies the media group's own ops read.
Each of the seven was written when `location`, `search`, `events` and `account` were still ahead of this branch; all four have landed, and the group each waiver names is the group that now covers the id. A waiver on a covered id is a promise that has already been kept, so it is noise in the one file whose whole job is naming what is still missing.
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
PR-5 of the v2 plan: contacts, users, blocking and the link resolver on the operation registry — 38 operations under
contact,user,resolveandlink— and the legacy contact/user modules, their IPC routes andClientWrappermethods deleted.dialog-statusandhide-storiesexactly as AGENT.md documents them. Indeterminate answers now travel asmeta.indeterminateon the envelope so the CLI exits 13 instead of reading an HTTP 200 as success.resolve link <url>normalises every t.me / tg:// link kind (user, chat, message, invite, folder, story, bot start, proxy, boost, gift, stars, wallpaper, theme, phone) into a typed object; username, phone and id resolution follow the cache → server → dialog-scan order from the MTProto notes.Numbers
6 commits, 3,440 tests, ruff + mypy clean. Parity: contacts_users P0 20/20; 99/121 required ids covered and 100% accounted (privacy keys → PR-12, nearby → PR-9, live presence → PR-4). Ten decisions in DECISIONS.md, notably
omit_defaults=Falseon contact/user models soalready: falseandhas_dialog: nullare always emitted.