Conversation
…tion log Full rewrite dated 2026-07-31. Cross-checked backend source, live docs, and the iOS client; adds a prioritized gap list, the ready-now vs backend-blocked split, live-probe evidence, and a phase-by-phase implementation plan/progress log. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…st-data-rows export Tier-0 defects (D1/D2/D3) — routes verified PATCH-only against backend source: - updateProfile/updateUserSettings: POST → patchCamel (/api/user/update) - editMessage: PUT → patchCamel (/api/messages/:id) - markNotificationRead: PUT → patch (/api/notifications/:id/read) G7: MutedUsersView (API already wired) linked from Settings. G8: exports now accept Bearer — add ExportType.listDataRows (4th CSV export). Also corrects 3 stale tests to match backend truth (multipart 'file', 'folderId'). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New DirectMessage models + 11 APIClient methods (/api/dm/*, Bearer, free). MessagesInboxView (inbox/sent/deleted) + DMThreadView (chat bubbles, markdown, image attach, block/not-mutual states, ~4s /updates poll). Envelope badge in MainTabView from AppDataStore.dmUnreadCount; 'Message' button on profiles. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
G3: documentTemplates() + createDocumentFromTemplate() (subscriber-gated) with a 'Start from template' picker in DocumentsView; DocumentTemplate model. G6: searchUsers() + FindPeopleView (searchable, debounced) linked from Profile. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrote LinkedInTarget to the real backend union {kind,pageId?,personalPageId?}
(dropped the wrong 'organizationId'). Added LinkedInPostingTarget +
linkedInPostingTargets(); ComposeView multi-select (subscriber + LinkedIn
identity) maps selected targets into linkedInTargets on post, personal-fallback.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Share-links (create/copy/revoke, watcher/collaborator/manager roles) for lists AND documents via a reusable ShareLinksSheet; per-person DocumentCollaboratorsView (reused WatcherRole). 8 APIClient methods (create subscriber-gated). Wired into list detail and document detail. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
UserList gains source/githubRepo/githubMeta; GitHubRepo/GitHubIssue models; githubRepos()/githubIssues()/refreshList() + createList(githubSource:). Repo picker in CreateListView gated on AuthState.hasGitHubIdentity + subscriber (default from user.githubDefaultRepo); Refresh + sync-status on list detail. In-app GitHub linking still needs a backend mobile callback (ask A1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
UserSession model + userSessions()/revokeSession(); SessionsView
('Where you're signed in') listing devices with current highlighted and
non-revocable, others revocable. Linked from Settings.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Registers the 22 new Swift sources/tests added across Phases 1-7 (DMs, sharing, templates, people-search, LinkedIn targets, GitHub lists, sessions, muted-users). Consolidated because the xcodeproj gem interleaves entries by hash order, so per-phase splitting of project.pbxproj isn't cleanly separable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
documentSync(lastSyncAt:) delta pull (full state when no cursor); pure DocumentSyncMerge applies upserts + deletedAt tombstones; SyncCache persists folders/documents/cursor per user. AppDataStore uses the sync path behind the ILOfflineDocSync flag (default on) — one call returns the whole tree vs. the root-only GET /api/documents; the online path is unchanged when the flag is off. Read-only slice: offline edit/push (slice 2) and conflict-copy (slice 3) deferred. Design in Offline-Document-Sync-Design.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ILWebURL builds canonical /user, /message, /lists, /documents permalinks; a 'Share link' action on message/profile/list/document shares the web URL. Pure AppDeepLink.parse routes both interlinedlist:// and https://interlinedlist.com links for profiles and messages (message(id:) + MessageLinkView loader); auth deep-links preserved. Universal Links (https→app) await backend AASA (ask A2); list/doc inbound + shared-token resolution are follow-ons. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…share copy
D-1 (smoke-test): DM 'New message' recipient tap didn't open the thread — the
onChange-after-dismiss nav was unreliable and the row wasn't fully tappable. Now
selection sets navigationDestination(item:) directly and the row uses
Spacer()+contentShape (mirrors the verified-good FindPeopleView pattern); recipient
filter extracted to a unit-tested DMRecipientFilter.
D-2 (pre-existing): FollowStatus failed to decode — /api/follow/:id/status returns
{status,isFollowing,isPending}, not {following,followedBy,pendingRequest}. Remapped
via a defensive init(from:) (also handles the nested {follow:{status}} shape from
POST /api/follow/:id); followedBy defaults false (not provided by these endpoints).
Nit: WatcherRole.detail(for:) makes share-link/collaborator copy resource-aware so
documents no longer read 'Can view this list'.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Top bar order is now Home, Lists, Documents, Messages, Notifications, then the user-avatar (profile) menu furthest right — previously the avatar sat 4th, before Messages/Notifications. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Offline document/folder create/edit/delete route through an optimistic outbox
(SyncOperation + DocumentSyncOutbox coalescing: create+updates→create,
update+updates→update, delete-of-unsynced-create cancels) and replay via
pushDocumentSync (POST /api/documents/sync → {lastSyncAt}; 429 → APIError.rateLimited).
syncCycle pushes-first-then-pulls (the endpoint swallows per-op errors, so the pull
reconciles); NetworkReachability replays on reconnect, plus foreground/refresh/
debounced triggers. DocumentsView branches on the ILOfflineDocSync flag with a
pending-sync glyph; the flag-off online path is unchanged. LWW for now —
conflict-copy is Slice 3 (seam marked TODO).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes offline document sync. Conflict = a locally dirty doc whose server updatedAt beats its baseline. Resolution keeps the local edit live and preserves the server version as a new '(conflicted copy <date>)' doc (never lose data), with a dismissible banner. syncCycle reordered to PULL-first-then-push so the server's version is observed before a local push would clobber it (the endpoint is LWW with no version guard). Adds DocumentSyncConflict (pure), baselines in DocumentSyncState, and DocumentSyncMerge.apply(protectingIds:) to keep conflicting dirty ids local during merge. Offline writes are no longer LWW, so the default-on ILOfflineDocSync flag is safe to ship. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hand-off spec for the two remaining backend/ops dependencies for iOS parity: exact backend diffs (GitHub authorize/callback mobile handoff; AASA route + middleware bypass), the AASA JSON with appID BJA9558E4B.com.interlinedlist.app, the iOS entitlement/flag, and the deploy + Apple-portal provisioning steps. Implementations: backend PR (CompositeCode/interlinedlist) + iOS HOLD PR #14. Co-Authored-By: Claude Opus 4.8 (1M context) <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.
iOS ↔ web feature parity build-out
Closes the feature gaps between the iOS client and
interlinedlist.com. Analysis + plan live inthe-gaps.md(rewritten); offline-sync design inOffline-Document-Sync-Design.md.Context
The prior analysis was blocked on "the backend rejects Bearer" for exports/GitHub/LinkedIn. That wall is gone — the backend now accepts Bearer everywhere (verified against source + live probes) — so all of it became buildable, and this PR builds it. Three shipped-but-broken writes (405s) are also fixed.
What's included
/api/user/update, edit message, mark-notification-read were POST/PUT → PATCH); muted-users screen (G7);list-data-rowsCSV export (G8, exports now work over Bearer)./updatespolling, image attach, block/not-mutual states, envelope badge, profile "Message" button.LinkedInTargetto the real backend union./api/documents/syncreturns the whole tree in one call; flag-gated, online path unchanged when off./api/follow/:id/status) + resource-aware share copy — from the interactive smoke-test.Verification
MockURLSessiontests +#Previews and passedios-review.Follow-ons (not in this PR)
apple-app-site-associationhosted; custom-scheme deep links work today.🤖 Generated with Claude Code