PLAN 5 — Vercel-like Platform on Hosted Cloudflare Workers + GitHub Actions
Table of Contents
- Core idea
- Goals
- Non-goals
- Recommended decision
- 1. Hosted Cloudflare Workers Architecture
- 2. Cloudflare Deployment Model
- 3. Branching Strategy Recommendation
- 4. Repository Initialization Model
- 5. GitHub Repository Automation
- 6. GitHub Actions Workflows
-
7.
roguvibe.yamlv1 - 8. Automatic Hostnames and Domains
- 9. Secrets and Environment Variables
- 10. AI Agent Skill Model
- 11. Rollback Model
- 12. Observability and Status
- 13. Implementation Phases
- 14. Risks and Mitigations
- 15. Recommended MVP Scope
- 16. Final Recommendation
- 17. Primary references
Core idea
Build the same user-facing product as PLAN 4: a Vercel-like
deployment platform for generated TypeScript sites/apps/tools
with Git-based deployment, roguvibe.yaml, automatic
URLs, logs, rollback, and generic Cloudflare Worker runtime
configuration.
The implementation changes:
PLAN 4: generated app → platform build → self-hosted Cloudflare workerd runtime pool
PLAN 5: generated app → GitHub Actions CI/CD → platform deploy layer → Cloudflare hosted Workers
Users should not need to understand Cloudflare Workers, Wrangler, dispatch namespaces, routes, assets, compatibility dates, or API tokens. The platform should expose simple concepts:
Project
Environment: development | production
Deployment
URL
Logs
Rollback
Internally, the platform uses Cloudflare hosted Workers, which are powered by Cloudflare's managed V8 isolate runtime.
Goals
- Provide a Vercel-like deployment experience for generated TypeScript apps/sites/tools.
-
Use Cloudflare hosted Workers as the runtime instead of
self-hosting
workerd. - Use GitHub repositories as the source of truth for vibe-coded app code.
- Use GitHub Actions hosted runners to execute CI/CD pipelines.
- Provide a simple branching model for non-engineering users and AI agents.
- Initialize each project repo locally and in GitHub with required branches, workflows, manifest, and agent instructions.
- Hide Cloudflare-specific deployment details behind a platform CLI/API.
-
Keep
roguvibe.yamlsimple and free of infrastructure knobs like memory request/limit. - Support development and production deployments.
- Make the repo lifecycle manageable by AI skills: initialize, change, deploy to development, promote to production, rollback.
Non-goals
-
Do not build or operate a self-hosted Cloudflare
workerdruntime pool. - Do not expose raw Cloudflare Worker concepts as the primary user interface.
- Do not require non-engineering users to use Git directly.
- Do not support arbitrary Docker apps in this runtime tier.
- Do not initially support languages beyond TypeScript/JavaScript.
- Do not put Cloudflare account API tokens into user-owned generated app repos unless there is no platform-token alternative.
-
Do not include memory request/limit fields in
roguvibe.yaml.
Recommended decision
Runtime implementation
Use Cloudflare hosted Workers.
Cloudflare becomes responsible for:
- V8 isolate runtime operation.
- Worker execution.
- Global edge placement.
- Runtime patching.
- Worker versions/deployments.
- Static asset support through Workers Static Assets where applicable.
- Custom domains/routes.
The platform remains responsible for:
- Project/repo initialization.
roguvibe.yamlschema.- Build conventions.
- Compatibility validation.
- Environment mapping.
- Cloudflare deployment abstraction.
- Domain naming policy.
- Deployment registry.
- Logs/status UI.
- Rollback orchestration.
- AI-agent-safe Git workflow.
Deployment abstraction
Create a platform deploy layer with a stable interface:
roguvibe deploy --environment development --commit "$GITHUB_SHA"
roguvibe deploy --environment production --commit "$GITHUB_SHA"
roguvibe validate
roguvibe status --environment production
roguvibe rollback --environment production --to <deployment-id>
GitHub Actions should call this CLI. The CLI talks to the platform API. The platform API owns Cloudflare credentials and chooses the internal deployment adapter.
Do not make generated repos call raw
wrangler deploy directly as the main interface.
Raw Wrangler can exist as an implementation detail or
fallback.
Cloudflare deployment adapter path
Use an adapter boundary from day one:
GitHub Actions runner
→ roguvibe CLI
→ Platform Deploy API
→ Cloudflare Deploy Adapter
→ MVP adapter: per-project/per-environment Worker
→ Scale adapter: Workers for Platforms dispatch namespace
Recommended implementation sequence:
- MVP: one Cloudflare Worker per project environment.
- Scale path: migrate internal deploy adapter to Workers for Platforms dispatch namespaces when project count, routing, or multi-tenant management justify it.
This keeps the product API stable while avoiding early Workers for Platforms complexity.
1. Hosted Cloudflare Workers Architecture
1.1 High-level architecture
User / AI agent
↓
Generated TypeScript app repo on GitHub
↓ push / PR / promotion
GitHub Actions hosted runner
↓
install + validate + test + build
↓
roguvibe CLI
↓
Platform Deploy API
↓
Cloudflare Deploy Adapter
↓
Cloudflare hosted Workers
↓
<repo-name>--<project-id>-dev.sirogu.com
<repo-name>--<project-id>.sirogu.com
1.2 Core components
Project initializer
Creates a local repo and matching GitHub repo with:
developmentbranch.productionbranch.roguvibe.yaml.- TypeScript app template.
- package scripts.
- GitHub Actions workflows.
- GitHub Environments.
- repo secrets/variables.
- branch protection.
AGENTS.mdinstructions for AI agents.-
.roguvibe/project.jsonmachine-readable project metadata.
Manifest validator
Validates roguvibe.yaml before deploy.
Responsibilities:
- Enforce required fields.
- Enforce supported app types.
- Enforce supported build output.
- Reject unsupported resource knobs.
- Resolve automatic hostname and route metadata from repo name, project ID, and environment.
- Produce a normalized deployment plan for the platform API.
Build adapter
Runs inside GitHub Actions.
Responsibilities:
- Install dependencies.
- Run tests/lint if configured.
- Run build command.
- Bundle server entrypoint into Worker-compatible ESM.
- Prepare static assets.
- Generate a deploy artifact manifest.
Platform Deploy API
Central control plane for deployments.
Responsibilities:
- Authenticate GitHub Actions deploy requests.
- Verify repo/project/environment mapping.
- Store deployment metadata.
- Call Cloudflare deploy adapter.
- Configure domains/routes.
- Store environment config.
- Record deployment status.
- Support rollback.
Cloudflare Deploy Adapter
Encapsulates Cloudflare implementation details.
Responsibilities:
- Create/update Workers.
- Upload Worker code/assets.
- Manage custom domains/routes.
- Manage Worker secrets/bindings.
- Roll back to previous Worker version/deployment.
- Fetch logs/status where supported.
2. Cloudflare Deployment Model
2.1 MVP model: one Worker per project environment
Each project gets two Cloudflare Worker services:
roguvibe-<project-id>-development
roguvibe-<project-id>-production
Branch mapping:
development branch → development environment → roguvibe-<project-id>-development
production branch → production environment → roguvibe-<project-id>-production
Hostnames:
<repo-name>--<project-id>-dev.sirogu.com → development Worker
<repo-name>--<project-id>.sirogu.com → production Worker
Strengths:
- Simple mental model.
- Easy to debug in Cloudflare dashboard.
- Easy to map one environment to one Worker.
-
Works well with
wrangler deploy --envor Cloudflare API. - Fastest path to MVP.
Weaknesses:
- Many Workers over time.
- More route/domain objects to manage.
- Cloudflare account limits and naming limits must be watched.
- Cross-project shared routing and policy are harder than with a central dispatcher.
Decision:
Use this for MVP unless Cloudflare account/product constraints make Workers for Platforms immediately necessary.
2.2 Scale model: Workers for Platforms dispatch namespace
For a larger multi-tenant platform, use Cloudflare Workers for Platforms:
Wildcard/custom domain route
↓
Platform dispatcher Worker
↓
Dispatch namespace
↓
User Worker script for project/environment/version
Conceptual mapping:
Host: <repo-name>--<project-id>.sirogu.com
→ dispatcher reads host
→ lookup project-id + environment in platform registry
→ dispatch to user Worker in namespace
Strengths:
- Better fit for a platform deploying code on behalf of many projects.
- Centralized dispatch/routing logic.
- Fewer top-level Worker services.
- Easier to implement platform-level policies.
- Better long-term abstraction for many user apps/tools.
Weaknesses:
- More Cloudflare-specific architecture.
- More complex local testing.
- More custom deploy code.
- Requires validating product limits, pricing, and account availability.
Decision:
Design the platform deploy layer so the MVP adapter can be replaced by a Workers for Platforms adapter without changing generated repos.
2.3 Static assets
Use Cloudflare Workers Static Assets for new static/full-stack projects when the project shape fits.
Recommended mapping:
build.output.server → Worker module entrypoint
build.output.assets → Workers Static Assets directory
For full-stack apps:
- Worker handles API/server routes.
- Static assets are served through the Worker assets binding.
- SPA fallback can use Cloudflare asset not-found handling.
3. Branching Strategy Recommendation
3.1 Recommended strategy: two environment branches + short-lived AI branches
Use a simple environment-branch model:
development = default branch, development environment
production = protected branch, production environment
ai/<task> = short-lived AI implementation branch
This is intentionally simpler than GitFlow and more explicit than trunk-based deployment for non-engineering users.
Why this model
Non-engineering users think in environments, not Git concepts:
"test it" → development
"publish it" → production
The branch model should match that language:
push/merge to development → deploy development
merge to production → deploy production
AI agents can manage this reliably because the rules are deterministic.
3.2 Branch responsibilities
development
Purpose:
- Default working branch.
- Latest tested development state.
- Auto-deploys to development URL.
Rules:
- Default branch in GitHub.
-
AI changes land here through PRs from
ai/<task>branches. - Direct pushes may be allowed only for the platform machine user during bootstrap or emergency repair.
- Every push triggers development deployment.
production
Purpose:
- Production source of truth.
- Auto-deploys to production URL.
Rules:
- Protected branch.
- No direct pushes.
-
Only updated by promotion from
development. - Requires successful validation/build checks.
- Optional manual approval through GitHub Environment protection.
- Every push triggers production deployment.
ai/<task>
Purpose:
- Safe workspace for AI agent changes.
Rules:
- Created by AI skills.
- Branches from
development. - PR target is
development. - Deleted after merge.
- Never deploys to production.
Example names:
ai/add-login-page
ai/fix-dashboard-filter
ai/update-backend-config
3.3 Deployment flow
Development deploy
AI/user requests change
↓
AI creates ai/<task> from development
↓
AI edits code
↓
AI opens PR to development
↓
validation workflow passes
↓
AI merges PR to development
↓
GitHub Actions deploys development
↓
user reviews development URL
For very low-risk generated changes, the platform may allow AI
to commit directly to development, but the
default should be PR-based.
Production promotion
User says "publish" / "release to production"
↓
AI verifies development deployment is healthy
↓
AI opens PR: development → production
↓
production validation passes
↓
AI merges PR after approval policy is satisfied
↓
GitHub Actions deploys production
↓
platform records production deployment
This gives a clean audit trail: production is exactly the code merged from development.
3.4 Why not GitFlow
Avoid classic GitFlow with develop,
release/*, hotfix/*, and version
branches.
Reasons:
- Too many branch concepts for non-engineering users.
- Too much ceremony for generated apps/sites/tools.
- Harder for AI agents to explain and recover from mistakes.
- Most projects only need development and production.
3.5 Why not single-branch trunk-only
Single-branch trunk deployment is simple for experienced engineers, but less ideal here.
Problems:
- Non-engineering users need a clear separation between "try it" and "publish it".
- AI agents need a safe place to land changes before production.
- Production promotion should be explicit.
Trunk-based can be revisited later for advanced users.
4. Repository Initialization Model
4.1 Required initializer
Create a platform command:
roguvibe project init <project-name>
Inputs:
project name
GitHub owner/org
app type: site | app | tool
non-sensitive Worker env vars
secret names required by the app
Outputs:
local git repo
GitHub repo
initialized branches
workflow files
roguvibe.yaml
project metadata
platform registry record
Cloudflare deployment placeholders
4.2 Repository structure
Recommended generated repo:
.
├── .github/
│ └── workflows/
│ ├── validate.yml
│ └── deploy.yml
├── .roguvibe/
│ ├── project.json
│ └── branch-policy.md
├── src/
│ └── index.ts
├── public/
├── AGENTS.md
├── roguvibe.yaml
├── package.json
├── package-lock.json
├── tsconfig.json
└── README.md
4.3 .roguvibe/project.json
Machine-readable metadata for AI agents and workflows:
{
"version": 1,
"projectId": "p_abc123",
"appName": "request-dashboard",
"platform": "roguvibe",
"manifest": "roguvibe.yaml",
"branches": {
"development": "development",
"production": "production"
},
"environments": {
"development": {
"url": "https://request-dashboard--p-abc123-dev.sirogu.com"
},
"production": {
"url": "https://request-dashboard--p-abc123.sirogu.com"
}
}
}
This file should not contain secrets.
4.4 AGENTS.md
Each repo should include explicit AI operating rules:
# AI Agent Instructions
## Branches
- Use `development` for development deployments.
- Use `production` only for production releases.
- Create task branches as `ai/<short-task-name>` from `development`.
- Never commit directly to `production`.
- Promote by opening a PR from `development` to `production`.
## Commands
- Validate: `npm run validate`
- Test: `npm test`
- Build: `npm run build`
- Platform validation: `npx roguvibe validate`
## Deployment
- Pushing to `development` deploys development.
- Merging to `production` deploys production.
- Do not edit `.github/workflows/*` unless the task explicitly asks for CI/CD changes.
- Do not add Cloudflare secrets to the repo.
5. GitHub Repository Automation
5.2 Initialization sequence
1. Platform receives create-project request.
2. Platform creates local scaffold from template.
3. Platform initializes git repo.
4. Platform commits initial files.
5. Platform creates GitHub repo with shared machine user/PAT.
6. Platform pushes `development` branch.
7. Platform creates `production` branch from the same initial commit.
8. Platform sets default branch to `development`.
9. Platform creates GitHub Environments: development, production.
10. Platform creates repo variables: ROGUVIBE_PROJECT_ID, ROGUVIBE_API_URL.
11. Platform creates environment secret: ROGUVIBE_DEPLOY_TOKEN.
12. Platform configures branch protection.
13. Platform registers project in platform DB.
14. Platform provisions Cloudflare Worker placeholders or dispatch namespace mapping.
15. Platform triggers first development deployment.
5.3 Branch protection
Recommended rules:
development
- Require status checks for PR merges.
- Require branch to be up to date before merge where practical.
- Allow direct pushes only by platform machine user during bootstrap.
- Delete AI branches after merge.
production
- Require pull request before merge.
-
Require status checks:
- manifest validation.
- TypeScript check.
- build.
- platform compatibility check.
- Require linear history.
- Restrict who can push.
- Optional: require deployment approval through GitHub Environment protection.
5.4 GitHub Environments
Create two GitHub Environments:
development
production
Use them for:
- Environment-specific secrets.
- Deployment history in GitHub UI.
- Optional production approval.
- Environment-specific URLs.
Recommended secret strategy:
Repository/environment contains only ROGUVIBE_DEPLOY_TOKEN.
Cloudflare API token stays in platform secret manager.
Avoid putting these in generated app repos:
CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_ID
Cloudflare zone tokens
backend admin/root credentials
API keys
database passwords
bearer tokens
6. GitHub Actions Workflows
6.1 Validation workflow
.github/workflows/validate.yml:
name: Validate
on:
pull_request:
branches:
- development
- production
workflow_dispatch:
permissions:
contents: read
jobs:
validate:
runs-on: tke-fe-small-runner
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run typecheck --if-present
- run: npm test --if-present
- run: npm run build
- run: npx roguvibe validate
6.2 Deployment workflow
.github/workflows/deploy.yml:
name: Deploy
on:
push:
branches:
- development
- production
workflow_dispatch:
inputs:
environment:
description: Environment to deploy
required: true
type: choice
options:
- development
- production
permissions:
contents: read
deployments: write
concurrency:
group: deploy-${{ github.ref_name }}
cancel-in-progress: false
jobs:
resolve:
runs-on: tke-fe-small-runner
outputs:
environment: ${{ steps.env.outputs.environment }}
steps:
- id: env
shell: bash
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "environment=${{ inputs.environment }}" >> "$GITHUB_OUTPUT"
elif [ "${{ github.ref_name }}" = "production" ]; then
echo "environment=production" >> "$GITHUB_OUTPUT"
else
echo "environment=development" >> "$GITHUB_OUTPUT"
fi
deploy:
needs: resolve
runs-on: tke-fe-small-runner
timeout-minutes: 30
environment: ${{ needs.resolve.outputs.environment }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build
- run: npx roguvibe validate
- name: Deploy through RoguVibe
env:
ROGUVIBE_API_URL: ${{ vars.ROGUVIBE_API_URL }}
ROGUVIBE_PROJECT_ID: ${{ vars.ROGUVIBE_PROJECT_ID }}
ROGUVIBE_DEPLOY_TOKEN: ${{ secrets.ROGUVIBE_DEPLOY_TOKEN }}
ROGUVIBE_ENVIRONMENT: ${{ needs.resolve.outputs.environment }}
run: |
npx roguvibe deploy \
--project "$ROGUVIBE_PROJECT_ID" \
--environment "$ROGUVIBE_ENVIRONMENT" \
--commit "$GITHUB_SHA"
6.3 Why the workflow calls roguvibe deploy
This keeps generated repos stable even if the Cloudflare implementation changes:
Today: roguvibe deploy → per-environment Worker
Later: roguvibe deploy → Workers for Platforms dispatch namespace
Generated repos do not need to change.
7. roguvibe.yaml v1
7.1 Recommended manifest
version: 1
app:
name: request-dashboard
type: app
source:
entrypoint: src/index.ts
assets: public
build:
command: npm run build
output:
server: dist/worker.js
assets: dist/public
env:
vars:
API_BASE_URL:
development: https://api-dev.example.com
production: https://api.example.com
FEATURE_FLAG_EXAMPLE:
development: "true"
production: "false"
secrets:
- BACKEND_API_KEY
- DB_USERNAME
- DB_PASSWORD
7.2 Cloudflare Worker environment variable model
Use roguvibe.yaml as the platform-level abstraction
for Cloudflare Worker environment configuration.
The manifest can define:
-
env.vars: non-sensitive text/JSON values safe to commit to Git. -
env.secrets: secret names only. Values are never stored in Git.
This mirrors Cloudflare Workers' distinction between environment variables and secrets:
-
plain environment variables are available to the Worker
through
env.<NAME>and may be stored as configuration; -
secrets are sensitive values exposed to the Worker through the
same
env.<NAME>interface but must be stored securely outside the repo.
Example Worker usage:
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const response = await fetch(`${env.API_BASE_URL}/health`, {
headers: {
Authorization: `Bearer ${env.BACKEND_API_KEY}`,
},
});
return response;
},
};
7.3 Backend configuration boundary
Backend provisioning and database/backend product selection are out of scope for this plan. Another workstream owns that research and discovery.
This platform only needs to ensure deployed Cloudflare Worker
apps can receive and use backend connection configuration
through the generic env.vars /
env.secrets model. Examples:
API_BASE_URL → env.vars
BACKEND_API_KEY → env.secrets
DB_HOST → env.vars or env.secrets depending on sensitivity
DB_USERNAME → env.secrets
DB_PASSWORD → env.secrets
For HTTP backends, generated apps can use standard
fetch. For direct TCP backends, validate Cloudflare
Workers connect() support and product limits before
committing to a template.
7.4 Secret safety rules
Vibe coders and AI agents must not push secret values to Git.
Rules:
-
env.varsmay contain only non-sensitive values. -
env.secretsmay contain only secret names, never secret values. -
Secret values must be written through platform UI/API/CLI, not
by editing
roguvibe.yaml. - The platform stores secret values in its secret manager.
- The Cloudflare Deploy Adapter writes secret values to Cloudflare Worker secrets during deploy.
-
Generated repos may include
.dev.vars.exampleor.env.examplewith placeholder values only. -
Generated repos must ignore local secret files such as
.dev.vars,.env, and.env.local. - CI must run secret scanning before deploy and fail if likely credentials are committed.
-
roguvibe validatemust reject suspiciousenv.varsvalues that look like credentials. - Pre-commit hooks should run the same secret scan locally where possible.
Validation heuristics:
-
Reject
env.varskeys matching sensitive names:*_KEY,*_SECRET,*_TOKEN,*_PASSWORD,*_PASS,*_USERNAME,DATABASE_URL,DB_URL. - Reject high-entropy values in
env.vars. -
Reject URL values in
env.varsthat contain credentials, such aspostgres://user:pass@host/db. -
Reject committed
.env,.dev.vars,.env.local, or similar local secret files. -
Allow only placeholder values in
*.examplefiles.
Recommended CLI flow:
roguvibe secret set BACKEND_API_KEY --environment development
roguvibe secret set DB_PASSWORD --environment production
The CLI sends secret values directly to the platform API. It
must not write them to roguvibe.yaml or commit them
to Git.
7.5 Fields intentionally not present
Do not include:
resources:
memoryMb: 128
cpu: 1
replicas: 2
Cloudflare Workers resource behavior should be handled by Cloudflare limits and platform policy, not by vibe-coder manifest fields.
7.6 Branch mapping
Branch mapping should be convention-based for MVP:
development branch → development environment
production branch → production environment
Do not require users to configure this in
roguvibe.yaml unless advanced branch mapping is
introduced later.
8. Automatic Hostnames and Domains
8.1 Hostname rule
Hostnames are always assigned automatically. There is no
hostname field in roguvibe.yaml.
Use the GitHub repository name as
<repo-name> / app name:
GitHub repo: request-dashboard
app name: request-dashboard
Development:
<repo-name>--<project-id>-dev.sirogu.com
Production:
<repo-name>--<project-id>.sirogu.com
Example:
request-dashboard--p-abc123-dev.sirogu.com
request-dashboard--p-abc123.sirogu.com
8.2 Project ID source
project-id is generated by the platform control
plane during roguvibe project init / project
creation.
Recommended source of truth:
Platform projects table: id = p_abc123
The generated ID is then written to non-secret repo metadata and GitHub variables:
.roguvibe/project.json → projectId
GitHub Actions variable → ROGUVIBE_PROJECT_ID
Platform DB → canonical project record
Rules:
- The platform DB is canonical.
-
.roguvibe/project.jsonis a checked-in convenience copy for AI agents and local tooling. -
ROGUVIBE_PROJECT_IDis used by GitHub Actions to identify the project during deploy. - The project ID should be immutable after creation.
- The project ID should be short, URL-safe, globally unique, and not derived from the repo name.
8.3 Domain routing
MVP with per-environment Workers:
<repo-name>--<project-id>-dev.sirogu.com → development Worker
<repo-name>--<project-id>.sirogu.com → production Worker
Scale model with dispatcher:
*.sirogu.com → dispatcher Worker → project/environment Worker
All generated apps are reachable through their assigned Cloudflare Worker hostname.
9. Secrets and Environment Variables
9.1 Secret ownership
There are three classes of secrets:
GitHub automation secrets
Used by GitHub Actions to authenticate to the platform.
ROGUVIBE_DEPLOY_TOKEN
Platform-owned Cloudflare secrets
Stored only in platform secret manager.
CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_ID
CLOUDFLARE_ZONE_ID
App runtime configuration
Configured through roguvibe.yaml and the platform
secret manager, then injected into Cloudflare Worker
environment bindings.
Non-sensitive values are declared under
env.vars in roguvibe.yaml:
API_BASE_URL
FEATURE_FLAG_EXAMPLE
Sensitive values are declared by name only under
env.secrets in roguvibe.yaml:
BACKEND_API_KEY
DB_USERNAME
DB_PASSWORD
Avoid injecting backend admin/root credentials into generated apps by default. Prefer scoped application credentials per project/environment.
9.2 Recommended flow
User/AI declares non-sensitive env vars in roguvibe.yaml
↓
User/platform registers secret values through platform UI/API/CLI
↓
Platform stores secret values in secret manager
↓
Deployment validates that every env.secret name has a value for the target environment
↓
Cloudflare Deploy Adapter writes vars/secrets to Worker environment bindings
↓
Worker receives env.API_BASE_URL / env.BACKEND_API_KEY / env.DB_PASSWORD
Generated repos should contain secret references, not secret values.
10. AI Agent Skill Model
10.1 Required skills
Create platform skills for AI agents:
/skill:init-project
/skill:change-app
/skill:deploy-development
/skill:promote-production
/skill:rollback
/skill:diagnose-deployment
10.2 Skill contracts
/skill:init-project
Responsibilities:
- Create scaffold.
- Initialize local git.
- Create GitHub repo.
-
Create
developmentandproductionbranches. - Configure workflows.
- Configure GitHub Environments.
- Configure branch protections.
- Register project in platform.
- Trigger first development deployment.
/skill:change-app
Responsibilities:
- Checkout
development. - Pull latest changes.
- Create
ai/<task>branch. - Modify app code.
- Run validation.
- Open PR to
development. - Merge only after checks pass.
/skill:deploy-development
Responsibilities:
-
Ensure current change is merged to
development. - Wait for GitHub Actions deployment.
- Fetch platform deployment status.
- Report development URL.
/skill:promote-production
Responsibilities:
-
Verify latest
developmentdeployment is healthy. -
Open PR from
developmenttoproduction. - Wait for checks.
- Satisfy approval policy.
- Merge PR.
- Wait for production deployment.
- Report production URL.
/skill:rollback
Responsibilities:
- Query previous successful deployments.
- Ask/confirm rollback target when necessary.
- Call platform rollback API.
- Verify production URL.
- Optionally open a revert PR to align Git state.
10.3 Agent safety rules
Agents must follow these rules:
- Never commit directly to
production. - Never add Cloudflare API tokens to the repo.
-
Never add backend admin/root credentials, API keys, passwords,
or token values to generated app code or
roguvibe.yaml. - Never change branch protection unless explicitly instructed.
- Prefer PR-based changes into
development. -
Promote only from
developmenttoproduction. - Treat platform deployment registry as the source of truth for deployment status.
11. Rollback Model
11.1 Runtime rollback
Rollback should not require rebuilding.
Select previous successful deployment
↓
Platform Deploy API calls Cloudflare rollback/version activation
↓
Environment route points to previous Worker version/deployment
↓
Platform records rollback event
11.2 Git alignment after rollback
Runtime rollback can make production runtime differ from the
production branch HEAD.
Recommended policy:
- Perform runtime rollback immediately for incident recovery.
-
AI agent opens a follow-up PR to align
productionbranch with the rollback target if needed.
This balances fast recovery with Git auditability.
12. Observability and Status
12.1 Deployment status
Platform should track:
project id
environment
git repo
git branch
git commit SHA
build run id
Cloudflare Worker name/script id
Cloudflare deployment/version id
hostname
status
created at
created by
12.2 User-facing status
Expose simple statuses:
Building
Deploying
Live
Failed
Rolled back
12.3 Logs
Initial MVP:
- Link to GitHub Actions run logs for build failures.
- Store platform deploy logs.
- Show Cloudflare deployment errors.
Later:
- Cloudflare Workers runtime logs integration.
- Per-request logs.
- Error summaries.
- Deployment health checks.
13. Implementation Phases
MVP Implementation Phases
This MVP is a narrow proof of concept inside the current repository. It should test whether this repo can deploy a simple static HTML site to Cloudflare Workers and expose it at this fixed hostname:
roguvibe-design--p-plan5demo.sirogu.com
The MVP should not build the RoguVibe CLI, control plane, project database, repo initializer, secret manager, deployment registry, rollback UI, or Workers for Platforms adapter. Use Cloudflare's default tooling where possible, especially Wrangler and the official Wrangler GitHub Action.
The MVP site should live under:
mvp/roguvibe-design/
The site should be an HTML version of this PLAN 5 document. The HTML version must preserve the same information as the Markdown plan, but present it as an easy-to-read static site with strong navigation and reading UX. It should also include D1-backed anchored threaded comments so the deployed Worker proves static asset delivery, API routing, and persistence in one flow.
MVP Phase 0 — In-repo MVP workspace and deployment identity
Goal: create the minimum in-repo workspace and fixed deployment identity needed to prove the Worker deployment flow.
Steps:
-
Create the MVP workspace in the current repo:
mvp/roguvibe-design/ -
Use fixed MVP deployment values:
repo-name: roguvibe-design project-id: p-plan5demo hostname: roguvibe-design--p-plan5demo.sirogu.com worker-name: roguvibe-design-p-plan5demo -
Add only the Cloudflare GitHub secrets needed by Wrangler, DNS/route automation, and D1 binding configuration:
CLOUDFLARE_API_TOKENCLOUDFLARE_ACCOUNT_IDCLOUDFLARE_ZONE_ID
-
Scope the Cloudflare token narrowly to the account/zone needed for Worker deploy, DNS/custom-domain registration, D1 database discovery/creation, and D1 migrations.
-
Do not add RoguVibe platform secrets, deploy tokens, project DB credentials, or custom CLI credentials.
Success criteria:
-
The MVP workspace exists under
mvp/roguvibe-design/. -
The hostname is fixed as
roguvibe-design--p-plan5demo.sirogu.com. - No custom RoguVibe CLI or control-plane service exists in this MVP.
MVP Phase 1 — HTML plan site
Goal: create a static HTML version of this plan that is pleasant to read and easy to navigate.
Steps:
-
Convert
plans/PLAN-5--Hosted-Cloudflare-Workers-GitHub-Actions-Platform.mdinto a static HTML site undermvp/roguvibe-design/. Preserve all plan content and code examples.
-
Design the HTML for reading UX:
- sticky/sidebar table of contents on desktop;
- compact top navigation or collapsible contents on mobile;
- readable typography and line height;
- clear heading hierarchy;
- anchor links for every major section;
- styled code blocks;
- visual callouts for goals, non-goals, risks, MVP phases, and final recommendation;
- responsive layout without requiring a heavy frontend framework.
-
Prefer a small Worker + static assets structure:
mvp/roguvibe-design/ ├── public/ │ ├── index.html │ ├── styles.css │ └── feedback.js ├── src/ │ └── worker.ts ├── migrations/ │ ├── 0002_threaded_comments.sql │ └── 0003_commenter_name_required.sql ├── wrangler.template.jsonc └── README.md -
Avoid app frameworks unless the HTML becomes hard to maintain.
-
Keep stable block ids for commentable paragraphs and list items so anchored comments do not drift onto the wrong content when nearby text changes.
Success criteria:
-
Opening
mvp/roguvibe-design/public/index.htmllocally shows the full plan content. - The page is easy to navigate and readable on desktop and mobile.
- The site is static and can be deployed through Workers Static Assets.
- The page structure has stable block ids that can be reused by the anchored comments API.
MVP Phase 2 — Wrangler Worker, static assets, and D1 configuration
Goal: deploy the HTML site through a small Worker using Cloudflare's default Wrangler path, with static assets and D1 configured up front.
Steps:
-
Add a minimal Wrangler configuration template at:
mvp/roguvibe-design/wrangler.template.jsonc -
Configure Workers Static Assets to serve:
mvp/roguvibe-design/public/ -
Add a small Worker entrypoint at:
mvp/roguvibe-design/src/worker.tsThe Worker should serve static assets by default and reserve
/api/*routes for the D1-backed anchored comments feature. -
Configure a D1 binding for anchored comments:
binding: DB database_name: roguvibe-design-p-plan5demo -
Render
wrangler.jsoncin CI with the fixed Worker name, hostname, and D1 database ID. -
Configure the Worker custom domain/route for:
roguvibe-design--p-plan5demo.sirogu.com
Example generated wrangler.jsonc shape:
{
"name": "roguvibe-design-p-plan5demo",
"main": "./src/worker.ts",
"compatibility_date": "2025-06-01",
"assets": {
"directory": "./public",
"binding": "ASSETS"
},
"d1_databases": [
{
"binding": "DB",
"database_name": "roguvibe-design-p-plan5demo",
"database_id": "__D1_DATABASE_ID__"
}
],
"routes": [
{
"pattern": "roguvibe-design--p-plan5demo.sirogu.com",
"custom_domain": true
}
]
}
Success criteria:
-
npx wrangler deploy --config mvp/roguvibe-design/wrangler.jsonccan publish the Worker-backed HTML site. -
Static assets are still served from
mvp/roguvibe-design/public/. -
wrangler.jsoncincludes aDBD1 binding for the MVP database. - No RoguVibe-specific deploy adapter is required for the MVP.
- The Wrangler config remains small and understandable.
MVP Phase 3 — GitHub Actions CI/CD scoped to
mvp/*
Goal: deploy the static HTML site automatically from GitHub Actions only when the MVP workspace changes.
Steps:
- Add a single deploy workflow for this MVP.
-
Trigger it on push to
mainonly when files undermvp/**change. -
Keep
workflow_dispatchfor manual redeploys. - Checkout the repo.
-
Validate
mvp/roguvibe-design/public/index.htmlexists. -
Render
mvp/roguvibe-design/wrangler.jsoncfrom the template, including the D1 database ID. - Apply D1 migrations with Wrangler before deploy.
-
Deploy with
cloudflare/wrangler-action@v3ornpx wrangler deploy. - Ensure DNS/custom-domain registration is handled automatically in CI/CD before or during deploy.
Example workflow shape:
name: Deploy RoguVibe Design MVP
on:
push:
branches:
- main
paths:
- "mvp/**"
workflow_dispatch:
permissions:
contents: read
jobs:
deploy:
runs-on: tke-fe-small-runner
timeout-minutes: 15
env:
MVP_DIR: mvp/roguvibe-design
HOSTNAME: roguvibe-design--p-plan5demo.sirogu.com
WORKER_NAME: roguvibe-design-p-plan5demo
D1_DATABASE_NAME: roguvibe-design-p-plan5demo
steps:
- uses: actions/checkout@v6
- name: Render Wrangler config
shell: bash
run: |
test -f "$MVP_DIR/public/index.html"
sed -e "s#__WORKER_NAME__#$WORKER_NAME#g" -e "s#__HOSTNAME__#$HOSTNAME#g" -e "s#__D1_DATABASE_ID__#$D1_DATABASE_ID#g" "$MVP_DIR/wrangler.template.jsonc" > "$MVP_DIR/wrangler.jsonc"
- name: Apply D1 migrations
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: d1 migrations apply roguvibe-design-p-plan5demo --remote --config mvp/roguvibe-design/wrangler.jsonc
- name: Deploy with Wrangler
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --config mvp/roguvibe-design/wrangler.jsonc
Success criteria:
-
Pushes that do not change
mvp/**do not trigger this MVP deploy workflow. -
Pushes that change
mvp/roguvibe-design/**deploy the HTML plan site. - GitHub Actions logs show the fixed hostname and Worker name.
- The workflow uses Wrangler directly and does not require a custom RoguVibe CLI.
MVP Phase 4 — Automatic DNS/custom-domain registration
Goal: prove the sirogu.com hostname can be
registered automatically from CI/CD.
Steps:
-
Prefer Wrangler custom-domain routing if it fully registers the Worker custom domain and required DNS state for:
roguvibe-design--p-plan5demo.sirogu.com -
If Wrangler does not fully register DNS for the account setup, add a CI step that uses the Cloudflare API to upsert the required proxied DNS record before deploy.
-
Keep DNS automation idempotent so rerunning the workflow is safe.
-
Do not require manual Cloudflare dashboard changes after the initial token/zone setup.
Success criteria:
- DNS/custom-domain registration is automatic from GitHub Actions.
- Rerunning the workflow does not create duplicate DNS records or routes.
-
The final site is reachable at
https://roguvibe-design--p-plan5demo.sirogu.com.
MVP Phase 5 — D1-backed anchored threaded comments
Goal: prove the deployed Worker can use Cloudflare D1 for a small persistence feature without introducing a RoguVibe control plane or external backend.
Feature: add anchored threaded comments to the PLAN 5 HTML site. Readers should be able to select text within a paragraph or list item, create a comment thread tied to that block, and reply to that thread without adding a large widget after every section.
Select text in a paragraph or list item
↓
[Comment on selection]
↓
Open comment drawer
↓
Write root comment with commenter name
↓
Other readers add named replies to the same thread
Steps:
-
Create the D1 database for the MVP:
roguvibe-design-p-plan5demo -
Add a D1 migration at:
mvp/roguvibe-design/migrations/0002_threaded_comments.sql mvp/roguvibe-design/migrations/0003_commenter_name_required.sql -
Use a minimal schema:
CREATE TABLE comment_threads ( id TEXT PRIMARY KEY, block_id TEXT NOT NULL, selected_text TEXT, selection_start INTEGER, selection_end INTEGER, created_at TEXT NOT NULL ); CREATE TABLE comments ( id TEXT PRIMARY KEY, thread_id TEXT NOT NULL, parent_comment_id TEXT, commenter_name TEXT NOT NULL, body TEXT NOT NULL, created_at TEXT NOT NULL ); -
Add Worker API routes:
POST /api/comments/summary GET /api/comments?block=<block-id> POST /api/comments POST /api/comments/:threadId/replies -
Keep comment bodies short and public. Reject invalid block ids, malformed selection ranges, empty names, empty replies, and overlong comment text.
-
Add lightweight client-side JavaScript under
mvp/roguvibe-design/public/feedback.jsto attach stable block ids, capture selection within a single block, open a comment drawer, submit root comments with commenter names, and submit named replies. -
Do not add authentication, moderation queues, email notifications, analytics tools, or an admin UI in this MVP.
-
Keep the feature resilient: if the feedback API fails, the plan content must still render and remain readable.
Success criteria:
- The deployed Worker has a
DBD1 binding. - D1 migrations can be applied by the GitHub Actions workflow or by a documented Wrangler command.
- A reader can create an anchored comment thread from the deployed hostname.
- Every root comment and reply requires a commenter name and comment body.
- Refreshing the page can show stored threads and replies read back from D1.
- Comments are keyed by stable block ids derived from the rendered plan content.
- The feature validates D1 writes, D1 reads, Worker API routing, and Workers Static Assets in the same MVP deployment.
- The HTML plan remains usable if the feedback API is unavailable.
MVP Phase 6 — Domain and UX verification
Goal: prove the hostname, static HTML UX, and D1-backed anchored comments feature work end to end.
Steps:
-
Open the fixed hostname in a browser:
https://roguvibe-design--p-plan5demo.sirogu.com Verify the HTML plan site loads.
Verify deep links to sections work.
-
Verify the page is readable on mobile and desktop.
-
Select text and create at least one anchored comment thread with a commenter name.
-
Add at least one named reply to an existing thread.
-
Refresh the page and verify anchored threads and replies are read back from D1.
-
Run simple HTTP checks:
curl -I "https://roguvibe-design--p-plan5demo.sirogu.com" curl -X POST "https://roguvibe-design--p-plan5demo.sirogu.com/api/comments/summary" \ -H "content-type: application/json" \ -d '{"blocks":["<stable-block-id-from-dom>"]}'
Success criteria:
-
The site is reachable at
roguvibe-design--p-plan5demo.sirogu.com. - The deployed content matches the HTML version of PLAN 5.
- The deployment is repeatable from GitHub Actions.
- The HTML site is easy to consume as a design/reference document.
- Anchored comment threads and replies can be submitted and read back through D1 on the deployed hostname.
MVP Phase 7 — Record lessons for the real platform
Goal: convert the proof-of-concept results into implementation input for the full RoguVibe platform.
Steps:
- Record the exact Cloudflare permissions required by Wrangler, DNS/custom-domain automation, and D1 migrations.
- Record whether custom domain/route setup can be fully automated from CI.
- Record any friction with Workers Static Assets.
- Record any friction with D1 database creation, binding configuration, migrations, local development, deployed reads/writes, and anchor drift.
- Record which parts should later move behind the RoguVibe CLI/control plane.
- Record whether a control-plane-generated project ID is required immediately or whether fixed/manual project IDs are acceptable for early pilots.
Success criteria:
-
The MVP produces a short findings document under
mvp/roguvibe-design/orartifacts/. - The full platform phases below can be updated with real Cloudflare and GitHub Actions constraints.
- No unnecessary custom tooling was built before the basic deployment path was proven.
Phase 0 — Hosted Workers spike
Estimated duration: 1 week.
Steps:
- Create a minimal generated TypeScript Worker app.
- Deploy manually to Cloudflare hosted Workers.
- Test Workers Static Assets.
- Test automatic custom domain/route automation using repo name + platform project ID.
- Test Worker environment variables and secrets for generic backend configuration such as API URL/IP, API key, username, and password.
- Test rollback/version behavior.
- Document required Cloudflare account permissions and limits.
Success criteria:
- TypeScript app deploys to Cloudflare Workers.
- Static assets work.
-
Worker runtime can connect to the configured backend using
env.vars/env.secretsand scoped credentials. - Custom development and production hostnames work.
- Rollback path is confirmed.
Phase 1 — Repo scaffold and branch model
Estimated duration: 1–2 weeks.
Steps:
- Define template repo structure.
- Define
roguvibe.yamlv1. - Add
AGENTS.mdtemplate. - Add
.roguvibe/project.jsontemplate. - Implement local scaffold generation.
-
Implement
developmentandproductionbranch initialization. - Add validation and deploy workflows.
- Document AI skill rules.
Success criteria:
- New local repo can be generated.
- Branches are initialized deterministically.
- Workflows exist and validate.
- AI instructions are present and machine-readable metadata is present.
Phase 2 — GitHub repo automation
Estimated duration: 1–2 weeks.
Steps:
- Implement GitHub repo creation with shared machine user/PAT.
- Push initialized branches.
- Set default branch to
development. - Create GitHub Environments.
- Set repo variables and environment secrets.
- Apply branch protection.
- Create initial PR/promotion flow test.
Success criteria:
- Platform can create a ready-to-use GitHub repo.
-
developmentandproductionbranches exist. - Branch protections are active.
- GitHub Actions runs on PR and push.
Phase 3 — Platform deploy API and CLI
Estimated duration: 2–3 weeks.
Steps:
- Implement
roguvibe validate. - Implement
roguvibe deploy. - Implement deploy-token authentication.
- Implement platform deployment registry.
- Implement environment mapping.
- Store deployment status and GitHub run metadata.
- Return deployment URL and status to GitHub Actions.
Success criteria:
-
GitHub Actions can deploy through
roguvibe deploy. - Platform registry records deployment metadata.
- Failed deployments show actionable errors.
- Generated repos do not need Cloudflare credentials.
Phase 4 — Cloudflare MVP adapter
Estimated duration: 2–4 weeks.
Steps:
- Implement per-project/per-environment Worker naming.
- Upload Worker module and static assets.
- Configure Worker environment variables and secrets.
- Configure custom domains/routes.
- Implement automatic development and production hostname generation from repo name + project ID.
- Implement rollback to previous successful deployment/version.
Success criteria:
-
Push to
developmentdeploys development Worker. -
Merge to
productiondeploys production Worker. - Automatically assigned development and production hostnames work.
- Rollback works without rebuild.
Phase 5 — AI skills and promotion workflow
Estimated duration: 1–2 weeks.
Steps:
- Implement
/skill:change-appworkflow. -
Implement
/skill:deploy-developmentworkflow. -
Implement
/skill:promote-productionworkflow. - Implement
/skill:rollbackworkflow. - Add status polling for GitHub Actions and platform deployment status.
- Add safe failure recovery docs.
Success criteria:
-
AI agent can make a change safely through
ai/<task>. - AI agent can deploy development.
- AI agent can promote development to production.
- AI agent can roll back production.
Phase 6 — Workers for Platforms evaluation/migration
Estimated duration: 2–4 weeks after MVP usage data.
Steps:
- Validate Workers for Platforms account/product availability.
- Build proof of concept dispatcher Worker.
- Upload user Workers to dispatch namespace.
- Map hostnames to dispatched Worker scripts.
- Compare limits, cost, operational complexity, and rollback model.
- Implement Cloudflare Deploy Adapter v2 behind existing platform API.
- Migrate one pilot project without repo workflow changes.
Success criteria:
- Existing generated repo workflow remains unchanged.
- Platform can deploy through dispatch namespace.
- Dispatcher resolves hostnames to correct project/environment.
- Rollback and logs remain supported.
14. Risks and Mitigations
14.2 Cloudflare credential leakage
Risk:
- Cloudflare tokens in generated repos would compromise runtime infrastructure.
Mitigation:
-
Generated repos receive only
ROGUVIBE_DEPLOY_TOKEN. - Platform owns Cloudflare credentials.
- Use scoped Cloudflare API token.
- Audit deploy adapter calls.
14.3 Branch confusion
Risk:
- Users or agents merge wrong branches.
Mitigation:
-
Use environment-named branches:
development,production. - Set
developmentas default. - Protect
production. -
Include
AGENTS.mdand.roguvibe/project.json. - Encode branch rules in skills.
14.4 Git/runtime drift after rollback
Risk:
-
Runtime rollback may not match
productionbranch HEAD.
Mitigation:
- Record rollback events.
- Show active deployment SHA.
- AI opens follow-up revert/alignment PR.
14.5 Cloudflare limits and product fit
Risk:
- Per-project Worker model may hit account limits or become operationally noisy.
Mitigation:
- Keep Cloudflare Deploy Adapter boundary.
- Track Worker counts and route counts.
- Evaluate Workers for Platforms before scaling broadly.
14.6 Non-Worker-compatible generated code
Risk:
- Generated TypeScript app may use unsupported Node APIs.
Mitigation:
- Provide templates.
- Run compatibility validation in CI.
- Prefer Web APIs.
- Keep framework adapter constraints explicit.
15. Recommended MVP Scope
MVP should include:
roguvibe project initscaffold.- GitHub repo creation with shared machine user/PAT.
-
developmentandproductionenvironment branches. - GitHub Actions validation and deploy workflows.
roguvibe.yamlv1 with no hostname config.-
roguvibe validateandroguvibe deploy. - Platform Deploy API.
- Cloudflare per-project/per-environment Worker adapter.
- Automatic development and production hostnames from repo name + platform project ID.
- Deployment registry.
- Basic rollback.
- AI skill contracts for change, deploy-development, promote-production, rollback.
Defer:
- Workers for Platforms migration.
- Advanced preview environments per PR.
- Advanced traffic splitting/canary deploys.
- Multi-region/custom placement controls.
- User-configurable resource knobs.
- GitHub App migration, unless PAT risk blocks launch.
16. Final Recommendation
Use Cloudflare hosted Workers as the runtime and GitHub Actions as the CI/CD runner, but keep both hidden behind a platform abstraction.
The most important product decision is the branch model:
development branch → development deployment
production branch → production deployment
ai/<task> branch → AI workspace only
This maps directly to how non-engineering users think, and it gives AI agents deterministic rules for safe changes and production promotion.
Build the MVP with one Worker per project environment because it
is simpler and faster. Put all Cloudflare-specific logic behind a
Cloudflare Deploy Adapter so the platform can later
move to Workers for Platforms dispatch namespaces without changing
generated repos or AI skills.
The generated repo should be fully ready after initialization:
branches, workflows, roguvibe.yaml,
AGENTS.md, repo variables/secrets, GitHub
Environments, and branch protection. From that point, the user can
ask an AI agent to change the app, test it in development, publish
it to production, or roll back without manually operating GitHub
or Cloudflare.
17. Primary references
- Cloudflare Workers GitHub Actions CI/CD: https://developers.cloudflare.com/workers/ci-cd/external-cicd/github-actions/
- Cloudflare Workers Wrangler configuration: https://developers.cloudflare.com/workers/wrangler/configuration/
- Cloudflare Workers Static Assets: https://developers.cloudflare.com/workers/static-assets/
- Cloudflare Workers custom domains/routes: https://developers.cloudflare.com/workers/configuration/routing/
- Cloudflare Workers versions/deployments/rollback: https://developers.cloudflare.com/workers/configuration/versions-and-deployments/
- Cloudflare Workers for Platforms: https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/
- GitHub Actions deployment environments: https://docs.github.com/en/actions/concepts/workflows-and-actions/deployment-environments
- GitHub Actions deploying with GitHub Actions: https://docs.github.com/en/actions/deployment/about-deployments/deploying-with-github-actions
- Cloudflare Workers environment variables: https://developers.cloudflare.com/workers/configuration/environment-variables/
- GitHub Actions secrets: https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions