BaryoDev / BaryoDev/barakoCMS

Document generation: an invoice or a booking confirmation as a PDF, without sending it to a third party

Open
#585 0 comments 0 reactions 0 assignees View on GitHub
enhancement module
Dominant language
C#
Stars
6
Forks
7
Avg merge
4h 42m
Merged PRs (30d)
307

Description

An invoice gets sent as a PDF. So does a booking confirmation, a delivery note, an enrollment letter, a receipt and a statement. It is the same requirement in every system on the list and there is no way to do it.

A workflow can call a third-party rendering service through a connector, which means paying per document and sending the contents of every invoice to somebody else. For an invoice that is a data protection question, not a cost question.

## What a module would provide

- A template per content type, with the same `{{...}}` holes the request templates already use.
- A workflow action that renders an entry to a PDF.
- Somewhere to put the result, which is the Files module.

## What it must inherit rather than reinvent

**The masking rules.** A document is an egress path like any other. It goes through `PublicDelivery.ToPublic` or the equivalent, so a field that cannot leave over the API cannot leave in a PDF. Without this it is the easiest way to exfiltrate a Sensitive field in the whole system, because nobody thinks of a PDF as an API response.

`RequestComposer.Refuse` already does this for outbound requests: it refuses a template naming a non-Public field. The same refusal belongs here, and reusing that code rather than writing a second copy is the point.

**Idempotency.** Rendering the same entry twice on a retry should not produce two documents in the file store. The run's idempotency key is available in the action's parameters.

## What to decide

**Which renderer.** HTML to PDF via a headless browser is the flexible answer and drags in a browser. A native library is smaller and more limited. This is the decision that determines the image size and the licence, so it should be made in the thread with both written down.

**Whether the template is HTML or something narrower.** HTML means the template can reach out to a URL, load a font, and phone home. A narrower template language cannot. Given the masking argument above, the narrower option is more consistent with how this codebase treats egress.

## Scope

A module. It needs no pipeline hook, only services, an action and the Files module, so it is buildable under the current contract.

## Done when

- A content type can have a document template and an entry renders to a PDF stored in Files.
- A template naming a non-Public field is refused, proven by a test.
- Two renders under the same idempotency key produce one stored document.

Contributor guide

Open the contributing guide

Research direction

Start by reading PublicDelivery.ToPublic and RequestComposer.Refuse to understand the existing masking and refusal rules. Then inspect the Files module and the action parameters for storage and idempotency context. The design must resolve the renderer and template format, and done means a PDF is stored, non-Public fields are refused by a test, and repeated renders under one idempotency key store one document.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.