These commits are when the Protocol Buffers files have changed: (only the last 100 relevant commits are shown)
| Commit: | 0b0144f | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7453 ChatSearch: optional message creator filter Rpc.Chat.Search.Request gains repeated creators (empty = all authors), honored in every scope: - FT path: Must-nested term clauses on the raw-indexed Author field (exact, case-sensitive identity match; boost 0) — scoping at the query keeps the candidate budget on the requested authors' messages instead of post-filtering them out of a shared page. Empty creator strings are ignored (a raw empty term would compile to a match-nothing clause). Hydration backstops the clause for stale FT docs. - Browse path (empty fullText): chatrepository.GetLastMessagesByCreators filters in the store query, newest selected, ascending like GetLastMessages (queryMessages reverses for chat-display order).
The documentation is generated from this commit.
| Commit: | 2b8863a | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7449 GO-7452 Default browse sort: lastModifiedDate desc when no sorts and no text Clients' browse requests (filters+limit only, observed from desktop) were getting an arbitrary id-ordered prefix per space: without a sort the per-space candidates are whatever natural order yields first and the merge falls back to the id tiebreak. Mirror chat search's browse default: empty sorts + empty fullText now sort by lastModifiedDate desc — served by the existing per-space lastModifiedDate index, so the per-space candidates become the newest offset+limit objects and the merged page is the true vault-wide recents list. Also dedupe an accidentally twice-inserted test and document in the proto that an unlimited request materializes every space in full.
| Commit: | 447b55c | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7449 GO-7452 Apply 3-lens review fixes: per-space FT scoping, merge-order fidelity, determinism Review round (3 independent lenses, findings measured against real tantivy): - CRITICAL: perSpaceQuery never set SpaceId, so every space ran the same global fulltext search, resolved the global candidate list against its own store and dropped everyone else's hits — spaces whose matches don't rank in the global candidate page silently returned nothing (measured: 5 of 6 spaces absent), each starving space escalating to the 2000-doc hard cap (measured 1.4s vs 7ms for 15 spaces). Now scoped per store. Paired fix: the ftsearch space clause gets boost 0 — at boost 1 its IDF added a per-space additive bias (larger for smaller spaces) that made _final_score incomparable across spaces; within one space it was a constant, so per-space ranking is unchanged. - Merge-order fidelity: the merge now reproduces exactly the order each store cut its candidates with — database.InjectDefaultOrder (implicit score-first order of fulltext queries) + exported database.NewSetOrder (includeTime resolution, custom orders) — instead of bare NewKeyOrder over the raw request sorts. Measured bugs fixed: fulltext+sorts pages duplicated and permanently hid records (top-K property violated), date sorts collapsed to day granularity and grouped by space. - Option/object order maps resolve across all queried stores via a union wrapper instead of one random representative space (foreign options produced empty sort keys and clumped). - Determinism: the store snapshot is sorted (map iteration order leaked into every tie) and the merge comparator ends on the object id — offset paging returned duplicates in ~15% of runs before. - allStoresLoaded now also turns false when a space's store failed and was skipped — it is the client's only completeness signal. - Tech space and marketplace are excluded (parity with the fulltext iteration and the cross-space subscription; spaceView/participant objects leaked into results). - ctx plumbed through (cancelable between spaces), negative paging clamped (offset==-limit used to disable the per-space bound), filters cloned per space (nested-filter injection mutated the shared slice). Regression tests: FT candidate survival across a noisy space, same-day date interleaving, repeat-call determinism + no-duplicate paging, tech space exclusion, negative-paging clamp.
| Commit: | 455507f | |
|---|---|---|
| Author: | Roman Khafizianov | |
| Committer: | Roman Khafizianov | |
GO-7449 GO-7452 One-shot cross-space ObjectSearch without subscription New ObjectCrossSpaceSearch RPC: query the spaces whose object stores are loaded at the moment of the call, with no subscription machinery and no waiting for the store warm-up (stores load sequentially on app start). The response reports allStoresLoaded so the caller knows when records cover only a partial space set — retry later for the complete view, or use ObjectCrossSpaceSearchSubscribe which streams later-loading spaces. objectstore.QueryCrossSpaceNoWait: snapshots the loaded stores (warm-up flag read before the snapshot so true always means a complete set), skips failing spaces instead of aborting, bounds per-space candidates by offset+limit and applies paging after the merge. Merged order: requested sorts (formats resolved via one store — bundled relations are identical across spaces), else the injected _final_score for fulltext queries.
| Commit: | f173ef8 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7449 Browse mode: empty fullText returns the latest messages in scope Empty query = the search screen's entry state: newest messages of every chat in scope, served from the message stores instead of FT (no indexing lag — a just-sent message appears immediately). Chats are enumerated from the object index (chatDerived|discussion, not deleted; cross-space query for the vault scope); each contributes its newest offset+limit messages by orderId, merged and sorted — default CREATED_AT desc, since scores don't exist without a query. Failing chats are skipped in multi-chat scopes, same as search.
| Commit: | da53491 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7449 Apply 3-lens review fixes: store-backed liveness gate, error isolation Review round (3 independent lenses) findings applied: - F1 (high): the preview registry covers only chatDerived, but message docs are FT-indexed for discussion (object chats) too — the space scope silently dropped object-chat hits. The gate is now isLiveChat: the per-space object index is queried for layout chatDerived|discussion and not-deleted, which also removes the Search dependency on the registry entirely. - F2 (major): one failing chat (space mid-deletion, broken store) aborted the whole multi-chat search and could resurrect a deleted space's crdt.db via a stale registry entry — multi-chat scopes now log and skip the chat; the single-chat scope keeps the hard error. - F3 (major): chatRegistrySnapshot serialized search behind the s.lock hold that Run keeps across the cross-space subscription bootstrap — gone with the registry. - SpaceId attribution: hits now carry the doc's stored SpaceID field (DocumentMatch.SpaceId), so results are attributable in every scope, including chatId-set/spaceId-empty. - ftLimit capped at 2000 (ftCandidatesHardLimit parity), bare error return wrapped, proto comment aligned with actual scope semantics (ORDER_ID note moved to sorts), ForceFTIndex comment no longer oversells freshness. Regression tests: discussion-layout inclusion, non-chat layout exclusion, broken-chat survival, stored-space attribution. Spec updated accordingly.
| Commit: | 32baa8c | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7449 Add spaceId to chat search results, document search scopes model.Search.Message.Result gains spaceId so hits are attributable when the search spans multiple chats or spaces. Chat.Search.Request comments document the new scope semantics: empty chatId = all chats in spaceId, empty spaceId = all spaces.
| Commit: | 20f452d | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7383 Provenance records the RAW app name, compared exactly (spec §5 revised) The stamped and compared value becomes the raw session AppName; the proto field is renamed to say what it holds — pb.Change.integrationName / ChangeNoSnapshot.integrationName, wire number 10 unchanged. The slug normalization is dropped at the root: it was many-to-one (F2, executed — a key paired as "Claude/Desktop" archived "Claude Desktop"'s output while the consent dialog showed two different strings) and lossy (F3, executed — Cyrillic/CJK/emoji names slugged to "", leaving those keys' objects permanently unprovenanced). The tolerance normalization bought (re-pair as "claude desktop" still matched) is deliberately given up: for an authorization comparison, tolerance is a liability. IntegrationKeyFromAppName is DELETED, not parked: with the raw name on the change it has no caller, and attribution's integration object will hash the raw name for its unique key (display comes from the name detail), so the slug is not its future helper either — keeping it would be a rival spelling authority. What remains in core/domain (integrationname.go): the ctx carrier, renamed CtxWithIntegrationName/IntegrationNameFromCtx, and the new bound. The bound: no length limit existed anywhere on AppName, and the raw name now rides every creating change and debug exports — CreateApp and the challenge flow (effective name: requested, else process name) reject names over domain.MaxIntegrationNameLen (128 bytes); reject, never truncate. The §11.7 empty-name guard is now sufficient as issued: no non-empty name can lose its record. Regression pins, each verified to fail under a simulated revert: middleware installs slug-hostile names raw ("Claude/Desktop", привет, \U0001f642); DELETE refuses the F2 pair "Claude Desktop" vs "Claude/Desktop" naming both; the F3 shape (both sides привет) archives; issuance refuses 129 bytes and mints 128. Spec: APIV2_OBJECT_DELETE.md §5 rewritten (the slug argument replaced by the revision record), §8/§10/§11/§12/§13/§14/§15 made consistent; APIV2.md §8.42 rule paragraph updated. protoc regen moved only pb/changes.pb.go + docs/proto.md.
| Commit: | b4920dd | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7383 pb.Change/ChangeNoSnapshot: integrationKey = 10, copied on the no-snapshot read path The change-level provenance field the object-DELETE rule reads and integration attribution later shares (APIV2_OBJECT_DELETE.md §11.1): a normalized slug of the paired app's name, stamped by heart from the session. Both messages take wire number 10 — they share numbers by design (content 3, fileKeys 6, timestamp 7, version 8, changeType 9; 1/2/5 are historical and stay unused). The ChangeNoSnapshot→Change conversion copies the field so a value written at creation is not silently dropped on every subsequent read.
| Commit: | 58b80d9 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7433 Add ObjectDeletionAudit RPC Lists what was removed from a space, newest first, with who created and who removed each one. Two sources, merged into one chronological list. Deleted objects come from the space settings tree, the space-level log every deletion is recorded in. Each of its changes is signed, so it carries the deleter's identity and the deletion time, and storage keeps those changes forever since tree reduction only prunes the in-memory tree. The walk starts at the root rather than resuming from the last change seen: a settings change synced from another device attaches under its own parent, which can sit behind wherever the previous walk stopped, and iterating from there would step over it forever. The mark is the tree's heads, checked from one head-storage lookup, so an unchanged tree costs nothing and never builds the tree at all. Types, properties, relation options and templates come from their own trees. These are never actually deleted — deleteDerivedObject sets isUninstalled and leaves the tree intact — so they never reach the settings tree. That leaves the evidence in better shape, not worse: isUninstalled is an ordinary synced detail, so setting it produced a signed change whose identity and timestamp are exactly who and when, and the object keeps its name, which no destroyed object can. The last change touching the relation wins, in either direction: tracking only the trues would pin whoever uninstalled it before the most recent reinstall. isUninstalled discriminates the two kinds in the response. Only one is reversible, and presenting them identically misstates what happened. Client implementation plan: anytype-ts/docs/plans/2026-08-09-deletion-audit-desktop.md
| Commit: | f15d6e8 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7383 API v2: scoped API keys — auth hygiene, the grant, and enforcement An API key can now be granted {spaces x read|readwrite}. No existing key breaks: enforcement is /v2-only, so /v1 behaves exactly as it ships today, and legacy keys are grandfathered and signalled rather than refused. P0, the pre-existing holes that made scoping meaningless until fixed: - H1 SolveChallenge minted the pairing session with the zero-valued named return (Limited) instead of challenge.scope, so a gRPC-paired JsonAPI client got a live Limited gRPC session in any space. - H2 the HTTP gate never consulted scope; a clipper key opened the whole JSON API. The gate now refuses non-JsonAPI/Full keys, on /v2 only. - H3 CreateApp persisted any scope, Full included; now rejected. - H4 revocation closed one session per app hash and missed tokens derived via WalletCreateSession(token:). It now sweeps the full token set through a reverse index, and ReadAppLink re-derives AppHash (it is json:"-", so every HTTP-minted session had been filed under "" and survived revoke). - H5 ExpireAt was stored and never enforced; now checked at mint and per request, evicting the cached entry. P1, the grant: - AppLinkGrant lives inside the sealed, HMAC-bound, signed envelope, at file version 2 so an older binary refuses a scoped key rather than honoring it unscoped. Validation is one persist-time gate, re-run at read. - New JSON-API keys mint as anytype_<52 base32>_<8 hex crc32>. The body alphabet excludes base64's + / = so the key survives \b-anchored scanner rules, query strings, double-click and shell quoting. Parsing strips the prefix and hashes the same raw bytes, so every existing key resolves. Format is never an authorization input; the grant is the sole authority. - Enforcement: apiv2.ensureSpaceGrant on the /v2 group over an explicit 46-entry route registry (verb x global class), fail-closed on anything unregistered; the tech space denied unless granted; granted keys refused on /v1; global search and space listing intersect their INPUT set so a non-granted space cannot leak through a per-space warning; a service-layer backstop carries both the space and verb halves at every write entry. - GET /v2/auth/whoami derives from the same grant record the gate reads — one derivation, so the mirror cannot drift from the gate. grant.scoped is an explicit boolean: spaces:null for a legacy key would be a fail-open trap. WWW-Authenticate accompanies auth failures. - Legacy keys get Anytype-Key-Status/Anytype-Notice and a Link rel="deprecation", never RFC 9745 Deprecation/Sunset: those require a Date and scope the signal to the resource, which on /v1 would assert the opposite of the grandfathering promise. - docs/secret-scanning/ ships detection-only gitleaks and TruffleHog rules on the published range pattern. Grants are issuable and editable over the gRPC app-link surface (CreateApp, the new UpdateApp, and a requestedGrant honored at SolveChallenge); the desktop picker rides the separate challenge rework.
| Commit: | e6fadf0 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7349 importv2 llm: AIParams on the import request (proto) Optional BYOK enrichment config: AIParams submessage (field 16) wrapping the existing Rpc.AI.ProviderConfig plus the includeContentSamples flag (docs/ImportV2LLM.md §9). Absent = feature off.
| Commit: | 6d4f18b | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7349 Merge remote-tracking branch 'origin/go-7383-anyblockjson' into go-7349-import-llm # Conflicts: # core/indexer/fulltext.go # core/indexer/fulltext_test.go # go.mod # pb/events.pb.go
| Commit: | c572323 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7395 Approve local-link pairing before minting the code Local-link pairing minted the 4-digit code the moment a challenge was requested and broadcast it to every session, so an unapproved request always had a secret to guess and the per-run counters were the only DoS defence. Rework the flow to approve-then-mint: - StartNewChallenge registers a pending request and mints nothing. The new LinkApprovalRequest event names the caller (process path, browser origin) and carries no code. - AccountLocalLinkApproveChallenge is the user's decision. It is the only place a code is minted and returns it to the approving session alone, never on the event bus. Addressed by (processPath, origin) — the caller the prompt displayed; one pending prompt per caller keeps it unambiguous. - SolveChallenge gates on approved state; a solve against a pending challenge does not count against the failure budget. - Denials are remembered for the app run; pending prompts expire after 60s, approved codes 5 min after approval (SweepExpired). The requesting client's API (/v1/auth/challenges, /v1/auth/api_keys) is unchanged; only the desktop client gains the approval step. Headless deployments use AccountLocalLinkCreateApp, which mints a key with no challenge, so no auto-approve backdoor is added. Security: AccountLocalLinkApproveChallenge stays out of noAuthMethods and limitedScopeMethods so authorization admits full scope alone, and it rejects any caller carrying an Origin header. Both pinned by tests. Incorporates the origin-attribution groundwork it depends on: ClientInfo.origin from the browser's Origin header, process resolution for JSON API callers, and per-caller challenge budgets. Docs: docs/LocalLinkPairingApproval.md (design), docs/LocalLinkApprovalDesktopGuide.md (client integration).
| Commit: | 46e015d | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7379 Merge develop; regenerate protos Only the generated pb/commands.pb.go conflicted (pb/protos/commands.proto merged cleanly); resolved by re-running make protos-go over the merged sources. networkId field intact.
| Commit: | d4a4092 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7222 Share an anyoneCanJoin invite only as a reader's link Nobody approves a join made through an anyoneCanJoin link: whoever holds it is in the space, with the permissions the invite carries. Read access is as much as a member is trusted to give away, so an invite that grants more than that stays in the owner's account. domain.ShareableWithinSpace is the rule, and the three ways to arrive at a shared invite that grants too much all go through it: generating one, publishing one the owner holds, and raising the permissions of one that is already shared. Each is refused with INVITE_NOT_SHAREABLE.
| Commit: | bc61498 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7222 Publish an owner-held invite instead of replacing it InviteGenerate for an invite of the type the space already has now decides on the sharing mode without touching the acl. Asking for shareWithinSpace on an invite the owner holds publishes it: the same cid and key move out of the owner's space view and into the workspace, no acl record is replaced and no new file is stored, so the link the owner already handed out keeps working. The other way round is refused with INVITE_ALREADY_SHARED. The workspace's change history has already given that invite's cid and key to every member of the space, and clearing the details would not take it back -- only revoking the invite does, and that is the client's call to make.
| Commit: | 78141f0 | |
|---|---|---|
| Author: | Roman Khafizianov | |
| Committer: | Roman Khafizianov | |
GO-7222 Keep space invites in the owner's account unless shareWithinSpace Rpc.Space.InviteGenerate gets a shareWithinSpace flag. Without it the invite's cid and key go to the owner's space view, which only their own devices sync, and the workspace -- which every member of the space syncs -- is left with nothing but the spaceInviteHeldByOwner marker. Members read the marker through InviteGetCurrent as heldByOwner with an empty cid and key: they learn an invite exists and that the owner is the one to ask for the link. With the flag set, the invite goes to the workspace as before and any member can share it. Generate and Revoke always write both objects, so switching a space between the two can never leave the previous invite readable where it used to live.
| Commit: | a13b4fa | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7379 Add networkId to DeviceNetworkStateSet for instant same-type switch recovery The type enum alone cannot express 'same type, different network' (Wi-Fi->Wi-Fi SSID switch, cellular PDP re-attach, VPN reconnect), so those OS callbacks were deduped away and recovery waited on the 5s interface poll or transport keepalives. Clients now pass the OS path identity (iOS: NWPath interfaces/gateways digest; Android: Network#getNetworkHandle()) and an identity change triggers the connectivity recovery pipeline immediately. Backward compatible: empty networkId keeps type-only semantics; the identity only counts as changed when known both before and after, so older clients see no behavior change.
| Commit: | 92f61c4 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7368 Add client pubsub: middleware protocol over any-sync ephemeral pub/sub Expose the any-sync space-scoped pub/sub engine to app clients: - PubsubPublish/PubsubSubscribe/PubsubUnsubscribe RPCs with wildcard topic patterns and subId-keyed subscriptions - Event.Pubsub.Message broadcast with verified sender identity - payloads encrypted with the space's current ACL read key (same key as object changes), decrypted+verified before events are emitted - LAN peers served via the shared DRPC server; publishes go to the responsible node plus LAN peers - docs/pubsub: design doc and client developer guide (topics, cadence, closing messages)
| Commit: | ce9ca6d | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7349 importv2: import report page + API surfacing (§16.1, decision §13.7) The issue ledger now reaches users instead of dying in Result.Issues. A run that produced warning-or-worse issues persists one report page in the space through the normal pool: a summary table (severity x code x count) and a toggle per group with a line per issue, mention-linked to the created object when its source key resolves (marks carry source keys so the resolver rewrites them like any other ref). The page is the primary surface - clients render a discard button on it; it is claimed before finalize so the root collection lists it. Report failures degrade to warnings and can never abort a finished import. Info-only runs stay clean (flavour/type-suggestion diagnostics ride along, never cause a report). API (sanctioned 2026-07-11): NotificationImport and EventImportFinish gain reportObjectId + issuesCount. The adapter also emits one structured end-of-run log line (counts by severity/code) so Sentry/Graylog events name the failing code and object class. Parity test excludes the v2-only report page.
| Commit: | 9b3e643 | |
|---|---|---|
| Author: | Roman Khafizianov | |
| Committer: | Roman Khafizianov | |
GO-7323 Add ObjectCleanupSuggestions and ObjectCleanupSuggestionIgnore protos
| Commit: | 490f764 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7323 Rename OrphansDetected event to CleanupSuggestion Phase 1 is unmerged, so the protocol has never shipped. The popup event and the new space-wide cleanup list are the same concept; unify the client-facing vocabulary on 'cleanup suggestion'. Internal Go keeps the precise term 'orphan'. Field number 146 and the Trigger enum are unchanged.
| Commit: | 996b348 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7323 Merge branch 'develop' of github.com:anyproto/anytype-heart into go-7323-cascade-deletion-orphan-events # Conflicts: # pb/commands.pb.go
| Commit: | 0146559 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7362 debug: make DebugRunProfiler trace opt-in, drop account_select_trace A timed DebugRunProfiler run now captures only CPU + heap(start/end) + goroutines(start/end) by default. The runtime execution trace is the heaviest artifact in both archive size and runtime overhead, so it is now opt-in via a new includeTrace flag on RpcDebugRunProfilerRequest. The in-flight account_select_trace is removed from the profiler bundle entirely, so the login flight recorder is left untouched by the profiler. RunProfiler is split into a testable runTimedProfiler(profilesDir, ...) inner method so the capture logic can be exercised without the global initialparams singleton; a new test asserts the trace gating.
| Commit: | ad586ff | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7323 Add OrphansDetected event and skipCascade request field
| Commit: | 92cc65a | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7292 Merge origin/develop into go-7292-client-driven-lazy-multispace-loading Resolve the chatsubscription warm-up conflict by adopting develop's gated warm-up (GO-7302): warm the chat tree only for full subscriptions (!OnlyLastMessage), skipping vault previews. Restored the objectGetter dependency, Init wiring, and cache/zap imports that the branch had dropped. Regenerated pb/commands.pb.go via `make protos`.
| Commit: | 66f0ce4 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7311 Support text ranges for first/last block in BlockCopy/BlockCut Add optional selectedTextRangeLastBlock to Rpc.Block.Copy.Request and Rpc.Block.Cut.Request. When set and the request contains multiple blocks, selectedTextRange is applied to the first block and selectedTextRangeLastBlock to the last block, so a selection can start and end in the middle of text blocks. Blocks in between are copied/cut whole; on cut, partially selected blocks keep the unselected part of their text. When the new field is not set, behavior is unchanged.
| Commit: | 07cca8a | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7292 Merge origin/develop into go-7292-client-driven-lazy-multispace-loading
| Commit: | 33c2cb4 | |
|---|---|---|
| Author: | Sergey Cherepanov | |
GO-7300 Push limit/offset to anystore in objects list API The GET /spaces/:id/objects API built an unbounded ObjectSearch request and applied limit/offset in memory, so any-store fetched and sorted the entire filtered result set just to return one page. Add a needTotal flag and total field to the ObjectSearch RPC. Implement spaceindex.QueryAndCount, which compiles the filters once and returns both the limited page and the full count (via coll.Find(filter).Count) without materializing or sorting the whole set. ListObjects now requests limit+1 to derive hasMore and reads the exact total from the response. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| Commit: | cb10981 | |
|---|---|---|
| Author: | Roman Khafizianov | |
| Committer: | Roman Khafizianov | |
GO-7292 Add preferredSpaceId + AccountPreloadRemainingSpaces proto
| Commit: | 0277214 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-6473 Add Admin to ParticipantPermissions enum
| Commit: | d30e876 | |
|---|---|---|
| Author: | Anthony Akentiev | |
| Committer: | GitHub | |
GO-7233 V2CartUpdate: IsLifetime option (#3125)
| Commit: | 6ff8f79 | |
|---|---|---|
| Author: | Sergey | |
GO-7214 Merge branch 'develop' of github.com:anyproto/anytype-heart into go-7214-quote-block
| Commit: | 329e0db | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7143 jsonInfo + KindGoroutines + trim DB path + rename LONG_RPC Proto (Event.Debug.ProfileCreated): - reasonDesc -> jsonInfo. The middleware always JSON-encodes extras (debugreporter.Reporter.Report marshals map[string]any), so the new name tells downstream consumers they can parse it directly and forward structured context to Sentry. - Expand comments: `reason` is NOT the DebugRunProfiler Reason enum; values come from the internal call sites (MEMORY_GROWTH, LONG_RPC, DB_CORRUPTION, ...). KindGoroutines: a lighter artifact for cases where goroutine stacks are the signal and a heap snapshot would be noise. debugsnapshot.Save learns a variadic options parameter (WithoutHeap). The long-RPC interceptor switches from KindHeap to KindGoroutines — the blocked stack is the actionable bit, and skipping heap.pb.gz cuts per-incident artifact cost noticeably. Rename LONG_METHOD -> LONG_RPC. Method was ambiguous (Go method? class method?); LONG_RPC matches the casing of the other internal reasons and makes clear we are talking about gRPC calls. Privacy: DB_CORRUPTION reports now send "parentDir/file.db" instead of the full absolute path — enough to identify which database was corrupted without disclosing the user's home directory or account layout through Sentry.
| Commit: | 974d306 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7143 Rename reasonDesc->jsonInfo, add KindGoroutines, strip db paths Proto changes (Event.Debug.ProfileCreated): - reasonDesc -> jsonInfo. The middleware always JSON-encodes its extras (see debugreporter.Reporter.Report which marshals map[string]any), so the new name tells downstream consumers they can parse it directly and forward structured context to Sentry. - Expanded comments to spell out that `reason` is NOT the DebugRunProfiler enum — values come from the internal call sites (MEMORY_GROWTH, LONG_METHOD, DB_CORRUPTION, ...). KindGoroutines: a lighter artifact for cases where goroutine stacks are the signal and heap data is noise. debugsnapshot.Save learns a variadic options parameter (WithoutHeap). The long-method interceptor switches from KindHeap to KindGoroutines — the blocked stack is the actionable bit, and skipping heap.pb.gz cuts per-incident artifact cost noticeably. Privacy: DB_CORRUPTION reports now send "parentDir/file.db" instead of the full absolute path — enough to identify which database was corrupted without disclosing the user's home directory or full account layout to Sentry.
| Commit: | f8ce064 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7143 Emit Event.Debug.ProfileCreated for server-initiated profiles Add a new oneof entry on Event.Message — Debug.ProfileCreated (field 145) — carrying reason, reasonDesc, path and a full bool. It signals that the middleware wrote a profile archive on its own accord, so clients can surface it or queue the archive for upload without polling common/profiles/. DebugRunProfiler responses already carry the path, so those aren't re-announced. Producers: - core/debug/profiler (desktop): after a successful memory-growth snapshot, broadcast via the event sender injected at Init. Mobile builds remain a no-op via the existing build-tag split. - metrics.saveLongMethodTrace: gains a SetProfileCreatedHook callback (atomic.Value, nil-by-default) that is invoked after each successful long_method_*.txt.gz write. The profiler component registers the hook in Init so both producers go through one broadcaster, and metrics stays free of a direct dependency on core/event. Proto regen covers events.pb.go and the generated docs.
| Commit: | f846755 | |
|---|---|---|
| Author: | Sergey | |
GO-7214 Split quote block into editor and message variants Replace MessageBlockQuote with two distinct variants: - MessageBlockEditorQuote for quoting a block from an editor object (blockId + content) - MessageBlockMessageQuote for quoting a chat message (messageId + participantId + content) Embed MessageBlockText as the shared content shape so quotes carry style, marks, checked, and lang for free. Extract marshalTextContent / unmarshalTextContent / validateTextContent helpers and reuse them from the text block and both quote variants. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| Commit: | 167848c | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7143 Add startup/shutdown logs, report options, buffered-log flush on close Lifecycle: - Log "starting app" with middleware and full app version in StartNewApp. - Log "closing app: initiated" and "closing app: finished" (with elapsed ms) in application.Service.stop(), and call log.Sync() at the tail so the shutdown line actually drains the buffered zap sink before exit. - Promote "anytype-app" and "anytype-core-account" to INFO in the default log levels so these lifecycle markers emit. DebugExportReport: - Add bool full to RpcDebugExportReport.Request; when false (default) include only the 2 newest log files by mtime, when true include all. - Preserve each source file's modification time in the zip via zip.FileHeader.Modified instead of using the archive creation time. - Rename the output archive to anytype-report-<version>-<YYYYMMDD-HHMMSS>-*.zip for easier triage. Logging buffer: - Use the same 256KB buffer / 30s flush interval on all platforms; mobile only keeps smaller rotated log files for disk reasons.
| Commit: | bc1a2fd | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7143 Merge remote-tracking branch 'origin/develop' into go-7143-improve-loggingtracingreporting
| Commit: | a6ecdae | |
|---|---|---|
| Author: | Anthony Akentiev | |
| Committer: | GitHub | |
GO-7118 membership: new option - Lifetime (#3103)
| Commit: | ae7fd86 | |
|---|---|---|
| Author: | Sergey | |
GO-7214 Add quote block type for chat messages Add MessageBlockQuote variant to ChatMessage.MessageBlock oneof with blockId and text fields. Wire marshal/unmarshal in the anyenc layer and require both fields non-empty on validation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| Commit: | fb681c2 | |
|---|---|---|
| Author: | Sergey | |
| Committer: | GitHub | |
Merge pull request #3092 from anyproto/go-6962-personal-favorites GO-6962 Personal favorites
| Commit: | 93feeb2 | |
|---|---|---|
| Author: | Sergey | |
GO-7168 Merge branch 'develop' of github.com:anyproto/anytype-heart into go-7168-notification-preferences-unread-tracking-for-object
| Commit: | 72f38bc | |
|---|---|---|
| Author: | Sergey | |
GO-7166 Split message count out of chat state Move messageCount from ChatState to a dedicated field on ChatGetMessages/ChatSubscribeLastMessages responses and emit a ChatUpdateMessageCount event when the count changes. Add CountMessages to the chat repository. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| Commit: | 3bb5fa4 | |
|---|---|---|
| Author: | Sergey | |
GO-6962 Merge branch 'develop' of github.com:anyproto/anytype-heart into go-6962-personal-favorites
| Commit: | 461a0c1 | |
|---|---|---|
| Author: | Sergey | |
GO-7166 Add message count to chat state Track total non-deleted message count in ChatState, populated on load and incremented via ChatStateUpdate events on new messages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| Commit: | 0392fba | |
|---|---|---|
| Author: | Sergey | |
GO-7168 Add notificationSubscribers relation to chat object Store the subscriber set as a participant-id list on the details doc via AddToSet/Pull so the format is compatible with a list<string> relation. Auto-subscribe the creator on ObjectAddDiscussion. Expose ChatAddNotificationSubscriber / ChatRemoveNotificationSubscriber RPCs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| Commit: | 9da7884 | |
|---|---|---|
| Author: | Sergey | |
GO-6962 Add personal widgets virtual object backed by tech-space store Personal favorites widgets are now stored in a single per-account CRDT store object in the tech space and projected into each space as a virtual SmartBlock under the hardcoded id `_personalWidgets_<spaceId>`. The tech-space store (SmartBlockTypeTechSpaceObject) holds all widget entries for all spaces. The per-space virtual widget (SmartBlockTypeTechSpaceVirtualObject) is a StaticSource smartblock that loads its entries from the store via a mediator Service, and on every Apply does a deterministic snapshot-sync of the block tree back into the store (Create / Delete / Update with AfterId — no linked-list repair, no MoveWidget). Wiring highlights: - techspace.Run now derives the personal favorites store on both create and load paths. - NewStore receives its update callback at construction time; the store dispatches observer fan-out on a goroutine so local pushes don't re-enter the caller's smartblock lock. - Handler.pending is mutex-guarded; BeforeModify/Delete look up the doc's spaceId so observer dispatch can filter by space. - idresolver.ResolveSpaceID short-circuits '_personalWidgets_*' by parsing the id directly — no dependency on the bindId index, which isn't populated on a clean cache. - smartblock.Apply's empty-tree guard now also exempts SmartBlockTypeTechSpaceObject, matching AccountObject. - Store values go through anyenc (arena.NewString / NewNumberInt) to avoid the "unexpected tail" parse failure caused by passing raw Go strings through storestate.Builder.Modify. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| Commit: | 0bd3c3f | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7152 Merge branch 'develop' of ssh://github.com/anyproto/anytype-heart into go-7152-context-aware-gc-all-objects # Conflicts: # pb/commands.pb.go # util/builtinobjects/data/get_started.zip
| Commit: | dffc943 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7152 Emit ObjectAutoRestore event when GC auto-restores objects Mirror the ObjectAutoArchive event for the unarchive direction: emit EventObjectAutoRestore from restoreObjectsOnUnarchive and CheckObjectsOnLinksRestored so callers can update their UI accordingly.
| Commit: | 13a5715 | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Merge develop
| Commit: | d428afd | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7152 Emit ObjectAutoArchive session event when GC archives files When the GC archives file objects as a side effect of archiving/editing, accumulate an Object.AutoArchive event in the session context so the originating client can show a toast. Key changes: - Add Object.AutoArchive proto event (field 142) and regenerate - Add sctx session.Context param to all three ObjectGC interface methods and thread it from every call site (API handlers, smartblock.Apply, chats service, delete, fileobject service, objectcreator) - Add accumulateAutoArchiveEvent helper in filegc that merges IDs into a single deduplicated event per session, so nested cascades produce exactly one event - Make triggerFileGCOnArchive synchronous so archive RPCs capture events before getResponseEvent is called - Add ResponseEvent event field to SetIsArchived and ListSetIsArchived responses; wire getResponseEvent in both RPC handlers - In smartblock.Apply use session.NewChildContext for the async GC goroutine and push accumulated events via SendToSession after it finishes, avoiding the page.Lock -> archive.Lock deadlock
| Commit: | 334f9e3 | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Template placeholders stage 1
| Commit: | 8977186 | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Merge develop
| Commit: | 07bd9bf | |
|---|---|---|
| Author: | kirillston | |
GO-6946 Space Members Add List RPC
| Commit: | ad15851 | |
|---|---|---|
| Author: | Roman Khafizianov | |
GO-7143 IOS-5994 Add DebugExportReport, DebugCleanupReport RPCs; export FreeOSMemory to clib - Rename DebugExportLog → DebugExportReport; add lastModifiedTs to response (unix ts of newest source file — pass to DebugCleanupReport after upload) - Add DebugCleanupReport(ts) RPC: removes log and profile files with modTime < ts - DebugRunProfiler: document durationInSeconds, replace string reason with typed enum (USER_REQUEST, MEMORY_PRESSURE_WARN/CRITICAL, THERMAL_SERIOUS/CRITICAL), add reasonDesc string for free-form context - Export FreeOSMemory() from clib (calls debug.FreeOSMemory — GC + release to OS) for iOS/Android to call on critical memory pressure signals
| Commit: | 1f48935 | |
|---|---|---|
| Author: | kirillston | |
GO-6946 Add permissions parameter
| Commit: | c73597c | |
|---|---|---|
| Author: | kirillston | |
GO-6946 Merge dev
| Commit: | cafc566 | |
|---|---|---|
| Author: | kirillston | |
GO-3455 New err code on BlockPaste
| Commit: | cc8c340 | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6915 Add Delete cmd
| Commit: | aa1a2c0 | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6915 Update data format
| Commit: | 9ff4d7c | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6915 Move rpc to template namespace
| Commit: | 0620736 | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6915 Add API for tmpl placeholders
| Commit: | 133a140 | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6915 Use MapValue
| Commit: | f0cf1ca | |
|---|---|---|
| Author: | kirillston | |
GO-6946 Add SpaceParticipantsAddList API and refactor inbox sender Introduce SpaceParticipantsAddList RPC endpoint that adds members to a space by identity and sends inbox invites. Refactor onetoone service into inbox/inboxsender package, consolidating one-to-one and regular space invite logic under a single Sender interface. Move inboxclient into core/inbox/ directory for better package organization. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 7c96c8d | |
|---|---|---|
| Author: | kirillston | |
GO-6752 Add homepage setting with migrations and fallback - Add homepage relation and SetHomepage command - Add SpaceType enum derived from space header - Migrate existing spaceDashboardId to homepage - Reset homepage on object deletion - Default homepage to widgets across all creation paths - Deprecate SpaceUxType_Chat in favor of SpaceType Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 7f37e85 | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6752 Support spaceType in invites
| Commit: | 9ae5dfe | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6752 Cover TODOs WIP
| Commit: | 45c001e | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6752 Add SetHomepage command
| Commit: | 0751ce8 | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6752 Add new relations WIP
| Commit: | 53fb44a | |
|---|---|---|
| Author: | kirillston | |
| Committer: | kirillston | |
GO-6752 Deprecate UXtype=chat
| Commit: | 755ec1b | |
|---|---|---|
| Author: | kirillston | |
GO-7002 Merge develop
| Commit: | 528182d | |
|---|---|---|
| Author: | Sergey Cherepanov | |
GO-6411 acl delete permissions
| Commit: | 9c9d60a | |
|---|---|---|
| Author: | kirillston | |
GO-7002 Add alternateRows bool flag to Dataview View Add alternateRows field (field 19) to the Dataview.View proto message and ViewUpdate.Fields event, following the same pattern as wrapContent. This allows clients to persist and sync the alternate row background colors setting for Grid View. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 26d02cd | |
|---|---|---|
| Author: | Sergey | |
GO-6807 Add reindex discussions method Add ForceReindexDiscussionsCounter (set to 1) to trigger reindexing of discussion objects. This clears their anystore collections and rebuilds from the tree, which is needed after the flusher fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| Commit: | b2c2885 | |
|---|---|---|
| Author: | Sergey | |
GO-6807 Add checked and lang fields to MessageBlockText Add bool checked and string lang fields to chat message text blocks, with zero-value omission in any-enc serialization. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | a43d599 | |
|---|---|---|
| Author: | Sergey | |
GO-6807 Add embed block type to chat message parts Add MessageBlockEmbed with text and processor fields (reusing Block.Content.Latex.Processor enum) as a third variant in the MessageBlock oneof, alongside Text and Link. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | c90f29f | |
|---|---|---|
| Author: | Sergey | |
GO-6807 Merge branch 'go-6807-object-discussions-comments' into go-6807-object-create-discussion
| Commit: | f73893e | |
|---|---|---|
| Author: | Sergey | |
GO-6807 Add ObjectAddDiscussion gRPC method Implement ObjectAddDiscussion RPC that creates a derived Discussion object bound to a parent object via ParentId, enabling cascading deletion. Bump any-sync to pick up ParentId support in ObjectTreeDerivePayload and thread it through the derivation flow. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 71c3001 | |
|---|---|---|
| Author: | Sergey | |
GO-6807 Add Discussion object type, layout, and SmartBlockType Introduce a new "discussion" layout and object type backed by a dedicated SmartBlockTypeDiscussionObject (0x222). The discussion editor reuses the chat store object implementation, with the factory passing the correct type key and layout at construction time. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 97e14ac | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Support multiple values
| Commit: | 129de38 | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Remove map format
| Commit: | 92373ee | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Placeholders based on store
| Commit: | 5d41dc1 | |
|---|---|---|
| Author: | Sergey | |
GO-6743 Remove unused LastUnreadReactionOrderId proto field The field was populated but never consumed by any code. Simplified unreadReactionIdsToModel to return only the map. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 1bbbd74 | |
|---|---|---|
| Author: | Sergey | |
GO-6807 Add MessageBlock to ChatMessage protocol Extend ChatMessage with repeated MessageBlock blocks field supporting structured content: text blocks with styles/marks and typed links (Object, File, Image, Bookmark) to objects/files. Includes serialization, validation, mention detection across blocks, full-text search indexing, push notification support, and file GC cleanup for link block targets. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | ad80756 | |
|---|---|---|
| Author: | Sergey | |
GO-6743 Remove unused orderId param from MarkReadReactions The orderId was passed through the entire call chain but never used. Also update proto comment for unreadReactionOrderId. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | df21b8c | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Move rpc to template namespace
| Commit: | e5b6738 | |
|---|---|---|
| Author: | Sergey | |
GO-6743 Merge branch 'fix-chat-parallel-subscriptions' into go-6743-unread-reaction-tracking
| Commit: | 5803dab | |
|---|---|---|
| Author: | Sergey | |
| Committer: | Sergey | |
GO-6743 Smart partial clearing in markReadReactions callback Derive maxOrderId from tree changes in the diff manager callback and pass it to the repository modifier. The modifier now distinguishes full clears (message orderId <= maxOrderId) from partial clears (only remove individual reaction entries up to maxOrderId). This replaces the previous blind-delete approach that ignored partial reads. Remove GetUnreadReactionChangeIdsUpToOrderId — orderId filtering now happens in the modifier, not the query. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 8a22008 | |
|---|---|---|
| Author: | Sergey | |
GO-6743 Rename ChatReadReaction to ChatReadReactions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 0a07d9e | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Add API for tmpl placeholders
| Commit: | 1496395 | |
|---|---|---|
| Author: | Sergey | |
GO-6449 Merge branch 'develop' of github.com:anyproto/anytype-heart into go-6449-upload-filesmedia-to-space
| Commit: | f7d03c0 | |
|---|---|---|
| Author: | Sergey | |
GO-6743 Add unread reaction counter with three-state reactionRead field Track unread reactions on the user's own messages using a three-state reactionRead field (absent=no tracking, false=unread, true=read). New reactions only mark as unread when the field is absent, preventing re-triggering after reactions have been seen. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | 45e78e1 | |
|---|---|---|
| Author: | Sergey | |
GO-6449 Filter dropped files by type and return filesCount in response When the Drop request specifies Image, Audio, or Video type, only files matching that type (detected via MIME magic bytes) are collected for upload. Directories are walked recursively to find matching files but no collections are created for them. The response now includes filesCount with the number of files selected for upload. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | e14d4e9 | |
|---|---|---|
| Author: | Sergey | |
GO-6449 Support FileDrop with empty contextId for direct space uploads When contextId is empty, files are uploaded directly to the space without attaching to any container object. Directories still create collections. A new spaceId field on File.Drop.Request identifies the target space. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| Commit: | e619fcd | |
|---|---|---|
| Author: | kirillston | |
GO-6915 Use MapValue
| Commit: | 621c682 | |
|---|---|---|
| Author: | kirillston | |
GO-6876 Merge develop
| Commit: | b2bba4f | |
|---|---|---|
| Author: | kirillston | |
GO-6876 Add filter id to responses
| Commit: | 801b0b7 | |
|---|---|---|
| Author: | kirillston | |
GO-6749 Add pinned sparse index