Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions docs/cli/mint.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,9 @@ Pass `--keep-pem` to preserve the PEM secret in Secret Manager.

## `mint enroll`

Registers a GitHub organization or repository in the mint's allowed list, enabling it to request tokens.
Registers a GitHub organization or repository in the mint's allowed list, enabling it to request tokens. Use `--platform` to select the target (default: `gcp`).

### GCP mode

```bash
fullsend mint enroll <org> \
Expand All @@ -244,16 +246,75 @@ fullsend mint enroll <owner/repo> \

Enrollment creates the WIF provider needed for OIDC verification only — it does not grant any IAM roles. Vertex AI access is provisioned separately via `fullsend inference provision`.

### Cloudflare mode

```bash
fullsend mint enroll <org> \
--platform cloudflare \
--worker-name "fullsend-mint"
```

Per-repo mode:

```bash
fullsend mint enroll <owner/repo> \
--platform cloudflare
```

Updates the durable Worker's `ALLOWED_ORGS` (org mode) or `PER_REPO_WIF_REPOS` (per-repo mode) via the Cloudflare Versions API — no local Worker sources or WASM build artifacts required. Per-repo enrollment does not modify `ALLOWED_ORGS`. Requires `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` (or a Wrangler OAuth session via `wrangler login`).

`--preview` is rejected — preview Workers are configured exclusively via `mint deploy`.

> **Enroll serially.** Concurrent enroll or unenroll commands against the same Worker can race — the CLI uses a read-modify-write cycle without concurrency control. Run them one at a time. See [Enrollment ordering](../guides/infrastructure/mint-administration.md#enrollment-ordering).

### Flags

| Flag | Default | Description |
|------|---------|-------------|
| `--platform` | `gcp` | Target platform: `gcp` or `cloudflare` |
| `--project` | | GCP project ID (required for `--platform=gcp`) |
| `--region` | `us-central1` | GCP region |
| `--worker-name` | `fullsend-mint` | Cloudflare Worker script name |
| `--preview` | | Rejected for enroll — use `mint deploy` for preview Workers |
| `--dry-run` | `false` | Preview changes without making them |

## `mint unenroll`

Removes an organization or repository from the mint's allowed list.
Removes an organization or repository from the mint's allowed list. Use `--platform` to select the target (default: `gcp`).

### GCP mode

```bash
fullsend mint unenroll <org|owner/repo> \
--project "<GCP_PROJECT>" \
--region "us-central1"
```

### Cloudflare mode

```bash
fullsend mint unenroll <org|owner/repo> \
--platform cloudflare \
--worker-name "fullsend-mint"
```

Removes the org/repo from the durable Worker's env vars via the Cloudflare Versions API — no local Worker sources or WASM build artifacts required.

> **Unenroll serially.** Like enroll, the Cloudflare unenroll path uses a read-modify-write cycle. Do not run concurrent unenroll commands against the same Worker — see [Enrollment ordering](../guides/infrastructure/mint-administration.md#enrollment-ordering).

### Flags

| Flag | Default | Description |
|------|---------|-------------|
| `--platform` | `gcp` | Target platform: `gcp` or `cloudflare` |
| `--project` | | GCP project ID (required for `--platform=gcp`) |
| `--region` | `us-central1` | GCP region |
| `--delete-provider` | `false` | Permanently delete WIF provider (GCP repo unenroll only) |
| `--worker-name` | `fullsend-mint` | Cloudflare Worker script name |
| `--preview` | | Rejected for unenroll — use `mint deploy` for preview Workers |
| `--dry-run` | `false` | Preview changes without making them |
| `--yolo` | `false` | Skip interactive confirmation |

## `mint workflow-host`

Manages the `WORKFLOW_HOST_REPOS` allow-list that controls which repositories may host workflows calling the mint for per-repo callers. Per-org callers are not affected.
Expand Down
4 changes: 3 additions & 1 deletion docs/guides/dev/cli-internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ The `mint`, `inference`, and `github` subcommands decompose setup into role-spec
| Install Phase | Standalone Command | Required Access |
|---------------|--------------------|-----------------|
| Phases 1-3: Mint deployment | `fullsend mint deploy` | GCP project (mint): `roles/iam.serviceAccountAdmin`, `roles/iam.workloadIdentityPoolAdmin`, `roles/cloudfunctions.developer`, `roles/run.admin`; with `--pem-dir` also `roles/secretmanager.admin`, `roles/resourcemanager.projectIamAdmin` |
| Phases 1-3: Mint enrollment | `fullsend mint enroll` | GCP project (mint): `roles/cloudfunctions.viewer`, `roles/run.admin`, `roles/iam.workloadIdentityPoolAdmin` |
| Phases 1-3: Mint enrollment | `fullsend mint enroll` | GCP project (mint): `roles/cloudfunctions.viewer`, `roles/run.admin`, `roles/iam.workloadIdentityPoolAdmin` ¹ |
| Phase 4: WIF provisioning | `fullsend inference provision` | GCP project (inference): `roles/iam.workloadIdentityPoolAdmin`, `roles/resourcemanager.projectIamAdmin` |
| Phases 5-7: GitHub setup + enrollment | `fullsend github setup` | GitHub only |

¹ GCP IAM roles apply to `--platform=gcp` (the default). Cloudflare enrollment (`--platform=cloudflare`) requires `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` (or an active `wrangler login` session via `wrangler auth token`). See [`docs/cli/mint.md`](../../cli/mint.md) and [`mint-administration.md`](../infrastructure/mint-administration.md).

The typical handoff: a GCP admin runs `mint deploy`, `mint enroll`, and `inference provision`, then passes the mint URL and WIF provider resource name to a GitHub maintainer who runs `github setup --mint-url=... --inference-wif-provider=...`. See [Advanced setup](../infrastructure/advanced-setup.md).

> **Deprecated:** The `admin install` command is deprecated. Use the
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/getting-started/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ For organizations that separate GCP and GitHub responsibilities across teams, fu
| GCP Admin (Mint) | `fullsend mint delete` | Tear down mint infrastructure (inverse of deploy) |
| GCP Admin (Mint) | `fullsend mint add-role <role>` | Register a role PEM and app ID on the mint |
| GCP Admin (Mint) | `fullsend mint remove-role <role>` | Remove a role from the mint (deletes PEM secret by default) |
| GCP Admin (Mint) | `fullsend mint enroll <org\|owner/repo>` | Register an org or repo in the mint (does not grant Agent Platform access — use `inference provision`) |
| GCP Admin (Mint) | `fullsend mint unenroll <org\|owner/repo>` | Remove an org or repo from the mint |
| Mint Admin | `fullsend mint enroll <org\|owner/repo>` | Register an org or repo in the mint — supports `--platform=gcp` (default) and `--platform=cloudflare` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] scope-creep

The PR renames the persona for mint enroll/unenroll from 'GCP Admin (Mint)' to 'Mint Admin' while adjacent rows (deploy, delete, add-role, remove-role, status) still use 'GCP Admin (Mint)', creating a visual inconsistency within the same table.

Suggested fix: Either rename all multi-platform mint commands to 'Mint Admin' for consistency, or keep the original label.

| Mint Admin | `fullsend mint unenroll <org\|owner/repo>` | Remove an org or repo from the mint — supports `--platform=gcp` (default) and `--platform=cloudflare` |
| GCP Admin (Mint) | `fullsend mint status` | Inspect mint state and PEM health |

| Fleet Admin | `fullsend repos migrate <org> --project <gcp-project>` | Migrate an org from per-org to per-repo install, generating a `repos.yaml` manifest |
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/getting-started/org-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ To tear down the entire fullsend installation (GitHub + GCP), coordinate between
|------|------|---------|
| 1 | GitHub Maintainer | `fullsend github uninstall "$ORG_NAME"` |
| 2 | GCP Admin (Inference) | `fullsend inference deprovision "$ORG_NAME"` |
| 3 | GCP Admin (Mint) | `fullsend mint unenroll "$ORG_NAME"` |
| 3 | Mint Admin | `fullsend mint unenroll "$ORG_NAME"` |

Each command prompts for confirmation. Add `--yolo` to skip prompts. See the [standalone commands](operations.md#standalone-commands) table for details on each command.

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/getting-started/repo-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ infrastructure, coordinate between roles:
|------|------|---------|
| 1 | Platform Admin | `fullsend repos uninstall "org/*" --yes` (forge-side cleanup + manifest removal) |
| 2 | GCP Admin (Inference) | `fullsend inference deprovision <org>` (WIF cleanup) |
| 3 | GCP Admin (Mint) | `fullsend mint unenroll <org>` |
| 3 | Mint Admin | `fullsend mint unenroll <org>` |

Each `fullsend` command that prompts for confirmation accepts a skip
flag: `--yes` for `repos` commands, `--yolo` for `github` and `mint`
Expand Down
58 changes: 51 additions & 7 deletions docs/guides/infrastructure/mint-administration.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,9 @@ This command does not uninstall GitHub Apps from organizations or update org `.f

