Edit Business Documents with Secure Document Reference
Evidence status: This recipe follows the current Java source example. See Latest Versions for installable packages.
Use the optional SecureDocumentReferenceModule when a client edits a business
object graph and the server must know exactly which rows and fields the client
was allowed to change. A document here is an editable business view, not a
PDF, DOCX, or encrypted file.
1. Define the editing boundary
For an order editor, choose a stable business ID, an aggregate type, and a
purpose such as edit-order. Decide which relations are fully loaded, which
fields are visible and writable, which rows may be removed, and how current
authorization and optimistic versions are checked. The application's
ContextBoundDocumentService owns those business decisions. Install
SecureDocumentReferenceModule with a trusted principal, key provider,
deployment identity, and document service. The module is opt-in for the
endpoints that need governed editing.
For example, a customer service agent may edit quantities on lines belonging to one order but not the order's payment fields or another customer's lines. The server opens only that allowed projection. The protected snapshot records what it issued and the scope in which the edit may be accepted.
2. Open and present the document
Authenticate the actor and set the trusted principal in UserContext. Open a
document for the business ID and purpose, then prepare it for the client. The
Java flow uses OpenRequest and ViewPreparationService:
var opened = views.prepare(context,
context.openDocumentForView(new OpenRequest(
"CustomerOrder", orderNumber, "edit-order", Duration.ofMinutes(15))),
queryViewOptions);
var body = opened.value();
var credentials = opened.documentCredentials();
The client receives a readable body, opaque references for issued rows, and the document credentials. Send the credentials back with the edited body; never derive them from database IDs or let a client invent references. The reference is limited by actor, aggregate scope, purpose, and lifetime.
3. Accept the edit
The client changes only the fields the view offered and submits a command ID with the body and original credentials. The server calls the document service to validate the snapshot, current permission, and versions before saving:
var accepted = context.acceptDocumentForView(new AcceptRequest(
"CustomerOrder", "edit-order",
new SubmittedDocument(
credentials.get("businessId"),
credentials.get("documentToken"),
commandId,
editedBody)));
var presented = views.prepare(context,
accepted.document(), committedViewOptions);
The application returns presented as the new view. A stale version, copied
reference, changed actor, wrong purpose, or edit outside the issued fields is
rejected. The business service decides what a deliberate removal means; it
must not treat an unloaded or omitted field as a request to clear it. Keep the
command ID stable when retrying the same submission so the service can apply
its receipt/idempotency policy.
4. Add file editing only when needed
SecureDocumentReferenceModule works without file fields. If the document
also lets a user replace an attachment, install
Blob Reference separately. The client
submits an allowed file selection with the document, and the document service
checks its actor, target field, scope, and snapshot before the Blob module
binds the selected file. A temporary download URL is display-only; sending it
back does not select a file.