Skip to content

Ergo spec 0.5

Choose a tag to compare

@github-actions github-actions released this 05 Nov 23:33
· 5 commits to main since this release
spec-v0.5
5fa8f24

New

  • Every failed row has a message, a line of plain text that says what Ergo found, never what the check expected: approver is "ana", and author is "ana", item 2 of tests: ok is false or signed: signature is missing; reviewed: reviewer is missing. message.row and the rules after it say how each cause, value, list, for line and any_of option is written, and how a for item is named, with or without its alias (message.alias). A row that passed has none.
  • A violation carries the message of its row.
  • A path on the right side of is one of, is not one of, contains, does not contain, contains all of, contains none of, contains some of, does not contain all of, matches and does not match walks lists the way a path after every does (walk.right): pin is in $input.sbom.components.name compares pin with the names of the components. The right side is listed as $input.sbom.components[].name, and a list it can't read from every item fails every row, with the cause and words every uses. A leading dot on that path reads the subject's field, and a message and an input name keep the dot only when a part, a parent subject or an alias has the same first name. A field that is on both sides of a phrase is said once in the message.
  • A message that repeats an earlier one in its row is left out, a for line over a part whose whose leaves no item prints the part's list, a for item that isn't an object reads item 2 of commits is null, which isn't an object, within an item, the items of a list under it come before a part that couldn't be read, a sentence on a for line over two lists that walks another list gives each of that list's items its own part, and a for line whose sentence reads a param that isn't a list prints the list it read, or the check followed by is false (message.join, message.empty, message.items).
  • A count of, a sum of or a whose that reads an item that isn't an object names it, item 2 of commits is null, which isn't an object, and an alias or a part is named without a $ (message.items, message.alias). A value or a key that spells an alias, like "$z: x", prints as the input had it.
  • A $min_subjects row that failed because a from line couldn't be read names where the read stopped, item 2 of things is missing or ws is missing for a child subject, without the parent's name (message.from).
  • that picks items by the value itself, where whose picks them by a field: from: every ws that starts with "b" (sentence.condition.word). It works wherever whose does, on a from line, in a check and on a for line. A field called that is written .that. On a from line the $applies row names the item by the subject's plain name, in its inputs and its message, and its expression writes the name in quotes when it has a space or is a word of the grammar, and in a check a that names a list it walks as a whose does (sentence.that.name).
  • distinct after every, some, count of or sum of drops an item whose value equals an earlier one's, by deep JSON equality, so 1 and 1.0 are the same (sentence.distinct). Its scope is the value its path points at, so an every or some phrase with distinct that reads another field of the item is written wrong (sentence.distinct.place). A failed item lists the location of every copy when the read goes through the subject, and a direct $input path lists its own location.
  • A path that reads inside an every, some or for alias that isn't an object and names its key by a field, like w.k named by zz with w a list, ends not_an_object whatever zz holds, and w named by zz with w holding 3 ends as the field says: absent, null or unusable when zz is missing, null or not text, and not_an_object when it is text. A list alias read by a position, like w[0] named by zz, is read as a list (path.field_step). A tie in the second list of a for line names the second item's key (message.cause). Cases cover all three.
  • A from line whose named by each of list starts anywhere but $params or $input, like t named by each of t.keys with t a parent subject, keys or .keys, is written wrong, and $well_formed lists named by each of takes a list from $params or $input, so it can't start at a field or a subject under subjects.<name>.from (subjects.keyed.list). Nothing is read from it, so the subject has no other rows.
  • A list in a list that no step separates from the list around it, like x[0] or x[0][0], is named it in a message: item 1 of x: item 1 of it is 1, which isn't an object (message.items). A count of a key read from a field names the value once, x.k is 1, which isn't a list or an object.
  • A named by field that can't be read, missing, null or not a string, never lets a check pass, does not exist included, whatever the path before it holds, the path being missing among them: x[0] named by zz does not exist with no x and no zz fails as absent (path.field_step).
  • A check whose path into params that aren't an object stops on them names them in its message: $params is 3, which isn't an object for $params.a is 1, zz is in $params.a and $params.a named by zz is 1, $params is 3, which isn't a list when the path starts with a position, like every $params[0].a is 1, and item 1 of $params is 3, which isn't an object when the position is there and the key after it isn't. It never says the check is false. A walk or a count that reads null params, like every $params.a is 1 or count of $params.a is 1, fails as absent with $params is missing, as a plain path does (path.start). A report that changes for a policy that reads such params has a new message, and for those walks and counts a new cause. The same goes for a for line over them, like for: every $params as p, a sentence of a for line, a named by key and a whose that read them, and a sum of or a count of ... whose over params that are a list, and $params exists and $params does not exist with null params fail as absent. A subject's from line that reads them, like things named by each of $params.ks, makes no subjects, and its $min_subjects row fails as unusable and names them in the same way, where it failed as absent and said $params.ks is missing. A check that reads them whole, like x is in $params, or reads a value that is there, says what it says with any params. Cases cover each.
  • A path from $input or $params on the right of contains or is in is named after the left side when both can't be read, zz is "v", which isn't a list, and $input.y is 3, which isn't an object, and a field of the subject there is named first, y is 3, which isn't an object, and zz is "v", which isn't a list. A count of through a position names the item once, item 1 of y: v is 1, which isn't a list or an object, and id is in $input[0].id with the input [{"id": "a"}] says $input[0].id is "a", which isn't a list (message.cause). Cases cover each.

