Appearance
Documents, Flow, Effects, Derive
Page intent This page is the chapter-level explanation of the universal document runtime: CRUD, lifecycle, effects surface, document relationship graph, and derivation workflow.
Trust level
- Verified anchors:
NGB.Runtime/Documents/DocumentService.cs - Architecture synthesis: yes
- Template guidance: yes
Chapter navigation
Verified source anchors
Confirmed in:
NGB.Runtime/Documents/DocumentService.cs
The verified source shows that DocumentService is much more than a CRUD handler. It already centralizes or coordinates:
- document type metadata access;
- generic page/list reads;
- document lookup across types;
- draft create/update/delete;
- post/unpost/repost/mark-for-deletion/unmark-for-deletion;
- document relationship graph loading;
- document effects loading;
- trusted/internal draft derivation creation.
The public 2.0 action surface is intentionally separate: IDocumentActionQueryService returns editor state and evaluated action metadata, and IDocumentActionDispatcher executes lifecycle, derivation, and vertical commands.
What this tells us architecturally
NGB documents are not mere tables with controllers. The platform treats a document as:
- a metadata-defined type;
- a lifecycle-bearing business artifact;
- a source of downstream business effects;
- a node in a document flow graph;
- a possible derivation source for new business documents.
Universal document CRUD
The verified source confirms several important design choices:
Head + parts model
DocumentService comments explicitly describe:
- scalar head fields in a
doc_*head table; - tabular parts in
doc_*__*tables; - common registry + typed head table persistence model.
Draft-first editing
The service supports create/update/delete of drafts before posting is involved.
Metadata-driven validation
Field and part validation are driven by metadata and draft validators rather than controller-specific hardcoding.
Document flow
The verified GetRelationshipGraphAsync implementation confirms that document flow is treated as a graph problem, not as a single foreign-key lookup.
Important confirmed behavior:
- backend loads relationship graph in a single API request;
- backend avoids N+1 head fetches by loading graph head rows across types in bulk;
- graph nodes are enriched with display, status, date, and optional amount.
That is a strong platform statement: document flow is a reusable explainability feature.
Document effects
The verified GetEffectsAsync implementation confirms that effects are a cross-engine concept.
Effects surface includes:
- accounting entries;
- operational register movements;
- reference register writes.
Action capability and disabled reasons are not effects. They are returned by the editor-state action query, which keeps explainable business effects separate from executable UI operations.
Derive
The verified source confirms that derivation is a first-class runtime concept. Registered derivations create new drafts and preserve relationship lineage. Public discovery is unified with all other operations in editor-state.actions; the dispatcher binds a disclosed derivation action to IDocumentDerivationService. The trusted/internal DocumentService.DeriveAsync(...) port retains the explicit payload-based compatibility fallback for non-interactive callers.
Architecturally, derive is the right place for:
- based-on document chains;
- follow-up documents;
- business workflows that should preserve lineage.
Recommended extension checklist
When adding a new document type, review all of these, not only CRUD:
- metadata and storage;
- draft validation;
- posting/effects;
- relationship graph behavior;
- Document Action definitions, authorization, availability, and handlers;
- derivation bindings and relationship lineage;
- audit visibility.