github.com/gemaraproj/gemara@v1.3.0

guidancecatalog.cue raw

  1// SPDX-License-Identifier: Apache-2.0
  2
  3// Schema lifecycle: experimental | stable | deprecated
  4@status("experimental")
  5package gemara
  6
  7import "list"
  8
  9@go(gemara)
 10
 11// GuidanceCatalog represents a concerted documentation effort to help bring about an optimal future without foreknowledge of the implementation details
 12#GuidanceCatalog: {
 13	#Catalog
 14	metadata: type: "GuidanceCatalog"
 15
 16	// type categorizes this document based on the intent of its contents
 17	type: #GuidanceType @go(GuidanceType)
 18
 19	// front-matter provides introductory text for the document to be used during rendering
 20	"front-matter"?: string @go(FrontMatter) @yaml("front-matter,omitempty")
 21
 22	// guidelines is a list of unique guidelines defined by this catalog
 23	guidelines?: [#Guideline, ...#Guideline] @go(Guidelines)
 24
 25	// exemptions provides information about situations where this guidance is not applicable
 26	exemptions?: [#Exemption, ...#Exemption] @go(Exemptions)
 27
 28	if guidelines != _|_ {
 29		_uniqueGuidelineIds: {for i, g in guidelines {(g.id): i}}
 30		groups: [#Group, ...#Group]
 31		let _validGroupIds = [for g in groups {g.id}]
 32
 33		// Unify the valid ID list with a list.Contains constraint to require each entry's value exists
 34		for i, g in guidelines {
 35			_groupValidation: "\(i)": _validGroupIds & list.Contains(g.group)
 36		}
 37		if metadata."applicability-groups" != _|_ {
 38			let _validApplicabilityIds = [for ag in metadata."applicability-groups" {ag.id}]
 39			for i, g in guidelines if g.applicability != _|_ {
 40				for j, a in g.applicability {
 41					_applicabilityValidation: "\(i)-\(j)": _validApplicabilityIds & list.Contains(a)
 42				}
 43			}
 44		}
 45	}
 46}
 47
 48// GuidanceType restricts the possible types that a catalog may be listed as
 49#GuidanceType: "Standard" | "Regulation" | "Best Practice" | "Framework" @go(-)
 50
 51// Exemption describes a single scenario where the catalog is not applicable
 52#Exemption: {
 53	// description identifies who or what is exempt from the full guidance
 54	description: string
 55
 56	// reason explains why the exemption is granted
 57	reason: string
 58
 59	// redirect points to alternative guidelines or controls that should be followed instead
 60	redirect?: #MultiEntryMapping @go(Redirect,optional=nillable)
 61}
 62
 63// Guideline provides explanatory context and recommendations for designing optimal outcomes 
 64#Guideline: {
 65	// id allows this entry to be referenced by other elements
 66	id: string
 67
 68	// title describes the contents of this guideline
 69	title: string
 70
 71	// objective is a unified statement of intent, which may encompass multiple situationally applicable statements
 72	objective: string
 73
 74	// group provides an id to the group that this guideline belongs to
 75	group: string @go(Group)
 76
 77	// recommendations is a list of non-binding suggestions to aid in evaluation or enforcement of the guideline
 78	recommendations?: [string, ...string]
 79
 80	// extends is an id for a guideline which this guideline adds to, in this document or elsewhere
 81	extends?: #EntryMapping @go(Extends,optional=nillable)
 82
 83	// applicability specifies the contexts in which this guideline applies
 84	applicability?: [string, ...string] @go(Applicability)
 85
 86	// rationale provides the context for this guideline
 87	rationale?: #Rationale @go(Rationale,optional=nillable)
 88
 89	// statements is a list of structural sub-requirements within a guideline
 90	statements?: [#Statement, ...#Statement] @go(Statements)
 91
 92	// principles documents the relationship between this guideline and one or more principles
 93	"principles"?: [#MultiEntryMapping, ...#MultiEntryMapping] @go(Principles) @yaml("principles,omitempty")
 94
 95	// vector-mappings documents the relationship between this guideline and one or more vectors
 96	"vectors"?: [#MultiEntryMapping, ...#MultiEntryMapping] @go(Vectors) @yaml("vectors,omitempty")
 97
 98	// see-also lists related guideline IDs within the same GuidanceCatalog
 99	"see-also"?: [string, ...string] @go(SeeAlso) @yaml("see-also,omitempty")
100
101	// state is the lifecycle state of this guideline
102	state: #Lifecycle @go(State) @yaml("state,omitempty")
103
104	// replaced-by references the guideline that supersedes this one when deprecated or retired
105	"replaced-by"?: #EntryMapping @go(ReplacedBy,optional=nillable) @yaml("replaced-by,omitempty")
106
107	// retired guidelines must not have recommendations
108	if state == "Retired" {
109		recommendations?: _|_
110	}
111}
112
113// Statement represents a structural sub-requirement within a guideline;
114// They do not increase strictness and all statements within a guideline apply together
115#Statement: {
116	// id allows this entry to be referenced by other elements
117	id: string
118
119	// title describes the contents of this statement
120	title?: string
121
122	// text is the body of this statement
123	text: string
124
125	// recommendations is a list of non-binding suggestions to aid in evaluation or enforcement of the statement
126	recommendations?: [string, ...string]
127}
128
129// Rationale provides a structured way to communicate a guideline author's intent
130#Rationale: {
131	// importance is an explanation of why this guideline matters
132	importance: string
133
134	// goals is a list of outcomes this guideline seeks to achieve
135	goals: [string, ...string]
136}