···11+---
22+title: Post Editing Spec (v1)
33+updated: 2026-04-14
44+---
55+66+## Summary
77+88+Add AT Protocol post editing to Lazurite by replacing post records via
99+`com.atproto.repo.deleteRecord` + `com.atproto.repo.createRecord` (same `rkey`,
1010+same URI), with a v1 scope of:
1111+1212+- Entry point: thread screen only
1313+- Editable fields: post text + regenerated facets
1414+- Preserved fields: reply/embed/langs/labels/tags/unknown fields
1515+- Concurrency control: `swapRecord` with the current post CID
1616+1717+## Protocol Mechanics
1818+1919+### Record Replacement
2020+2121+Use delete + recreate on the existing `app.bsky.feed.post` rkey:
2222+2323+- `repo`: authenticated account DID
2424+- `collection`: `app.bsky.feed.post`
2525+- `rkey`: extracted from post AT-URI
2626+- Delete guard: `swapRecord` with latest/current CID from the post view
2727+- Recreate: `createRecord` with the same `rkey` to preserve AT-URI
2828+2929+The edit payload is built from the original record, replacing only:
3030+3131+- `text`
3232+- `facets` (recomputed from updated text; removed when empty)
3333+3434+`createdAt` is preserved from the original record when present. If missing or
3535+invalid, fallback to current UTC timestamp as a defensive safeguard.
3636+3737+### Conflict Handling
3838+3939+When delete/recreate detects stale state (`InvalidSwap`) or changed ownership,
4040+Lazurite treats the edit as a conflict and shows a non-merge message instructing
4141+the user to reopen and retry.
4242+4343+If recreate fails after delete, Lazurite attempts defensive recovery by
4444+restoring the original record on the same `rkey`.
4545+4646+## UX and Flow
4747+4848+### Thread Entry
4949+5050+For author-owned posts in the thread action sheet:
5151+5252+- Add `Edit Post` action.
5353+- Navigate to compose with edit context:
5454+ - `editPostUri`
5555+ - `editPostCid`
5656+ - `editRecord`
5757+ - `initialText`
5858+5959+On successful edit completion, refresh the thread by reloading the current
6060+post URI.
6161+6262+### Compose Edit Mode
6363+6464+Compose supports explicit edit mode via route context.
6565+6666+Edit-mode behavior:
6767+6868+- Title/action labels switch to edit wording (`Edit Post`, `Save Changes`)
6969+- Inline algorithm-impact notice is shown with an info dialog
7070+- Unsupported create-flow controls are disabled/hidden:
7171+ - Save Draft
7272+ - Schedule
7373+ - Add/remove image
7474+ - Add/remove video
7575+- Submission performs `putRecord` update rather than `createRecord`
7676+7777+## Algorithmic Implications (User Notice)
7878+7979+Editing can change how the post is indexed and distributed:
8080+8181+- Post metadata like `indexedAt` may change after edits
8282+- Feed ranking and search visibility may shift after re-indexing
8383+- Read-after-write propagation can be delayed across services and surfaces
8484+- Because edits are saved as delete+recreate on the same URI, counters and
8585+ visibility can briefly lag while services reconcile state
8686+8787+Lazurite informs users inline in compose edit mode and provides an info action
8888+for additional context.
8989+9090+## Limitations
9191+9292+- Edit action is exposed only in thread view
9393+- Only text/facets are user-editable
9494+- No merge flow for edit conflicts
9595+9696+## Beyond
9797+9898+- Add edit entry points in timeline/search/saved post cards
9999+- Consider edit-history affordances and richer conflict resolution UX
100100+ - The question here is where do we store history? What happens between logins? At what
101101+ point does Lazurite need its own lexicons for features like this?