assertions-mate 0.2.0__tar.gz → 0.5.0__tar.gz
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.
- assertions_mate-0.5.0/.env +1 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/.gitignore +3 -1
- assertions_mate-0.5.0/CHANGELOG.md +73 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/PKG-INFO +15 -11
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/README.md +6 -0
- assertions_mate-0.5.0/Taskfile.yaml +46 -0
- assertions_mate-0.5.0/docs/explanation/architecture.md +66 -0
- assertions_mate-0.5.0/docs/explanation/compatibility-and-limitations.md +40 -0
- assertions_mate-0.5.0/docs/explanation/testing-and-reliability.md +32 -0
- assertions_mate-0.5.0/docs/how-to/add-cql2-polygon-area-function.md +57 -0
- assertions_mate-0.5.0/docs/how-to/author-cql2-json-encoding.md +46 -0
- assertions_mate-0.5.0/docs/how-to/combine-multiple-hints.md +57 -0
- assertions_mate-0.5.0/docs/how-to/create-reusable-rego-snippets.md +52 -0
- assertions_mate-0.5.0/docs/how-to/test-hints-with-pytest.md +27 -0
- assertions_mate-0.5.0/docs/how-to/troubleshoot-cwl-loader-errors.md +19 -0
- assertions_mate-0.5.0/docs/how-to/troubleshoot-rego-invalid-literal.md +32 -0
- assertions_mate-0.5.0/docs/how-to/use-packed-vs-single-cwl.md +28 -0
- assertions_mate-0.5.0/docs/how-to/validate-array-cardinality-jsonschema.md +48 -0
- assertions_mate-0.5.0/docs/how-to/validate-bbox-overlap-cql2.md +53 -0
- assertions_mate-0.5.0/docs/how-to/validate-conditional-required-rego.md +46 -0
- assertions_mate-0.5.0/docs/how-to/validate-cross-field-dependency-rego.md +46 -0
- assertions_mate-0.5.0/docs/how-to/validate-date-range-inputs.md +85 -0
- assertions_mate-0.5.0/docs/how-to/validate-datetime-input.md +83 -0
- assertions_mate-0.5.0/docs/how-to/validate-datetime-window-rego.md +64 -0
- assertions_mate-0.5.0/docs/how-to/validate-disjoint-geometries-cql2.md +38 -0
- assertions_mate-0.5.0/docs/how-to/validate-enum-jsonschema.md +45 -0
- assertions_mate-0.5.0/docs/how-to/validate-numeric-range-rego.md +48 -0
- assertions_mate-0.5.0/docs/how-to/validate-optional-input-rego.md +51 -0
- assertions_mate-0.5.0/docs/how-to/validate-point-in-polygon-cql2.md +43 -0
- assertions_mate-0.5.0/docs/how-to/validate-polygon-area-cql2.md +42 -0
- assertions_mate-0.5.0/docs/how-to/validate-polygon-intersects-aoi-cql2.md +38 -0
- assertions_mate-0.5.0/docs/how-to/validate-polygon-parameter.md +82 -0
- assertions_mate-0.5.0/docs/how-to/validate-required-property-rego.md +41 -0
- assertions_mate-0.5.0/docs/how-to/validate-uri-host-rego.md +57 -0
- assertions_mate-0.5.0/docs/how-to/validate-uri-input.md +78 -0
- assertions_mate-0.5.0/docs/index.md +44 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/docs/jsonschema.ipynb +10 -2
- assertions_mate-0.5.0/docs/pygeofilter.ipynb +3070 -0
- assertions_mate-0.5.0/docs/reference/cli.md +41 -0
- assertions_mate-0.5.0/docs/reference/errors.md +50 -0
- assertions_mate-0.5.0/docs/reference/hints.md +60 -0
- assertions_mate-0.5.0/docs/reference/hints_schema.html +226 -0
- assertions_mate-0.5.0/docs/reference/runtime-compatibility.md +53 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/docs/regopy.ipynb +39 -22
- assertions_mate-0.5.0/docs/tutorials/first-validated-workflow.md +93 -0
- assertions_mate-0.5.0/examples/array-cardinality-validation/inputs-invalid.yaml +1 -0
- assertions_mate-0.5.0/examples/array-cardinality-validation/inputs-valid.yaml +1 -0
- assertions_mate-0.5.0/examples/array-cardinality-validation/workflow.cwl +20 -0
- assertions_mate-0.5.0/examples/bbox-overlap-validation/inputs-invalid.yaml +2 -0
- assertions_mate-0.5.0/examples/bbox-overlap-validation/inputs-valid.yaml +2 -0
- assertions_mate-0.5.0/examples/bbox-overlap-validation/workflow.cwl +33 -0
- assertions_mate-0.5.0/examples/conditional-required-validation/inputs-invalid.yaml +2 -0
- assertions_mate-0.5.0/examples/conditional-required-validation/inputs-valid.yaml +9 -0
- assertions_mate-0.5.0/examples/conditional-required-validation/workflow.cwl +24 -0
- assertions_mate-0.5.0/examples/cql2-json-validation/inputs-invalid.yaml +1 -0
- assertions_mate-0.5.0/examples/cql2-json-validation/inputs-valid.yaml +1 -0
- assertions_mate-0.5.0/examples/cql2-json-validation/workflow.cwl +18 -0
- assertions_mate-0.5.0/examples/cross-field-dependency-validation/inputs-invalid.yaml +2 -0
- assertions_mate-0.5.0/examples/cross-field-dependency-validation/inputs-valid.yaml +2 -0
- assertions_mate-0.5.0/examples/cross-field-dependency-validation/workflow.cwl +24 -0
- assertions_mate-0.5.0/examples/date-range-validation/README.md +30 -0
- assertions_mate-0.5.0/examples/date-range-validation/inputs-invalid.yaml +4 -0
- assertions_mate-0.5.0/examples/date-range-validation/inputs-null.yaml +4 -0
- assertions_mate-0.5.0/examples/date-range-validation/inputs-valid.yaml +4 -0
- assertions_mate-0.5.0/examples/date-range-validation/workflow.cwl +79 -0
- assertions_mate-0.5.0/examples/datetime-validation/README.md +30 -0
- assertions_mate-0.5.0/examples/datetime-validation/inputs-invalid.yaml +2 -0
- assertions_mate-0.5.0/examples/datetime-validation/inputs-null.yaml +2 -0
- assertions_mate-0.5.0/examples/datetime-validation/inputs-valid.yaml +2 -0
- assertions_mate-0.5.0/examples/datetime-validation/workflow.cwl +46 -0
- assertions_mate-0.5.0/examples/datetime-window-validation/inputs-invalid.yaml +2 -0
- assertions_mate-0.5.0/examples/datetime-window-validation/inputs-valid.yaml +2 -0
- assertions_mate-0.5.0/examples/datetime-window-validation/workflow.cwl +35 -0
- assertions_mate-0.5.0/examples/disjoint-geometries-validation/inputs-invalid.yaml +16 -0
- assertions_mate-0.5.0/examples/disjoint-geometries-validation/inputs-valid.yaml +16 -0
- assertions_mate-0.5.0/examples/disjoint-geometries-validation/workflow.cwl +16 -0
- assertions_mate-0.5.0/examples/enum-validation/inputs-invalid.yaml +1 -0
- assertions_mate-0.5.0/examples/enum-validation/inputs-valid.yaml +1 -0
- assertions_mate-0.5.0/examples/enum-validation/workflow.cwl +17 -0
- assertions_mate-0.5.0/examples/multi-hint-validation/inputs-invalid.yaml +17 -0
- assertions_mate-0.5.0/examples/multi-hint-validation/inputs-valid.yaml +17 -0
- assertions_mate-0.5.0/examples/multi-hint-validation/workflow.cwl +36 -0
- assertions_mate-0.5.0/examples/numeric-range-validation/inputs-invalid.yaml +1 -0
- assertions_mate-0.5.0/examples/numeric-range-validation/inputs-valid.yaml +1 -0
- assertions_mate-0.5.0/examples/numeric-range-validation/workflow.cwl +26 -0
- assertions_mate-0.5.0/examples/optional-input-validation/inputs-invalid.yaml +1 -0
- assertions_mate-0.5.0/examples/optional-input-validation/inputs-valid.yaml +1 -0
- assertions_mate-0.5.0/examples/optional-input-validation/workflow.cwl +23 -0
- assertions_mate-0.5.0/examples/point-in-polygon-validation/README.md +23 -0
- assertions_mate-0.5.0/examples/point-in-polygon-validation/inputs-invalid.yaml +11 -0
- assertions_mate-0.5.0/examples/point-in-polygon-validation/inputs-valid.yaml +11 -0
- assertions_mate-0.5.0/examples/point-in-polygon-validation/workflow.cwl +23 -0
- assertions_mate-0.5.0/examples/polygon-intersects-validation/inputs-invalid.yaml +16 -0
- assertions_mate-0.5.0/examples/polygon-intersects-validation/inputs-valid.yaml +16 -0
- assertions_mate-0.5.0/examples/polygon-intersects-validation/workflow.cwl +16 -0
- assertions_mate-0.5.0/examples/polygon-validation/README.md +23 -0
- assertions_mate-0.5.0/examples/polygon-validation/inputs-invalid.yaml +4 -0
- assertions_mate-0.5.0/examples/polygon-validation/inputs-null.yaml +1 -0
- assertions_mate-0.5.0/examples/polygon-validation/inputs-valid.yaml +9 -0
- assertions_mate-0.5.0/examples/polygon-validation/workflow.cwl +27 -0
- assertions_mate-0.5.0/examples/pytest-validation/test_validators_example.py +20 -0
- assertions_mate-0.5.0/examples/required-property-validation/inputs-invalid.yaml +9 -0
- assertions_mate-0.5.0/examples/required-property-validation/inputs-valid.yaml +10 -0
- assertions_mate-0.5.0/examples/required-property-validation/workflow.cwl +19 -0
- assertions_mate-0.5.0/examples/reusable-rego-snippets/inputs-invalid.yaml +2 -0
- assertions_mate-0.5.0/examples/reusable-rego-snippets/inputs-valid.yaml +2 -0
- assertions_mate-0.5.0/examples/reusable-rego-snippets/workflow.cwl +32 -0
- assertions_mate-0.5.0/examples/uri-host-validation/inputs-invalid.yaml +1 -0
- assertions_mate-0.5.0/examples/uri-host-validation/inputs-valid.yaml +1 -0
- assertions_mate-0.5.0/examples/uri-host-validation/workflow.cwl +26 -0
- assertions_mate-0.5.0/examples/uri-validation/README.md +30 -0
- assertions_mate-0.5.0/examples/uri-validation/inputs-invalid.yaml +2 -0
- assertions_mate-0.5.0/examples/uri-validation/inputs-null.yaml +2 -0
- assertions_mate-0.5.0/examples/uri-validation/inputs-valid.yaml +2 -0
- assertions_mate-0.5.0/examples/uri-validation/workflow.cwl +46 -0
- assertions_mate-0.5.0/mkdocs.yaml +137 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/pyproject.toml +17 -19
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/schemas/hints.yaml +16 -6
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/src/assertions_mate/__about__.py +1 -1
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/src/assertions_mate/__init__.py +4 -2
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/src/assertions_mate/cql2_validator.py +24 -19
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/src/assertions_mate/rego_validator.py +1 -1
- assertions_mate-0.5.0/tests/test_cql2_validator.py +86 -0
- assertions_mate-0.5.0/tests/test_howto_hints.py +83 -0
- assertions_mate-0.2.0/Taskfile.yaml +0 -32
- assertions_mate-0.2.0/docs/index.md +0 -9
- assertions_mate-0.2.0/docs/pygeofilter.ipynb +0 -191
- assertions_mate-0.2.0/mkdocs.yaml +0 -102
- assertions_mate-0.2.0/tests/test_cql2_validator.py +0 -51
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/.github/workflows/docs.yaml +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/.github/workflows/package.yaml +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/LICENSE +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/NOTICE +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/docs/diagrams/src/class.puml +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/docs/diagrams/src/flow.puml +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/docs/diagrams/src/overall.puml +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/docs/diagrams/src/sequence.puml +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/src/assertions_mate/cli.py +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/src/assertions_mate/error_models.py +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/src/assertions_mate/jsonschema_validator.py +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/tests/artifacts/request_body.yaml +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/tests/test_hints.py +0 -0
- {assertions_mate-0.2.0 → assertions_mate-0.5.0}/tests/test_jsonschema_validator.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
TASK_X_REMOTE_TASKFILES=1
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
### Deprecated
|
|
15
|
+
|
|
16
|
+
### Removed
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
### Security
|
|
21
|
+
|
|
22
|
+
## [0.4.0] - 2026-05-29
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Expanded the documentation site with Diataxis-oriented tutorials, how-to guides, reference pages, and explanation pages.
|
|
27
|
+
- Added runnable CWL examples for URI, datetime, date range, polygon, bbox overlap, CQL2 JSON, enum, array cardinality, multi-hint, Rego, and pytest-based validation workflows.
|
|
28
|
+
- Added generated schema reference documentation for assertion hints.
|
|
29
|
+
- Added support for `Cql2FilterHint.custom_functions`, allowing CWL hints to provide Python functions used by CQL2 validation.
|
|
30
|
+
- Added tests that exercise how-to hint extraction and CQL2 custom function execution.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Changed assertion schema records to extend `cwl:ProcessRequirement` instead of `cwl:ProcessHint`.
|
|
35
|
+
- Updated the CQL2 hint schema with field documentation and links to CQL2 and Rego references.
|
|
36
|
+
- Moved the default Taskfile workflow to remote shared quality tasks and added documentation/schema-generation tasks.
|
|
37
|
+
- Updated package metadata through `0.4.0`; the repository currently has no Git tags after `v0.2.0`.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- Normalized CWL/YAML scalar values before parsing CQL2 JSON filters.
|
|
42
|
+
- Updated Rego validation to use the default regopy interpreter setup, avoiding runtime issues with supported policy syntax.
|
|
43
|
+
- Fixed URI and datetime examples to validate typed input payloads through their `value` fields.
|
|
44
|
+
- Fixed and expanded CQL2 bbox validation examples to use custom functions declared in the CWL hint.
|
|
45
|
+
- Fixed MkDocs configuration and documentation navigation for the expanded site.
|
|
46
|
+
|
|
47
|
+
## [0.2.0] - 2026-03-06
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- Added the initial Python package for validating CWL workflow inputs from embedded assertion hints.
|
|
52
|
+
- Added support for `eoap:JSONSchemaHint`, `eoap:RegoPolicyHint`, and `eoap:Cql2FilterHint`.
|
|
53
|
+
- Added the `assertions-mate` command-line entry point for loading CWL workflows, reading YAML inputs, and reporting validation violations.
|
|
54
|
+
- Added CWL schema definitions for the supported assertion hint records.
|
|
55
|
+
- Added Pydantic error models for validation problem details and business rule violations.
|
|
56
|
+
- Added unit tests for JSON Schema, Rego, CQL2, and hint extraction behavior.
|
|
57
|
+
- Added README usage documentation, notebooks, and the initial MkDocs documentation setup.
|
|
58
|
+
- Added Hatch, pytest, Ruff, Taskfile, and CI configuration for development and validation workflows.
|
|
59
|
+
- Added Apache-2.0 license headers across the package.
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- Updated workflow CI to use Python 3.12 and then expanded the test matrix across Python 3.10 through 3.14.
|
|
64
|
+
- Aligned hint keyword naming and schema structure with CWL/EOAP conventions.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- Fixed documentation build issues around PlantUML and MkDocs plugin configuration.
|
|
69
|
+
- Fixed API documentation generation and schema behavior according to canonical CWL practices.
|
|
70
|
+
|
|
71
|
+
[Unreleased]: https://github.com/Terradue/assertions-mate/compare/v0.4.0...develop
|
|
72
|
+
[0.4.0]: https://github.com/Terradue/assertions-mate/compare/v0.2.0...v0.4.0
|
|
73
|
+
[0.2.0]: https://github.com/Terradue/assertions-mate/releases/tag/v0.2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: assertions-mate
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Project-URL: Documentation, https://github.com/Terradue/assertions-mate#README.md
|
|
5
5
|
Project-URL: Issues, https://github.com/Terradue/assertions-mate/issues
|
|
6
6
|
Project-URL: Source, https://github.com/Terradue/assertions-mate
|
|
@@ -18,17 +18,15 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
18
18
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
19
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
|
-
Requires-Dist: click
|
|
22
|
-
Requires-Dist: cwl-utils
|
|
23
|
-
Requires-Dist: cwl2ogc
|
|
24
|
-
Requires-Dist: jsonschema
|
|
25
|
-
Requires-Dist: loguru
|
|
26
|
-
Requires-Dist: pydantic
|
|
27
|
-
Requires-Dist: pygeofilter
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist: pystac-client
|
|
21
|
+
Requires-Dist: click==8.3.3
|
|
22
|
+
Requires-Dist: cwl-utils==0.41
|
|
23
|
+
Requires-Dist: cwl2ogc==0.18.0
|
|
24
|
+
Requires-Dist: jsonschema==4.26.0
|
|
25
|
+
Requires-Dist: loguru==0.7.3
|
|
26
|
+
Requires-Dist: pydantic==2.12.5
|
|
27
|
+
Requires-Dist: pygeofilter[backend-native]==0.3.3
|
|
28
|
+
Requires-Dist: pyyaml==6.0.3
|
|
30
29
|
Requires-Dist: regopy==0.4.6
|
|
31
|
-
Requires-Dist: shapely
|
|
32
30
|
Description-Content-Type: text/markdown
|
|
33
31
|
|
|
34
32
|
# Assertions Mate
|
|
@@ -42,6 +40,12 @@ It adds policy and rule checks on top of CWL typing by supporting:
|
|
|
42
40
|
|
|
43
41
|
Documentation site: https://terradue.github.io/assertions-mate/
|
|
44
42
|
|
|
43
|
+
Documentation follows the Diataxis framework:
|
|
44
|
+
- Tutorials: learning-oriented walkthroughs
|
|
45
|
+
- How-to guides: task-focused recipes
|
|
46
|
+
- Reference: technical contracts and interfaces
|
|
47
|
+
- Explanation: design rationale and concepts
|
|
48
|
+
|
|
45
49
|
## Why Use It
|
|
46
50
|
|
|
47
51
|
When a CWL workflow needs stricter runtime checks (business rules, policy constraints, geospatial conditions), `assertions-mate` lets you define them as workflow hints and evaluate them against an input payload before execution.
|
|
@@ -9,6 +9,12 @@ It adds policy and rule checks on top of CWL typing by supporting:
|
|
|
9
9
|
|
|
10
10
|
Documentation site: https://terradue.github.io/assertions-mate/
|
|
11
11
|
|
|
12
|
+
Documentation follows the Diataxis framework:
|
|
13
|
+
- Tutorials: learning-oriented walkthroughs
|
|
14
|
+
- How-to guides: task-focused recipes
|
|
15
|
+
- Reference: technical contracts and interfaces
|
|
16
|
+
- Explanation: design rationale and concepts
|
|
17
|
+
|
|
12
18
|
## Why Use It
|
|
13
19
|
|
|
14
20
|
When a CWL workflow needs stricter runtime checks (business rules, policy constraints, geospatial conditions), `assertions-mate` lets you define them as workflow hints and evaluate them against an input payload before execution.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright 2026 Terradue
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
version: '3'
|
|
16
|
+
|
|
17
|
+
includes:
|
|
18
|
+
quality: https://raw.githubusercontent.com/Terradue/taskfile-utils/refs/heads/main/quality.yaml
|
|
19
|
+
|
|
20
|
+
tasks:
|
|
21
|
+
|
|
22
|
+
default:
|
|
23
|
+
cmds:
|
|
24
|
+
- task: quality:test
|
|
25
|
+
- task: quality:check
|
|
26
|
+
|
|
27
|
+
generate_schema_doc:
|
|
28
|
+
cmds:
|
|
29
|
+
- |
|
|
30
|
+
uv run \
|
|
31
|
+
--no-cache \
|
|
32
|
+
--no-project \
|
|
33
|
+
--with schema-salad \
|
|
34
|
+
schema-salad-doc \
|
|
35
|
+
--only 'http://oeap.github.io/schema#JSONSchemaHint' \
|
|
36
|
+
--only 'http://oeap.github.io/schema#RegoPolicyHint' \
|
|
37
|
+
--only 'http://oeap.github.io/schema#Cql2Query' \
|
|
38
|
+
--only 'http://oeap.github.io/schema#Cql2FilterHint' \
|
|
39
|
+
./schemas/hints.yaml > ./docs/reference/hints_schema.html
|
|
40
|
+
|
|
41
|
+
docs:serve:
|
|
42
|
+
desc: "Serve MkDocs site using hatch docs environment"
|
|
43
|
+
cmds:
|
|
44
|
+
- |
|
|
45
|
+
set -euo pipefail
|
|
46
|
+
HATCH_DATA_DIR="$PWD/.task/hatch" hatch run docs:serve
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Architecture and Design
|
|
2
|
+
|
|
3
|
+
`assertions-mate` is built around hint-driven validation for CWL workflows.
|
|
4
|
+
|
|
5
|
+
## Why Hints
|
|
6
|
+
|
|
7
|
+
CWL input typing can enforce structure, but many operational constraints are semantic:
|
|
8
|
+
- policy constraints
|
|
9
|
+
- domain rules
|
|
10
|
+
- geospatial relationships
|
|
11
|
+
|
|
12
|
+
Hints let these constraints travel with workflow definitions and be checked consistently before runtime.
|
|
13
|
+
|
|
14
|
+
## Validation Flow
|
|
15
|
+
|
|
16
|
+
1. Load CWL workflow document(s).
|
|
17
|
+
2. Read `workflow.hints`.
|
|
18
|
+
3. Map supported `eoap:*` hint classes to typed hint models.
|
|
19
|
+
4. Build validator objects from hints.
|
|
20
|
+
5. Run each validator against provided inputs.
|
|
21
|
+
6. Aggregate and log violations.
|
|
22
|
+
|
|
23
|
+
## Execution Semantics
|
|
24
|
+
|
|
25
|
+
`assertions-mate` follows a best-effort setup model:
|
|
26
|
+
|
|
27
|
+
- each hint is mapped and initialized independently
|
|
28
|
+
- setup failures for one hint do not prevent other hints from running
|
|
29
|
+
- validation output is therefore partial if one validator fails to initialize
|
|
30
|
+
|
|
31
|
+
This model favors operational continuity and progressive validation.
|
|
32
|
+
|
|
33
|
+
## Validator Model
|
|
34
|
+
|
|
35
|
+
Each hint type is responsible for producing a validator via `.validator()`.
|
|
36
|
+
|
|
37
|
+
This keeps:
|
|
38
|
+
- hint parsing and serialization concerns in hint models
|
|
39
|
+
- runtime validation behavior in validator classes
|
|
40
|
+
|
|
41
|
+
## Input Shape and Key Resolution
|
|
42
|
+
|
|
43
|
+
Validators operate on the loaded input mapping as-is.
|
|
44
|
+
|
|
45
|
+
Implications:
|
|
46
|
+
- input keys must match workflow input names exactly
|
|
47
|
+
- object wrappers such as `value` must be handled explicitly in rules (for example in Rego)
|
|
48
|
+
- inconsistent shape across workflows can produce false negatives if rules target the wrong path
|
|
49
|
+
|
|
50
|
+
## Supported Rule Languages
|
|
51
|
+
|
|
52
|
+
- JSON Schema: structural constraints over payload shape and values
|
|
53
|
+
- Rego: policy-oriented queries and rich rule composition
|
|
54
|
+
- CQL2: declarative predicate checks, including geospatial expressions
|
|
55
|
+
|
|
56
|
+
## Reliability Tradeoffs
|
|
57
|
+
|
|
58
|
+
- Strength: multi-validator execution can still produce useful checks when one hint fails setup.
|
|
59
|
+
- Tradeoff: setup errors and runtime backend constraints may reduce total coverage for a given run.
|
|
60
|
+
- Practical guidance: treat logs as part of the contract and monitor setup failures explicitly in CI.
|
|
61
|
+
|
|
62
|
+
## Known Gaps and Improvement Areas
|
|
63
|
+
|
|
64
|
+
- Runtime-specific parser differences can affect CWL load behavior and Rego syntax support.
|
|
65
|
+
- Some CQL2 features require explicit coercion helpers (`ensure_spatial`, `ensure_bbox`).
|
|
66
|
+
- Strict fail-fast exit semantics for reported violations are not yet guaranteed in all execution paths.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Compatibility and Limitations
|
|
2
|
+
|
|
3
|
+
This page explains where runtime behavior depends on parser and backend versions.
|
|
4
|
+
|
|
5
|
+
## Rego Runtime Coupling
|
|
6
|
+
|
|
7
|
+
Rego syntax support is runtime-dependent.
|
|
8
|
+
|
|
9
|
+
Stable pattern in current examples:
|
|
10
|
+
|
|
11
|
+
```rego
|
|
12
|
+
deny[msg] {
|
|
13
|
+
condition
|
|
14
|
+
msg := "..."
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Depending on runtime, newer syntax forms can fail with parser errors such as `Invalid literal`.
|
|
19
|
+
|
|
20
|
+
## CQL2 Backend Constraints
|
|
21
|
+
|
|
22
|
+
CQL2 spatial predicates operate reliably when payloads are coerced with helper functions:
|
|
23
|
+
|
|
24
|
+
- `ensure_spatial(...)` for GeoJSON geometry objects
|
|
25
|
+
|
|
26
|
+
Without coercion, backend exceptions can occur because predicates receive non-geometry objects.
|
|
27
|
+
|
|
28
|
+
## External CWL Type References
|
|
29
|
+
|
|
30
|
+
External schema refs (for example EOAP `#DateTime`, `#Polygon`) may require online resolution and parser compatibility.
|
|
31
|
+
|
|
32
|
+
Operational impact:
|
|
33
|
+
- local/offline environments may fail to resolve external refs
|
|
34
|
+
- integration tests should allow offline skip behavior
|
|
35
|
+
|
|
36
|
+
## JSON CQL2 From YAML
|
|
37
|
+
|
|
38
|
+
YAML-native scalar wrappers can affect CQL2 JSON evaluation if not normalized.
|
|
39
|
+
|
|
40
|
+
Current validator behavior includes normalization to builtin Python values before parsing CQL2 JSON, improving reliability.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Testing and Reliability
|
|
2
|
+
|
|
3
|
+
This project benefits from a split testing strategy.
|
|
4
|
+
|
|
5
|
+
## Unit Tests
|
|
6
|
+
|
|
7
|
+
Focus on deterministic behavior with local types and direct validator logic.
|
|
8
|
+
|
|
9
|
+
Examples:
|
|
10
|
+
- hint extraction and mapping tests
|
|
11
|
+
- CQL2 text/json predicate tests
|
|
12
|
+
- JSON schema validation tests
|
|
13
|
+
|
|
14
|
+
## Integration-Oriented Tests
|
|
15
|
+
|
|
16
|
+
Use real example workflows and external type references.
|
|
17
|
+
|
|
18
|
+
Because these can require network and parser compatibility, they should:
|
|
19
|
+
- skip when offline
|
|
20
|
+
- be isolated from core deterministic tests
|
|
21
|
+
|
|
22
|
+
## Reliability Patterns for CI
|
|
23
|
+
|
|
24
|
+
- treat hint setup errors as first-class signals
|
|
25
|
+
- include at least one valid and one invalid case per how-to example
|
|
26
|
+
- prefer stable syntax subsets for Rego and CQL2 in production pipelines
|
|
27
|
+
|
|
28
|
+
## Practical Guardrails
|
|
29
|
+
|
|
30
|
+
- keep payload key names aligned with workflow inputs
|
|
31
|
+
- document scalar vs wrapped object shapes (`value`) and test both where applicable
|
|
32
|
+
- reuse proven example expressions to avoid backend incompatibilities
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# How-to: Add `polygon_area(...)` to the CQL2 Evaluator
|
|
2
|
+
|
|
3
|
+
This guide shows how to extend `assertions-mate` so CQL2 rules can compare polygon area against a fixed threshold.
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
|
|
7
|
+
Enable expressions like:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
polygon_area(aoi) < 1000
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 1. Define the new function in a CQL2 hint
|
|
14
|
+
|
|
15
|
+
In your workflow hints, plug the suggested implementation:
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
hints:
|
|
19
|
+
- class: eoap:Cql2FilterHint
|
|
20
|
+
custom_functions: |
|
|
21
|
+
from shapely import geometry
|
|
22
|
+
from typing import Any, List, Mapping, Union
|
|
23
|
+
|
|
24
|
+
def polygon_area(input: Union[Mapping[str, Any], List[Any]]):
|
|
25
|
+
"""Return area for a GeoJSON Polygon payload or raw coordinates list."""
|
|
26
|
+
if isinstance(input, dict):
|
|
27
|
+
geo_type = input.get("type")
|
|
28
|
+
coords = input.get("coordinates")
|
|
29
|
+
if geo_type != "Polygon" or not coords:
|
|
30
|
+
raise ValueError("Input must be a GeoJSON Polygon with coordinates")
|
|
31
|
+
geom = geometry.Polygon(coords[0])
|
|
32
|
+
return geom.area
|
|
33
|
+
|
|
34
|
+
if isinstance(input, list):
|
|
35
|
+
geom = geometry.Polygon(input[0] if input and isinstance(input[0], list) else input)
|
|
36
|
+
return geom.area
|
|
37
|
+
|
|
38
|
+
raise ValueError(f"Unsupported polygon input type: {type(input)}")
|
|
39
|
+
queries:
|
|
40
|
+
- id: aoi-area-limit
|
|
41
|
+
cql2: "polygon_area(aoi) < 1000"
|
|
42
|
+
message: "AOI area must be smaller than 1000"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 2. Validate with CLI
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
assertions-mate path/to/workflow.cwl --inputs path/to/inputs.yaml
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Notes on units
|
|
52
|
+
|
|
53
|
+
If AOI coordinates are lon/lat (EPSG:4326), `polygon_area` from Shapely returns degree-squared values, not square meters.
|
|
54
|
+
|
|
55
|
+
For metric thresholds, either:
|
|
56
|
+
- reproject geometry before computing area
|
|
57
|
+
- or compute geodesic area with a dedicated geodesic approach
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# How-to: Author CQL2 Rules in JSON Encoding
|
|
2
|
+
|
|
3
|
+
You can provide `cql2` as JSON, not only text.
|
|
4
|
+
|
|
5
|
+
## 1. Define the input
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
inputs:
|
|
9
|
+
mode:
|
|
10
|
+
type: string
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 2. Add CQL2 JSON rule
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
hints:
|
|
17
|
+
- class: eoap:Cql2FilterHint
|
|
18
|
+
queries:
|
|
19
|
+
- id: mode-is-strict
|
|
20
|
+
cql2:
|
|
21
|
+
op: "="
|
|
22
|
+
args:
|
|
23
|
+
- property: mode
|
|
24
|
+
- "strict"
|
|
25
|
+
message: "mode must be strict"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 3. Validate with sample values
|
|
29
|
+
|
|
30
|
+
Valid:
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
mode: "strict"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Run:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
assertions-mate workflow.cwl --inputs inputs-valid.yaml
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Ready-to-run example in this repository
|
|
43
|
+
|
|
44
|
+
- `examples/cql2-json-validation/workflow.cwl`
|
|
45
|
+
- `examples/cql2-json-validation/inputs-valid.yaml`
|
|
46
|
+
- `examples/cql2-json-validation/inputs-invalid.yaml`
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# How-to: Combine Multiple Hints in One Workflow
|
|
2
|
+
|
|
3
|
+
Use `JSONSchemaHint`, `RegoPolicyHint`, and `Cql2FilterHint` together to enforce structure, policy, and spatial predicates.
|
|
4
|
+
|
|
5
|
+
## 1. Define the inputs
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
inputs:
|
|
9
|
+
count:
|
|
10
|
+
type: int
|
|
11
|
+
aoi:
|
|
12
|
+
type: https://raw.githubusercontent.com/eoap/schemas/main/geojson.yaml#Polygon
|
|
13
|
+
candidate:
|
|
14
|
+
type: https://raw.githubusercontent.com/eoap/schemas/main/geojson.yaml#Polygon
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 2. Add multiple hints
|
|
18
|
+
|
|
19
|
+
```yaml
|
|
20
|
+
hints:
|
|
21
|
+
- class: eoap:JSONSchemaHint
|
|
22
|
+
json_schema:
|
|
23
|
+
type: object
|
|
24
|
+
required: [count, aoi, candidate]
|
|
25
|
+
properties:
|
|
26
|
+
count:
|
|
27
|
+
type: integer
|
|
28
|
+
minimum: 1
|
|
29
|
+
- class: eoap:RegoPolicyHint
|
|
30
|
+
module: |
|
|
31
|
+
package workflow
|
|
32
|
+
deny[msg] {
|
|
33
|
+
input["count"] > 10
|
|
34
|
+
msg := "count must be <= 10"
|
|
35
|
+
}
|
|
36
|
+
queries:
|
|
37
|
+
- data.workflow.deny[_]
|
|
38
|
+
- class: eoap:Cql2FilterHint
|
|
39
|
+
queries:
|
|
40
|
+
- id: spatial-check
|
|
41
|
+
cql2: "s_intersects(ensure_spatial(candidate), ensure_spatial(aoi))"
|
|
42
|
+
message: "candidate must intersect aoi"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 3. Validate with sample values
|
|
46
|
+
|
|
47
|
+
Run:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
assertions-mate workflow.cwl --inputs inputs-valid.yaml
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Ready-to-run example in this repository
|
|
54
|
+
|
|
55
|
+
- `examples/multi-hint-validation/workflow.cwl`
|
|
56
|
+
- `examples/multi-hint-validation/inputs-valid.yaml`
|
|
57
|
+
- `examples/multi-hint-validation/inputs-invalid.yaml`
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# How-to: Create Reusable Rego Snippets
|
|
2
|
+
|
|
3
|
+
Keep common checks reusable by copying a shared module block between workflows.
|
|
4
|
+
|
|
5
|
+
## 1. Define the inputs
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
inputs:
|
|
9
|
+
start-date:
|
|
10
|
+
type: string
|
|
11
|
+
end-date:
|
|
12
|
+
type: string
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 2. Add reusable Rego helper
|
|
16
|
+
|
|
17
|
+
```rego
|
|
18
|
+
package workflow
|
|
19
|
+
|
|
20
|
+
is_rfc3339_utc(s) {
|
|
21
|
+
regex.match("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$", s)
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Then reuse in multiple deny rules.
|
|
26
|
+
|
|
27
|
+
## 3. Add hint using the helper
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
hints:
|
|
31
|
+
- class: eoap:RegoPolicyHint
|
|
32
|
+
module: |
|
|
33
|
+
package workflow
|
|
34
|
+
|
|
35
|
+
is_rfc3339_utc(s) {
|
|
36
|
+
regex.match("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$", s)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
deny[msg] {
|
|
40
|
+
s := input["start-date"]
|
|
41
|
+
not is_rfc3339_utc(s)
|
|
42
|
+
msg := "start-date format is invalid"
|
|
43
|
+
}
|
|
44
|
+
queries:
|
|
45
|
+
- data.workflow.deny[_]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Ready-to-run example in this repository
|
|
49
|
+
|
|
50
|
+
- `examples/reusable-rego-snippets/workflow.cwl`
|
|
51
|
+
- `examples/reusable-rego-snippets/inputs-valid.yaml`
|
|
52
|
+
- `examples/reusable-rego-snippets/inputs-invalid.yaml`
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# How-to: Test Hints With pytest
|
|
2
|
+
|
|
3
|
+
Use direct validator classes in unit tests for quick feedback.
|
|
4
|
+
|
|
5
|
+
## 1. Create a validator test
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from assertions_mate import Cql2Query
|
|
9
|
+
from assertions_mate.cql2_validator import Cql2Validator
|
|
10
|
+
|
|
11
|
+
def test_rule_fails_when_count_not_positive():
|
|
12
|
+
validator = Cql2Validator(
|
|
13
|
+
queries=[Cql2Query(id="q", cql2="count > 0", message="count must be positive")]
|
|
14
|
+
)
|
|
15
|
+
result = validator.validate_inputs({"count": 0})
|
|
16
|
+
assert result is not None
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 2. Run the test
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
hatch run test:test-q examples/pytest-validation/test_validators_example.py
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Ready-to-run example in this repository
|
|
26
|
+
|
|
27
|
+
- `examples/pytest-validation/test_validators_example.py`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# How-to: Troubleshoot CWL Loader Errors
|
|
2
|
+
|
|
3
|
+
When validation fails before hints execute, the CWL document may be rejected by `cwl_utils`.
|
|
4
|
+
|
|
5
|
+
## Common symptom
|
|
6
|
+
|
|
7
|
+
- `schema_salad.exceptions.ValidationException`
|
|
8
|
+
- messages around invalid `requirements` field shape
|
|
9
|
+
|
|
10
|
+
## Checklist
|
|
11
|
+
|
|
12
|
+
1. Start with a minimal single-workflow document (`class: Workflow`, `cwlVersion: v1.2`).
|
|
13
|
+
2. Add one input at a time and re-run.
|
|
14
|
+
3. If failures appear after adding `requirements`, temporarily remove that section to isolate parser compatibility.
|
|
15
|
+
4. Keep examples runnable first; reintroduce advanced schema refs after parser behavior is confirmed.
|
|
16
|
+
|
|
17
|
+
## Tip
|
|
18
|
+
|
|
19
|
+
Different environments can parse the same CWL differently depending on exact `cwl_utils` and schema-salad versions.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# How-to: Troubleshoot Rego "Invalid literal" Errors
|
|
2
|
+
|
|
3
|
+
If you see errors around `deny contains ... if { ... }`, your runtime is parsing classic Rego syntax.
|
|
4
|
+
|
|
5
|
+
## Symptoms
|
|
6
|
+
|
|
7
|
+
- `Invalid literal`
|
|
8
|
+
- `wellformed_error`
|
|
9
|
+
- validator setup fails for `RegoPolicyHint`
|
|
10
|
+
|
|
11
|
+
## Fix
|
|
12
|
+
|
|
13
|
+
Use classic syntax:
|
|
14
|
+
|
|
15
|
+
```rego
|
|
16
|
+
deny[msg] {
|
|
17
|
+
input["x"] == null
|
|
18
|
+
msg := "x is required"
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
instead of:
|
|
23
|
+
|
|
24
|
+
```rego
|
|
25
|
+
deny contains "x is required" if {
|
|
26
|
+
input["x"] == null
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Verify
|
|
31
|
+
|
|
32
|
+
Run your workflow and ensure `Setting up validator for RegoPolicyHint...` completes without parser errors.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# How-to: Use Packed CWL vs Single Workflow CWL
|
|
2
|
+
|
|
3
|
+
## Single workflow
|
|
4
|
+
|
|
5
|
+
Best for local examples and fast validation loops.
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
cwlVersion: v1.2
|
|
9
|
+
class: Workflow
|
|
10
|
+
id: my-workflow
|
|
11
|
+
...
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Packed workflow (`$graph`)
|
|
15
|
+
|
|
16
|
+
Useful when distributing multiple process definitions in one file.
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
cwlVersion: v1.2
|
|
20
|
+
$graph:
|
|
21
|
+
- class: Workflow
|
|
22
|
+
id: my-workflow
|
|
23
|
+
...
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Recommendation
|
|
27
|
+
|
|
28
|
+
Start with single-workflow CWL for validator docs/examples, then move to packed CWL once parser compatibility is confirmed in your target runtime.
|