Skip to content

operator-proposal schema accepts approval.via on a policy approval, and the loader drops it #46

Closed

Description

@shipmill-romamo

What happens

With #42, config/schemas/v1/operator-proposal.schema.json gives an approval an optional via (terminal or unknown). Only a person's approval should carry it, and the Python model rejects a policy approval that has one. The schema doesn't say that: it accepts via on an autonomous (OperatorPolicy) approval, and when such a receipt is loaded, the field is silently dropped.

So a receipt that passes schema validation can lose data on load, and the schema and the loader disagree about what a valid receipt is.

Expected

The schema refuses via on a policy approval (for example an if/then on the approval's kind), or the loader refuses the receipt instead of dropping the field. Either way, the schema and the loader agree.

Found in the review of #42 (Part of #35).

Activity

  1. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Triage: implement.

    Confirmed on main (20b33c7):

    • config/schemas/v1/operator-proposal.schema.json gives approval.via an enum and nothing ties it to mode, so {"mode": "autonomous", "via": "terminal"} passes validation
    • The proposal loader (sdk/src/cloudfall/operator.py, around line 598) reads via only when mode == "human", so on an autonomous approval the field is silently dropped. ApprovalRecord itself refuses that combination, so the schema is looser than the model
    • No code writes via on an autonomous approval. Only a hand-edited receipt can hold one

    Design. This tightens a published v1 schema. That is a contract change, but a narrow one: it refuses only a shape that the model already calls invalid and that no code writes. Nothing in a decisions log is departed from (there is none yet).

    • In the approval object, an if mode is autonomous, then via is not allowed. A receipt with that shape then fails schema validation when it loads, like any other invalid receipt, instead of losing the field
    • A test that a receipt with an autonomous approval and a via is refused, and that human receipts with and without via (older ones) still load
    • CHANGELOG under Fixed
    • Compatibility: a receipt someone edited by hand into that shape stops loading. Code never wrote one
  2. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Released in v0.6.0rc7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions