Fold in Gemini round-4 CI/CD + decoupling findings (with corrections)

- ARM64 markers (enable-qemu both files + platform:LINUX_ARM64) for Docker-bundled tier
  tasks -> Phase 0b build + exit (per reference_cicd_arm64_qemu).
- Node 24 / workflows: sh-agentforce keeps thin ci.yaml/deploy.yaml callers but they call
  the new cd-sfdx, NOT the AWS CDK templates (corrected the reviewer's framing).
- CR-1 decoupling: client/audience matrix injected as config (SSM/CDK env), not hardcoded
  into the transport-agnostic core; corrected reviewer's 'Secrets Manager' -> SSM (client_ids
  are non-sensitive). §6 #8d.
- Role isolation: new isolated githubdeploy-sh-agentforce (never reuse sh-mcp role), scoped
  only to read the JWT secret since deploy target is Salesforce not AWS.
Reviewer applied AWS/CDK conventions to a Salesforce-deploying repo; folded in with corrections.
This commit is contained in:
Adam Moussa 2026-06-11 13:49:57 -04:00
parent 9cf124a24b
commit 0d4bb39175

View file

@ -240,6 +240,22 @@ Gemini APPROVED the rest: B1/B5 parallel-run dual-feed + Bolt fallback sound; §
integrated with the token-layer mechanism. **All three families (Claude/Fable, GPT-4.1, Gemini) now converge: the
structural plan is sound; the only open risk is the auth token-mint mechanism, fully spike-gated in Phase 0a.**
**Round 4 (Gemini, CI/CD + decoupling pass — 2026-06-11).** Four findings, all folded in WITH corrections (the
reviewer applied AWS/CDK conventions to a Salesforce-deploying repo and over-classified config as a secret):
- **FIX (ARM64):** added `enable-qemu` (both ci+deploy) + `platform: LINUX_ARM64` for any Docker-bundled tier
task to Phase 0b build + exit (per `reference_cicd_arm64_qemu`). Valid as-is.
- **FIX (Node 24 / workflows):** corrected — sh-agentforce keeps the thin `ci.yaml`/`deploy.yaml` callers on Node
24, but they call the **new `cd-sfdx`**, NOT the AWS `ci-typescript-cdk`/`cd-cdk` templates (those don't fit the
`sf` toolchain). §1g + Phase 0b.
- **FIX/QUESTION (CR-1 coupling):** valid — the client/audience matrix is **injected as config (SSM / CDK env),
not hardcoded**, keeping the transport-agnostic core decoupled from topology. Corrected the reviewer's "Secrets
Manager" → SSM (client_ids are non-sensitive). §6 #8d.
- **NIT (role isolation):** valid + sharpened — provision a **NEW isolated `githubdeploy-sh-agentforce`** (never
reuse the sh-mcp role), but note it exists *only* to read the JWT secret since sh-agentforce deploys to
Salesforce, not AWS. §1g + Phase 0b.
Pattern holds (per `feedback_fable_review_gates`): cross-family reviewers assert convention-application
confidently — verify and correct, don't adopt wholesale. Structural verdict unchanged: sound, auth spike-gated.
**Cross-family review (GPT-4.1 `cross_reviewer`, 2026-06-11) — auth/trifecta sections.** Run per the mandatory
cross-review gate for auth/IAM design (Fable is Claude-family, not a substitute). Findings folded in:
- **CR-1 (BLOCK):** validate `aud` at the edge **AND** server-side (defense in depth) — the per-tier authorizer
@ -415,6 +431,10 @@ handbook is one-deploy-target-per-repo. Coexistence:
org; **branch protection + a required check** (the SFDX analog of `ci / ci`); **enable vulnerability-alerts +
`dependabot_security_updates` + secret_scanning** — Dependabot is **NOT N/A** (the `github-actions` ecosystem
applies even without npm; also watch `@salesforce/cli`); pin `@salesforce/cli`; kebab-case repo/workflow names.
Thin **`ci.yaml`/`deploy.yaml` caller files on a Node 24 runner** (org standard, subject to `@salesforce/cli`
Node compatibility) that call the new **`cd-sfdx`** reusable workflow — **NOT** the AWS `ci-typescript-cdk`/
`cd-cdk` templates, which don't fit the `sf` metadata toolchain (G10). The handbook ci.yaml/deploy.yaml caller
convention still applies; only the reusable workflow they call differs.
- **`cd-sfdx` deploy auth (F3 — the prod-deploy key for the entire agent surface; design/verify story of its
own, NOT one Jira bullet).** Salesforce has **no OIDC**; CD authenticates via the **JWT-bearer flow of a
connected app** using a private key + cert. That key is a **long-lived secret** — store it in **AWS Secrets
@ -422,6 +442,9 @@ handbook is one-deploy-target-per-repo. Coexistence:
pull it in the workflow, **scope separate connected apps for sandbox vs prod**, and define a **rotation cadence**.
`cd-sfdx` is a brand-new org-wide reusable workflow (Gap G10) implementing deploy-then-merge against
sandbox→prod orgs — it gets its **own design + verification step** before any agent metadata depends on it.
The workflow fetches the JWT key from Secrets Manager via a **NEW isolated `githubdeploy-sh-agentforce` OIDC
role** (1:1 repo↔role per `cicd.md` — never the sh-mcp role), scoped to that one secret; the role exists only to
read the JWT key, since the actual deploy target is the Salesforce org, not AWS.
- **Cross-review gate extends to Agentforce metadata** that changes tool exposure, audience, or scope binding —
security-relevant just like an IAM diff (design.md §8). `ASSUMPTION`: GenAiPlannerBundle/connection changes and
the `cd-sfdx` connected-app trust go through `cross_reviewer` (GPT-4.1) the same as IAM.
@ -635,7 +658,7 @@ Follows design.md §6 phasing; each legacy bot is deprecated **only at proven pa
| Phase | Work | Parity / exit gate | Rollback |
|-------|------|--------------------|----------|
| **0a — Auth spike (GATING, B5)** | **Before any other Phase-0 spend.** Stand up a **minimal throwaway kit** (one Cognito user pool + one app client + one ES action + one Cognito-fronted smoke endpoint; licensing already accepted) and prove the **Per-User OAuth Browser Flow action in Slack** carries the real Google `sub` (§6 verify #1, #3, #8). Confirm the model selector + AWS-Hosted name (#4) and the Testing-Center identity question (#5). **0a also implicitly tests verify #6 — if the Slack plan does not support Employee Agents, 0a cannot start (escalate immediately).** | **FATAL gate (fail → STOP, switch to fallback, do NOT proceed to 0b):** real Google `sub` reaches the server; first-call Slack consent works; token refresh survives; the `aud`/authorizer mechanism (#8) works. **Decision-input (non-fatal):** Testing-Center per-user invocation (#5) — if it can't, parity runs as scripted per-user sessions (G12), not a fallback trigger. | N/A (legacy untouched) |
| **0b — Platform build (F4)** | Only after 0a passes. **Build the servers:** monorepo + `shared` auth/scope/PII/audit guard + per-service packages + **transport-agnostic core + OpenAPI adapter** + **per-tier API Gateway + Cognito authorizer + shared WAF** (B3); Cognito + Google federation + pre-token (per-audience scoping, B4) + 5-min group-sync (design.md §6.1); **deploy-role-first** (`githubdeploy-sh-mcp` already exists; add for `sh-agentforce`), CI/CD reusable workflows, coverage gate. Create `sh-agentforce` SFDX repo + **design & verify `cd-sfdx`** (G10, F3). Stand up Data Cloud + **Seahaven Ops Knowledge** Data Library; **`notion-sync` DUAL-FEEDS** Bedrock KB **and** Data Cloud (B1 — legacy KB stays fresh for rollback). | SSO end-to-end; per-user JWT reaches a smoke-test tool with real `sub`; **core + OpenAPI adapter green at the design.md §7.3 coverage gate** (80% lines, 100% shared auth guard); Data Library retriever returns Front SOP answers; legacy Bedrock KB still fed. | N/A (legacy untouched) |
| **0b — Platform build (F4)** | Only after 0a passes. **Build the servers:** monorepo + `shared` auth/scope/PII/audit guard + per-service packages + **transport-agnostic core + OpenAPI adapter** + **per-tier API Gateway + Cognito authorizer + shared WAF** (B3); Cognito + Google federation + pre-token (per-audience scoping, B4) + 5-min group-sync (design.md §6.1); **deploy-role-first + 1:1 repo↔role isolation (NIT):** `githubdeploy-sh-mcp` exists; provision a **NEW isolated `githubdeploy-sh-agentforce`** — never reuse/expand the sh-mcp role — scoped minimally to read `sh-agentforce/sfdx-jwt-key` (the Salesforce deploy itself uses the JWT key, not an AWS role). Thin `ci.yaml`/`deploy.yaml` callers on **Node 24**: sh-mcp → AWS/CDK reusable workflows; sh-agentforce → the **new `cd-sfdx`** (NOT the AWS templates — they don't fit the `sf` toolchain). **ARM64 markers (FIX, per `reference_cicd_arm64_qemu` — bit slack-bot + exec-aide twice):** any Docker-bundled tier task needs `enable-qemu: true` in BOTH ci.yaml AND deploy.yaml **and** `platform: LINUX_ARM64` on every image asset. Coverage gate. Create `sh-agentforce` SFDX repo + **design & verify `cd-sfdx`** (G10, F3). Stand up Data Cloud + **Seahaven Ops Knowledge** Data Library; **`notion-sync` DUAL-FEEDS** Bedrock KB **and** Data Cloud (B1 — legacy KB stays fresh for rollback). | SSO end-to-end; per-user JWT reaches a smoke-test tool with real `sub`; **core + OpenAPI adapter green at the design.md §7.3 coverage gate** (80% lines, 100% shared auth guard); **`githubdeploy-sh-agentforce` provisioned (isolated); CI/CD green with ARM64 markers — no `exec format error`**; Data Library retriever returns Front SOP answers; legacy Bedrock KB still fed. | N/A (legacy untouched) |
| **1 — Seahaven Ops** | Wire Ops agent → `sh-mcp-ops` facade; vendors (KB/Maps) + WO/PO/site + knowledge + tasks. | Behavioral suite + golden-transcripts vs **Alex** green; per-user auth + per-tool scope verified at the server. | **Flip Slack default back to Alex** (Alex still running — NOT torn down until Phase 4). |
| **2 — Seahaven Finance** | Wire Finance agent → `sh-mcp-finance` facade; full audit logging; 15-min TTL + deny-list. | Audit records emitted; PII-redaction tests green; **per-tier audience-binding rejection verified** (B3). | **Flip back to Alex** (whose QBO action group is still live — Alex runs through Phase 4). |
| **3 — Lauren Exec** | Wire Exec agent → `sh-mcp-ops` facade `*:self`; per-user Google grant; DM-scoped. Refactor `fetch-classify`/`daily-digest`/`reminder` to import shared packages (design.md §6.4). | Channel-aware-privacy + golden-transcripts vs **Lauren** green; ABAC Gmail isolation proven. | **Keep exec-aide running**; Lauren's workflow needs explicit sign-off before retiring exec-aide (design.md §6.6). |
@ -843,7 +866,12 @@ Groups to reconcile the two control planes (G11, recommend SCIM).
(b) **Confirm the `pre-token V2` trigger is available** on our Cognito plan (it may be a paid feature).
(c) **Pick + prove the per-tier rejection mechanism** — `client_id` allow-list per gateway, resource-server
scope-prefix, or custom `aud` via V2 — since Cognito access tokens carry no native per-resource-server `aud`.
The B3 edge rejection, B4 boundary, and §1h audience tests all depend on (a)–(c).
(d) **The client/audience matrix is injected as CONFIG, not hardcoded (decoupling FIX/QUESTION).** The
transport-agnostic core must NOT embed gateway/topology identifiers in application logic (that would violate the
D12/B3 decoupling). It validates against an allow-list **supplied via SSM Parameter Store or a CDK-injected env
var** — client_ids are **non-sensitive identifiers → SSM/config, NOT Secrets Manager** (secrets-and-config.md;
the reviewer's "Secrets Manager" was over-classified). The core consumes a matrix; it doesn't know the topology.
The B3 edge rejection, B4 boundary, and §1h audience tests all depend on (a)–(d).
---