Skip to content

feat: explicit per-callback secrets mapping #29

Description

@joshua-temple

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

  • workflow.go parses workflow_call.secrets blocks and surfaces them alongside existing inputs metadata.
  • Manifest schema accepts secrets: map on build/deploy/validate callbacks; absent means inherit.
  • Generator emits explicit secrets: map on jobs.<id>.uses when the callback entry provides one.
  • Validation reports an error when a callback's required secret is not present in the manifest's secrets: map for that callback.
  • secrets: inherit is still emitted when no explicit map is provided (backward-compatible default).
  • e2e scenario: a manifest with two callbacks — one with an explicit secrets: map and one without — generates a workflow where the first job has explicit secret mappings and the second has secrets: inherit; cascade validate passes when all required secrets are covered and fails with a clear message when one is missing.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions