Portable Agent Development Environments
PADE describes what a development session requires, not which vendor or infrastructure must satisfy those requirements.
A repository declares portable capability intent. A conforming implementation decides how to satisfy that intent using existing runtimes, credential systems, network infrastructure, ingress systems, and so on.
PADE uses Kubernetes-style declarative API conventions because they provide a familiar vocabulary for API versioning, resource kinds, metadata, and desired intent under spec. PADE does not require Kubernetes, and DevelopmentSession is not currently a Kubernetes CRD. See docs/manifest-conventions.md.
DevelopmentSession.spec
↓
declares portable intent
↓
conforming implementation
↓
DevPod / Coder / local / cloud runtime
+
env / Vault / 1Password / Keeper / enterprise broker
+
future ingress/network providers
The checked-in manifest must not encode those provider choices.
PADE is an exploratory interoperability contract for portable development capability intent: declare what a project may need, consume that intent safely, and broker authorized capabilities through existing authority systems.
It currently defines three draft specification surfaces:
| Spec | Core question | Document |
|---|---|---|
| Intent | What capabilities does this project declare it may need? | spec/intent.md |
| Consumer | How does a development workload interpret that intent and request/use authority? | spec/consumer.md |
| Broker | How does an authority boundary authenticate the workload, authorize the request, and materialize an approved capability? | spec/broker.md |
Specification entry point: spec/README.md.
pade.yaml (DevelopmentSession)
|
| portable intent
v
Consumer
|
| authenticated capability request
v
Broker
|
| authorization + materialization
v
Keeper / Vault / cloud IAM / preview provider /
enterprise platform / other service
These specs are draft / exploratory (pade.local/v1alpha1)—not an industry standard. No vendor is claimed to support PADE today. The pade.local API group is an exploratory identifier (.local avoids claiming a public DNS domain).
This repository contains the Go reference Consumer (pade) and Broker (pade-broker). Third parties can implement the contract without running binaries from this repository.
| Piece | Role | Maturity |
|---|---|---|
cmd/pade |
Reference Consumer (validate, plan, capabilities, exec, identity) |
Implemented (v0.1 capability path) |
cmd/pade-broker |
Reference Broker | Experimental spike |
spec/pade.schema.json |
Machine-readable Intent schema | v1alpha1 DevelopmentSession |
Provider adapters (env, Vault, 1Password, Keeper, Keeper Secrets Manager) and the Cursor OIDC workload identity adapter are reference implementation integrations—not automatic parts of the PADE standard.
Requires Go 1.22+. macOS Homebrew go 1.13 will fail with errors like cannot load embed — that toolchain predates the embed standard library.
export PATH="$(pwd)/.tools/go/bin:$PATH"
go version # expect go1.22+
go test ./...
go run ./cmd/pade validate -f spec/examples/web-app.yaml
go run ./cmd/pade plan -f spec/examples/web-app.yaml
go run ./cmd/pade plan -f spec/examples/web-app.yaml --json
go run ./cmd/pade capabilities -f spec/examples/web-app.yaml --bindings spec/examples/bindings.example.yaml
GA_PROPERTY_ID=demo GOOGLE_APPLICATION_CREDENTIALS=/tmp/x \
go run ./cmd/pade exec -f spec/examples/web-app.yaml \
--bindings spec/examples/bindings.example.yaml \
--capability google-analytics.read -- /bin/sh -c 'test -n "$GA_PROPERTY_ID" && echo ok'Or use Make (auto-selects .tools/go when present):
make test
make validate
make plan
make ci # local mirror of GitHub Actions checksDogfood and learning milestones (not the product definition):
- Milestone 9 — Keeper Secrets Manager direct mode + Cursor Cloud composition (
KSM_CONFIGon the agent VM). - Phase 2 spike — Cursor OIDC + experimental
pade-brokersoKSM_CONFIGcan stay off the agent VM. - Milestone 8 spike — Teleport Application Access composition (not a PADE dependency).
- Environment lifecycle — DevPod (or equivalent) owns workspace create/SSH/ports/prebuilds; PADE does not reimplement that.
make dogfood # PADE smoke against examples/demo-project
make dogfood-identity # Milestone 5: Alice/Bob bindings against the same pade.yaml
make dogfood-vault # Vault -dev resolution (+ Alice/Bob KV paths; prototype only)
make dogfood-onepassword # Milestone 6: 1Password CLI adapter (fake-op shim in CI)
make install-onepassword-cli # install real `op` (Homebrew or .tools/op)
make dogfood-onepassword-live # local only: real 1Password + real GitHub API
make dogfood-keeper # Milestone 7: Keeper Commander adapter (fake-keeper shim in CI)
make install-keeper-cli # install real `keeper` (Homebrew or .tools/keeper-venv)
make dogfood-keeper-live # local only: real Keeper + real GitHub API
make dogfood-ksm # Milestone 9: Keeper Secrets Manager (PADE_KSM_FAKE=1 in CI)
make dogfood-ksm-live # local / Cursor Cloud: real KSM + real GitHub API
make dogfood-broker # Phase 2 spike: fake Cursor OIDC + pade-broker + fake KSM
make dogfood-broker-stage-b # Stage B: real Cursor OIDC + local broker (Cloud Agent only)
make smoke-broker-container # Docker image smoke: healthz + unauthenticated resolve deny
make dogfood-ingress-teleport # Milestone 8 spike: Teleport Application Access (host; Docker optional)
make dogfood-ingress-teleport-down
make dogfood-devpod # optional: full DevPod proof (needs docker + devpod)CI runs on pushes to main and on pull requests via .github/workflows/ci.yml:
- Unit tests —
gofmt,go vet,go test, build (fast feedback) - Smoke — example validate/plan/exec, identity dogfood, Vault
-devdogfood, 1Password dogfood, Keeper dogfood, KSM dogfood, broker OIDC dogfood (needs the unit job) - Container smoke —
docker buildthepade-brokerimage, start it with-tls-termination=proxy+PORT, requireGET /healthz→ 200 and unauthenticatedPOST /v1/resolve→ 401 (logs dumped on failure; image is not pushed)
Local mirrors: make ci (unit + smoke), make smoke-broker-container / make ci-container (Docker required).
Trusted upstream TLS termination (Cloud Run, ingress, or load balancer terminates HTTPS; container speaks plaintext on PORT):
docker run --rm -p 8080:8080 -e PORT=8080 \
-v "$PWD/policy.yaml:/config/policy.yaml:ro" \
-v "$PWD/bindings.yaml:/config/bindings.yaml:ro" \
pade-broker:ci \
-tls-termination=proxy \
-policy /config/policy.yaml \
-bindings /config/bindings.yamlOr with an empty -listen and PORT set (same as Cloud Run injects): the broker binds 0.0.0.0:$PORT. PORT alone does not opt into proxy mode — -tls-termination=proxy remains required for non-loopback plaintext. See SECURITY.md and docs/cursor-oidc-broker-dogfood.md.
A separate DevPod dogfood workflow boots a real DevPod workspace and runs PADE inside it (path-filtered / manual workflow_dispatch). Dependabot keeps Go modules and GitHub Actions on a weekly cadence via .github/dependabot.yml.
- A repository declares Intent (capability names), not secrets — see spec/intent.md.
- A Consumer validates/plans and resolves capabilities for scoped executions (reference:
pade exec). - Resolution may use local provider bindings or a Broker with workload identity (reference spike:
pade-broker+ Cursor OIDC). - DevPod (or an equivalent runtime) owns workspace creation and lifecycle.
- Longer-term hypotheses (authenticated review URLs, resource/lease-shaped capabilities) remain open — see spec/README.md and sequencing in ROADMAP.md.
Dev Container spec → DevPod → local/remote workspace
Intent (pade.yaml) → Consumer → [bindings | Broker] → authority systems → process-scoped use
A future Intent evolution may add runtime-produced status or further separate pure portable intent from prototype hints; that is not part of v1alpha1 input. Do not add fields anticipating it. Legacy flat version: "0.1" Intent manifests are rejected with an explicit migration error.
Earlier sections of DESIGN.md and docs/go-reference.md describe a broader orchestration CLI (pade up / Dev Container provider, services, localhost ingress). That path remains a learning artifact. Prefer composition over reimplementation.
| Path | Purpose |
|---|---|
| ROADMAP.md | Authoritative planned work (releases, external dogfood, open decisions) |
| docs/provider-contract.md | Draft external provider: exec fulfill/derive contract |
| spec/README.md | Specification entry (Intent / Consumer / Broker) |
| spec/intent.md | Intent Specification |
| spec/consumer.md | Consumer Specification |
| spec/broker.md | Broker Specification (experimental protocol) |
| spec/pade.schema.json | Intent JSON Schema (DevelopmentSession v1alpha1) |
| docs/manifest-conventions.md | apiVersion / kind / metadata / spec conventions |
| spec/examples/ | Example manifests, bindings, broker policy |
| RFC.md | Architectural history / evolving proposal |
| DESIGN.md | Reference implementation design history |
| SECURITY.md | Trust boundaries and secret-handling invariants |
| docs/README.md | Design + dogfood documentation index |
| docs/go-reference.md | Go reference Consumer/Broker design notes |
| AGENTS.md | Guidance for coding agents working in this repo |
| CONTRIBUTING.md | How to contribute |
| LICENSE | Apache License 2.0 |
| docs/devpod-dogfood.md | DevPod composition / Milestone 4 |
| docs/identity-separation.md | Milestone 5 identity-separation dogfood |
| docs/vault-dogfood.md | Vault -dev capability resolution dogfood |
| docs/onepassword-dogfood.md | 1Password provider + live dogfood |
| docs/keeper-dogfood.md | Keeper Commander provider / Milestone 7 |
| docs/keeper-secrets-manager-dogfood.md | Keeper Secrets Manager / Milestone 9 |
| docs/cursor-cloud-dogfood.md | Cursor Cloud Agent + KSM (vendor-specific) |
| docs/cursor-oidc-broker-dogfood.md | Phase 2 Cursor OIDC broker spike |
| docs/teleport-ingress.md | Teleport Application Access / Milestone 8 spike |
| examples/demo-project | DevPod-first dogfood project (+ identities/) |
| examples/ingress-demo | Teleport ingress dogfood (tiny Go HTTP app) |
| cmd/pade | Reference Consumer |
| cmd/pade-broker | Reference Broker (experimental) |
| internal/manifest | Intent load + schema/semantic validation |
| internal/binding | Local bindings + provider adapters |
| internal/broker | Broker policy, OIDC verify, resolve API |
| internal/identity | Workload token source seam (+ Cursor adapter) |
| internal/execution | Process-scoped injection + best-effort redaction |
| internal/planner | Side-effect-free plan model |
| internal/output | Human and JSON rendering |
Capabilities only — no secrets in the repo:
apiVersion: pade.local/v1alpha1
kind: DevelopmentSession
metadata:
name: demo
spec:
capabilities:
github.user.read:
access: read(Schema examples under spec/examples/ may still show other capability names such as google-analytics.read.)
Environment construction stays in .devcontainer/devcontainer.json and is started with DevPod (for example devpod up .). See spec/examples/web-app.yaml. The earlier orchestration-oriented example (spec/examples/web-app-orchestrated.yaml) has been reduced to portable capability Intent under the same v1alpha1 shape.
pade.yaml is the conventional filename for a DevelopmentSession Intent document. It declares capability names under spec.capabilities only. Bindings are local to the reference Consumer (or broker host), not portable Intent:
.pade/bindings.yaml(gitignored via.pade/)~/.config/pade/bindings.yamlPADE_BINDINGSor--bindings
See spec/examples/bindings.example.yaml. Plan/capabilities may show paths and env names, never secret values. Vault -dev and the 1Password dogfood shim are prototype-only.
| Command | Status | Role |
|---|---|---|
pade validate |
Implemented | Validate Intent (DevelopmentSession in pade.yaml) and referenced config |
pade plan |
Implemented | Side-effect-free plan including binding status |
pade capabilities |
Implemented | Show declared capabilities and binding probes |
pade exec --capability … -- <cmd> |
Implemented | Run a command with process-scoped capability injection |
pade identity --audience … |
Implemented | Inspect Cursor workload identity (safe claims; no raw JWT) |
pade-broker |
Experimental spike | OIDC-verified capability broker (Phase 2) |
Flags: -f / --file, --bindings, --json (validate/plan/capabilities), --capability / -c (exec, repeatable).
Workspace lifecycle: prefer devpod up / devpod stop directly. See examples/demo-project and docs/devpod-dogfood.md.
- Compose Dev Containers, DevPod, and existing IAM/secrets systems; standardize only the missing capability interoperability boundary.
- Separate environment, agent behavior, and runtime authority.
- Separate Intent, Consumer, and Broker specification surfaces from the Go reference code.
- Credentials must never appear in manifests, plan output,
.pade/state, or normal logs. - Downstream systems remain authoritative for authorization.
- If an existing tool already owns a concern, PADE should delegate or drop the abstraction.
Authoritative forward plan: ROADMAP.md (GitHub App + Google Analytics reference providers on the same generic seam before v0.1.0, then released artifacts, Cloudflare/preview dogfood, endpoint decision).
Completed learning milestones (not the live plan; see ROADMAP.md):
| Milestone | Focus |
|---|---|
| 0 | Repo, docs, license, schema stub, examples |
| 1 | validate / plan against schema |
| 2 | Local bindings (env, vault) + capabilities |
| 3 | Scoped pade exec --capability |
| 4 | DevPod dogfood (examples/demo-project) |
| 5 | Identity separation (same repo, distinct credentials) |
| 5b | Vault -dev validation of bindings / identity paths |
| 6 | Second credential provider (1Password CLI adapter) |
| 7 | Keeper Commander CLI binding provider (fake-keeper CI) |
| 8 | Local Teleport authenticated ingress (examples/ingress-demo) |
| 9 | Keeper Secrets Manager + Cursor Cloud dogfood (KSM_CONFIG, exec redaction) |
| 9b (spike) | Cursor OIDC token source + minimal pade-broker — experimental reference Broker |
Earlier “9+ / Later” rows in this README are superseded by ROADMAP.md Milestones A–O.
Licensed under the Apache License 2.0.