Skip to content

Reject duty-only properties on non-Duty rules - #244

Merged
jgeluk merged 1 commit into
issue/184-schedule-modelfrom
issue/239-duty-only-properties
Aug 19, 2026
Merged

jgeluk merged 1 commit into
issue/184-schedule-modelfrom
issue/239-duty-only-properties

Conversation

@jgeluk

@jgeluk jgeluk commented Aug 19, 2026

Copy link
Copy Markdown
Member

Addresses #239.

This is intentionally stacked on #234 because the acceptance criteria require the Schedule model introduced there. Once #234 is merged, this branch can be rebased onto develop and the PR base changed.

Changes

  • add regression tests for Permission and Prohibition misuse of every surviving duty-only property
  • remove OWL domains that silently inferred an additional odrl:Duty type
  • enforce Duty subject scope through fail-closed SHACL
  • retain global rejection of obsolete dprod:recurrence
  • verify generic dprod:schedule remains valid on non-Duty resources
  • document SHACL as the enforceable source of Duty-only scope

Verification

  • python -m unittest discover -s dprod-contracts/tests (48 tests)
  • python -m unittest discover -s tests (2 tests)
  • python dprod-contracts/validate.py
  • python spec-generator/main.py
  • git diff --check

@vercel

vercel Bot commented Aug 19, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dprod Ready Ready Preview Aug 19, 2026 5:11pm

@jgeluk
jgeluk merged commit f79f28c into issue/184-schedule-model Aug 19, 2026
5 checks passed
jgeluk added a commit to matthiasautrata/dprod that referenced this pull request Oct 21, 2026
[Carried forward onto develop for EKGF#275 by Matthias Autrata: conflicts
resolved against EKGF#244/EKGF#245/EKGF#262/EKGF#268/EKGF#270/EKGF#272, the namespace changed from
https://www.omg.org/spec/DPROD/dprod/ to https://ekgf.org/dprod/spec/develop/,
and EKGF#244's duty-only shape and test migrated from dprod:recurrence to
dprod:schedule, which is not duty-only.]
jgeluk added a commit to matthiasautrata/dprod that referenced this pull request Oct 21, 2026
[Carried forward onto develop for EKGF#275 by Matthias Autrata: conflicts
resolved against EKGF#244/EKGF#245/EKGF#262/EKGF#268/EKGF#270/EKGF#272, the namespace changed from
https://www.omg.org/spec/DPROD/dprod/ to https://ekgf.org/dprod/spec/develop/,
and EKGF#244's duty-only shape and test migrated from dprod:recurrence to
dprod:schedule, which is not duty-only.]
tonyseale pushed a commit to matthiasautrata/dprod that referenced this pull request Oct 29, 2026
[Carried forward onto develop for EKGF#275 by Matthias Autrata: conflicts
resolved against EKGF#244/EKGF#245/EKGF#262/EKGF#268/EKGF#270/EKGF#272, the namespace changed from
https://www.omg.org/spec/DPROD/dprod/ to https://ekgf.org/dprod/spec/develop/,
and EKGF#244's duty-only shape and test migrated from dprod:recurrence to
dprod:schedule, which is not duty-only.]
tonyseale pushed a commit to matthiasautrata/dprod that referenced this pull request Oct 29, 2026
[Carried forward onto develop for EKGF#275 by Matthias Autrata: conflicts
resolved against EKGF#244/EKGF#245/EKGF#262/EKGF#268/EKGF#270/EKGF#272, the namespace changed from
https://www.omg.org/spec/DPROD/dprod/ to https://ekgf.org/dprod/spec/develop/,
and EKGF#244's duty-only shape and test migrated from dprod:recurrence to
dprod:schedule, which is not duty-only.]
tonyseale pushed a commit that referenced this pull request Oct 29, 2026
Resolves #184. Supersedes #234. Step 7 of #275.

