Skip to main content

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.