chore(a2a): FuzeAgent-first prod rollout (DRAFT — needs owner secrets/config) - #93
Merged
Conversation
…RAFT — do not merge) Stages deploy/helm/a2a-shared/values-prod.yaml to enabled:true for the FuzeAgent-first bring-up (FuzeAgent tenant, anthropic provider, OIDC auth) with REPLACE_ME placeholders for owner-supplied config and secretRef names for the SealedSecrets. Adds GO-LIVE.md: the exact owner checklist (oidcIssuerUrl, SealedSecrets, providesTo backfill, clean-squash-message so release.yml builds the image). Prod is GitOps — this only takes effect on merge + Argo sync. Do NOT merge until GO-LIVE.md is satisfied. No secrets are committed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
…ator role (#94) Only the oidcIssuerUrl placeholder remains owner-supplied; entryRole now points at the serving role added in #94. Still DRAFT — do not merge until GO-LIVE.md is satisfied. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
izzywdev
added a commit
that referenced
this pull request
Jul 23, 2026
…2a block) (#94) * feat(a2a): FuzeAgent agent-orchestrator serving role + role-schema a2a block FuzeAgent had only _base under agent-templates/roles/, so it projected an EMPTY A2A card and could not be the first tenant. Adds: - agent-templates/roles/agent-orchestrator/role.json — the serving role (caller hands a goal; FuzeAgent dispatches a managed agent and returns the result + artifacts), with a2a.examples for discoverability. - an OPTIONAL `a2a` property on agent-templates/schema/role-manifest.schema.json mirroring contracts/a2a/v1/schema/role-a2a-extension.schema.json — the schema follow-on the A2A contract flagged (card_generator.py already reads role.a2a.*). additionalProperties stays false; no existing constraint weakened. Unblocks the FuzeAgent-first prod rollout (#93 sets entryRole: agent-orchestrator). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549 * chore(governance): reconcile managed files to FuzeSDLC v1 [skip ci] * test(a2a): validate the repo's real roles project a valid card + widen a2a-unit paths - test_repo_cards.py: loads THIS repo's .fuze/manifest.json + agent-templates/roles/ and asserts generate_cards() yields a schema-valid FuzeAgent card whose skills include agent-orchestrator (with examples) and never _base. Guards the actual serving-role set, not just fixtures. - a2a-unit.yml: add agent-templates/roles/** and schema/role-manifest.schema.json to the path filters — a role/schema change changes the projected card, so it must run a2a-unit (previously it did not, so #94's role addition would have gone unvalidated). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549 * test(a2a): sign the projected card (fuze-profile requires the signatures field) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549 --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…machine-identity dep oidcIssuerUrl = https://app.fuzefront.com/application/o/fuzefront/ (from FuzeFront deploy/helm/fuzefront/values-prod.yaml — the family OIDC issuer). Adds GO-LIVE.md §1b: A2A callers are machine agents, so FuzeFront must register each as an Authentik client_credentials machine identity and the audience/callerClaim->repo-name mapping must be confirmed (sub=client_id UUID for client_credentials; authz.md needs the repo name). Cross-repo item for FuzeFront via @claude. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
… not JWT) in #93 FuzeFront#364's @claude handler no-op'd, so I read FuzeFront backend/security/src/services/machine-identity.ts directly. Its machine identity is INTROSPECTION-based (client_credentials, sub_mode=hashed_user_id, validated via Authentik introspection) — the current OIDC/JWT auth block (oidcIssuerUrl/audience/callerClaim) does NOT fit. GO-LIVE.md §1b now records the finding + that this is a CTO/contract decision (introspection support in the A2A server vs FuzeFront issuing repo-name JWTs). Marked DO-NOT-MERGE until resolved. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
…e JWTs) FuzeFront (identity owner) chose Option 2: issue repo-name JWTs, not introspection (fits the frozen contract, no per-pod introspection creds, no client_id->repo map). Resolved auth: callerClaim=repo, audience=a2a, iss stays public app.fuzefront.com but JWKS/discovery fetched in-cluster (authentik-server:9000) to dodge the CF-tunnel hairpin. GO-LIVE §1b now lists the critical path: FuzeFront M2M-provisioning PR (emit repo/aud claim) -> in-cluster FuzeAgent registration -> FuzeInfra NetworkPolicy (fuzeagent->authentik-server:9000) -> #93 finalize. Still DO-NOT-MERGE until those land + a real token is decoded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
…URL (#93) authentik-server runs in the fuzefront namespace → in-cluster discovery = authentik-server.fuzefront.svc.cluster.local:9000. FuzeInfra#372 opened for the fuzeagent->fuzefront NetworkPolicy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
…uzeInfra#372) FuzeInfra handler correctly determined the fuzeagent->authentik-server NetworkPolicy belongs in FuzeFront's chart (podSelector matches own ns; fuzeinfra AppProject can't target fuzefront), and flagged that a standalone allow-policy would flip authentik-server to deny-all and break Traefik->Authentik login (no default-deny baseline). Tracked at FuzeFront#368. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
…ened go-live Now that the frozen values-interface exposes auth.oidcDiscoveryUrl (v1.1.0, FuzeAgent#96), set it in values-prod.yaml to the in-cluster Authentik discovery URL so the A2A server fetches JWKS in-cluster (no CF-tunnel hairpin) while still validating iss against oidcIssuerUrl. Keep the hardened (Option B) secret set: a2a-mtls-ca + a2a-card-signing + a2a-provider-anthropic + ghcr-pull. FuzeAgent tenant repo is PUBLIC, so drop reposGitTokenSecretRef (anonymous clone) -> exactly 4 operator SealedSecrets. GO-LIVE.md rewritten to the hardened sequence: 4-secret list (names+keys), the FuzeFront NetworkPolicy already enabled (FuzeFront#373), the in-cluster JWKS URL, the decode-a-real-token step, and the clean-squash-merge requirement (no [skip ci] so release.yml builds/pushes the image + bumps the tag). DO-NOT-MERGE guard retained (secrets must exist + token decoded). Verified: helm lint clean (default + prod); helm template | kubeconform -strict -ignore-missing-schemas passes (prod 3/3, ci 4/4, default renders empty); values-prod a2a block validates against the v1.1.0 schema (oidcDiscoveryUrl accepted). Server oidcDiscoveryUrl support is backend-engineer's slice. Co-Authored-By: Claude <claude-opus-4-8> <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
2 tasks
…t-prep # Conflicts: # deploy/helm/a2a-shared/values-prod.yaml
…t-prep # Conflicts: # deploy/helm/a2a-shared/values-prod.yaml
…rd-signing) Encrypted for fuzeagent/<name> (kubeseal strict scope, contabo-prod controller). enabled-gated + sync-wave -1 so they materialise before the Deployment mounts them. ghcr-pull already exists in the namespace (reused). Completes the Option-B secret set so #93 can go live; register-a2a-cli (caller-side client) remains a follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549
…to main's release SHA)
izzywdev
marked this pull request as ready for review
July 24, 2026 00:50
izzywdev
added a commit
that referenced
this pull request
Jul 24, 2026
…o-live (#115) fuzeagent-quota capped limits.cpu at 4 and it was fully consumed by the existing workloads, so a2a-shared (limits.cpu=500m) could not schedule: FailedCreate: exceeded quota: fuzeagent-quota ... limited: limits.cpu=4 Only the CPU-limit ceiling was tight (memory 4/8Gi, pods 8/20, requests 450m/2 all had headroom). 6 fits a2a plus its rolling-update surge; limits are ceilings, not reservations (requests.cpu cap stays 2). Unblocks the #93 A2A prod bring-up. Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
izzywdev
added a commit
that referenced
this pull request
Jul 24, 2026
…nfigMap) (#117) The a2a-shared pod was stuck: `MountVolume.SetUp failed ... configmap "a2a-state" not found`. The `state` volume was wired as an optional READ-ONLY ConfigMap, but FUZE_STATE_DIR=/state is where the server persists in-flight session state (run_until_block) — it must be WRITABLE. Switch it to an emptyDir (always mounted). Ephemeral is fine for v1 (in-flight tasks don't need to survive a pod restart yet). Unblocks the #93 A2A prod bring-up (pod was Init:0/1 on the failed mount). Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
izzywdev
added a commit
that referenced
this pull request
Jul 24, 2026
…o slug (#119) Card endpoint 500'd: FileNotFoundError /repos/FuzeAgent/.fuze/manifest.json. The server's LocalRepoResolver reads /repos/<tenant> (case-preserved tenant identity), but the repo-sync init container cloned to /repos/<a2a.repoSlug .repo> = /repos/fuzeagent (lowercased). Clone to /repos/{{ .tenant }} so it matches what the server reads. Final blocker for the #93 A2A prod bring-up (pod Running + /healthz ok; only the card projection failed on the path mismatch). Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
izzywdev
added a commit
that referenced
this pull request
Jul 24, 2026
…hema) (#120) Card endpoint 500'd at runtime: FileNotFoundError /app/contracts/a2a/v1/VERSION. card_generator.contract_version() reads CONTRACT_ROOT/VERSION (=/app/contracts/a2a/v1) and the card validator reads schema/ from there, but the Dockerfile only copied the contract's client/ subtree (pip-installed to /app/contract-client). Add `COPY contracts/a2a/v1/ /app/contracts/a2a/v1/` so the runtime file reads resolve. Worked in CI only because that ran from the source checkout. Final #93 bring-up blocker. Claude-Session-Id: 17fb89fd-3579-433b-a6c4-9c9e7f3ec549 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prod is GitOps; this is a staged, reviewable rollout — do NOT merge until the checklist is met. Flips
deploy/helm/a2a-shared/values-prod.yamltoenabled:truefor the FuzeAgent-first bring-up, and addsdeploy/helm/a2a-shared/GO-LIVE.md(the owner checklist).What's staged
a2a.enabled: true, FuzeAgent tenant (anthropic provider), OIDC auth + mTLS + card-signing wired to SealedSecret refs (no secret values committed).REPLACE_MEplaceholders for the two owner-supplied values:oidcIssuerUrland the tenantentryRole.Owner must do before merge (see GO-LIVE.md)
oidcIssuerUrl(family Authentik/Keycloaka2aissuer) + the FuzeAgententryRole.fuzeagent:a2a-provider-anthropic+ghcr-pull(required);a2a-mtls-ca,a2a-card-signing,a2a-repos-git(optional — can trim for a minimal bring-up).providesTostays absent for now (accepts no callers yet — safe); backfill it from FuzeSDLC#54 when the first consumer is enabled.Image caveat (important)
release.ymlbuildsfuzeagent-a2aon merge-to-main underdeploy/helm/a2a-shared/**, but it skipped the prior A2A merges because their squash bodies inherited a[skip ci]from the governance-sync reconcile commits. Merge this PR with a CLEAN squash message (no[skip ci]) so the image builds and thetag:bumps. Verify:gh api user/packages/container/fuzeagent-a2a/versions.Not done here (by design)
The actual prod flip (you merge after secrets), the exec-tier + spine enable steps, and applying the
providesTobackfill — all follow-ons. I did not merge and did not touch prod.🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com