BaryoDev / BaryoDev/barakoCMS

A header with lines: the shape every transactional system needs and the model has no concept of

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

Description

Every transactional system is a header with lines. An order with order lines. An invoice with items. An enrollment with documents. A booking with guests. A delivery with a manifest. A stock movement with allocations.

barakoCMS has no concept of it. There is no parent, no child, no aggregate in `barakoCMS/Models` or `Features/Content`. The `reference` field type is a single Guid string (`FieldTypeRegistry`), with no integrity, no cascade, and no way to load a header with its lines in one read or write them in one transaction.

This is the single largest gap between what barakoCMS is and what an inventory, booking, enrollment, delivery or trading backend needs. It is the part a developer currently has to build themselves, which means the product ships the easy half.

## What it has to provide

**One transaction.** A header and its lines commit together or not at all. Marten gives this; nothing exposes it.

**Referential integrity.** A line cannot exist without its header, and deleting a header decides what happens to its lines rather than orphaning them.

**One read.** Loading an order with twenty lines is one query, not twenty-one.

**Validation across the set.** "The total equals the sum of the lines" is an invariant of the aggregate, not of either document alone. Today `IContentValidatorService` validates one entry against its type.

**Tenancy unchanged.** Conjoined tenancy filters by tenant. A join that drops the filter is a data exposure defect, so whatever query loads the set needs a test that fails if the tenant filter is removed.

## What to decide before building

**Whether lines are content or their own document type.** As content they inherit sensitivity, capabilities, history, delivery and the whole existing surface, which is a lot of value. They also inherit editorial concepts that do not fit, such as `Draft` and `Published` on an order line.

**Whether the aggregate is a content type feature or a module.** It touches the write path and validation, which suggests core, and core is meant to stay generic.

**Whether concurrency is on the aggregate or the entry.** For a header with lines the useful unit is the aggregate. This depends on content getting optimistic concurrency at all, which it does not have today.

## Why this one first

State machines and reservations both sit on top of it. So does anything that computes a total. Without it every one of those verticals starts by building the same thing by hand.

## Done when

- A content type can declare a child collection.
- A header and its lines are written in one transaction and read in one query.
- A cross-set invariant can be declared and is enforced on write.
- A test proves the load is tenant-filtered and fails if the filter is removed.

Contributor guide

Open the contributing guide

Research direction

Start by reading the Models and Features/Content areas, then trace FieldTypeRegistry and IContentValidatorService to understand the existing content and validation paths. The work is done when child collections, transactional aggregate reads and writes, cross-set invariants, and tenant-filtered loading are implemented with tests for the stated requirements.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend, database
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.