WIP: docs: plan sharing and app-password slice 1 #823
Closed
kayg
wants to merge 1 commit from
docs/sharing-slice-1 into dev
pull from: docs/sharing-slice-1
merge into: kayg:dev
kayg:main
kayg:fix/shared-row-swipes
kayg:feat/pass8
kayg:t3/paged-search-reconcile-final
kayg:feat/style-sheet-fixes
kayg:storage/wal-checkpoint-off-save-1051
kayg:feat/contrast
kayg:review/calendar-2
kayg:dev
kayg:feat/collections-db
kayg:fix/instant-keys-1056
kayg:feat/money-round
kayg:perf/stalls-1054
kayg:wip/tiering-v3-cold4
kayg:wip/tiering-v3-cold5
kayg:port/rows-actions
kayg:port/rows-drop
kayg:port/hidden-blocks
kayg:port/rows
kayg:port/port-tables
kayg:port/port-tables-2
kayg:t3/mail-1011-liveness
kayg:port/devices
kayg:port/port-attachments
kayg:port/port-attachments-2
kayg:port/port-attachments-3
kayg:docs/design-consistency
kayg:docs/engineering-standards
kayg:fix/rusqlite-0.41-rustsec-2026-0459
kayg:feat/iphone-fixes
kayg:shared/restore-and-stale-918-919
kayg:fix/phone-top-band-contrast
kayg:feat/notes-approve
kayg:perf/soak-max-gate
kayg:feat/files-s1-identity
kayg:fix/lifecycle-event-id
kayg:feat/quickfix
kayg:wip/tiering-v3-cold
kayg:perf/web-mockup-frame-fixes
kayg:port/contacts-merge
kayg:port/contacts-edit
kayg:test/shared-room-no-deleted-text
kayg:perf/first-paint-credits
kayg:fix/shared-history-after-grant
kayg:fix/phone-swipe-regressions
kayg:feat/contrast-r1
kayg:review/sharing-pr3-review
kayg:feat/tiering-v3-s2-tags
kayg:feat/folder-drop
kayg:fix/deskpills-lazy-share
kayg:feat/sharing-s1-pr3
kayg:tmp/money-round-before
kayg:fix/phone-pane-backdrop-roots
kayg:fix/palette-preload-chips
kayg:fix/invite-defaults
kayg:port/tasks-matrix
kayg:fix/restore-green-gates
kayg:fix/sharing-fast-path-hardening
kayg:t3/photos-s1
kayg:feat/tiering-v3-s1-namespace
kayg:notes-archive-hide
kayg:feat/tasks-actions
kayg:t3/photos-plan-slice-one
kayg:feat/whiteboard-s1
kayg:t3/paged-search-reconcile
kayg:t3/smooth-pane-transitions
kayg:t3/index-position-startup-scan
kayg:fix/private-staging-759b-r2
kayg:feat/dav-transport
kayg:feat/imap-notes-fetch
kayg:feat/imap-notes-projection
kayg:feat/imap-notes-readonly
kayg:feat/imap-notes-auth
kayg:feat/imap-notes-server-foundation
kayg:docs/undo-block-ids-plan
kayg:fix/undo-768
kayg:proto/block-identity-v7d
kayg:issue/carddav-read-perf-fix-r2
kayg:issue/carddav-read-r2
kayg:docs/imap-766-plan-v2
kayg:docs/imap-notes-plan
kayg:docs/quota-plan-2
kayg:fix/parallel-test-flakes
kayg:feat/contacts-companion-pure
kayg:docs/calendar-backend-v2-plan
kayg:feat/calendar-ical-converter
kayg:docs/tasks-writes-v2-plan
kayg:docs/carddav-writes-v2-plan
kayg:docs/contacts-import-v2-plan
kayg:issue/610-pm-midnight
kayg:feat/calendar-v2-s1-containment
kayg:docs/dav-recorder-v2-plan
kayg:plan/previews-865
kayg:plan/save-log-durable-entry
kayg:fix/e2e-data-on-ram
kayg:feat/appwindow3
kayg:feat/appwindow2
kayg:feat/appwindow
kayg:feat/money-p1
kayg:feat/keys-sheet
kayg:review/calendar-2-themes
kayg:feat/smooth-cursor
kayg:fix/float-style
kayg:review/calendar-2-float
kayg:release/2026-11-06-hotfix
kayg:archive/port/rows-drop-code
kayg:archive/port/rows-actions
kayg:archive/port/rows
kayg:scratch/tasks-894-ui-gates
kayg:review/calendar-2-night-wip
kayg:release/2026-11-05
kayg:archive/feat/tiering-v3-s1-namespace
kayg:archive/flaky/rows-drop-fixed
kayg:archive/flaky/rows-actions
kayg:archive/feat/tiering-v3-reader
kayg:archive/feat/tiering-v3-roots
kayg:archive/flaky/rows
kayg:sim/bm15-final
kayg:sim/bm15-fix
kayg:sim/bm15-bis-932
kayg:sim/bm15-bis-909
kayg:sim/bm15
kayg:sim/bm15-bis-887
kayg:perf/tiering-option-b
kayg:port/style-3
kayg:port/style-2
kayg:port/style
kayg:fix/sw-lazy-precache
kayg:fix/vim-w-waits-for-save
kayg:fix/signout-test-races
kayg:fp-scratch/all
kayg:sim/bm15-first-paint
kayg:archive/bm15/rows-drop
kayg:archive/bm15/rows-actions
kayg:fix/palette-snippet-contrast
kayg:archive/bm15/rows
kayg:archive/bm15/hidden
kayg:archive/plan/save-log-durable-entry
kayg:mock/money-fix2
kayg:archive/fix/e2e-data-on-ram
kayg:mock/appearance-all
kayg:mock/pill-press
kayg:archive/docs/design-consistency
kayg:mock/auto-swipes
kayg:mock/mail-actions
kayg:archive/feat/mail-p1
kayg:mock/money-static
kayg:archive/review/standards-917
kayg:archive/docs/engineering-standards
kayg:perf/tiering-761-fix
kayg:mock/type-audit
kayg:mock/third-pane
kayg:feat/contacts-import-v2-s1
kayg:perf/executor-hot-path
kayg:archive/port/hidden-blocks
kayg:archive/port/devices
kayg:scratch/executor-on-894
kayg:scratch/executor-spans2
kayg:scratch/executor-spans
kayg:train/2026-11-03-bm14c
kayg:archive/port/rows-drop
kayg:feat/tiering-761-d-scale
kayg:feat/tiering-761-c-index
kayg:feat/tiering-761-b-reader
kayg:archive/review/sharing-pr3-review-9fec3d1f
kayg:train/2026-11-03-bm14b
kayg:perf/ports-lazy-budgets
kayg:feat/tiering-761-a-migration
kayg:train/2026-11-03-bm14
kayg:train/2026-11-03-bm12
kayg:archive/review/sharing-pr3-review
kayg:archive/feat/sharing-s1-pr3
kayg:train/2026-11-03-bm11
kayg:archive/feat/imap-notes-fetch
kayg:train/2026-11-03-bm10
kayg:archive/review/sharing-pr3-review-code
kayg:archive/plan/previews-865
kayg:train/2026-11-02-bm9
kayg:archive/port/port-attachments-3
kayg:archive/port/contacts-merge
kayg:fix/motion-audit-859
kayg:train/2026-11-02-bm8
kayg:archive/scratch/bm8-prep
kayg:archive/port/port-pickers
kayg:archive/port/port-tables-2
kayg:archive/port/port-tables
kayg:archive/feat/sharing-s1-pr3-code
kayg:archive/scratch/bm7-fixed
kayg:train/2026-11-02-bm7
kayg:archive/fix/parallel-test-flakes-code-minipc01
kayg:train/2026-11-02-bm6
kayg:docs/imap-766-readonly-slice
kayg:feat/dav-recorder-v3
kayg:research/788-diagnosis
kayg:archive/fix/parallel-test-flakes
kayg:archive/perf/pr792-cold-index-edit
kayg:archive/docs/imap-766-plan-v2
kayg:feat/dav-recorder-v2
kayg:archive/docs/dav-recorder-v2-plan
kayg:spike/imap-766-s0-cases
kayg:archive/fix/undo-768
kayg:feat/dav-recorder
kayg:archive/docs/contacts-import-v2-plan
kayg:archive/feat/calendar-ical-converter
kayg:feat/contacts-import
kayg:perf/cold-growth-on-764
kayg:perf/cold-growth-on-tiering
kayg:archive/docs/tasks-writes-v2-plan
kayg:archive/docs/calendar-backend-v2-plan
kayg:archive/feat/contacts-companion-pure
kayg:feat/tasks-set-status
kayg:feat/tasks-move-reorder
kayg:archive/docs/carddav-writes-v2-plan
kayg:archive/feat/calendar-v2-s1-containment
kayg:feat/tasks-delete-promote-duplicate
kayg:archive/feat/dav-transport
kayg:archive/fix/carddav-rebuild-r1
kayg:archive/fix/carddav-retention-r1
kayg:feat/carddav-writes
kayg:perf/quota-on-tiering
kayg:perf/quota-simple
kayg:perf/cold-growth-on-quota-stack
kayg:feat/calendar-identity
kayg:feat/calendar-event-parser
kayg:feat/calendar-props-maps
kayg:port/glass-when-ring
kayg:feat/tiering-761-s1
kayg:wip/10by32-01-impl-759b-scratch-20261030
kayg:wip/6by32-01-bm3-webkit-pause-20261030
kayg:wip/10by32-01-bm3-chromium-pause-20261030
kayg:wip/6by32-01-tier-761-s1-pause-20261030
kayg:spike/imap-766-s0
kayg:wip/6by32-02-calternal-pause-20261030
kayg:wip/8by64-01-review-688-pause-20261030
kayg:wip/6by32-01-verify-744-pause-20261030
kayg:wip/6by32-01-verify-742-pause-20261030
kayg:fix/private-staging-759b
kayg:wip/6by32-01-review-748-pause-20261030
kayg:wip/6by32-01-review-733c-pause-20261030
kayg:wip/6by32-01-review-733b-pause-20261030
kayg:wip/6by32-01-perf-idle-8-pause-20261030
kayg:wip/6by32-01-perf767-base-pause-20261030
kayg:wip/6by32-01-perf767b-767-pause-20261030
kayg:wip/6by32-01-perf767b-764-pause-20261030
kayg:wip/6by32-01-perf767-767-pause-20261030
kayg:wip/6by32-01-perf767-764-pause-20261030
kayg:wip/6by32-01-lists-b-pause-20261030
kayg:wip/6by32-01-ids-verify5-pause-20261030
kayg:wip/6by32-01-ids-verify4-pause-20261030
kayg:review/calendar-month
kayg:wip/10by32-02-undo-768-20261030
kayg:test/ids-verify3
kayg:wip/10by32-02-bm3-chromium-20261030
kayg:wip/10by32-01-review-753-20261030
kayg:wip/10by32-01-perf-idle-2-20261030
kayg:wip/10by32-01-bm2-webkit2-20261030
kayg:plan/759b-staging
kayg:train/2026-10-30-bm2
kayg:review/758b-tests
kayg:review/758-tests
kayg:review/764d-tests
kayg:review/767b-tests
kayg:review/preview-2026-10-29
kayg:review/767-tests
kayg:docs/tiering-731-plan
kayg:wip/c6b02-when2
kayg:wip/c6b02-tasks-create-fix5
kayg:wip/c6b02-settings-frost-mock
kayg:wip/c6b02-settings-frost-base
kayg:wip/c6b02-settings-frost
kayg:wip/c6b02-ring
kayg:wip/c6b02-review-733d
kayg:wip/c6b02-bm1-full-a
kayg:wip/compute02-when-field
kayg:wip/compute02-webkit-lists-repro
kayg:wip/compute02-train-bl2-dev
kayg:wip/compute02-dev-green-pw164
kayg:docs/deploy-plan
kayg:review/764c-tests
kayg:review/764b-tests
kayg:review/748g-tests
kayg:review/764-tests
kayg:review/759b-tests
kayg:fix/storage-owner-liveness-642
kayg:fix/storage-fix-7
kayg:wip/compute02-storage-fix-7
kayg:review/759-tests
kayg:feat/tiering-731
kayg:wip/tiering-731-first-attempt
kayg:wip/compute02-storage-fix-1
kayg:review/754g-tests
kayg:perf/idle-honest-2
kayg:review/754f-tests
kayg:review/754e-tests
kayg:review/755-tests
kayg:review/754d-tests
kayg:review/754c-tests
kayg:review/754b-tests
kayg:review/754-tests
kayg:fix/storage-private-tmp-642-dev
kayg:wip/compute02-verify-750
kayg:test/ids-verify5
kayg:test/ids-verify4
kayg:fix/storage-exact-file-quarantine-642
kayg:wip/compute02-verify-740
kayg:perf/one-flush-save
kayg:review/calendar-static
kayg:wip/compute02-verify-737
kayg:review/indexing-ring
kayg:review/when-field-2
kayg:wip/compute02-review-733
kayg:proto/block-identity-2-review
kayg:proto/block-identity-review
kayg:wip/c6b02-tc-design
kayg:review/when-field
kayg:issue/tasks-create-ids
kayg:issue/tasks-create
kayg:review/combined
kayg:wip/compute02-review-combined
kayg:review/task-polish
kayg:review/top-buttons
kayg:review/q1-q5
kayg:train/2026-10-26-bl2
kayg:archive/wt-398h
kayg:archive/train-bm-proptest-seed
kayg:archive/integ325-293
kayg:archive/integ325-ci
kayg:archive/client-auth-review-baseline
kayg:archive/wt-sim-4853
kayg:archive/wt-sim-4811
kayg:archive/wt-448m
kayg:archive/wt-398a-allocator
kayg:issue/calendar-adr
kayg:archive/old/train/2026-10-23bk2
kayg:archive/old/train/2026-10-23bk
kayg:issue/469-mockup-9a
kayg:issue/smart-tasks-mockup
kayg:issue/469-menus
kayg:issue/652-signout-flake
kayg:issue/652-history-fix7
kayg:issue/652-history-fix6
kayg:archive/old/issue/spring-check-perf
kayg:issue/spring-check-perf
kayg:issue/659-rename-fast
kayg:archive/old/train/2026-10-21ar
kayg:issue/search-hardening-3
kayg:issue/652-history-fix5
kayg:issue/660-port-sheets-glass
kayg:issue/652-history-fix4
kayg:issue/652-history-fix3
kayg:issue/652-history-fix2
kayg:issue/652-history-flake
kayg:train/2026-10-21an
kayg:issue/settings-admin-port
kayg:issue/search-port
kayg:train/2026-10-20am
kayg:issue/storage-split-fix2
kayg:issue/storage-split
kayg:archive/old/issue/folder-ids-fix
kayg:train/2026-10-20al
kayg:archive/old/issue/folder-ids
kayg:train/2026-10-20ak
kayg:issue/tables-mockup
kayg:train/2026-10-19aj
kayg:train/2026-10-19ai
kayg:issue/469-merge-fixes
kayg:issue/sidebar-band
kayg:archive/old/issue/608-settings-spec
kayg:train/2026-10-19ah
kayg:issue/swipe-offscreen
kayg:train/2026-10-19ag
kayg:archive/old/issue/590-nlp-adr
kayg:archive/old/issue/587-event-after-write-2
kayg:train/2026-10-19af
kayg:archive/old/issue/587-event-after-write
kayg:issue/469-pill-room-c
kayg:issue/469-pill-room
kayg:train/2026-10-19ae
kayg:issue/469-narrow-handle
kayg:issue/397-ios-swipe-2
kayg:archive/old/issue/adrs-photos-files-tasks
kayg:issue/469-desk-fixes
kayg:archive/old/issue/auto-update-adr
kayg:issue/469-filter-gap
kayg:issue/469-port-1b
kayg:issue/442-opacity-flake
kayg:archive/397-ios-swipe-2
kayg:issue/327-web-fast-3
kayg:archive/old/issue/469-port-1
kayg:issue/469-port-1
kayg:issue/327-web-fast-2
kayg:archive/old/issue/327-web-fast
kayg:archive/old/issue/425-stt-bench-vq1
kayg:archive/old/issue/445-no-bleed
kayg:archive/old/issue/400-swipe-mockup-2
kayg:issue/426-client-review
kayg:issue/426-client-2
kayg:issue/426-client
kayg:archive/old/issue/476-safe-area-lab
kayg:archive/445-top-light-2
kayg:archive/old/issue/445-top-light
kayg:issue/471-blocks-mockup
kayg:archive/old/issue/448-links-app-2
kayg:archive/old/issue/448-links-app
kayg:archive/old/issue/398-cold-links
kayg:issue/434-442-small-2
kayg:issue/434-442-small
kayg:archive/old/issue/398-unload
kayg:archive/old/issue/445-bottom-band
kayg:issue/445-bottom-band
kayg:issue/351-rem-3
kayg:archive/312-views-mockup
kayg:issue/351-rem-2
kayg:issue/351-rem
kayg:archive/old/issue/327-first-note
kayg:issue/395-width-phone
kayg:archive/old/issue/327-typing
kayg:issue/396-ios-edges
kayg:issue/397-ios-swipe
kayg:archive/398-allocator
kayg:archive/old/issue/327-notes-index
kayg:issue/345-347-contrast-empty-2
kayg:archive/old/issue/44-arenas
kayg:issue/44-arenas
kayg:archive/integ325
kayg:archive/old/issue/327-perf-harness
kayg:archive/old/issue/44-thp
kayg:issue/44-thp
kayg:archive/old/issue/285-sticky-pills
kayg:archive/old/issue/44-trim-3
kayg:issue/44-trim-3
kayg:archive/old/issue/165-cards
kayg:archive/old/issue/165-picker-2
kayg:archive/old/issue/212-multi-select
No reviewers
Labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
kayg/calternal!823
Loading…
Reference in a new issue
No description provided.
Delete branch "docs/sharing-slice-1"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Plan only: docs/plans/0409-sharing-slice-1.md; settled decisions: docs/grills/sharing.md.
Revision after final independent review comment #72378:
The remaining grill is whether app passwords may carry the independent
notes.sharescope (recommended yes) and whether a Read grant to a shared View includes history (recommended yes in Slice 2). Documentation only;rtk git diff --checkpassed and no implementation tests were run.docs: plan sharing and app-password slice 1to WIP: docs: plan sharing and app-password slice 1Independent plan review
verdict: revise. reviewed
docs/plans/0409-sharing-slice-1.mdat33473d2033, against the listed ADRs, the checked-in sharing grill and the settled decisions supplied in the review brief. this is a plan review, not a claim that the proposed implementation already has these defects. no builds, tests, commits or pushes were performed.contradictions and reopened decisions
docs/grills/sharing.mdends at Q8; current remotedevhas the same content. neither it nor #409's available comments contains A1–A13, G1–G7 or Q10–Q16. the supplied Q10/Q11/Q14/Q16 decisions are authoritative for this review. i cannot honestly attest to every A/G item without their text. reconcile the full decided record and add an item-to-plan/gate map before approval. closing grill 2 (app-password share authority) and 4 (read history) have no settled source in the available material: cite the existing answer if covered by A/G; do not ask kayg again or present a recommendation as an approved decision.findings
P1 · access coverage is broad, but enforcement is still a collection of call-site promises (L80–96; Tasks 1/3).
the table covers reads, lists/metadata/snippets, backlinks/Linked here, attachments/thumbnails, history/restore previews, search results/counts/highlights/recents, sync/journal replay, rooms, websocket delivery and DAV scope separation. this is a good inventory, but a shared helper is not yet one mandatory choke point. export and notifications are absent; preview images are mentioned only through thumbnails/backdrops, without cache/delivery rules. explicitly cover download/archive/export jobs, image variants and private response caches, attachment ranges/resumed reads, and any notification or webhook payload. declare unavailable paths out of scope with a refusal test instead of silently omitting them. preserve SH8: returning a readable source's backlinks must not reveal an unreadable referring note.
specify one authorization contract combining credential capability and current object rights, enforced in the executor/resource resolver, with direct byte-serving adapters required to use an authorized resource handle. centralize list/search visibility predicates before counts/snippets and paginate after filtering. require an enumerated route/action matrix that fails for unclassified additions. ADR 0011 calls for one set of rules, not independent policy implementations in every adapter.
P1 · revocation has no defined ordering against the owner's durable write or buffered delivery (L68, L92–93, L113, L120).
grants commit in shared
auth.db; rooms, owner files/history and owner journals commit elsewhere. “recheck inside the serialized write transaction” does not identify a transaction/lock shared with revoke. revoke can commit after a grant check but before file/history commit; a response or room update can already be queued. specify a common per-resource serialization boundary or equivalent grant-generation validation spanning authorization and durable commit, plus publication ordering. define the boundary precisely: bytes already delivered cannot be recalled. test revoke between check/commit and check/enqueue, pending room flushes with multiple authors, edit-to-read downgrade, lost replies/idempotent retry, and owner deletion. do not discard another author's accepted pending edits when one recipient loses access.P1 · filtering journal replay by current grants can suppress the very purge event a revoked device needs (L91, L113; Task 3).
after the final grant disappears, a uniform “current access” filter rejects
sharing.revokedtoo. define recipient-addressed control tombstones that remain replayable without content rights, with sufficient stable identity to purge/rescue but no note body. establish monotonic grant generations/source versions so delayedgranted/changedevents cannot resurrect a revoked copy after revoke/regrant. define snapshot/reset recovery for a cursor older than journal retention and atomic application with the client cursor. gates must include two offline devices, crash during rescue/purge and replay after retention, not only one live recipient seeing one event. this is required to fulfill Q16, ADRs 0044 and 0047.P1 · app-password scope intent is sound; the end-to-end enforcement contract is incomplete (L75; Task 1).
the plan explicitly refuses login, setup/recovery, passkeys, account changes and unrelated DAV protocols, and reserves grants for
notes.share. however, it accepts credentials “only on notes routes” while mutations actually use the generic/api/v1/actions/{name}. at this head,Authenticator::Identityreturns only user/Installation andapi::Signedcreates aCallerwith no credential kind/scopes;run_actiondispatches arbitrary registered names, and journal reads receive only the user. Task 1 must name the identity/Caller/executor changes that preserve and enforce the scope ceiling on every dispatched action and sync operation, not merely a route check. specify whether scopes imply one another, howsharing.list/shared-with-me/search are classified, and how mixed sync or bulk payloads are checked per operation. an owner user id must never bypass the Installation's scope ceiling. anotes.writepassword must fail grant/revoke even when its user owns the note;notes.sharestill cannot reshare somebody else's note. require a deny-by-default capability map and tests through the generic endpoint, cached idempotent outcomes, credential revocation and an established websocket. there is no demonstrated bypass here yet; this missing contract prevents approval.P2 · fan-out is O(R) events plus recipient indexing work, with unbounded global write pressure (L64, L100–104).
batching delivery at 100 rows does not bound the preceding transaction that enumerates all recipients, queued bytes, oldest-event latency or work across all owners. shared FTS duplicates O(R × B) text overall; updating it can dominate compact journal events. define a slice-1 recipient limit, bounded enumeration/queueing, fairness, backlog limits, metrics and restart behavior. keep owner edits independent of recipient indexing. spell out grant-time snapshot plus journal watermark and deduplication so a share created while the worker is behind neither misses an edit nor replays arbitrary earlier events. define per-recipient order and what happens if the source journal is compacted before the fan-out cursor catches up. measure owner edit latency and recipient catch-up at the supported recipient limit.
P2 · search correctness needs bounded candidate refill and full-pipeline isolation (L94, L105; Task 4).
K returned matches is not the amount of authorization work when many stale candidates are denied. specify capped candidate scanning/refill, ordering and pagination so revoked rows neither hide readable results nor dominate latency. grant checks after matching do not alone address per-index vocabulary/typo suggestions, ranking statistics, previews or cached recents derived from revoked text. extend the stale-index gate to these outputs, and retain ADR 0031's measured first-results budget.
concrete cuts
approval requires: reconcile the complete decided record without another grill; make the authorization/scope boundary and revoke ordering concrete; specify durable multi-device rescue/purge; and bound fan-out. no P0 finding is established by this plan-only review.
Revised the plan in place following comment #72305:
notes.sharescope and View-history questions.Documentation-only update.
rtk git diff --checkpassed; no implementation tests were run.Independent plan review, round 2
verdict: revise. reviewed
docs/plans/0409-sharing-slice-1.mdatc6f2903405, round 1 #72305, the planner's reply #72336, and the recorded sharing decisions. this is a plan review; findings concern missing or conflicting contracts, not demonstrated implementation failures. no P0 established.round-1 status
notes.shareissuance is still explicitly open in both source and plan. resolve that existing choice before implementation; its recommendation is not an approved decision. View history remains a later-slice question.findings
P1 · journal publication order does not yet define a race-free read/delivery boundary (L84–90, L109–123; gate 2).
the shared sequence protects source commits and recipient-journal appends. it does not say that journal reads, snapshot construction, resource-handle use or socket output participate in an atomic authorization/delivery decision. concrete counter-interleaving: a reader checks generation g and prepares a content response; revoke commits g+1; the reader enqueues or streams the prepared response. an
AuthorizedResourceobtained before revoke and an “immediately before” check do not close this gap. a pre-revoke journal append can also be read after revoke; append order alone is insufficient. the table requires current checks, but does not specify their atomic boundary with revoke.define the observable cutover precisely and use it consistently. readers should take a versioned snapshot, authorize it and discard/retry stale work at the defined admission point, without holding the writer sequencer across read I/O, response construction, queue backpressure or network sends. explicitly distinguish server admission from bytes already admitted/in flight: the latter can arrive after revoke and cannot be recalled. if the plan retains the stronger literal “no note bytes delivered after the revocation point” promise, explain how it can hold without writers waiting for readers; the current design supplies neither proof nor mechanism. add barriers at read-check/response admission and admission/socket-send, not only publisher-check/journal-enqueue.
P1 · the sequenced acceptance point is not mapped to the existing room's durable history and live publication (L84, L122; Task 3).
the current room saves files after a quiet interval, while edits can enter durable history and live room state earlier (
crates/notes/src/room/save.rs,edit.rs). the plan groups note/history/source-journal commit into one slot and separately says to check operations and flushes, but does not identify which existing step is acceptance. a later flush check cannot undo an earlier history commit or live update.walk the required interleaving explicitly: A has an edit in flight; revoke of A's Edit commits at s; A's write reaches the server; B reads its journal. if A has not durably accepted before s, its operation must fail before modifying authoritative history or shared room state, produce no source/fan-out event, and remain locally available for rescue. B receives no event or room update containing that operation. if A was durably accepted before s, classify it as an earlier accepted operation even when file materialization occurs later. B, if independently authorized, can receive that earlier operation; A's later access still follows the cutover.
name the room/history acceptance step that acquires the sequence and carries actor, credential authority and generation. later file flush should materialize accepted operations, rather than reauthorize a mixed-author document under one caller. specify how a valid B operation continues when an unaccepted A operation is rejected, and how precommit room broadcasts are prevented. add a gate that pauses between room receipt, durable history acceptance, live broadcast and file flush. the existing multi-author gate names the race but does not settle this essential design choice.
P2 · Edit-to-Read has no explicit rescue trigger (L88–90, L104, L148).
controls and rescue are specified for revoke/delete, and L88 explicitly says no purge while Read survives. after an Edit-to-Read downgrade, A can retain unsent edits that now fail permanently without receiving the full-revocation rescue/purge control. define a loss-of-Edit transition that rescues rejected/pending authored edits, retires their shared-write outbox entries, and retains the authorized readable copy. test it separately from final loss of Read; do not force a body purge just to rescue edits.
P2 · O(1) owner work needs an explicit outbox and lock qualification (L84–86, L130–138).
with R recipients, an edit needs O(R) journal appends and grant/generation checks, plus up to O(R × B) shared indexing work. each publication also takes the same resource sequence: moving it to a worker does not remove its contention with writers. source commit is O(1) in R only if it records one source intent/watermark, rather than enumerating recipients or persisting R per-recipient rows inside that slot. clarify which representation is intended. define one short append/validation slot per recipient, release it before indexing, and never wait under it for a recipient queue, reader or socket. a stalled recipient must not hold the resource sequence. gate 6 should assert writer progress while a reader is paused and a recipient queue is full, alongside the latency measurement. the search formula also needs C grant checks, not just K: O(C log G) with individual indexed checks, or state the batched lookup assumption.
smallest useful slice and concrete cuts
the core slice remains useful: named single-note Read/Edit, scope enforcement, live sync, shared search, history authorship, attachments, owner revoke, recipient hide and durable rescue/purge. the extra access and recovery work follows those decisions. the revision nevertheless adds avoidable breadth:
do not cut controls, attribution, rescue, scope checks, shared search or concurrency gates. approval requires resolving the two P1 boundaries and making reader-independent writer progress explicit. review only: no builds, tests, commits or pushes performed.
Updated the plan at
d4b64dc5:Documentation only;
rtk git diff --checkpassed.Independent plan review, round 3 (final)
verdict: revise. reviewed
docs/plans/0409-sharing-slice-1.mdatd4b64dc5510589f9a248d1afd0b8d0e4791aa4d3, the settleddocs/grills/sharing.md, rounds 1 and 2, and the planner's change list. plan review only, not evidence of an implemented failure. no P0 established. this is the final review round; the remaining correction is described below without requesting another round or another grill.notes.shareissuance remains genuinely open in both documents; the plan correctly requires resolving it before enabling that scope.findings
P1 · a purge control is not yet a durable barrier to older, interval-eligible content (L81–85, L98–99, L143; gates 2–3). This is the remaining part of round 2's read/delivery finding, not a request to hold readers or sockets under the writer lock.
Concrete trace: grant starts at 2; an authorized edit commits at 8; revoke commits at 9. A reconnecting device consumes control 9 first, rescues/purges and acknowledges it, as specified. A delayed entry/update 8 still passes
2 ≤ 8 < 9. Nothing in the application contract says it cannot restore room/cache state or apply content after that purge. Journal events are references, so a fresh byte fetch is correctly denied by current-access checks; that protects the fetch, but does not settle delayed room payloads or already prepared content reads. This concerns state after the client has applied the control, not recalling bytes already in flight.Re-grant makes the omission observable without a denied fetch: grant at 12 identifies a new committed baseline, then a delayed entry from the old [2,9) interval is still interval-eligible. The plan does not define how that old notification/update is prevented from rolling state back, or how a delayed old revoke control avoids purging the new baseline. Per-note fan-out ordering is useful but insufficient when controls are processed ahead of content or room/read responses travel independently.
Small correction: persist a per-note client control/baseline watermark with the purge/rescue state. Historical interval eligibility may still permit journal references, but applying content, room updates and completed reads must respect that watermark and the currently installed authorized baseline. Old entries cannot recreate a purged copy; a newer re-grant installs its identified authorized baseline before accepting its updates; older controls cannot remove that newer baseline. Define this once for sync, room and read completion, retaining lock-free readers and the existing source-admission invariant. This needs no general transaction framework or new audience machinery.
Required deterministic gates: (1) pause a revoked recipient's own read/update after preparation, apply and acknowledge its revoke control, then release the old response/update and assert the shared copy stays purged; (2) drain lagging pre-R fan-out after control processing and assert the same; (3) perform grant→revoke→grant→revoke→grant with edits in each interval and gap, install the latest baseline, then replay old content and controls across channels/restart and assert no rollback, gap exposure or new-copy purge. Include an admitted pre-R room broadcast and an unadmitted post-R edit. Gate 2 currently reads as independently authorized B and asserts interval membership, which these old entries satisfy; gate 3 asserts purge but not its persistence after delayed delivery. Randomization does not replace these barriers.
P2 · Task 5 says to purge on every control, contradicting Edit→Read (L242 versus L85/L99 and gate 3). Change that checklist item to rescue/retire on loss of Edit and purge only on loss of Read, including owner deletion. Otherwise a literal UI implementation removes a still-readable copy. No new policy decision is needed.
No other new P0–P3 findings.
suggested PR split
Three dependent implementation PRs are realistic; two would combine too much cross-layer work. Keep this plan PR separate.
Each PR needs its own relevant merge gates; “PR 1 gates”/“all gates for the implementation PR” should become final slice acceptance gates plus the per-PR subsets. Do not defer backend isolation or recovery correctness to the UI PR.
final verdict: revise for the replay/application fence and the downgrade checklist correction. The source-admission simplification is sound and the writer section is bounded. review only: no builds, tests, repository edits, commits or pushes performed.
Updated the plan at
9bf4a9c5:Documentation only;
rtk git diff --checkpassed.Closing per #931: the sharing slice made this plan out of date (#827/#829).
Pull request closed