Editing different "views" of the same document

I’ve got a use case where the editor of a document can embed “redacted” blocks. These blocks are completely stripped out of the document when it’s delivered to a consumer, who views the document in a read-only mode. This works fine as long as the document can’t be changed in this state.

I’m wondering if there’s a way to allow editing in this state, as well. It seems like there might be a creative way to model this as a in-flight rebasing sort of problem, but it seems like it might get a little sticky.

I have a few ideas:

  1. Treat editing like an inversion of the read. The user edits their redacted document, the changes are sent, the “unredaction” changes are treated like a transaction that comes just before the user changes, the user changes are rebased on top of these, and the results are saved.

  2. Rather than literally removing redacted blocks and remapping the document, the redaction creates a node of size N, where N is the size of the actual node. The “fake” node takes up actual-space in the document without taking up visual space. Not sure if this is possible, and would have to somehow prevent this node from being deleted by those without permission.

Could also have a redacted node’s text content replaced with spoiler tags, but the presence of a secret is a secret itself, and this seems to run into the editable islands problem that Marijn advises against in another post.

Anyone have any ideas? Is there a simpler solution here that I’m totally missing?

I think it should be possible, if you use size-1 leaf nodes for the redacted nodes on the client but have the unredacted document on the server, to create a step map that conceptually replaces each of these (in the pre-change doc) with their actual size (by directly building up the vector and wrapping it in a StepMap). That represents the mapping from the client document to the full document, and mapping the client’s step through that should be able to create a step that can be applied to the full document. (And the other way around, you could map server steps through its inverse to get steps that the client can apply locally.)