Changed

  • A bare field called distinct is written wrong, and .distinct reads it. Reports of a policy with such a field now fail $well_formed.
  • Reports change: the report's ergo says v0.5, every failed row has a new message field, and so does every violation. The report schema allows it. Nothing else in a report changes, except that a path on the right side of those phrases that goes through a list of objects used to fail every row as unusable with no message that said why, and now compares with the list it reads or fails with the cause and message of the item that can't be read, and that a $input or $params path that reads into text, like $input.a.b with a text, now says $input.a is "x", which isn't an object.
  • Every condition in a whose chain starts with its own whose or that, after each and: deployments whose environment is "prod" and whose change_type is "emergency". A line written the old way, whose a is 1 and b is 2, is written wrong. Reports of policies that use whose with and change that way, since they now fail $well_formed until the policy is changed. Their problem reads a condition after and starts with whose or that. Other reports change in a few places: whose a and whose b used to fail with doesn't parse and now reads, a is a word of the grammar: write .a when a is a word of the grammar, a field called that must be written .that, a whose or that in the wrong place names the word that was written, and a for line with a whose and a that gets the same cause in either order.
  • it is gone from the language, and the subject's name takes its place (sentence.path.subject). With subject region, region is one of $params.allowed_regions checks each region string, and a row names it region. The name reads the subject on the right side of a phrase too (sentence.path.subject.right), and nothing can follow it: region.name is 1 is written wrong with region.name: nothing can follow region, which means the subject: for a field called region, write .region.name, and named by region with named by region: region is the whole subject, so it can't name a key (sentence.path.subject.step). A field called like the subject is written .region. it is an ordinary word now, so a subject, a field, an alias or a part can be called it (sentence.path.subject.name), and a policy that used it for the subject now reads a field called it, or fails with a missing field, until it names the subject. The message of a row that read a value that isn't an object or a list names the subject by its name. Reports change for every policy that used it.
  • A message no longer says the subject is ..., and names the subject or where a read starts instead. A for line on a subject that isn't an object names it, thing is 3, which isn't an object. A for line's whose that meets an item that isn't an object names the item without a colon, item 1 of xs is 1, which isn't an object, where it said item 1 of xs: it is 1, which isn't an object. An $applies row on an item that isn't an object names the subject, t is 3, which isn't an object, and a $min_subjects row whose from stops before its first step names where it starts, $input is null, or the parent subject, artifact is "x", which isn't a list or an object. A child subject read from an item of its parent names the parent, item 1 of p is missing, where it said item 1 of $input is missing. Reports of plain policies change in those messages. (message.items, message.from)
  • The subject's name followed by brackets, s[0], is written wrong like any other step, and the problem says write .s[0] for a field called s. first of s and item 2 of s read an item of a subject that is a list. (sentence.path.subject.step)
  • On the left of a whose and after sorted by, the subject's name is the item's field, like any bare word there, in a check, a for line and a from line, and so is a quoted word of the grammar (sentence.path.start, sentence.path.subject). from: every ws whose w starts with "b", for a subject called w, reads each item's w field, where it read the item itself. On the right of a whose the name reads the subject and .s the item's field (sentence.path.subject.right), so count of $input.ys whose k is s is 1 compares each k with the subject, where it compared it with the item's own s. A field named like the subject is printed with its dot, in a row's inputs and its message, and so is a field named like a part when it is read on the item, like item 1 of .cov.xs is 1 (name.dot). Reports change for policies that write the subject's name in a whose or after sorted by, or read a field named like the subject or a part.