Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions .github/workflows/code-hygiene-self-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,43 @@
path: "${{ steps.fixtures.outputs.root }}/bad-k9",
},
},
# The ignore lists: each must lift exactly its own validator's finding.
# The two positives use the same bad fixtures as the negatives above,
# so they pass only because the named file is skipped.
{
name: "Verify both negative controls failed",
name: "An invalid DEED file on the caller's DEED ignore list must pass",
uses: "$/actions/manifest-check",
with: {
path: "${{ steps.fixtures.outputs.root }}/bad-deed",
deed-paths-ignore: "control.deed",
},
},
{
name: "An invalid K9 file on the caller's K9 ignore list must pass",
uses: "$/actions/manifest-check",
with: {
path: "${{ steps.fixtures.outputs.root }}/bad-k9",
k9-paths-ignore: "control.k9.ncl",
},
},
{
name: "A DEED ignore list must leave K9 validation on",
id: "deed-ignore-k9-on",
continue-on-error: true,
uses: "$/actions/manifest-check",
with: {
path: "${{ steps.fixtures.outputs.root }}/bad-k9",
deed-paths-ignore: "control.k9.ncl",
},
},
{
name: "Verify the negative controls failed",
env: {
DEED_OUTCOME: "${{ steps.bad-deed.outcome }}",
K9_OUTCOME: "${{ steps.bad-k9.outcome }}",
CROSS_OUTCOME: "${{ steps.deed-ignore-k9-on.outcome }}",
},
run: "test \"$DEED_OUTCOME\" = failure && test \"$K9_OUTCOME\" = failure",
run: "test \"$DEED_OUTCOME\" = failure && test \"$K9_OUTCOME\" = failure && test \"$CROSS_OUTCOME\" = failure",
},
# formatting-check reads `git ls-files` in the workspace, so its controls
# run on this checkout: clean it must pass, and with one planted
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/main-estate-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ on:
pull_request:
branches: [ "main" ]
workflow_call:
inputs:
# Forwarded to manifest-check. For files that carry a manifest extension
# but are not manifests (panic-attack's suppression registry at
# audits/assail-classifications.a2ml, for one). A value REPLACES that
# validator's default ignore list; empty keeps the defaults. On this
# repository's own push and pull_request runs both are empty.
manifest-deed-paths-ignore:
description: 'Newline-separated path fragments the DEED validator skips (replaces its defaults; empty keeps them).'
type: string
required: false
default: ''
manifest-k9-paths-ignore:
description: 'Newline-separated path fragments the K9 validator skips (replaces its defaults; empty keeps them).'
type: string
required: false
default: ''

permissions:
contents: read
Expand Down Expand Up @@ -114,6 +130,9 @@ jobs:
- name: Manifest Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/manifest-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
with:
deed-paths-ignore: ${{ inputs.manifest-deed-paths-ignore }}
k9-paths-ignore: ${{ inputs.manifest-k9-paths-ignore }}
Comment thread
hyperpolymath marked this conversation as resolved.
- name: Recipes Set Validation Gate
if: ${{ !cancelled() && steps.checkout.outcome == 'success' }}
uses: hyperpolymath/cicd-suite/actions/recipes-set-check@1aa6bfb657f8240db089a8eef1ad4a7ac198bcf0 # 2026-10-09 (#48)
Expand Down
29 changes: 29 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,35 @@ because `+GITHUB_TOKEN+` may not write under `+.github/workflows/+`.
`+rollout_estate.sh+` does all three for every local estate clone. It
writes files and does not commit them.

If a file carries a manifest extension but is not a manifest, the
`+manifests+` check will fail on it. Panic-attack's suppression registry
at `+audits/assail-classifications.a2ml+` is one such file. Name it in the
caller rather than editing or moving it:

[source,yaml]
----
jobs:
estate:
uses: hyperpolymath/cicd-suite/.github/workflows/main-estate-audit.yml@<40-hex sha> # cicd-suite main
with:
manifest-deed-paths-ignore: |
vendor/
vendored/
verified-container-spec/
.audittraining/
integration/fixtures/
test/fixtures/
tests/fixtures/
audits/assail-classifications.a2ml
----

