Design: one policy language for signal authorization and beyond. CEL coherence instead of bespoke YAML keys like distinct_from_starter
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 9
- Forks
- 0
- Avg merge
- 3h 3m
- Merged PRs (30d)
- 509
Description
Owner review feedback on the signal authorization surface, recorded as the design question it is.
The smell
signals:
deploy-approved:
allow:
- subject: ${"https://issuer.example.com#" + inputs.expected_approver}
claims:
team: release-managers
distinct_from_starter: true
distinct_from_starter: true is a one-off boolean for one specific predicate. allow: is a bespoke match-list grammar with its own semantics for subject, claims, and list-membership. Each new authorization need (approver quorums, time windows, delegation, "not the author of the change under review") would grow another key. That is DSL bloat: the YAML substrate is accreting a policy vocabulary that CEL already expresses, and the project's own invariant says one expression language for data flow and policy is the central cohesion win. The egress, secret-access, and task-shape surfaces already reason in CEL over an identity object; signal authorization is the odd one out with a bespoke shape.
The direction to explore
A signal gate as a CEL predicate over a scope built for it:
signals:
deploy-approved:
when: ${sender.subject == "https://issuer.example.com#" + inputs.expected_approver
&& "release-managers" in sender.claims.team
&& sender.subject != run.starter.subject}
One key. The vocabulary is the scope (sender, run.starter, inputs, and whatever else the gate legitimately sees), not the grammar. distinct_from_starter becomes one clause anyone can read, vary, or combine, and quorum-style or delegation policies become expressible without schema changes.
What has to be gotten right (the nuance the feedback names)
- Administrator vs author vs team. A workflow author writes the file's gate; the operator of the deployment must be able to impose policy the file cannot weaken (the fail-closed house rule). That suggests two layers with one language: a deployment-level CEL policy surface (like egress and secret-access today) that ANDs with the file's
when:, never OR. Which layer owns which vocabulary needs deciding, and the same split likely generalizes to other surfaces. - Composability and reuse. Policy fragments teams share and apply across workflows and across DSL surfaces (signals, egress declarations if those land, task-shape) rather than restating clauses per file. Whether that is named CEL bindings, a policy file the deployment loads, or module-level reuse once modules exist, is part of this design.
- Fail-closed defaults preserved. The current shape's virtues must survive: attested senders only, deny on error, deny when no rule matches, compile-and-type-check at load. A
when:that errors denies. - Plugins. A plugin-provided task or a plugin-mediated signal source should participate in the same scope contract, optionally, without inventing a parallel mechanism.
- Migration.
allow:/claims:/distinct_from_starter:exist in shipped examples; the retirement path is an edition sweep withflow fixrewriting, the mechanism the language already has for exactly this.
Scope note
This pattern audit should walk the whole DSL for other bespoke-key policy shapes that CEL should subsume, so the language shrinks coherently rather than key by key. Related records: #206 (where the current shape landed), #177 (typed inputs feed the scope), #157 (language slate).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the current signal authorization shape described in #206, then compare the scope and policy behavior with the related language records #177 and #157. Audit the signal, egress, secret-access, and task-shape surfaces for bespoke policy keys. Done means a settled CEL-based design covering vocabulary, policy layers, reuse, fail-closed behavior, plugins, and migration.
Written by the indexing model from the issue text.
Assessment
- Domain
- authorization, compilers, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100