Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions deploy/helm/a2a-shared/GO-LIVE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# A2A `a2a-shared` — production go-live checklist (FuzeAgent-first)

Prod is **GitOps** (Contabo k3s, Argo CD `a2a-shared` Application, `values-prod.yaml`). Nothing is
hand-deployed. This overlay is staged to `enabled: true` in the rollout PR, but Argo renders it only
once the PR **merges to `main`** — and it will not run correctly until the items below exist.

**None of these can be done by an automated agent** — they are real credentials/config that only the
owner (or the sealed-secrets flow) can provide. The rollout PR fills all config values (§1) and leaves
`secretRef` names; you seal the secrets (§2) and confirm the token (§1b step 6).

> **⛔ DO NOT MERGE #93 until (a) the 4 SealedSecrets in §2 exist in the `fuzeagent` namespace AND
> (b) a real minted token has been decoded to confirm the exact `iss` / `aud` / `repo` claim strings
> and the `fuzefront` app slug.** Until then #93 is not on `main`, so Argo renders nothing.

## 1. Owner-supplied config (edit `values-prod.yaml`)

| Field | What to set |
|---|---|
| `a2a.auth.oidcIssuerUrl` | **Set** to FuzeFront's prod Authentik issuer `https://app.fuzefront.com/application/o/fuzefront/` (from FuzeFront `deploy/helm/fuzefront/values-prod.yaml`). The `iss` anchor. Already filled in `values-prod.yaml`. |
| `a2a.auth.oidcDiscoveryUrl` | **Set** to the in-cluster discovery URL `http://authentik-server.fuzefront.svc.cluster.local:9000/application/o/fuzefront/.well-known/openid-configuration`. The server fetches JWKS/discovery from HERE while still validating `iss` against `oidcIssuerUrl`. Added to the frozen interface in **contract v1.1.0** (FuzeAgent#96, optional + additive). Already filled. |
| `a2a.auth.audience` | `a2a` (dedicated M2M audience). Already filled. |
| `a2a.auth.callerClaim` | `repo` (custom claim carrying the exact repo name — the allowlist key). Already filled. |
| `a2a.tenants[0].entryRole` | **Set** to `agent-orchestrator` (the serving role added in #94). Already filled. |

### 1b. Machine-identity integration with FuzeFront — RESOLVED (FuzeFront#364)

FuzeFront (identity owner) decided **Option 2: issue repo-name JWTs**, not introspection. Rationale:
it fits the frozen A2A contract (standard stateless JWT validation, no `authz.md §2` amendment),
avoids handing every A2A pod its own introspection credential + a round-trip per call, and removes
the `client_id → repo` lookup that introspection would still require (`sub` is
`hashed_user_id`; the only stable key today is the opaque `client_id`).

**Mechanism:** an Authentik **scope mapping** on each A2A machine provider emits a stable claim,
`{"repo": "<RepoName>", "aud": "a2a"}`. Authentik OAuth2 access tokens are JWTs signed by the
provider and published at the issuer's JWKS, so standard validation works.

**Resolved A2A `auth` values (now in `values-prod.yaml`):**
- `callerClaim: repo` — the custom claim carrying the exact repo name (the allowlist key).
- `audience: a2a` — one dedicated M2M audience across all A2A providers (NOT the human `fuzefront` app).
- `oidcIssuerUrl` (the `iss` anchor) stays the public `https://app.fuzefront.com/application/o/fuzefront/`
(`issuer_mode: global`), **but JWKS/discovery is fetched in-cluster** to avoid a Cloudflare-tunnel
hairpin (FuzeFront hit 17–34 s hairpin timeouts before), via **`oidcDiscoveryUrl`**:
`http://authentik-server.fuzefront.svc.cluster.local:9000/application/o/fuzefront/.well-known/openid-configuration`.
- The `oidcDiscoveryUrl` override is now a **first-class field in the frozen interface as of
contract v1.1.0** (FuzeAgent#96 — optional + purely additive; the server validates `iss` against
`oidcIssuerUrl` while fetching keys from `oidcDiscoveryUrl`). It is set in `values-prod.yaml`.
App slug is **`fuzefront`** (confirm against a real minted token before go-live).

**Critical-path work items (in order — #93 stays DO-NOT-MERGE until all done):**
1. **Contract v1.1.0 (contract-designer) — DONE:** `auth.oidcDiscoveryUrl` added to the frozen
values-interface (FuzeAgent#96, merged to `main`). #93 is rebased onto it, so helm-validate sees
a schema that accepts `oidcDiscoveryUrl`.
2. **Server `oidcDiscoveryUrl` support (backend-engineer, parallel):** the A2A server must honour the
`oidcDiscoveryUrl` override — fetch discovery/JWKS from it while validating `iss` against
`oidcIssuerUrl`. Tracked separately; NOT part of this devops PR.
3. **FuzeFront PR (backend-engineer):** extend M2M provisioning to attach the `a2a` scope mapping
emitting `{"repo": <name>, "aud": "a2a"}` on A2A machine providers — mirror the existing
`provisionM2MClients()` / `ensureScopeMapping()` (`backend/src/authentik/provision-m2m-clients.ts`,
already does this shape for `fuzefront:apps`). Without it, a registered `FuzeAgent` gets tokens
that FAIL A2A validation.
4. **In-cluster registration** of `FuzeAgent` (operator / one-shot Job in the fuzefront ns, where
`AUTHENTIK_ADMIN_TOKEN` + `AUTHENTIK_BASE_URL=http://authentik-server:9000` already live) →
returns `client_id`; seal the returned `client_secret` on the FuzeAgent side. Repeat per tenant.
5. **NetworkPolicy — FuzeFront chart (FuzeFront#373) — ALREADY ENABLED:** the cross-namespace
`fuzeagent → authentik-server:9000` JWKS path is admitted by FuzeFront's own chart
(`networkPolicy.enabled: true` in `fuzefront` prod values, `fuzeagentNamespace: fuzeagent`).
It lives in FuzeFront's chart (not FuzeInfra) because a NetworkPolicy's `podSelector` only matches
its own namespace and the `fuzeinfra` AppProject can't target `fuzefront`. The rule is authored
ALONGSIDE Authentik's existing ingress allowances so it does NOT flip `authentik-server` to
deny-all (which would break Traefik→Authentik login). **Operator: nothing to do here — verify only.**
6. **FuzeAgent #93 finalize (this devops PR):** `oidcDiscoveryUrl` is set in `values-prod.yaml`; the
hardened secret set is referenced. Before merge, **decode one real minted token** to confirm the
exact `iss`/`aud`/`repo` strings and the `fuzefront` app slug, then seal the §2 secrets and merge
with a CLEAN squash message (§4). This PR does NOT create the secrets or decode the token — those
are operator steps.

## 2. SealedSecrets that must exist in namespace `fuzeagent` before Argo sync

This is the **hardened (Option B) bring-up** — mTLS + card-signing stay ON. Seal each with `kubeseal`
against the **prod cluster's** sealed-secrets controller cert. Names/keys must match `values-prod.yaml`
exactly. **Exactly these 4 SealedSecrets are required for the FuzeAgent-first rollout:**

| SealedSecret `name` | key | Purpose | Required? |
|---|---|---|---|
| `a2a-provider-anthropic` | `api-key` | Anthropic API key the server's provider uses (also exported as `ANTHROPIC_API_KEY` for session provisioning) | **Yes** |
| `ghcr-pull` | `.dockerconfigjson` | Pull the private `fuzeagent-a2a` image from GHCR (`kubernetes.io/dockerconfigjson` type) | **Yes** |
| `a2a-mtls-ca` | `ca.crt` | In-cluster mTLS CA (defence-in-depth) — `a2a.auth.mtls.enabled: true` | **Yes (Option B)** |
| `a2a-card-signing` | `jws.key` | JWS key to sign Agent Cards — `a2a.cardSigning` kept | **Yes (Option B)** |

> **`a2a-repos-git` is NOT needed for this bring-up.** The only tenant (`izzywdev/FuzeAgent`) is a
> PUBLIC repo, so the repo-sync init container clones anonymously and `deploy.reposGitTokenSecretRef`
> is `null`. Seal an `a2a-repos-git` (`token`) and repoint that ref ONLY when a PRIVATE tenant repo is
> onboarded.
>
> Lighter (non-hardened) alternative: set `a2a.auth.mtls.enabled: false` and comment out the
> `a2a.cardSigning` block to drop `a2a-mtls-ca` + `a2a-card-signing` (down to 2 secrets). Option B
> keeps them for defence-in-depth.

## 3. `providesTo` backfill (authz — fail-closed)

FuzeAgent's `.fuze/manifest.json` has **no `providesTo`**, so with A2A enabled it will accept **no
callers** — safe, and fine for the first bring-up (nothing else is enabled to call it yet). Before a
consumer (FuzePlan, a product) is allowed to call FuzeAgent, add FuzeAgent's `providesTo` from the
approved graph (**FuzeSDLC#54**) in the same PR that enables that consumer. Do the same for each
tenant as it is added.

## 4. The image (auto-built on merge — one caveat)

`release.yml` builds/pushes `ghcr.io/izzywdev/fuzeagent-a2a` and rewrites the `tag:` in this file on
push to `main` under `deploy/helm/a2a-shared/**`. It has **not** run for the A2A merges because the
squash-merge commit bodies inherited a `[skip ci]` line from the governance-sync reconcile commits.

➡️ **Merge this rollout PR with a CLEAN squash message (no `[skip ci]`)** so `release.yml` fires,
builds the image, and bumps `a2a.image.tag`. Verify afterward: `gh api
user/packages/container/fuzeagent-a2a/versions`.

## 5. Merge → verify

1. Config §1 is already filled (`oidcIssuerUrl`, `oidcDiscoveryUrl`, `audience`, `callerClaim`,
`entryRole`). Seal the 4 SealedSecrets in §2; confirm §3 for the first tenant.
2. **Decode a real minted token** (§1b step 6) and confirm the `iss` == `oidcIssuerUrl`,
`aud` == `a2a`, and the `repo` claim carries the exact repo name (`FuzeAgent`), and that the
Authentik app slug in the discovery URL is `fuzefront`. Only proceed if they match.
3. Merge the rollout PR with a **CLEAN squash message (no `[skip ci]`)** — see §4.
4. `release.yml` builds the image + bumps `tag`; Argo syncs the `a2a-shared` Application.
5. Verify: pod healthy (`GET /healthz`), card resolves at the well-known path, and the
`a2a-acceptance.yml` gate run against the live URL is green.

## Rollout order (this PR = step 1 only)

**FuzeAgent** (this PR) → **exec tier** (`Exec-cto/ceo/cfo/ciso` cards, per FuzeSDLC#54) →
**spine** (`FuzePlan` next — unblocks the real cross-product ticket scenario — then the other spine
services as they expose agents) → **leaves**. Each step: add the tenant + backfill that repo's
`providesTo` in one PR, merge clean, let Argo sync.
50 changes: 50 additions & 0 deletions deploy/helm/a2a-shared/templates/a2a-sealed-secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{{- if .Values.a2a.enabled }}
# A2A go-live SealedSecrets — encrypted for fuzeagent/<name> (kubeseal strict scope; only
# this cluster's controller can decrypt). sync-wave "-1" so the controller materialises the
# Secrets before the Deployment (wave 0) mounts them. ghcr-pull already exists in the ns.
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
annotations:
argocd.argoproj.io/sync-wave: "-1"
name: a2a-provider-anthropic
namespace: fuzeagent
spec:
encryptedData:
api-key: AgDLK6h6Zuk8MZJ61BrCjqhbqJ9n2ZTLowcXfiIeBQDY8lEw5Jk9o1ORuraNYTDwtXFUoYDyuxSPVnnd9Nn/dSMppjEeyYY7+fqT7T9AMPvvwA9AP05o5KM6syfd5MX9dkRdRX4CLz6uIZ6zBEOgVJS5NIDHyeeJAhMhiLZDm8l7GvLw7u00n714C4SNimxFb0PD5M9BjUSaxrWRDKt+uI5W0LIpGXpdDDYrQPvJc+aqecGygGPd5p8ZtNwzirIQGdkEKQegTRQyo0VnvzQNJQ4xhbcfY+wkRrFi7oiYkvfoGuIopKK95YHPgAm53uACb9LZzr8hyC7BU58pxC2QG2Y5FJwYiHrG14iEB9mkhgXlBCEhs28AX2sp+8Kp9SOoL+ZOsh498p6AAw8SmLQ5GJsKUs4a2otDGL7zVmXnirisHD2OsQ5j5ONdShBVdfPAfpBEtBZRF9lf7Qvv0bsB1uVTB7QLyKAZqpkJTNWUgOnpCUHMyxy2DVzXvxr6fc6aV0uljSUwM+897eXOwEWcXy2qJOisRpd8fvzw9Wx86JlHlA90TID+0bMRbIKIcp4HBwfCA6z2/KB3TKhfQC8Vd/8G0YUvNlwcUSJv4jrc3hjz4t1pctuIKNRjw+vmGPuygF13VIVh4EnKD08SOWPNhvnPzhgg6/0Xy2l48+ufNnfEuH1qnPBbP9MEoHddB+gL7KSP8zM3VvrgGBZm/A4e+YE+/llUxprlSl6t/xA=
template:
metadata:
name: a2a-provider-anthropic
namespace: fuzeagent
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
annotations:
argocd.argoproj.io/sync-wave: "-1"
name: a2a-mtls-ca
namespace: fuzeagent
spec:
encryptedData:
ca.crt: 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
template:
metadata:
name: a2a-mtls-ca
namespace: fuzeagent
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
annotations:
argocd.argoproj.io/sync-wave: "-1"
name: a2a-card-signing
namespace: fuzeagent
spec:
encryptedData:
jws.key: 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
template:
metadata:
name: a2a-card-signing
namespace: fuzeagent
{{- end }}
Loading
Loading