## Enrolling organizations and repositories

`fullsend mint enroll` registers an organization or repository in the mint and configures WIF to accept OIDC tokens from the target.
`fullsend mint enroll` registers an organization or repository in the mint. Use `--platform` to select the target (default: `gcp`).

### GCP enrollment

```bash
# Enroll an organization
Expand All @@ -268,14 +270,35 @@ fullsend mint enroll acme-corp --project="$GCP_PROJECT"
fullsend mint enroll acme-corp/my-repo --project="$GCP_PROJECT"
```

Enrollment does **not** grant Agent Platform (inference) access — use `fullsend inference provision` separately after enrollment. See [Getting Started](../getting-started/) for the end-user inference setup path.
GCP enrollment configures WIF to accept OIDC tokens from the target. Enrollment does **not** grant Agent Platform (inference) access — use `fullsend inference provision` separately after enrollment. See [Getting Started](../getting-started/) for the end-user inference setup path.

### Cloudflare enrollment

```bash
# Enroll an organization
fullsend mint enroll acme-corp --platform=cloudflare

# Enroll a specific repository
fullsend mint enroll acme-corp/my-repo --platform=cloudflare --worker-name="my-mint"
```

Cloudflare enrollment updates the durable Worker's env vars via the Cloudflare Versions API — no local Worker sources or WASM build artifacts required. The command clones the currently deployed version's modules, updates the target plain-text bindings, and deploys the new version to 100% traffic. Org enrollment updates `ALLOWED_ORGS`; per-repo enrollment updates `PER_REPO_WIF_REPOS` only (it does not modify `ALLOWED_ORGS`). There is no WIF step — the CF mint handler authorizes callers directly via env var lists.

