spec: lifecycle stages, report scope, and status references by name - #6
Open
delchev wants to merge 1 commit into
Open
spec: lifecycle stages, report scope, and status references by name#6delchev wants to merge 1 commit into
delchev wants to merge 1 commit into
Conversation
An aggregation over an entity that carries a lifecycle is wrong by default: drafts nobody has issued, cancelled documents and voided ones all land in the sum unless the author remembers a predicate over positional status ids, and nothing in the format said so. Three additions, one idea - a status id is data, but its MEANING is not: - `stage` on a status seed row classifies it (draft | live | cancelled | void). Metadata, never a column; it must accompany the row's primary key; a value outside the vocabulary and a colliding `stage` property are authoring errors. - `scope` on a report states which lifecycle rows it counts, in stage terms. With no scope, an aggregating report over a stage-classified nomenclature counts the live rows - but only when its dimensions and filter do not already reference the status, so a breakdown BY status stays complete and an authored predicate stays authoritative. `all` is the explicit opt-out. An aggregation that resolves no stage classification must be reported as a diagnostic; emitting it silently is non-conforming. - Every site that names a status accepts the seeded NAME. Resolution happens before any other validation, so every later rule sees the id. An unresolvable name is an authoring error naming the known statuses; ordering comparisons against a name are rejected because a name has no order; a nomenclature owned by another model is seeded there and must be referenced numerically (listed under Planned). Appendix A gains rows for `scope`, `stage` and status names.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
An aggregation over an entity that carries a lifecycle (
function: EntityStatus) is wrong by default. Drafts nobody has issued, cancelled documents and voided ones all land in the sum unless the author remembers a status predicate — and nothing in the format says an aggregate over such an entity is incomplete without one. The omission is invisible: the file validates, the query is well-formed, the number renders, and the number is wrong.Worse, the only way to say "the rows that count" today is a predicate over positional ids:
Inserting a status into the middle of a nomenclature shifts every later id, and every filter and guard authored against the old numbering keeps producing well-formed output that now means a different status. Nothing downstream can tell, because the emitted constant is valid.
The proposed shape
One idea in three parts: a status id is data, but its meaning is not.
1. Classify the nomenclature where it is seeded.
stageis a closed vocabulary and metadata — never a column of the seeded table.2. Reports state which lifecycle rows they count, in stage terms.
3. Every site that names a status accepts the seeded name.
Expected behaviour
Stated in the chapters; the load-bearing normative rules:
stageMUST NOT reach the seeded table as a column, MUST accompany the row's primary key, and a value outsidedraft | live | cancelled | voidis an authoring error. An entity owning its ownstageproperty cannot be classified this way — the collision is reported, not guessed at.scopeisallor one stage name, meaningful only over a source declaring a status relation. With noscope, a report counts every row except when it aggregates AND its nomenclature is stage-classified AND neither its dimensions nor itsfilterreference the status — then it counts theliverows. A generator MUST NOT combine an implicit scope with an authored status predicate or a status dimension.Edge rules and deliberate boundaries
stage:markers, so no existing file changes meaning until its author classifies the statuses.filteron the status stays authoritative — the implicit scope stands down for both.Prior art / workarounds
Today: a hand-written string predicate over magic ids, repeated per report, plus the same ids in enforcement guards. In a real deployment that combination retired a document through a
VOIDEDtransition while a reversal posting was still guarded on the pre-insertion id — so the ledger kept a receivable and revenue for a document that no longer existed, with valid generated code throughout.Implementation
Implemented in the Eclipse Dirigible reference implementation: eclipse-dirigible/dirigible#6647 (issue eclipse-dirigible/dirigible#6645), with unit coverage per rule and end-to-end coverage of the emitted query, the diagnostic, and the resolved names.