Skip to content

feat(ge-demo-generator): Cloud Run org-policy diagnosis, IAM 2-tier fallback, Layer 9, and setup docs alignment (v12.23-public) - #3105

Merged
holtskinner merged 3 commits into
GoogleCloudPlatform:mainfrom
ryotat7:port/prepare-5dc5e6e
Sep 11, 2026
Merged

feat(ge-demo-generator): Cloud Run org-policy diagnosis, IAM 2-tier fallback, Layer 9, and setup docs alignment (v12.23-public)#3105
holtskinner merged 3 commits into
GoogleCloudPlatform:mainfrom
ryotat7:port/prepare-5dc5e6e

Conversation

@ryotat7

@ryotat7 ryotat7 commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Description

This PR updates the GE Demo Generator to v12.23-public (skill v2.25.0), bringing four essential reliability improvements, architectural enhancements, and documentation alignments:

  1. Cloud Run Organization Policy Diagnostics:

    • Both deploy surfaces (app/Code.gs and setup_and_deploy.sh) detect constraints/run.allowedVPCEgress and constraints/run.allowedBinaryAuthorizationPolicies refusals.
    • For Cloud Functions Gen2 (Data Viewer), detects generic Org Policies refusals where constraint names are omitted by gcloud functions deploy, ensuring clear guidance is shown instead of an unexplained 400 error.
    • Diagnoses on failure without slow upfront probing; leaves default unconstrained deploys byte-for-byte identical.
  2. IAM 2-Tier Fallback for signBlob and actAs:

    • When granting roles/iam.serviceAccountTokenCreator (minting signed URLs via signBlob) and roles/iam.serviceAccountUser (Cloud Tasks worker dispatch) to the runtime compute service account, attempts resource-level self-binding first (gcloud iam service-accounts add-iam-policy-binding).
    • If resource-level IAM binding is restricted or denied by organization policy, automatically falls back to project-level IAM binding (gcloud projects add-iam-policy-binding).
  3. Autonomous Post-Deployment Verification & Self-Healing (Layer 9):

    • Extends verify_and_heal.py from 8 to 9 infrastructure layers, adding automated verification and self-healing for AI Governance & Telemetry (roles/cloudtrace.agent and roles/modelarmor.user when opted in).
  4. Web UI Setup Docs & Clasp v3 Alignment:

    • Updates README.md and app/package.json to replace deprecated clasp open with clasp open-script.
    • Fixes README §2/§3 setup instructions: removes misleading root npm install, clarifies that .clasp.json belongs in the project root pointing to {"rootDir": "app"}, and warns against running clasp from inside app/ (which caused empty deployments).
    • Corrects manual spreadsheet authorization function name from forceAuthorizeSpreadsheet to forceAuthorize.

Architectural Decision Records (ADRs)

  • ADR-01: Diagnostics on Failure vs Pre-flight Probing:
    Org-policy rejections are refused by the Cloud Run control plane in ~11 seconds before Cloud Build starts. Rather than burdening every user with speculative upfront API calls that require elevated permissions (orgpolicy.policies.list), diagnostics trigger only on failure and inspect real error logs.
  • ADR-02: 2-Tier IAM Fallback for Service Account Self-Impersonation:
    Least-privilege principles favor resource-level self-binding for signBlob and actAs. However, some enterprise environments restrict service account resource policy modification (setIamPolicy on service accounts). Falling back to project-level role grants ensures deployment resilience without sacrificing security.
  • ADR-03: Clasp v3 Root Execution Standard:
    Clasp v3 configuration (.clasp.json) operates from the project root with "rootDir": "app". Running clasp from within app/ caused Tracked files: 0 empty deployments. The documentation strictly establishes the project root as the execution directory.
  • ADR-04: Non-Invasive Public Boundary (Gate 10):
    Internal automatic VPC/subnet provisioning repair scripts (scripts/internal/orgpolicy_heal.sh) are intentionally excluded from public distributions to respect reader enterprise network governance. Only diagnostic explanations and remediation guidance are shipped publicly.