The list goes to the DEED validator as its `+paths-ignore+` and
*replaces* its defaults, so repeat the defaults you still want, as above.
`+manifest-k9-paths-ignore+` does the same for the K9 validator. That
validator has a different default list, which is why the two lists are
separate. Each fragment is matched as a substring of the file's path.
Leave both unset and each validator keeps its own defaults.

=== Licence

Code MPL-2.0, prose CC-BY-SA-4.0. See link:LICENSE[`+LICENSE+`].
41 changes: 41 additions & 0 deletions actions/manifest-check/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,60 @@ inputs:
description: 'Promote validator warnings to failures.'
required: false
default: 'false'
deed-paths-ignore:
description: >-
Newline-separated path fragments the DEED validator skips, passed through
as its own `paths-ignore`. Use it for files that carry a manifest
extension but are not manifests, such as panic-attack's suppression
registry at audits/assail-classifications.a2ml. A value REPLACES the
validator's default list (vendor/, vendored/, verified-container-spec/,
.audittraining/, integration/fixtures/, test/fixtures/, tests/fixtures/),
so repeat those you still want skipped. Empty, the default, leaves the
validator's defaults in place.
required: false
default: ''
k9-paths-ignore:
description: >-
The same for the K9 validator, whose default list differs (it also skips
coordination.k9, session/custom-checks.k9 and
self-validating/methodology-guard.k9.ncl). Kept separate from
deed-paths-ignore so that ignoring a DEED path never replaces K9's
defaults. Empty, the default, leaves the validator's defaults in place.
required: false
default: ''
runs:
using: 'composite'
# Each validator is called once, with or without the caller's list. A
# `with:` key is always passed, even when empty, and both validators read an
# empty paths-ignore as "skip nothing", so forwarding an empty input would
# widen the scan rather than leave it alone.
steps:
- name: Validate DEED manifests
if: ${{ inputs.deed-paths-ignore == '' }}
uses: hyperpolymath/deed-ecosystem/validate-action@f9d999b60cb5f383679ea19912bcdc49c944973a # main @ 2026-09-17 — SHA-pinned: sha_pinning_required + audit de-onboarded; lock SHA keys cover the onboarded self-test path
with:
path: ${{ inputs.path }}
strict: ${{ inputs.strict }}
- name: Validate DEED manifests (caller's ignore list)
if: ${{ inputs.deed-paths-ignore != '' }}
uses: hyperpolymath/deed-ecosystem/validate-action@f9d999b60cb5f383679ea19912bcdc49c944973a # main @ 2026-09-17 — SHA-pinned: ditto
with:
path: ${{ inputs.path }}
strict: ${{ inputs.strict }}
paths-ignore: ${{ inputs.deed-paths-ignore }}
- name: Validate K9 manifests
if: ${{ inputs.k9-paths-ignore == '' }}
uses: hyperpolymath/k9-ecosystem/validate-action@2155aa26a21758f2ba119f61bc7e0e1981c106fb # main @ 2026-09-17 — SHA-pinned: ditto
with:
path: ${{ inputs.path }}
strict: ${{ inputs.strict }}
- name: Validate K9 manifests (caller's ignore list)
if: ${{ inputs.k9-paths-ignore != '' }}
uses: hyperpolymath/k9-ecosystem/validate-action@2155aa26a21758f2ba119f61bc7e0e1981c106fb # main @ 2026-09-17 — SHA-pinned: ditto
with:
path: ${{ inputs.path }}
strict: ${{ inputs.strict }}
paths-ignore: ${{ inputs.k9-paths-ignore }}
# These validators check manifest structure. Executable Nickel contracts need
# a separate Nickel evaluation step; neither an empty-field grep nor this
# structural check establishes that a contract evaluates or a proof holds.
Loading