@malloy-publisher/skills 0.1.50 → 0.1.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/eval-answer/SKILL.md +1 -1
- package/skills/eval-diagnose/SKILL.md +1 -1
- package/skills/eval-import/SKILL.md +1 -1
- package/skills/eval-improve/SKILL.md +1 -1
- package/skills/eval-judge/SKILL.md +1 -1
- package/skills/eval-loop/SKILL.md +1 -1
- package/skills/eval-report/SKILL.md +1 -1
- package/skills/malloy-analysis/SKILL.md +2 -1
- package/skills/malloy-analysis-report/SKILL.md +1 -1
- package/skills/malloy-charts/SKILL.md +1 -1
- package/skills/malloy-classify/SKILL.md +1 -1
- package/skills/malloy-compliance-review/SKILL.md +35 -12
- package/skills/malloy-compliance-review/reference/checks.md +14 -5
- package/skills/malloy-compliance-review/reference/register.md +5 -4
- package/skills/malloy-compliance-review/reference/report.md +13 -2
- package/skills/malloy-compliance-review/scripts/compliance.py +192 -38
- package/skills/malloy-compliance-review/scripts/compliance_test.py +337 -9
- package/skills/malloy-dashboards/SKILL.md +1 -1
- package/skills/malloy-define/SKILL.md +1 -1
- package/skills/malloy-define-agent/SKILL.md +1 -1
- package/skills/malloy-discover/SKILL.md +1 -1
- package/skills/malloy-document/SKILL.md +3 -3
- package/skills/malloy-getting-started/SKILL.md +2 -2
- package/skills/malloy-gotchas-modeling/SKILL.md +2 -2
- package/skills/malloy-html-data-apps/SKILL.md +1 -1
- package/skills/malloy-lookml-review/SKILL.md +1 -1
- package/skills/malloy-lookml-review/reference/build-unnest.md +1 -1
- package/skills/malloy-materialization/SKILL.md +1 -1
- package/skills/malloy-model/SKILL.md +3 -3
- package/skills/malloy-model-as-you-go/SKILL.md +1 -1
- package/skills/malloy-modeling/SKILL.md +1 -1
- package/skills/malloy-notebooks/SKILL.md +1 -1
- package/skills/malloy-phrase-detection/SKILL.md +1 -1
- package/skills/malloy-powerbi-review/SKILL.md +1 -1
- package/skills/malloy-publish/SKILL.md +1 -1
- package/skills/malloy-queries/SKILL.md +23 -1
- package/skills/malloy-reports/SKILL.md +1 -1
- package/skills/malloy-review/SKILL.md +1 -1
- package/skills/malloy-review/reference/rubric-correctness.md +1 -1
- package/skills/malloy-run-agent/SKILL.md +1 -1
- package/skills/malloy-source-unreachable/SKILL.md +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eval-answer
|
|
3
3
|
description: 'Score one analytical answer against a verified golden, and score which of the entities the golden depends on retrieval delivered to the answerer. Run the contamination checklist, re-execute the submitted query yourself, then spawn a judge subagent per skill:eval-judge. Append attempt, tool_call, score, and retrieval_score events to the file ledger (reference/ledger-schema.md). Never explain the failure (eval-diagnose) or edit the model (eval-improve). Use when asked whether an answer was correct, to score a run, or to baseline a model.'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Evaluate One Answer
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eval-diagnose
|
|
3
3
|
description: 'Diagnose why a scored answer failed and who owns the fix, then cluster the failures by shared root cause. Walk dataset, agent-call, get_context/model, get_context/retrieval, construction, then model-definition. Append issue events to the file ledger, linked by traceId, one per cluster. Use after eval-answer, when triaging a run, or before changing a model. Does not edit the model (eval-improve).'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Diagnose One Answer
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eval-import
|
|
3
3
|
description: 'Turn a list of questions into an eval set, whatever shape it arrived in: a JSONL a customer sent, a CSV, a spreadsheet export, a markdown doc, an email thread, or a pull from production logs. Classify each item by what came WITH the question (a query, a number, prose criteria, or nothing), write cases.jsonl and set.json per reference/case-format.md, keep the file as it arrived, and seal each question so a later edit is detectable. Never marks a value-bearing golden verified and never invents a question. Use when questions arrive from outside and need to become a set, or before the first run against a set nobody here authored.'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Import questions into an eval set
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eval-improve
|
|
3
3
|
description: 'Make the smallest safe edit that closes a diagnosed gap the model repo owns: a Malloy model edit, or a package skill under skills/. Every factual claim carries a probe receipt. Use after eval-diagnose, or when asked to fix a model so an agent can discover the right answer. Never accepts its own edit; the acceptance check belongs to eval-loop. Does not decide whether an answer was wrong (eval-answer) or why (eval-diagnose).'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Improve the Model
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eval-judge
|
|
3
3
|
description: 'Decide whether ONE answer matches its golden, and say whether you believe the golden. Read this before emitting any verdict. Covers containment, column pairing, near_match, refusals, and the gold_status judgement. Use when scoring an attempt in an evaluation run; never to conduct a run (eval-loop), diagnose a failure (eval-diagnose) or edit a model (eval-improve).'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# The judge
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eval-loop
|
|
3
3
|
description: 'Conduct a local Publisher evaluation loop in five steps: scrape/run, eval, diagnose, improve, checkpoint. You are the conductor: import cases into the file ledger, spawn a blind answerer, then run eval-answer, eval-diagnose, and eval-improve. Persistence is plain files: the set in the model package''s evals/ directory, runs in the set''s workdir; checkpoints are git commits of the model repo. `eval.py` runs each step from the set''s eval.toml. Use to score a model, diagnose failures, improve behind an acceptance check, or roll back a bad direction.'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# The Evaluation Loop
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eval-report
|
|
3
3
|
description: 'Write the summary a person reads after an evaluation run: what ran, what it scored, which failures were the MODEL and which were the EVAL itself (out of turns, contaminated, unestablished golden, unreadable judge), what was learned, and what to do next. Every claim links to the artifact behind it. Use at the end of any run, before quoting a number to anyone. Never scores an answer (eval-answer) or decides who owns a failure (eval-diagnose).'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Report a Run
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-analysis
|
|
3
3
|
description: "Read before your first get_context call on any business or data question. The required workflow, not background: which source, which rows, how to verify. Skipping it causes confident wrong answers."
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
<!-- Copyright (c) Credible Data Inc. SPDX-License-Identifier: MIT -->
|
|
@@ -83,6 +83,7 @@ Your first result is a draft, not an answer. The difference between a useful ana
|
|
|
83
83
|
- **Ask "what would make this wrong?"** then run the query that would expose that problem. A plausible-looking wrong answer is the most dangerous kind.
|
|
84
84
|
- **Check the common failure modes:**
|
|
85
85
|
- Fan-out / double-counting: if you joined across grain, compare `count()` with `count(base_key)`, the base source's own key (in Malloy `count(field)` is already the distinct count). A large gap means base rows are repeated and aggregates are inflated. The check reads one way only: `count(joined.field)` is a distinct count at the joined grain, so it is normally much SMALLER than `count()`, which is not missing data. Measure coverage at the base grain: `count() { where: joined.field is null }`.
|
|
86
|
+
- Grouping by an array: a field with `relationship: "many"` that is not reached through a join (`lines.sku`, `tags.each`) gives one group per distinct element value, and a row lands in every group its array holds, so its groups add up to more than the total, as across a one-to-many join. Do not print a total row across it, and count elements with `tags.count()`, not `count(tags.each)`, which is the distinct count.
|
|
86
87
|
- Broken filters: a quick count confirms a filter narrowed the data as expected. Watch case, spelling and date-format mismatches; a filter that matches nothing still returns a result, just the wrong one. Confirm which dimension the user's word ("brand") maps to when several fields look alike, and that the field means what you assume (gross against net revenue): read its doc. Before a `pick` or `where` that groups values into categories, list the field's distinct values, since an unlisted one falls into `else` unnoticed. Apply the filter the question implies ("last quarter" with no time filter returns all-time data). A view can have a `where:` built in (`recent_orders`): read its code, and query the base source with explicit filters if it conflicts with the ask.
|
|
87
88
|
- Null-driven loss: `count() { where: the_field is null }` shows how many rows a key field drops (`count(the_field)` counts distinct values, so subtracting it from `count()` is not a null count).
|
|
88
89
|
- Parts that do not sum to the whole: if you split a total into categories, confirm they add up. If a doc says the parts are not additive (one event logged on two layers, a non-additive measure), do not print a total row across that dimension, least of all one nobody asked for; give the per-category figures and say why.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-analysis-report
|
|
3
3
|
description: Combine validated Malloy queries into a report (a linear report, read top to bottom). Use when the user asks to "create a report", "combine these into a report", or wants a persistent multi-query artifact.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
<!--
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-charts
|
|
3
3
|
description: Read before choosing a chart or adding a chart annotation. Chart types, tag syntax and scale rules, KPI cards, dashboards, sparklines, and the renderer mistakes that fail silently.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-classify
|
|
3
3
|
description: 'Propose #(classification) annotations for a Malloy model from an access policy''s class scheme, backed by aggregate value evidence from the served data, and show them as a diff before writing anything. Use when the user asks to "classify the model", "tag PHI/PII", "label sensitive fields", or adds fields to a package that a policy governs, and before running malloy-compliance-review on a model nobody has classified.'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
<!--
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-compliance-review
|
|
3
3
|
description: 'Check a Malloy package and its controls against a written access policy: turn the policy''s prose into a control register, run compliance.py check against a served package (structure, access as each role, and the values themselves), judge what needs a person, and produce a report and a signable attestation. Use when the user asks whether a model "complies with", "satisfies" or "meets" a policy, HIPAA, SOC 2, PCI or the like, asks for a compliance review or attestation, or wants the review in CI.'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.52
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
<!--
|
|
@@ -22,12 +22,13 @@ The review has two halves, and they are kept apart on purpose:
|
|
|
22
22
|
- **The register** (`policies/controls.json`) is the policy as checks. You draft it from the prose;
|
|
23
23
|
the policy owner approves it. It changes when the policy changes.
|
|
24
24
|
- **The check** (`scripts/compliance.py check`) runs the register against the package as it is
|
|
25
|
-
served. It changes nothing, reads only aggregates, and exits 1 when a control fails, so the same
|
|
25
|
+
served. It changes nothing, reads only aggregates, and exits 1 when a control fails (3 when nothing failed but something could not be checked), so the same
|
|
26
26
|
command gates every change in CI.
|
|
27
27
|
|
|
28
|
-
What Publisher
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
What Publisher refuses at load (a domain exposing a class its `#(carries)` omits) the check reports
|
|
29
|
+
as the control it breaks. A join that reaches a gated source around its gate is only a `join-bypass`
|
|
30
|
+
warning on the server, in every package, so the check fails it: this review is the hard stop. It
|
|
31
|
+
does not re-derive either.
|
|
31
32
|
|
|
32
33
|
## Before you start
|
|
33
34
|
|
|
@@ -35,6 +36,8 @@ reports as the control it breaks. It does not re-derive them.
|
|
|
35
36
|
review against a server with **no gateway in front**: each persona's givens are sent with the
|
|
36
37
|
request and honored, which is how the check asks "what would this role see". Never point it at a
|
|
37
38
|
production endpoint, where a trusted tier sets those givens and the probe would be meaningless.
|
|
39
|
+
A pass certifies the package's controls. In production they hold only behind the gateway that
|
|
40
|
+
authenticates users, sets the givens and blocks raw SQL, so a report says that alongside the verdict.
|
|
38
41
|
- The policy document.
|
|
39
42
|
- A classified model. If fields are unclassified, `skill:malloy-classify` first.
|
|
40
43
|
|
|
@@ -75,8 +78,14 @@ the MCP endpoint (`--mcp`, default `http://127.0.0.1:4040/mcp`) and `GET /api/v0
|
|
|
75
78
|
every published domain as every persona with a count, queries every source the package does not
|
|
76
79
|
publish (read from the `.malloy` files in the current directory, or `--package-dir`) to confirm it
|
|
77
80
|
refuses, and profiles every published dimension with aggregates (seconds to a minute for 140
|
|
78
|
-
fields). It writes `review/report.json` and `review/report.md`.
|
|
79
|
-
|
|
81
|
+
fields). It writes `review/report.json` and `review/report.md`. Against a server that is not on
|
|
82
|
+
localhost, `--mcp` is required (a usage error otherwise).
|
|
83
|
+
|
|
84
|
+
Exit codes: **0** every control holds, **1** a control fails, **2** usage (a bad flag, or a register that is missing, not JSON or has no `controls`),
|
|
85
|
+
**3** nothing failed but something could not be checked, **4** an internal error (traceback on
|
|
86
|
+
stderr). A probe the server neither answered nor refused (a 400, a 401, a 404 that is not the query
|
|
87
|
+
boundary's refusal, or that names the `--model` itself as missing) is never a pass: it needs review, so a typo cannot make a control hold.
|
|
88
|
+
`--allow-review` turns 3 into 0 for a pipeline that triages review items by hand.
|
|
80
89
|
|
|
81
90
|
### 3. Judge what needs a person
|
|
82
91
|
|
|
@@ -86,9 +95,10 @@ Read `review/report.md`. `reference/report.md` explains each section. For each c
|
|
|
86
95
|
- **FAILS**: name the domain and field from the finding, the requirement it breaks, and the
|
|
87
96
|
smallest change to the model that would fix it. A failure the server refused at load (the report
|
|
88
97
|
says the package is serving a stale model) is already contained: the change was not deployed.
|
|
89
|
-
Say both.
|
|
90
|
-
- **Needs review**: a
|
|
91
|
-
|
|
98
|
+
Say both. A `join-bypass` failure is not contained: the server serves that package with a warning.
|
|
99
|
+
- **Needs review**: a check that could not decide (free text on a de-identified domain, a probe
|
|
100
|
+
the server neither answered nor refused, a cap on a field that was not profiled, a field whose
|
|
101
|
+
declared class is lower than what its expression reads). Look at the evidence and say what you concluded and why; if it needs the
|
|
92
102
|
policy owner, say so.
|
|
93
103
|
- **Not provable here**: say who can prove it.
|
|
94
104
|
|
|
@@ -109,8 +119,21 @@ and rerun.
|
|
|
109
119
|
### 5. In CI
|
|
110
120
|
|
|
111
121
|
Run the same `check` on every change to a `.malloy` file, against a Publisher started on the
|
|
112
|
-
change's checkout, and fail the build on exit 1
|
|
113
|
-
|
|
122
|
+
change's checkout, and fail the build on any non-zero exit: 1 and 4 are never acceptable, and 3
|
|
123
|
+
means a person has to look. `docs/compliance-review.md` has a GitHub Actions example. Upload
|
|
124
|
+
`review/` as the build's artifact so the evidence travels with the change.
|
|
125
|
+
|
|
126
|
+
```yaml
|
|
127
|
+
- name: Review
|
|
128
|
+
run: |
|
|
129
|
+
python3 <skills>/malloy-compliance-review/scripts/compliance.py check \
|
|
130
|
+
--environment ci --package <pkg> --register policies/controls.json --out-dir review
|
|
131
|
+
# add --allow-review to pass on exit 3 (needs review, none failing)
|
|
132
|
+
|
|
133
|
+
- if: always()
|
|
134
|
+
uses: actions/upload-artifact@v4
|
|
135
|
+
with: { name: compliance-review, path: review/ }
|
|
136
|
+
```
|
|
114
137
|
|
|
115
138
|
## Rules
|
|
116
139
|
|
|
@@ -13,14 +13,14 @@ status. The rest are aggregate queries run as the register's personas. None read
|
|
|
13
13
|
| Check | Fails when | Reads |
|
|
14
14
|
| --- | --- | --- |
|
|
15
15
|
| `inventory` | The classification summary lists no source, or `get_context` could not list the published fields | classification summary, `get_context` |
|
|
16
|
-
| `loads` | The package did not load,
|
|
16
|
+
| `loads` | The package did not load, serves a stale model because its latest files were refused, or loads with a `join-bypass` warning (a join that reaches a stricter gate than the entry's). One finding per refusal or warning, tagged with the domain and kind (`ceiling`, `join`); a warning is always kind `join` | `/api/v0/status`, the package read's `warnings` |
|
|
17
17
|
| `refusals` | Never fails on a refusal: a refused change is evidence that a violating change is not deployed | `/api/v0/status` |
|
|
18
|
-
| `coverage` | A published field has no class | classification summary |
|
|
18
|
+
| `coverage` | A published field has no class. A field that declares a lower class than the fields it reads (a `classification-downgrade` warning) needs review | classification summary |
|
|
19
19
|
| `gated` | A published domain has neither `#(authorize)` nor a row filter | model read |
|
|
20
20
|
| `secure_gates` | A gate reads a given that is not `#(secure)` | model read |
|
|
21
|
-
| `locked_bases` | A source the package does not publish answers a count to an identity holding every role the register names. Its sources are read from the package's `.malloy` files and queried through each file's own path; with no files found it needs review | package files, a count per source |
|
|
21
|
+
| `locked_bases` | A source the package does not publish answers a count to an identity holding every role the register names. Its sources are read from the package's `.malloy` files and queried through each file's own path; with no files found, or a probe the server neither answered nor refused, it needs review | package files, a count per source |
|
|
22
22
|
| `ceiling` | A domain declares no `#(carries)`, declares a class its `must_not_carry` forbids, or serves a class beyond it | classification summary, register |
|
|
23
|
-
| `access` | A persona's outcome on a domain differs from the register, or the register names a domain the package does not publish | a count per domain per persona |
|
|
23
|
+
| `access` | A persona's outcome on a domain differs from the register, a gated domain answers a caller with no givens (a domain gated only by a row filter may answer with no rows), or the register names a domain the package does not publish. A probe the server neither answered nor refused needs review | a count per domain per persona, and per gated domain with no givens |
|
|
24
24
|
| `values` | A field's values prove more than its class allows, a de-identified domain serves day dates, five-digit ZIPs or uncapped values. Free text there needs review | `get_context`, an aggregate profile per field |
|
|
25
25
|
|
|
26
26
|
## What the values prove
|
|
@@ -43,8 +43,17 @@ A floor is a lower bound. A birth date's values show dates to the day, a quasi-i
|
|
|
43
43
|
policy's class table makes it direct. The check fails a field declared *below* its floor, never one
|
|
44
44
|
declared above.
|
|
45
45
|
|
|
46
|
+
A probe is **refused** when the server answers 403, or 404 with the query boundary's own refusal
|
|
47
|
+
(`Query target is not queryable.` or `No queryable ...`). Any other non-2xx (a 400 from a typo, a 401,
|
|
48
|
+
a 404 for a domain's model path that is not served) means the probe never reached the gate, so it needs
|
|
49
|
+
review rather than counting as a refusal. `locked_bases` probes models the package keeps off its surface,
|
|
50
|
+
which the server answers like a missing one, so it runs only when `--package-dir` holds a `publisher.json`,
|
|
51
|
+
and is review otherwise.
|
|
52
|
+
|
|
46
53
|
## Scoping
|
|
47
54
|
|
|
48
55
|
A check runs once per review, however many controls name it. A control that names `values:research`
|
|
49
|
-
takes only the findings about `research`;
|
|
56
|
+
takes only the findings about `research`; a scope on `coverage`, `gated`, `secure_gates`, `ceiling` or `values` that names no published domain, or on any other
|
|
57
|
+
check that names no domain, declared source or refusal kind, fails as an unknown scope, and `locked_bases` scopes are checked against the sources the
|
|
58
|
+
package's files declare; if every finding is about another domain, the control
|
|
50
59
|
holds for that check and the report says nothing it found touches `research`.
|
|
@@ -30,7 +30,7 @@ is a complete one for a HIPAA minimum-necessary policy.
|
|
|
30
30
|
| --- | --- | --- |
|
|
31
31
|
| `rows` | Admitted, with every row | The count probe answers, and the domain has no row filter |
|
|
32
32
|
| `scoped` | Admitted, with only the rows its givens select | The count probe answers, and the model read shows a row filter in force |
|
|
33
|
-
| `refused` | Not admitted | The count probe answers 403 |
|
|
33
|
+
| `refused` | Not admitted | The count probe answers 403, or 404 with the query boundary's refusal |
|
|
34
34
|
|
|
35
35
|
`scoped` is read from the model's row filter, never from a smaller count: a persona may be the only
|
|
36
36
|
one admitted to a domain and still be scoped.
|
|
@@ -41,14 +41,15 @@ one admitted to a domain and still be scoped.
|
|
|
41
41
|
"research": {
|
|
42
42
|
"deidentified": true,
|
|
43
43
|
"must_not_carry": ["phi.direct_identifier"],
|
|
44
|
-
"caps": [{ "field": "patient.age", "max": 90 }]
|
|
44
|
+
"caps": [{ "field": "patient.age", "max": 90 }, { "field": "patient.birth_year", "min": 1930 }]
|
|
45
45
|
}
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
- `deidentified`: the domain may serve no day-level date, no five-digit ZIP, and nothing that reads
|
|
49
49
|
as free text.
|
|
50
50
|
- `must_not_carry`: classes the domain's `#(carries)` may not list.
|
|
51
|
-
- `caps`: a numeric field's
|
|
51
|
+
- `caps`: a numeric field's `max`, `min` or both, as the values show it. A capped field that was not
|
|
52
|
+
profiled, or whose numeric query errored, needs review.
|
|
52
53
|
|
|
53
54
|
### Controls
|
|
54
55
|
|
|
@@ -59,7 +60,7 @@ one admitted to a domain and still be scoped.
|
|
|
59
60
|
|
|
60
61
|
- `id` and `text` are the policy's, verbatim.
|
|
61
62
|
- `checks` name what proves the control. A check scoped with `:domain` takes only that domain's
|
|
62
|
-
findings; `loads:` also takes a refusal kind (`ceiling`, `
|
|
63
|
+
findings; `loads:` also takes a refusal kind (`ceiling`, `join`).
|
|
63
64
|
- A control nothing in the model can prove takes `"status": "not_provable_here"` and a `why`.
|
|
64
65
|
- `why` on any control is printed in the report beside it.
|
|
65
66
|
|
|
@@ -17,9 +17,19 @@ SPDX-License-Identifier: MIT
|
|
|
17
17
|
| --- | --- |
|
|
18
18
|
| Holds | Every check the control names passed |
|
|
19
19
|
| FAILS | At least one finding failed. The command exits 1 |
|
|
20
|
-
| Needs review | Nothing failed, but a finding could not decide on its own |
|
|
20
|
+
| Needs review | Nothing failed, but a finding could not decide on its own. With no failure the command exits 3, or 0 under `--allow-review` |
|
|
21
21
|
| Not provable here | The register says the model cannot prove it, and why |
|
|
22
22
|
|
|
23
|
+
## Exit codes
|
|
24
|
+
|
|
25
|
+
| Code | Means |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| 0 | Every control holds or is not provable here |
|
|
28
|
+
| 1 | At least one control fails |
|
|
29
|
+
| 2 | Usage: a bad flag, `--mcp` missing for a server that is not localhost, or a register that cannot be run |
|
|
30
|
+
| 3 | Nothing failed, but at least one control needs review |
|
|
31
|
+
| 4 | Internal error; the traceback is on stderr |
|
|
32
|
+
|
|
23
33
|
## A stale model
|
|
24
34
|
|
|
25
35
|
When the latest files did not load, Publisher keeps serving the model it compiled before, and the
|
|
@@ -32,7 +42,8 @@ deployed. The fix is to the files on disk; the served model is still the last go
|
|
|
32
42
|
On a fresh server, as in CI, a change Publisher refuses at load leaves no earlier model to serve, so
|
|
33
43
|
the package is absent. The report says so at the top. The controls the refusal names fail; every
|
|
34
44
|
other control needs review, marked "not checked", because nothing could be checked. A package the
|
|
35
|
-
server does not know at all
|
|
45
|
+
server does not know at all, with no load error naming it, is review too (exit 3): nothing was
|
|
46
|
+
checked, so check the environment and package names.
|
|
36
47
|
|
|
37
48
|
## Evidence
|
|
38
49
|
|