using Big.Domain; namespace Big.Application; /// A zorgprofessional's upload of the diploma their registration is waiting for ("documenten /// aanleveren"). is the authenticated caller (from the DigiD token, forwarded by /// the BFF): only the registration's own bsn may provide its documents. is /// the raw file, with its and . public sealed record ProvideDocumentsCommand( RegistrationId RegistrationId, string Bsn, byte[] Content, string FileName, string ContentType); /// The outcome of a provide-documents request. public enum ProvideDocumentsOutcome { /// The documents were accepted; the process's document wait was completed (if any). Accepted, /// No registration with that id belongs to the caller — unknown, or owned by someone else /// (the two are deliberately indistinguishable, so the endpoint reveals neither). NotFound, } /// /// The provide-documents use case (S-10a/S-10b): a zorgprofessional uploads the diploma their /// registration is parked waiting for. The document is stored in ZGW via the ACL (§8.1), then the /// WachtOpDocumenten task is completed so the registratie process leaves the 30-day wait and continues /// to beoordeling (ADR-0017). Owner-scoped by bsn. Both steps are best-effort about missing preconditions /// (mirroring ): storage needs an opened zaak, and completion needs a /// running process — a request that arrives before either still stands, storing/completing what it can. /// public sealed class ProvideDocuments(IRegistrationStore store, IWorkflowClient workflow, IAclClient acl) { public async Task HandleAsync(ProvideDocumentsCommand command, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(command); var registration = await store.GetAsync(command.RegistrationId, ct); // Unknown, or not the caller's registration: report NotFound either way (don't reveal which). if (registration is null || registration.Bsn != command.Bsn) return ProvideDocumentsOutcome.NotFound; // Store the diploma against the zaak (once it is opened) — the ACL is the only ZGW caller (§8.1). if (registration.ZaakUrl is not null) await acl.StoreDiplomaAsync( registration.ZaakUrl, command.Content, command.FileName, command.ContentType, ct); // Complete the document wait (if a process is running) so beoordeling can proceed. if (registration.ProcessInstanceId is not null) await workflow.CompleteDocumentWaitAsync(registration.ProcessInstanceId, ct); return ProvideDocumentsOutcome.Accepted; } }