Required credentials: `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID`, or a Wrangler OAuth session (`wrangler login`).

`--preview` is rejected for enroll — preview Workers are configured exclusively via `mint deploy` with the full desired config.

> **Enroll serially.** The Cloudflare enroll/unenroll path uses a read-modify-write cycle against the Versions API — the CLI reads the current env vars, merges the change, and deploys a new version. Concurrent enroll or unenroll commands against the same Worker will race, and one change may be lost. Run enrollment and unenrollment commands one at a time, just like GCP enrollment (see [Enrollment ordering](#enrollment-ordering)).

### Flags

| Flag | Default | Description |
|------|---------|-------------|
| `--project` | | GCP project ID (required) |
| `--platform` | `gcp` | Target platform: `gcp` or `cloudflare` |
| `--project` | | GCP project ID (required for `--platform=gcp`) |
| `--region` | `us-central1` | Cloud region for the mint service |
| `--worker-name` | `fullsend-mint` | Cloudflare Worker script name |
| `--preview` | | Rejected for enroll — use `mint deploy` for preview Workers |
| `--dry-run` | `false` | Preview changes without making them |

### Migration from per-org app ID flags
Expand Down Expand Up @@ -315,11 +338,13 @@ This prevents a class of bugs where the service template is updated but traffic

### Enrollment ordering

Enroll organizations serially — do not run concurrent enrollment commands against the same mint. The CLI reads the current env vars, merges the new org's entries, and writes the result back. Two concurrent enrollments will race, and one org's entries may be lost.
Enroll organizations serially — do not run concurrent enrollment or unenrollment commands against the same mint. On both GCP and Cloudflare, the CLI reads the current env vars, merges the new org's entries, and writes the result back. Two concurrent commands will race, and one change may be lost. This is an accepted CLI limitation (no ETag-based concurrency control); always run enroll and unenroll commands one at a time.

## Unenrolling organizations and repositories

`fullsend mint unenroll` removes an organization or repository from the mint.
`fullsend mint unenroll` removes an organization or repository from the mint. Use `--platform` to select the target (default: `gcp`).

### GCP unenrollment

```bash
# Unenroll an organization
Expand All @@ -331,13 +356,32 @@ fullsend mint unenroll acme-corp/my-repo --project="$GCP_PROJECT"

Org-scoped unenroll removes the org from mint env vars and the shared WIF provider's attribute condition. Role PEM secrets are shared across orgs and are not modified. Repo-scoped unenroll only disables the repo-specific WIF provider (or permanently deletes it with `--delete-provider`) — it does not touch PEM secrets.

### Cloudflare unenrollment

```bash
# Unenroll an organization
fullsend mint unenroll acme-corp --platform=cloudflare

# Unenroll a specific repository
fullsend mint unenroll acme-corp/my-repo --platform=cloudflare --worker-name="my-mint"
```

Removes the org/repo from the durable Worker's env vars (`ALLOWED_ORGS` or `PER_REPO_WIF_REPOS`) via the Cloudflare Versions API — no local Worker sources or WASM build artifacts required. If the entity is not currently enrolled, the command succeeds without creating a new version.

`--preview` is rejected — preview Workers are configured exclusively via `mint deploy`.

> **Unenroll serially.** Like enroll, the Cloudflare unenroll path uses a read-modify-write cycle. Do not run concurrent unenroll commands against the same Worker — see [Enrollment ordering](#enrollment-ordering).

### Flags

| Flag | Default | Description |
|------|---------|-------------|
| `--project` | | GCP project ID (required) |
| `--platform` | `gcp` | Target platform: `gcp` or `cloudflare` |
| `--project` | | GCP project ID (required for `--platform=gcp`) |
| `--region` | `us-central1` | Cloud region for the mint service |
| `--delete-provider` | `false` | Permanently delete WIF provider (repo-scoped only) |
| `--delete-provider` | `false` | Permanently delete WIF provider (GCP repo-scoped only) |
| `--worker-name` | `fullsend-mint` | Cloudflare Worker script name |
| `--preview` | | Rejected for unenroll — use `mint deploy` for preview Workers |
| `--dry-run` | `false` | Preview changes without making them |
| `--yolo` | `false` | Skip interactive confirmation (for automation) |

Expand Down
Loading
Loading