Carries Jacobus Geluk's reusable schedule model (#234) forward onto
`develop`. His two commits are kept with their authorship (`047dcb4`,
`81777dd`); each has a note recording what changed while carrying it
forward. Following Tony's and Jacobus's decision on #184, the anchor
rule is: **the schedule's DTSTART/TZ sets the occurrence times, and
activation only limits the range.**

## Stacking

This branch is built on #268 → #272, plus a merge of #270 (`687ea77`),
because the schedule errors use #268's error model and §3.2 combines
with #270's `asset`. Until those three merge, this PR also shows their
commits. The schedule work is the last four commits:

- `047dcb4` Implement reusable schedule model (Jacobus)
- `81777dd` Address review findings on the schedule model (Jacobus)
- `7c67d39` Migrate the spec and examples from `dprod:recurrence` to
`dprod:schedule`
- `257e65c` Bump the contracts modification dates

**Merge after #270, #268 and #272.** Then squash-merge directly (the
shared changes are identical) or first rebase the four commits onto
`develop`.

## Changes compared with #234

- **No frozen-archive changes, and no duplicate of #244.** #244's
duty-only shape and test now cover `dprod:deadline`,
`dprod:subjectOfDuty` and `dprod:objectOfDuty`. `dprod:schedule` is not
duty-only. The obsolete `dprod:recurrence` is rejected by
`RejectObsoleteRecurrenceShape` on every rule type, and there are tests
for both.
- **Develop namespace.** `https://www.omg.org/spec/DPROD/dprod/` is
replaced throughout, including the TZID-conflict SPARQL. The namespace
move stays at step 10 of #275.
- **Schedule errors fit #267's fail-closed model.** There is no `errors`
field on the Result. A schedule that can't be processed adds its error
to a new set E₅ (`occurrences(d, Σ) = Error(e)`, computed in Step 3),
and Step 7 returns `Failure(E₃ ∪ E₄ ∪ E₅)`. D-FREEZE: a duty whose
schedule is in error makes no transition, so only the Permit path is
affected; Deny and NotApplicable are not. `EvaluationError =
Set<ResolutionError | ScheduleError>`, and the §9.7 completion argument
also replaces each schedule error with some set of occurrence times.
- **The workflow change is dropped.** #262 already runs `validate.py` in
CI.
- **`ScheduleIdentifierShape` is renamed
`RejectAnonymousScheduleShape`.** The spec generator renders every
NodeShape that has a `sh:targetClass` as a class except `Reject*`
shapes, so the old name appeared as a spurious "ScheduleIdentifier"
class.
- **The core spec and examples move to `dprod:schedule`.** The
data-offer-and-contract, lifecycle-and-versioning, provider-duties and
odcs-mapping examples, plus the `respec/template.html` contract example,
now use identified `Schedule` nodes with an explicit `DTSTART;TZID=…`
and an RRULE. The overview diagram is regenerated, and
`tests/test_spec_contract_sections.py` expects `Schedule` and
`ScheduleFormat` classes.
- **The modification dates are bumped** in the contracts docs and in
`dct:modified` on the profile, shapes and vocabulary.

All 9 review findings on #234 were checked and are addressed. They are:
crontab whitespace, the RFC 5545 regex (EXDATE/RDATE order, duplicate
FREQ), the TZ conflict and `carriesTimeZone`, how ScheduleError is
consumed and totality, the `expand` signature, bare-config tests,
undefined guide examples, the identifier message on its own shape, the
RRULE table, and the recurrence sweep of specification.md.

## Tests

- This branch: core 26 OK, contracts 98 OK, `validate.py` clean.
- Integrated with #264, #266, #270, #268 and #272: core 26 OK, contracts
102 OK, `validate.py` clean.

Every JSON-LD example that uses a schedule conforms to the contracts
shapes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Jacobus Geluk <jacobus.geluk@ekgf.org>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — 07eb5ff3 Deployed Aug 19, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant