Problem
Every callback job that cascade generates receives secrets: inherit, propagating all workflow secrets to every called workflow unconditionally (generator.go:491,641). The callback workflow's own workflow_call.secrets declaration is never parsed (workflow.go has zero matches for secrets parsing).
This violates least-privilege: a docs-build callback ends up with access to production deploy credentials. It also makes it impossible for cascade to validate that a callback's required secrets are actually satisfied — the same class of problem the existing required-inputs validation solves for with: inputs.
What to add
Parse workflow_call.secrets in workflow.go (mirroring the existing inputs parsing) so cascade knows which secrets each callback declares and whether they are required.
Add an optional secrets: field to each build/deploy/validate callback in the manifest schema that maps caller-side secret names to callback-declared names.
Schema sketch:
callbacks:
- name: deploy-prod
workflow: ./.github/workflows/deploy.yaml
secrets:
DEPLOY_TOKEN: DEPLOY_TOKEN # explicit mapping: caller-name -> callback-name
DB_PASS: DB_PASS
# omit `secrets:` entirely to keep the current `secrets: inherit` behaviour
When secrets: is present on a callback, the generator emits the explicit map instead of inherit. When absent, inherit is preserved as the default so existing manifests are unaffected.
Validation should warn (or error, configurable) when a callback declares a required: true secret that is not covered by the manifest's secrets: map for that callback.
Acceptance criteria
Problem
Every callback job that cascade generates receives
secrets: inherit, propagating all workflow secrets to every called workflow unconditionally (generator.go:491,641). The callback workflow's ownworkflow_call.secretsdeclaration is never parsed (workflow.gohas zero matches for secrets parsing).This violates least-privilege: a docs-build callback ends up with access to production deploy credentials. It also makes it impossible for cascade to validate that a callback's required secrets are actually satisfied — the same class of problem the existing required-inputs validation solves for
with:inputs.What to add
Parse
workflow_call.secretsinworkflow.go(mirroring the existinginputsparsing) so cascade knows which secrets each callback declares and whether they are required.Add an optional
secrets:field to each build/deploy/validate callback in the manifest schema that maps caller-side secret names to callback-declared names.Schema sketch:
When
secrets:is present on a callback, the generator emits the explicit map instead ofinherit. When absent,inheritis preserved as the default so existing manifests are unaffected.Validation should warn (or error, configurable) when a callback declares a
required: truesecret that is not covered by the manifest'ssecrets:map for that callback.Acceptance criteria
workflow.goparsesworkflow_call.secretsblocks and surfaces them alongside existing inputs metadata.secrets:map on build/deploy/validate callbacks; absent meansinherit.secrets:map onjobs.<id>.useswhen the callback entry provides one.secrets:map for that callback.secrets: inheritis still emitted when no explicit map is provided (backward-compatible default).secrets:map and one without — generates a workflow where the first job has explicit secret mappings and the second hassecrets: inherit;cascade validatepasses when all required secrets are covered and fails with a clear message when one is missing.