Verification

  • tools/public_gates.sh offline rehearsal:
    • Gate 1 (ShellCheck): PASS (0 warnings)
    • Gate 2 (shfmt): PASS (cleanly formatted)
    • Gate 3 (Hadolint): PASS (clean)
    • Gate 6 (Forbidden-Pattern Scan): PASS (0 hits)
    • Gate 7 (Spelling Candidates): PASS (0 candidates)
    • Gate 8 (Version Parity): PASS (v12.23-public matches internal v12.23-internal)
    • Gate 9 (Code.gs Parity): PASS (all 8 internal parity checks pass)
    • Gate 10 (Internal-Only Repair Absent): PASS (0 leaks)
  • node --check app/Code.gs: PASS
  • python3 -m py_compile on all Python scripts: PASS

…n unset VPC egress (v12.21-public)

Hardened Google Cloud projects reject `gcloud run deploy` before anything is
built:

    constraints/run.allowedVPCEgress violated ... annotation
      "run.googleapis.com/vpc-access-egress" set to null
    constraints/run.allowedBinaryAuthorizationPolicies violated ... annotation
      "run.googleapis.com/binary-authorization" set to null

Both are list policies, and `CreateService` with the matching annotation unset
counts as a violation of a non-empty `allowedValues`, so such a project refuses
a service for an annotation it never mentioned. There is no value meaning
"leave it unset" - `--vpc-egress` accepts only `private-ranges-only` and
`all-traffic`, and gcloud rejects the flag unless a network or connector comes
with it - so the deploy cannot be made to comply by dropping something.

Until now the run ended with a raw gcloud stack trace, which names a policy and
explains nothing; the operator concludes the generator is broken. Worse, the
account running the demo usually cannot read the policy at all, because it is
inherited from a folder it has no access to.

Both deploy surfaces now explain the refusal, name the flag that satisfies each
constraint, print the command that reads the project's allowed values, and say
where to put them:

    GE_RUN_NETWORK=... GE_RUN_SUBNET=... GE_RUN_VPC_EGRESS=... GE_RUN_BINAUTHZ=...

Set in `.env`, those four are picked up automatically on the next run. They are
empty on every unconstrained project, so the deploy command is byte-for-byte
what it always was.

The Data Viewer stays fail-soft and now says why it was skipped, rather than
reporting "skipped (optional)" for what is actually a policy refusal.
@ryotat7
ryotat7 requested a review from a team as a code owner September 11, 2026 09:21
…allback, Layer 9, and setup docs alignment (v12.23-public)

- Update Data Viewer deployment error diagnostics in Code.gs to detect generic
  Cloud Functions / Cloud Run org policy refusals and explain all applicable constraints.
- Implement 2-tier fallback for IAM signBlob and actAs bindings (resource-level self-binding
  first, falling back to project-level when resource policy manipulation is restricted).
- Add Layer 9 (AI Governance & Telemetry IAM verification & self-healing) to verify_and_heal.py.
- Align README and package.json with Clasp v3 commands (clasp open-script) and fix setup docs
  to clarify root directory execution and prevent misplaced cd app runs.
- Correct manual spreadsheet authorization function name to forceAuthorize.
- Bump APP_VERSION to v12.23-public and update SKILL.md to v2.25.0.
- Update spelling allow-list for newly introduced tokens.
@ryotat7 ryotat7 changed the title feat(ge-demo-generator): survive Cloud Run org policies that refuse an unset VPC egress (v12.21-public) feat(ge-demo-generator): Cloud Run org-policy diagnosis, IAM 2-tier fallback, Layer 9, and setup docs alignment (v12.23-public) Sep 11, 2026
@holtskinner
holtskinner merged commit f0c5707 into GoogleCloudPlatform:main Sep 11, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants