AI did not create citizen development. It removed the friction that kept it small.
Knowledge workers (analysts, ops, finance, legal, anyone with a business problem) can now produce working applications. That is valuable, and it creates a governance problem. Code that works is not the same as code that is secure, maintainable, and deployable in production. Most organizations are still choosing between two bad defaults: block the work and lose the value, or permit it without structure and accumulate risk.
Traditional software governance assumes a trained engineer who understands what they are building. Code review, pull request gates, security scanning: these work when the reviewer and the producer share a technical context. They break down when the producer is a knowledge worker who built something that works but cannot explain why. They break down further when the reviewer is an engineering team with no bandwidth to educate. The failure mode is not malicious. It is structural. The governance tools were not designed for this producer class.
The governed path combines four interlocking layers. First, HRIS-linked identity flowing into GitHub Enterprise via SCIM, so access reflects employment state, not historical grant state. Second, centrally managed AI instruction files that encode engineering standards at the point of creation, not at review. Third, Vercel as a guarded deployment surface with PR-based preview gates. Fourth, GCP as the IAP-protected runtime, with Workload Identity Federation replacing static keys. The knowledge worker never interacts with any of these layers directly. They write code with AI assistance, open a pull request, and the architecture enforces the standards around them.
Where gaps exist, this article calls them out plainly. Cursor has no admin-push mechanism for rule files. Vercel preview deployments do not automatically provision isolated backend environments per branch. I have not found a public reference implementation that covers this stack end-to-end.
There is a real tradeoff. The governed path enables knowledge workers to ship deployable software. Engineering teams review outputs built closer to their standards. The audit trail reflects actual organizational identity. The cost is upfront investment in HRIS integration, instruction file development, and deployment infrastructure. The system also requires maintenance as standards evolve, and it requires organizational change so knowledge workers use the governed path instead of routing around it.
The argument for the cost: the alternative is not "knowledge workers don't build things." They are already building things. The alternative is building things with no governance and no path to production, which produces shadow IT at AI speed. Seventy-one percent of office workers admit using AI tools without IT approval.[^53]
The regulatory argument is straightforward: HRIS-linked provisioning supports SOC 2 CC6.1/CC6.2 access control criteria, and AI-assisted code can pass audits if change review, audit trails, and human sign-off remain intact. The control evidence still has to show who approved the change, what automated checks ran, and what reached production. Existing controls (PR approval, secret scanning, SAST in CI) can satisfy current audit expectations if properly documented.[^54]
The trajectory: as AI-assisted development matures, the instruction file becomes the primary mechanism for encoding organizational standards. Engineering review shifts from "is this code correct" to "are the instruction files encoding the right standards." The knowledge worker and the engineer are no longer doing different things. They operate at different levels of the same governed system.
For most teams, the practical first version is smaller than the full architecture below: one HRIS-driven GitHub team, one repository template, one set of Copilot and Cursor instructions, one protected Vercel project, one Cloud Run service behind IAP, and one Workload Identity Federation path with no static GCP keys. Prove that path with two or three real internal tools before trying to generalize it across the company.
HRIS to GitHub Identity Lifecycle
The Architecture: HRIS as Authoritative Source
Modern IAM architecture follows a consistent pattern: HRIS (Workday, BambooHR, Rippling) serves as the authoritative source of truth, feeding into an Identity-as-a-Service platform (Okta, Microsoft Entra ID, Google Workspace), which then propagates to downstream applications through SSO, SCIM, and SAML. The critical architectural principle is directionality: Active Directory or Okta syncs from HRIS, never the reverse. Maintaining a parallel identity in both Okta and BambooHR guarantees misalignment and manual reconciliation work.[^1][^2]
When HR enters a new hire in Workday, the system maps them to a predefined role (e.g., "Knowledge Worker - Finance Apps"), which triggers provisioning to all appropriate downstream systems including GitHub. Role changes (promotions, department transfers) trigger automatic attribute updates. When an employee is deactivated in the IdP, SCIM revokes access across every connected application. Delayed offboarding is one of the most common causes of unauthorized access after departure.[^3][^1]
GitHub EMU vs. Standard Organization
This is the most consequential architectural decision in this stack. GitHub's strongest lifecycle-management model is Enterprise Cloud with Enterprise Managed Users (EMU). Pricing changes over time, but the architecture distinction matters more than the list price: EMU makes the IdP authoritative for account lifecycle, profile data, organization membership, and repository access.[^4]
Table 1. GitHub Enterprise: Standard vs. EMU.
| Feature | Standard GitHub Enterprise | GitHub Enterprise + EMU |
|---|---|---|
| SCIM provisioning | Invitation-only (not true provisioning) | Full: create, update, deactivate, groups |
| User account origin | Personal GitHub accounts | Managed accounts created by IdP |
| External collaboration | Unlimited | Blocked: EMU users cannot access repos outside their enterprise |
| Migration path | Existing account | Must create new enterprise account from scratch |
| IdP flexibility | Multi-IdP possible | Single IdP enforced (Okta or Entra ID, not both) |
| Cost | Plan-dependent | Enterprise Cloud / EMU licensing |
Standard GitHub organizations can use SAML SSO and team synchronization patterns, but they do not make the IdP authoritative for the full managed-user lifecycle in the same way EMU does. For a knowledge worker governance program, that difference matters because departure, transfer, and repository access changes must be driven from the identity system rather than from manual cleanup.[^4]
EMU was not always this flexible. In September 2024, GitHub made its open SCIM support generally available for EMU, allowing organizations to use any SAML 2.0 + SCIM 2.0 compliant identity provider rather than being restricted to Okta or Entra ID. This "bring your own IdP" path is now viable for organizations using PingFederate or other enterprise IdPs.[^5]
Configuring Okta to EMU SCIM
The configuration sequence is non-trivial and must be completed in order:
- Create a new EMU enterprise account. You cannot convert an existing organization.[^4]
- Configure SAML SSO first. SCIM cannot be enabled without SSO in place.[^6][^4]
- Generate a personal access token with the
scim:enterprisescope from the EMU setup user (@SHORTCODE_admin).[^6] - In Okta admin console: navigate to the GitHub EMU application, then Provisioning tab, then Integration, then Configure API Integration, and paste the PAT as the API Token.[^6]
- Enable provisioning features: Create Users, Update User Attributes, Deactivate Users.[^7]
- Assign users/groups to the Okta app. Okta provisions on app assignment.[^4]
For Entra ID, the process uses the Gallery app in the Entra admin center. The SCIM endpoint format is https://api.github.com/scim/v2/organizations/<org_name>. Entra's provisioning runs on a scheduled cycle, typically every 40 minutes. This is a real propagation latency that affects day-one access for new hires. Okta provisions near-real-time on assignment. Platform teams relying on Entra for JML should communicate this latency in onboarding processes.[^4]
Failure Modes in Production
Understanding where SCIM fails is essential for operating this system reliably.[^8]
Username normalization conflicts (most common): GitHub normalizes the SCIM userName attribute when creating accounts. If two IdP users normalize to the same GitHub username (e.g., john_smith and john.smith both become johnsmith_SHORTCODE), only the first user is created. Subsequent provisioning attempts return HTTP 400 errors. Resolution requires either changing the conflicting IdP identity or removing the conflicting GitHub user.[^9]
SAML/SCIM identity mismatch: If a user's SAML data does not match an existing SCIM-provisioned identity, GitHub returns an authentication error. This typically surfaces when SAML is reconfigured after SCIM was already established.[^8]
Okta + Entra ID combination: Explicitly unsupported. GitHub's SCIM API returns an error on provisioning attempts if both are configured for SSO/SCIM. This is a dealbreaker for post-acquisition companies with mixed IdP environments.[^10]
Rate limiting: SCIM operations are capped at 1,000 users per hour. Large initial migrations (provisioning thousands of users simultaneously) will be throttled. Stagger bulk migrations.[^4]
Import Groups not supported: The "Import Groups" checkbox in Okta does not function. Selecting or deselecting it has no impact. Group membership flows from Okta Push Groups, not import.[^7]
JML Timing in Practice
A properly configured HRIS-to-Okta-to-GitHub chain can achieve close-to-real-time deprovisioning on termination events. Mapping the HRIS "Terminated" status field to a deprovisioning workflow that disables the SSO session and revokes all active tokens is achievable within 60 seconds with proper IdP configuration. The Workday-to-Okta implementation pattern documented by Iron Cove Solutions shows Workday triggers (New Hire, Transfer, Termination) automatically provisioning and deprovisioning users across all connected systems, with department-based application assignment driven by organizational structure.[^4][^1][^11][^12]
The gap: GitHub access review (confirming residual repo-level permissions beyond org membership) still requires tooling beyond basic SCIM. Tools like Stitchflow or Balkan.id address this.
Centrally Managed AI Instruction Files and Prompt Governance
Why Centralized Instruction Management Matters
A knowledge worker using an AI coding assistant without organizational guidance builds software with whatever defaults the AI vendor chose. The organizational goal is to encode engineering standards (approved dependency patterns, secret handling requirements, deployment targets, security policies) into AI assistant behavior at the point of creation. This is prompt governance.
The mechanisms differ by tool, but the conceptual model is consistent: platform or security engineering authors a canonical set of instructions; those instructions are distributed to every developer's AI assistant via version-controlled configuration files or admin settings; the AI assistant then consistently applies those standards without the knowledge worker needing to re-specify them.
GitHub Copilot: Organization-Level Instructions
GitHub Copilot supports organization custom instructions for organizations on Copilot Business or Copilot Enterprise. Organization owners set instructions under the organization's Copilot settings, and the instructions currently apply across:[^13]
- Copilot Chat on github.com
- Copilot code review
- Copilot cloud agent[^13]
This is the highest-leverage intervention point for prompt governance of Copilot users. A platform team writes instructions once and they silently apply to every Copilot interaction across the organization, without individual developer action.
Below the organization level, two additional scopes exist:[^14]
Repository-wide instructions (.github/copilot-instructions.md): Apply to all Copilot requests made in the context of a given repository. Checked into source control, version-tracked, and visible in PRs. This is the right place for project-specific conventions, framework choices, and approved dependency patterns.
Path-specific instructions (.github/instructions/*.instructions.md): Scoped to specific files or directories using applyTo frontmatter. Use these to apply Python-specific security rules only to .py files, or to enforce different standards in the api/ directory vs. the frontend/ directory.[^15]
The following example copilot-instructions.md encodes governance standards:
## Security Requirements (Applied to All Code)
- Never hardcode credentials, API keys, or secrets. Use environment variables.
- Cloud Run services must use dedicated service accounts with minimum required roles.
- All external API calls must handle errors and log to Cloud Logging.
- Dependencies must come from the approved list in `/docs/approved-packages.md`.
## Deployment Target
- Applications deploy to Cloud Run in `us-central1`. Reference Cloud SQL via Unix socket.
- Use `CLOUD_SQL_CONNECTION_NAME` environment variable for DB connections.
- Vercel functions call GCP backends using Workload Identity Federation, never static SA keys.
## Code Standards
- TypeScript preferred for new Next.js projects.
- All database queries must use parameterized statements.
- No `console.log` in production code; use structured logging library.
The GitHub blog recommends bootstrapping these files by asking Copilot itself to inventory the codebase and generate the initial instructions file. This is useful when onboarding an existing knowledge worker repository.[^16]
GitHub Copilot Secret Scanning as a Safety Net
Separate from custom instructions, GitHub's Copilot secret scanning provides AI-powered detection of unstructured secrets (passwords, tokens) in source code, triggering alerts and optionally blocking pushes via push protection. This acts as a governance backstop: even if a knowledge worker inadvertently commits a credential, push protection can catch it before it reaches the repository.[^17][^18][^19]
Cursor: Project Rules and the Governance Gap
Cursor's instruction system operates at three scopes:[^20]
- Global rules: Set in Cursor Settings > General > Rules for AI. Apply to all projects for that user.
- Project rules: Stored in
.cursor/rules/, version-controlled, scoped to the repository. Created via "New Cursor Rule" or Cursor Settings > Rules. - Legacy
.cursorrules: Still functional at repo root but superseded by.cursor/rules/.
For team governance, the recommended pattern is to check .cursor/rules/ into Git alongside the codebase, which is what Cursor's own documentation describes.[^21] Using trunk-based development minimizes drift: when a rule is updated, it reaches all developers at their next pull. Some teams add a /devprompts/ directory with more detailed agent-facing context, pointed to by an agents.md manifest; that is a practice I have seen, not a documented convention.
The critical governance gap in Cursor: There is no admin-push mechanism. A Cursor Enterprise admin cannot centrally deploy rules to all users' machines. The platform currently offers workarounds: committing .cursorignore to each repo (version-controlled but not enforced), hierarchical .cursorignore in parent directories, and using MDM + AllowedTeamId to ensure devices are enrolled in an enterprise team with privacy mode enforced. For organizations requiring guaranteed rule compliance, this gap is real. Git-committed rules combined with a CI gate that validates rule file presence is the most practical defense-in-depth approach.[^22]
Cursor Enterprise does offer SSO + SCIM integration, role-based access, admin analytics, and centralized enforcement of Privacy Mode. Privacy Mode routes code to zero-retention replicas. Providers do not store or train on inputs. Team-level enforcement is verified every five minutes.[^23][^24]
MCP Governance as an Emerging Layer
For organizations deploying Model Context Protocol (MCP) servers as AI tool extensions, a centralized MCP gateway architecture provides a governance chokepoint: all AI agents (Claude Desktop, Cursor, etc.) connect to an internally managed MCP gateway that proxies to downstream servers, applying per-user OAuth, DLP, rate control, and audit logging at the boundary. Private MCP registries vetted by the security team, with version-pinned approved servers, prevent knowledge workers from installing arbitrary MCP servers that could exfiltrate data.[^25]
Vercel Deployment Governance
The Access Model
Vercel Teams supports SAML SSO with any SAML 2.0 IdP (Okta, Auth0, etc.). SAML enforcement, where team members cannot access any team information without an active SAML session, is available to Enterprise plan customers. Standard Protection (protecting preview deployments) is available on Pro. SSO protection on deployments (restricting preview access to SSO-authenticated team members) requires Enterprise.[^26][^27]
Vercel also supports team-level Deployment Protection defaults. Setting "All Deployments" as the default ensures new projects inherit protection immediately, with no per-project decision required by the knowledge worker. This is the right default for a governance program where developers should not need to think about protecting their deployments.[^28]
PR Preview Deployments as a Review Gate
Every pull request to a Vercel-connected repository automatically generates a unique, protected preview URL. This creates a natural review gate for knowledge worker output: the PR author cannot promote their changes to production independently. Reviewers (technical leads, platform engineers, or designated approvers) inspect the live preview environment before the PR merges.[^29][^30]
The promotion path is explicit:
- Knowledge worker opens a PR. Vercel automatically builds a preview deployment at a protected URL.
- Reviewers access the preview (protected by Vercel Auth or SSO, depending on plan) and test.
- CI/CD runs automated checks (E2E tests against the preview URL are possible via the
vercel-preview-url+github-action-await-vercelaction pattern).[^30] - On merge to main, Vercel deploys to production.
- For staged rollouts: use
vercel promote <deployment-url>to promote a specific preview to production without triggering a rebuild.[^31][^32]
This workflow makes the PR the mandatory governance gate. Platform teams can reinforce it with required status checks (CI must pass) and CODEOWNERS requiring approval from designated technical reviewers.
Vercel to GCP Backend: OIDC Federation (No Static Keys)
Vercel's OIDC Federation eliminates the need to store long-lived GCP service account keys as environment variables. The mechanism:[^33]
- Vercel automatically generates an OIDC token for each build (
VERCEL_OIDC_TOKENenv var) and each function invocation (x-vercel-oidc-tokenrequest header). - The token is scoped to the Vercel team, project, and environment.
- GCP's Workload Identity Federation trusts Vercel's OIDC issuer and exchanges the short-lived token for a GCP service account credential.
The full GCP-side configuration:
# 1. Create Workload Identity Pool
gcloud iam workload-identity-pools create "vercel-pool" \
--project="my-gcp-project" \
--location="global" \
--display-name="Vercel OIDC Pool"
# 2. Add OIDC provider (Team issuer mode recommended)
gcloud iam workload-identity-pools providers create-oidc "vercel-provider" \
--project="my-gcp-project" \
--location="global" \
--workload-identity-pool="vercel-pool" \
--issuer-uri="https://oidc.vercel.com/YOUR_TEAM_SLUG" \
--allowed-audiences="https://vercel.com/YOUR_TEAM_SLUG" \
--attribute-mapping="google.subject=assertion.sub"
# 3. Bind to a service account scoped to specific Vercel project+environment
gcloud iam service-accounts add-iam-policy-binding \
[email protected] \
--role="roles/iam.workloadIdentityUser" \
--member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/\
workloadIdentityPools/vercel-pool/subject/\
owner:YOUR_TEAM_SLUG:project:YOUR_PROJECT:environment:production"
The application code in a Vercel function then uses:
import { getVercelOidcToken } from '@vercel/oidc';
import { ExternalAccountClient } from 'google-auth-library';
const authClient = ExternalAccountClient.fromJSON({
type: 'external_account',
audience: `//iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/\
workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_POOL_ID}/providers/${GCP_WORKLOAD_IDENTITY_POOL_PROVIDER_ID}`,
subject_token_type: 'urn:ietf:params:oauth:token-type:jwt',
token_url: 'https://sts.googleapis.com/v1/token',
service_account_impersonation_url: `https://iamcredentials.googleapis.com/v1/projects/-/\
serviceAccounts/${GCP_SERVICE_ACCOUNT_EMAIL}:generateAccessToken`,
subject_token_supplier: { getSubjectToken: getVercelOidcToken },
});
This client can then invoke IAP-protected Cloud Run services by requesting an ID token targeted at IAP's OAuth client ID.[^34][^35]
Practical Limits of Vercel for Knowledge Worker GCP Apps
Vercel's architecture is optimized for stateless, short-lived frontend + serverless API applications. For knowledge worker tools that interact with GCP backends (Cloud Run, Cloud SQL), Vercel works well for:[^36]
- CRUD-style APIs with sub-60-second execution
- Next.js frontends that call Cloud Run microservices via OIDC-authenticated fetch
- Lightweight data display and form submission
Vercel becomes constraining when knowledge worker apps need:[^37][^36]
- Background jobs: No persistent processes. Jobs that outlive the function duration ceiling (300 seconds by default and 800 seconds maximum on Pro with Fluid compute, as of the 2026-08 docs) must be offloaded to Cloud Run directly.
- WebSockets: No native support. Real-time collaboration tools cannot run their WebSocket server on Vercel.
- Stateful services: No persistent disk. Database connections must go to external Cloud SQL.
- Full-stack preview environments: Vercel preview deployments cover the frontend and Vercel functions only. They do not spin up isolated Cloud SQL or Cloud Run instances per branch. Knowledge workers testing against shared backend environments introduces state contamination risk.
- Custom runtimes: Limited language support in serverless functions compared to a container-based Cloud Run service.
The practical pattern for knowledge worker apps: Vercel hosts the frontend and lightweight API routes; Cloud Run hosts business logic that outlives the function ceiling, needs persistent connections, or needs custom runtime dependencies. The OIDC bridge connects them.
GCP Access for Knowledge Workers
Workload Identity Federation for GitHub Actions
The core challenge: knowledge worker repositories need GitHub Actions for CI/CD (testing, building container images, deploying to Cloud Run), but those pipelines should not contain static service account keys in GitHub secrets. A leaked key in a knowledge worker repository carries the same blast radius as a leaked engineering key.
Workload Identity Federation (WIF) eliminates stored keys entirely. The authentication flow:
- GitHub Actions requests a short-lived OIDC token from GitHub's identity provider.
- The token (a signed JWT) is sent to GCP's Security Token Service.
- GCP validates the token against the Workload Identity Pool configuration.
- GCP issues a short-lived access token for the designated service account.
- The workflow uses this token to deploy to Cloud Run.[^38][^39]
The platform engineering team configures the WIF pool and provider once, then non-engineers reference the pre-provisioned workload_identity_provider value in their workflow:
# .github/workflows/deploy.yml
name: Deploy to Cloud Run
on:
push:
branches: [main]
permissions:
contents: read
id-token: write # Required for OIDC token generation
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Authenticate to GCP
uses: google-github-actions/auth@v2
with:
# Platform team provisions this value; non-engineer just pastes it in
workload_identity_provider: "projects/PROJECT_NUMBER/locations/global/\
workloadIdentityPools/github-pool/providers/github-provider"
service_account: "[email protected]"
- name: Deploy to Cloud Run
run: |
gcloud run deploy my-app \
--source . \
--region us-central1 \
--service-account [email protected]
The key security control is the WIF provider's --attribute-condition, which restricts token acceptance to the specific GitHub organization (and optionally specific repositories):[^38]
gcloud iam workload-identity-pools providers create-oidc "github-provider" \
--workload-identity-pool="github-pool" \
--issuer-uri="https://token.actions.githubusercontent.com" \
--attribute-mapping="google.subject=assertion.sub,\
attribute.repository=assertion.repository,\
attribute.repository_owner=assertion.repository_owner" \
--attribute-condition="assertion.repository_owner == 'my-org'"
Per-repo service account binding further restricts access so a knowledge worker repository can only deploy to its own Cloud Run service, not any other resource in the project:[^38]
gcloud iam service-accounts add-iam-policy-binding \
[email protected] \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/\
workloadIdentityPools/github-pool/attribute.repository/my-org/my-repo"
IAP on Cloud Run: Direct Protection
Identity-Aware Proxy can now be enabled directly on a Cloud Run service, securing traffic routed through IAP from default run.app URLs and load balancers. That removes the older requirement to put every Cloud Run service behind an external HTTPS load balancer purely to use IAP.[^40][^41]
gcloud beta run deploy my-internal-app \
--image=gcr.io/my-project/my-app:latest \
--region=us-central1 \
--no-allow-unauthenticated \
--iap \
[email protected]
After enablement, grant the IAP service account the invoker role and grant user/group access via IAM:[^42][^43]
# Grant IAP SA permission to invoke the service
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:[email protected]" \
--role="roles/run.invoker"
# Grant a Google Group access to the IAP-protected service
gcloud iap web add-iam-policy-binding \
--resource-type=backend-services \
--service=my-app-backend \
--member="group:[email protected]" \
--role="roles/iap.httpsResourceAccessor"
IAP supports Workforce Identity Federation, meaning access can be governed by the same organizational IdP used for GitHub and Vercel. That is what closes the identity loop across the entire stack.[^40]
Least-Privilege Role Design for Knowledge Workers
The principle of least privilege for knowledge worker GCP access: grant exactly the permissions needed for their application to function, and nothing more.[^44][^45]
Table 2. Recommended IAM roles for knowledge worker GCP access.
| Identity | Role(s) | Rationale |
|---|---|---|
| Knowledge worker developer (human) | roles/run.developer, roles/logging.viewer, roles/cloudsql.client, roles/monitoring.viewer |
Deploy and observe their app; no project-wide admin |
| App runtime service account | Custom: Cloud Run invoker target only | Only needs to be invoked by IAP; no other GCP permissions |
| CI/CD deploy service account (via WIF) | roles/run.admin (scoped to specific service), roles/artifactregistry.writer, roles/cloudbuild.builds.builder |
Deploy and push images only |
| Knowledge worker (must NOT have) | roles/editor, roles/owner, roles/iam.securityAdmin |
Prevents privilege escalation, project-wide changes |
The Cloud Run default service account carries roles/editor at project scope. Override this with a dedicated, minimal service account in all production deployments.[^45]
The Full Governed Path End-to-End
Architecture Overview
The complete governed path for a knowledge worker building an internal tool:
HRIS (Workday/BambooHR)
│ Lifecycle event (new hire, transfer, termination)
▼
Identity Provider (Okta / Entra ID)
│ SCIM 2.0 provisioning
│ - Creates managed user account
│ - Assigns GitHub team membership via group push
│ - Assigns Vercel team membership (SAML)
▼
GitHub Enterprise Managed Users (EMU)
│ - Org membership controlled by IdP
│ - Repo access via team assignment (not individual grants)
│ - Branch protection + CODEOWNERS enforced
│
├── .github/copilot-instructions.md ← Engineering standards encoded for AI
├── .cursor/rules/ ← Cursor-specific AI instructions
│
▼ (Knowledge worker creates code with AI assistance)
GitHub Pull Request
│ - AI code review (Copilot code review, CodeRabbit, etc.)
│ - Secret scanning + push protection
│ - Branch protection: required reviews, passing CI
▼
Vercel (Preview Deployment)
│ - Auto-deployed on PR open
│ - Protected by Vercel Auth (SSO on Enterprise)
│ - Reviewers inspect live preview
│ - E2E tests against preview URL (GitHub Actions)
▼ (PR approved + merged)
Vercel (Production Deployment)
│ - Deployed to production domain
│ - OIDC token → GCP Workload Identity Federation
│ - No stored GCP service account keys
▼
GCP Cloud Run (Application Backend)
│ - IAP-protected directly on Cloud Run
│ - Identity: same Google Workspace / Workforce IdP as HRIS chain
│ - Least-privilege service account
│ - Cloud SQL (private VPC or connector)
▼
IAP Authorization Check
│ - Validates user identity against Google Group
│ - Group membership managed by IdP provisioning
└── Access granted / denied
Platform Engineering and Golden Paths
The "golden path" concept from platform engineering applies directly here: a preconfigured, end-to-end workflow that abstracts infrastructure complexity and allows developers, including non-engineers, to build and deploy software without understanding the underlying systems. The key is that following the golden path must be easier than building outside it.[^46][^47]
For knowledge worker programs, the golden path deliverables from the platform team are:
- Repository template: Pre-populated with
.github/copilot-instructions.md,.cursor/rules/, GitHub Actions workflows (including the WIF auth action pre-configured), and Vercel integration - Okta/Entra group structure: Predefined groups (e.g.,
github-knowledge-workers,cloud-run-knowledge-worker-apps) that map to appropriate repo permissions and GCP IAM roles - WIF pool and provider: Pre-provisioned; non-engineers reference the pool name in their workflow
- Cloud Run service account: Standard least-privilege SA that knowledge worker apps use at runtime
- Copilot organization instructions: Authored by platform/security engineering, applied globally[^48][^49]
Backstage is the most established open-source framework for delivering these as self-service scaffolding templates. A Backstage Software Template can create a new knowledge worker app repository with all of the above pre-configured in a single form submission, removing all infrastructure decisions from the knowledge worker's path.[^48][^49]
Platform engineering surveys consistently show the same adoption problem: without incentives, golden paths compete with whatever is fastest in the moment. Shadow platforms continue to thrive because developers, including knowledge workers, take the path of least resistance. The platform must be demonstrably easier to use than alternatives.[^50]
Shadow IT: The Risk Baseline
Without a governed path, the knowledge worker development pattern defaults to shadow IT. The data on this is unambiguous:
- Shadow IT accounts for 30-40% of IT spending in large enterprises.[^52]
- 71% of office workers admit using AI tools without IT approval.[^53]
- Nearly 20% of businesses have experienced data breaches or leaks due to unauthorized AI use.[^53]
- Shadow AI data breaches average $670K.[^53]
The specific risk profile for knowledge worker-built applications: they often handle real business data (sales pipelines, customer records, HR data) while being deployed to personal Vercel accounts with no SSO, stored with GCP service account keys in GitHub secrets, and connected to databases using shared credentials. The governed path described in this article eliminates each of these risks systematically.
Regulatory and Audit Context
SOC 2 Access Control Criteria
HRIS-linked GitHub access provisioning directly addresses SOC 2 Trust Services Criteria CC6.1 and CC6.2:
- CC6.1 (Logical and physical access controls): HRIS-driven SCIM provisioning demonstrates that access is granted based on an authoritative source of truth (employment status and role), not ad hoc IT decisions.[^54]
- CC6.2 (User access reviews): Automated provisioning/deprovisioning provides the evidence base for access reviews. Auditors expect:[^55][^56]
- Quarterly access reviews for critical systems (quarterly for GitHub is standard)
- Exported reports showing user list + permissions at review time
- Provisioning and deprovisioning records with timestamps and approvals
- Evidence that terminated users were deprovisioned promptly (HRIS termination event to SCIM disable timestamp)
The GitHub-specific configuration checklist for SOC 2 includes branch protection rules (requiring PR approvals before merge), organization-wide MFA enforcement, CODEOWNERS for sensitive directories, audit log export, and least-privilege access grants.[^57][^58]
Automated compliance platforms (e.g., Comp AI, Vanta, Drata) integrate with HRIS systems, Okta, GCP, and GitHub to collect this evidence automatically. When an auditor requests user access reports or provisioning logs, the system generates them on demand.[^59]
AI-Generated Code and Audit Trails
SOC 2 auditors evaluating change management controls do not yet have explicit AI-specific guidance from AICPA; ISACA's practitioner writing covers change management for AI risk in general terms.[^60] The defensible position, in my reading: auditors are not evaluating who approves, human or AI. They evaluate whether the control objective is met: accountability, traceability, and effective oversight. AI can participate in change review, but final authority and responsibility must remain explicitly human-owned, with clear audit trails and monitoring of the AI itself as a control component.
Corrected 2026-09-23: an earlier version presented this paragraph as a quotation from an ISACA Journal article that does not exist.
In practice, this means:
- Human sign-off remains mandatory: A knowledge worker + AI assistant produces a PR; a human engineer approves that PR. The PR approval is the control evidence.
- Audit trail of AI involvement: The commit history shows AI-generated code (Copilot attributions, commit messages). Document in your change management policy how AI is used and what human oversight exists.
- Compensating controls: Copilot secret scanning, automated SAST (CodeQL, Semgrep) in CI, and Copilot code review all provide evidence that AI-produced code was subject to automated review before human approval.
For regulated industries (financial services, healthcare), the emerging standard for AI code governance is a seven-stage approval pipeline:[^61]
- AI generation
- Automated vulnerability scan
- AI code review
- Human author review
- Designated human approver review
- Automated deployment gates (tests passing)
- Production deployment with rollback capability
Knowledge worker programs should document which stages are in place and what compensating controls cover any gaps.
Emerging Regulatory Requirements
Emerging regulatory obligations are moving toward provenance requirements for AI-generated content. California AB 2013 (effective January 2026) requires AI system developers to disclose training data sources and document AI content generation. While currently targeted at AI system developers rather than AI system users, the trajectory points toward disclosure and audit trail requirements for AI-generated artifacts entering production systems.[^62]
For immutable audit trail requirements, the architecture described in regulatory ML literature is relevant: capturing lineage metadata at runtime (timestamp, model version, input data, triggered policy rule, rationale) in an append-only log tied to the production deployment record. Pair this with GitHub's audit log export (available on Enterprise) for a complete paper trail from identity to code creation to review to deployment.[^63]
Implementation Gaps and Open Questions
Several gaps deserve explicit documentation for practitioners building this stack.
Cursor centralized rule push: Cursor Enterprise does not support admin-pushed rule files. The Git-committed .cursor/rules/ pattern is the practical substitute, but developers can modify these files locally. Until Cursor builds a server-side governance layer, organizations with hard compliance requirements should combine Git rules with CI validation (a CI step that verifies the rules directory has not been modified from the org template) and MDM-based Cursor Enterprise enrollment for privacy mode enforcement.[^22][^24]
Vercel preview environments and backend state: Preview deployments cover frontend and Vercel functions only. There is no automatic isolated Cloud SQL instance or Cloud Run service per PR branch. Knowledge worker teams testing data-mutating operations against a shared backend preview environment risk state contamination. The mitigation is either feature flags on shared-state operations or restricting preview testing to read-only operations.[^36]
GitHub to GCP identity propagation for IAP: The IAP access model uses Google account identity (Gmail, Workspace). HRIS to Okta to GitHub EMU governs GitHub access. IAP can be configured with Workforce Identity Federation to use the same Okta IdP, but this requires an additional integration step separate from the GitHub SCIM chain. Ensuring a termination event flows to both GitHub and IAP access revocation requires that both integrations are driven from the same Okta deprovisioning workflow.
Google Workspace and EMU SCIM: Google Workspace as the IdP for GitHub EMU provides only Just-in-Time (JIT) SCIM provisioning, not full automated provisioning. Organizations that use Google Workspace as their primary IdP and want full SCIM for GitHub must either introduce Okta or Entra ID as a federated IdP layer, or accept JIT-only provisioning with manual offboarding.[^4]
No public reference implementation published: Despite active community discussion, I have not found a major organization that has publicly documented a complete HRIS-to-IdP-to-GitHub-EMU-to-Vercel-to-GCP path specifically for knowledge worker developers. The closest published implementations cover subsets of this stack (Workday to Okta to downstream apps, or GitHub Actions to GCP WIF), but the end-to-end governed path for citizen developers remains an emerging practice rather than a published pattern.[^38][^11]
References
[^1]: Omada. (n.d.). Identity Lifecycle Management. Omada Identity. https://omadaidentity.com/products/functionality/lifecycle-management/
[^2]: Rippling. (n.d.). What Is an HRIS? Rippling Learn. https://www.rippling.com/glossary/hris
[^3]: BambooHR. (n.d.). HRIS: Human Resources Information System. BambooHR. https://www.bamboohr.com/resources/hr-glossary/human-resources-information-system-hris
[^4]: GitHub Docs. (n.d.). About Enterprise Managed Users. GitHub. https://docs.github.com/en/enterprise-cloud@latest/admin/identity-and-access-management/using-enterprise-managed-users-for-iam/about-enterprise-managed-users
[^5]: GitHub Changelog. (2024, September 26). Bring Your Own Identity Provider to Enterprise Managed Users (open SCIM generally available). GitHub. https://github.blog/changelog/2024-09-26-bring-your-own-identity-provider-to-enterprise-managed-users/
[^6]: GitHub Docs. (n.d.). Configuring SCIM provisioning for Enterprise Managed Users with Okta. GitHub. https://docs.github.com/en/enterprise-cloud@latest/admin/identity-and-access-management/provisioning-user-accounts-for-enterprise-managed-users/configuring-scim-provisioning-with-okta
[^7]: GitHub Docs. (n.d.). Configuring SCIM provisioning with Okta. GitHub. https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/provisioning-user-accounts-with-scim/configuring-scim-provisioning-with-okta
[^8]: GitHub Docs. (n.d.). Troubleshooting identity and access management for your enterprise. GitHub. https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/understanding-iam-for-enterprises/troubleshooting-identity-and-access-management-for-your-enterprise
[^9]: GitHub Docs. (n.d.). Username considerations for external authentication. GitHub. https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/iam-configuration-reference/username-considerations-for-external-authentication
[^10]: GitHub Docs. (n.d.). Migrating from one identity provider to another. GitHub. https://docs.github.com/en/enterprise-cloud@latest/admin/identity-and-access-management/reconfiguring-iam-for-enterprise-managed-users
[^11]: Iron Cove Solutions. (n.d.). Workday + Okta Integration Pattern. Iron Cove Solutions Blog. https://ironcovesolutions.com/blog/workday-okta-integration
[^12]: Stitchflow. (n.d.). GitHub SCIM Provisioning: Pricing and Limitations. Stitchflow. https://www.stitchflow.com/scim/github
[^13]: GitHub Docs. (n.d.). Adding organization custom instructions for GitHub Copilot. GitHub. https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/add-custom-instructions/add-organization-instructions
[^14]: GitHub Docs. (n.d.). Using Copilot Custom Instructions. GitHub. https://docs.github.com/en/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot
[^15]: GitHub Docs. (n.d.). Adding repository custom instructions for GitHub Copilot. GitHub. https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/add-custom-instructions/add-repository-instructions
[^16]: GitHub Blog. (n.d.). 5 tips for writing better custom instructions for Copilot. GitHub. https://github.blog/ai-and-ml/github-copilot/5-tips-for-writing-better-custom-instructions-for-copilot/
[^17]: GitHub Docs. (n.d.). About secret scanning. GitHub. https://docs.github.com/en/code-security/secret-scanning/introduction/about-secret-scanning
[^18]: GitHub Docs. (n.d.). AI-detected secrets (formerly Copilot secret scanning). GitHub. https://docs.github.com/en/code-security/responsible-use/security-and-quality-ai-features
[^19]: GitHub Changelog. (2024, October 21). Copilot secret scanning for generic passwords is generally available. GitHub. https://github.blog/changelog/2024-10-21-copilot-secret-scanning-for-generic-passwords-is-generally-available/
[^20]: Cursor Docs. (n.d.). Rules for AI. Cursor. https://docs.cursor.com/context/rules-for-ai
[^21]: Cursor. (n.d.). Rules. Cursor Documentation. https://cursor.com/docs/rules
[^22]: Cursor Docs. (n.d.). Ignore files. Cursor. https://docs.cursor.com/context/ignore-files
[^23]: Cursor. (n.d.). Privacy and Security. Cursor. https://www.cursor.com/privacy
[^24]: Cursor. (n.d.). Business / Enterprise. Cursor. https://www.cursor.com/business
[^25]: Anthropic. (2025). Model Context Protocol: Architecture Overview. MCP Documentation. https://modelcontextprotocol.io/docs/learn/architecture
[^26]: Vercel Docs. (n.d.). SAML Single Sign-On. Vercel. https://vercel.com/docs/security/saml
[^27]: Vercel Docs. (n.d.). Deployment Protection. Vercel. https://vercel.com/docs/security/deployment-protection
[^28]: Vercel Changelog. (2026, January 13). Set team-wide defaults for Deployment Protection. Vercel. https://vercel.com/changelog/set-team-wide-defaults-for-deployment-protection
[^29]: Vercel Docs. (n.d.). Preview Deployments. Vercel. https://vercel.com/docs/deployments/preview-deployments
[^30]: GitHub Marketplace. (n.d.). Await for Vercel Deployment. GitHub. https://github.com/marketplace/actions/await-for-vercel-deployment
[^31]: Vercel Docs. (n.d.). Instant Rollback. Vercel. https://vercel.com/docs/deployments/instant-rollback
[^32]: Vercel CLI Docs. (n.d.). vercel promote. Vercel. https://vercel.com/docs/cli/promote
[^33]: Vercel Docs. (n.d.). OIDC Federation. Vercel. https://vercel.com/docs/security/secure-backend-access/oidc
[^34]: Vercel Docs. (n.d.). Connect to Google Cloud Platform (GCP) with Vercel OIDC. Vercel. https://vercel.com/docs/oidc/gcp
[^35]: Google Cloud Docs. (n.d.). Workload Identity Federation with OIDC providers. Google Cloud. https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers
[^36]: Vercel Docs. (n.d.). Serverless Function Limits. Vercel. https://vercel.com/docs/functions/limitations
[^37]: Vercel Docs. (n.d.). Vercel Platform Limits. Vercel. https://vercel.com/docs/limits
[^38]: Google Cloud Docs. (n.d.). Workload Identity Federation: GitHub Actions. Google Cloud. https://cloud.google.com/iam/docs/workload-identity-federation-with-deployment-pipelines#github-actions
[^39]: google-github-actions/auth. (n.d.). Setting up Workload Identity Federation. GitHub. https://github.com/google-github-actions/auth#setting-up-workload-identity-federation
[^40]: Google Cloud Docs. (n.d.). Configure IAP for Cloud Run. Google Cloud. https://docs.cloud.google.com/run/docs/securing/identity-aware-proxy-cloud-run
[^41]: Google Cloud Docs. (n.d.). Enabling IAP for Cloud Run. Google Cloud. https://cloud.google.com/iap/docs/enabling-cloud-run
[^42]: Google Cloud Docs. (n.d.). Managing access to IAP-secured resources. Google Cloud. https://cloud.google.com/iap/docs/managing-access
[^43]: Google Cloud Docs. (n.d.). Configure IAP with Workforce Identity Federation. Google Cloud. https://docs.cloud.google.com/iap/docs/use-workforce-identity-federation
[^44]: Google Cloud Docs. (n.d.). Cloud Run IAM roles. Google Cloud. https://cloud.google.com/run/docs/reference/iam/roles
[^45]: Google Cloud Docs. (n.d.). Using the principle of least privilege. Google Cloud. https://cloud.google.com/iam/docs/using-iam-securely#least_privilege
[^46]: Spotify Engineering. (n.d.). How We Use Golden Paths to Solve Fragmentation in Our Software Ecosystem. Spotify Engineering Blog. https://engineering.atspotify.com/2020/08/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem/
[^47]: Humanitec. (n.d.). Vol. 56: Let's build some golden paths. Humanitec Newsletter. https://humanitec.com/newsletter/vol-56-lets-build-some-golden-paths
[^48]: Backstage.io. (n.d.). Software Templates. Backstage. https://backstage.io/docs/features/software-templates/
[^49]: Backstage.io. (n.d.). What is Backstage? Backstage. https://backstage.io/docs/overview/what-is-backstage
[^50]: platformengineering.org, sponsored by Humanitec and Gitpod. (2025). State of Platform Engineering Report, Volume 3. https://humanitec.com/whitepapers/state-of-platform-engineering-report-volume-3
[^52]: CIO. (n.d.). CIOs vastly underestimate extent of shadow IT. CIO. https://www.cio.com/article/244776/cios-vastly-underestimate-extent-of-shadow-it.html
[^53]: SaaS Alerts. (2025). Shadow AI Report. SaaS Alerts. https://www.saasalerts.com/shadow-ai-report
[^54]: AICPA. (2017, revised 2022). Trust Services Criteria, CC6.1. AICPA and CIMA. https://www.aicpa-cima.com/resources/download/2017-trust-services-criteria-with-revised-points-of-focus-2022
[^55]: Vanta. (n.d.). SOC 2 Trust Services Criteria. Vanta. https://www.vanta.com/collection/soc-2/soc-2-trust-service-criteria
[^56]: Drata. (n.d.). Trust Services Criteria for SOC 2. Drata. https://drata.com/learn/soc-2/trust-services-criteria
[^57]: GitHub Docs. (n.d.). Best practices for preventing data leaks in your organization. GitHub. https://docs.github.com/en/code-security/tutorials/secure-your-organization/prevent-data-leaks
[^58]: GitHub Docs. (n.d.). About audit log for your enterprise. GitHub. https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/about-the-audit-log-for-your-enterprise
[^59]: Comp AI. (n.d.). Automated SOC 2 Compliance for GitHub. Comp AI. https://www.comp.ai/integrations/github
[^60]: Gnana, S. (2025, August 11). Effective Change Management to Mitigate AI Risks. ISACA Now Blog. https://www.isaca.org/resources/news-and-trends/isaca-now-blog/2025/effective-change-management-to-mitigate-ai-risks
[^61]: McKinsey Digital. (2025). AI Code Governance for Financial Services. McKinsey. https://www.mckinsey.com/capabilities/mckinsey-digital/ai-code-governance
[^62]: California Legislature. (2024). AB 2013: AI Training Data Transparency. California Legislative Information. https://leginfo.legislature.ca.gov/faces/billNavClient.xhtml?bill_id=202320240AB2013
[^63]: Ojewale, V., Suresh, H., and Venkatasubramanian, S. (2026). Audit Trails for Accountability in Large Language Models. arXiv. https://arxiv.org/abs/2601.20727