ADR 0008: Reusable workflows for credential isolation (undecided) - #107
ADR 0008: Reusable workflows for credential isolation (undecided)#107ralphbean wants to merge 5 commits into
Conversation
Establishes that control flows strictly downward through the execution stack (Dispatch → Infrastructure → Sandbox → Harness → Runtime) and no layer may influence layers above it. Distinguishes prohibited upward control flow from permitted upward data flow (telemetry, failure signals). Renames "Work Coordinator" to "Agent Dispatch and Coordination Layer" for clarity. Adds an "Execution Stack" section to architecture.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deterministic code paths (agent runtime wrapper and skill scripts) use a shared library (forgekit) for forge-portable operations. Agents themselves use native forge CLIs — LLMs adapt naturally to the forge they're working with. Updates architecture.md: adds Forge Abstraction Layer section, updates Identity Provider for forgekit credential issuance, generalizes dispatch layer to use forge-neutral language. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GitHub Actions is the first execution platform, serving as both trigger and infrastructure. A platform-agnostic entry point ensures nothing below the infrastructure layer knows it's running on GH Actions. Kubernetes is the anticipated second platform. Updates architecture.md: resolves the initial platform question in Agent Infrastructure, adds GH Actions trigger note to Agent Dispatch and Coordination Layer. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Proposes using GitHub reusable workflows so secrets (GitHub App private key) live only in the .fullsend repo, structurally inaccessible to enrolled repos. Marked undecided pending an experiment to verify that workflow_call actually provides this isolation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
||
| Undecided — the core premise (that GitHub reusable workflows prevent the | ||
| calling repo from accessing the called workflow's secrets) needs experimental | ||
| validation before this can be accepted. |
There was a problem hiding this comment.
Perhaps we can focus on leveraging workflow authorization instead of protecting long-lived secrets. The per-workflow token that GitHub issues in GITHUB_TOKEN for example, contains the REF of the reusable workflow in its job_workflow_ref field.
We can use AgentGateway to inspect the token on the road to the LLM in order to avoid having to make IT setup the trust for us in IAM or the GCP/Vertex equivalent.
|
IMO the only valid solution is to use oidc federation. It's the santdard nowadays and very easy to configure. https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-google-cloud-platform |
Defining this needs a bunch of permissions on the Google Cloud side that IT does not seem to grant us:
We wither need to start negotiating with IT to get those, or consider Agent Gateway |
|
I think the OIDC federation vs long-lived secrets decision is orthogonal — or at least layered on top of this one. The core thing I want to decide here is that we isolate the right to act as the agent in a "namespace" where the owners of the individual repos don't have the ability to execute arbitrary code or arbitrary workflows. Whether it's an OIDC JWT or a long-lived secret, the owners of individual repositories in the org can't access them directly. At best, they'd have to get the agent to exfiltrate them — but let's take that up in a separate decision around sandboxing the agent runtime. I've updated the ADR to sharpen this framing: Option 3 (OIDC/external secrets) is now presented as complementary to the execution isolation decision, not as a peer alternative. It also notes that |
OIDC federation vs stored secrets is orthogonal — the core decision is isolating the agent's execution namespace from enrolled repo owners. Credential provisioning is now a separate discussion section rather than a competing option. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
||
| ### Experiment needed | ||
|
|
||
| Create a test GitHub App with minimal permissions. Set up: |
There was a problem hiding this comment.
Maybe I missed something, why do we need a github app? The GITHUB_TOKEN provided by default to workshops doesn't have enough permissions?
gbenhaim
left a comment
There was a problem hiding this comment.
I'm not sure about the central repo approach. It means that credentials are going to be shared by different users and it's difficult to see the benefits of it without more examples on which secrets are going to be stored.
Does it mean there is a single agent in fullsend everyone should use? "namespace" where the owners of the individual repos don't have the ability to execute arbitrary code or arbitrary workflows. Whether it's an OIDC JWT or a long-lived secret, the owners of individual repositories in the org can't access them directly. At best, they'd have to get the agent to exfiltrate them — but let's take that up in a separate decision around sandboxing the agent runtime.
|
|
Question on the The shim workflow in enrolled repos passes the App private key to the reusable workflow: jobs:
agent:
uses: {org}/.fullsend/.github/workflows/agent.yaml@main
secrets:
APP_PRIVATE_KEY: ${{ secrets.FULLSEND_APP_PRIVATE_KEY }}For this to work, the enrolled repo must have access to
From the PR #119 experiment (nonflux/integration-service), the full workflow approach (complete agent workflows in the target repo, referencing org secrets directly) has the same credential exposure but avoids the cross-repo dependency. The tradeoff is update burden at scale vs. a single point of failure in The only architecture that truly isolates the private key from enrolled repos would be a relay pattern — a lightweight service (Cloud Run, Lambda) that receives webhooks, holds the private key, mints a scoped installation token, and passes just the token to the enrolled repo's workflow via Is the credential isolation in this ADR's title referring to a different isolation boundary than key isolation from enrolled repos? |
|
Yeah, agreed - |
|
Dropping this. See #167 |
Summary
Dependencies
🤖 Generated with Claude Code